]> git.unchartedbackwaters.co.uk Git - francis/libjit.git/commitdiff
Redesign the exception handling mechanism to use "setjmp" rather
authorRhys Weatherley <rweather@southern-storm.com.au>
Fri, 21 May 2004 02:20:00 +0000 (02:20 +0000)
committerRhys Weatherley <rweather@southern-storm.com.au>
Fri, 21 May 2004 02:20:00 +0000 (02:20 +0000)
than C++ exceptions.

ChangeLog
include/jit/jit-except.h
jit/jit-except.cpp
jit/jit-function.c
jit/jit-insn.c
jit/jit-internal.h
jit/jit-interp.cpp
jit/jit-interp.h
jit/jit-setjmp.h [new file with mode: 0644]

index 831ed90a3635637a964c9dc207fb500b21d3113c..b47a1ebc97e1d5852885f4a29d061c258b9accb5 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -4,6 +4,11 @@
        * jit/jit-gen-arm.c, jit/jit-gen-arm.h: modify the ARM codegen
        macros so that they can be used for branch elimination.
 
+       * include/jit/jit-except.h, jit/jit-except.cpp, jit/jit-function.c,
+       jit/jit-insn.c, jit/jit-internal.h, jit/jit-interp.cpp,
+       jit/jit-interp.h, jit/jit-setjmp.h: redesign the exception handling
+       mechanism to use "setjmp" rather than C++ exceptions.
+
 2004-05-20  Rhys Weatherley  <rweather@southern-storm.com.au>
 
        * include/jit/jit-value.h, jit/jit-insn.c, jit/jit-value.c:
index 3afabc1eda9448e72dd46307875bf56c0c2b4003..6d1be10227d445545a4c1193c3b283cc3bb9ae49 100644 (file)
@@ -54,6 +54,7 @@ typedef struct jit_stack_trace *jit_stack_trace_t;
  * External function declarations.
  */
 void *jit_exception_get_last(void);
+void *jit_exception_get_last_and_clear(void);
 void jit_exception_set_last(void *object);
 void jit_exception_clear_last(void);
 void jit_exception_throw(void *object);
index ee527cb07f0ddfd45436bd9858c4ecfe33db5796..88cfece776bcdd304df7471394d4e5805a27c65b 100644 (file)
@@ -36,7 +36,7 @@ straight vanilla ANSI C.
        #include "jit-interp.h"
 #endif
 #include <stdio.h>
