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]

Fix backtrace for interpreted code


Tom Tromey noticed that stack traces no longer work for interpreted code.
This is due to the fact that we use a truly bogus way to discover if
the PC points into _Jv_InterpMethod::run.

There's no truly portable way to do something like this, but with a
little help from the unwinder library we can do it.  This won't work
without the unwinder, but as far as I'm aware
_Unwind_FindEnclosingFunction should work on all targets.

Is this true even of mingw and Cygwin?  Anyone who knows, please let
me know.

Andrew.


2004-10-13  Andrew Haley  <aph@redhat.com>

	* interpret.cc (_Jv_InterpMethod::run): Initialize
	_Jv_StartOfInterpreter.
	(_Jv_StartOfInterpreter, _Jv_EndOfInterpreter): Functions removed.
	(_Jv_StartOfInterpreter, _Jv_EndOfInterpreter): New variables.
	* gnu/gcj/runtime/natStackTrace.cc (fillInStackTrace): Use
	_Unwind_FindEnclosingFunction to discover whether PC is within the
	interpreter.	

Index: interpret.cc
===================================================================
RCS file: /cvs/gcc/gcc/libjava/interpret.cc,v
retrieving revision 1.45
diff -u -w -r1.45 interpret.cc
--- interpret.cc	13 Jul 2004 21:06:33 -0000	1.45
+++ interpret.cc	13 Oct 2004 17:40:10 -0000
@@ -774,18 +774,25 @@
 }
 #endif /* DIRECT_THREADED */
 
-// This function exists so that the stack-tracing code can find the
-// boundaries of the interpreter.
-void
-_Jv_StartOfInterpreter (void)
-{
-}
+// These exist so that the stack-tracing code can find the boundaries
+// of the interpreter.
+void *_Jv_StartOfInterpreter;
+void *_Jv_EndOfInterpreter;
+extern "C" void *_Unwind_FindEnclosingFunction (void *pc);
 
 void
 _Jv_InterpMethod::run (void *retp, ffi_raw *args)
 {
   using namespace java::lang::reflect;
 
+  // Record the address of the start of this member function in
+  // _Jv_StartOfInterpreter.  Such a write to a global variable
+  // without acquiring a lock is correct iff reads and writes of words
+  // in memory are atomic, but Java requires that anyway.
+ foo:
+  if (! _Jv_StartOfInterpreter)
+    _Jv_StartOfInterpreter = _Unwind_FindEnclosingFunction (&&foo);
+
   // 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
@@ -3219,13 +3226,6 @@
     }
 }
 
-// This function exists so that the stack-tracing code can find the
-// boundaries of the interpreter.
-void
-_Jv_EndOfInterpreter (void)
-{
-}
-
 static void
 throw_internal_error (char *msg)
 {
Index: gnu/gcj/runtime/natStackTrace.cc
===================================================================
RCS file: /cvs/gcc/gcc/libjava/gnu/gcj/runtime/natStackTrace.cc,v
retrieving revision 1.6
diff -u -w -r1.6 natStackTrace.cc
--- gnu/gcj/runtime/natStackTrace.cc	2 Oct 2003 07:10:34 -0000	1.6
+++ gnu/gcj/runtime/natStackTrace.cc	13 Oct 2004 17:40:10 -0000
@@ -45,6 +45,10 @@
 #include <unwind.h>
 
 
+#ifdef INTERPRETER
+extern "C" void *_Unwind_FindEnclosingFunction (void *pc);
+#endif // INTERPRETER
+
 // Fill in this stack trace with MAXLEN elements starting at offset.
 void
 gnu::gcj::runtime::StackTrace::fillInStackTrace (jint maxlen, jint offset)
@@ -58,8 +62,8 @@
   if (len > 0)
     {
 #ifdef INTERPRETER
-      extern void _Jv_StartOfInterpreter (void);
-      extern void _Jv_EndOfInterpreter (void);
+      extern void *_Jv_StartOfInterpreter;
+      extern void *_Jv_EndOfInterpreter;
 
       java::lang::Thread *thread = java::lang::Thread::currentThread();
       _Jv_MethodChain *interp_frame
@@ -70,15 +74,24 @@
       frame = (_Jv_frame_info *) _Jv_Malloc (len * sizeof (_Jv_frame_info));
       for (int n = 0; n < len; n++)
 	{
-	  frame[n].addr = p[n];
+	  void *pc = p[n];
+	  frame[n].addr = pc;
 #ifdef INTERPRETER
-	  if (p[n] >= &_Jv_StartOfInterpreter && p[n] <= &_Jv_EndOfInterpreter)
+	  frame[n].interp = 0;
+	  if (_Jv_StartOfInterpreter != NULL)
+	    {
+	      if ((_Jv_EndOfInterpreter == NULL || pc < _Jv_EndOfInterpreter)
+		  && _Unwind_FindEnclosingFunction (pc) == _Jv_StartOfInterpreter)
 	    {
 	      frame[n].interp = (void *) interp_frame->self;
 	      interp_frame = interp_frame->next;
 	    }
 	  else
-	    frame[n].interp = 0;
+		{
+		  if (_Jv_EndOfInterpreter == NULL || pc < _Jv_EndOfInterpreter)
+		    _Jv_EndOfInterpreter = pc;
+		}
+	    }
 #endif // INTERPRETER
 	}
     }


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