changeset 15088:d3add9b82b71

change to StackIntrospection and Truffle getStackTrace implementation
author Lukas Stadler <lukas.stadler@oracle.com>
date Mon, 14 Apr 2014 18:20:09 +0200
parents f3e74d317e83
children 448338c9ce96
files graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/stack/StackIntrospection.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotFrameInstance.java graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotTruffleRuntime.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameInstance.java graal/com.oracle.truffle.sl.test/tests/HelloEqualsWorld.sl graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLStackTraceBuiltin.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/call/SLGenericDispatchNode.java src/share/vm/graal/graalCompilerToVM.cpp
diffstat 12 files changed, 117 insertions(+), 51 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/stack/StackIntrospection.java	Mon Apr 14 15:38:19 2014 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/stack/StackIntrospection.java	Mon Apr 14 18:20:09 2014 +0200
@@ -30,10 +30,10 @@
      * Accesses the current stack, returning a collection of {@long InspectedFrame}s that can be
      * used to inspect the stack frames' contents.
      *
-     * @param initialMethod if this is non-{@code null}, then the stack trace will start at this
-     *            method
-     * @param matchingMethod if this is non-{@code null}, then only matching stack frames are
+     * @param initialMethods if this is non-{@code null}, then the stack trace will start at these
+     *            methods
+     * @param matchingMethods if this is non-{@code null}, then only matching stack frames are
      *            returned
      */
-    Iterable<InspectedFrame> getStackTrace(ResolvedJavaMethod initialMethod, ResolvedJavaMethod matchingMethod);
+    Iterable<InspectedFrame> getStackTrace(ResolvedJavaMethod[] initialMethods, ResolvedJavaMethod[] matchingMethods);
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java	Mon Apr 14 15:38:19 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java	Mon Apr 14 18:20:09 2014 +0200
@@ -445,10 +445,12 @@
         }
     }
 
-    public Iterable<InspectedFrame> getStackTrace(final ResolvedJavaMethod initialMethod, final ResolvedJavaMethod matchingMethod) {
+    public Iterable<InspectedFrame> getStackTrace(ResolvedJavaMethod[] initialMethods, ResolvedJavaMethod[] matchingMethods) {
+        final long[] initialMetaMethods = toMeta(initialMethods);
+        final long[] matchingMetaMethods = toMeta(matchingMethods);
         class StackFrameIterator implements Iterator<InspectedFrame> {
 
-            private HotSpotStackFrameReference current = compilerToVm.getNextStackFrame(null, (HotSpotResolvedJavaMethod) initialMethod);
+            private HotSpotStackFrameReference current = compilerToVm.getNextStackFrame(null, initialMetaMethods);
             // we don't want to read ahead if hasNext isn't called
             private boolean advanced = true;
 
@@ -465,7 +467,7 @@
 
             private void update() {
                 if (!advanced) {
-                    current = compilerToVm.getNextStackFrame(current, (HotSpotResolvedJavaMethod) matchingMethod);
+                    current = compilerToVm.getNextStackFrame(current, matchingMetaMethods);
                     advanced = true;
                 }
             }
@@ -476,4 +478,16 @@
             }
         };
     }
+
+    private static long[] toMeta(ResolvedJavaMethod[] methods) {
+        if (methods == null) {
+            return null;
+        } else {
+            long[] result = new long[methods.length];
+            for (int i = 0; i < result.length; i++) {
+                result[i] = ((HotSpotResolvedJavaMethod) methods[i]).getMetaspaceMethod();
+            }
+            return result;
+        }
+    }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java	Mon Apr 14 15:38:19 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java	Mon Apr 14 18:20:09 2014 +0200
@@ -339,10 +339,11 @@
      * Looks for the next Java stack frame with the given method.
      *
      * @param frame the starting point of the search, where {@code null} refers to the topmost frame
-     * @param method the method to look for, where {@code null} means that any frame is returned
+     * @param methods the metaspace methods to look for, where {@code null} means that any frame is
+     *            returned
      * @return the frame, or {@code null} if the end of the stack was reached during the search
      */