-#include <setjmp.h>
+#include "jit-setjmp.h"
 
 /*@
 
@@ -65,6 +65,28 @@ extern "C" void *jit_exception_get_last(void)
        }
 }
 
+/*@
+ * @deftypefun {void *} jit_exception_get_last_and_clear (void)
+ * Get the last exception object that occurred on this thread and also
+ * clear the exception state to NULL.  This combines the effect of
+ * both @code{jit_exception_get_last} and @code{jit_exception_clear_last}.
+ * @end deftypefun
+@*/
+extern "C" void *jit_exception_get_last_and_clear(void)
+{
+       jit_thread_control_t control = _jit_thread_get_control();
+       if(control)
+       {
+               void *obj = control->last_exception;
+               control->last_exception = 0;
+               return obj;
+       }
+       else
+       {
+               return 0;
+       }
+}
+
 /*@
  * @deftypefun void jit_exception_set_last (void *object)
  * Set the last exception object that occurred on this thread, so that
@@ -110,36 +132,16 @@ extern "C" void jit_exception_clear_last(void)
 @*/
 extern "C" void jit_exception_throw(void *object)
 {
-#if defined(JIT_BACKEND_INTERP)
-       throw new jit_exception(object);
-#else
        jit_thread_control_t control = _jit_thread_get_control();
-       jit_backtrace_t trace;
        if(control)
        {
-               trace = control->backtrace_head;
-               while(trace != 0 && trace->pc != 0 && trace->catch_pc == 0)
+               control->last_exception = object;
+               if(control->setjmp_head)
                {
-                       trace = trace->parent;
-               }
-               if(trace)
-               {
-                       if(trace->catch_pc)
-                       {
-                               /* We have a native "catch" clause at this level */
-                               _jit_backtrace_set(trace->parent);
-                               _jit_gen_unwind_stack(trace->sp, trace->catch_pc, object);
-                       }
-                       else
-                       {
-                               /* The next higher level is "jit_function_apply_vararg",
-                                  so use "longjmp" to unwind the stack to that position */
-                               jit_exception_set_last(object);
-                               longjmp(*((jmp_buf *)(trace->sp)), 1);
-                       }
+                       control->backtrace_head = control->setjmp_head->trace;
+                       longjmp(control->setjmp_head->buf, 1);
                }
        }
-#endif
 }
 
 /*@
@@ -489,3 +491,33 @@ extern "C" void _jit_backtrace_set(jit_backtrace_t trace)
                control->backtrace_head = trace;
        }
 }
+
+extern "C" void _jit_unwind_push_setjmp(jit_jmp_buf *jbuf)
+{
+       jit_thread_control_t control = _jit_thread_get_control();
+       if(control)
+       {
+               jbuf->trace = control->backtrace_head;
+               jbuf->parent = control->setjmp_head;
+               control->setjmp_head = jbuf;
+       }
+}
+
+extern "C" void _jit_unwind_pop_setjmp(void)
+{
+       jit_thread_control_t control = _jit_thread_get_control();
+       if(control && control->setjmp_head)
+       {
+               control->backtrace_head = control->setjmp_head->trace;
+               control->setjmp_head = control->setjmp_head->parent;
+       }
+}
+
+extern "C" void _jit_unwind_fix_setjmp(void)
+{
+       jit_thread_control_t control = _jit_thread_get_control();
+       if(control && control->setjmp_head)
+       {
+               control->backtrace_head = control->setjmp_head->trace;
+       }
+}
index d73e1e4e6db05dcd96826bb9fb926e9d6710b7d3..d4fe2b26658c3737927a5c2991ba614a4c7994d6 100644 (file)
@@ -23,7 +23,7 @@
 #include "jit-rules.h"
 #include "jit-reg-alloc.h"
 #include "jit-apply-func.h"
-#include <setjmp.h>
+#include "jit-setjmp.h"
 
 /*@
  * @deftypefun jit_function_t jit_function_create (jit_context_t context, jit_type_t signature)
@@ -1249,14 +1249,14 @@ void *_jit_function_compile_on_demand(jit_function_t func)
 
 int jit_function_apply(jit_function_t func, void **args, void *return_area)
 {
-       if(!func)
+       if(func)
        {
-               return 0;
+               return jit_function_apply_vararg
+                       (func, func->signature, args, return_area);
        }
        else
        {
-               return jit_function_apply_vararg
-                       (func, func->signature, args, return_area);
+               return jit_function_apply_vararg(func, 0, args, return_area);
        }
 }
 
@@ -1265,20 +1265,22 @@ int jit_function_apply_vararg
 {
        struct jit_backtrace call_trace;
        void *entry;
-       jmp_buf buf;
-
-       /* Create a backtrace entry that blocks exceptions from
-          flowing further than this up the stack */
-       _jit_backtrace_push(&call_trace, 0, 0, &jbuf);
+       jit_jmp_buf jbuf;
 
        /* Establish a "setjmp" point here so that we can unwind the
-          stack when an exception occurs that is blocked by us */
-       if(setjmp(jbuf) != 0)
+          stack to this point when an exception occurs and then prevent
+          the exception from propagating further up the stack */
+       _jit_unwind_push_setjmp(&jbuf);
+       if(setjmp(jbuf.buf))
        {
-               _jit_backtrace_set(call_trace.parent);
+               _jit_unwind_pop_setjmp();
                return 1;
        }
 
+       /* Create a backtrace entry that blocks exceptions from
+          flowing further than this up the stack */
+       _jit_backtrace_push(&call_trace, 0, 0, 0);
+
        /* Get the function's entry point */
        if(!func)
        {
@@ -1312,8 +1314,8 @@ int jit_function_apply_vararg
        jit_apply(signature, func->entry_point, args,
                          jit_type_num_params(func->signature), return_area);
 
-       /* Restore the backtrace context and exit */
-       _jit_backtrace_set(call_trace.parent);
+       /* Restore the backtrace and "setjmp" contexts and exit */
+       _jit_unwind_pop_setjmp();
        return 0;
 }
 
index 30933463ff62f7ed93830ad60db457eae1ba12c4..85635d65ad85896851ffbb5dbe792d16af0380f8 100644 (file)
@@ -6278,7 +6278,7 @@ int jit_insn_start_try
        /* This function has a "try" block.  This flag helps native
           back ends know when they must be careful about global
           register allocation */
