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: Fix backtrace for interpreted code


Revised, with comments.

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	14 Oct 2004 15:18:05 -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 == NULL)
+    _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	14 Oct 2004 15:18:05 -0000
@@ -45,6 +45,11 @@
 #include <unwind.h>
 
 
+#ifdef INTERPRETER
+extern "C" void *_Unwind_FindEnclosingFunction (void *pc)
+  __attribute__((pure));
+#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 +63,8 @@
   if (len > 0)
     {
 #ifdef INTERPRETER
-      extern void _Jv_StartOfInterpreter (void);
-      extern void _Jv_EndOfInterpreter (void);
+      extern void *const _Jv_StartOfInterpreter;
+      extern void * _Jv_EndOfInterpreter;
 
       java::lang::Thread *thread = java::lang::Thread::currentThread();
       _Jv_MethodChain *interp_frame
@@ -70,16 +75,41 @@
       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 is NULL either we've never
+	  // entered the intepreter or _Unwind_FindEnclosingFunction
+	  // is broken.
+	  if (__builtin_expect (_Jv_StartOfInterpreter != NULL, false))
+	    {
+	      // _Jv_StartOfInterpreter marks the very first
+	      // instruction in the interpreter, but
+	      // _Jv_EndOfInterpreter is an upper bound.  If PC is
+	      // less than _Jv_EndOfInterpreter it might be in the
+	      // interpreter: we call _Unwind_FindEnclosingFunction to
+	      // find out.
+	      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;
+		{
+		  // We've found an address that we know is not within
+		  // the interpreter.  We use that to refine our upper
+		  // bound on where the interpreter ends.
+		  if (_Jv_EndOfInterpreter == NULL || pc < _Jv_EndOfInterpreter)
+		    _Jv_EndOfInterpreter = pc;
+		}
+	    }
 #endif // INTERPRETER
+
 	}
     }
   else


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