changeset 7310:79a7b761755c

Added getLineNumberTable and getFileName capabilities.
author Thomas Wuerthinger <thomas.wuerthinger@oracle.com>
date Thu, 20 Dec 2012 14:50:56 +0100
parents 75c18356504d
children 3fda7128589e
files graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaMethod.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedPrimitiveType.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MethodCallTargetNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/GraphUtil.java src/cpu/x86/vm/jniTypes_x86.hpp src/share/vm/graal/graalCompilerToVM.cpp
diffstat 7 files changed, 149 insertions(+), 16 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaMethod.java	Thu Dec 20 14:43:37 2012 +0100
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaMethod.java	Thu Dec 20 14:50:56 2012 +0100
@@ -24,6 +24,7 @@
 
 import java.lang.annotation.*;
 import java.lang.reflect.*;
+import java.lang.reflect.Method;
 import java.util.*;
 
 /**
@@ -159,4 +160,10 @@
      * Returns {@code true} if this method can be inlined.
      */
     boolean canBeInlined();
+
+
+    /**
+     * Returns the LineNumberTable of this method.
+     */
+    LineNumberTable getLineNumberTable();
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java	Thu Dec 20 14:43:37 2012 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java	Thu Dec 20 14:50:56 2012 +0100
@@ -34,6 +34,7 @@
 import com.oracle.graal.api.meta.ProfilingInfo.ExceptionSeen;
 import com.oracle.graal.bytecode.*;
 import com.oracle.graal.hotspot.*;
+import com.oracle.graal.hotspot.debug.*;
 import com.oracle.graal.phases.*;
 
 /**
@@ -290,6 +291,21 @@
         return HotSpotGraalRuntime.getInstance().getCompilerToVM().isMethodCompilable(metaspaceMethod);
     }
 
+    @Override
+    public LineNumberTable getLineNumberTable() {
+        long[] values = HotSpotGraalRuntime.getInstance().getCompilerToVM().getLineNumberTable(this);
+        assert values.length % 2 == 0;
+        int[] bci = new int[values.length / 2];
+        int[] line = new int[values.length / 2];
+
+        for (int i = 0; i < values.length / 2; i++) {
+            bci[i] = (int) values[i * 2];
+            line[i] = (int) values[i * 2 + 1];
+        }
+
+        return new LineNumberTableImpl(line, bci);
+    }
+
     /**
      * Returns the offset of this method into the v-table.
      * If the holder is not initialized, returns -1
@@ -309,4 +325,5 @@
     public CompilationTask currentTask() {
         return currentTask;
     }
+
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedPrimitiveType.java	Thu Dec 20 14:43:37 2012 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedPrimitiveType.java	Thu Dec 20 14:50:56 2012 +0100
@@ -181,7 +181,12 @@
     }
 
     @Override
-    public Class<?> mirror() {
+    public String getSourceFileName() {
+        throw GraalInternalError.shouldNotReachHere();
+    }
+
+    @Override
+    public Class< ? > mirror() {
         return javaMirror;
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MethodCallTargetNode.java	Thu Dec 20 14:43:37 2012 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MethodCallTargetNode.java	Thu Dec 20 14:50:56 2012 +0100
@@ -148,4 +148,13 @@
         }
         return targetMethod().getName();
     }
+
+    public static MethodCallTargetNode find(StructuredGraph graph, ResolvedJavaMethod method) {
+        for (MethodCallTargetNode target : graph.getNodes(MethodCallTargetNode.class)) {
+            if (target.targetMethod == method) {
+                return target;
+            }
+        }
+        return null;
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/GraphUtil.java	Thu Dec 20 14:43:37 2012 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/GraphUtil.java	Thu Dec 20 14:50:56 2012 +0100
@@ -186,30 +186,67 @@
     /**
      * Gets an approximate source code location for a node if possible.
      *
-     * @return a file name and source line number in stack trace format (e.g. "String.java:32")
-     *          if an approximate source location is found, null otherwise
+     * @return the StackTraceElements if an approximate source location is found, null otherwise
      */
