src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/GraphDecoder.java
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File hotspot Cdiff src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/GraphDecoder.java

src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/GraphDecoder.java

Print this page

        

*** 29,46 **** import java.util.ArrayDeque; import java.util.ArrayList; 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.Fields; import org.graalvm.compiler.core.common.util.TypeReader; import org.graalvm.compiler.core.common.util.UnsafeArrayTypeReader; import org.graalvm.compiler.debug.Debug; import org.graalvm.compiler.debug.GraalError; --- 29,45 ---- import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Arrays; import java.util.BitSet; import java.util.Deque; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.SortedMap; import java.util.TreeMap; ! 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; import org.graalvm.compiler.debug.Debug; import org.graalvm.compiler.debug.GraalError;
*** 60,69 **** --- 59,71 ---- import org.graalvm.compiler.nodes.GraphDecoder.MethodScope; import org.graalvm.compiler.nodes.GraphDecoder.ProxyPlaceholder; 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; import jdk.vm.ci.meta.DeoptimizationReason; import jdk.vm.ci.meta.JavaConstant;
*** 104,114 **** public final List<ReturnNode> returnNodes; /** The exception unwind node encountered during decoding, or null. */ public final List<UnwindNode> unwindNodes; /** All merges created during loop explosion. */ ! public final NodeBitMap 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}. */ public MergeNode loopExplosionHead; --- 106,116 ---- public final List<ReturnNode> returnNodes; /** The exception unwind node encountered during decoding, or null. */ public final List<UnwindNode> unwindNodes; /** All merges created during loop explosion. */ ! public final EconomicSet<Node> 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}. */ public MergeNode loopExplosionHead;
*** 117,146 **** this.callerLoopScope = callerLoopScope; this.graph = graph; this.methodStartMark = graph.getMark(); this.encodedGraph = encodedGraph; this.loopExplosion = loopExplosion; ! this.cleanupTasks = new ArrayList<>(); ! this.returnNodes = new ArrayList<>(); ! this.unwindNodes = new ArrayList<>(); 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]; for (int i = 0; i < nodeCount; i++) { ! nodeStartOffsets[i] = encodedGraph.getStartOffset() - reader.getUV(); } encodedGraph.nodeStartOffsets = nodeStartOffsets; } } else { reader = null; } if (loopExplosion != LoopExplosionKind.NONE) { ! loopExplosionMerges = new NodeBitMap(graph); } else { loopExplosionMerges = null; } } } --- 119,148 ---- this.callerLoopScope = callerLoopScope; this.graph = graph; this.methodStartMark = graph.getMark(); this.encodedGraph = encodedGraph; this.loopExplosion = loopExplosion; ! 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(); ! int[] nodeStartOffsets = new int[nodeCount]; for (int i = 0; i < nodeCount; i++) { ! nodeStartOffsets[i] = encodedGraph.getStartOffset() - reader.getUVInt(); } encodedGraph.nodeStartOffsets = nodeStartOffsets; } } else { reader = null; } if (loopExplosion != LoopExplosionKind.NONE) { ! loopExplosionMerges = EconomicSet.create(Equivalence.IDENTITY); } else { loopExplosionMerges = null; } } }
*** 159,169 **** /** * Information about already processed loop iterations for state merging during loop * explosion. Only used when {@link MethodScope#loopExplosion} is * {@link LoopExplosionKind#MERGE_EXPLODE}. */ ! public final Map<LoopExplosionState, LoopExplosionState> iterationStates; public final int loopBeginOrderId; /** * The worklist of fixed nodes to process. Since we already the correct processing order * from the orderId, we just set the orderId bit in the bitset when a node is ready for * processing. The lowest set bit is the next node to process. --- 161,171 ---- /** * Information about already processed loop iterations for state merging during loop * explosion. Only used when {@link MethodScope#loopExplosion} is * {@link LoopExplosionKind#MERGE_EXPLODE}. */ ! public final EconomicMap<LoopExplosionState, LoopExplosionState> iterationStates; public final int loopBeginOrderId; /** * The worklist of fixed nodes to process. Since we already the correct processing order * from the orderId, we just set the orderId bit in the bitset when a node is ready for * processing. The lowest set bit is the next node to process.
*** 191,201 **** this.initialCreatedNodes = new Node[nodeCount]; this.createdNodes = new Node[nodeCount]; } protected LoopScope(MethodScope methodScope, LoopScope outer, int loopDepth, int loopIteration, int loopBeginOrderId, Node[] initialCreatedNodes, Node[] createdNodes, ! Deque<LoopScope> nextIterations, Map<LoopExplosionState, LoopExplosionState> iterationStates) { this.methodScope = methodScope; this.outer = outer; this.loopDepth = loopDepth; this.loopIteration = loopIteration; this.nextIterations = nextIterations; --- 193,203 ---- this.initialCreatedNodes = new Node[nodeCount]; this.createdNodes = new Node[nodeCount]; } protected LoopScope(MethodScope methodScope, LoopScope outer, int loopDepth, int loopIteration, int loopBeginOrderId, Node[] initialCreatedNodes, Node[] createdNodes, ! Deque<LoopScope> nextIterations, EconomicMap<LoopExplosionState, LoopExplosionState> iterationStates) { this.methodScope = methodScope; this.outer = outer; this.loopDepth = loopDepth; this.loopIteration = loopIteration; this.nextIterations = nextIterations;
*** 379,389 **** return loopScope; } protected final void decode(LoopScope initialLoopScope) { LoopScope loopScope = initialLoopScope; ! /* Process inlined methods. */ while (loopScope != null) { MethodScope methodScope = loopScope.methodScope; /* Process loops of method. */ while (loopScope != null) { --- 381,391 ---- return loopScope; } protected final void decode(LoopScope initialLoopScope) { LoopScope loopScope = initialLoopScope; ! /* Process (inlined) methods. */ while (loopScope != null) { MethodScope methodScope = loopScope.methodScope; /* Process loops of method. */ while (loopScope != null) {
*** 493,504 **** methodScope.reader.setByteIndex(methodScope.encodedGraph.nodeStartOffsets[nodeOrderId]); 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); LoopScope resultScope = loopScope; if (node instanceof LoopBeginNode) { if (methodScope.loopExplosion != LoopExplosionKind.NONE) { handleLoopExplosionBegin(methodScope, loopScope, (LoopBeginNode) node); --- 495,506 ---- methodScope.reader.setByteIndex(methodScope.encodedGraph.nodeStartOffsets[nodeOrderId]); int typeId = methodScope.reader.getUVInt(); assert node.getNodeClass() == methodScope.encodedGraph.getNodeClasses()[typeId]; readProperties(methodScope, node); makeInputNodes(methodScope, loopScope, node, true); + makeSuccessorStubs(methodScope, successorAddScope, node, updatePredecessors); LoopScope resultScope = loopScope; if (node instanceof LoopBeginNode) { if (methodScope.loopExplosion != LoopExplosionKind.NONE) { handleLoopExplosionBegin(methodScope, loopScope, (LoopBeginNode) node);
*** 531,541 **** if (merge instanceof LoopBeginNode) { assert phiNodeScope == phiInputScope && phiNodeScope == loopScope; 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); phiInputScope = resultScope; phiNodeScope = resultScope; registerNode(loopScope, mergeOrderId, null, true, true); loopScope.nodesToProcess.clear(mergeOrderId); --- 533,543 ---- if (merge instanceof LoopBeginNode) { assert phiNodeScope == phiInputScope && phiNodeScope == loopScope; 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 ? EconomicMap.create(Equivalence.DEFAULT) : null); phiInputScope = resultScope; phiNodeScope = resultScope; registerNode(loopScope, mergeOrderId, null, true, true); loopScope.nodesToProcess.clear(mergeOrderId);
*** 590,599 **** --- 592,606 ---- * Without inlining, the original loop scope must be returned. */ 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 { ((InvokeNode) invokeData.invoke).setCallTarget(callTarget); }
*** 603,613 **** invokeData.invoke.setNext(makeStubNode(methodScope, loopScope, invokeData.nextOrderId)); if (invokeData.invoke instanceof InvokeWithExceptionNode) { ((InvokeWithExceptionNode) invokeData.invoke).setExceptionEdge((AbstractBeginNode) makeStubNode(methodScope, loopScope, invokeData.exceptionOrderId)); } - return loopScope; } /** * Hook for subclasses to perform simplifications for a non-loop-header control flow merge. * --- 610,619 ----
*** 635,645 **** return; } } MergeNode merge = methodScope.graph.add(new MergeNode()); ! methodScope.loopExplosionMerges.markAndGrow(merge); if (methodScope.loopExplosion == LoopExplosionKind.MERGE_EXPLODE) { if (loopScope.iterationStates.size() == 0 && loopScope.loopDepth == 1) { if (methodScope.loopExplosionHead != null) { throw new PermanentBailoutException("Graal implementation restriction: Method with %s loop explosion must not have more than one top-level loop", LoopExplosionKind.MERGE_EXPLODE); --- 641,651 ---- return; } } MergeNode merge = methodScope.graph.add(new MergeNode()); ! methodScope.loopExplosionMerges.add(merge); if (methodScope.loopExplosion == LoopExplosionKind.MERGE_EXPLODE) { if (loopScope.iterationStates.size() == 0 && loopScope.loopDepth == 1) { if (methodScope.loopExplosionHead != null) { throw new PermanentBailoutException("Graal implementation restriction: Method with %s loop explosion must not have more than one top-level loop", LoopExplosionKind.MERGE_EXPLODE);
*** 672,683 **** } 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 = newFrameState; } loopBegin.replaceAtUsagesAndDelete(merge); merge.setStateAfter(frameState); --- 678,688 ---- } 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.replaceAtUsagesAndDelete(newFrameState); frameState = newFrameState; } loopBegin.replaceAtUsagesAndDelete(merge); merge.setStateAfter(frameState);
*** 762,772 **** /* * This exit might end up as a loop exit of a loop detected after partial evaluation. We * 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); EndNode end = methodScope.graph.add(new EndNode()); begin.setNext(end); loopExitPlaceholder.addForwardEnd(end); --- 767,777 ---- /* * This exit might end up as a loop exit of a loop detected after partial evaluation. We * need to be able to create a FrameState and the necessary proxy nodes in this case. */ loopExitPlaceholder = methodScope.graph.add(new MergeNode()); ! methodScope.loopExplosionMerges.add(loopExitPlaceholder); EndNode end = methodScope.graph.add(new EndNode()); begin.setNext(end); loopExitPlaceholder.addForwardEnd(end);
*** 962,972 **** if (fields.getType(pos).isPrimitive()) { long primitive = methodScope.reader.getSV(); fields.setRawPrimitive(node, pos, primitive); } else { Object value = readObject(methodScope); ! fields.set(node, pos, value); } } } /** --- 967,977 ---- if (fields.getType(pos).isPrimitive()) { long primitive = methodScope.reader.getSV(); fields.setRawPrimitive(node, pos, primitive); } else { Object value = readObject(methodScope); ! fields.putObject(node, pos, value); } } } /**
*** 974,986 **** * non-fixed nodes (because fixed nodes are processed in reverse postorder. Such non-fixed nodes * are created on demand (recursively since they can themselves reference not yet created * nodes). */ protected void makeInputNodes(MethodScope methodScope, LoopScope loopScope, Node node, boolean updateUsages) { ! Edges edges = node.getNodeClass().getEdges(Edges.Type.Inputs); for (int index = 0; index < edges.getDirectCount(); index++) { ! if (skipEdge(node, edges, index, true, true)) { continue; } int orderId = readOrderId(methodScope); Node value = ensureNodeCreated(methodScope, loopScope, orderId); edges.initializeNode(node, index, value); --- 979,991 ---- * non-fixed nodes (because fixed nodes are processed in reverse postorder. Such non-fixed nodes * are created on demand (recursively since they can themselves reference not yet created * nodes). */ protected void makeInputNodes(MethodScope methodScope, LoopScope loopScope, Node node, boolean updateUsages) { ! Edges edges = node.getNodeClass().getInputEdges(); for (int index = 0; index < edges.getDirectCount(); index++) { ! if (skipDirectEdge(node, edges, index)) { continue; } int orderId = readOrderId(methodScope); Node value = ensureNodeCreated(methodScope, loopScope, orderId); edges.initializeNode(node, index, value);
*** 988,998 **** edges.update(node, null, value); } } for (int index = edges.getDirectCount(); index < edges.getCount(); index++) { ! if (skipEdge(node, edges, index, false, true)) { continue; } int size = methodScope.reader.getSVInt(); if (size != -1) { NodeList<Node> nodeList = new NodeInputList<>(node, size); --- 993,1003 ---- edges.update(node, null, value); } } for (int index = edges.getDirectCount(); index < edges.getCount(); index++) { ! if (skipIndirectEdge(node, edges, index, true)) { continue; } int size = methodScope.reader.getSVInt(); if (size != -1) { NodeList<Node> nodeList = new NodeInputList<>(node, size);
*** 1101,1124 **** * Process successor edges of a node. We create the successor nodes so that we can fill the * successor list, but no properties or edges are loaded yet. That is done when the successor is * 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); for (int index = 0; index < edges.getDirectCount(); index++) { ! if (skipEdge(node, edges, index, true, true)) { continue; } int orderId = readOrderId(methodScope); Node value = makeStubNode(methodScope, loopScope, orderId); edges.initializeNode(node, index, value); if (updatePredecessors && value != null) { edges.update(node, null, value); } } for (int index = edges.getDirectCount(); index < edges.getCount(); index++) { ! if (skipEdge(node, edges, index, false, true)) { continue; } int size = methodScope.reader.getSVInt(); if (size != -1) { NodeList<Node> nodeList = new NodeSuccessorList<>(node, size); --- 1106,1129 ---- * Process successor edges of a node. We create the successor nodes so that we can fill the * successor list, but no properties or edges are loaded yet. That is done when the successor is * on top of the worklist in {@link #processNextNode}. */ protected void makeSuccessorStubs(MethodScope methodScope, LoopScope loopScope, Node node, boolean updatePredecessors) { ! Edges edges = node.getNodeClass().getSuccessorEdges(); for (int index = 0; index < edges.getDirectCount(); index++) { ! if (skipDirectEdge(node, edges, index)) { continue; } int orderId = readOrderId(methodScope); Node value = makeStubNode(methodScope, loopScope, orderId); edges.initializeNode(node, index, value); if (updatePredecessors && value != null) { edges.update(node, null, value); } } for (int index = edges.getDirectCount(); index < edges.getCount(); index++) { ! if (skipIndirectEdge(node, edges, index, true)) { continue; } int size = methodScope.reader.getSVInt(); if (size != -1) { NodeList<Node> nodeList = new NodeSuccessorList<>(node, size);
*** 1152,1193 **** registerNode(loopScope, nodeOrderId, node, false, false); loopScope.nodesToProcess.set(nodeOrderId); 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) { 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; } else { assert edges.type() == Edges.Type.Inputs; --- 1157,1169 ---- registerNode(loopScope, nodeOrderId, node, false, false); loopScope.nodesToProcess.set(nodeOrderId); return node; } ! 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(); 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; } else { assert edges.type() == Edges.Type.Inputs;
*** 1196,1205 **** --- 1172,1214 ---- } else if (edges.getType(index) == FrameState.class) { assert edges.get(node, index) == null || edges.get(node, index) == ((Invoke) node).stateAfter() : "Only stateAfter can be a FrameState during encoding"; 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; } protected Node lookupNode(LoopScope loopScope, int nodeOrderId) {
*** 1325,1335 **** Debug.dump(Debug.VERBOSE_LOG_LEVEL, methodScope.graph, "After loop detection"); } private List<Loop> findLoops() { /* Mapping from the loop header node to additional loop information. */ ! Map<MergeNode, Loop> unorderedLoops = new HashMap<>(); /* Loops in reverse order of, i.e., inner loops before outer loops. */ List<Loop> orderedLoops = new ArrayList<>(); /* * Ensure we have an outermost loop that we can use to eliminate irreducible loops. This --- 1334,1344 ---- Debug.dump(Debug.VERBOSE_LOG_LEVEL, methodScope.graph, "After loop detection"); } private List<Loop> findLoops() { /* Mapping from the loop header node to additional loop information. */ ! EconomicMap<MergeNode, Loop> unorderedLoops = EconomicMap.create(Equivalence.IDENTITY); /* Loops in reverse order of, i.e., inner loops before outer loops. */ List<Loop> orderedLoops = new ArrayList<>(); /* * Ensure we have an outermost loop that we can use to eliminate irreducible loops. This
*** 1350,1368 **** if (active.isMarked(current)) { /* We are back-tracking, i.e., all successor nodes have been processed. */ 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); } } else { /* * Process the node. Note that we do not remove the node from the stack, i.e., we * will peek it again. But the next time the node is marked as active, so we do not --- 1359,1379 ---- if (active.isMarked(current)) { /* We are back-tracking, i.e., all successor nodes have been processed. */ stack.pop(); active.clear(current); ! 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 { /* * Process the node. Note that we do not remove the node from the stack, i.e., we * will peek it again. But the next time the node is marked as active, so we do not
*** 1388,1399 **** } } return orderedLoops; } ! private Loop findOrCreateLoop(Map<MergeNode, Loop> unorderedLoops, MergeNode loopHeader) { ! assert methodScope.loopExplosionMerges.isMarkedAndGrow(loopHeader) : loopHeader; Loop loop = unorderedLoops.get(loopHeader); if (loop == null) { loop = new Loop(); loop.header = loopHeader; unorderedLoops.put(loopHeader, loop); --- 1399,1410 ---- } } return orderedLoops; } ! private Loop findOrCreateLoop(EconomicMap<MergeNode, Loop> unorderedLoops, MergeNode loopHeader) { ! assert methodScope.loopExplosionMerges.contains(loopHeader) : loopHeader; Loop loop = unorderedLoops.get(loopHeader); if (loop == null) { loop = new Loop(); loop.header = loopHeader; unorderedLoops.put(loopHeader, loop);
*** 1407,1417 **** * are reachable until we hit the loop begin. All successors of loop nodes that are not * marked as loop nodes themselves are exits of the loop. We mark all successors, and then * subtract the loop nodes, to find the exits. */ ! NodeBitMap possibleExits = methodScope.graph.createNodeBitMap(); NodeBitMap visited = methodScope.graph.createNodeBitMap(); Deque<Node> stack = new ArrayDeque<>(); for (EndNode loopEnd : loop.ends) { stack.push(loopEnd); visited.mark(loopEnd); --- 1418,1428 ---- * are reachable until we hit the loop begin. All successors of loop nodes that are not * marked as loop nodes themselves are exits of the loop. We mark all successors, and then * subtract the loop nodes, to find the exits. */ ! List<Node> possibleExits = new ArrayList<>(); NodeBitMap visited = methodScope.graph.createNodeBitMap(); Deque<Node> stack = new ArrayDeque<>(); for (EndNode loopEnd : loop.ends) { stack.push(loopEnd); visited.mark(loopEnd);
*** 1446,1456 **** * All loop exits of the inner loop possibly need a LoopExit of our loop. * Because we are processing inner loops first, we are guaranteed to already * have all exits of the inner loop. */ for (LoopExitNode exit : innerLoopBegin.loopExits()) { ! possibleExits.mark(exit); } } } else if (!visited.isMarked(predecessor)) { stack.push(predecessor); --- 1457,1467 ---- * All loop exits of the inner loop possibly need a LoopExit of our loop. * Because we are processing inner loops first, we are guaranteed to already * have all exits of the inner loop. */ for (LoopExitNode exit : innerLoopBegin.loopExits()) { ! possibleExits.add(exit); } } } else if (!visited.isMarked(predecessor)) { stack.push(predecessor);
*** 1463,1482 **** * mark visited nodes. But it is easier to just mark everything, since * we subtract all visited nodes in the end anyway. Note that at this * point we do not have the complete visited information, so we would * always mark too many possible exits. */ ! possibleExits.mark(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 * we exit the loop. During graph decoding, we create a FrameState for every exploded loop * iteration. We need to do a forward marking until we hit the next such point. This puts --- 1474,1490 ---- * mark visited nodes. But it is easier to just mark everything, since * we subtract all visited nodes in the end anyway. Note that at this * point we do not have the complete visited information, so we would * always mark too many possible exits. */ ! possibleExits.add(succ); } } } } } /* * 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 * we exit the loop. During graph decoding, we create a FrameState for every exploded loop * iteration. We need to do a forward marking until we hit the next such point. This puts
*** 1490,1502 **** * necessary into a loop because it computes loop information based on bytecodes, before the * actual parsing. */ for (Node succ : possibleExits) { stack.push(succ); visited.mark(succ); ! assert !methodScope.loopExplosionMerges.isMarkedAndGrow(succ); } while (!stack.isEmpty()) { Node current = stack.pop(); assert visited.isMarked(current); --- 1498,1512 ---- * necessary into a loop because it computes loop information based on bytecodes, before the * actual parsing. */ for (Node succ : possibleExits) { + if (!visited.contains(succ)) { stack.push(succ); visited.mark(succ); ! assert !methodScope.loopExplosionMerges.contains(succ); ! } } while (!stack.isEmpty()) { Node current = stack.pop(); assert visited.isMarked(current);
*** 1504,1514 **** for (Node successor : current.cfgSuccessors()) { if (visited.isMarked(successor)) { /* Already processed this successor. */ ! } else if (methodScope.loopExplosionMerges.isMarkedAndGrow(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 * MergeNode, the current node mus be a AbstractEndNode with only that MergeNode * as the successor. --- 1514,1524 ---- for (Node successor : current.cfgSuccessors()) { if (visited.isMarked(successor)) { /* Already processed this 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 * MergeNode, the current node mus be a AbstractEndNode with only that MergeNode * as the successor.
*** 1575,1585 **** * Insert the LoopExit nodes (the easy part) and compute the FrameState for the new exits * (the difficult part). */ for (AbstractEndNode exit : loop.exits) { AbstractMergeNode loopExplosionMerge = exit.merge(); ! assert methodScope.loopExplosionMerges.isMarkedAndGrow(loopExplosionMerge); LoopExitNode loopExit = methodScope.graph.add(new LoopExitNode(loopBegin)); exit.replaceAtPredecessor(loopExit); loopExit.setNext(exit); assignLoopExitState(loopExit, loopExplosionMerge, exit); --- 1585,1595 ---- * Insert the LoopExit nodes (the easy part) and compute the FrameState for the new exits * (the difficult part). */ for (AbstractEndNode exit : loop.exits) { AbstractMergeNode loopExplosionMerge = exit.merge(); ! assert methodScope.loopExplosionMerges.contains(loopExplosionMerge); LoopExitNode loopExit = methodScope.graph.add(new LoopExitNode(loopBegin)); exit.replaceAtPredecessor(loopExit); loopExit.setNext(exit); assignLoopExitState(loopExit, loopExplosionMerge, exit);
*** 1594,1608 **** */ private void assignLoopExitState(LoopExitNode loopExit, AbstractMergeNode loopExplosionMerge, AbstractEndNode loopExplosionEnd) { FrameState oldState = loopExplosionMerge.stateAfter(); /* Collect all nodes that are in the FrameState at the LoopBegin. */ ! NodeBitMap loopBeginValues = new NodeBitMap(methodScope.graph); 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)); } } } List<ValueNode> newValues = new ArrayList<>(oldState.values().size()); --- 1604,1618 ---- */ private void assignLoopExitState(LoopExitNode loopExit, AbstractMergeNode loopExplosionMerge, AbstractEndNode loopExplosionEnd) { FrameState oldState = loopExplosionMerge.stateAfter(); /* Collect all nodes that are in the FrameState at the LoopBegin. */ ! EconomicSet<Node> 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.add(ProxyPlaceholder.unwrap(value)); } } } List<ValueNode> newValues = new ArrayList<>(oldState.values().size());
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/GraphDecoder.java
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File