libjit.git - libjit

index : libjit.git
libjit
summary refs log tree commit diff
diff options
context:
space:
mode:
Diffstat
-rw-r--r--ChangeLog 5
-rw-r--r--include/jit/jit-opcode.h 135
-rw-r--r--jit/jit-except.c 14
-rw-r--r--jit/jit-function.c 2
-rw-r--r--jit/jit-insn.c 345
-rw-r--r--jit/jit-internal.h 7
-rw-r--r--jit/jit-interp.c 11
-rw-r--r--jit/jit-opcode.c 1
-rw-r--r--jit/jit-setjmp.h 8
9 files changed, 367 insertions, 161 deletions
diff --git a/ChangeLog b/ChangeLog
index f84a9ba..35b9524 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -10,6 +10,11 @@
to "jit_insn_move_blocks_to_end" and add a new function
"jit_insn_move_blocks_to_start" for creating initialization code.
+ * include/jit/jit-opcode.h, jit/jit-except.c, jit/jit-function.c,
+ jit/jit-insn.c, jit/jit-internal.h, jit/jit-interp.c, jit/jit-opcode.c,
+ jit/jit-setjmp.h: modify the function call logic to use "setjmp"
+ with native back ends.
+
2004年05月21日 Rhys Weatherley <rweather@southern-storm.com.au>
* jit/jit-gen-arm.c, jit/jit-gen-arm.h: modify the ARM codegen
diff --git a/include/jit/jit-opcode.h b/include/jit/jit-opcode.h
index 52eb1be..9116c0f 100644
--- a/include/jit/jit-opcode.h
+++ b/include/jit/jit-opcode.h
@@ -413,101 +413,102 @@ extern "C" {
#define JIT_OP_CALL_FILTER_RETURN 0x0154
#define JIT_OP_PREPARE_FOR_LEAVE 0x0155
#define JIT_OP_PREPARE_FOR_RETURN 0x0156
+#define JIT_OP_JUMP_TO_CATCHER 0x0157
/*
* Data manipulation.
*/
-#define JIT_OP_COPY_LOAD_SBYTE 0x0157
-#define JIT_OP_COPY_LOAD_UBYTE 0x0158
-#define JIT_OP_COPY_LOAD_SHORT 0x0159
-#define JIT_OP_COPY_LOAD_USHORT 0x015A
-#define JIT_OP_COPY_INT 0x015B
-#define JIT_OP_COPY_LONG 0x015C
-#define JIT_OP_COPY_FLOAT32 0x015D
-#define JIT_OP_COPY_FLOAT64 0x015E
-#define JIT_OP_COPY_NFLOAT 0x015F
-#define JIT_OP_COPY_STRUCT 0x0160
-#define JIT_OP_COPY_STORE_BYTE 0x0161
-#define JIT_OP_COPY_STORE_SHORT 0x0162
-#define JIT_OP_ADDRESS_OF 0x0163
+#define JIT_OP_COPY_LOAD_SBYTE 0x0158
+#define JIT_OP_COPY_LOAD_UBYTE 0x0159
+#define JIT_OP_COPY_LOAD_SHORT 0x015A
+#define JIT_OP_COPY_LOAD_USHORT 0x015B
+#define JIT_OP_COPY_INT 0x015C
+#define JIT_OP_COPY_LONG 0x015D
+#define JIT_OP_COPY_FLOAT32 0x015E
+#define JIT_OP_COPY_FLOAT64 0x015F
+#define JIT_OP_COPY_NFLOAT 0x0160
+#define JIT_OP_COPY_STRUCT 0x0161
+#define JIT_OP_COPY_STORE_BYTE 0x0162
+#define JIT_OP_COPY_STORE_SHORT 0x0163
+#define JIT_OP_ADDRESS_OF 0x0164
/*
* Incoming registers, outgoing registers, and stack pushes.
*/
-#define JIT_OP_INCOMING_REG 0x0164
-#define JIT_OP_INCOMING_FRAME_POSN 0x0165
-#define JIT_OP_OUTGOING_REG 0x0166
-#define JIT_OP_RETURN_REG 0x0167
-#define JIT_OP_PUSH_INT 0x0168
-#define JIT_OP_PUSH_LONG 0x0169
-#define JIT_OP_PUSH_FLOAT32 0x016A
-#define JIT_OP_PUSH_FLOAT64 0x016B
-#define JIT_OP_PUSH_NFLOAT 0x016C
-#define JIT_OP_PUSH_STRUCT 0x016D
-#define JIT_OP_POP_STACK 0x016E
-#define JIT_OP_FLUSH_SMALL_STRUCT 0x016F
+#define JIT_OP_INCOMING_REG 0x0165
+#define JIT_OP_INCOMING_FRAME_POSN 0x0166
+#define JIT_OP_OUTGOING_REG 0x0167
+#define JIT_OP_RETURN_REG 0x0168
+#define JIT_OP_PUSH_INT 0x0169
+#define JIT_OP_PUSH_LONG 0x016A
+#define JIT_OP_PUSH_FLOAT32 0x016B
+#define JIT_OP_PUSH_FLOAT64 0x016C
+#define JIT_OP_PUSH_NFLOAT 0x016D
+#define JIT_OP_PUSH_STRUCT 0x016E
+#define JIT_OP_POP_STACK 0x016F
+#define JIT_OP_FLUSH_SMALL_STRUCT 0x0170
/*
* Pointer-relative loads and stores.
*/
-#define JIT_OP_LOAD_RELATIVE_SBYTE 0x0170
-#define JIT_OP_LOAD_RELATIVE_UBYTE 0x0171
-#define JIT_OP_LOAD_RELATIVE_SHORT 0x0172
-#define JIT_OP_LOAD_RELATIVE_USHORT 0x0173
-#define JIT_OP_LOAD_RELATIVE_INT 0x0174
-#define JIT_OP_LOAD_RELATIVE_LONG 0x0175
-#define JIT_OP_LOAD_RELATIVE_FLOAT32 0x0176
-#define JIT_OP_LOAD_RELATIVE_FLOAT64 0x0177
-#define JIT_OP_LOAD_RELATIVE_NFLOAT 0x0178
-#define JIT_OP_LOAD_RELATIVE_STRUCT 0x0179
-#define JIT_OP_STORE_RELATIVE_BYTE 0x017A
-#define JIT_OP_STORE_RELATIVE_SHORT 0x017B
-#define JIT_OP_STORE_RELATIVE_INT 0x017C
-#define JIT_OP_STORE_RELATIVE_LONG 0x017D
-#define JIT_OP_STORE_RELATIVE_FLOAT32 0x017E
-#define JIT_OP_STORE_RELATIVE_FLOAT64 0x017F
-#define JIT_OP_STORE_RELATIVE_NFLOAT 0x0180
-#define JIT_OP_STORE_RELATIVE_STRUCT 0x0181
-#define JIT_OP_ADD_RELATIVE 0x0182
+#define JIT_OP_LOAD_RELATIVE_SBYTE 0x0171
+#define JIT_OP_LOAD_RELATIVE_UBYTE 0x0172
+#define JIT_OP_LOAD_RELATIVE_SHORT 0x0173
+#define JIT_OP_LOAD_RELATIVE_USHORT 0x0174
+#define JIT_OP_LOAD_RELATIVE_INT 0x0175
+#define JIT_OP_LOAD_RELATIVE_LONG 0x0176
+#define JIT_OP_LOAD_RELATIVE_FLOAT32 0x0177
+#define JIT_OP_LOAD_RELATIVE_FLOAT64 0x0178
+#define JIT_OP_LOAD_RELATIVE_NFLOAT 0x0179
+#define JIT_OP_LOAD_RELATIVE_STRUCT 0x017A
+#define JIT_OP_STORE_RELATIVE_BYTE 0x017B
+#define JIT_OP_STORE_RELATIVE_SHORT 0x017C
+#define JIT_OP_STORE_RELATIVE_INT 0x017D
+#define JIT_OP_STORE_RELATIVE_LONG 0x017E
+#define JIT_OP_STORE_RELATIVE_FLOAT32 0x017F
+#define JIT_OP_STORE_RELATIVE_FLOAT64 0x0180
+#define JIT_OP_STORE_RELATIVE_NFLOAT 0x0181
+#define JIT_OP_STORE_RELATIVE_STRUCT 0x0182
+#define JIT_OP_ADD_RELATIVE 0x0183
/*
* Array element loads and stores.
*/
-#define JIT_OP_LOAD_ELEMENT_SBYTE 0x0183
-#define JIT_OP_LOAD_ELEMENT_UBYTE 0x0184
-#define JIT_OP_LOAD_ELEMENT_SHORT 0x0185
-#define JIT_OP_LOAD_ELEMENT_USHORT 0x0186
-#define JIT_OP_LOAD_ELEMENT_INT 0x0187
-#define JIT_OP_LOAD_ELEMENT_UINT 0x0188
-#define JIT_OP_LOAD_ELEMENT_LONG 0x0189
-#define JIT_OP_LOAD_ELEMENT_ULONG 0x018A
-#define JIT_OP_LOAD_ELEMENT_FLOAT32 0x018B
-#define JIT_OP_LOAD_ELEMENT_FLOAT64 0x018C
-#define JIT_OP_LOAD_ELEMENT_NFLOAT 0x018D
-#define JIT_OP_STORE_ELEMENT_BYTE 0x018E
-#define JIT_OP_STORE_ELEMENT_SHORT 0x018F
-#define JIT_OP_STORE_ELEMENT_INT 0x0190
-#define JIT_OP_STORE_ELEMENT_LONG 0x0191
-#define JIT_OP_STORE_ELEMENT_FLOAT32 0x0192
-#define JIT_OP_STORE_ELEMENT_FLOAT64 0x0193
-#define JIT_OP_STORE_ELEMENT_NFLOAT 0x0194
+#define JIT_OP_LOAD_ELEMENT_SBYTE 0x0184
+#define JIT_OP_LOAD_ELEMENT_UBYTE 0x0185
+#define JIT_OP_LOAD_ELEMENT_SHORT 0x0186
+#define JIT_OP_LOAD_ELEMENT_USHORT 0x0187
+#define JIT_OP_LOAD_ELEMENT_INT 0x0188
+#define JIT_OP_LOAD_ELEMENT_UINT 0x0189
+#define JIT_OP_LOAD_ELEMENT_LONG 0x018A
+#define JIT_OP_LOAD_ELEMENT_ULONG 0x018B
+#define JIT_OP_LOAD_ELEMENT_FLOAT32 0x018C
+#define JIT_OP_LOAD_ELEMENT_FLOAT64 0x018D
+#define JIT_OP_LOAD_ELEMENT_NFLOAT 0x018E
+#define JIT_OP_STORE_ELEMENT_BYTE 0x018F
+#define JIT_OP_STORE_ELEMENT_SHORT 0x0190
+#define JIT_OP_STORE_ELEMENT_INT 0x0191
+#define JIT_OP_STORE_ELEMENT_LONG 0x0192
+#define JIT_OP_STORE_ELEMENT_FLOAT32 0x0193
+#define JIT_OP_STORE_ELEMENT_FLOAT64 0x0194
+#define JIT_OP_STORE_ELEMENT_NFLOAT 0x0195
/*
* Block operations.
*/
-#define JIT_OP_MEMCPY 0x0195
-#define JIT_OP_MEMMOVE 0x0196
-#define JIT_OP_MEMSET 0x0197
+#define JIT_OP_MEMCPY 0x0196
+#define JIT_OP_MEMMOVE 0x0197
+#define JIT_OP_MEMSET 0x0198
/*
* Allocate memory from the stack.
*/
-#define JIT_OP_ALLOCA 0x0198
+#define JIT_OP_ALLOCA 0x0199
/*
* The number of opcodes in the above list.
*/
-#define JIT_OP_NUM_OPCODES 0x0199
+#define JIT_OP_NUM_OPCODES 0x019A
/*
* Opcode information.
diff --git a/jit/jit-except.c b/jit/jit-except.c
index e8c20b1..7a63942 100644
--- a/jit/jit-except.c
+++ b/jit/jit-except.c
@@ -432,16 +432,13 @@ void jit_stack_trace_free(jit_stack_trace_t trace)
}
}
-void _jit_backtrace_push
- (jit_backtrace_t trace, void *pc, void *catch_pc, void *sp)
+void _jit_backtrace_push(jit_backtrace_t trace, void *pc)
{
jit_thread_control_t control = _jit_thread_get_control();
if(control)
{
trace->parent = control->backtrace_head;
trace->pc = pc;
- trace->catch_pc = catch_pc;
- trace->sp = sp;
trace->security_object = 0;
trace->free_security_object = 0;
control->backtrace_head = trace;
@@ -450,8 +447,6 @@ void _jit_backtrace_push
{
trace->parent = 0;
trace->pc = pc;
- trace->catch_pc = catch_pc;
- trace->sp = sp;
trace->security_object = 0;
trace->free_security_object = 0;
}
@@ -490,6 +485,7 @@ void _jit_unwind_push_setjmp(jit_jmp_buf *jbuf)
if(control)
{
jbuf->trace = control->backtrace_head;
+ jbuf->catcher = 0;
jbuf->parent = control->setjmp_head;
control->setjmp_head = jbuf;
}
@@ -504,3 +500,9 @@ void _jit_unwind_pop_setjmp(void)
control->setjmp_head = control->setjmp_head->parent;
}
}
+
+void _jit_unwind_pop_and_rethrow(void)
+{
+ _jit_unwind_pop_setjmp();
+ jit_exception_throw(jit_exception_get_last());
+}
diff --git a/jit/jit-function.c b/jit/jit-function.c
index 5ca0505..ac22229 100644
--- a/jit/jit-function.c
+++ b/jit/jit-function.c
@@ -1284,7 +1284,7 @@ int jit_function_apply_vararg
/* Create a backtrace entry that blocks exceptions from
flowing further than this up the stack */
- _jit_backtrace_push(&call_trace, 0, 0, 0);
+ _jit_backtrace_push(&call_trace, 0);
/* Get the function's entry point */
if(!func)
diff --git a/jit/jit-insn.c b/jit/jit-insn.c
index 8781aaa..c65d5b9 100644
--- a/jit/jit-insn.c
+++ b/jit/jit-insn.c
@@ -20,6 +20,7 @@
#include "jit-internal.h"
#include "jit-rules.h"
+#include "jit-setjmp.h"
#include <config.h>
#if HAVE_ALLOCA_H
#include <alloca.h>
@@ -4624,8 +4625,22 @@ static int setup_eh_frame_for_call(jit_function_t func, int flags)
jit_type_t params[2];
jit_value_t struct_return;
- /* If the "nothrow" or "tail" flags are set, then we don't
- need to worry about this */
+ /* If "tail" is set, then we need to pop the "setjmp" context */
+ if((flags & JIT_CALL_TAIL) != 0 && func->has_try)
+ {
+ type = jit_type_create_signature
+ (jit_abi_cdecl, jit_type_void, 0, 0, 1);
+ if(!type)
+ {
+ return 0;
+ }
+ jit_insn_call_native
+ (func, "_jit_unwind_pop_setjmp",
+ (void *)_jit_unwind_pop_setjmp, type, 0, 0, JIT_CALL_NOTHROW);
+ jit_type_free(type);
+ }
+
+ /* If "nothrow" or "tail" is set, then there is no more to do */
if((flags & (JIT_CALL_NOTHROW | JIT_CALL_TAIL)) != 0)
{
return 1;
@@ -4634,6 +4649,7 @@ static int setup_eh_frame_for_call(jit_function_t func, int flags)
/* This function may throw an exception */
func->builder->may_throw = 1;
+#if JIT_APPLY_BROKEN_FRAME_BUILTINS != 0
/* Get the value that holds the exception frame information */
if((eh_frame_info = func->builder->eh_frame_info) == 0)
{
@@ -4685,43 +4701,44 @@ static int setup_eh_frame_for_call(jit_function_t func, int flags)
return 0;
}
- /* Set up to call the "_jit_backtrace_push" intrinsic */
- if(!_jit_create_call_setup_insns
- (func, type, args, 2, 0, 0, &struct_return))
- {
- jit_type_free(type);
- return 0;
- }
-
- /* Terminate the current block and then call "_jit_backtrace_push" */
- block = _jit_block_create(func, 0);
- if(!block)
- {
- jit_type_free(type);
- return 0;
- }
- block->entered_via_top = 1;
- func->builder->current_block = block;
- insn = _jit_block_add_insn(block);
- if(!insn)
- {
- jit_type_free(type);
- return 0;
- }
- insn->opcode = JIT_OP_CALL_EXTERNAL;
- insn->flags = JIT_INSN_DEST_IS_NATIVE | JIT_INSN_VALUE1_IS_NAME;
- insn->dest = (jit_value_t)(void *)_jit_backtrace_push;
- insn->value1 = (jit_value_t)"_jit_backtrace_push";
+ /* Call the "_jit_backtrace_push" function */
+ jit_insn_call_native
+ (func, "_jit_backtrace_push",
+ (void *)_jit_backtrace_push, type, args, 2, JIT_CALL_NOTHROW);
+ jit_type_free(type);
+#endif
- /* Clean up after the function call */
- if(!_jit_create_call_return_insns(func, type, args, 2, 0, 0))
+ /* Are we currently within a "try" context covered by a "catch"? */
+ block = func->builder->current_block;
+ if(block->block_eh &&
+ block->block_eh->catch_label != jit_label_undefined &&
+ func->builder->setjmp_value != 0)
{
- jit_type_free(type);
- return 0;
+ /* Set the "catcher" field within "setjmp_value" to the catcher */
+ args[0] = jit_value_create(func, jit_type_void_ptr);
+ if(!(args[0]))
+ {
+ return 0;
+ }
+ insn = _jit_block_add_insn(func->builder->current_block);
+ if(!insn)
+ {
+ return 0;
+ }
+ jit_value_ref(func, args[1]);
+ insn->opcode = JIT_OP_LOAD_CATCHER_PC;
+ insn->flags |= JIT_INSN_VALUE1_IS_LABEL;
+ insn->dest = args[0];
+ insn->value1 = (jit_value_t)(block->block_eh->catch_label);
+ if(!jit_insn_store_relative
+ (func, jit_insn_address_of(func->builder->setjmp_value),
+ jit_jmp_catcher_offset, args[0]))
+ {
+ return 0;
+ }
}
/* We are now ready to make the actual function call */
- jit_type_free(type);
return 1;
#else /* JIT_BACKEND_INTERP */
/* The interpreter handles exception frames for us */
@@ -4751,6 +4768,7 @@ static int restore_eh_frame_after_call(jit_function_t func, int flags)
return 1;
}
+#if JIT_APPLY_BROKEN_FRAME_BUILTINS != 0
/* Create the signature prototype "void (void)" */
type = jit_type_create_signature
(jit_abi_cdecl, jit_type_void, 0, 0, 0);
@@ -4759,43 +4777,34 @@ static int restore_eh_frame_after_call(jit_function_t func, int flags)
return 0;
}
- /* Set up to call the "_jit_backtrace_pop" intrinsic */
- if(!_jit_create_call_setup_insns
- (func, type, 0, 0, 0, 0, &struct_return))
- {
- jit_type_free(type);
- return 0;
- }
-
- /* Terminate the current block and then call "_jit_backtrace_pop" */
- block = _jit_block_create(func, 0);
- if(!block)
- {
- jit_type_free(type);
- return 0;
- }
- block->entered_via_top = 1;
- func->builder->current_block = block;
- insn = _jit_block_add_insn(block);
- if(!insn)
- {
- jit_type_free(type);
- return 0;
- }
- insn->opcode = JIT_OP_CALL_EXTERNAL;
- insn->flags = JIT_INSN_DEST_IS_NATIVE | JIT_INSN_VALUE1_IS_NAME;
- insn->dest = (jit_value_t)(void *)_jit_backtrace_pop;
- insn->value1 = (jit_value_t)"_jit_backtrace_pop";
+ /* Call the "_jit_backtrace_pop" function */
+ jit_insn_call_native
+ (func, "_jit_backtrace_pop",
+ (void *)_jit_backtrace_pop, type, 0, 0, JIT_CALL_NOTHROW);
+ jit_type_free(type);
+#endif
- /* Clean up after the function call */
- if(!_jit_create_call_return_insns(func, type, 0, 0, 0, 0))
+ /* Are we currently within a "try" context covered by a "catch"? */
+ block = func->builder->current_block;
+ if(block->block_eh &&
+ block->block_eh->catch_label != jit_label_undefined &&
+ func->builder->setjmp_value != 0)
{
- jit_type_free(type);
- return 0;
+ /* Set the "catcher" field within "setjmp_value" to NULL */
+ args[0] = jit_value_create_nint_constant(func, jit_type_void_ptr, 0);
+ if(!(args[0]))
+ {
+ return 0;
+ }
+ if(!jit_insn_store_relative
+ (func, jit_insn_address_of(func->builder->setjmp_value),
+ jit_jmp_catcher_offset, args[0]))
+ {
+ return 0;
+ }
}
/* Everything is back to where it should be */
- jit_type_free(type);
return 1;
#else /* JIT_BACKEND_INTERP */
/* The interpreter handles exception frames for us */
@@ -4961,12 +4970,11 @@ jit_value_t jit_insn_call
it will be eliminated during later code generation */
if((flags & JIT_CALL_NORETURN) != 0)
{
- block = _jit_block_create(func, 0);
- if(!block)
+ func->builder->current_block->ends_in_dead = 1;
+ if(!jit_insn_label(func, 0))
{
return 0;
}
- func->builder->current_block = block;
}
/* Create space for the return value, if we don't already have one */
@@ -5076,12 +5084,11 @@ jit_value_t jit_insn_call_indirect
it will be eliminated during later code generation */
if((flags & JIT_CALL_NORETURN) != 0)
{
- block = _jit_block_create(func, 0);
- if(!block)
+ func->builder->current_block->ends_in_dead = 1;
+ if(!jit_insn_label(func, 0))
{
return 0;
}
- func->builder->current_block = block;
}
/* Create space for the return value, if we don't already have one */
@@ -5193,12 +5200,11 @@ jit_value_t jit_insn_call_indirect_vtable
it will be eliminated during later code generation */
if((flags & JIT_CALL_NORETURN) != 0)
{
- block = _jit_block_create(func, 0);
- if(!block)
+ func->builder->current_block->ends_in_dead = 1;
+ if(!jit_insn_label(func, 0))
{
return 0;
}
- func->builder->current_block = block;
}
/* Create space for the return value, if we don't already have one */
@@ -5306,12 +5312,11 @@ jit_value_t jit_insn_call_native
it will be eliminated during later code generation */
if((flags & JIT_CALL_NORETURN) != 0)
{
- block = _jit_block_create(func, 0);
- if(!block)
+ func->builder->current_block->ends_in_dead = 1;
+ if(!jit_insn_label(func, 0))
{
return 0;
}
- func->builder->current_block = block;
}
/* Create space for the return value, if we don't already have one */
@@ -6218,6 +6223,184 @@ jit_value_t jit_insn_get_call_stack(jit_function_t func)
return value;
}
+/*
+ * Initialize the "setjmp" setup block that is needed to catch exceptions
+ * thrown back to this level of execution. The block looks like this:
+ *
+ * jit_jmp_buf jbuf;
+ * void *catcher;
+ *
+ * _jit_unwind_push_setjmp(&jbuf);
+ * if(setjmp(&jbuf.buf))
+ * {
+ * catcher = jbuf.catcher;
+ * if(catcher)
+ * {
+ * jbuf.catcher = 0;
+ * goto *catcher;
+ * }
+ * else
+ * {
+ * _jit_unwind_pop_and_rethrow();
+ * }
+ * }
+ *
+ * The field "jbuf.catcher" will be set to the address of the relevant
+ * "catch" block just before a subroutine call that may involve exceptions.
+ * It will be reset to NULL after such subroutine calls.
+ *
+ * Native back ends are responsible for outputting a call to the function
+ * "_jit_unwind_pop_setjmp()" just before "return" instructions if the
+ * "has_try" flag is set on the function.
+ */
+static int initialize_setjmp_block(jit_function_t func)
+{
+#if !defined(JIT_BACKEND_INTERP)
+ jit_label_t start_label = jit_label_undefined;
+ jit_label_t end_label = jit_label_undefined;
+ jit_label_t rethrow_label = jit_label_undefined;
+ jit_type_t type;
+ jit_value_t args[1];
+ jit_value_t value;
+
+ /* Bail out if we have already done this before */
+ if(func->builder->setjmp_value)
+ {
+ return 1;
+ }
+ func->builder->longjmp_label = jit_label_undefined;
+
+ /* Force the start of a new block to mark the start of the init code */
+ if(!jit_insn_label(func, &start_label))
+ {
+ return 0;
+ }
+
+ /* Create a value to hold an item of type "jit_jmp_buf" */
+ type = jit_type_create_struct(0, 0, 1);
+ if(!type)
+ {
+ return 0;
+ }
+ jit_type_set_size_and_alignment
+ (type, sizeof(jit_jmp_buf), JIT_BEST_ALIGNMENT);
+ if((func->builder->setjmp_value = jit_value_create(func, type)) == 0)
+ {
+ jit_type_free(type);
+ return 0;
+ }
+ jit_type_free(type);
+
+ /* Call "_jit_unwind_push_setjmp" with "&setjmp_value" as its argument */
+ type = jit_type_void_ptr;
+ type = jit_type_create_signature
+ (jit_abi_cdecl, jit_type_void, &type, 1, 1);
+ if(!type)
+ {
+ return 0;
+ }
+ args[0] = jit_insn_address_of(func, func->builder->setjmp_value);
+ jit_insn_call_native
+ (func, "_jit_unwind_push_setjmp",
+ (void *)_jit_unwind_push_setjmp, type, args, 1, JIT_CALL_NOTHROW);
+ jit_type_free(type);
+
+ /* Call "setjmp" with "&setjmp_value" as its argument */
+ type = jit_type_void_ptr;
+ type = jit_type_create_signature
+ (jit_abi_cdecl, jit_type_int, &type, 1, 1);
+ if(!type)
+ {
+ return 0;
+ }
+ args[0] = jit_insn_address_of(func, func->builder->setjmp_value);
+ value = jit_insn_call_native
+ (func, "setjmp", (void *)setjmp, type, args, 1, JIT_CALL_NOTHROW);
+ jit_type_free(type);
+ if(!value)
+ {
+ return 0;
+ }
+
+ /* Branch to the end of the init code if "setjmp" returned zero */
+ if(!jit_insn_branch_if_not(func, value, &end_label))
+ {
+ return 0;
+ }
+
+ /* The current point in the code is where "longjmp" will resume from */
+ if(!jit_insn_label(func, &(func->builder->longjmp_label)))
+ {
+ return 0;
+ }
+
+ /* Get the value of "catcher" from within "setjmp_value". This indicates
+ which catcher we should use to handle the thrown exception. If the
+ catcher is NULL, then we need to rethrow the exception higher up
+ because it isn't covered by any of the catch blocks that we have */
+ value = jit_insn_load_relative
+ (func, jit_insn_address_of(func, func->builder->setjmp_value),
+ jit_jmp_catcher_offset, jit_type_void_ptr);
+ if(!value)
+ {
+ return 0;
+ }
+ if(!jit_insn_branch_if_not(func, value, &rethrow_label))
+ {
+ return 0;
+ }
+
+ /* Clear the original "catcher" value within "setjmp_value" */
+ if(!jit_insn_store_relative
+ (func, jit_insn_address_of(func, func->builder->setjmp_value),
+ jit_jmp_catcher_offset, jit_value_create_nint_constant
+ (func, jit_type_void_ptr, 0)))
+ {
+ return 0;
+ }
+
+ /* Jump to the address indicated by the catcher */
+ if(!create_unary_note(func, JIT_OP_JUMP_TO_CATCHER, value))
+ {
+ return 0;
+ }
+ func->builder->current_block->ends_in_dead = 1;
+
+ /* Mark the position of the rethrow label */
+ if(!jit_insn_label(func, &rethrow_label))
+ {
+ return 0;
+ }
+
+ /* Call "_jit_unwind_pop_and_rethrow" to pop the current
+ "setjmp" context and then rethrow the current exception */
+ type = jit_type_create_signature
+ (jit_abi_cdecl, jit_type_void, 0, 0, 1);
+ if(!type)
+ {
+ return 0;
+ }
+ jit_insn_call_native
+ (func, "_jit_unwind_pop_and_rethrow",
+ (void *)_jit_unwind_pop_and_rethrow, type, 0, 0,
+ JIT_CALL_NOTHROW | JIT_CALL_NORETURN);
+ jit_type_free(type);
+
+ /* Force the start of a new block to mark the end of the init code */
+ if(!jit_insn_label(func, &end_label))
+ {
+ return 0;
+ }
+
+ /* Move the initialization code to the head of the function so that
+ it is performed once upon entry to the function */
+ return jit_insn_move_blocks_to_start(func, start_label, end_label);
+#else
+ /* The interpreter doesn't need the "setjmp" setup block */
+ return 1;
+#endif
+}
+
/*@
* @deftypefun int jit_insn_start_try (jit_function_t func, {jit_label_t *} catch_label, {jit_label_t *} finally_label, int finally_on_fault)
* Start an exception-handling @code{try} block at the current position
@@ -6280,6 +6463,12 @@ int jit_insn_start_try
register allocation */
func->has_try = 1;
+ /* Make sure that the "setjmp" setup block is present in this function */
+ if(!initialize_setjmp_block(func))
+ {
+ return 0;
+ }
+
/* Anything with a finally handler makes the function not a leaf,
because we may need to do a native "call" to invoke the handler */
if(finally_label)
diff --git a/jit/jit-internal.h b/jit/jit-internal.h
index 1dec549..1993d83 100644
--- a/jit/jit-internal.h
+++ b/jit/jit-internal.h
@@ -298,6 +298,8 @@ struct _jit_builder
/* Exception handlers for the function */
jit_block_eh_t exception_handlers;
jit_block_eh_t current_handler;
+ jit_value_t setjmp_value;
+ jit_label_t longjmp_label;
/* Flag that is set to indicate that this function is not a leaf */
int non_leaf : 1;
@@ -458,8 +460,6 @@ struct jit_backtrace
{
jit_backtrace_t parent;
void *pc;
- void *catch_pc;
- void *sp;
void *security_object;
jit_meta_free_func free_security_object;
};
@@ -467,8 +467,7 @@ struct jit_backtrace
/*
* Push a new backtrace onto the stack. The fields in "trace" are filled in.
*/
-void _jit_backtrace_push
- (jit_backtrace_t trace, void *pc, void *catch_pc, void *sp);
+void _jit_backtrace_push(jit_backtrace_t trace, void *pc);
/*
* Pop the top-most backtrace item.
diff --git a/jit/jit-interp.c b/jit/jit-interp.c
index 34bd53c..f4937c3 100644
--- a/jit/jit-interp.c
+++ b/jit/jit-interp.c
@@ -3324,7 +3324,7 @@ void _jit_run_function(jit_function_interp_t func, jit_item *args,
call_func = (jit_function_t)VM_NINT_ARG;
VM_MODIFY_PC_AND_STACK(2, 0);
entry = call_func->entry_point;
- _jit_backtrace_push(&call_trace, pc, 0, 0);
+ _jit_backtrace_push(&call_trace, pc);
if(!entry)
{
entry = _jit_function_compile_on_demand(call_func);
@@ -3341,7 +3341,7 @@ void _jit_run_function(jit_function_interp_t func, jit_item *args,
tempptr = (void *)VM_NINT_ARG;
temparg = VM_NINT_ARG2;
VM_MODIFY_PC_AND_STACK(3, 2);
- _jit_backtrace_push(&call_trace, pc, 0, 0);
+ _jit_backtrace_push(&call_trace, pc);
apply_from_interpreter((jit_type_t)tempptr,
(void *)VM_STK_PTRP2,
stacktop,
@@ -3361,7 +3361,7 @@ void _jit_run_function(jit_function_interp_t func, jit_item *args,
}
VM_MODIFY_PC_AND_STACK(1, 1);
entry = call_func->entry_point;
- _jit_backtrace_push(&call_trace, pc, 0, 0);
+ _jit_backtrace_push(&call_trace, pc);
if(!entry)
{
entry = _jit_function_compile_on_demand(call_func);
@@ -3379,7 +3379,7 @@ void _jit_run_function(jit_function_interp_t func, jit_item *args,
tempptr2 = (void *)VM_NINT_ARG2;
temparg = VM_NINT_ARG3;
VM_MODIFY_PC_AND_STACK(4, 1);
- _jit_backtrace_push(&call_trace, pc, 0, 0);
+ _jit_backtrace_push(&call_trace, pc);
apply_from_interpreter((jit_type_t)tempptr,
(void *)tempptr2,
stacktop,
@@ -4478,6 +4478,7 @@ void _jit_run_function(jit_function_interp_t func, jit_item *args,
VMCASE(JIT_OP_CALL_FILTER_RETURN):
VMCASE(JIT_OP_PREPARE_FOR_LEAVE):
VMCASE(JIT_OP_PREPARE_FOR_RETURN):
+ VMCASE(JIT_OP_JUMP_TO_CATCHER):
{
/* Shouldn't happen, but skip the instruction anyway */
VM_MODIFY_PC_AND_STACK(1, 0);
@@ -4533,7 +4534,7 @@ int jit_function_apply_vararg
}
/* Initialize the backtrace information */
- _jit_backtrace_push(&call_trace, 0, 0, 0);
+ _jit_backtrace_push(&call_trace, 0);
/* Clear the exception context */
jit_exception_clear_last();
diff --git a/jit/jit-opcode.c b/jit/jit-opcode.c
index cb5ff33..65d297d 100644
--- a/jit/jit-opcode.c
+++ b/jit/jit-opcode.c
@@ -429,6 +429,7 @@ jit_opcode_info_t const jit_opcodes[JIT_OP_NUM_OPCODES] = {
{"call_filter_return", F_(ANY, EMPTY, EMPTY)},
{"prepare_for_leave", F_(EMPTY, EMPTY, EMPTY)},
{"prepare_for_return", F_(EMPTY, EMPTY, EMPTY)},
+ {"jump_to_catcher", F_(EMPTY, PTR, EMPTY)},
/*
* Data manipulation.
diff --git a/jit/jit-setjmp.h b/jit/jit-setjmp.h
index df6b596..b2baa65 100644
--- a/jit/jit-setjmp.h
+++ b/jit/jit-setjmp.h
@@ -34,9 +34,12 @@ typedef struct jit_jmp_buf
{
jmp_buf buf;
jit_backtrace_t trace;
+ void *catcher;
struct jit_jmp_buf *parent;
} jit_jmp_buf;
+#define jit_jmp_catcher_offset \
+ ((jit_nint)&(((jit_jmp_buf *)0)->catcher))
/*
* Push a "setjmp" buffer onto the current thread's unwind stck.
@@ -48,6 +51,11 @@ void _jit_unwind_push_setjmp(jit_jmp_buf *jbuf);
*/
void _jit_unwind_pop_setjmp(void);
+/*
+ * Pop the top-most "setjmp" buffer and rethrow the current exception.
+ */
+void _jit_unwind_pop_and_rethrow(void);
+
#ifdef __cplusplus
};
#endif
generated by cgit v1.2.3 (git 2.39.1) at 2025年09月16日 21:09:00 +0000

AltStyle によって変換されたページ (->オリジナル) /