# HG changeset patch # User Doug Simon # Date 1339683954 -7200 # Node ID 46f8a4c46b6a895ce2703e1b057c30401a1e9433 # Parent dbd82d1edce6535e0c9674728062b4768c123660# Parent a9b615da0cba85a20307d2d9302ed494cc1bc533 Merge. diff -r dbd82d1edce6 -r 46f8a4c46b6a graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/DebugInfoBuilder.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/DebugInfoBuilder.java Thu Jun 14 16:20:59 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/DebugInfoBuilder.java Thu Jun 14 16:25:54 2012 +0200 @@ -32,7 +32,6 @@ import com.oracle.graal.graph.*; import com.oracle.graal.lir.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.PhiNode.PhiType; import com.oracle.graal.nodes.virtual.*; public class DebugInfoBuilder { @@ -52,20 +51,13 @@ VirtualObject[] virtualObjectsArray = null; if (virtualObjects.size() != 0) { // collect all VirtualObjectField instances: - IdentityHashMap objectStates = new IdentityHashMap<>(); + IdentityHashMap objectStates = new IdentityHashMap<>(); FrameState current = topState; do { - for (Node n : current.virtualObjectMappings()) { - Node p = n; - while (p instanceof PhiNode) { - PhiNode phi = (PhiNode) p; - assert phi.type() == PhiType.Virtual; - p = phi.valueAt(0); - } - VirtualObjectFieldNode field = (VirtualObjectFieldNode) p; + for (VirtualObjectState state : current.virtualObjectMappings()) { // null states occur for objects with 0 fields - if (field != null && !objectStates.containsKey(field.object())) { - objectStates.put(field.object(), field); + if (!objectStates.containsKey(state.object())) { + objectStates.put(state.object(), state); } } current = current.outerFrameState(); @@ -87,20 +79,11 @@ entry.getValue().setValues(values); if (values.length > 0) { changed = true; - ValueNode currentField = objectStates.get(vobj); + VirtualObjectState currentField = objectStates.get(vobj); assert currentField != null; - do { - if (currentField instanceof VirtualObjectFieldNode) { - int index = ((VirtualObjectFieldNode) currentField).index(); - if (values[index] == null) { - values[index] = toCiValue(((VirtualObjectFieldNode) currentField).input()); - } - currentField = ((VirtualObjectFieldNode) currentField).lastState(); - } else { - assert currentField instanceof PhiNode : currentField; - currentField = ((PhiNode) currentField).valueAt(0); - } - } while (currentField != null); + for (int i = 0; i < vobj.fieldsCount(); i++) { + values[i] = toCiValue(currentField.fields().get(i)); + } } } } diff -r dbd82d1edce6 -r 46f8a4c46b6a graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/loop/LoopFragment.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/loop/LoopFragment.java Thu Jun 14 16:20:59 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/loop/LoopFragment.java Thu Jun 14 16:25:54 2012 +0200 @@ -30,7 +30,6 @@ import com.oracle.graal.lir.cfg.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.PhiNode.PhiType; -import com.oracle.graal.nodes.util.*; public abstract class LoopFragment { @@ -244,14 +243,8 @@ PhiNode phi = graph.add(vpn.type() == PhiType.Value ? new PhiNode(vpn.kind(), merge) : new PhiNode(vpn.type(), merge)); phi.addInput(vpn); phi.addInput(newVpn); - if (vpn.type() == PhiType.Value) { - replaceWith = phi; - } else { - assert vpn.type() == PhiType.Virtual; - ValueNode vof = GraphUtil.unProxify(vpn); - ValueNode newVof = GraphUtil.unProxify(newVpn); - replaceWith = GraphUtil.mergeVirtualChain(graph, vof, newVof, phi, earlyExit, newEarlyExit, merge); - } + assert vpn.type() == PhiType.Value; + replaceWith = phi; } else { replaceWith = vpn.value(); } diff -r dbd82d1edce6 -r 46f8a4c46b6a graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/loop/LoopFragmentInside.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/loop/LoopFragmentInside.java Thu Jun 14 16:20:59 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/loop/LoopFragmentInside.java Thu Jun 14 16:25:54 2012 +0200 @@ -246,9 +246,6 @@ if (duplicateState != null) { duplicateState.replaceFirstInput(phi, firstPhi); // fix the merge's state after } - if (phi.type() == PhiType.Virtual) { - initializer = GraphUtil.mergeVirtualChain(graph, firstPhi, newExitMerge); - } mergedInitializers.put(phi, initializer); } } diff -r dbd82d1edce6 -r 46f8a4c46b6a graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/BoxingEliminationPhase.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/BoxingEliminationPhase.java Thu Jun 14 16:20:59 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/BoxingEliminationPhase.java Thu Jun 14 16:25:54 2012 +0200 @@ -110,7 +110,7 @@ assert boxNode.objectStamp().isExactType(); virtualizeUsages(boxNode, boxNode.source(), boxNode.objectStamp().type()); - if (boxNode.usages().filter(isNotA(FrameState.class).nor(VirtualObjectFieldNode.class)).isNotEmpty()) { + if (boxNode.usages().filter(isNotA(VirtualState.class)).isNotEmpty()) { // Elimination failed, because boxing object escapes. return; } @@ -125,7 +125,7 @@ private static void virtualizeUsages(ValueNode boxNode, ValueNode replacement, ResolvedJavaType exactType) { ValueNode virtualValueNode = null; VirtualObjectNode virtualObjectNode = null; - for (Node n : boxNode.usages().filter(NodePredicates.isA(FrameState.class).or(VirtualObjectFieldNode.class)).snapshot()) { + for (Node n : boxNode.usages().filter(NodePredicates.isA(VirtualState.class)).snapshot()) { if (virtualValueNode == null) { virtualObjectNode = n.graph().unique(new BoxedVirtualObjectNode(exactType, replacement)); } diff -r dbd82d1edce6 -r 46f8a4c46b6a graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/EscapeAnalysisPhase.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/EscapeAnalysisPhase.java Thu Jun 14 16:20:59 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/EscapeAnalysisPhase.java Thu Jun 14 16:25:54 2012 +0200 @@ -24,7 +24,6 @@ import java.util.*; -import com.oracle.max.criutils.*; import com.oracle.graal.api.code.*; import com.oracle.graal.compiler.*; import com.oracle.graal.compiler.graph.*; @@ -38,38 +37,34 @@ import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.virtual.*; +import com.oracle.max.criutils.*; public class EscapeAnalysisPhase extends Phase { + /** + * Encapsulates the state of the virtual object, which is updated while traversing the control flow graph. + */ public static class BlockExitState implements MergeableState { public final ValueNode[] fieldState; public final VirtualObjectNode virtualObject; - public ValueNode virtualObjectField; public final Graph graph; public BlockExitState(EscapeField[] fields, VirtualObjectNode virtualObject) { this.fieldState = new ValueNode[fields.length]; this.virtualObject = virtualObject; - this.virtualObjectField = null; this.graph = virtualObject.graph(); for (int i = 0; i < fields.length; i++) { fieldState[i] = ConstantNode.defaultForKind(fields[i].type().kind(), virtualObject.graph()); - virtualObjectField = graph.add(new VirtualObjectFieldNode(virtualObject, virtualObjectField, fieldState[i], i)); } } public BlockExitState(BlockExitState state) { this.fieldState = state.fieldState.clone(); this.virtualObject = state.virtualObject; - this.virtualObjectField = state.virtualObjectField; this.graph = state.graph; } - public void updateField(int fieldIndex) { - virtualObjectField = graph.add(new VirtualObjectFieldNode(virtualObject, virtualObjectField, fieldState[fieldIndex], fieldIndex)); - } - @Override public BlockExitState clone() { return new BlockExitState(this); @@ -77,14 +72,8 @@ @Override public boolean merge(MergeNode merge, List withStates) { - PhiNode vobjPhi = null; PhiNode[] valuePhis = new PhiNode[fieldState.length]; for (BlockExitState other : withStates) { - if (virtualObjectField != other.virtualObjectField && vobjPhi == null) { - vobjPhi = graph.add(new PhiNode(PhiType.Virtual, merge)); - vobjPhi.addInput(virtualObjectField); - virtualObjectField = vobjPhi; - } for (int i2 = 0; i2 < fieldState.length; i2++) { if (fieldState[i2] != other.fieldState[i2] && valuePhis[i2] == null) { valuePhis[i2] = graph.add(new PhiNode(fieldState[i2].kind(), merge)); @@ -94,51 +83,27 @@ } } for (BlockExitState other : withStates) { - if (vobjPhi != null) { - vobjPhi.addInput(other.virtualObjectField); - } for (int i2 = 0; i2 < fieldState.length; i2++) { if (valuePhis[i2] != null) { valuePhis[i2].addInput(other.fieldState[i2]); } } } - assert vobjPhi == null || vobjPhi.valueCount() == withStates.size() + 1; - for (int i2 = 0; i2 < fieldState.length; i2++) { - if (valuePhis[i2] != null) { - virtualObjectField = graph.add(new VirtualObjectFieldNode(virtualObject, virtualObjectField, valuePhis[i2], i2)); - assert valuePhis[i2].valueCount() == withStates.size() + 1; - } - } return true; } @Override public void loopBegin(LoopBeginNode loopBegin) { - assert virtualObjectField != null : "unexpected null virtualObjectField"; - PhiNode vobjPhi = null; - vobjPhi = graph.add(new PhiNode(PhiType.Virtual, loopBegin)); - vobjPhi.addInput(virtualObjectField); - virtualObjectField = vobjPhi; for (int i2 = 0; i2 < fieldState.length; i2++) { PhiNode valuePhi = graph.add(new PhiNode(fieldState[i2].kind(), loopBegin)); valuePhi.addInput(fieldState[i2]); fieldState[i2] = valuePhi; - updateField(i2); } } @Override public void loopEnds(LoopBeginNode loopBegin, List loopEndStates) { - while (!loopBegin.isPhiAtMerge(virtualObjectField)) { - if (virtualObjectField instanceof PhiNode) { - virtualObjectField = ((PhiNode) virtualObjectField).valueAt(0); - } else { - virtualObjectField = ((VirtualObjectFieldNode) virtualObjectField).lastState(); - } - } for (BlockExitState loopEndState : loopEndStates) { - ((PhiNode) virtualObjectField).addInput(loopEndState.virtualObjectField); for (int i2 = 0; i2 < fieldState.length; i2++) { ((PhiNode) fieldState[i2]).addInput(loopEndState.fieldState[i2]); } @@ -175,6 +140,12 @@ } } + private void process() { + for (Node usage : node.usages().snapshot()) { + op.beforeUpdate(node, usage); + } + } + public void removeAllocation() { escapeFields = op.fields(node); for (int i = 0; i < escapeFields.length; i++) { @@ -202,42 +173,21 @@ final PostOrderNodeIterator iterator = new PostOrderNodeIterator(next, startState) { @Override protected void node(FixedNode curNode) { - int changedField = op.updateState(virtual, curNode, fields, state.fieldState); - if (changedField != -1) { - state.updateField(changedField); - } + op.updateState(virtual, curNode, fields, state.fieldState); if (curNode instanceof LoopExitNode) { - state.virtualObjectField = graph.unique(new ValueProxyNode(state.virtualObjectField, (LoopExitNode) curNode, PhiType.Virtual)); for (int i = 0; i < state.fieldState.length; i++) { state.fieldState[i] = graph.unique(new ValueProxyNode(state.fieldState[i], (LoopExitNode) curNode, PhiType.Value)); } } if (!curNode.isDeleted() && curNode instanceof StateSplit && ((StateSplit) curNode).stateAfter() != null) { - if (state.virtualObjectField != null) { - ValueNode v = state.virtualObjectField; - if (curNode instanceof LoopBeginNode) { - while (!((LoopBeginNode) curNode).isPhiAtMerge(v)) { - if (v instanceof PhiNode) { - v = ((PhiNode) v).valueAt(0); - } else { - v = ((VirtualObjectFieldNode) v).lastState(); - } - } - } - ((StateSplit) curNode).stateAfter().addVirtualObjectMapping(v); - } + VirtualObjectState v = graph.add(new VirtualObjectState(virtual, state.fieldState)); + ((StateSplit) curNode).stateAfter().addVirtualObjectMapping(v); } } }; iterator.apply(); } } - - private void process() { - for (Node usage : node.usages().snapshot()) { - op.beforeUpdate(node, usage); - } - } } private final TargetDescription target; @@ -278,7 +228,7 @@ private static Node escape(EscapeRecord record, Node usage) { final Node node = record.node; - if (usage instanceof FrameState) { + if (usage instanceof VirtualState) { assert usage.inputs().contains(node); return null; } else { @@ -318,8 +268,6 @@ // in order to not escape, the access needs to have a valid constant index and either a store into node or be self-referencing return EscapeOp.isValidConstantIndex(x) && x.value() != node ? null : x.array(); } - } else if (usage instanceof VirtualObjectFieldNode) { - return null; } else if (usage instanceof RegisterFinalizerNode) { assert ((RegisterFinalizerNode) usage).object() == node; return null; @@ -467,7 +415,7 @@ for (Node usage : node.usages().snapshot()) { boolean escapes = op.escape(node, usage); if (escapes) { - if (usage instanceof FrameState) { + if (usage instanceof VirtualState) { // nothing to do... } else if (usage instanceof MethodCallTargetNode) { if (usage.usages().size() == 0) { diff -r dbd82d1edce6 -r 46f8a4c46b6a graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/InsertStateAfterPlaceholderPhase.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/InsertStateAfterPlaceholderPhase.java Thu Jun 14 16:20:59 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/InsertStateAfterPlaceholderPhase.java Thu Jun 14 16:25:54 2012 +0200 @@ -49,7 +49,7 @@ protected void run(StructuredGraph graph) { for (ReturnNode ret : graph.getNodes(ReturnNode.class)) { PlaceholderNode p = graph.add(new PlaceholderNode()); - p.setStateAfter(graph.add(new FrameState(null, FrameState.AFTER_BCI, 0, 0, false, false))); + p.setStateAfter(graph.add(new FrameState(FrameState.AFTER_BCI))); graph.addBeforeFixed(ret, p); } } diff -r dbd82d1edce6 -r 46f8a4c46b6a graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/schedule/SchedulePhase.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/schedule/SchedulePhase.java Thu Jun 14 16:20:59 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/schedule/SchedulePhase.java Thu Jun 14 16:25:54 2012 +0200 @@ -130,7 +130,7 @@ Block block; if (latestBlock == null) { block = earliestBlock(node); - } else if (GraalOptions.ScheduleOutOfLoops && !(node instanceof VirtualObjectFieldNode) && !(node instanceof VirtualObjectNode)) { + } else if (GraalOptions.ScheduleOutOfLoops && !(node instanceof VirtualObjectNode)) { Block earliestBlock = earliestBlock(node); block = scheduleOutOfLoops(node, latestBlock, earliestBlock); assert earliestBlock.dominates(block) : "Graph can not be scheduled : inconsistent for " + node + " (" + earliestBlock + " needs to dominate " + block + ")"; @@ -260,22 +260,26 @@ closure.apply(mergeBlock.getPredecessors().get(i)); } } - } else if (usage instanceof FrameState) { + } else if (usage instanceof VirtualState) { // The following logic does not work if node is a PhiNode, but this method is never called for PhiNodes. - for (Node frameStateUsage : usage.usages()) { - if (frameStateUsage instanceof FrameState) { + for (Node unscheduledUsage : usage.usages()) { + if (unscheduledUsage instanceof VirtualState) { // If a FrameState is an outer FrameState this method behaves as if the inner FrameState was the actual usage, by recursing. - blocksForUsage(node, frameStateUsage, closure); - } else if (frameStateUsage instanceof MergeNode) { + blocksForUsage(node, unscheduledUsage, closure); + } else if (unscheduledUsage instanceof MergeNode) { + // Only FrameStates can be connected to MergeNodes. + assert usage instanceof FrameState; // If a FrameState belongs to a MergeNode then it's inputs will be placed at the common dominator of all EndNodes. - for (Node pred : frameStateUsage.cfgPredecessors()) { + for (Node pred : unscheduledUsage.cfgPredecessors()) { closure.apply(cfg.getNodeToBlock().get(pred)); } } else { + // For the time being, only FrameStates can be connected to StateSplits. + assert usage instanceof FrameState; + assert unscheduledUsage instanceof StateSplit; // Otherwise: Put the input into the same block as the usage. - assert frameStateUsage instanceof StateSplit; - assignBlockToNode((ScheduledNode) frameStateUsage); - closure.apply(cfg.getNodeToBlock().get(frameStateUsage)); + assignBlockToNode((ScheduledNode) unscheduledUsage); + closure.apply(cfg.getNodeToBlock().get(unscheduledUsage)); } } } else { @@ -351,13 +355,14 @@ blockToNodesMap.put(b, sortedInstructions); } - private void addFrameStateToSorting(Block b, FrameState state, List sortedInstructions, NodeBitMap visited) { + private void addUnscheduledToSorting(Block b, VirtualState state, List sortedInstructions, NodeBitMap visited) { if (state != null) { + // UnscheduledNodes should never be marked as visited. assert !visited.isMarked(state); for (Node input : state.inputs()) { - if (input instanceof FrameState) { - addFrameStateToSorting(b, (FrameState) input, sortedInstructions, visited); + if (input instanceof VirtualState) { + addUnscheduledToSorting(b, (VirtualState) input, sortedInstructions, visited); } else { addToSorting(b, (ScheduledNode) input, sortedInstructions, visited); } @@ -386,7 +391,7 @@ addToSorting(b, (ScheduledNode) i.predecessor(), sortedInstructions, visited); visited.mark(i); - addFrameStateToSorting(b, state, sortedInstructions, visited); + addUnscheduledToSorting(b, state, sortedInstructions, visited); assert write == null || !visited.isMarked(write); addToSorting(b, write, sortedInstructions, visited); diff -r dbd82d1edce6 -r 46f8a4c46b6a graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeList.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeList.java Thu Jun 14 16:20:59 2012 +0200 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeList.java Thu Jun 14 16:25:54 2012 +0200 @@ -21,11 +21,7 @@ * questions. */ package com.oracle.graal.graph; -import java.util.Arrays; -import java.util.Collection; -import java.util.Iterator; -import java.util.List; -import java.util.ListIterator; +import java.util.*; import com.oracle.graal.graph.iterators.*; @@ -60,6 +56,7 @@ this.nodes = new Node[elements.length]; for (int i = 0; i < elements.length; i++) { this.nodes[i] = elements[i]; + assert this.nodes[i] == null || !this.nodes[i].isDeleted(); } } } @@ -75,6 +72,7 @@ this.nodes = new Node[elements.size()]; for (int i = 0; i < elements.size(); i++) { this.nodes[i] = elements.get(i); + assert this.nodes[i] == null || !this.nodes[i].isDeleted(); } } } diff -r dbd82d1edce6 -r 46f8a4c46b6a graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/CallTargetNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/CallTargetNode.java Thu Jun 14 16:20:59 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/CallTargetNode.java Thu Jun 14 16:25:54 2012 +0200 @@ -28,6 +28,7 @@ import com.oracle.graal.nodes.type.*; public abstract class CallTargetNode extends ValueNode implements LIRLowerable { + @Input protected final NodeInputList arguments; public CallTargetNode(ValueNode[] arguments) { @@ -45,6 +46,6 @@ @Override public void generate(LIRGeneratorTool gen) { - //nop + // nop } } diff -r dbd82d1edce6 -r 46f8a4c46b6a 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 Thu Jun 14 16:20:59 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FrameState.java Thu Jun 14 16:25:54 2012 +0200 @@ -35,7 +35,7 @@ * The {@code FrameState} class encapsulates the frame state (i.e. local variables and * operand stack) at a particular point in the abstract interpretation. */ -public final class FrameState extends Node implements Node.IterableNodeType, LIRLowerable { +public final class FrameState extends VirtualState implements Node.IterableNodeType, LIRLowerable { protected final int localsSize; @@ -74,11 +74,10 @@ @Input private final NodeInputList values; - @Input private final NodeInputList virtualObjectMappings; + @Input private final NodeInputList virtualObjectMappings; /** - * The bytecode index to which this frame state applies. This will be {@code -1} - * iff this state is mutable. + * The bytecode index to which this frame state applies. */ public final int bci; @@ -93,19 +92,28 @@ * @param stackSize size of the stack * @param rethrowException if true the VM should re-throw the exception on top of the stack when deopt'ing using this framestate */ - public FrameState(ResolvedJavaMethod method, int bci, int localsSize, int stackSize, boolean rethrowException, boolean duringCall) { + public FrameState(ResolvedJavaMethod method, int bci, List values, int stackSize, boolean rethrowException, boolean duringCall, List virtualObjectMappings) { assert stackSize >= 0; + assert (bci >= 0 && method != null) || (bci < 0 && method == null && values.isEmpty()); this.method = method; this.bci = bci; - this.localsSize = localsSize; + this.localsSize = values.size() - stackSize; this.stackSize = stackSize; - this.values = new NodeInputList<>(this, localsSize + stackSize); - this.virtualObjectMappings = new NodeInputList<>(this); + this.values = new NodeInputList<>(this, values); + this.virtualObjectMappings = new NodeInputList<>(this, virtualObjectMappings); this.rethrowException = rethrowException; this.duringCall = duringCall; assert !rethrowException || stackSize == 1 : "must have exception on top of the stack"; } + /** + * Simple constructor used to create marker FrameStates. + * @param bci marker bci, needs to be < 0 + */ + public FrameState(int bci) { + this(null, bci, Collections.emptyList(), 0, false, false, Collections.emptyList()); + } + public FrameState(ResolvedJavaMethod method, int bci, ValueNode[] locals, ValueNode[] stack, int stackSize, boolean rethrowException, boolean duringCall) { this.method = method; this.bci = bci; @@ -140,10 +148,6 @@ this.outerFrameState = x; } - private void setValueAt(int i, ValueNode x) { - values.set(i, x); - } - public boolean rethrowException() { return rethrowException; } @@ -160,8 +164,7 @@ return method; } - public void addVirtualObjectMapping(Node virtualObject) { - assert virtualObject instanceof VirtualObjectFieldNode || virtualObject instanceof PhiNode || virtualObject instanceof ValueProxyNode : virtualObject; + public void addVirtualObjectMapping(VirtualObjectState virtualObject) { virtualObjectMappings.add(virtualObject); } @@ -173,7 +176,7 @@ return virtualObjectMappings.get(i); } - public Iterable virtualObjectMappings() { + public Iterable virtualObjectMappings() { return virtualObjectMappings; } @@ -192,9 +195,7 @@ } public FrameState duplicate(int newBci, boolean duplicateOuter) { - FrameState other = graph().add(new FrameState(method, newBci, localsSize, stackSize, rethrowException, duringCall)); - other.values.setAll(values); - other.virtualObjectMappings.setAll(virtualObjectMappings); + FrameState other = graph().add(new FrameState(method, newBci, values, stackSize, rethrowException, duringCall, virtualObjectMappings)); FrameState newOuterFrameState = outerFrameState(); if (duplicateOuter && newOuterFrameState != null) { newOuterFrameState = newOuterFrameState.duplicate(newOuterFrameState.bci, duplicateOuter); @@ -209,30 +210,18 @@ * or double is followed by a null slot. */ public FrameState duplicateModified(int newBci, boolean newRethrowException, Kind popKind, ValueNode... pushedValues) { - int popSlots = 0; + ArrayList copy = new ArrayList<>(values); if (popKind != Kind.Void) { if (stackAt(stackSize() - 1) == null) { - popSlots = 2; - } else { - popSlots = 1; + copy.remove(copy.size() - 1); } - assert stackAt(stackSize() - popSlots).kind().stackKind() == popKind.stackKind() || (stackAt(stackSize() - popSlots) instanceof BoxedVirtualObjectNode && popKind.isObject()); + ValueNode lastSlot = copy.get(copy.size() - 1); + assert lastSlot.kind().stackKind() == popKind.stackKind() || (lastSlot instanceof BoxedVirtualObjectNode && popKind.isObject()); + copy.remove(copy.size() - 1); } + Collections.addAll(copy, pushedValues); - int pushSlots = pushedValues.length; - FrameState other = graph().add(new FrameState(method, newBci, localsSize, stackSize - popSlots + pushSlots, newRethrowException, false)); - for (int i = 0; i < localsSize; i++) { - other.setValueAt(i, localAt(i)); - } - for (int i = 0; i < stackSize - popSlots; i++) { - other.setValueAt(localsSize + i, stackAt(i)); - } - int slot = localsSize + stackSize - popSlots; - for (int i = 0; i < pushSlots; i++) { - assert pushedValues[i] == null || !pushedValues[i].kind().isVoid(); - other.setValueAt(slot++, pushedValues[i]); - } - other.virtualObjectMappings.setAll(virtualObjectMappings); + FrameState other = graph().add(new FrameState(method, newBci, copy, copy.size() - localsSize, newRethrowException, false, virtualObjectMappings)); other.setOuterFrameState(outerFrameState()); return other; } diff -r dbd82d1edce6 -r 46f8a4c46b6a graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PhiNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PhiNode.java Thu Jun 14 16:20:59 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PhiNode.java Thu Jun 14 16:25:54 2012 +0200 @@ -36,8 +36,7 @@ public static enum PhiType { Value(null), // normal value phis - Memory(StampFactory.dependency()), // memory phis - Virtual(StampFactory.virtual()); // phis used for VirtualObjectField merges + Memory(StampFactory.dependency()); public final Stamp stamp; diff -r dbd82d1edce6 -r 46f8a4c46b6a graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ScheduledNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ScheduledNode.java Thu Jun 14 16:20:59 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ScheduledNode.java Thu Jun 14 16:25:54 2012 +0200 @@ -26,7 +26,7 @@ import com.oracle.graal.graph.*; -public class ScheduledNode extends Node { +public abstract class ScheduledNode extends Node { @Successor private ScheduledNode scheduledNext; // the immediate successor of the current node diff -r dbd82d1edce6 -r 46f8a4c46b6a graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/VirtualState.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/VirtualState.java Thu Jun 14 16:25:54 2012 +0200 @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.nodes; + +import com.oracle.graal.graph.*; + +/** + * Base class for nodes that contain "virtual" state, like FrameState and VirtualObjectState. + * Subclasses of this class will be treated in a special way by the scheduler. + */ +public abstract class VirtualState extends Node { + +} diff -r dbd82d1edce6 -r 46f8a4c46b6a graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/EscapeOp.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/EscapeOp.java Thu Jun 14 16:20:59 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/EscapeOp.java Thu Jun 14 16:25:54 2012 +0200 @@ -29,8 +29,6 @@ import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.java.*; -import com.oracle.graal.nodes.virtual.*; - public abstract class EscapeOp { @@ -43,7 +41,7 @@ } else if (usage instanceof IsTypeNode) { assert ((IsTypeNode) usage).objectClass() == node; return false; - } else if (usage instanceof FrameState) { + } else if (usage instanceof VirtualState) { assert usage.inputs().contains(node); return true; } else if (usage instanceof AccessMonitorNode) { @@ -73,8 +71,6 @@ // in order to not escape the access needs to have a valid constant index and either a store into node or self-referencing return !isValidConstantIndex(x) || x.value() == node && x.array() != node; } - } else if (usage instanceof VirtualObjectFieldNode) { - return false; } else if (usage instanceof RegisterFinalizerNode) { assert ((RegisterFinalizerNode) usage).object() == node; return false; @@ -112,8 +108,8 @@ ((StructuredGraph) x.graph()).replaceFloating(x, ConstantNode.forBoolean(false, node.graph())); } else if (usage instanceof IsTypeNode) { IsTypeNode x = (IsTypeNode) usage; - assert x.type() == ((ValueNode) node).objectStamp().type(); - ((StructuredGraph) x.graph()).replaceFloating(x, ConstantNode.forBoolean(true, node.graph())); + boolean result = ((ValueNode) node).objectStamp().type() == x.type(); + ((StructuredGraph) x.graph()).replaceFloating(x, ConstantNode.forBoolean(result, node.graph())); } else if (usage instanceof AccessMonitorNode) { ((AccessMonitorNode) usage).eliminate(); } diff -r dbd82d1edce6 -r 46f8a4c46b6a graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/GraphUtil.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/GraphUtil.java Thu Jun 14 16:20:59 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/GraphUtil.java Thu Jun 14 16:25:54 2012 +0200 @@ -31,14 +31,12 @@ import com.oracle.graal.graph.iterators.*; import com.oracle.graal.graph.iterators.NodePredicates.PositiveTypePredicate; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.PhiNode.PhiType; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.java.*; -import com.oracle.graal.nodes.virtual.*; public class GraphUtil { - private static final PositiveTypePredicate FLOATING = isA(FloatingNode.class).or(CallTargetNode.class).or(FrameState.class).or(VirtualObjectFieldNode.class).or(VirtualObjectNode.class); + private static final PositiveTypePredicate FLOATING = isA(FloatingNode.class).or(VirtualState.class).or(CallTargetNode.class); public static void killCFG(FixedNode node) { assert node.isAlive(); @@ -221,144 +219,4 @@ } return v; } - - private static ValueProxyNode findProxy(ValueNode value, BeginNode proxyPoint) { - for (ValueProxyNode vpn : proxyPoint.proxies()) { - ValueNode v = vpn; - while (v instanceof ValueProxyNode) { - v = ((ValueProxyNode) v).value(); - if (v == value) { - return vpn; - } - } - } - return null; - } - - public static ValueNode mergeVirtualChain( - StructuredGraph graph, - ValueNode vof, - ValueNode newVof, - PhiNode vPhi, - BeginNode earlyExit, - BeginNode newEarlyExit, - MergeNode merge) { - VirtualObjectNode vObject = virtualObject(vof); - assert virtualObject(newVof) == vObject; - ValueNode[] virtualState = virtualState(vof); - ValueNode[] newVirtualState = virtualState(newVof); - ValueNode chain = vPhi; - for (int i = 0; i < virtualState.length; i++) { - ValueNode value = virtualState[i]; - ValueNode newValue = newVirtualState[i]; - assert value.kind() == newValue.kind(); - if (value != newValue) { - PhiNode valuePhi = graph.add(new PhiNode(value.kind(), merge)); - ValueProxyNode inputProxy = findProxy(value, earlyExit); - if (inputProxy != null) { - ValueProxyNode newInputProxy = findProxy(newValue, newEarlyExit); - assert newInputProxy != null : "no proxy for " + newValue + " at " + newEarlyExit; - valuePhi.addInput(inputProxy); - valuePhi.addInput(newInputProxy); - } else { - valuePhi.addInput(graph.unique(new ValueProxyNode(value, earlyExit, PhiType.Value))); - valuePhi.addInput(newValue); - } - chain = graph.add(new VirtualObjectFieldNode(vObject, chain, valuePhi, i)); - } - } - return chain; - } - - public static ValueNode mergeVirtualChain( - StructuredGraph graph, - PhiNode vPhi, - MergeNode merge) { - NodeInputList virtuals = vPhi.values(); - VirtualObjectNode vObject = virtualObject(unProxify(virtuals.first())); - List virtualStates = new ArrayList<>(virtuals.size()); - for (ValueNode virtual : virtuals) { - virtualStates.add(virtualState(unProxify(virtual))); - } - ValueNode chain = vPhi; - int stateLength = virtualStates.get(0).length; - for (int i = 0; i < stateLength; i++) { - ValueNode v = null; - boolean reconcile = false; - for (ValueNode[] state : virtualStates) { - if (v == null) { - v = state[i]; - } else if (v != state[i]) { - reconcile = true; - break; - } - assert v.kind() == state[i].kind(); - } - if (reconcile) { - PhiNode valuePhi = graph.add(new PhiNode(v.kind(), merge)); - for (ValueNode[] state : virtualStates) { - valuePhi.addInput(state[i]); - } - chain = graph.add(new VirtualObjectFieldNode(vObject, chain, valuePhi, i)); - } - } - return chain; - } - - /** - * Returns the VirtualObjectNode associated with the virtual chain of the provided virtual node. - * @param vof a virtual ValueNode (a VirtualObjectFieldNode or a Virtual Phi) - * @return the VirtualObjectNode associated with the virtual chain of the provided virtual node. - */ - public static VirtualObjectNode virtualObject(ValueNode vof) { - assert vof instanceof VirtualObjectFieldNode || (vof instanceof PhiNode && ((PhiNode) vof).type() == PhiType.Virtual) : vof; - ValueNode currentField = vof; - do { - if (currentField instanceof VirtualObjectFieldNode) { - return ((VirtualObjectFieldNode) currentField).object(); - } else { - assert currentField instanceof PhiNode && ((PhiNode) currentField).type() == PhiType.Virtual : currentField; - currentField = ((PhiNode) currentField).valueAt(0); - } - } while (currentField != null); - throw new GraalInternalError("Invalid virtual chain : cound not find virtual object from %s", vof); - } - - /** - * Builds the state of the virtual object at the provided point into a virtual chain. - * @param vof a virtual ValueNode (a VirtualObjectFieldNode or a Virtual Phi) - * @return the state of the virtual object at the provided point into a virtual chain. - */ - public static ValueNode[] virtualState(ValueNode vof) { - return virtualState(vof, virtualObject(vof)); - } - - /** - * Builds the state of the virtual object at the provided point into a virtual chain. - * @param vof a virtual ValueNode (a VirtualObjectFieldNode or a Virtual Phi) - * @param vObj the virtual object - * @return the state of the virtual object at the provided point into a virtual chain. - */ - public static ValueNode[] virtualState(ValueNode vof, VirtualObjectNode vObj) { - int fieldsCount = vObj.fieldsCount(); - int dicovered = 0; - ValueNode[] state = new ValueNode[fieldsCount]; - ValueNode currentField = vof; - do { - if (currentField instanceof VirtualObjectFieldNode) { - int index = ((VirtualObjectFieldNode) currentField).index(); - if (state[index] == null) { - dicovered++; - state[index] = ((VirtualObjectFieldNode) currentField).input(); - } - currentField = ((VirtualObjectFieldNode) currentField).lastState(); - } else if (currentField instanceof ValueProxyNode) { - currentField = ((ValueProxyNode) currentField).value(); - } else { - assert currentField instanceof PhiNode && ((PhiNode) currentField).type() == PhiType.Virtual : currentField; - currentField = ((PhiNode) currentField).valueAt(0); - } - } while (currentField != null && dicovered < fieldsCount); - return state; - } } diff -r dbd82d1edce6 -r 46f8a4c46b6a graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualObjectFieldNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualObjectFieldNode.java Thu Jun 14 16:20:59 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,90 +0,0 @@ -/* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.nodes.virtual; - -import java.util.*; - -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; - -public class VirtualObjectFieldNode extends ValueNode implements LIRLowerable { - - @Input private VirtualObjectNode object; - @Input private ValueNode lastState; - @Input private ValueNode input; - - private int index; - - public VirtualObjectNode object() { - return object; - } - - public ValueNode lastState() { - return lastState; - } - - public ValueNode input() { - return input; - } - - public VirtualObjectFieldNode(VirtualObjectNode object, ValueNode lastState, ValueNode input, int index) { - super(StampFactory.virtual()); - this.index = index; - this.object = object; - this.lastState = lastState; - this.input = input; - } - - public int index() { - return index; - } - - @Override - public void generate(LIRGeneratorTool gen) { - // nothing to do... - } - - @Override - public boolean verify() { - assertTrue(object != null, "No object"); - assertTrue(input != null, "No input"); - return super.verify(); - } - - @Override - public Map getDebugProperties() { - Map properties = super.getDebugProperties(); - properties.put("index", index); - return properties; - } - - @Override - public String toString(Verbosity verbosity) { - if (verbosity == Verbosity.Name && object() != null && object().fields() != null) { - return super.toString(Verbosity.Name) + " " + object().fields()[index].name(); - } else { - return super.toString(verbosity); - } - } -} diff -r dbd82d1edce6 -r 46f8a4c46b6a graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualObjectNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualObjectNode.java Thu Jun 14 16:20:59 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualObjectNode.java Thu Jun 14 16:25:54 2012 +0200 @@ -23,12 +23,11 @@ package com.oracle.graal.nodes.virtual; import com.oracle.graal.api.meta.*; -import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; - -public class VirtualObjectNode extends ValueNode implements LIRLowerable { +public class VirtualObjectNode extends FloatingNode implements LIRLowerable { private ResolvedJavaType type; private EscapeField[] fields; diff -r dbd82d1edce6 -r 46f8a4c46b6a graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualObjectState.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualObjectState.java Thu Jun 14 16:25:54 2012 +0200 @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.nodes.virtual; + +import com.oracle.graal.graph.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.spi.*; + +/** + * This class encapsulated the virtual state of an escape analyzed object. + */ +public final class VirtualObjectState extends VirtualState implements Node.IterableNodeType, LIRLowerable { + + @Input private VirtualObjectNode object; + @Input private NodeInputList fields; + + public VirtualObjectNode object() { + return object; + } + + public NodeInputList fields() { + return fields; + } + + public VirtualObjectState(VirtualObjectNode object, ValueNode[] fields) { + this.object = object; + assert object.fields().length == fields.length; + this.fields = new NodeInputList<>(this, fields); + } + + @Override + public void generate(LIRGeneratorTool generator) { + // Nothing to do, virtual object states are processed as part of the handling of StateSplit nodes. + } +}