interpret.cc (_Jv_InterpMethod::run): Initialize _Jv_StartOfInterpreter.

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.

From-SVN: r89037
This commit is contained in:
Andrew Haley 2004-10-14 15:21:13 +00:00 committed by Andrew Haley
parent b79187bb54
commit 180a373d0d
3 changed files with 62 additions and 22 deletions

View File

@ -1,3 +1,13 @@
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.
2004-10-12 Rutger Ovidius <ovidr@users.sourceforge.net> 2004-10-12 Rutger Ovidius <ovidr@users.sourceforge.net>
PR libgcj/17903: PR libgcj/17903:

View File

@ -45,6 +45,11 @@ details. */
#include <unwind.h> #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. // Fill in this stack trace with MAXLEN elements starting at offset.
void void
gnu::gcj::runtime::StackTrace::fillInStackTrace (jint maxlen, jint offset) gnu::gcj::runtime::StackTrace::fillInStackTrace (jint maxlen, jint offset)
@ -58,9 +63,9 @@ gnu::gcj::runtime::StackTrace::fillInStackTrace (jint maxlen, jint offset)
if (len > 0) if (len > 0)
{ {
#ifdef INTERPRETER #ifdef INTERPRETER
extern void _Jv_StartOfInterpreter (void); extern void *const _Jv_StartOfInterpreter;
extern void _Jv_EndOfInterpreter (void); extern void * _Jv_EndOfInterpreter;
java::lang::Thread *thread = java::lang::Thread::currentThread(); java::lang::Thread *thread = java::lang::Thread::currentThread();
_Jv_MethodChain *interp_frame _Jv_MethodChain *interp_frame
= (thread ? reinterpret_cast<_Jv_MethodChain *> (thread->interp_frame) = (thread ? reinterpret_cast<_Jv_MethodChain *> (thread->interp_frame)
@ -70,16 +75,41 @@ gnu::gcj::runtime::StackTrace::fillInStackTrace (jint maxlen, jint offset)
frame = (_Jv_frame_info *) _Jv_Malloc (len * sizeof (_Jv_frame_info)); frame = (_Jv_frame_info *) _Jv_Malloc (len * sizeof (_Jv_frame_info));
for (int n = 0; n < len; n++) for (int n = 0; n < len; n++)
{ {
frame[n].addr = p[n]; void *pc = p[n];
frame[n].addr = pc;
#ifdef INTERPRETER #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))
{ {
frame[n].interp = (void *) interp_frame->self; // _Jv_StartOfInterpreter marks the very first
interp_frame = interp_frame->next; // 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
{
// 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;
}
} }
else
frame[n].interp = 0;
#endif // INTERPRETER #endif // INTERPRETER
} }
} }
else else

View File

@ -774,18 +774,25 @@ _Jv_InterpMethod::compile (const void * const *insn_targets)
} }
#endif /* DIRECT_THREADED */ #endif /* DIRECT_THREADED */
// This function exists so that the stack-tracing code can find the // These exist so that the stack-tracing code can find the boundaries
// boundaries of the interpreter. // of the interpreter.
void void *_Jv_StartOfInterpreter;
_Jv_StartOfInterpreter (void) void *_Jv_EndOfInterpreter;
{ extern "C" void *_Unwind_FindEnclosingFunction (void *pc);
}
void void
_Jv_InterpMethod::run (void *retp, ffi_raw *args) _Jv_InterpMethod::run (void *retp, ffi_raw *args)
{ {
using namespace java::lang::reflect; 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 // FRAME_DESC registers this particular invocation as the top-most
// interpreter frame. This lets the stack tracing code (for // interpreter frame. This lets the stack tracing code (for
// Throwable) print information about the method being interpreted // Throwable) print information about the method being interpreted
@ -3219,13 +3226,6 @@ _Jv_InterpMethod::run (void *retp, ffi_raw *args)
} }
} }
// This function exists so that the stack-tracing code can find the
// boundaries of the interpreter.
void
_Jv_EndOfInterpreter (void)
{
}
static void static void
throw_internal_error (char *msg) throw_internal_error (char *msg)
{ {