--- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/GraphDecoder.java 2017-03-20 17:40:23.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/GraphDecoder.java 2017-03-20 17:40:23.000000000 -0700 @@ -31,14 +31,13 @@ import java.util.Arrays; import java.util.BitSet; import java.util.Deque; -import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.SortedMap; import java.util.TreeMap; -import org.graalvm.compiler.common.PermanentBailoutException; +import org.graalvm.compiler.core.common.PermanentBailoutException; import org.graalvm.compiler.core.common.Fields; import org.graalvm.compiler.core.common.util.TypeReader; import org.graalvm.compiler.core.common.util.UnsafeArrayTypeReader; @@ -62,6 +61,9 @@ import org.graalvm.compiler.nodes.calc.FloatingNode; import org.graalvm.compiler.nodes.extended.IntegerSwitchNode; import org.graalvm.compiler.nodes.graphbuilderconf.LoopExplosionPlugin.LoopExplosionKind; +import org.graalvm.util.Equivalence; +import org.graalvm.util.EconomicMap; +import org.graalvm.util.EconomicSet; import jdk.vm.ci.code.Architecture; import jdk.vm.ci.meta.DeoptimizationAction; @@ -106,7 +108,7 @@ public final List unwindNodes; /** All merges created during loop explosion. */ - public final NodeBitMap loopExplosionMerges; + public final EconomicSet loopExplosionMerges; /** * The start of explosion, and the merge point for when irreducible loops are detected. Only * used when {@link MethodScope#loopExplosion} is {@link LoopExplosionKind#MERGE_EXPLODE}. @@ -119,17 +121,17 @@ this.methodStartMark = graph.getMark(); this.encodedGraph = encodedGraph; this.loopExplosion = loopExplosion; - this.cleanupTasks = new ArrayList<>(); - this.returnNodes = new ArrayList<>(); - this.unwindNodes = new ArrayList<>(); + this.cleanupTasks = new ArrayList<>(2); + this.returnNodes = new ArrayList<>(1); + this.unwindNodes = new ArrayList<>(0); if (encodedGraph != null) { reader = UnsafeArrayTypeReader.create(encodedGraph.getEncoding(), encodedGraph.getStartOffset(), architecture.supportsUnalignedMemoryAccess()); if (encodedGraph.nodeStartOffsets == null) { int nodeCount = reader.getUVInt(); - long[] nodeStartOffsets = new long[nodeCount]; + int[] nodeStartOffsets = new int[nodeCount]; for (int i = 0; i < nodeCount; i++) { - nodeStartOffsets[i] = encodedGraph.getStartOffset() - reader.getUV(); + nodeStartOffsets[i] = encodedGraph.getStartOffset() - reader.getUVInt(); } encodedGraph.nodeStartOffsets = nodeStartOffsets; } @@ -138,7 +140,7 @@ } if (loopExplosion != LoopExplosionKind.NONE) { - loopExplosionMerges = new NodeBitMap(graph); + loopExplosionMerges = EconomicSet.create(Equivalence.IDENTITY); } else { loopExplosionMerges = null; } @@ -161,7 +163,7 @@ * explosion. Only used when {@link MethodScope#loopExplosion} is * {@link LoopExplosionKind#MERGE_EXPLODE}. */ - public final Map iterationStates; + public final EconomicMap iterationStates; public final int loopBeginOrderId; /** * The worklist of fixed nodes to process. Since we already the correct processing order @@ -193,7 +195,7 @@ } protected LoopScope(MethodScope methodScope, LoopScope outer, int loopDepth, int loopIteration, int loopBeginOrderId, Node[] initialCreatedNodes, Node[] createdNodes, - Deque nextIterations, Map iterationStates) { + Deque nextIterations, EconomicMap iterationStates) { this.methodScope = methodScope; this.outer = outer; this.loopDepth = loopDepth; @@ -381,7 +383,7 @@ protected final void decode(LoopScope initialLoopScope) { LoopScope loopScope = initialLoopScope; - /* Process inlined methods. */ + /* Process (inlined) methods. */ while (loopScope != null) { MethodScope methodScope = loopScope.methodScope; @@ -495,8 +497,8 @@ int typeId = methodScope.reader.getUVInt(); assert node.getNodeClass() == methodScope.encodedGraph.getNodeClasses()[typeId]; readProperties(methodScope, node); - makeSuccessorStubs(methodScope, successorAddScope, node, updatePredecessors); makeInputNodes(methodScope, loopScope, node, true); + makeSuccessorStubs(methodScope, successorAddScope, node, updatePredecessors); LoopScope resultScope = loopScope; if (node instanceof LoopBeginNode) { @@ -533,7 +535,7 @@ resultScope = new LoopScope(methodScope, loopScope, loopScope.loopDepth + 1, 0, mergeOrderId, Arrays.copyOf(loopScope.createdNodes, loopScope.createdNodes.length), loopScope.createdNodes, // methodScope.loopExplosion != LoopExplosionKind.NONE ? new ArrayDeque<>() : null, // - methodScope.loopExplosion == LoopExplosionKind.MERGE_EXPLODE ? new HashMap<>() : null); + methodScope.loopExplosion == LoopExplosionKind.MERGE_EXPLODE ? EconomicMap.create(Equivalence.DEFAULT) : null); phiInputScope = resultScope; phiNodeScope = resultScope; @@ -592,6 +594,11 @@ protected LoopScope handleInvoke(MethodScope methodScope, LoopScope loopScope, InvokeData invokeData) { assert invokeData.invoke.callTarget() == null : "callTarget edge is ignored during decoding of Invoke"; CallTargetNode callTarget = (CallTargetNode) ensureNodeCreated(methodScope, loopScope, invokeData.callTargetOrderId); + appendInvoke(methodScope, loopScope, invokeData, callTarget); + return loopScope; + } + + protected void appendInvoke(MethodScope methodScope, LoopScope loopScope, InvokeData invokeData, CallTargetNode callTarget) { if (invokeData.invoke instanceof InvokeWithExceptionNode) { ((InvokeWithExceptionNode) invokeData.invoke).setCallTarget(callTarget); } else { @@ -605,7 +612,6 @@ if (invokeData.invoke instanceof InvokeWithExceptionNode) { ((InvokeWithExceptionNode) invokeData.invoke).setExceptionEdge((AbstractBeginNode) makeStubNode(methodScope, loopScope, invokeData.exceptionOrderId)); } - return loopScope; } /** @@ -637,7 +643,7 @@ } MergeNode merge = methodScope.graph.add(new MergeNode()); - methodScope.loopExplosionMerges.markAndGrow(merge); + methodScope.loopExplosionMerges.add(merge); if (methodScope.loopExplosion == LoopExplosionKind.MERGE_EXPLODE) { if (loopScope.iterationStates.size() == 0 && loopScope.loopDepth == 1) { @@ -674,8 +680,7 @@ FrameState newFrameState = methodScope.graph.add(new FrameState(frameState.outerFrameState(), frameState.getCode(), frameState.bci, newFrameStateValues, frameState.localsSize(), frameState.stackSize(), frameState.rethrowException(), frameState.duringCall(), frameState.monitorIds(), frameState.virtualObjectMappings())); - frameState.replaceAtUsages(newFrameState); - frameState.safeDelete(); + frameState.replaceAtUsagesAndDelete(newFrameState); frameState = newFrameState; } @@ -764,7 +769,7 @@ * need to be able to create a FrameState and the necessary proxy nodes in this case. */ loopExitPlaceholder = methodScope.graph.add(new MergeNode()); - methodScope.loopExplosionMerges.markAndGrow(loopExitPlaceholder); + methodScope.loopExplosionMerges.add(loopExitPlaceholder); EndNode end = methodScope.graph.add(new EndNode()); begin.setNext(end); @@ -964,7 +969,7 @@ fields.setRawPrimitive(node, pos, primitive); } else { Object value = readObject(methodScope); - fields.set(node, pos, value); + fields.putObject(node, pos, value); } } } @@ -976,9 +981,9 @@ * nodes). */ protected void makeInputNodes(MethodScope methodScope, LoopScope loopScope, Node node, boolean updateUsages) { - Edges edges = node.getNodeClass().getEdges(Edges.Type.Inputs); + Edges edges = node.getNodeClass().getInputEdges(); for (int index = 0; index < edges.getDirectCount(); index++) { - if (skipEdge(node, edges, index, true, true)) { + if (skipDirectEdge(node, edges, index)) { continue; } int orderId = readOrderId(methodScope); @@ -990,7 +995,7 @@ } } for (int index = edges.getDirectCount(); index < edges.getCount(); index++) { - if (skipEdge(node, edges, index, false, true)) { + if (skipIndirectEdge(node, edges, index, true)) { continue; } int size = methodScope.reader.getSVInt(); @@ -1103,9 +1108,9 @@ * on top of the worklist in {@link #processNextNode}. */ protected void makeSuccessorStubs(MethodScope methodScope, LoopScope loopScope, Node node, boolean updatePredecessors) { - Edges edges = node.getNodeClass().getEdges(Edges.Type.Successors); + Edges edges = node.getNodeClass().getSuccessorEdges(); for (int index = 0; index < edges.getDirectCount(); index++) { - if (skipEdge(node, edges, index, true, true)) { + if (skipDirectEdge(node, edges, index)) { continue; } int orderId = readOrderId(methodScope); @@ -1116,7 +1121,7 @@ } } for (int index = edges.getDirectCount(); index < edges.getCount(); index++) { - if (skipEdge(node, edges, index, false, true)) { + if (skipIndirectEdge(node, edges, index, true)) { continue; } int size = methodScope.reader.getSVInt(); @@ -1154,38 +1159,9 @@ return node; } - /** - * Returns false for {@link Edges} that are not necessary in the encoded graph because they are - * reconstructed using other sources of information. - */ - protected static boolean skipEdge(Node node, Edges edges, int index, boolean direct, boolean decode) { - if (node instanceof PhiNode) { - /* The inputs of phi functions are filled manually when the end nodes are processed. */ - assert edges.type() == Edges.Type.Inputs; - if (direct) { - assert index == edges.getDirectCount() - 1 : "PhiNode has one direct input (the MergeNode)"; - } else { - assert index == edges.getCount() - 1 : "PhiNode has one variable size input (the values)"; - if (decode) { - /* The values must not be null, so initialize with an empty list. */ - edges.initializeList(node, index, new NodeInputList<>(node)); - } - } - return true; - - } else if (node instanceof AbstractMergeNode && edges.type() == Edges.Type.Inputs && !direct) { - /* The ends of merge nodes are filled manually when the ends are processed. */ - assert index == edges.getCount() - 1 : "MergeNode has one variable size input (the ends)"; - assert Edges.getNodeList(node, edges.getOffsets(), index) != null : "Input list must have been already created"; - return true; - - } else if (node instanceof LoopExitNode && edges.type() == Edges.Type.Inputs && edges.getType(index) == FrameState.class) { - /* The stateAfter of the loop exit is filled manually. */ - return true; - - } else if (node instanceof Invoke) { + protected static boolean skipDirectEdge(Node node, Edges edges, int index) { + if (node instanceof Invoke) { assert node instanceof InvokeNode || node instanceof InvokeWithExceptionNode : "The only two Invoke node classes. Got " + node.getClass(); - assert direct : "Invoke and InvokeWithException only have direct successor and input edges"; if (edges.type() == Edges.Type.Successors) { assert edges.getCount() == (node instanceof InvokeWithExceptionNode ? 2 : 1) : "InvokeNode has one successor (next); InvokeWithExceptionNode has two successors (next, exceptionEdge)"; return true; @@ -1198,6 +1174,39 @@ return true; } } + } else if (node instanceof PhiNode) { + /* The inputs of phi functions are filled manually when the end nodes are processed. */ + assert edges.type() == Edges.Type.Inputs; + assert index == edges.getDirectCount() - 1 : "PhiNode has one direct input (the MergeNode)"; + return true; + + } else if (node instanceof LoopExitNode && edges.type() == Edges.Type.Inputs && edges.getType(index) == FrameState.class) { + /* The stateAfter of the loop exit is filled manually. */ + return true; + + } + return false; + } + + protected static boolean skipIndirectEdge(Node node, Edges edges, int index, boolean decode) { + assert !(node instanceof Invoke); + assert !(node instanceof LoopExitNode && edges.type() == Edges.Type.Inputs && edges.getType(index) == FrameState.class); + if (node instanceof AbstractMergeNode && edges.type() == Edges.Type.Inputs) { + /* The ends of merge nodes are filled manually when the ends are processed. */ + assert index == edges.getCount() - 1 : "MergeNode has one variable size input (the ends)"; + assert Edges.getNodeList(node, edges.getOffsets(), index) != null : "Input list must have been already created"; + return true; + + } else if (node instanceof PhiNode) { + /* The inputs of phi functions are filled manually when the end nodes are processed. */ + assert edges.type() == Edges.Type.Inputs; + assert index == edges.getCount() - 1 : "PhiNode has one variable size input (the values)"; + if (decode) { + /* The values must not be null, so initialize with an empty list. */ + edges.initializeList(node, index, new NodeInputList<>(node)); + } + return true; + } return false; } @@ -1327,7 +1336,7 @@ private List findLoops() { /* Mapping from the loop header node to additional loop information. */ - Map unorderedLoops = new HashMap<>(); + EconomicMap unorderedLoops = EconomicMap.create(Equivalence.IDENTITY); /* Loops in reverse order of, i.e., inner loops before outer loops. */ List orderedLoops = new ArrayList<>(); @@ -1352,14 +1361,16 @@ stack.pop(); active.clear(current); - Loop loop = unorderedLoops.get(current); - if (loop != null) { - /* - * Since nodes are popped in reverse order that they were pushed, we add inner - * loops before outer loops here. - */ - assert !orderedLoops.contains(loop); - orderedLoops.add(loop); + if (current instanceof MergeNode) { + Loop loop = unorderedLoops.get((MergeNode) current); + if (loop != null) { + /* + * Since nodes are popped in reverse order that they were pushed, we add + * inner loops before outer loops here. + */ + assert !orderedLoops.contains(loop); + orderedLoops.add(loop); + } } } else { @@ -1390,8 +1401,8 @@ return orderedLoops; } - private Loop findOrCreateLoop(Map unorderedLoops, MergeNode loopHeader) { - assert methodScope.loopExplosionMerges.isMarkedAndGrow(loopHeader) : loopHeader; + private Loop findOrCreateLoop(EconomicMap unorderedLoops, MergeNode loopHeader) { + assert methodScope.loopExplosionMerges.contains(loopHeader) : loopHeader; Loop loop = unorderedLoops.get(loopHeader); if (loop == null) { loop = new Loop(); @@ -1409,7 +1420,7 @@ * subtract the loop nodes, to find the exits. */ - NodeBitMap possibleExits = methodScope.graph.createNodeBitMap(); + List possibleExits = new ArrayList<>(); NodeBitMap visited = methodScope.graph.createNodeBitMap(); Deque stack = new ArrayDeque<>(); for (EndNode loopEnd : loop.ends) { @@ -1448,7 +1459,7 @@ * have all exits of the inner loop. */ for (LoopExitNode exit : innerLoopBegin.loopExits()) { - possibleExits.mark(exit); + possibleExits.add(exit); } } @@ -1465,16 +1476,13 @@ * point we do not have the complete visited information, so we would * always mark too many possible exits. */ - possibleExits.mark(succ); + possibleExits.add(succ); } } } } } - /* All visited nodes are not exits of our loop. */ - possibleExits.subtract(visited); - /* * Now we know all the actual loop exits. Ideally, we would insert LoopExit nodes for them. * However, a LoopExit needs a valid FrameState that captures the state at the point where @@ -1492,9 +1500,11 @@ */ for (Node succ : possibleExits) { - stack.push(succ); - visited.mark(succ); - assert !methodScope.loopExplosionMerges.isMarkedAndGrow(succ); + if (!visited.contains(succ)) { + stack.push(succ); + visited.mark(succ); + assert !methodScope.loopExplosionMerges.contains(succ); + } } while (!stack.isEmpty()) { @@ -1506,7 +1516,7 @@ if (visited.isMarked(successor)) { /* Already processed this successor. */ - } else if (methodScope.loopExplosionMerges.isMarkedAndGrow(successor)) { + } else if (methodScope.loopExplosionMerges.contains(successor)) { /* * We have a FrameState for the successor. The LoopExit will be inserted between * the current node and the successor node. Since the successor node is a @@ -1577,7 +1587,7 @@ */ for (AbstractEndNode exit : loop.exits) { AbstractMergeNode loopExplosionMerge = exit.merge(); - assert methodScope.loopExplosionMerges.isMarkedAndGrow(loopExplosionMerge); + assert methodScope.loopExplosionMerges.contains(loopExplosionMerge); LoopExitNode loopExit = methodScope.graph.add(new LoopExitNode(loopBegin)); exit.replaceAtPredecessor(loopExit); @@ -1596,11 +1606,11 @@ FrameState oldState = loopExplosionMerge.stateAfter(); /* Collect all nodes that are in the FrameState at the LoopBegin. */ - NodeBitMap loopBeginValues = new NodeBitMap(methodScope.graph); + EconomicSet loopBeginValues = EconomicSet.create(Equivalence.IDENTITY); for (FrameState state = loopExit.loopBegin().stateAfter(); state != null; state = state.outerFrameState()) { for (ValueNode value : state.values()) { if (value != null && !value.isConstant() && !loopExit.loopBegin().isPhiAtMerge(value)) { - loopBeginValues.mark(ProxyPlaceholder.unwrap(value)); + loopBeginValues.add(ProxyPlaceholder.unwrap(value)); } } }