-    public static String approxSourceLocation(Node node) {
+    public static StackTraceElement[] approxSourceStackTraceElement(Node node) {
+        ArrayList<StackTraceElement> elements = new ArrayList<>();
         Node n = node;
         while (n != null) {
             if (n instanceof MethodCallTargetNode) {
+                elements.add(((MethodCallTargetNode) n).targetMethod().asStackTraceElement(-1));
                 n = ((MethodCallTargetNode) n).invoke().node();
             }
 
             if (n instanceof StateSplit) {
-                FrameState stateAfter = ((StateSplit) n).stateAfter();
-                if (stateAfter != null) {
-                    ResolvedJavaMethod method = stateAfter.method();
+                FrameState state = ((StateSplit) n).stateAfter();
+                while (state != null) {
+                    ResolvedJavaMethod method = state.method();
                     if (method != null) {
-                        StackTraceElement stackTraceElement = method.asStackTraceElement(stateAfter.bci);
-                        if (stackTraceElement.getFileName() != null && stackTraceElement.getLineNumber() >= 0) {
-                            return stackTraceElement.getFileName() + ":" + stackTraceElement.getLineNumber();
-                        }
+                        elements.add(method.asStackTraceElement(state.bci - 1));
                     }
+                    state = state.outerFrameState();
                 }
+                break;
             }
             n = n.predecessor();
         }
+        return elements.toArray(new StackTraceElement[elements.size()]);
+    }
+
+
+    /**
+     * Gets an approximate source code location for a node, encoded as an exception, if possible.
+     *
+     * @return the exception with the location
+     */
+    public static RuntimeException approxSourceException(Node node, Throwable cause) {
+        final StackTraceElement[] elements = approxSourceStackTraceElement(node);
+        @SuppressWarnings("serial")
+        RuntimeException exception = new RuntimeException(cause.getMessage(), cause) {
+
+            @Override
+            public synchronized Throwable fillInStackTrace() {
+                setStackTrace(elements);
+                return this;
+            }
+        };
+        return exception;
+    }
+
+    /**
+     * Gets an approximate source code location for a node if possible.
+     *
+     * @return a file name and source line number in stack trace format (e.g. "String.java:32") if an approximate source
+     *         location is found, null otherwise
+     */
+    public static String approxSourceLocation(Node node) {
+        StackTraceElement[] stackTraceElements = approxSourceStackTraceElement(node);
+        if (stackTraceElements != null && stackTraceElements.length > 0) {
+            StackTraceElement top = stackTraceElements[0];
+            if (top.getFileName() != null && top.getLineNumber() >= 0) {
+                return top.getFileName() + ":" + top.getLineNumber();
+            }
+        }
         return null;
     }
 
--- a/src/cpu/x86/vm/jniTypes_x86.hpp	Thu Dec 20 14:43:37 2012 +0100
+++ b/src/cpu/x86/vm/jniTypes_x86.hpp	Thu Dec 20 14:50:56 2012 +0100
@@ -128,11 +128,25 @@
   static inline jfloat  get_float (intptr_t *from) { return *(jfloat *) from; }
   static inline jdouble get_double(intptr_t *from) { return *(jdouble *)(from + _JNI_SLOT_OFFSET); }
 
-  static inline jint    get_int   (intptr_t *from, int& pos) { return get_int(from + pos++); }
-  static inline jlong   get_long  (intptr_t *from, int& pos) { return get_long(from + pos); pos += 2; }
-  static inline oop     get_obj   (intptr_t *from, int& pos) { return get_obj(from + pos++); }
-  static inline jfloat  get_float (intptr_t *from, int& pos) { return get_float(from + pos++); }
-  static inline jdouble get_double(intptr_t *from, int& pos) { return get_double(from + pos); pos += 2; }
+  static inline jint    get_int   (intptr_t *from, int& pos) {
+    return get_int(from + pos++);
+  }
+  static inline jlong   get_long  (intptr_t *from, int& pos) {
+    jlong result = get_long(from + pos);
+    pos += 2;
+    return result;
+  }
+  static inline oop     get_obj   (intptr_t *from, int& pos) {
+    return get_obj(from + pos++);
+  }
+  static inline jfloat  get_float (intptr_t *from, int& pos) {
+    return get_float(from + pos++);
+  }
+  static inline jdouble get_double(intptr_t *from, int& pos) {
+    jdouble result = get_double(from + pos);
+    pos += 2;
+    return result;
+  }
 #undef _JNI_SLOT_OFFSET
 };
 
--- a/src/share/vm/graal/graalCompilerToVM.cpp	Thu Dec 20 14:43:37 2012 +0100
+++ b/src/share/vm/graal/graalCompilerToVM.cpp	Thu Dec 20 14:50:56 2012 +0100
@@ -938,6 +938,47 @@
   return JNIHandles::make_local(result());
 C2V_END
 
+C2V_ENTRY(jlongArray, getLineNumberTable, (JNIEnv *env, jobject, jobject hotspot_method))
+// XXX: Attention: it seEms that the line number table of a method just contains lines that are important, means that
+// empty lines are left out or lines that can't have a breakpoint on it; eg int a; or try {
+  Method* method = getMethodFromHotSpotMethod(JNIHandles::resolve(hotspot_method));
+  if(!method->has_linenumber_table()) {
+    return NULL;
+  }
+  u2 num_entries = 0;
+  CompressedLineNumberReadStream streamForSize(method->compressed_linenumber_table());
+  while (streamForSize.read_pair()) {
+    num_entries++;
+  }
+
+  CompressedLineNumberReadStream stream(method->compressed_linenumber_table());
+  jlongArray result = env->NewLongArray(2 * num_entries);
+
+  int i = 0;
+  jlong value;
+  while (stream.read_pair()) {
+    value = ((long) stream.bci());
+    env->SetLongArrayRegion(result,i,1,&value);
+    value = ((long) stream.line());
+    env->SetLongArrayRegion(result,i + 1,1,&value);
+    i += 2;
+  }
+
+  return result;
+C2V_END
+
+
+C2V_VMENTRY(jobject, getFileName, (JNIEnv *, jobject, jobject klass))
+  ResourceMark rm;
+  InstanceKlass* k = (InstanceKlass*) asKlass(HotSpotResolvedObjectType::metaspaceKlass(klass));
+  Symbol *s = k->source_file_name();
+  int length;
+  jchar *name = s->as_unicode(length);
+
+  Handle result = java_lang_String::create_from_unicode(name, length, CHECK_NULL);
+  return JNIHandles::make_local(result());
+
+C2V_END
 
 #define CC (char*)  /*cast a literal from (const char*)*/
 #define FN_PTR(f) CAST_FROM_FN_PTR(void*, &(c2v_ ## f))
@@ -960,6 +1001,7 @@
 #define CLASS                 "Ljava/lang/Class;"
 #define STACK_TRACE_ELEMENT   "Ljava/lang/StackTraceElement;"
 #define HS_RESOLVED_TYPE      "Lcom/oracle/graal/hotspot/meta/HotSpotResolvedObjectType;"
+#define HS_RESOLVED_JAVA_TYPE "Lcom/oracle/graal/hotspot/meta/HotSpotResolvedJavaType;"
 #define HS_RESOLVED_METHOD    "Lcom/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod;"
 #define HS_RESOLVED_FIELD     "Lcom/oracle/graal/hotspot/meta/HotSpotResolvedJavaField;"
 #define HS_COMP_RESULT        "Lcom/oracle/graal/hotspot/HotSpotCompilationResult;"
@@ -1008,6 +1050,8 @@
   {CC"executeCompiledMethodVarargs",  CC"("METASPACE_METHOD NMETHOD "["OBJECT")"OBJECT,                 FN_PTR(executeCompiledMethodVarargs)},
   {CC"getDeoptedLeafGraphIds",        CC"()[J",                                                         FN_PTR(getDeoptedLeafGraphIds)},
   {CC"decodePC",                      CC"(J)"STRING,                                                    FN_PTR(decodePC)},
+  {CC"getLineNumberTable",            CC"("HS_RESOLVED_METHOD")[J",                                     FN_PTR(getLineNumberTable)},
+  {CC"getFileName",                   CC"("HS_RESOLVED_JAVA_TYPE")"STRING,                              FN_PTR(getFileName)},
 };
 
 int CompilerToVM_methods_count() {