aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2005-01-05 09:59:00 +0000
committerJakub Jelinek <jakub@redhat.com>2005-01-05 09:59:00 +0000
commit92db0175aa3b31e694b53003bf2509ffaef3f8f5 (patch)
tree42345bdecf9c34f44c3a6944a15ea374d2648dcf
parent0c67fa44453c96787c439c225546c9d20333c4d8 (diff)
2004-12-13 Jakub Jelinek <jakub@redhat.com>
Revert: 2004-01-21 Tom Tromey <tromey@redhat.com> PR java/13468: * Makefile.in: Rebuilt. * Makefile.am (interpret.lo): New target. 2004-10-18 Andrew Haley <aph@redhat.com> PR java/18036: * gnu/gcj/runtime/natStackTrace.cc (fillInStackTrace): Reorganize and correct logic used to find interpreter. 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. git-svn-id: https://gcc.gnu.org/svn/gcc/branches/gcc-3_4-rhl-branch@92944 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--libjava/ChangeLog24
-rw-r--r--libjava/Makefile.am7
-rw-r--r--libjava/Makefile.in3
-rw-r--r--libjava/gnu/gcj/runtime/natStackTrace.cc49
-rw-r--r--libjava/interpret.cc81
5 files changed, 105 insertions, 59 deletions
diff --git a/libjava/ChangeLog b/libjava/ChangeLog
index 0d609ca83bb..bf226a054c1 100644
--- a/libjava/ChangeLog
+++ b/libjava/ChangeLog
@@ -1,3 +1,27 @@
+2004-12-13 Jakub Jelinek <jakub@redhat.com>
+
+ Revert:
+ 2004-01-21 Tom Tromey <tromey@redhat.com>
+ PR java/13468:
+ * Makefile.in: Rebuilt.
+ * Makefile.am (interpret.lo): New target.
+
+2004-10-18 Andrew Haley <aph@redhat.com>
+
+ PR java/18036:
+ * gnu/gcj/runtime/natStackTrace.cc (fillInStackTrace): Reorganize
+ and correct logic used to find interpreter.
+
+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-12-06 Tom Tromey <tromey@redhat.com>
For PR java/14853:
diff --git a/libjava/Makefile.am b/libjava/Makefile.am
index d8eb43b67d5..197c4419243 100644
--- a/libjava/Makefile.am
+++ b/libjava/Makefile.am
@@ -511,13 +511,6 @@ $(nat_files) $(x_nat_files): %.lo: %.cc
$(c_files): %.lo: %.c
$(LTCOMPILE) -c -o $@ $<
-## A special rule for interpret.lo for the time being. Our current
-## approach to stack-trace handling is fragile and will not work with
-## unit-at-a-time. So, for now we disable it. This will be fixed by
-## a larger patch in the future.
-interpret.lo: interpret.cc
- $(LTCXXCOMPILE) -fno-unit-at-a-time -c -o $@ $<
-
$(extra_cc_files): %.lo: %.cc
$(LTCXXCOMPILE) -c -o $@ $<
diff --git a/libjava/Makefile.in b/libjava/Makefile.in
index 1da73747cd2..0a0f5fb6998 100644
--- a/libjava/Makefile.in
+++ b/libjava/Makefile.in
@@ -5415,9 +5415,6 @@ $(nat_files) $(x_nat_files): %.lo: %.cc
$(c_files): %.lo: %.c
$(LTCOMPILE) -c -o $@ $<
-interpret.lo: interpret.cc
- $(LTCXXCOMPILE) -fno-unit-at-a-time -c -o $@ $<
-
$(extra_cc_files): %.lo: %.cc
$(LTCXXCOMPILE) -c -o $@ $<
diff --git a/libjava/gnu/gcj/runtime/natStackTrace.cc b/libjava/gnu/gcj/runtime/natStackTrace.cc
index 5e5aed87e5c..d9f3355c046 100644
--- a/libjava/gnu/gcj/runtime/natStackTrace.cc
+++ b/libjava/gnu/gcj/runtime/natStackTrace.cc
@@ -45,6 +45,11 @@ details. */
#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 @@ gnu::gcj::runtime::StackTrace::fillInStackTrace (jint maxlen, jint offset)
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,44 @@ gnu::gcj::runtime::StackTrace::fillInStackTrace (jint maxlen, jint offset)
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))
{
- frame[n].interp = (void *) interp_frame->self;
- interp_frame = interp_frame->next;
+ // _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 (pc >= _Jv_StartOfInterpreter
+ && (pc < _Jv_EndOfInterpreter
+ || _Jv_EndOfInterpreter == NULL))
+ {
+ if (_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.
+ _Jv_EndOfInterpreter = pc;
+ }
+ }
}
- else
- frame[n].interp = 0;
#endif // INTERPRETER
+
}
}
else
diff --git a/libjava/interpret.cc b/libjava/interpret.cc
index c5d2afdb905..332833b4454 100644
--- a/libjava/interpret.cc
+++ b/libjava/interpret.cc
@@ -774,46 +774,17 @@ _Jv_InterpMethod::compile (const void * const *insn_targets)
}
#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;
- // 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;
-
- _Jv_word locals[max_locals];
-
- /* Go straight at it! the ffi raw format matches the internal
- stack representation exactly. At least, that's the idea.
- */
- memcpy ((void*) locals, (void*) args, args_raw_size);
-
- _Jv_word *pool_data = defining_class->constants.data;
-
- /* These three are temporaries for common code used by several
- instructions. */
- void (*fun)();
- _Jv_ResolvedMethod* rmeth;
- int tmpval;
-
#define INSN_LABEL(op) &&insn_##op
static const void *const insn_target[] =
@@ -1027,6 +998,41 @@ _Jv_InterpMethod::run (void *retp, ffi_raw *args)
0
};
+ // 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.
+ if (_Jv_StartOfInterpreter == NULL)
+ _Jv_StartOfInterpreter = _Unwind_FindEnclosingFunction ((void *) insn_target[0]);
+
+ // 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;
+
+ _Jv_word locals[max_locals];
+
+ /* Go straight at it! the ffi raw format matches the internal
+ stack representation exactly. At least, that's the idea.
+ */
+ memcpy ((void*) locals, (void*) args, args_raw_size);
+
+ _Jv_word *pool_data = defining_class->constants.data;
+
+ /* These three are temporaries for common code used by several
+ instructions. */
+ void (*fun)();
+ _Jv_ResolvedMethod* rmeth;
+ int tmpval;
+
pc_t pc;
#ifdef DIRECT_THREADED
@@ -3227,13 +3233,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
throw_internal_error (char *msg)
{