[kaffe] -O4 jit3 problem
Patrick Tullmann
tullmann@cs.utah.edu
Tue, 4 Jun 2002 00:04:46 -0600
I wrote:
> Tim wrote:
> > What about using local labels in END_EXCEPTION_HANDLING?
>
> Ah! That's probably exactly what is needed. I was hoping there was
> some GCC way of handling this.
Seems to work, too!
The attached patch lets optimized versions of Kaffe pass all(*) the
built-in regression tests. In fact, it should improve odd corner
cases a bit, as now Kaffe_JNI exception handlers cover only the code
they should.
(*) InternHog seems to fail in the (non-optimized) interp-debug builds
now. Of course, I can't get it to fail when run under GDB... Bah!
I'll keep poking at that one.
In figuring out how the vmException code was used, I discovered that
half of the fields were only used in the interpreter, and half only
used in the Kaffe_JNI entrypoints, so I updated the struct to use a
union (saves 8 bytes per vmException! :). I also renamed
'vmException' to 'VmExceptHandler' and hid the accesses to the struct
behind inline functions (mostly to get a lot of asserts in).
I'm not entirely confident in this change, because I haven't looked to
see which tests (if any) actually stress this code. I'll look more
closely at this, too.
Anyway, if anyone has comments on the patch let me know. JIM, let me
know if you think this is safe to check in, and I will...
-Pat
----- ----- ---- --- --- -- - - - - -
Pat Tullmann tullmann@cs.utah.edu
Ignorance more frequently begets confidence than does knowledge.
diff -u -r -N --exclude=CVS --exclude=.* --exclude=DEAD --exclude=Makefile.in --exclude=configure pure/kaffe/kaffevm/classMethod.c optjit/kaffe/kaffevm/classMethod.c
--- pure/kaffe/kaffevm/classMethod.c Thu May 30 12:06:19 2002
+++ optjit/kaffe/kaffevm/classMethod.c Mon Jun 3 20:25:58 2002
@@ -1559,6 +1559,7 @@
return true;
}
+#if defined(TRANSLATOR)
/*
* When do we need a trampoline?
*
@@ -1604,6 +1605,9 @@
}
return (false);
}
+#endif /* TRANSLATOR */
+
+
/*
* Build a trampoline if necessary, return the address of the native code
diff -u -r -N --exclude=CVS --exclude=.* --exclude=DEAD --exclude=Makefile.in --exclude=configure pure/kaffe/kaffevm/exception.c optjit/kaffe/kaffevm/exception.c
--- pure/kaffe/kaffevm/exception.c Thu May 30 12:06:19 2002
+++ optjit/kaffe/kaffevm/exception.c Mon Jun 3 22:57:20 2002
@@ -37,6 +37,7 @@
#include "machine.h"
#include "slots.h"
#include "gcj/gcj.h"
+#include "kaffe_jni.h"
#if defined(INTERPRETER)
#define FIRSTFRAME(f, e) /* Does nothing */
@@ -48,8 +49,6 @@
static void floatingException(struct _exceptionFrame *);
static void dispatchException(Hjava_lang_Throwable*, stackTraceInfo*) __NORETURN__;
-extern void Kaffe_JNIExceptionHandler(void);
-
extern void printStackTrace(struct Hjava_lang_Throwable*, struct Hjava_lang_Object*, int);
static bool findExceptionBlockInMethod(uintp, Hjava_lang_Class*, Method*, exceptionInfo*);
@@ -297,9 +296,9 @@
return (0);
}
#endif
-#else
- vmException* nfm;
- nfm = ((vmException*)fm)->prev;
+#else /* INTERPRETER */
+ VmExceptHandler* nfm;
+ nfm = ((VmExceptHandler*)fm)->prev;
return (nfm);
#endif
}
@@ -330,8 +329,22 @@
meth = findExceptionInMethod(frame->pc, class, &einfo);
- if (einfo.method == 0 && IS_IN_JNI_RANGE(frame->pc)) {
- Kaffe_JNIExceptionHandler();
+ assert(meth == einfo.method);
+
+ /*
+ * If no exception block found in method, perhaps
+ * it is a Kaffe_JNI entrypoint?
+ */
+ if (einfo.method == 0)
+ {
+ VmExceptHandler* ebuf = (VmExceptHandler*)(unhand(getCurrentThread())->exceptPtr);
+ if ((ebuf != 0)
+ && vmExcept_isJNIFrame(ebuf)
+ && vmExcept_JNIContains(ebuf, frame->pc))
+ {
+ /* Does not return. */
+ Kaffe_JNIExceptionHandler(ebuf);
+ }
}
/* Find the sync. object */
@@ -404,18 +417,21 @@
{
Hjava_lang_Object* obj;
exceptionInfo einfo;
- vmException* frame;
+ VmExceptHandler* frame;
bool res;
- for (frame = (vmException*)unhand(ct)->exceptPtr; frame != 0; frame = frame->prev) {
+ for (frame = (VmExceptHandler*)unhand(ct)->exceptPtr; frame != 0; frame = frame->prev) {
- if (frame->meth == (Method*)1) {
+ if (vmExcept_isJNIFrame(frame)) {
unhand(ct)->exceptPtr = (struct Hkaffe_util_Ptr*)frame;
- Kaffe_JNIExceptionHandler();
+ Kaffe_JNIExceptionHandler(frame); /* No Return */
}
/* Look for handler */
- res = findExceptionBlockInMethod(frame->pc, eobj->base.dtable->class, frame->meth, &einfo);
+ res = findExceptionBlockInMethod(frame->frame.intrp.pc,
+ eobj->base.dtable->class,
+ frame->meth,
+ &einfo);
/* Find the sync. object */
if (einfo.method == 0 || (einfo.method->accflags & ACC_SYNCHRONISED) == 0) {
@@ -425,14 +441,14 @@
obj = &einfo.class->head;
}
else {
- obj = frame->mobj;
+ obj = vmExcept_getSyncobj(frame);
}
/* If handler found, call it */
if (res == true) {
unhand(ct)->needOnStack = STACK_HIGH;
- frame->pc = einfo.handler;
- JTHREAD_LONGJMP(JTHREAD_ACCESS_JMPBUF(frame, jbuf), 1);
+ vmExcept_setPC(frame, einfo.handler);
+ vmExcept_jumpToHandler(frame); /* Does not return */
}
/* If not here, exit monitor if synchronised. */
@@ -569,6 +585,9 @@
/*
* Look for exception block in method.
* Returns true if there is an exception handler, false otherwise.
+ *
+ * Passed 'pc' is the program counter where the exception entered
+ * the current frame (the 'throw' or from a nested method call).
*/
static bool
findExceptionBlockInMethod(uintp pc, Hjava_lang_Class* class, Method* ptr, exceptionInfo* info)
diff -u -r -N --exclude=CVS --exclude=.* --exclude=DEAD --exclude=Makefile.in --exclude=configure pure/kaffe/kaffevm/exception.h optjit/kaffe/kaffevm/exception.h
--- pure/kaffe/kaffevm/exception.h Thu May 30 12:06:19 2002
+++ optjit/kaffe/kaffevm/exception.h Mon Jun 3 22:50:03 2002
@@ -13,6 +13,23 @@
#include "config-setjmp.h"
+/*
+ * Values for Thread.needOnStack. This variable
+ * says how many bytes need to be left on the stack when entering a function
+ * call. When throwing a StackOverflowException, this variable is set to
+ * STACK_LOW to have enough space to create the StackOverflowError --- if
+ * the error is caught, we set it back to STACK_HIGH.
+ */
+#define STACK_HIGH (8*1024)
+#define STACK_LOW 256
+
+/* XXX Why is this here? Its duplicated in a number of places. */
+#if defined(__WIN32__)
+#define SIG_T void(*)()
+#else
+#define SIG_T void*
+#endif
+
struct _exceptionFrame;
struct Hjava_lang_Class;
struct Hjava_lang_Object;
@@ -36,13 +53,46 @@
jexceptionEntry entry[1];
} jexception;
-typedef struct _vmException {
- struct _vmException* prev;
- JTHREAD_DECLARE_JMPBUF (jbuf);
+/*
+ * A VmExceptHandle is used to handle *any* exception in native code
+ * in the core of the VM. Set up when entering Kaffe_JNI methods, or
+ * when callMethodA or callMethodV are invoked.
+ *
+ * Each thread in the system has a exceptPtr, which points
+ * to the most recent VmExceptHandler buffer (the buffers
+ * are chained throught the 'prev' field.)
+ *
+ * In the interpreter *every frame* has a VmExceptHandler
+ * associated with it, this is used for catching exceptions at
+ * each interpreter stack frame and unlocking synchronized
+ * objects if necessary.
+ */
+typedef struct VmExceptHandler {
+ struct VmExceptHandler* prev;
struct _methods* meth;
- u4 pc;
- struct Hjava_lang_Object* mobj;
-} vmException;
+ union
+ {
+ /* Only valid if meth == VMEXCEPTHANDLER_KAFFEJNI_HANDLER */
+ struct
+ {
+ const void* start;
+ const void* end;
+ } jni;
+ /*
+ * Only valid if meth != 0 && meth != VMEXCEPTHANDLER_KAFFEJNI_HANDLER
+ *
+ * XXX Only used in the interpreter...
+ */
+ struct
+ {
+ struct Hjava_lang_Object* syncobj;
+ u4 pc;
+ } intrp;
+ } frame;
+ JTHREAD_DECLARE_JMPBUF (jbuf);
+} VmExceptHandler;
+
+#define VMEXCEPTHANDLER_KAFFEJNI_HANDLER ((struct _methods*)1)
struct _exceptionFrame;
@@ -56,26 +106,118 @@
struct Hjava_lang_Throwable *eobj);
void unhandledException(struct Hjava_lang_Throwable *eobj) __NORETURN__;
-extern uintp Kaffe_JNI_estart;
-extern uintp Kaffe_JNI_eend;
-#define IS_IN_JNI_RANGE(pc) ((pc) >= Kaffe_JNI_estart && (pc) < Kaffe_JNI_eend)
-
extern void initExceptions(void);
-#if defined(__WIN32__)
-#define SIG_T void(*)()
-#else
-#define SIG_T void*
+static inline bool vmExcept_isJNIFrame(VmExceptHandler* eh) __UNUSED__;
+static inline bool vmExcept_JNIContains(VmExceptHandler* eh, void *pc) __UNUSED__;
+static inline void vmExcept_setJNIFrame(VmExceptHandler* eh, const void* start, const void* end) __UNUSED__;
+static inline struct _methods* vmExcept_getMeth(VmExceptHandler* eh) __UNUSED__;
+static inline void vmExcept_setMeth(VmExceptHandler* eh, struct _methods* m) __UNUSED__;
+static inline void vmExcept_setSyncobj(VmExceptHandler* eh, struct Hjava_lang_Object* syncobj) __UNUSED__;
+static inline struct Hjava_lang_Object* vmExcept_getSyncobj(VmExceptHandler* eh) __UNUSED__;
+static inline void vmExcept_setPC(volatile VmExceptHandler* eh, u4 pc) __UNUSED__;
+static inline u4 vmExcept_getPC(const VmExceptHandler* eh) __UNUSED__;
+static inline void vmExcept_jumpToHandler(VmExceptHandler* frame) __UNUSED__ __NORETURN__;
+
+static inline bool
+vmExcept_isJNIFrame(VmExceptHandler* eh)
+{
+ assert(eh);
+ return (eh->meth == VMEXCEPTHANDLER_KAFFEJNI_HANDLER);
+}
+
+static inline bool
+vmExcept_JNIContains(VmExceptHandler* eh, void *pc)
+{
+ assert(eh);
+ assert(eh->meth == VMEXCEPTHANDLER_KAFFEJNI_HANDLER);
+ assert(pc);
+
+ return (eh->frame.jni.start <= pc)
+ && (eh->frame.jni.end > pc);
+}
+
+static inline void
+vmExcept_jumpToHandler(VmExceptHandler* frame)
+{
+ JTHREAD_LONGJMP(JTHREAD_ACCESS_JMPBUF(frame, jbuf), 1);
+}
+
+static inline void
+vmExcept_setJNIFrame(VmExceptHandler* eh, const void* start, const void* end)
+{
+ assert(eh);
+ assert(start != 0);
+ assert(start < end);
+
+ eh->meth = VMEXCEPTHANDLER_KAFFEJNI_HANDLER;
+ eh->frame.jni.start = start;
+ eh->frame.jni.end = end;
+}
+
+static inline void
+vmExcept_setIntrpFrame(VmExceptHandler* eh, u4 pc, struct _methods* meth, struct Hjava_lang_Object* syncobj)
+{
+ assert(eh);
+ assert(meth);
+
+ eh->meth = meth;
+ eh->frame.intrp.pc = pc;
+ eh->frame.intrp.syncobj = syncobj;
+}
+
+static inline void
+vmExcept_setSyncobj(VmExceptHandler* eh, struct Hjava_lang_Object* syncobj)
+{
+ assert(eh);
+ assert(eh->meth != 0);
+ assert(eh->meth != VMEXCEPTHANDLER_KAFFEJNI_HANDLER);
+ eh->frame.intrp.syncobj = syncobj;
+}
+
+static inline struct Hjava_lang_Object*
+vmExcept_getSyncobj(VmExceptHandler* eh)
+{
+ assert(eh);
+ assert(eh->meth != 0);
+ assert(eh->meth != VMEXCEPTHANDLER_KAFFEJNI_HANDLER);
+ return eh->frame.intrp.syncobj;
+}
+
+static inline void
+vmExcept_setMeth(VmExceptHandler* eh, struct _methods* meth)
+{
+ assert(eh);
+ assert(meth);
+ eh->meth = meth;
+}
+
+static inline struct _methods*
+vmExcept_getMeth(VmExceptHandler* eh)
+{
+ assert(eh);
+ return eh->meth;
+}
+
+static inline void
+vmExcept_setPC(volatile VmExceptHandler* eh, u4 pc)
+{
+ assert(eh);
+ assert(eh->meth != 0);
+ assert(eh->meth != VMEXCEPTHANDLER_KAFFEJNI_HANDLER);
+ eh->frame.intrp.pc = pc;
+}
+
+static inline u4
+vmExcept_getPC(const VmExceptHandler* eh)
+{
+ assert(eh);
+ assert(eh->meth != 0);
+ assert(eh->meth != VMEXCEPTHANDLER_KAFFEJNI_HANDLER);
+ return eh->frame.intrp.pc;
+}
+
#endif
-/*
- * Values for Thread.needOnStack. This variable
- * says how many bytes need to be left on the stack when entering a function
- * call. When throwing a StackOverflowException, this variable is set to
- * STACK_LOW to have enough space to create the StackOverflowError --- if
- * the error is caught, we set it back to STACK_HIGH.
- */
-#define STACK_HIGH (8*1024)
-#define STACK_LOW 256
-#endif
+
diff -u -r -N --exclude=CVS --exclude=.* --exclude=DEAD --exclude=Makefile.in --exclude=configure pure/kaffe/kaffevm/intrp/machine.c optjit/kaffe/kaffevm/intrp/machine.c
--- pure/kaffe/kaffevm/intrp/machine.c Sun Jun 17 10:39:34 2001
+++ optjit/kaffe/kaffevm/intrp/machine.c Mon Jun 3 21:09:05 2002
@@ -84,14 +84,14 @@
int profFlag; /* flag to control profiling */
#endif
-void runVirtualMachine(methods *meth, slots *lcl, slots *sp, uintp npc, slots *retval, volatile vmException *mjbuf, Hjava_lang_Thread *tid);
+void runVirtualMachine(methods *meth, slots *lcl, slots *sp, uintp npc, slots *retval, volatile VmExceptHandler *mjbuf, Hjava_lang_Thread *tid);
void
virtualMachine(methods*volatile meth, slots* volatile arg, slots* volatile retval, Hjava_lang_Thread* volatile tid)
{
methods *volatile const vmeth = meth;
Hjava_lang_Object* volatile mobj;
- vmException mjbuf;
+ VmExceptHandler mjbuf;
accessFlags methaccflags;
slots* volatile lcl;
@@ -168,11 +168,9 @@
/* If we have any exception handlers we must prepare to catch them.
* We also need to catch if we are synchronised (so we can release it).
*/
- mjbuf.pc = 0;
- mjbuf.mobj = mobj;
- mjbuf.meth = meth;
+ vmExcept_setIntrpFrame(&mjbuf, 0, meth, mobj);
if (tid != NULL && unhand(tid)->PrivateInfo != 0) {
- mjbuf.prev = (vmException*)unhand(tid)->exceptPtr;
+ mjbuf.prev = (VmExceptHandler*)unhand(tid)->exceptPtr;
unhand(tid)->exceptPtr = (struct Hkaffe_util_Ptr*)&mjbuf;
}
@@ -180,7 +178,7 @@
if (JTHREAD_SETJMP(mjbuf.jbuf) != 0) {
meth = vmeth;
unhand(tid)->exceptPtr = (struct Hkaffe_util_Ptr*)&mjbuf;
- npc = mjbuf.pc;
+ npc = vmExcept_getPC(&mjbuf);
sp = &lcl[meth->localsz];
#if defined(DEBUG)
{
@@ -219,11 +217,13 @@
}
/* this lock is safe for Thread.stop() */
lockObject(mobj);
- /* We must store the object on which we synchronized in
- * the mjbuf chain or else the exception handler routine
- * won't find it.
+
+ /*
+ * We must store the object on which we synchronized
+ * in the mjbuf chain for the exception handler
+ * routine to find it (and unlock it when unwinding).
*/
- mjbuf.mobj = mobj;
+ vmExcept_setSyncobj(&mjbuf, mobj);
}
sp = &lcl[meth->localsz - 1];
@@ -242,7 +242,7 @@
RDBG( dprintf("Returning from method %s%s.\n", meth->name->data, METHOD_SIGD(meth)); )
}
-void runVirtualMachine(methods *meth, slots *lcl, slots *sp, uintp npc, slots *retval, volatile vmException *mjbuf, Hjava_lang_Thread *tid) {
+void runVirtualMachine(methods *meth, slots *lcl, slots *sp, uintp npc, slots *retval, volatile VmExceptHandler *mjbuf, Hjava_lang_Thread *tid) {
bytecode *code = (bytecode*)meth->c.bcode.code;
/* Misc machine variables */
@@ -268,7 +268,7 @@
register uintp pc = npc;
assert(npc < meth->c.bcode.codelen);
- mjbuf->pc = pc;
+ vmExcept_setPC(mjbuf, pc);
npc = pc + insnLen[code[pc]];
switch (code[pc]) {
diff -u -r -N --exclude=CVS --exclude=.* --exclude=DEAD --exclude=Makefile.in --exclude=configure pure/kaffe/kaffevm/jni.c optjit/kaffe/kaffevm/jni.c
--- pure/kaffe/kaffevm/jni.c Thu May 30 12:06:20 2002
+++ optjit/kaffe/kaffevm/jni.c Mon Jun 3 23:04:10 2002
@@ -47,6 +47,7 @@
#include "machine.h"
#include "feedback.h"
#endif
+#include "kaffe_jni.h"
/*
* Define the version of JNI we support.
@@ -83,31 +84,40 @@
/*
* Define how we handle exceptions in JNI.
*
- * XXX variable declarations in macros are nasty.
+ * Each BEGIN_EXCEPTION_HANDLING macro must be matched by an
+ * END_EXCEPTION_HANDLING macro call in the same scope. Each should
+ * be used only once in a given JNI entrypoint.
+ *
+ * Yes, that's a "&&" to get the address of a label. See:
+ * http://gcc.gnu.org/onlinedocs/gcc/Local-Labels.html#Local%20Labels
+ * http://gcc.gnu.org/onlinedocs/gcc/Labels-as-Values.html#Labels%20as%20Values
*/
#define BEGIN_EXCEPTION_HANDLING(X) \
- vmException ebuf; \
- ebuf.prev = (vmException*)unhand(getCurrentThread())->exceptPtr;\
- ebuf.meth = (Method*)1; \
- if (JTHREAD_SETJMP(ebuf.jbuf) != 0) { \
+ VmExceptHandler ebuf; \
+ vmExcept_setJNIFrame(&ebuf, &&start_label, &&end_label); \
+ ebuf.prev = (VmExceptHandler*)(unhand(getCurrentThread())->exceptPtr);\
+ if (JTHREAD_SETJMP(JTHREAD_ACCESS_JMPBUF(&ebuf, jbuf)) != 0) { \
unhand(getCurrentThread())->exceptPtr = \
(struct Hkaffe_util_Ptr*)ebuf.prev; \
return X; \
} \
+ start_label: \
unhand(getCurrentThread())->exceptPtr = (struct Hkaffe_util_Ptr*)&ebuf
#define BEGIN_EXCEPTION_HANDLING_VOID() \
- vmException ebuf; \
- ebuf.prev = (vmException*)unhand(getCurrentThread())->exceptPtr;\
- ebuf.meth = (Method*)1; \
- if (JTHREAD_SETJMP(ebuf.jbuf) != 0) { \
+ VmExceptHandler ebuf; \
+ vmExcept_setJNIFrame(&ebuf, &&start_label, &&end_label); \
+ ebuf.prev = (VmExceptHandler*)(unhand(getCurrentThread())->exceptPtr);\
+ if (JTHREAD_SETJMP(JTHREAD_ACCESS_JMPBUF(&ebuf, jbuf)) != 0) { \
unhand(getCurrentThread())->exceptPtr = \
(struct Hkaffe_util_Ptr*)ebuf.prev; \
return; \
} \
+ start_label: \
unhand(getCurrentThread())->exceptPtr = (struct Hkaffe_util_Ptr*)&ebuf
#define END_EXCEPTION_HANDLING() \
+ end_label: \
unhand(getCurrentThread())->exceptPtr = (struct Hkaffe_util_Ptr*)ebuf.prev
/*
@@ -118,9 +128,6 @@
#define GET_STATIC_FIELD(T,F) *(T*)FIELD_ADDRESS((Field*)F)
#define SET_STATIC_FIELD(T,F,V) *(T*)FIELD_ADDRESS((Field*)F) = (V)
-uintp Kaffe_JNI_estart;
-uintp Kaffe_JNI_eend;
-
extern struct JNINativeInterface Kaffe_JNINativeInterface;
extern JavaVMInitArgs Kaffe_JavaVMInitArgs;
extern JavaVM Kaffe_JavaVM;
@@ -133,7 +140,6 @@
static void Kaffe_wrapper(Method* xmeth, void* func, bool use_JNI);
#endif
-void Kaffe_JNIExceptionHandler(void);
static jint Kaffe_GetVersion(JNIEnv*);
static jclass Kaffe_FindClass(JNIEnv*, const char*);
static jint Kaffe_ThrowNew(JNIEnv*, jclass, const char*);
@@ -166,10 +172,6 @@
Kaffe_JavaVMArgs[0] = *args;
initialiseKaffe();
- /* Setup the JNI Exception handler */
- Kaffe_JNI_estart = (uintp)&Kaffe_GetVersion; /* First routine */
- Kaffe_JNI_eend = (uintp)&Kaffe_JNIExceptionHandler; /* Last routine */
-
/* Setup JNI for main thread */
#if defined(NEED_JNIREFS)
unhand(getCurrentThread())->jnireferences = gc_malloc(sizeof(jnirefs), &gcNormal);
@@ -3493,18 +3495,10 @@
* Handle exceptions which fall back to the JNI layer.
*/
void
-Kaffe_JNIExceptionHandler(void)
+Kaffe_JNIExceptionHandler(VmExceptHandler* frame)
{
- vmException* frame;
-
- frame = (vmException*)unhand(getCurrentThread())->exceptPtr;
- if (frame) {
- /* Worry about window around BEGIN and END exception
- * handling, as well as functions which only delay
- * external exceptions.
- */
- JTHREAD_LONGJMP(JTHREAD_ACCESS_JMPBUF(frame, jbuf), 1);
- }
+ assert(frame != 0);
+ vmExcept_jumpToHandler(frame);
}
/*
diff -u -r -N --exclude=CVS --exclude=.* --exclude=DEAD --exclude=Makefile.in --exclude=configure pure/kaffe/kaffevm/kaffe_jni.h optjit/kaffe/kaffevm/kaffe_jni.h
--- pure/kaffe/kaffevm/kaffe_jni.h Wed Dec 31 17:00:00 1969
+++ optjit/kaffe/kaffevm/kaffe_jni.h Mon Jun 3 20:44:20 2002
@@ -0,0 +1,21 @@
+/*
+ * kaffe_jni.h
+ * Prototypes for jni.c methods used elsewhere
+ *
+ * Copyright (c) 2002
+ * Pat Tullmann <pat@tullmann.org>. All rights reserved.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file.
+ */
+
+#ifndef KAFFE_KAFFEVM_KAFFE_JNI_H
+#define KAFFE_KAFFEVM_KAFFE_JNI_H
+
+#include "config.h"
+
+struct VmExceptHandler; /* exception.h */
+
+extern void Kaffe_JNIExceptionHandler(struct VmExceptHandler* handler) __NORETURN__;
+
+#endif /* KAFFE_KAFFEVM_KAFFE_JNI_H */
diff -u -r -N --exclude=CVS --exclude=.* --exclude=DEAD --exclude=Makefile.in --exclude=configure pure/kaffe/kaffevm/stackTrace.h optjit/kaffe/kaffevm/stackTrace.h
--- pure/kaffe/kaffevm/stackTrace.h Fri Jun 16 11:47:13 2000
+++ optjit/kaffe/kaffevm/stackTrace.h Mon Jun 3 22:46:48 2002
@@ -26,7 +26,7 @@
#if defined(INTERPRETER)
typedef struct _stackTrace {
- vmException* frame;
+ VmExceptHandler* frame;
} stackTrace;
/* Dummy exceptionFrame */
@@ -34,13 +34,13 @@
char dummy;
};
-#define STACKTRACEINIT(S,I,O,R) ((S).frame = (vmException*)unhand(getCurrentThread())->exceptPtr)
+#define STACKTRACEINIT(S,I,O,R) ((S).frame = (VmExceptHandler*)unhand(getCurrentThread())->exceptPtr)
#define STACKTRACESTEP(S) ((S).frame = nextFrame((S).frame))
-#define STACKTRACEPC(S) ((S).frame->pc)
+#define STACKTRACEPC(S) (vmExcept_getPC((S).frame))
#define STACKTRACEFP(S) (0)
-#define STACKTRACEMETHCREATE(S) ((S).frame->meth)
+#define STACKTRACEMETHCREATE(S) (vmExcept_getMeth((S).frame))
#define STACKTRACEEND(S) ((S).frame == 0)
-#define STACKTRACESKIP(S) ((S).frame->meth == (Method*)1)
+#define STACKTRACESKIP(S) (vmExcept_isJNIFrame((S).frame))
#elif defined(TRANSLATOR)
diff -u -r -N --exclude=CVS --exclude=.* --exclude=DEAD --exclude=Makefile.in --exclude=configure pure/kaffe/kaffevm/support.c optjit/kaffe/kaffevm/support.c
--- pure/kaffe/kaffevm/support.c Thu May 30 12:06:20 2002
+++ optjit/kaffe/kaffevm/support.c Mon Jun 3 21:07:17 2002
@@ -529,7 +529,7 @@
}
else {
Hjava_lang_Object* syncobj = 0;
- vmException mjbuf;
+ VmExceptHandler mjbuf;
Hjava_lang_Thread* tid = getCurrentThread();
if (meth->accflags & ACC_SYNCHRONISED) {
@@ -542,11 +542,9 @@
lockObject(syncobj);
}
- mjbuf.pc = 0;
- mjbuf.mobj = syncobj;
- mjbuf.meth = meth;
+ vmExcept_setIntrpFrame(&mjbuf, 0, meth, syncobj);
if (tid != NULL && unhand(tid)->PrivateInfo != 0) {
- mjbuf.prev = (vmException*)unhand(tid)->exceptPtr;
+ mjbuf.prev = (VmExceptHandler*)unhand(tid)->exceptPtr;
unhand(tid)->exceptPtr = (struct Hkaffe_util_Ptr*)&mjbuf;
}
@@ -747,7 +745,7 @@
}
else {
Hjava_lang_Object* syncobj = 0;
- vmException mjbuf;
+ VmExceptHandler mjbuf;
Hjava_lang_Thread* tid = getCurrentThread();
if (meth->accflags & ACC_SYNCHRONISED) {
@@ -760,11 +758,9 @@
lockObject(syncobj);
}
- mjbuf.pc = 0;
- mjbuf.mobj = syncobj;
- mjbuf.meth = meth;
+ vmExcept_setIntrpFrame(&mjbuf, 0, meth, syncobj);
if (tid != NULL && unhand(tid)->PrivateInfo != 0) {
- mjbuf.prev = (vmException*)unhand(tid)->exceptPtr;
+ mjbuf.prev = (VmExceptHandler*)unhand(tid)->exceptPtr;
unhand(tid)->exceptPtr = (struct Hkaffe_util_Ptr*)&mjbuf;
}
diff -u -r -N --exclude=CVS --exclude=.* --exclude=DEAD --exclude=Makefile.in --exclude=configure pure/kaffe/kaffevm/thread.c optjit/kaffe/kaffevm/thread.c
--- pure/kaffe/kaffevm/thread.c Tue Dec 19 19:40:33 2000
+++ optjit/kaffe/kaffevm/thread.c Sun Apr 28 17:55:25 2002
@@ -357,7 +357,7 @@
/* note that since exception.c does not allow JNI to catch
* ThreadDeath (for now!), we won't see ThreadDeath here.
- * That is, we must invoke the uncaughtException paper
+ * That is, we must invoke the uncaughtException method
* if we see an exception here.
*/
eobj = (*env)->ExceptionOccurred(env);