Browse Source

Redesign the exception handling mechanism to use "setjmp" rather


			
			
				cache-refactoring
			
			
		
Rhys Weatherley 21 years ago
parent
commit
d1401a8587
  1. 5
      ChangeLog
  2. 1
      include/jit/jit-except.h
  3. 82
      jit/jit-except.cpp
  4. 32
      jit/jit-function.c
  5. 2
      jit/jit-insn.c
  6. 5
      jit/jit-internal.h
  7. 536
      jit/jit-interp.cpp
  8. 16
      jit/jit-interp.h
  9. 55
      jit/jit-setjmp.h

5
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:

1
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);

82
jit/jit-except.cpp

@ -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;
}
}

32
jit/jit-function.c

@ -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;
}

2
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 */

5
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;
};
/*

536
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 */

16
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.
*/

55
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 <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 */
Loading…
Cancel
Save