use of org.graalvm.compiler.nodes.Invoke in project graal by oracle.
the class LoopSafepointEliminationPhase method run.
@Override
protected void run(StructuredGraph graph, MidTierContext context) {
LoopsData loops = new LoopsData(graph);
if (context.getOptimisticOptimizations().useLoopLimitChecks(graph.getOptions()) && graph.getGuardsStage().allowsFloatingGuards()) {
loops.detectedCountedLoops();
for (LoopEx loop : loops.countedLoops()) {
if (loop.loop().getChildren().isEmpty() && loop.counted().getStamp().getBits() <= 32) {
boolean hasSafepoint = false;
for (LoopEndNode loopEnd : loop.loopBegin().loopEnds()) {
hasSafepoint |= loopEnd.canSafepoint();
}
if (hasSafepoint) {
loop.counted().createOverFlowGuard();
loop.loopBegin().disableSafepoint();
}
}
}
}
for (LoopEx loop : loops.loops()) {
for (LoopEndNode loopEnd : loop.loopBegin().loopEnds()) {
Block b = loops.getCFG().blockFor(loopEnd);
blocks: while (b != loop.loop().getHeader()) {
assert b != null;
for (FixedNode node : b.getNodes()) {
if (node instanceof Invoke || (node instanceof ForeignCallNode && ((ForeignCallNode) node).isGuaranteedSafepoint())) {
loopEnd.disableSafepoint();
break blocks;
}
}
b = b.getDominator();
}
}
}
loops.deleteUnusedNodes();
}
use of org.graalvm.compiler.nodes.Invoke in project graal by oracle.
the class MethodSubstitutionTest method testGraph.
@SuppressWarnings("try")
protected StructuredGraph testGraph(final String snippet, String name) {
DebugContext debug = getDebugContext();
try (DebugContext.Scope s = debug.scope("MethodSubstitutionTest", getResolvedJavaMethod(snippet))) {
StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES, debug);
HighTierContext context = getDefaultHighTierContext();
debug.dump(DebugContext.BASIC_LEVEL, graph, "Graph");
new InliningPhase(new CanonicalizerPhase()).apply(graph, context);
debug.dump(DebugContext.BASIC_LEVEL, graph, "Graph");
new CanonicalizerPhase().apply(graph, context);
new DeadCodeEliminationPhase().apply(graph);
// Try to ensure any macro nodes are lowered to expose any resulting invokes
if (graph.getNodes().filter(MacroNode.class).isNotEmpty()) {
new LoweringPhase(new CanonicalizerPhase(), LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context);
}
if (graph.getNodes().filter(MacroNode.class).isNotEmpty()) {
new LoweringPhase(new CanonicalizerPhase(), LoweringTool.StandardLoweringStage.MID_TIER).apply(graph, context);
}
assertNotInGraph(graph, MacroNode.class);
if (name != null) {
for (Node node : graph.getNodes()) {
if (node instanceof Invoke) {
Invoke invoke = (Invoke) node;
if (invoke.callTarget() instanceof MethodCallTargetNode) {
MethodCallTargetNode call = (MethodCallTargetNode) invoke.callTarget();
assertTrue(!call.targetMethod().getName().equals(name), "Unexpected invoke of intrinsic %s", call.targetMethod());
}
}
}
} else {
assertNotInGraph(graph, Invoke.class);
}
return graph;
} catch (Throwable e) {
throw debug.handle(e);
}
}
use of org.graalvm.compiler.nodes.Invoke in project graal by oracle.
the class VerifyUsageWithEquals method isAssignableToRestrictedType.
/**
* Determines whether the type of {@code node} is assignable to the {@link #restrictedClass}.
*/
private boolean isAssignableToRestrictedType(ValueNode node, MetaAccessProvider metaAccess) {
if (node.stamp(NodeView.DEFAULT) instanceof ObjectStamp) {
ResolvedJavaType restrictedType = metaAccess.lookupJavaType(restrictedClass);
ResolvedJavaType nodeType = StampTool.typeOrNull(node);
if (nodeType == null && node instanceof LoadFieldNode) {
nodeType = (ResolvedJavaType) ((LoadFieldNode) node).field().getType();
}
if (nodeType == null && node instanceof Invoke) {
ResolvedJavaMethod target = ((Invoke) node).callTarget().targetMethod();
nodeType = (ResolvedJavaType) target.getSignature().getReturnType(target.getDeclaringClass());
}
if (nodeType == null && node instanceof UncheckedInterfaceProvider) {
nodeType = StampTool.typeOrNull(((UncheckedInterfaceProvider) node).uncheckedStamp());
}
if (nodeType != null && restrictedType.isAssignableFrom(nodeType)) {
return true;
}
}
return false;
}
use of org.graalvm.compiler.nodes.Invoke in project graal by oracle.
the class InliningUtil method inline.
/**
* Performs an actual inlining, thereby replacing the given invoke with the given
* {@code inlineGraph}.
*
* @param invoke the invoke that will be replaced
* @param inlineGraph the graph that the invoke will be replaced with
* @param receiverNullCheck true if a null check needs to be generated for non-static inlinings,
* false if no such check is required
* @param inlineeMethod the actual method being inlined. Maybe be null for snippets.
* @param reason the reason for inlining, used in tracing
* @param phase the phase that invoked inlining
*/
@SuppressWarnings("try")
public static UnmodifiableEconomicMap<Node, Node> inline(Invoke invoke, StructuredGraph inlineGraph, boolean receiverNullCheck, ResolvedJavaMethod inlineeMethod, String reason, String phase) {
FixedNode invokeNode = invoke.asNode();
StructuredGraph graph = invokeNode.graph();
final NodeInputList<ValueNode> parameters = invoke.callTarget().arguments();
assert inlineGraph.getGuardsStage().ordinal() >= graph.getGuardsStage().ordinal();
assert !invokeNode.graph().isAfterFloatingReadPhase() : "inline isn't handled correctly after floating reads phase";
if (receiverNullCheck && !((MethodCallTargetNode) invoke.callTarget()).isStatic()) {
nonNullReceiver(invoke);
}
ArrayList<Node> nodes = new ArrayList<>(inlineGraph.getNodes().count());
ArrayList<ReturnNode> returnNodes = new ArrayList<>(4);
ArrayList<Invoke> partialIntrinsicExits = new ArrayList<>();
UnwindNode unwindNode = null;
final StartNode entryPointNode = inlineGraph.start();
FixedNode firstCFGNode = entryPointNode.next();
if (firstCFGNode == null) {
throw new IllegalStateException("Inlined graph is in invalid state: " + inlineGraph);
}
for (Node node : inlineGraph.getNodes()) {
if (node == entryPointNode || (node == entryPointNode.stateAfter() && node.usages().count() == 1) || node instanceof ParameterNode) {
// Do nothing.
} else {
nodes.add(node);
if (node instanceof ReturnNode) {
returnNodes.add((ReturnNode) node);
} else if (node instanceof Invoke) {
Invoke invokeInInlineGraph = (Invoke) node;
if (invokeInInlineGraph.bci() == BytecodeFrame.UNKNOWN_BCI) {
ResolvedJavaMethod target1 = inlineeMethod;
ResolvedJavaMethod target2 = invokeInInlineGraph.callTarget().targetMethod();
assert target1.equals(target2) : String.format("invoke in inlined method expected to be partial intrinsic exit (i.e., call to %s), not a call to %s", target1.format("%H.%n(%p)"), target2.format("%H.%n(%p)"));
partialIntrinsicExits.add(invokeInInlineGraph);
}
} else if (node instanceof UnwindNode) {
assert unwindNode == null;
unwindNode = (UnwindNode) node;
}
}
}
final AbstractBeginNode prevBegin = AbstractBeginNode.prevBegin(invokeNode);
DuplicationReplacement localReplacement = new DuplicationReplacement() {
@Override
public Node replacement(Node node) {
if (node instanceof ParameterNode) {
return parameters.get(((ParameterNode) node).index());
} else if (node == entryPointNode) {
return prevBegin;
}
return node;
}
};
assert invokeNode.successors().first() != null : invoke;
assert invokeNode.predecessor() != null;
Mark mark = graph.getMark();
// Instead, attach the inlining log of the child graph to the current inlining log.
EconomicMap<Node, Node> duplicates;
try (InliningLog.UpdateScope scope = graph.getInliningLog().openDefaultUpdateScope()) {
duplicates = graph.addDuplicates(nodes, inlineGraph, inlineGraph.getNodeCount(), localReplacement);
if (scope != null) {
graph.getInliningLog().addDecision(invoke, true, reason, phase, duplicates, inlineGraph.getInliningLog());
}
}
FrameState stateAfter = invoke.stateAfter();
assert stateAfter == null || stateAfter.isAlive();
FrameState stateAtExceptionEdge = null;
if (invoke instanceof InvokeWithExceptionNode) {
InvokeWithExceptionNode invokeWithException = ((InvokeWithExceptionNode) invoke);
if (unwindNode != null) {
ExceptionObjectNode obj = (ExceptionObjectNode) invokeWithException.exceptionEdge();
stateAtExceptionEdge = obj.stateAfter();
}
}
updateSourcePositions(invoke, inlineGraph, duplicates, !Objects.equals(inlineGraph.method(), inlineeMethod), mark);
if (stateAfter != null) {
processFrameStates(invoke, inlineGraph, duplicates, stateAtExceptionEdge, returnNodes.size() > 1);
int callerLockDepth = stateAfter.nestedLockDepth();
if (callerLockDepth != 0) {
for (MonitorIdNode original : inlineGraph.getNodes(MonitorIdNode.TYPE)) {
MonitorIdNode monitor = (MonitorIdNode) duplicates.get(original);
processMonitorId(invoke.stateAfter(), monitor);
}
}
} else {
assert checkContainsOnlyInvalidOrAfterFrameState(duplicates);
}
firstCFGNode = (FixedNode) duplicates.get(firstCFGNode);
for (int i = 0; i < returnNodes.size(); i++) {
returnNodes.set(i, (ReturnNode) duplicates.get(returnNodes.get(i)));
}
for (Invoke exit : partialIntrinsicExits) {
// A partial intrinsic exit must be replaced with a call to
// the intrinsified method.
Invoke dup = (Invoke) duplicates.get(exit.asNode());
if (dup instanceof InvokeNode) {
InvokeNode repl = graph.add(new InvokeNode(invoke.callTarget(), invoke.bci()));
dup.intrinsify(repl.asNode());
} else {
((InvokeWithExceptionNode) dup).replaceWithNewBci(invoke.bci());
}
}
if (unwindNode != null) {
unwindNode = (UnwindNode) duplicates.get(unwindNode);
}
finishInlining(invoke, graph, firstCFGNode, returnNodes, unwindNode, inlineGraph.getAssumptions(), inlineGraph);
GraphUtil.killCFG(invokeNode);
return duplicates;
}
use of org.graalvm.compiler.nodes.Invoke 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