This is the mail archive of the java-patches@gcc.gnu.org mailing list for the Java project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: RFC: stack trace info for interpreter frames


Tom> I'll check this in a bit later.  I may change it to demangle the
Tom> method signature first.

I decided not to demangle yet.
I've appended what I'm checking in.

Tom

Index: ChangeLog
from  Tom Tromey  <tromey@redhat.com>

	* include/jvm.h (struct _Jv_frame_info): New structure.
	* gnu/gcj/runtime/natNameFinder.cc: Include StringBuffer.h,
	java-interp.h.
	(lookupInterp): New method.
	(getAddrAsString): Use _Jv_frame_info.
	(dladdrLookup): Likewise.
	* gnu/gcj/runtime/NameFinder.java (lookup): Try to look up
	interpreted frame.
	(lookupInterp): Declare.
	* java/lang/natVMThrowable.cc: Include Thread.h, java-interp.h.
	(fillInStackTrace): Collect information on interpreted frames.
	Use _Jv_frame_info.
	* interpret.cc: Include Thread.h.
	(run): Create and push _Jv_MethodChain object.
	(_Jv_EndOfInterpreter): New global.
	* java/lang/Thread.java (interp_frame): New field.
	* include/java-interp.h (struct _Jv_MethodChain): New structure.
	Include NameFinder.h.

Index: interpret.cc
===================================================================
RCS file: /cvs/gcc/gcc/libjava/interpret.cc,v
retrieving revision 1.33
diff -u -r1.33 interpret.cc
--- interpret.cc 24 Jun 2002 20:38:45 -0000 1.33
+++ interpret.cc 29 Aug 2002 17:48:47 -0000
@@ -22,7 +22,6 @@
 #include <jvm.h>
 #include <java-cpool.h>
 #include <java-interp.h>
-// #include <java/lang/fdlibm.h>
 #include <java/lang/System.h>
 #include <java/lang/String.h>
 #include <java/lang/Integer.h>
@@ -36,6 +35,7 @@
 #include <java/lang/NullPointerException.h>
 #include <java/lang/ArithmeticException.h>
 #include <java/lang/IncompatibleClassChangeError.h>
+#include <java/lang/Thread.h>
 #include <java-insns.h>
 #include <java-signal.h>
 
@@ -744,11 +744,28 @@
 }
 #endif /* DIRECT_THREADED */
 
+// This function exists so that the stack-tracing code can find the
+// boundaries of the interpreter.
+void
+_Jv_StartOfInterpreter (void)
+{
+}
+
 void
 _Jv_InterpMethod::run (void *retp, ffi_raw *args)
 {
   using namespace java::lang::reflect;
 
+  // FRAME_DESC registers this particular invocation as the top-most
+  // interpreter frame.  This lets the stack tracing code (for
+  // Throwable) print information about the method being interpreted
+  // rather than about the interpreter itself.  FRAME_DESC has a
+  // destructor so it cleans up automatically when the interpreter
+  // returns.
+  java::lang::Thread *thread = java::lang::Thread::currentThread();
+  _Jv_MethodChain frame_desc (this,
+			      (_Jv_MethodChain **) &thread->interp_frame);
+
   _Jv_word stack[max_stack];
   _Jv_word *sp = stack;
 
@@ -3167,6 +3184,13 @@
       // No handler, so re-throw.
       throw ex;
     }
+}
+
+// This function exists so that the stack-tracing code can find the
+// boundaries of the interpreter.
+void
+_Jv_EndOfInterpreter (void)
+{
 }
 
 static void
Index: include/java-interp.h
===================================================================
RCS file: /cvs/gcc/gcc/libjava/include/java-interp.h,v
retrieving revision 1.17
diff -u -r1.17 java-interp.h
--- include/java-interp.h 24 Jun 2002 20:38:46 -0000 1.17
+++ include/java-interp.h 29 Aug 2002 17:48:47 -0000
@@ -13,6 +13,7 @@
 
 #include <jvm.h>
 #include <java-cpool.h>
+#include <gnu/gcj/runtime/NameFinder.h>
 
 #ifdef INTERPRETER
 
@@ -138,6 +139,7 @@
 
   friend class _Jv_ClassReader;
   friend class _Jv_BytecodeVerifier;
+  friend class gnu::gcj::runtime::NameFinder;
 
   friend void _Jv_PrepareClass(jclass);
 };
