From: Rhys Weatherley Date: Fri, 21 May 2004 02:20:00 +0000 (+0000) Subject: Redesign the exception handling mechanism to use "setjmp" rather X-Git-Tag: r.0.0.4~97 X-Git-Url: https://git.unchartedbackwaters.co.uk/w/?a=commitdiff_plain;h=d1401a85874b3f25c792f291af2febd8f713969d;p=francis%2Flibjit.git Redesign the exception handling mechanism to use "setjmp" rather than C++ exceptions. --- diff --git a/ChangeLog b/ChangeLog index 831ed90..b47a1eb 100644 --- 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 * include/jit/jit-value.h, jit/jit-insn.c, jit/jit-value.c: diff --git a/include/jit/jit-except.h b/include/jit/jit-except.h index 3afabc1..6d1be10 100644 --- a/include/jit/jit-except.h +++ b/include/jit/jit-except.h @@ -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); diff --git a/jit/jit-except.cpp b/jit/jit-except.cpp index ee527cb..88cfece 100644 --- a/jit/jit-except.cpp +++ b/jit/jit-except.cpp @@ -36,7 +36,7 @@ straight vanilla ANSI C. #include "jit-interp.h" #endif #include -#include +#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; + } +} diff --git a/jit/jit-function.c b/jit/jit-function.c index d73e1e4..d4fe2b2 100644 --- a/jit/jit-function.c +++ b/jit/jit-function.c @@ -23,7 +23,7 @@ #include "jit-rules.h" #include "jit-reg-alloc.h" #include "jit-apply-func.h" -#include +#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; } diff --git a/jit/jit-insn.c b/jit/jit-insn.c index 3093346..85635d6 100644 --- a/jit/jit-insn.c +++ b/jit/jit-insn.c @@ -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 */ diff --git a/jit/jit-internal.h b/jit/jit-internal.h index d2f9acd..9f1974a 100644 --- a/jit/jit-internal.h +++ b/jit/jit-internal.h @@ -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; }; /* diff --git a/jit/jit-interp.cpp b/jit/jit-interp.cpp index ed2b60c..132d50c 100644 --- a/jit/jit-interp.cpp +++ b/jit/jit-interp.cpp @@ -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 */ diff --git a/jit/jit-interp.h b/jit/jit-interp.h index c23b0a5..fdffa24 100644 --- a/jit/jit-interp.h +++ b/jit/jit-interp.h @@ -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 index 0000000..df6b596 --- /dev/null +++ b/jit/jit-setjmp.h @@ -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 + +#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 */