-    HotSpotStackFrameReference getNextStackFrame(HotSpotStackFrameReference frame, HotSpotResolvedJavaMethod method);
+    HotSpotStackFrameReference getNextStackFrame(HotSpotStackFrameReference frame, long[] methods);
 
     /**
      * Materialized all virtual objects within the given stack frame and update the locals within
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java	Mon Apr 14 15:38:19 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java	Mon Apr 14 18:20:09 2014 +0200
@@ -179,7 +179,7 @@
 
     public native boolean hasCompiledCodeForOSR(long metaspaceMethod, int entryBCI, int level);
 
-    public native HotSpotStackFrameReference getNextStackFrame(HotSpotStackFrameReference frame, HotSpotResolvedJavaMethod method);
+    public native HotSpotStackFrameReference getNextStackFrame(HotSpotStackFrameReference frame, long[] methods);
 
     public native void materializeVirtualObjects(HotSpotStackFrameReference stackFrame, boolean invalidate);
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java	Mon Apr 14 15:38:19 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java	Mon Apr 14 18:20:09 2014 +0200
@@ -162,6 +162,10 @@
         return HotSpotMetaspaceConstant.forMetaspaceObject(getHostWordKind(), metaspaceMethod, this);
     }
 
+    public long getMetaspaceMethod() {
+        return metaspaceMethod;
+    }
+
     @Override
     public Constant getEncoding() {
         return getMetaspaceMethodConstant();
--- a/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotFrameInstance.java	Mon Apr 14 15:38:19 2014 +0200
+++ b/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotFrameInstance.java	Mon Apr 14 18:20:09 2014 +0200
@@ -34,7 +34,7 @@
 
 public abstract class HotSpotFrameInstance implements FrameInstance {
 
-    private final InspectedFrame stackFrame;
+    protected final InspectedFrame stackFrame;
 
     public HotSpotFrameInstance(InspectedFrame stackFrame) {
         this.stackFrame = stackFrame;
@@ -51,13 +51,15 @@
         if (access == FrameAccess.NONE) {
             return null;
         }
-        if (!slowPath) {
+        if (!slowPath && getNotifyIndex() != -1) {
             MaterializedFrameNotify notify = (MaterializedFrameNotify) stackFrame.getLocal(getNotifyIndex());
-            if (access.ordinal() > notify.getOutsideFrameAccess().ordinal()) {
-                notify.setOutsideFrameAccess(access);
-            }
-            if (stackFrame.isVirtual(getFrameIndex())) {
-                stackFrame.materializeVirtualObjects(true);
+            if (notify != null) {
+                if (access.ordinal() > notify.getOutsideFrameAccess().ordinal()) {
+                    notify.setOutsideFrameAccess(access);
+                }
+                if (stackFrame.isVirtual(getFrameIndex())) {
+                    stackFrame.materializeVirtualObjects(true);
+                }
             }
         }
         switch (access) {
@@ -82,9 +84,9 @@
         return stackFrame.isVirtual(getFrameIndex());
     }
 
-    public CallTarget getCallTarget() {
-        return (CallTarget) stackFrame.getLocal(getCallTargetIndex());
-    }
+    public abstract CallTarget getCallTarget();
+
+    public abstract CallTarget getTargetCallTarget();
 
     public CallNode getCallNode() {
         Object receiver = stackFrame.getLocal(getNotifyIndex());
@@ -100,7 +102,7 @@
      * {@link DefaultCallNode#callProxy(MaterializedFrameNotify, CallTarget, VirtualFrame, Object[])}
      * method.
      */