@@ -202,6 +204,28 @@
   void set_function (void *f)
   {
     function = f;
+  }
+};
+
+// A structure of this type is used to link together interpreter
+// invocations on the stack.
+struct _Jv_MethodChain
+{
+  const _Jv_InterpMethod *self;
+  _Jv_MethodChain **ptr;
+  _Jv_MethodChain *next;
+
+  _Jv_MethodChain (const _Jv_InterpMethod *s, _Jv_MethodChain **n)
+  {
+    self = s;
+    ptr = n;
+    next = *n;
+    *n = this;
+  }
+
+  ~_Jv_MethodChain ()
+  {
+    *ptr = next;
   }
 };
 
Index: include/jvm.h
===================================================================
RCS file: /cvs/gcc/gcc/libjava/include/jvm.h,v
retrieving revision 1.51
diff -u -r1.51 jvm.h
--- include/jvm.h 11 Apr 2002 15:57:56 -0000 1.51
+++ include/jvm.h 29 Aug 2002 17:48:47 -0000
@@ -111,6 +111,20 @@
   jdouble d;
 };                              
 
+// An instance of this type is used to represent a single frame in a
+// backtrace.  If the interpreter has been built, we also include
+// information about the interpreted method.
+struct _Jv_frame_info
+{
+  // PC value.
+  void *addr;
+#ifdef INTERPRETER
+  // Actually a _Jv_InterpMethod, but we don't want to include
+  // java-interp.h everywhere.
+  void *interp;
+#endif // INTERPRETER
+};
+
 /* Extract a character from a Java-style Utf8 string.
  * PTR points to the current character.
  * LIMIT points to the end of the Utf8 string.
Index: gnu/gcj/runtime/NameFinder.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/gnu/gcj/runtime/NameFinder.java,v
retrieving revision 1.1
diff -u -r1.1 NameFinder.java
--- gnu/gcj/runtime/NameFinder.java 24 Aug 2002 22:46:19 -0000 1.1
+++ gnu/gcj/runtime/NameFinder.java 29 Aug 2002 17:48:48 -0000
@@ -173,17 +173,26 @@
   native private String getAddrAsString(RawData addrs, int n);
 
   /**
+   * If nth element of stack is an interpreted frame, return the
+   * element representing the method being interpreted.
+   */
+  native private StackTraceElement lookupInterp(RawData addrs, int n);
+
+  /**
    * Creates the nth StackTraceElement from the given native stacktrace.
    */
   private StackTraceElement lookup(RawData addrs, int n)
   {
     StackTraceElement result;
 
-    result = dladdrLookup(addrs, n);
+    result = lookupInterp(addrs, n);
+    if (result == null)
+      result = dladdrLookup(addrs, n);
     if (result == null)
       {
 	String name = null;
 	String file = null;
+
 	String hex = getAddrAsString(addrs, n);
 	
 	if (addr2line != null)
Index: gnu/gcj/runtime/natNameFinder.cc
===================================================================
RCS file: /cvs/gcc/gcc/libjava/gnu/gcj/runtime/natNameFinder.cc,v
retrieving revision 1.1
diff -u -r1.1 natNameFinder.cc
--- gnu/gcj/runtime/natNameFinder.cc 24 Aug 2002 22:46:19 -0000 1.1
+++ gnu/gcj/runtime/natNameFinder.cc 29 Aug 2002 17:48:48 -0000
@@ -1,4 +1,4 @@
-// natNameFinder.cc - native helper methods for NameFiner.java
+// natNameFinder.cc - native helper methods for NameFinder.java
 
 /* Copyright (C) 2002  Free Software Foundation, Inc
 
@@ -19,6 +19,8 @@
 #include <jvm.h>
 #include <java/lang/String.h>
 #include <java/lang/StackTraceElement.h>
+#include <java/lang/StringBuffer.h>
+#include <java-interp.h>
 
 #include <gnu/gcj/runtime/NameFinder.h>
 
@@ -29,15 +31,15 @@
 java::lang::String*
 gnu::gcj::runtime::NameFinder::getExecutable (void)
 {
-    return JvNewStringLatin1 (_Jv_ThisExecutable ());
+  return JvNewStringLatin1 (_Jv_ThisExecutable ());
 }
 
 java::lang::String*
 gnu::gcj::runtime::NameFinder::getAddrAsString(RawData* addrs, jint n)
 {
-  void **p = (void **) addrs;
+  _Jv_frame_info *p = (_Jv_frame_info *) addrs;
   typedef unsigned word_t __attribute ((mode (word)));
-  word_t w = (word_t) p[n];
+  word_t w = (word_t) p[n].addr;
   int digits = sizeof (void *) * 2;
   char hex[digits+5];
 
@@ -61,8 +63,8 @@
   extern char **_Jv_argv;
   char name[1024];
   char file_name[1024];
-  void **stack = (void **) addrs;
-  void* p = stack[n];
+  _Jv_frame_info *stack = (_Jv_frame_info *) addrs;
+  void* p = stack[n].addr;
   Dl_info dl_info;
    
   if (dladdr (p, &dl_info))
@@ -81,4 +83,30 @@
     }
 #endif
   return NULL;
+}
+
+java::lang::StackTraceElement *
+gnu::gcj::runtime::NameFinder::lookupInterp(RawData* addrs, jint n)
+{
+#ifdef INTERPRETER
+  _Jv_frame_info *stack = (_Jv_frame_info *) addrs;
+  if (stack[n].interp == NULL)
+    return NULL;
+
+  _Jv_InterpMethod *meth
+    = reinterpret_cast<_Jv_InterpMethod *> (stack[n].interp);
+  // FIXME: demangle.
+  java::lang::StringBuffer *sb = new java::lang::StringBuffer();
+  sb->append(_Jv_NewStringUtf8Const(meth->self->name));
+  sb->append(_Jv_NewStringUtf8Const(meth->self->signature));
+  // FIXME: source file name and line number can be found from
+  // bytecode debug information.  But currently we don't keep that
+  // around.
+  // FIXME: is using the defining class correct here?
+  return new java::lang::StackTraceElement(NULL, -1,
+					   meth->defining_class->getName(),
+					   sb->toString(), false);
+#else // INTERPRETER
+  return NULL;
+#endif // INTERPRETER
 }
Index: java/lang/Thread.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/lang/Thread.java,v
retrieving revision 1.22
diff -u -r1.22 Thread.java
--- java/lang/Thread.java 18 Jun 2002 15:39:38 -0000 1.22
+++ java/lang/Thread.java 29 Aug 2002 17:48:48 -0000
@@ -10,6 +10,8 @@
 
 package java.lang;
 
+import gnu.gcj.RawData;
+
 /**
  * @author Tom Tromey <tromey@cygnus.com>
  * @date August 24, 1998 
@@ -310,6 +312,9 @@
   private boolean alive_flag;
   private boolean startable_flag;
   private ClassLoader context_class_loader;
+
+  // This describes the top-most interpreter frame for this thread.
+  RawData interp_frame;
 
   // Our native data - points to an instance of struct natThread.
   private Object data;
Index: java/lang/natVMThrowable.cc
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/lang/natVMThrowable.cc,v
retrieving revision 1.1
diff -u -r1.1 natVMThrowable.cc
--- java/lang/natVMThrowable.cc 24 Aug 2002 22:46:19 -0000 1.1
+++ java/lang/natVMThrowable.cc 29 Aug 2002 17:48:48 -0000
@@ -26,6 +26,8 @@
 #include <java-threads.h>
 #include <java/lang/Throwable.h>
 #include <java/lang/VMThrowable.h>
+#include <java/lang/Thread.h>
+#include <java-interp.h>
 
 #include <sys/types.h>
 
@@ -54,13 +56,35 @@
   // to include the calls to fillInStackTrace in the trace.
   int n = backtrace (p, 128) - 1;  
 
-  void **addrs;
+  _Jv_frame_info *addrs;
   if (n > 0)
     {
+#ifdef INTERPRETER
+      extern void _Jv_StartOfInterpreter (void);
+      extern void _Jv_EndOfInterpreter (void);
+
+      java::lang::Thread *thread = java::lang::Thread::currentThread();
+      _Jv_MethodChain *interp_frame
+	= (thread ? reinterpret_cast<_Jv_MethodChain *> (thread->interp_frame)
+	   : NULL);
+#endif // INTERPRETER
+
       state->length = n;
-      addrs = (void **) _Jv_Malloc (n * sizeof p[0]);
+      int len = n;
+      addrs = (_Jv_frame_info *) _Jv_Malloc (n * sizeof (_Jv_frame_info));
       while (n--)
-	addrs[n] = p[n];
+	{
+	  addrs[n].addr = p[n];
+#ifdef INTERPRETER
+	  if (p[n] >= &_Jv_StartOfInterpreter && p[n] <= &_Jv_EndOfInterpreter)
+	    {
+	      addrs[n].interp = (void *) interp_frame->self;
+	      interp_frame = interp_frame->next;
+	    }
+	  else
+	    addrs[n].interp = 0;
+#endif // INTERPRETER
+	}
     }
   else
     addrs = NULL;


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]