Refinement of the Scalarization Process for Value Objects during Parsing and PEA#3
Refinement of the Scalarization Process for Value Objects during Parsing and PEA#3MichaelHaas99 wants to merge 59 commits into
Conversation
| obj = closure.getObjectState(this, cacheValue); | ||
| if (obj != null) { | ||
| assert !obj.isVirtual(); | ||
| assert obj.isMaterialized(); |
There was a problem hiding this comment.
only necessary due to a bug?
| tool.createVirtualObject(virtualObject, state, Collections.emptyList(), getNodeSourcePosition(), false, this.oop, this.nonNull, isAllocatedOrNull); | ||
| for (int i = 0; i < state.length; i++) { | ||
| ValueNode entry = tool.getEntry(virtualObject, i); | ||
| ValueNode newEntry = tool.scalarize(entry); |
There was a problem hiding this comment.
pass in the type of the value object to the scalarize method as well
| * non-larval. | ||
| */ | ||
| if (!StampTool.isNullableInlineType(materialized, null) || isLarval()) { | ||
| entries = null; |
There was a problem hiding this comment.
don't delete entries for value object, as they are strict and final
| protected void scalarize(ValueNode node, PartialEscapeBlockState state, GraphEffectList effects, FixedNode position, GuardingNode guard){ | ||
| tool.reset(state, node, position, effects); | ||
| VirtualInstanceNode newNode = scalarizeValueObject(node, state, true, guard); | ||
| this.addVirtualAlias(newNode, node); |
There was a problem hiding this comment.
do a sanity check here, for some calls an alias should already exist
There was a problem hiding this comment.
Put the scalarized field values into all states where this virtual object is also present, and also into the merge state if it is present.
| ValueNode entry = entryState[i]; | ||
| if (StampTool.isNullableInlineType(entry, tool.getValhallaOptionsProvider())) { | ||
| VirtualInstanceNode newNode = scalarizeValueObject(entry, state, true, visited, guard, stopAtVirtual); | ||
| if(newNode != null) { |
There was a problem hiding this comment.
create an alias for materialized objects, such that we can scalarize them at any time.
|
As we scalarize a value object as early as possible, if we land in a circle where we can't scalarize any further, we should create an alias for the remaining value object. So a virtual object pointing to a materialized object state. This allows us to scalarize the value object at the next possibility, we will only need to fill in the object state with the field values. The point for doing this, is to have an alias available. We should only do this for nodes that are ReadMultiValue nodes as the result from the current scalarization. |
There was a problem hiding this comment.
A value object without an alias shouldn't be possible anymore. Throw an exception in this case as sanity check.
|
Can we maybe make the scalarization procedure in PEReadEliminationClosure more generic, e.g. we already generalize the behaviour for MultiValue nodes. |
| associateAlias(piNode, state, effects, lastFixedNode.next()); | ||
| } | ||
| } else if (node instanceof ParameterNode param) { | ||
| if (StampTool.isNullableInlineType(param, tool.getValhallaOptionsProvider())) { |
There was a problem hiding this comment.
TODO: we are not allowed to scalarize here if we compile a constructor method
589e0e3 to
138b932
Compare
138b932 to
ce65670
Compare
e1fc4aa to
ee26717
Compare
db1e5bb to
2417f9c
Compare
…ems if the value is part of a mapping before.
Alias new allocated objects. Fix error with effects, don't use the index directly but the predecessor function. Don't scalarize ReadMultiValue nodes as they can be scheduled above an invoke and cause a missing object state in the virtual mapping. Add sanity checks to check if an alias is associated to a value object.
Only insert new nodes into scalarizationAliases map. Update isLarval for Pi nodes. Ask for alias on LoadField object.
b3ff2c0 to
2ea3d2c
Compare
Remove PEA in entry point. Associate alias to loop phis before first processing.
In case a NewInstance node was not virtualized, make the object state larval.
4e454d9 to
fc80a48
Compare
…irtualize will always be called. Move scalarization into virtualize method.
…ation will handle them then. getAliasAndResolve should return the materialized value for non-value objects.
…ation will handle them then. getAliasAndResolve should return the materialized value for non-value objects. Add a verification after PEA that checks that LoadField node are removed and Scalarization nodes have no guard. Make Invoke, FinalFieldBarrier and Membar node Guarding nodes.
The main bullet points of this PR are:
We need a way to propagate the Scalarization nodes for method arguments during inlining or inserted during merge processing in PEA through the graph. If that is not easily possible, I think we should move to the implementation of C2 and remove all changes from PEA. My solution would be:
Value objects from outside a compilation unit can be encountered with the following nodes with stamp value object:
Parameter (non OSR) nodes
LoadStatic node
LoadField node
Invoke node
They are non-larval and can be scalarized. Value objects within a compilation unit are normally virtual during PEA but will be materialized in case the constructor is not inlined. So value objects can also be scalarized if they are receiver of an Invoke node with a constructor call. If all constructors are inlined, it is virtual anyway during PEA.
What I mean with scalarization during PEA is that we alias the corresponding node with a virtual alias. The field values are directly loaded below the definition of the node.
A special case are OSR arguments as they may still be larval.
In Graal they are marked with the EntryProxy node and replace by an OSRLocal node after parsing. So how can we scalarize, or in other words know that they are non-larval?
We associate an alias to the Pi node having the OSRLocal node as its input with an object state being materialized and tracking the larval state. Whenever we encounter a node that requires the node to be non-larval and we have not encountered a constructor call or StoreField node in between, so the object state indicates larval, we know that the OSR node must have been non-larval from the beginning onwoards. As the Scalarization node is floating we can set the scalarized values in all object states, as we scalarize directly at the beginning.
When we reach a StoreField node we set the field to initialized in the object state.
Scalarizarion nodes should be made floating and anchored at the earliest possible position. We should rely on location identities as this is not necessary and allows GVN. Value objects are immutable, so it does not make any difference when a field is read, as long as it is non-larval.
As a consequence the input to a Scalarization node inserted during parsing should always be virtual.