diff options
author | tromey <tromey@138bc75d-0d04-0410-961f-82ee72b054a4> | 2002-08-29 17:53:28 +0000 |
---|---|---|
committer | tromey <tromey@138bc75d-0d04-0410-961f-82ee72b054a4> | 2002-08-29 17:53:28 +0000 |
commit | 3196bed74979360646cbc8418db5c86c0527ced4 (patch) | |
tree | 538202560a3a2f376b6fb55ee3b836b195f01e73 | |
parent | 1153c2dcea1d760a4e4503c103995e48d5399800 (diff) | |
download | gcc-3196bed74979360646cbc8418db5c86c0527ced4.tar.gz |
* 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.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@56657 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r-- | libjava/ChangeLog | 21 | ||||
-rw-r--r-- | libjava/gnu/gcj/runtime/NameFinder.java | 11 | ||||
-rw-r--r-- | libjava/gnu/gcj/runtime/natNameFinder.cc | 40 | ||||
-rw-r--r-- | libjava/include/java-interp.h | 24 | ||||
-rw-r--r-- | libjava/include/jvm.h | 14 | ||||
-rw-r--r-- | libjava/interpret.cc | 26 | ||||
-rw-r--r-- | libjava/java/lang/Thread.java | 5 | ||||
-rw-r--r-- | libjava/java/lang/natVMThrowable.cc | 30 |
8 files changed, 160 insertions, 11 deletions
diff --git a/libjava/ChangeLog b/libjava/ChangeLog index 442350028cf..8d8f248bed3 100644 --- a/libjava/ChangeLog +++ b/libjava/ChangeLog @@ -1,3 +1,24 @@ +2002-08-29 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. + 2002-08-28 Tom Tromey <tromey@redhat.com> * java/lang/Class.h: Include Package.h. diff --git a/libjava/gnu/gcj/runtime/NameFinder.java b/libjava/gnu/gcj/runtime/NameFinder.java index 60f47ac64fe..f32ebe0f530 100644 --- a/libjava/gnu/gcj/runtime/NameFinder.java +++ b/libjava/gnu/gcj/runtime/NameFinder.java @@ -173,17 +173,26 @@ public class NameFinder 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) diff --git a/libjava/gnu/gcj/runtime/natNameFinder.cc b/libjava/gnu/gcj/runtime/natNameFinder.cc index 42cc164c324..29488eddda7 100644 --- a/libjava/gnu/gcj/runtime/natNameFinder.cc +++ b/libjava/gnu/gcj/runtime/natNameFinder.cc @@ -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 @@ details. */ #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 @@ details. */ 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 @@ gnu::gcj::runtime::NameFinder::dladdrLookup(RawData* addrs, jint n) 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)) @@ -82,3 +84,29 @@ gnu::gcj::runtime::NameFinder::dladdrLookup(RawData* addrs, jint n) #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 +} diff --git a/libjava/include/java-interp.h b/libjava/include/java-interp.h index de1d88f452e..e3f96713ce7 100644 --- a/libjava/include/java-interp.h +++ b/libjava/include/java-interp.h @@ -13,6 +13,7 @@ details. */ #include <jvm.h> #include <java-cpool.h> +#include <gnu/gcj/runtime/NameFinder.h> #ifdef INTERPRETER @@ -138,6 +139,7 @@ class _Jv_InterpMethod : public _Jv_MethodBase friend class _Jv_ClassReader; friend class _Jv_BytecodeVerifier; + friend class gnu::gcj::runtime::NameFinder; friend void _Jv_PrepareClass(jclass); }; @@ -205,6 +207,28 @@ public: } }; +// 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; + } +}; + #endif /* INTERPRETER */ #endif /* __JAVA_INTERP_H__ */ diff --git a/libjava/include/jvm.h b/libjava/include/jvm.h index fc3a7f73ecf..e02901de824 100644 --- a/libjava/include/jvm.h +++ b/libjava/include/jvm.h @@ -111,6 +111,20 @@ union _Jv_word2 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. diff --git a/libjava/interpret.cc b/libjava/interpret.cc index e5c40cff150..d231387dc9a 100644 --- a/libjava/interpret.cc +++ b/libjava/interpret.cc @@ -22,7 +22,6 @@ details. */ #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 @@ details. */ #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 @@ _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) +{ +} + 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; @@ -3169,6 +3186,13 @@ _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) { diff --git a/libjava/java/lang/Thread.java b/libjava/java/lang/Thread.java index af5b95f14c6..64d58dda080 100644 --- a/libjava/java/lang/Thread.java +++ b/libjava/java/lang/Thread.java @@ -10,6 +10,8 @@ details. */ package java.lang; +import gnu.gcj.RawData; + /** * @author Tom Tromey <tromey@cygnus.com> * @date August 24, 1998 @@ -311,6 +313,9 @@ public class Thread implements Runnable 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; } diff --git a/libjava/java/lang/natVMThrowable.cc b/libjava/java/lang/natVMThrowable.cc index 358bab7f13b..f5c56c7a1d4 100644 --- a/libjava/java/lang/natVMThrowable.cc +++ b/libjava/java/lang/natVMThrowable.cc @@ -26,6 +26,8 @@ details. */ #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 @@ java::lang::VMThrowable::fillInStackTrace (java::lang::Throwable* t) // 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; |