changeset 9673:37ec49e1d7e2

extended RuntimeCallStub to support calls returning an Object
author Doug Simon <doug.simon@oracle.com>
date Mon, 13 May 2013 19:01:30 +0200
parents 67804a97c1ce
children e897b58936aa
files graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/RuntimeCallStub.java
diffstat 1 files changed, 87 insertions(+), 61 deletions(-) [+]
line wrap: on
line diff
--- 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 extends Node> 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<ValueNode> 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);
-        }
-    }
 }