It is not possible to throw exceptions directly from jato functions
because we cannot unwind C functions. Instead we store the exception
pointer in current execution environment and set "exception_guard"
pointer to a hidden guard page. When control will be returned to jit
method the code will poll memory pointed by "exception_guard" and will
trigger SIGSEGV. The signal handler takes care of throwing the
exception.

Signed-off-by: Tomek Grabiec <tgrab...@gmail.com>
---
 include/jit/exception.h |   17 +++++++++++
 jit/exception.c         |   71 ++++++++++++++++++++++++++++++++++++++++------
 test/arch-x86/Makefile  |    1 +
 test/jit/Makefile       |    1 +
 vm/jato.c               |    5 ++-
 vm/signal.c             |   21 ++++++++++++-
 6 files changed, 103 insertions(+), 13 deletions(-)

diff --git a/include/jit/exception.h b/include/jit/exception.h
index 0c1ff5c..5bfce28 100644
--- a/include/jit/exception.h
+++ b/include/jit/exception.h
@@ -7,6 +7,17 @@
 struct compilation_unit;
 struct jit_stack_frame;
 
+/*
+ * This is a per-thread pointer to a memory location which should be
+ * polled by JIT code to check whether exception occurred. When
+ * exception is set this pointer will point to a hidden guard page
+ * which will trigger SIGSEGV on access. The signal handler will throw
+ * the exception then.
+ */
+extern __thread void *exception_guard;
+
+extern void *exceptions_guard_page;
+
 struct exception_table_entry *exception_find_entry(struct methodblock *,
                                                   unsigned long);
 
@@ -27,5 +38,11 @@ unsigned char *throw_exception(struct compilation_unit *cu,
                               struct object *exception);
 void throw_exception_from_signal(void *ctx, struct object *exception);
 void unwind(void);
+void signal_exception(struct object *obj);
+void clear_exception();
+struct object *exception_occurred();
+void init_exceptions();
+void thread_init_exceptions();
+
 
 #endif /* JATO_JIT_EXCEPTION_H */
diff --git a/jit/exception.c b/jit/exception.c
index 3f05dd6..a01d06a 100644
--- a/jit/exception.c
+++ b/jit/exception.c
@@ -30,11 +30,59 @@
 #include <jit/exception.h>
 #include <jit/compiler.h>
 
+#include <vm/guard-page.h>
 #include <vm/buffer.h>
+#include <vm/die.h>
+
 #include <arch/stack-frame.h>
 #include <arch/instruction.h>
 #include <errno.h>
 
