aboutsummaryrefslogtreecommitdiff
path: root/libjava
diff options
context:
space:
mode:
authorTom Tromey <tromey@redhat.com>2002-08-29 17:53:28 +0000
committerTom Tromey <tromey@gcc.gnu.org>2002-08-29 17:53:28 +0000
commit3308c46e47a0b17d37b4c29a130e6519c424a737 (patch)
tree538202560a3a2f376b6fb55ee3b836b195f01e73 /libjava
parentce4e997039ab374d5d1719b02aae3ded0a2a8ec4 (diff)
downloadgcc-3308c46e47a0b17d37b4c29a130e6519c424a737.zip
gcc-3308c46e47a0b17d37b4c29a130e6519c424a737.tar.gz
gcc-3308c46e47a0b17d37b4c29a130e6519c424a737.tar.bz2
jvm.h (struct _Jv_frame_info): New structure.
* 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. From-SVN: r56657
Diffstat (limited to 'libjava')
-rw-r--r--libjava/ChangeLog21
-rw-r--r--libjava/gnu/gcj/runtime/NameFinder.java11
-rw-r--r--libjava/gnu/gcj/runtime/natNameFinder.cc40
-rw-r--r--libjava/include/java-interp.h24
-rw-r--r--libjava/include/jvm.h14
-rw-r--r--libjava/interpret.cc26
-rw-r--r--libjava/java/lang/Thread.java5
-rw-r--r--libjava/java/lang/natVMThrowable.cc30
8 files changed, 160 insertions, 11 deletions
diff --git a/libjava/ChangeLog b/libjava/ChangeLog
index 4423500..8d8f248 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 60f47ac..f32ebe0 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 42cc164..29488ed 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 de1d88f..e3f9671 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 fc3a7f7..e02901d 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 e5c40cf..d231387 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 af5b95f..64d58dd 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 358bab7..f5c56c7 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;