# HG changeset patch # User Thomas Wuerthinger # Date 1422370908 -3600 # Node ID e349dfa54db151b85272ce5a8d1e2b401c4a0d6c # Parent edf3a7fdd0670c8c7d64cfe4601cf731ce398f0c Simplifications in PEA. diff -r edf3a7fdd067 -r e349dfa54db1 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FrameState.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FrameState.java Tue Jan 27 14:54:55 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FrameState.java Tue Jan 27 16:01:48 2015 +0100 @@ -458,8 +458,10 @@ @Override public void applyToNonVirtual(NodeClosure closure) { - for (ValueNode value : values.nonNull()) { - closure.apply(this, value); + for (ValueNode value : values) { + if (value != null) { + closure.apply(this, value); + } } if (monitorIds != null) { diff -r edf3a7fdd067 -r e349dfa54db1 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/VirtualState.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/VirtualState.java Tue Jan 27 14:54:55 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/VirtualState.java Tue Jan 27 16:01:48 2015 +0100 @@ -32,9 +32,9 @@ @NodeInfo(allowedUsageTypes = {InputType.State}) public abstract class VirtualState extends Node { - public interface NodeClosure { + public abstract static class NodeClosure { - void apply(Node usage, T node); + public abstract void apply(Node usage, T node); } public interface VirtualClosure { diff -r edf3a7fdd067 -r e349dfa54db1 graal/com.oracle.graal.phases/src/com/oracle/graal/phases/util/GraphOrder.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/util/GraphOrder.java Tue Jan 27 14:54:55 2015 +0100 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/util/GraphOrder.java Tue Jan 27 16:01:48 2015 +0100 @@ -163,6 +163,7 @@ if (pendingStateAfter != null && node instanceof FixedNode) { pendingStateAfter.applyToNonVirtual(new NodeClosure() { + @Override public void apply(Node usage, Node nonVirtualNode) { assert currentState.isMarked(nonVirtualNode) || nonVirtualNode instanceof VirtualObjectNode : nonVirtualNode + " not available at virtualstate " + usage + " before " + node + " in block " + block + " \n" + list; @@ -196,8 +197,11 @@ for (Node input : node.inputs()) { if (input != stateAfter) { if (input instanceof FrameState) { - ((FrameState) input).applyToNonVirtual((usage, nonVirtual) -> { - assert currentState.isMarked(nonVirtual) : nonVirtual + " not available at " + node + " in block " + block + "\n" + list; + ((FrameState) input).applyToNonVirtual(new VirtualState.NodeClosure() { + @Override + public void apply(Node usage, Node nonVirtual) { + assert currentState.isMarked(nonVirtual) : nonVirtual + " not available at " + node + " in block " + block + "\n" + list; + } }); } else { assert currentState.isMarked(input) || input instanceof VirtualObjectNode : input + " not available at " + node + " in block " + block + "\n" + list; @@ -220,6 +224,7 @@ } if (pendingStateAfter != null) { pendingStateAfter.applyToNonVirtual(new NodeClosure() { + @Override public void apply(Node usage, Node nonVirtualNode) { assert currentState.isMarked(nonVirtualNode) || nonVirtualNode instanceof VirtualObjectNode : nonVirtualNode + " not available at virtualstate " + usage + " at end of block " + block + " \n" + list; diff -r edf3a7fdd067 -r e349dfa54db1 graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java Tue Jan 27 14:54:55 2015 +0100 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java Tue Jan 27 16:01:48 2015 +0100 @@ -56,6 +56,38 @@ private final NodeBitMap usages; private final VirtualizerToolImpl tool; + private final class CollectVirtualObjectsClosure extends NodeClosure { + private final Set virtual; + private final GraphEffectList effects; + private final BlockT state; + + private CollectVirtualObjectsClosure(Set virtual, GraphEffectList effects, BlockT state) { + this.virtual = virtual; + this.effects = effects; + this.state = state; + } + + @Override + public void apply(Node usage, ValueNode value) { + ObjectState valueObj = getObjectState(state, value); + if (valueObj != null) { + virtual.add(valueObj); + effects.replaceFirstInput(usage, value, valueObj.virtual); + } else if (value instanceof VirtualObjectNode) { + ObjectState virtualObj = null; + for (ObjectState obj : state.getStates()) { + if (value == obj.virtual) { + virtualObj = obj; + break; + } + } + if (virtualObj != null) { + virtual.add(virtualObj); + } + } + } + } + /** * Final subclass of PartialEscapeClosure, for performance and to make everything behave nicely * with generics. @@ -109,10 +141,12 @@ } if (isMarked) { for (Node input : node.inputs()) { - ObjectState obj = getObjectState(state, input); - if (obj != null) { - VirtualUtil.trace("replacing input %s at %s: %s", input, node, obj); - replaceWithMaterialized(input, node, insertBefore, state, obj, effects, METRIC_MATERIALIZATIONS_UNHANDLED); + if (input instanceof ValueNode) { + ObjectState obj = getObjectState(state, (ValueNode) input); + if (obj != null) { + VirtualUtil.trace("replacing input %s at %s: %s", input, node, obj); + replaceWithMaterialized(input, node, insertBefore, state, obj, effects, METRIC_MATERIALIZATIONS_UNHANDLED); + } } } if (node instanceof NodeWithState) { @@ -124,76 +158,76 @@ private void processNodeWithState(NodeWithState nodeWithState, final BlockT state, final GraphEffectList effects) { for (FrameState fs : nodeWithState.states()) { - FrameState frameState = fs; - if (frameState.getUsageCount() > 1) { - // Can happen for example from inlined snippets with multiple state split nodes. - FrameState copy = (FrameState) frameState.copyWithInputs(); - nodeWithState.asNode().replaceFirstInput(frameState, copy); - frameState = copy; - } - final Set virtual = new ArraySet<>(); - frameState.applyToNonVirtual(new NodeClosure() { + FrameState frameState = getUniqueFramestate(nodeWithState, fs); + Set virtual = new ArraySet<>(); + frameState.applyToNonVirtual(new CollectVirtualObjectsClosure(virtual, effects, state)); + collectLockedVirtualObjects(state, virtual); + collectReferencedVirtualObjects(state, virtual); + addVirtualMappings(state, effects, frameState, virtual); + } + } + + private static FrameState getUniqueFramestate(NodeWithState nodeWithState, FrameState frameState) { + if (frameState.getUsageCount() > 1) { + // Can happen for example from inlined snippets with multiple state split nodes. + FrameState copy = (FrameState) frameState.copyWithInputs(); + nodeWithState.asNode().replaceFirstInput(frameState, copy); + return copy; + } + return frameState; + } - @Override - public void apply(Node usage, ValueNode value) { - ObjectState valueObj = getObjectState(state, value); - if (valueObj != null) { - virtual.add(valueObj); - effects.replaceFirstInput(usage, value, valueObj.virtual); - } else if (value instanceof VirtualObjectNode) { - ObjectState virtualObj = null; - for (ObjectState obj : state.getStates()) { - if (value == obj.virtual) { - virtualObj = obj; - break; - } - } - if (virtualObj != null) { - virtual.add(virtualObj); - } - } - } - }); - for (ObjectState obj : state.getStates()) { - if (obj.isVirtual() && obj.hasLocks()) { - virtual.add(obj); - } + private void addVirtualMappings(final BlockT state, final GraphEffectList effects, FrameState frameState, Set virtual) { + for (ObjectState obj : virtual) { + EscapeObjectState v; + if (obj.isVirtual()) { + v = createVirtualObjectState(state, obj); + } else { + v = new MaterializedObjectState(obj.virtual, obj.getMaterializedValue()); } + effects.addVirtualMapping(frameState, v); + } + } - ArrayDeque queue = new ArrayDeque<>(virtual); - while (!queue.isEmpty()) { - ObjectState obj = queue.removeLast(); - if (obj.isVirtual()) { - for (ValueNode field : obj.getEntries()) { - if (field instanceof VirtualObjectNode) { - ObjectState fieldObj = state.getObjectState((VirtualObjectNode) field); - if (fieldObj.isVirtual() && !virtual.contains(fieldObj)) { - virtual.add(fieldObj); - queue.addLast(fieldObj); - } + private void collectReferencedVirtualObjects(final BlockT state, final Set virtual) { + ArrayDeque queue = new ArrayDeque<>(virtual); + while (!queue.isEmpty()) { + ObjectState obj = queue.removeLast(); + if (obj.isVirtual()) { + for (ValueNode entry : obj.getEntries()) { + if (entry instanceof VirtualObjectNode) { + ObjectState fieldObj = state.getObjectState((VirtualObjectNode) entry); + if (fieldObj.isVirtual() && !virtual.contains(fieldObj)) { + virtual.add(fieldObj); + queue.addLast(fieldObj); } } } } - for (ObjectState obj : virtual) { - EscapeObjectState v; - if (obj.isVirtual()) { - ValueNode[] fieldState = obj.getEntries().clone(); - for (int i = 0; i < fieldState.length; i++) { - ObjectState valueObj = getObjectState(state, fieldState[i]); - if (valueObj != null) { - if (valueObj.isVirtual()) { - fieldState[i] = valueObj.virtual; - } else { - fieldState[i] = valueObj.getMaterializedValue(); - } - } - } - v = new VirtualObjectState(obj.virtual, fieldState); + } + } + + private EscapeObjectState createVirtualObjectState(final BlockT state, ObjectState obj) { + EscapeObjectState v; + ValueNode[] fieldState = obj.getEntries().clone(); + for (int i = 0; i < fieldState.length; i++) { + ObjectState valueObj = getObjectState(state, fieldState[i]); + if (valueObj != null) { + if (valueObj.isVirtual()) { + fieldState[i] = valueObj.virtual; } else { - v = new MaterializedObjectState(obj.virtual, obj.getMaterializedValue()); + fieldState[i] = valueObj.getMaterializedValue(); } - effects.addVirtualMapping(frameState, v); + } + } + v = new VirtualObjectState(obj.virtual, fieldState); + return v; + } + + private void collectLockedVirtualObjects(final BlockT state, final Set virtual) { + for (ObjectState obj : state.getStates()) { + if (obj.isVirtual() && obj.hasLocks()) { + virtual.add(obj); } } } @@ -222,44 +256,51 @@ @Override protected void processLoopExit(LoopExitNode exitNode, BlockT initialState, BlockT exitState, GraphEffectList effects) { - Map proxies = Node.newMap(); - - for (ProxyNode proxy : exitNode.proxies()) { - ObjectState obj = getObjectState(exitState, proxy.value()); - if (obj != null) { - proxies.put(obj.virtual, proxy); + if (exitNode.graph().hasValueProxies()) { + Map proxies = Node.newMap(); + for (ProxyNode proxy : exitNode.proxies()) { + ObjectState obj = getObjectState(exitState, proxy.value()); + if (obj != null) { + proxies.put(obj.virtual, proxy); + } } - } - if (exitNode.graph().hasValueProxies()) { for (ObjectState obj : exitState.getStates()) { ObjectState initialObj = initialState.getObjectStateOptional(obj.virtual); if (obj.isVirtual()) { - for (int i = 0; i < obj.getEntries().length; i++) { - ValueNode value = obj.getEntry(i); - if (!(value instanceof VirtualObjectNode || value.isConstant())) { - if (exitNode.loopBegin().isPhiAtMerge(value) || initialObj == null || !initialObj.isVirtual() || initialObj.getEntry(i) != value) { - ProxyNode proxy = new ValueProxyNode(value, exitNode); - obj.setEntry(i, proxy); - effects.addFloatingNode(proxy, "virtualProxy"); - } - } - } + processVirtualAtLoopExit(exitNode, effects, obj, initialObj); } else { - if (initialObj == null || initialObj.isVirtual()) { - ProxyNode proxy = proxies.get(obj.virtual); - if (proxy == null) { - proxy = new ValueProxyNode(obj.getMaterializedValue(), exitNode); - effects.addFloatingNode(proxy, "proxy"); - } else { - effects.replaceFirstInput(proxy, proxy.value(), obj.getMaterializedValue()); - // nothing to do - will be handled in processNode - } - obj.updateMaterializedValue(proxy); - } else { - if (initialObj.getMaterializedValue() == obj.getMaterializedValue()) { - Debug.log("materialized value changes within loop: %s vs. %s at %s", initialObj.getMaterializedValue(), obj.getMaterializedValue(), exitNode); - } - } + processMaterializedAtLoopExit(exitNode, effects, proxies, obj, initialObj); + } + } + } + } + + private static void processMaterializedAtLoopExit(LoopExitNode exitNode, GraphEffectList effects, Map proxies, ObjectState obj, ObjectState initialObj) { + if (initialObj == null || initialObj.isVirtual()) { + ProxyNode proxy = proxies.get(obj.virtual); + if (proxy == null) { + proxy = new ValueProxyNode(obj.getMaterializedValue(), exitNode); + effects.addFloatingNode(proxy, "proxy"); + } else { + effects.replaceFirstInput(proxy, proxy.value(), obj.getMaterializedValue()); + // nothing to do - will be handled in processNode + } + obj.updateMaterializedValue(proxy); + } else { + if (initialObj.getMaterializedValue() == obj.getMaterializedValue()) { + Debug.log("materialized value changes within loop: %s vs. %s at %s", initialObj.getMaterializedValue(), obj.getMaterializedValue(), exitNode); + } + } + } + + private static void processVirtualAtLoopExit(LoopExitNode exitNode, GraphEffectList effects, ObjectState obj, ObjectState initialObj) { + for (int i = 0; i < obj.getEntries().length; i++) { + ValueNode value = obj.getEntry(i); + if (!(value instanceof VirtualObjectNode || value.isConstant())) { + if (exitNode.loopBegin().isPhiAtMerge(value) || initialObj == null || !initialObj.isVirtual() || initialObj.getEntry(i) != value) { + ProxyNode proxy = new ValueProxyNode(value, exitNode); + obj.setEntry(i, proxy); + effects.addFloatingNode(proxy, "virtualProxy"); } } } @@ -322,10 +363,7 @@ super.merge(states); // calculate the set of virtual objects that exist in all predecessors - Set virtualObjTemp = Node.newSet(states.get(0).getVirtualObjects()); - for (int i = 1; i < states.size(); i++) { - virtualObjTemp.retainAll(states.get(i).getVirtualObjects()); - } + Set virtualObjTemp = intersectVirtualObjects(states); ObjectState[] objStates = new ObjectState[states.size()]; boolean materialized; @@ -361,8 +399,10 @@ mergeEffects.addFloatingNode(materializedValuePhi, "materializedPhi"); for (int i = 0; i < objStates.length; i++) { ObjectState obj = objStates[i]; - Block predecessor = mergeBlock.getPredecessors().get(i); - materialized |= ensureMaterialized(states.get(i), obj, predecessor.getEndNode(), blockEffects.get(predecessor), METRIC_MATERIALIZATIONS_MERGE); + if (obj.isVirtual()) { + Block predecessor = mergeBlock.getPredecessors().get(i); + materialized |= ensureMaterialized(states.get(i), obj, predecessor.getEndNode(), blockEffects.get(predecessor), METRIC_MATERIALIZATIONS_MERGE); + } afterMergeEffects.addPhiInput(materializedValuePhi, obj.getMaterializedValue()); } newState.addObject(object, new ObjectState(object, materializedValuePhi, EscapeState.Materialized, null)); @@ -383,6 +423,14 @@ } while (materialized); } + private Set intersectVirtualObjects(List states) { + Set virtualObjTemp = Node.newSet(states.get(0).getVirtualObjects()); + for (int i = 1; i < states.size(); i++) { + virtualObjTemp.retainAll(states.get(i).getVirtualObjects()); + } + return virtualObjTemp; + } + /** * Try to merge multiple virtual object states into a single object state. If the incoming * object states are compatible, then this method will create PhiNodes for the object's @@ -628,8 +676,8 @@ } } - public ObjectState getObjectState(PartialEscapeBlockState state, Node value) { - if (value == null || value instanceof VirtualState) { + public ObjectState getObjectState(PartialEscapeBlockState state, ValueNode value) { + if (value == null) { return null; } if (value.isAlive() && !aliases.isNew(value)) {