use of org.graalvm.compiler.nodes.AbstractMergeNode in project graal by oracle.
the class UseTrappingNullChecksPhase method tryUseTrappingNullCheck.
private static void tryUseTrappingNullCheck(MetaAccessProvider metaAccessProvider, DynamicDeoptimizeNode deopt, long implicitNullCheckLimit) {
Node predecessor = deopt.predecessor();
if (predecessor instanceof AbstractMergeNode) {
AbstractMergeNode merge = (AbstractMergeNode) predecessor;
// Process each predecessor at the merge, unpacking the reasons and speculations as
// needed.
ValueNode reason = deopt.getActionAndReason();
ValuePhiNode reasonPhi = null;
List<ValueNode> reasons = null;
int expectedPhis = 0;
if (reason instanceof ValuePhiNode) {
reasonPhi = (ValuePhiNode) reason;
if (reasonPhi.merge() != merge) {
return;
}
reasons = reasonPhi.values().snapshot();
expectedPhis++;
} else if (!reason.isConstant()) {
return;
}
ValueNode speculation = deopt.getSpeculation();
ValuePhiNode speculationPhi = null;
List<ValueNode> speculations = null;
if (speculation instanceof ValuePhiNode) {
speculationPhi = (ValuePhiNode) speculation;
if (speculationPhi.merge() != merge) {
return;
}
speculations = speculationPhi.values().snapshot();
expectedPhis++;
}
if (merge.phis().count() != expectedPhis) {
return;
}
int index = 0;
for (AbstractEndNode end : merge.cfgPredecessors().snapshot()) {
ValueNode thisReason = reasons != null ? reasons.get(index) : reason;
ValueNode thisSpeculation = speculations != null ? speculations.get(index++) : speculation;
if (!thisReason.isConstant() || !thisSpeculation.isConstant() || !thisSpeculation.asConstant().equals(JavaConstant.NULL_POINTER)) {
continue;
}
DeoptimizationReason deoptimizationReason = metaAccessProvider.decodeDeoptReason(thisReason.asJavaConstant());
tryUseTrappingNullCheck(deopt, end.predecessor(), deoptimizationReason, null, implicitNullCheckLimit);
}
}
}
use of org.graalvm.compiler.nodes.AbstractMergeNode in project graal by oracle.
the class InliningUtil method handleMissingAfterExceptionFrameState.
public static FrameState handleMissingAfterExceptionFrameState(FrameState nonReplaceableFrameState, Invoke invoke, EconomicMap<Node, Node> replacements, boolean alwaysDuplicateStateAfter) {
StructuredGraph graph = nonReplaceableFrameState.graph();
NodeWorkList workList = graph.createNodeWorkList();
workList.add(nonReplaceableFrameState);
for (Node node : workList) {
FrameState fs = (FrameState) node;
for (Node usage : fs.usages().snapshot()) {
if (!usage.isAlive()) {
continue;
}
if (usage instanceof FrameState) {
workList.add(usage);
} else {
StateSplit stateSplit = (StateSplit) usage;
FixedNode fixedStateSplit = stateSplit.asNode();
if (fixedStateSplit instanceof AbstractMergeNode) {
AbstractMergeNode merge = (AbstractMergeNode) fixedStateSplit;
while (merge.isAlive()) {
AbstractEndNode end = merge.forwardEnds().first();
DeoptimizeNode deoptimizeNode = addDeoptimizeNode(graph, DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.NotCompiledExceptionHandler);
end.replaceAtPredecessor(deoptimizeNode);
GraphUtil.killCFG(end);
}
} else if (fixedStateSplit instanceof ExceptionObjectNode) {
// The target invoke does not have an exception edge. This means that the
// bytecode parser made the wrong assumption of making an
// InvokeWithExceptionNode for the partial intrinsic exit. We therefore
// replace the InvokeWithExceptionNode with a normal
// InvokeNode -- the deoptimization occurs when the invoke throws.
InvokeWithExceptionNode oldInvoke = (InvokeWithExceptionNode) fixedStateSplit.predecessor();
FrameState oldFrameState = oldInvoke.stateAfter();
InvokeNode newInvoke = oldInvoke.replaceWithInvoke();
newInvoke.setStateAfter(oldFrameState.duplicate());
if (replacements != null) {
replacements.put(oldInvoke, newInvoke);
}
handleAfterBciFrameState(newInvoke.stateAfter(), invoke, alwaysDuplicateStateAfter);
} else {
FixedNode deoptimizeNode = addDeoptimizeNode(graph, DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.NotCompiledExceptionHandler);
if (fixedStateSplit instanceof AbstractBeginNode) {
deoptimizeNode = BeginNode.begin(deoptimizeNode);
}
fixedStateSplit.replaceAtPredecessor(deoptimizeNode);
GraphUtil.killCFG(fixedStateSplit);
}
}
}
}
return nonReplaceableFrameState;
}
use of org.graalvm.compiler.nodes.AbstractMergeNode in project graal by oracle.
the class ComputeInliningRelevance method createLoopScope.
/**
* Determines the parent of the given loop and creates a {@link Scope} object for each one. This
* method will call itself recursively if no {@link Scope} for the parent loop exists.
*/
private Scope createLoopScope(LoopBeginNode loopBegin, EconomicMap<LoopBeginNode, Scope> loops, Scope topScope) {
Scope scope = loops.get(loopBegin);
if (scope == null) {
final Scope parent;
// look for the parent scope
FixedNode current = loopBegin.forwardEnd();
while (true) {
if (current.predecessor() == null) {
if (current instanceof LoopBeginNode) {
// if we reach a LoopBeginNode then we're within this loop
parent = createLoopScope((LoopBeginNode) current, loops, topScope);
break;
} else if (current instanceof StartNode) {
// we're within the outermost scope
parent = topScope;
break;
} else {
assert current instanceof MergeNode : current;
// follow any path upwards - it doesn't matter which one
current = ((AbstractMergeNode) current).forwardEndAt(0);
}
} else if (current instanceof LoopExitNode) {
// if we reach a loop exit then we follow this loop and have the same parent
parent = createLoopScope(((LoopExitNode) current).loopBegin(), loops, topScope).parent;
break;
} else {
current = (FixedNode) current.predecessor();
}
}
scope = new Scope(loopBegin, parent);
loops.put(loopBegin, scope);
}
return scope;
}
use of org.graalvm.compiler.nodes.AbstractMergeNode in project graal by oracle.
the class InliningIterator method queueMerge.
private void queueMerge(AbstractEndNode end) {
AbstractMergeNode merge = end.merge();
if (!queuedNodes.isMarked(merge) && visitedAllEnds(merge)) {
queuedNodes.mark(merge);
nodeQueue.add(merge);
}
}
use of org.graalvm.compiler.nodes.AbstractMergeNode in project graal by oracle.
the class InliningIterator method apply.
public LinkedList<Invoke> apply() {
LinkedList<Invoke> invokes = new LinkedList<>();
FixedNode current;
forcedQueue(start);
while ((current = nextQueuedNode()) != null) {
assert current.isAlive();
if (current instanceof Invoke && ((Invoke) current).callTarget() instanceof MethodCallTargetNode) {
if (current != start) {
invokes.addLast((Invoke) current);
}
queueSuccessors(current);
} else if (current instanceof LoopBeginNode) {
queueSuccessors(current);
} else if (current instanceof LoopEndNode) {
// nothing to do
} else if (current instanceof AbstractMergeNode) {
queueSuccessors(current);
} else if (current instanceof FixedWithNextNode) {
queueSuccessors(current);
} else if (current instanceof EndNode) {
queueMerge((EndNode) current);
} else if (current instanceof ControlSinkNode) {
// nothing to do
} else if (current instanceof ControlSplitNode) {
queueSuccessors(current);
} else {
assert false : current;
}
}
assert invokes.size() == count(start.graph().getInvokes());
return invokes;
}
Aggregations