-       func->builder->has_try = 1;
+       func->has_try = 1;
 
        /* Anything with a finally handler makes the function not a leaf,
           because we may need to do a native "call" to invoke the handler */
index d2f9acd43d3c359b6393f9376006224655338869..9f1974abd87f30f1fb6d7c0455df4459418a8032 100644 (file)
@@ -304,9 +304,6 @@ struct _jit_builder
        /* Flag that indicates if the function has an ordinary return */
        int                                     ordinary_return : 1;
 
-       /* Flag that indicates if we have "try" blocks */
-       int                                     has_try : 1;
-
        /* List of all instructions in this function */
        jit_insn_t                 *insns;
        int                                     num_insns;
@@ -363,6 +360,7 @@ struct _jit_function
        int                                     is_recompilable : 1;
        int                                     no_throw : 1;
        int                                     no_return : 1;
+       int                                     has_try : 1;
        int                                     optimization_level : 8;
        int volatile            is_compiled;
 
@@ -487,6 +485,7 @@ struct jit_thread_control
        void                       *last_exception;
        jit_exception_func      exception_handler;
        jit_backtrace_t         backtrace_head;
+       struct jit_jmp_buf *setjmp_head;
 };
 
 /*
index ed2b60cacf807660b49750d31123c1b5df26f0c5..132d50c2ec52319453d269d50df499c25484006a 100644 (file)
@@ -39,6 +39,7 @@ straight vanilla ANSI C.
                #define alloca  _alloca
        #endif
 #endif
+#include "jit-setjmp.h"
 
 #if defined(JIT_BACKEND_INTERP)
 
@@ -240,6 +241,7 @@ void _jit_run_function(jit_function_interp *func, jit_item *args,
        void *entry;
        void *exception_object = 0;
        void *handler;
+       jit_jmp_buf *jbuf;
 
        /* Set up the stack frame for this function */
        frame = (jit_item *)alloca(func->frame_size);
