# HG changeset patch # User Doug Simon # Date 1368464490 -7200 # Node ID 37ec49e1d7e243c1af8a2e46f679cd5d8ad4bc66 # Parent 67804a97c1ce43c5c1b3fd901c4af28d50c04cab extended RuntimeCallStub to support calls returning an Object diff -r 67804a97c1ce -r 37ec49e1d7e2 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/RuntimeCallStub.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/RuntimeCallStub.java Mon May 13 19:00:24 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/RuntimeCallStub.java Mon May 13 19:01:30 2013 +0200 @@ -25,7 +25,7 @@ import static com.oracle.graal.api.meta.MetaUtil.*; import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; -import java.util.*; +import java.lang.reflect.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.code.CallingConvention.Type; @@ -37,6 +37,7 @@ import com.oracle.graal.hotspot.bridge.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hotspot.nodes.*; +import com.oracle.graal.hotspot.replacements.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind; @@ -149,96 +150,121 @@ }; } + static class GraphBuilder { + + public GraphBuilder(Stub stub) { + this.graph = new StructuredGraph(stub.toString(), null); + graph.replaceFixed(graph.start(), graph.add(new StubStartNode(stub))); + this.lastFixedNode = graph.start(); + } + + final StructuredGraph graph; + private FixedWithNextNode lastFixedNode; + + T add(T node) { + T result = graph.add(node); + assert node == result; + if (result instanceof FixedNode) { + assert lastFixedNode != null; + FixedNode fixed = (FixedNode) result; + assert fixed.predecessor() == null; + graph.addAfterFixed(lastFixedNode, fixed); + if (fixed instanceof FixedWithNextNode) { + lastFixedNode = (FixedWithNextNode) fixed; + } else { + lastFixedNode = null; + } + } + return result; + } + } + @Override protected StructuredGraph getGraph() { Class[] args = linkage.getDescriptor().getArgumentTypes(); - LocalNode[] locals = new LocalNode[args.length]; + boolean isObjectResult = linkage.getCallingConvention().getReturn().getKind() == Kind.Object; + + GraphBuilder builder = new GraphBuilder(this); + + LocalNode[] locals = createLocals(builder, args); + + ReadRegisterNode thread = prependThread || isObjectResult ? builder.add(new ReadRegisterNode(runtime.threadRegister(), true, false)) : null; + ValueNode result = createTargetCall(builder, locals, thread); + createInvoke(builder, StubUtil.class, "handlePendingException", ConstantNode.forBoolean(isObjectResult, builder.graph)); + if (isObjectResult) { + InvokeNode object = createInvoke(builder, HotSpotReplacementsUtil.class, "getAndClearObjectResult", thread); + result = createInvoke(builder, StubUtil.class, "verifyObject", object); + } + builder.add(new ReturnNode(linkage.descriptor.getResultType() == void.class ? null : result)); - StructuredGraph graph = new StructuredGraph(toString(), null); - StubStartNode start = graph.add(new StubStartNode(this)); - graph.replaceFixed(graph.start(), start); + if (Debug.isDumpEnabled()) { + Debug.dump(builder.graph, "Initial stub graph"); + } + + for (InvokeNode invoke : builder.graph.getNodes(InvokeNode.class).snapshot()) { + inline(invoke); + } + assert builder.graph.getNodes(InvokeNode.class).isEmpty(); + if (Debug.isDumpEnabled()) { + Debug.dump(builder.graph, "Stub graph before compilation"); + } + + return builder.graph; + } + + private LocalNode[] createLocals(GraphBuilder builder, Class[] args) { + LocalNode[] locals = new LocalNode[args.length]; ResolvedJavaType accessingClass = runtime.lookupJavaType(getClass()); for (int i = 0; i < args.length; i++) { - JavaType type = runtime.lookupJavaType(args[i]).resolve(accessingClass); + ResolvedJavaType type = runtime.lookupJavaType(args[i]).resolve(accessingClass); Kind kind = type.getKind().getStackKind(); Stamp stamp; if (kind == Kind.Object) { - stamp = StampFactory.declared((ResolvedJavaType) type); + stamp = StampFactory.declared(type); } else { stamp = StampFactory.forKind(kind); } - LocalNode local = graph.unique(new LocalNode(i, stamp)); + LocalNode local = builder.add(new LocalNode(i, stamp)); locals[i] = local; } - - // Create target call - CRuntimeCall call = createTargetCall(locals, graph, start); - - // Create call to handlePendingException - ResolvedJavaMethod hpeMethod = resolveMethod(StubUtil.class, "handlePendingException", boolean.class); - JavaType returnType = hpeMethod.getSignature().getReturnType(null); - ValueNode[] hpeArgs = {ConstantNode.forBoolean(linkage.getCallingConvention().getReturn().getKind() == Kind.Object, graph)}; - MethodCallTargetNode hpeTarget = graph.add(new MethodCallTargetNode(InvokeKind.Static, hpeMethod, hpeArgs, returnType)); - InvokeNode hpeInvoke = graph.add(new InvokeNode(hpeTarget, FrameState.UNKNOWN_BCI)); - List emptyStack = Collections.emptyList(); - hpeInvoke.setStateAfter(graph.add(new FrameState(null, FrameState.INVALID_FRAMESTATE_BCI, new ValueNode[0], emptyStack, new ValueNode[0], false, false))); - graph.addAfterFixed(call, hpeInvoke); - - // Create return node - ReturnNode ret = graph.add(new ReturnNode(linkage.descriptor.getResultType() == void.class ? null : call)); - graph.addAfterFixed(hpeInvoke, ret); - - if (Debug.isDumpEnabled()) { - Debug.dump(graph, "Initial stub graph"); - } - - // Inline call to handlePendingException - inline(hpeInvoke); - - if (Debug.isDumpEnabled()) { - Debug.dump(graph, "Stub graph before compilation"); - } - - return graph; + return locals; } - private CRuntimeCall createTargetCall(LocalNode[] locals, StructuredGraph graph, StubStartNode start) { - CRuntimeCall call; - ValueNode[] targetArguments; + private InvokeNode createInvoke(GraphBuilder builder, Class declaringClass, String name, ValueNode... hpeArgs) { + ResolvedJavaMethod method = null; + for (Method m : declaringClass.getDeclaredMethods()) { + if (Modifier.isStatic(m.getModifiers()) && m.getName().equals(name)) { + assert method == null : "found more than one method in " + declaringClass + " named " + name; + method = runtime.lookupJavaMethod(m); + } + } + assert method != null : "did not find method in " + declaringClass + " named " + name; + JavaType returnType = method.getSignature().getReturnType(null); + MethodCallTargetNode callTarget = builder.add(new MethodCallTargetNode(InvokeKind.Static, method, hpeArgs, returnType)); + InvokeNode invoke = builder.add(new InvokeNode(callTarget, FrameState.UNKNOWN_BCI)); + return invoke; + } + + private CRuntimeCall createTargetCall(GraphBuilder builder, LocalNode[] locals, ReadRegisterNode thread) { if (prependThread) { - ReadRegisterNode thread = graph.add(new ReadRegisterNode(runtime.threadRegister(), true, false)); - graph.addAfterFixed(start, thread); - targetArguments = new ValueNode[1 + locals.length]; + ValueNode[] targetArguments = new ValueNode[1 + locals.length]; targetArguments[0] = thread; System.arraycopy(locals, 0, targetArguments, 1, locals.length); - call = graph.add(new CRuntimeCall(target.descriptor, targetArguments)); - graph.addAfterFixed(thread, call); + return builder.add(new CRuntimeCall(target.descriptor, targetArguments)); } else { - targetArguments = new ValueNode[locals.length]; - System.arraycopy(locals, 0, targetArguments, 0, locals.length); - call = graph.add(new CRuntimeCall(target.descriptor, targetArguments)); - graph.addAfterFixed(start, call); + return builder.add(new CRuntimeCall(target.descriptor, locals)); } - return call; } private void inline(InvokeNode invoke) { StructuredGraph graph = invoke.graph(); ResolvedJavaMethod method = ((MethodCallTargetNode) invoke.callTarget()).targetMethod(); ReplacementsImpl repl = new ReplacementsImpl(runtime, new Assumptions(false), runtime.getTarget()); - StructuredGraph hpeGraph = repl.makeGraph(method, null, null); - InliningUtil.inline(invoke, hpeGraph, false); + StructuredGraph calleeGraph = repl.makeGraph(method, null, null); + InliningUtil.inline(invoke, calleeGraph, false); new NodeIntrinsificationPhase(runtime).apply(graph); new WordTypeRewriterPhase(runtime, wordKind()).apply(graph); new DeadCodeEliminationPhase().apply(graph); } - - private ResolvedJavaMethod resolveMethod(Class declaringClass, String name, Class... parameterTypes) { - try { - return runtime.lookupJavaMethod(declaringClass.getDeclaredMethod(name, parameterTypes)); - } catch (Exception e) { - throw new GraalInternalError(e); - } - } }