+__thread void *exception_guard = NULL;
+void *exceptions_guard_page;
+
+void init_exceptions()
+{
+       exceptions_guard_page = alloc_guard_page();
+       if (!exceptions_guard_page)
+               die("%s: failed to allocate exceptions guard page.", __func__);
+
+       /* TODO: Should be called from thread initialization code. */
+       thread_init_exceptions();
+}
+
+/**
+ * thread_init_exceptions - initializes per-thread structures.
+ */
+void thread_init_exceptions()
+{
+       exception_guard = &exception_guard; /* assign a safe pointer */
+}
+
+/**
+ * signal_exception - used for signaling that exception has occurred in
+ *         jato functions.  Exception will be thrown as soon as
+ *         controll is returned back to JIT method code.
+ *
+ * @exception: exception object to be thrown.
+ */
+void signal_exception(struct object *exception)
+{
+       getExecEnv()->exception = exception;
+       exception_guard = exceptions_guard_page;
+}
+
+struct object *exception_occurred()
+{
+       return getExecEnv()->exception;
+}
+
+void clear_exception()
+{
+       exception_guard = &exception_guard;
+       getExecEnv()->exception = NULL;
+}
+
 struct exception_table_entry *exception_find_entry(struct methodblock *method,
                                                   unsigned long target)
 {
@@ -116,14 +164,16 @@ unsigned char *throw_exception_from(struct 
compilation_unit *cu,
                                    unsigned char *native_ptr,
                                    struct object *exception)
 {
-       unsigned char *eh_ptr = NULL;
+       struct object *ee_exception;
        unsigned long bc_offset;
+       unsigned char *eh_ptr;
+
+       eh_ptr = NULL;
 
-       if (getExecEnv()->exception != NULL) {
-               /* Looks like we've caught some asynchronous exception,
-                  which must have precedence. */
-               exception = getExecEnv()->exception;
-               getExecEnv()->exception = NULL;
+       ee_exception = exception_occurred();
+       if (ee_exception) {
+               exception = ee_exception;
+               clear_exception();
        }
 
        bc_offset = native_ptr_to_bytecode_offset(cu, native_ptr);
@@ -134,10 +184,11 @@ unsigned char *throw_exception_from(struct 
compilation_unit *cu,
        }
 
        if (!is_jit_method(frame->return_address)) {
-               /* No handler found within jitted method call
-                  chain. Set exception in execution environment and
-                  return to previous (not jit) method. */
-               getExecEnv()->exception = exception;
+               /*
+                * No handler found within jitted method call chain.
+                * Signal exception and return to previous (not jit) method.
+                */
+               signal_exception(exception);
                return bb_native_ptr(cu->exit_bb);
        }
 
diff --git a/test/arch-x86/Makefile b/test/arch-x86/Makefile
index c12e0c9..91e27c2 100644
--- a/test/arch-x86/Makefile
+++ b/test/arch-x86/Makefile
@@ -36,6 +36,7 @@ OBJS = \
        ../../vm/types.o \
        ../../vm/zalloc.o \
        ../../vm/radix-tree.o \
+       ../../vm/guard-page.o \
        ../../jit/alloc.o \
        ../../jit/basic-block.o \
        ../../jit/compilation-unit.o \
diff --git a/test/jit/Makefile b/test/jit/Makefile
index 4d26480..ab708fc 100644
--- a/test/jit/Makefile
+++ b/test/jit/Makefile
@@ -14,6 +14,7 @@ OBJS = \
        ../../vm/types.o \
        ../../vm/zalloc.o \
        ../../vm/radix-tree.o \
+       ../../vm/guard-page.o \
        ../../jit/alloc.o \
        ../../jit/arithmetic-bc.o \
        ../../jit/basic-block.o \
diff --git a/vm/jato.c b/vm/jato.c
index 3960196..34125dc 100644
--- a/vm/jato.c
+++ b/vm/jato.c
@@ -28,8 +28,10 @@
 #include <vm/natives.h>
 #include <vm/signal.h>
 #include <vm/vm.h>
-#include <jit/compiler.h>
+
 #include <jit/cu-mapping.h>
+#include <jit/exception.h>
+#include <jit/compiler.h>
 
 #ifdef USE_ZIP
 #define BCP_MESSAGE "<jar/zip files and directories separated by :>"
@@ -300,6 +302,7 @@ int main(int argc, char *argv[]) {
 
     setup_signal_handlers();
     init_cu_mapping();
+    init_exceptions();
 
     setDefaultInitArgs(&args);
     int class_arg = parseCommandLine(argc, argv, &args);
diff --git a/vm/signal.c b/vm/signal.c
index 0055ed1..af89c6e 100644
--- a/vm/signal.c
+++ b/vm/signal.c
@@ -59,10 +59,12 @@ static void sigfpe_handler(int sig, siginfo_t *si, void 
*ctx)
 
 static void sigsegv_handler(int sig, siginfo_t *si, void *ctx)
 {
+       if (!signal_from_jit_method(ctx))
+               goto exit;
+
        /* Assume that zero-page access is caused by dereferencing a
           null pointer */
-       if (signal_from_jit_method(ctx) &&
-           ((unsigned long)si->si_addr < (unsigned long)getpagesize())) {
+       if ((unsigned long)si->si_addr < (unsigned long)getpagesize()) {
                struct object *exception;
 
                /* TODO: exception's stack trace should be filled using ctx */
@@ -77,6 +79,21 @@ static void sigsegv_handler(int sig, siginfo_t *si, void 
*ctx)
                return;
        }
 
+       /* Check if exception was triggered by exception guard */
+       if (si->si_addr == exceptions_guard_page) {
+               struct object *exception;
+
+               exception = exception_occurred();
+               if (exception == NULL) {
+                       fprintf(stderr, "%s: spurious exception-test failure\n",
+                               __func__);
+                       goto exit;
+               }
+
+               throw_exception_from_signal(ctx, exception);
+               return;
+       }
+
  exit:
        print_backtrace_and_die(sig, si, ctx);
 }
-- 
1.6.0.6


------------------------------------------------------------------------------
OpenSolaris 2009.06 is a cutting edge operating system for enterprises 
looking to deploy the next generation of Solaris that includes the latest 
innovations from Sun and the OpenSource community. Download a copy and 
enjoy capabilities such as Networking, Storage and Virtualization. 
Go to: http://p.sf.net/sfu/opensolaris-get
_______________________________________________
Jatovm-devel mailing list
Jatovm-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/jatovm-devel

Reply via email to