@@ -249,6 +251,24 @@ void _jit_run_function(jit_function_interp *func, jit_item *args,
        /* Get the initial program counter */
        pc = jit_function_interp_entry_pc(func);
 
+       /* Create a "setjmp" point if this function has a "try" block.
+          This is used to catch exceptions on their way up the stack */
+       if(func->func->has_try)
+       {
+               jbuf = (jit_jmp_buf *)alloca(sizeof(jit_jmp_buf));
+               _jit_unwind_push_setjmp(jbuf);
+               if(setjmp(jbuf->buf))
+               {
+                       /* An exception has been thrown by lower-level code */
+                       exception_object = jit_exception_get_last_and_clear();
+                       goto handle_exception;
+               }
+       }
+       else
+       {
+               jbuf = 0;
+       }
+
        /* Enter the instruction dispatch loop */
        VMSWITCH(pc)
        {
@@ -3301,23 +3321,13 @@ void _jit_run_function(jit_function_interp *func, jit_item *args,
                        VM_MODIFY_PC_AND_STACK(2, 0);
                        entry = call_func->entry_point;
                        _jit_backtrace_push(&call_trace, pc, 0, 0);
-                       try
+                       if(!entry)
                        {
-                               if(!entry)
-                               {
-                                       entry = _jit_function_compile_on_demand(call_func);
-                               }
-                               _jit_run_function((jit_function_interp_t)entry, stacktop,
-                                                                 return_area);
-                               _jit_backtrace_pop();
-                       }
-                       catch(jit_exception *e)
-                       {
-                               _jit_backtrace_set(call_trace.parent);
-                               exception_object = e->object;
-                               delete e;
-                               goto handle_exception;
+                               entry = _jit_function_compile_on_demand(call_func);
                        }
+                       _jit_run_function((jit_function_interp_t)entry, stacktop,
+                                                         return_area);
+                       _jit_backtrace_pop();
                }
                VMBREAK;
 
@@ -3328,22 +3338,12 @@ void _jit_run_function(jit_function_interp *func, jit_item *args,
                        temparg = VM_NINT_ARG2;
                        VM_MODIFY_PC_AND_STACK(3, 2);
                        _jit_backtrace_push(&call_trace, pc, 0, 0);
-                       try
-                       {
-                               apply_from_interpreter((jit_type_t)tempptr,
-                                                                          (void *)VM_STK_PTRP2,
-                                                                          stacktop,
-                                                                          (unsigned int)temparg,
-                                                                          VM_STK_PTRP);
-                               _jit_backtrace_pop();
-                       }
-                       catch(jit_exception *e)
-                       {
-                               _jit_backtrace_set(call_trace.parent);
-                               exception_object = e->object;
-                               delete e;
-                               goto handle_exception;
-                       }
+                       apply_from_interpreter((jit_type_t)tempptr,
+                                                                  (void *)VM_STK_PTRP2,
+                                                                  stacktop,
+                                                                  (unsigned int)temparg,
+                                                                  VM_STK_PTRP);
+                       _jit_backtrace_pop();
                }
                VMBREAK;
 
@@ -3358,23 +3358,13 @@ void _jit_run_function(jit_function_interp *func, jit_item *args,
                        VM_MODIFY_PC_AND_STACK(1, 1);
                        entry = call_func->entry_point;
                        _jit_backtrace_push(&call_trace, pc, 0, 0);
-                       try
+                       if(!entry)
                        {
-                               if(!entry)
-                               {
-                                       entry = _jit_function_compile_on_demand(call_func);
-                               }
-                               _jit_run_function((jit_function_interp_t)entry, stacktop,
-                                                                 return_area);
-                               _jit_backtrace_pop();
-                       }
-                       catch(jit_exception *e)
-                       {
-                               _jit_backtrace_set(call_trace.parent);
-                               exception_object = e->object;
-                               delete e;
-                               goto handle_exception;
+                               entry = _jit_function_compile_on_demand(call_func);
                        }
+                       _jit_run_function((jit_function_interp_t)entry, stacktop,
+                                                         return_area);
+                       _jit_backtrace_pop();
                }
                VMBREAK;
 
@@ -3386,28 +3376,22 @@ void _jit_run_function(jit_function_interp *func, jit_item *args,
                        temparg = VM_NINT_ARG3;
                        VM_MODIFY_PC_AND_STACK(4, 1);
                        _jit_backtrace_push(&call_trace, pc, 0, 0);
-                       try
-                       {
-                               apply_from_interpreter((jit_type_t)tempptr,
-                                                                          (void *)tempptr2,
-                                                                          stacktop,
-                                                                          (unsigned int)temparg,
-                                                                          VM_STK_PTRP);
-                               _jit_backtrace_pop();
-                       }
-                       catch(jit_exception *e)
-                       {
-                               _jit_backtrace_set(call_trace.parent);
-                               exception_object = e->object;
-                               delete e;
-                               goto handle_exception;
-                       }
+                       apply_from_interpreter((jit_type_t)tempptr,
+                                                                  (void *)tempptr2,
+                                                                  stacktop,
+                                                                  (unsigned int)temparg,
+                                                                  VM_STK_PTRP);
+                       _jit_backtrace_pop();
                }
                VMBREAK;
 
                VMCASE(JIT_OP_RETURN):
                {
                        /* Return from the current function, with no result */
+                       if(jbuf)
+                       {
+                               _jit_unwind_pop_setjmp();
+                       }
                        return;
                }
                /* Not reached */
@@ -3416,6 +3400,10 @@ void _jit_run_function(jit_function_interp *func, jit_item *args,
                {
                        /* Return from the current function, with an integer result */
                        return_area->int_value = VM_STK_INT0;
+                       if(jbuf)
+                       {
+                               _jit_unwind_pop_setjmp();
+                       }
                        return;
                }
                /* Not reached */
@@ -3424,6 +3412,10 @@ void _jit_run_function(jit_function_interp *func, jit_item *args,
                {
                        /* Return from the current function, with a long result */
                        return_area->long_value = VM_STK_LONG0;
+                       if(jbuf)
+                       {
+                               _jit_unwind_pop_setjmp();
+                       }
                        return;
                }
                /* Not reached */
@@ -3432,6 +3424,10 @@ void _jit_run_function(jit_function_interp *func, jit_item *args,
                {
                        /* Return from the current function, with a 32-bit float result */
                        return_area->float32_value = VM_STK_FLOAT320;
+                       if(jbuf)
+                       {
+                               _jit_unwind_pop_setjmp();
+                       }
                        return;
                }
                /* Not reached */
@@ -3440,6 +3436,10 @@ void _jit_run_function(jit_function_interp *func, jit_item *args,
                {
                        /* Return from the current function, with a 64-bit float result */
                        return_area->float64_value = VM_STK_FLOAT640;
+                       if(jbuf)
+                       {
+                               _jit_unwind_pop_setjmp();
+                       }
                        return;
                }
                /* Not reached */
@@ -3448,6 +3448,10 @@ void _jit_run_function(jit_function_interp *func, jit_item *args,
                {
                        /* Return from the current function, with a native float result */
                        return_area->nfloat_value = VM_STK_NFLOAT0;
+                       if(jbuf)
+                       {
+                               _jit_unwind_pop_setjmp();
+                       }
                        return;
                }
                /* Not reached */
@@ -3459,6 +3463,10 @@ void _jit_run_function(jit_function_interp *func, jit_item *args,
                        jit_memcpy(return_area->struct_value, VM_STK_PTR0,
                                           (unsigned int)VM_NINT_ARG);
                #endif
+                       if(jbuf)
+                       {
+                               _jit_unwind_pop_setjmp();
+                       }
                        return;
                }
                /* Not reached */
@@ -3552,7 +3560,8 @@ void _jit_run_function(jit_function_interp *func, jit_item *args,
                        else
                        {
                                /* Throw the exception up to the next level */
-                               throw new jit_exception(exception_object);
+                               _jit_unwind_pop_setjmp();
+                               jit_exception_throw(exception_object);
                        }
                }
                VMBREAK;
@@ -4451,23 +4460,9 @@ void _jit_run_function(jit_function_interp *func, jit_item *args,
        VMSWITCHEND
 
 handle_builtin: ;
-       /* TODO */
+       jit_exception_builtin(builtin_exception);
 }
 
-/*
- * Class that helps restore the backtrace when C++ exceptions
- * travel up the stack.  Acts sort of like a "finally" clause.
- */
-class jit_trace_restorer
-{
-public:
-       jit_backtrace_t previous;
-       jit_trace_restorer(jit_backtrace_t previous)
-               { this->previous = previous; }
-       ~jit_trace_restorer()
-               { _jit_backtrace_set(previous); }
-};
-
 extern "C" int jit_function_apply
        (jit_function_t func, void **args, void *return_area)
 {
@@ -4497,238 +4492,243 @@ extern "C" int jit_function_apply_vararg
        jit_type_t type;
        unsigned int num_params;
        unsigned int param;
+       jit_jmp_buf jbuf;
 
+       /* Push a "setjmp" context onto the stack, so that we can catch
+          any exceptions that are thrown up to this level and prevent
+          them from propagating further */
+       _jit_unwind_push_setjmp(&jbuf);
+       if(setjmp(jbuf.buf))
+       {
+               _jit_unwind_pop_setjmp();
+               return 1;
+       }
+
+       /* Initialize the backtrace information */
        _jit_backtrace_push(&call_trace, 0, 0, 0);
+
+       /* Clear the exception context */
+       jit_exception_clear_last();
+
+       /* Bail out if the function is NULL */
+       if(!func)
+       {
+               jit_exception_builtin(JIT_RESULT_NULL_FUNCTION);
+       }
+
+       /* Make sure that the function is compiled */
+       if(func->is_compiled)
+       {
+               entry = (jit_function_interp *)(func->entry_point);
+       }
+       else
+       {
+               entry = (jit_function_interp *)
+                       _jit_function_compile_on_demand(func);
+       }
+
+       /* Populate the low-level argument buffer */
+       if(!signature)
+       {
+               signature = func->signature;
+               arg_buffer = (jit_item *)alloca(entry->args_size);
+       }
+       else if(signature == func->signature)
+       {
+               arg_buffer = (jit_item *)alloca(entry->args_size);
+       }
+       else
+       {
+               arg_buffer = (jit_item *)alloca
+                       (_jit_interp_calculate_arg_size(func, signature));
+       }
+       temp_arg = arg_buffer;
+       if(func->nested_parent)
        {
-               jit_trace_restorer restorer(call_trace.parent);
-               jit_exception_clear_last();
-               try
+               jit_exception_builtin(JIT_RESULT_CALLED_NESTED);
+       }
+       type = jit_type_get_return(signature);
+       if(jit_type_return_via_pointer(type))
+       {
+               if(!return_area)
+               {
+                       return_area = alloca(jit_type_get_size(type));
+               }
+               temp_arg->ptr_value = return_area;
+               ++temp_arg;
+       }
+       num_params = jit_type_num_params(signature);
+       for(param = 0; param < num_params; ++param)
+       {
+               type = jit_type_normalize
+                       (jit_type_get_param(signature, param));
+               if(!(args[param]))
+               {
+                       jit_exception_builtin(JIT_RESULT_NULL_REFERENCE);
+               }
+               switch(type->kind)
                {
-                       /* Bail out if the function is NULL */
-                       if(!func)
+                       case JIT_TYPE_SBYTE:
                        {
-                               jit_exception_builtin(JIT_RESULT_NULL_FUNCTION);
+                               temp_arg->int_value = *((jit_sbyte *)(args[param]));
+                               ++temp_arg;
                        }
+                       break;
 
-                       /* Make sure that the function is compiled */
-                       if(func->is_compiled)
+                       case JIT_TYPE_UBYTE:
                        {
-                               entry = (jit_function_interp *)(func->entry_point);
+                               temp_arg->int_value = *((jit_ubyte *)(args[param]));
+                               ++temp_arg;
                        }
-                       else
+                       break;
+
+                       case JIT_TYPE_SHORT:
                        {
-                               entry = (jit_function_interp *)
-                                       _jit_function_compile_on_demand(func);
+                               temp_arg->int_value = *((jit_short *)(args[param]));
+                               ++temp_arg;
                        }
+                       break;
 
-                       /* Populate the low-level argument buffer */
-                       if(!signature)
+                       case JIT_TYPE_USHORT:
                        {
-                               signature = func->signature;
-                               arg_buffer = (jit_item *)alloca(entry->args_size);
+                               temp_arg->int_value = *((jit_ushort *)(args[param]));
+                               ++temp_arg;
                        }
-                       else if(signature == func->signature)
+                       break;
+
+                       case JIT_TYPE_INT:
+                       case JIT_TYPE_UINT:
                        {
-                               arg_buffer = (jit_item *)alloca(entry->args_size);
+                               temp_arg->int_value = *((jit_int *)(args[param]));
+                               ++temp_arg;
                        }
-                       else
+                       break;
+
+                       case JIT_TYPE_LONG:
+                       case JIT_TYPE_ULONG:
                        {
-                               arg_buffer = (jit_item *)alloca
-                                       (_jit_interp_calculate_arg_size(func, signature));
+                               temp_arg->long_value = *((jit_long *)(args[param]));
+                               ++temp_arg;
                        }
-                       temp_arg = arg_buffer;
-                       if(func->nested_parent)
+                       break;
+
+                       case JIT_TYPE_FLOAT32:
                        {
-                               jit_exception_builtin(JIT_RESULT_CALLED_NESTED);
+                               temp_arg->float32_value =
+                                       *((jit_float32 *)(args[param]));
+                               ++temp_arg;
                        }
-                       type = jit_type_get_return(signature);
-                       if(jit_type_return_via_pointer(type))
+                       break;
+
+                       case JIT_TYPE_FLOAT64:
                        {
-                               if(!return_area)
-                               {
-                                       return_area = alloca(jit_type_get_size(type));
-                               }
-                               temp_arg->ptr_value = return_area;
+                               temp_arg->float64_value =
+                                       *((jit_float64 *)(args[param]));
                                ++temp_arg;
                        }
-                       num_params = jit_type_num_params(signature);
-                       for(param = 0; param < num_params; ++param)
-                       {
-                               type = jit_type_normalize
-                                       (jit_type_get_param(signature, param));
-                               if(!(args[param]))
-                               {
-                                       jit_exception_builtin(JIT_RESULT_NULL_REFERENCE);
-                               }
-                               switch(type->kind)
-                               {
-                                       case JIT_TYPE_SBYTE:
-                                       {
-                                               temp_arg->int_value = *((jit_sbyte *)(args[param]));
-                                               ++temp_arg;
-                                       }
-                                       break;
+                       break;
 
-                                       case JIT_TYPE_UBYTE:
-                                       {
-                                               temp_arg->int_value = *((jit_ubyte *)(args[param]));
-                                               ++temp_arg;
-                                       }
-                                       break;
+                       case JIT_TYPE_NFLOAT:
+                       {
+                               temp_arg->nfloat_value =
+                                       *((jit_nfloat *)(args[param]));
+                               ++temp_arg;
+                       }
+                       break;
 
-                                       case JIT_TYPE_SHORT:
-                                       {
-                                               temp_arg->int_value = *((jit_short *)(args[param]));
-                                               ++temp_arg;
-                                       }
-                                       break;
+                       case JIT_TYPE_STRUCT:
+                       case JIT_TYPE_UNION:
+                       {
+                               jit_memcpy(temp_arg, args[param],
+                                                  jit_type_get_size(type));
+                               temp_arg += JIT_NUM_ITEMS_IN_STRUCT
+                                       (jit_type_get_size(type));
+                       }
+                       break;
+               }
+       }
 
-                                       case JIT_TYPE_USHORT:
-                                       {
-                                               temp_arg->int_value = *((jit_ushort *)(args[param]));
-                                               ++temp_arg;
-                                       }
-                                       break;
+       /* Run the function */
+       _jit_run_function(entry, arg_buffer, &interp_return_area);
 
-                                       case JIT_TYPE_INT:
-                                       case JIT_TYPE_UINT:
-                                       {
-                                               temp_arg->int_value = *((jit_int *)(args[param]));
-                                               ++temp_arg;
-                                       }
-                                       break;
+       /* Copy the return value into place, if it isn't already there */
+       if(return_area)
+       {
+               type = jit_type_normalize(jit_type_get_return(signature));
+               if(type && type != jit_type_void)
+               {
+                       switch(type->kind)
+                       {
+                               case JIT_TYPE_SBYTE:
+                               case JIT_TYPE_UBYTE:
+                               {
+                                       *((jit_sbyte *)return_area) =
+                                               (jit_sbyte)(interp_return_area.int_value);
+                               }
+                               break;
 
-                                       case JIT_TYPE_LONG:
-                                       case JIT_TYPE_ULONG:
-                                       {
-                                               temp_arg->long_value = *((jit_long *)(args[param]));
-                                               ++temp_arg;
-                                       }
-                                       break;
+                               case JIT_TYPE_SHORT:
+                               case JIT_TYPE_USHORT:
+                               {
+                                       *((jit_short *)return_area) =
+                                               (jit_short)(interp_return_area.int_value);
+                               }
+                               break;
 
-                                       case JIT_TYPE_FLOAT32:
-                                       {
-                                               temp_arg->float32_value =
-                                                       *((jit_float32 *)(args[param]));
-                                               ++temp_arg;
-                                       }
-                                       break;
+                               case JIT_TYPE_INT:
+                               case JIT_TYPE_UINT:
+                               {
+                                       *((jit_int *)return_area) =
+                                               interp_return_area.int_value;
+                               }
+                               break;
 
-                                       case JIT_TYPE_FLOAT64:
-                                       {
-                                               temp_arg->float64_value =
-                                                       *((jit_float64 *)(args[param]));
-                                               ++temp_arg;
-                                       }
-                                       break;
+                               case JIT_TYPE_LONG:
+                               case JIT_TYPE_ULONG:
+                               {
+                                       *((jit_long *)return_area) =
+                                               interp_return_area.long_value;
+                               }
+                               break;
 
-                                       case JIT_TYPE_NFLOAT:
-                                       {
-                                               temp_arg->nfloat_value =
-                                                       *((jit_nfloat *)(args[param]));
-                                               ++temp_arg;
-                                       }
-                                       break;
+                               case JIT_TYPE_FLOAT32:
+                               {
+                                       *((jit_float32 *)return_area) =
+                                               interp_return_area.float32_value;
+                               }
+                               break;
 
-                                       case JIT_TYPE_STRUCT:
-                                       case JIT_TYPE_UNION:
-                                       {
-                                               jit_memcpy(temp_arg, args[param],
-                                                                  jit_type_get_size(type));
-                                               temp_arg += JIT_NUM_ITEMS_IN_STRUCT
-                                                       (jit_type_get_size(type));
-                                       }
-                                       break;
+                               case JIT_TYPE_FLOAT64:
+                               {
+                                       *((jit_float64 *)return_area) =
+                                               interp_return_area.float64_value;
                                }
-                       }
+                               break;
 
-                       /* Run the function */
-                       _jit_run_function(entry, arg_buffer, &interp_return_area);
+                               case JIT_TYPE_NFLOAT:
+                               {
+                                       *((jit_nfloat *)return_area) =
+                                               interp_return_area.nfloat_value;
+                               }
+                               break;
 
-                       /* Copy the return value into place, if it isn't already there */
-                       if(return_area)
-                       {
-                               type = jit_type_normalize(jit_type_get_return(signature));
-                               if(type && type != jit_type_void)
+                               case JIT_TYPE_STRUCT:
+                               case JIT_TYPE_UNION:
                                {
-                                       switch(type->kind)
+                                       if(!jit_type_return_via_pointer(type))
                                        {
-                                               case JIT_TYPE_SBYTE:
-                                               case JIT_TYPE_UBYTE:
-                                               {
-                                                       *((jit_sbyte *)return_area) =
-                                                               (jit_sbyte)(interp_return_area.int_value);
-                                               }
-                                               break;
-
-                                               case JIT_TYPE_SHORT:
-                                               case JIT_TYPE_USHORT:
-                                               {
-                                                       *((jit_short *)return_area) =
-                                                               (jit_short)(interp_return_area.int_value);
-                                               }
-                                               break;
-
-                                               case JIT_TYPE_INT:
-                                               case JIT_TYPE_UINT:
-                                               {
-                                                       *((jit_int *)return_area) =
-                                                               interp_return_area.int_value;
-                                               }
-                                               break;
-
-                                               case JIT_TYPE_LONG:
-                                               case JIT_TYPE_ULONG:
-                                               {
-                                                       *((jit_long *)return_area) =
-                                                               interp_return_area.long_value;
-                                               }
-                                               break;
-
-                                               case JIT_TYPE_FLOAT32:
-                                               {
-                                                       *((jit_float32 *)return_area) =
-                                                               interp_return_area.float32_value;
-                                               }
-                                               break;
-
-                                               case JIT_TYPE_FLOAT64:
-                                               {
-                                                       *((jit_float64 *)return_area) =
-                                                               interp_return_area.float64_value;
-                                               }
-                                               break;
-
-                                               case JIT_TYPE_NFLOAT:
-                                               {
-                                                       *((jit_nfloat *)return_area) =
-                                                               interp_return_area.nfloat_value;
-                                               }
-                                               break;
-
-                                               case JIT_TYPE_STRUCT:
-                                               case JIT_TYPE_UNION:
-                                               {
-                                                       if(!jit_type_return_via_pointer(type))
-                                                       {
-                                                               jit_memcpy(return_area, &interp_return_area,
-                                                                                  jit_type_get_size(type));
-                                                       }
-                                               }
-                                               break;
+                                               jit_memcpy(return_area, &interp_return_area,
+                                                                  jit_type_get_size(type));
                                        }
                                }
+                               break;
                        }
-                       return 1;
-               }
-               catch(jit_exception *e)
-               {
-                       /* Record the exception, but don't throw it any further yet */
-                       jit_exception_set_last(e->object);
-                       delete e;
-                       return 0;
                }
        }
+
+       /* Pop the "setjmp" context and exit */
+       _jit_unwind_pop_setjmp();
+       return 1;
 }
 
 #endif /* JIT_BACKEND_INTERP */
index c23b0a5f8969364498b48ff12a2560d1dadf13ef..fdffa24cd20fa6c265cb8af8eef7c9fa5e52ee12 100644 (file)
@@ -87,22 +87,6 @@ struct jit_function_interp
 #define        jit_function_interp_entry_pc(info)      \
                        ((void **)(((unsigned char *)(info)) + jit_function_interp_size))
 
-#if defined(__cplusplus)
-
-/*
- * The JIT exception class.  Instances of this object are thrown
- * to simulate a JIT-level exception.
- */
-class jit_exception
-{
-public:
-       jit_exception(void *object) { this->object = object; }
-
-       void *object;
-};
-
-#endif /* __cplusplus */
-
 /*
  * Argument variable access opcodes.
  */
diff --git a/jit/jit-setjmp.h b/jit/jit-setjmp.h
new file mode 100644 (file)
index 0000000..df6b596
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * jit-setjmp.h - Support definitions that use "setjmp" for exceptions.
+ *
+ * Copyright (C) 2004  Southern Storm Software, Pty Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef        _JIT_SETJMP_H
+#define        _JIT_SETJMP_H
+
+#include <setjmp.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Jump buffer structure, with link.
+ */
+typedef struct jit_jmp_buf
+{
+       jmp_buf                         buf;
+       jit_backtrace_t         trace;
+       struct jit_jmp_buf *parent;
+
+} jit_jmp_buf;
+
+/*
+ * Push a "setjmp" buffer onto the current thread's unwind stck.
+ */
+void _jit_unwind_push_setjmp(jit_jmp_buf *jbuf);
+
+/*
+ * Pop the top-most "setjmp" buffer from the current thread's unwind stack.
+ */
+void _jit_unwind_pop_setjmp(void);
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif /* _JIT_SETJMP_H */