-    public static final class NextFrame extends HotSpotFrameInstance {
+    public static final class CallNodeFrame extends HotSpotFrameInstance {
         public static final Method METHOD;
         static {
             try {
@@ -113,7 +115,7 @@
         private static final int CALL_TARGET_INDEX = 1;
         private static final int FRAME_INDEX = 2;
 
-        public NextFrame(InspectedFrame stackFrame) {
+        public CallNodeFrame(InspectedFrame stackFrame) {
             super(stackFrame);
         }
 
@@ -131,6 +133,16 @@
         protected int getFrameIndex() {
             return FRAME_INDEX;
         }
+
+        @Override
+        public CallTarget getCallTarget() {
+            return getCallNode().getRootNode().getCallTarget();
+        }
+
+        @Override
+        public CallTarget getTargetCallTarget() {
+            return (CallTarget) stackFrame.getLocal(getCallTargetIndex());
+        }
     }
 
     /**
@@ -138,7 +150,7 @@
      * {@link RootCallTarget#callProxy(VirtualFrame)} method.
      */
     @SuppressWarnings("javadoc")
-    public static final class CurrentFrame extends HotSpotFrameInstance {
+    public static final class CallTargetFrame extends HotSpotFrameInstance {
         public static final Method METHOD;
         static {
             try {
@@ -147,17 +159,19 @@
                 throw new GraalInternalError(e);
             }
         }
-        private static final int NOTIFY_INDEX = 0;
+        private static final int NOTIFY_INDEX = -1;
         private static final int CALL_TARGET_INDEX = 0;
         private static final int FRAME_INDEX = 1;
+        private final boolean currentFrame;
 
-        public CurrentFrame(InspectedFrame stackFrame) {
+        public CallTargetFrame(InspectedFrame stackFrame, boolean currentFrame) {
             super(stackFrame);
+            this.currentFrame = currentFrame;
         }
 
         @Override
         public Frame getFrame(FrameAccess access, boolean slowPath) {
-            if (!slowPath) {
+            if (!slowPath && currentFrame) {
                 throw new UnsupportedOperationException("cannot access current frame as fast path");
             }
             return super.getFrame(access, slowPath);
@@ -177,5 +191,15 @@
         protected int getFrameIndex() {
             return FRAME_INDEX;
         }
+
+        @Override
+        public CallTarget getCallTarget() {
+            return (CallTarget) stackFrame.getLocal(getCallTargetIndex());
+        }
+
+        @Override
+        public CallTarget getTargetCallTarget() {
+            return null;
+        }
     }
 }
--- a/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotTruffleRuntime.java	Mon Apr 14 15:38:19 2014 +0200
+++ b/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotTruffleRuntime.java	Mon Apr 14 18:20:09 2014 +0200
@@ -69,8 +69,16 @@
     private ArrayList<String> includes;
     private ArrayList<String> excludes;
 
+    private final ResolvedJavaMethod[] callNodeMethod;
+    private final ResolvedJavaMethod[] callTargetMethod;
+    private final ResolvedJavaMethod[] anyFrameMethod;
+
     private HotSpotTruffleRuntime() {
         installOptimizedCallTargetCallMethod();
+
+        callNodeMethod = new ResolvedJavaMethod[]{getGraalProviders().getMetaAccess().lookupJavaMethod(HotSpotFrameInstance.CallNodeFrame.METHOD)};
+        callTargetMethod = new ResolvedJavaMethod[]{getGraalProviders().getMetaAccess().lookupJavaMethod(HotSpotFrameInstance.CallTargetFrame.METHOD)};
+        anyFrameMethod = new ResolvedJavaMethod[]{callNodeMethod[0], callTargetMethod[0]};
     }
 
     public String getName() {
@@ -221,16 +229,27 @@
         if (stackIntrospection == null) {
             stackIntrospection = Graal.getRequiredCapability(StackIntrospection.class);
         }
-        ResolvedJavaMethod method = getGraalProviders().getMetaAccess().lookupJavaMethod(HotSpotFrameInstance.NextFrame.METHOD);
-        final Iterator<InspectedFrame> frames = stackIntrospection.getStackTrace(method, method).iterator();
+        final Iterator<InspectedFrame> frames = stackIntrospection.getStackTrace(anyFrameMethod, anyFrameMethod).iterator();
+        assert frames.hasNext();
+        InspectedFrame calltarget = frames.next();
+        assert calltarget.getMethod().equals(callTargetMethod[0]);
         class FrameIterator implements Iterator<FrameInstance> {
+
             public boolean hasNext() {
                 return frames.hasNext();
             }
 
             public FrameInstance next() {
                 InspectedFrame frame = frames.next();
-                return new HotSpotFrameInstance.NextFrame(frame);
+                if (frame.getMethod().equals(callNodeMethod[0])) {
+                    assert frames.hasNext();
+                    InspectedFrame calltarget2 = frames.next();
+                    assert calltarget2.getMethod().equals(callTargetMethod[0]);
+                    return new HotSpotFrameInstance.CallNodeFrame(frame);
+                } else {
+                    assert frame.getMethod().equals(callTargetMethod[0]);
+                    return new HotSpotFrameInstance.CallTargetFrame(frame, false);
+                }
             }
         }
         return new Iterable<FrameInstance>() {
@@ -244,10 +263,9 @@
         if (stackIntrospection == null) {
             stackIntrospection = Graal.getRequiredCapability(StackIntrospection.class);
         }
-        ResolvedJavaMethod method = getGraalProviders().getMetaAccess().lookupJavaMethod(HotSpotFrameInstance.CurrentFrame.METHOD);
-        Iterator<InspectedFrame> frames = stackIntrospection.getStackTrace(method, method).iterator();
+        Iterator<InspectedFrame> frames = stackIntrospection.getStackTrace(callTargetMethod, callTargetMethod).iterator();
         if (frames.hasNext()) {
-            return new HotSpotFrameInstance.CurrentFrame(frames.next());
+            return new HotSpotFrameInstance.CallTargetFrame(frames.next(), true);
         } else {
             System.out.println("no current frame found");
             return null;
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameInstance.java	Mon Apr 14 15:38:19 2014 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameInstance.java	Mon Apr 14 18:20:09 2014 +0200
@@ -43,4 +43,6 @@
     CallNode getCallNode();
 
     CallTarget getCallTarget();
+
+    CallTarget getTargetCallTarget();
 }
--- a/graal/com.oracle.truffle.sl.test/tests/HelloEqualsWorld.sl	Mon Apr 14 15:38:19 2014 +0200
+++ b/graal/com.oracle.truffle.sl.test/tests/HelloEqualsWorld.sl	Mon Apr 14 18:20:09 2014 +0200
@@ -19,4 +19,4 @@
     doIt(i);
     i = i + 1;
   }
-}  
+}
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLStackTraceBuiltin.java	Mon Apr 14 15:38:19 2014 +0200
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLStackTraceBuiltin.java	Mon Apr 14 18:20:09 2014 +0200
@@ -46,12 +46,12 @@
     private static String createStackTrace() {
         StringBuilder str = new StringBuilder();
         for (FrameInstance frame : Truffle.getRuntime().getStackTrace()) {
-            dumpFrame(str, frame.getCallNode().getRootNode(), frame.getFrame(FrameAccess.READ_ONLY, true), frame.isVirtualFrame());
+            dumpFrame(str, frame.getCallTarget(), frame.getFrame(FrameAccess.READ_ONLY, true), frame.isVirtualFrame());
         }
         return str.toString();
     }
 
-    private static void dumpFrame(StringBuilder str, RootNode rootNode, Frame frame, boolean isVirtual) {
+    private static void dumpFrame(StringBuilder str, CallTarget rootNode, Frame frame, boolean isVirtual) {
         if (str.length() > 0) {
             str.append("\n");
         }
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/call/SLGenericDispatchNode.java	Mon Apr 14 15:38:19 2014 +0200
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/call/SLGenericDispatchNode.java	Mon Apr 14 18:20:09 2014 +0200
@@ -42,7 +42,7 @@
          * SL has a quite simple call lookup: just ask the function for the current call target, and
          * call it.
          */
-        return DefaultCallNode.callProxy(this, function.getCallTarget(), frame, arguments);
+        return function.getCallTarget().call(arguments);
     }
 
     public FrameAccess getOutsideFrameAccess() {
--- a/src/share/vm/graal/graalCompilerToVM.cpp	Mon Apr 14 15:38:19 2014 +0200
+++ b/src/share/vm/graal/graalCompilerToVM.cpp	Mon Apr 14 18:20:09 2014 +0200
@@ -786,12 +786,22 @@
   return tty->time_stamp().milliseconds();
 C2V_END
 
+bool matches(jlongArray methods, Method* method) {
+  typeArrayOop methods_oop = (typeArrayOop) JNIHandles::resolve(methods);
+
+  for (int i = 0; i < methods_oop->length(); i++) {
+    if (methods_oop->long_at(i) == (jlong) method) {
+      return true;
+    }
+  }
+  return false;
+}
+
 // public native HotSpotStackFrameReference getNextStackFrame(HotSpotStackFrameReference frame, ResolvedJavaMethod method);
-C2V_VMENTRY(jobject, getNextStackFrame, (JNIEnv *env, jobject compilerToVM, jobject hs_frame, jobject hs_method))
+C2V_VMENTRY(jobject, getNextStackFrame, (JNIEnv *env, jobject compilerToVM, jobject hs_frame, jlongArray methods))
   ResourceMark rm;
 
   if (!thread->has_last_Java_frame()) return NULL;
-  methodHandle method = hs_method == NULL ? NULL : asMethod(HotSpotResolvedJavaMethod::metaspaceMethod(hs_method));
   Handle result = InstanceKlass::cast(HotSpotStackFrameReference::klass())->allocate_instance(thread);
   HotSpotStackFrameReference::klass()->initialize(thread);
 
@@ -840,7 +850,7 @@
       if (vf->is_compiled_frame()) {
         // compiled method frame
         compiledVFrame* cvf = compiledVFrame::cast(vf);
-        if (method == NULL || cvf->method() == method()) {
+        if (methods == NULL || matches(methods, cvf->method())) {
           GrowableArray<ScopeValue*>* objects = cvf->scope()->objects();
           bool reallocated = false;
           if (objects != NULL) {
@@ -864,23 +874,15 @@
 
           locals = cvf->locals();
           HotSpotStackFrameReference::set_bci(result, cvf->bci());
-          if (hs_method == NULL) {
-            HotSpotStackFrameReference::set_metaspaceMethod(result, (jlong) cvf->method());
-          } else {
-            HotSpotStackFrameReference::set_metaspaceMethod(result, (jlong) method());
-          }
+          HotSpotStackFrameReference::set_metaspaceMethod(result, (jlong) cvf->method());
         }
       } else if (vf->is_interpreted_frame()) {
         // interpreted method frame
         interpretedVFrame* ivf = interpretedVFrame::cast(vf);
-        if (method == NULL || ivf->method() == method()) {
+        if (methods == NULL || matches(methods, ivf->method())) {
           locals = ivf->locals();
           HotSpotStackFrameReference::set_bci(result, ivf->bci());
-          if (hs_method == NULL) {
-            HotSpotStackFrameReference::set_metaspaceMethod(result, (jlong) ivf->method());
-          } else {
-            HotSpotStackFrameReference::set_metaspaceMethod(result, (jlong) method());
-          }
+          HotSpotStackFrameReference::set_metaspaceMethod(result, (jlong) ivf->method());
           HotSpotStackFrameReference::set_localIsVirtual(result, NULL);
         }
       }
@@ -1031,6 +1033,7 @@
 #define CLASS                 "Ljava/lang/Class;"
 #define STACK_TRACE_ELEMENT   "Ljava/lang/StackTraceElement;"
 #define HS_RESOLVED_METHOD    "Lcom/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod;"
+#define RESOLVED_METHOD       "Lcom/oracle/graal/api/meta/ResolvedJavaMethod;"
 #define HS_COMPILED_CODE      "Lcom/oracle/graal/hotspot/HotSpotCompiledCode;"
 #define HS_CONFIG             "Lcom/oracle/graal/hotspot/HotSpotVMConfig;"
 #define HS_INSTALLED_CODE     "Lcom/oracle/graal/hotspot/meta/HotSpotInstalledCode;"
@@ -1093,7 +1096,7 @@
   {CC"isMature",                                     CC"("METASPACE_METHOD_DATA")Z",                                   FN_PTR(isMature)},
   {CC"hasCompiledCodeForOSR",                        CC"("METASPACE_METHOD"II)Z",                                      FN_PTR(hasCompiledCodeForOSR)},
   {CC"getTimeStamp",                                 CC"()J",                                                          FN_PTR(getTimeStamp)},
-  {CC"getNextStackFrame",                            CC"("HS_STACK_FRAME_REF HS_RESOLVED_METHOD")"HS_STACK_FRAME_REF,  FN_PTR(getNextStackFrame)},
+  {CC"getNextStackFrame",                            CC"("HS_STACK_FRAME_REF "[J)"HS_STACK_FRAME_REF,                  FN_PTR(getNextStackFrame)},
   {CC"materializeVirtualObjects",                    CC"("HS_STACK_FRAME_REF"Z)V",                                     FN_PTR(materializeVirtualObjects)},
 };