/** * Creates a graph for this stub. * * <p>If the stub returns an object, the graph created corresponds to this pseudo code: * * <pre> * Object foreignFunctionStub(args...) { * foreignFunction(currentThread, args); * if (clearPendingException(thread())) { * getAndClearObjectResult(thread()); * DeoptimizeCallerNode.deopt(InvalidateReprofile, RuntimeConstraint); * } * return verifyObject(getAndClearObjectResult(thread())); * } * </pre> * * If the stub returns a primitive or word, the graph created corresponds to this pseudo code * (using {@code int} as the primitive return type): * * <pre> * int foreignFunctionStub(args...) { * int result = foreignFunction(currentThread, args); * if (clearPendingException(thread())) { * DeoptimizeCallerNode.deopt(InvalidateReprofile, RuntimeConstraint); * } * return result; * } * </pre> * * If the stub is void, the graph created corresponds to this pseudo code: * * <pre> * void foreignFunctionStub(args...) { * foreignFunction(currentThread, args); * if (clearPendingException(thread())) { * DeoptimizeCallerNode.deopt(InvalidateReprofile, RuntimeConstraint); * } * } * </pre> * * In each example above, the {@code currentThread} argument is the C++ JavaThread value (i.e., * %r15 on AMD64) and is only prepended if {@link #prependThread} is true. */ @Override protected StructuredGraph getGraph() { WordTypes wordTypes = providers.getWordTypes(); Class<?>[] args = linkage.getDescriptor().getArgumentTypes(); boolean isObjectResult = !linkage.getOutgoingCallingConvention().getReturn().getLIRKind().isValue(); StructuredGraph graph = new StructuredGraph(toString(), null, AllowAssumptions.NO); graph.disableUnsafeAccessTracking(); GraphKit kit = new GraphKit(graph, providers, wordTypes, providers.getGraphBuilderPlugins()); ParameterNode[] params = createParameters(kit, args); ReadRegisterNode thread = kit.append( new ReadRegisterNode( providers.getRegisters().getThreadRegister(), wordTypes.getWordKind(), true, false)); ValueNode result = createTargetCall(kit, params, thread); kit.createInvoke( StubUtil.class, "handlePendingException", thread, ConstantNode.forBoolean(isObjectResult, graph)); if (isObjectResult) { InvokeNode object = kit.createInvoke(HotSpotReplacementsUtil.class, "getAndClearObjectResult", thread); result = kit.createInvoke(StubUtil.class, "verifyObject", object); } kit.append( new ReturnNode(linkage.getDescriptor().getResultType() == void.class ? null : result)); if (Debug.isDumpEnabled()) { Debug.dump(graph, "Initial stub graph"); } kit.inlineInvokes(); if (Debug.isDumpEnabled()) { Debug.dump(graph, "Stub graph before compilation"); } return graph; }