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