[kaffe] -O4 jit3 problem
Jim Pick
jim@kaffe.org
15 Jun 2002 09:20:11 -0700
Good work. I want to study it a bit more before I put it in though
(give me a day or two).
As for gcc - people have used MSVC with Kaffe in the past, but I don't
know of anybody who is currently using it (although one person did
express some interest in using it). Unfortunately, this change does
look like it would be very hard to duplicate in another compiler without
using the gcc feature for getting the address of a label.
I guess I'm more concerned that we've increased the size of the
exception structure on the stack for each JNI method call. Is there any
additional benefits in doing so, other than the fact that it solves a
build time issue (we need to figure out how to force the compiler/linker
to keep the functions together in the text segment)?
We could force the compiler/linker to keep all the functions together by
using GCC attributes and a linker script. The Linux kernel does this
for initcalls (see include/linux/init.h). It's a gcc extension, but it
could probably be done in such a way that it wouldn't break on other
compilers (providing, of course, they naturally keep the functions
together).
I do like some of the other bits of the patch.
Cheers,
- Jim
On Fri, 2002-06-14 at 17:16, Patrick Tullmann wrote:
> Tim wrote:
> > I had a little problem
> ...
> > in exception.h. The "assert(start < end);" needs to be changed to
> > "assert(start <= end);" otherwise it will fail if there are no
> > instructions between the start_label and end_label. Which seems to
> > happen with Kaffe_ExceptionOccurred() and if NEED_JNIREFS isn't
> > defined...
>
> Ah, good catch.
>
> I've updated the patch to do per-method native exception handlers to
> include Tim's fix, and to hide the GCC-isms behind "#if
> defined(__GNUC__)", as Gwenole Beauchesne pointed out.
>
> Note that with this patch, jni.c will *fail to compile* with an
> "#error" if its not being compiled with GCC. Looking at the sources,
> there is currently a lot of GCC-specific code (mostly asm's) in Kaffe.
> However, all of that stuff is kept off in the config/ tree, so the
> core of the VM is actually free of GCC-isms (I think).
>
> Is this a problem if Kaffe requires GCC? Anyone out there compile
> Kaffe with a non-gcc compiler?
>
> Note that the there is still a problem with intern'd strings and dead
> value arrays. (This patch tickles things just right so that InternHog
> in the intrp+debug version will fail.) At this point, I'm quite
> confident that that is a separate bug, and that Tim's suggestion to
> gcAddRef/gcRemRef on the underlying char array will at least fix the
> crashes. But that will be a separate patch.
>
> Anywhere, here is the latest patch. And a ChangeLog entry:
>
> Patrick Tullmann <pat@tullmann.org>
> * kaffe/kaffevm/classMethod.c: Compile methodNeedsTrampoline()
> in JIT only.
> * kaffe/kaffevm/exception.h: Replace VMException struct
> with VMExceptHandler, add accessors,
> * kaffe/kaffevm/exception.c: Use new VMExceptHandler struct in
> place of VMException, update test to see if a JNI handler is
> installed when dispatching exceptions
> * kaffe/kaffevm/intrp/machine.c: Use new VMExceptHandler and
> accessors
> * kaffe/kaffevm/jni.c: Use label-addresses to provide
> exception handler coverage for JNI entrypoints.
> * kaffe/kaffevm/kaffe_jni.h: New header JNI entrypoints used
> elsewhere in kaffevm.
> * kaffe/kaffevm/stackTrace.h: Use new VMExceptHandler.
> * kaffe/kaffevm/support.c: Use new VMExceptHandler.
>
> -Pat
>
> ----- ----- ---- --- --- -- - - - - -
> Pat Tullmann tullmann@cs.utah.edu
> Indifference may cause the downfall of mankind, but who really cares?
>
> 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 Wed May 29 16:58:43 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 Wed May 29 13:46:24 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 Wed May 29 13:46:24 2002
> +++ optjit/kaffe/kaffevm/exception.h Mon Jun 10 12:32:44 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 Wed May 29 16:58:44 2002
> +++ optjit/kaffe/kaffevm/jni.c Tue Jun 4 03:04:53 2002
> @@ -47,6 +47,7 @@
> #include "machine.h"
> #include "feedback.h"
> #endif
> +#include "kaffe_jni.h"
>
> /*
> * Define the version of JNI we support.
> @@ -80,34 +81,50 @@
> */
> #define JNI_METHOD_CODE(M) METHOD_INDIRECTMETHOD(M)
>
> +#if defined(__GNUC__)
> +/*
> + * Yes, that's a unary "&&" 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 LABEL_ADDR(x) (&&x)
> +#else
> +#error LABEL_ADDR Taking the address of a label is a GCC-extension to C
> +#endif
> +
> /*
> * 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.
> */
> #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, LABEL_ADDR(start_label), LABEL_ADDR(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, LABEL_ADDR(start_label), LABEL_ADDR(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 +135,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 +147,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 +179,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);
> @@ -198,8 +207,6 @@
> *
> * Everything from Kaffe_GetVersion to Kaffe_JNIExceptionHandler
> * should be bracketed with BEGIN and END _EXCEPTION_HANDLING.
> - * Question: what happens when an asynchronous exception occurs at the
> - * very start or end of one of these calls.
> */
> static void
> Kaffe_FatalError(JNIEnv* env, const char* mess)
> @@ -3493,18 +3500,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 Wed May 29 16:58:44 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;
> }
>
>
> _______________________________________________
> kaffe mailing list
> kaffe@kaffe.org
> http://kaffe.org/cgi-bin/mailman/listinfo/kaffe