]> git.unchartedbackwaters.co.uk Git - francis/libjit.git/commitdiff
Rewrite the exception region routines to make them easier
authorRhys Weatherley <rweather@southern-storm.com.au>
Mon, 24 May 2004 04:19:42 +0000 (04:19 +0000)
committerRhys Weatherley <rweather@southern-storm.com.au>
Mon, 24 May 2004 04:19:42 +0000 (04:19 +0000)
to use from CLI and JVM style systems.

17 files changed:
ChangeLog
include/jit/jit-insn.h
include/jit/jit-opcode.h
jit/jit-block.c
jit/jit-dump.c
jit/jit-except.c
jit/jit-function.c
jit/jit-insn.c
jit/jit-internal.h
jit/jit-interp.c
jit/jit-interp.h
jit/jit-opcode.c
jit/jit-rules-arm.c
jit/jit-rules-interp.c
jit/jit-rules-x86.c
jit/jit-rules.h
jit/jit-setjmp.h

index 35b952466a1d14d3145092d3f24a57a5ebdd90e3..bb5dc29ad5b6ad658e9178e3ecca6b8d25391fbe 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,14 @@
 
+2004-05-24  Rhys Weatherley  <rweather@southern-storm.com.au>
+
+       * include/jit/jit-insn.h, include/jit/jit-opcode.h, jit/jit-block.c,
+       jit/jit-dump.c, jit/jit-except.c, jit/jit-function.c, jit/jit-insn.c,
+       jit/jit-internal.h, jit/jit-interp.c, jit/jit-interp.h,
+       jit/jit-opcode.c, jit/jit-rules-arm.c, jit/jit-rules-interp.c,
+       jit/jit-rules-x86.c, jit/jit-rules.h, jit/jit-setjmp.h:
+       rewrite the exception region routines to make them easier
+       to use from CLI and JVM style systems.
+
 2004-05-22  Rhys Weatherley  <rweather@southern-storm.com.au>
 
        * jit/jit-block.c (_jit_block_peephole_branch): don't allow
index 43318bf1579bf6f4c6c4a1f1378e39e57f26f018..d19d169654a6953acfc9bf93a5af9b5f884f651f 100644 (file)
@@ -210,6 +210,8 @@ int jit_insn_branch_if_not
        (jit_function_t func, jit_value_t value, jit_label_t *label) JIT_NOTHROW;
 jit_value_t jit_insn_address_of
        (jit_function_t func, jit_value_t value1) JIT_NOTHROW;
+jit_value_t jit_insn_address_of_label
+       (jit_function_t func, jit_label_t *label) JIT_NOTHROW;
 jit_value_t jit_insn_convert
        (jit_function_t func, jit_value_t value,
         jit_type_t type, int overflow_check) JIT_NOTHROW;
@@ -255,20 +257,26 @@ int jit_insn_return_ptr
 int jit_insn_default_return(jit_function_t func) JIT_NOTHROW;
 int jit_insn_throw(jit_function_t func, jit_value_t value) JIT_NOTHROW;
 jit_value_t jit_insn_get_call_stack(jit_function_t func) JIT_NOTHROW;
-int jit_insn_start_try
-       (jit_function_t func, jit_label_t *catch_label,
-        jit_label_t *finally_label, int finally_on_fault);
-jit_value_t jit_insn_start_catch
-       (jit_function_t func, jit_label_t *catch_label);
-int jit_insn_end_try(jit_function_t func);
-int jit_insn_start_finally(jit_function_t func, jit_label_t *finally_label);
-int jit_insn_return_from_finally(jit_function_t func);
+
+jit_value_t jit_insn_thrown_exception(jit_function_t func) JIT_NOTHROW;
+int jit_insn_uses_catcher(jit_function_t func) JIT_NOTHROW;
+jit_value_t jit_insn_start_catcher(jit_function_t func) JIT_NOTHROW;
+int jit_insn_branch_if_pc_not_in_range
+       (jit_function_t func, jit_label_t start_label,
+        jit_label_t end_label, jit_label_t *label) JIT_NOTHROW;
+int jit_insn_rethrow_unhandled(jit_function_t func) JIT_NOTHROW;
+int jit_insn_start_finally
+       (jit_function_t func, jit_label_t *finally_label) JIT_NOTHROW;
+int jit_insn_return_from_finally(jit_function_t func) JIT_NOTHROW;
+int jit_insn_call_finally
+       (jit_function_t func, jit_label_t *finally_label) JIT_NOTHROW;
 jit_value_t jit_insn_start_filter
-       (jit_function_t func, jit_label_t *label, jit_type_t type);
-int jit_insn_return_from_filter(jit_function_t func, jit_value_t value);
+       (jit_function_t func, jit_label_t *label, jit_type_t type) JIT_NOTHROW;
+int jit_insn_return_from_filter
+       (jit_function_t func, jit_value_t value) JIT_NOTHROW;
 jit_value_t jit_insn_call_filter
        (jit_function_t func, jit_label_t *label,
-        jit_value_t value, jit_type_t type);
+        jit_value_t value, jit_type_t type) JIT_NOTHROW;
 
 int jit_insn_memcpy
        (jit_function_t func, jit_value_t dest,
index 9116c0ff40e13e313bdad037f8683848b59ed363..8f51f7dfeb35bfbdb100abfc2d748178eebdd511 100644 (file)
@@ -403,17 +403,17 @@ extern    "C" {
  * Exception handling.
  */
 #define        JIT_OP_THROW                                            0x014C
-#define        JIT_OP_LOAD_PC                                          0x014D
-#define        JIT_OP_ENTER_CATCH                                      0x014E
-#define        JIT_OP_ENTER_FINALLY                            0x014F
-#define        JIT_OP_LEAVE_FINALLY                            0x0150
-#define        JIT_OP_ENTER_FILTER                                     0x0151
-#define        JIT_OP_LEAVE_FILTER                                     0x0152
-#define        JIT_OP_CALL_FILTER                                      0x0153
-#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
+#define        JIT_OP_RETHROW                                          0x014D
+#define        JIT_OP_LOAD_PC                                          0x014E
+#define        JIT_OP_LOAD_EXCEPTION_PC                        0x014F
+#define        JIT_OP_ENTER_FINALLY                            0x0150
+#define        JIT_OP_LEAVE_FINALLY                            0x0151
+#define        JIT_OP_CALL_FINALLY                                     0x0152
+#define        JIT_OP_ENTER_FILTER                                     0x0153
+#define        JIT_OP_LEAVE_FILTER                                     0x0154
+#define        JIT_OP_CALL_FILTER                                      0x0155
+#define        JIT_OP_CALL_FILTER_RETURN                       0x0156
+#define        JIT_OP_ADDRESS_OF_LABEL                         0x0157
 
 /*
  * Data manipulation.
@@ -547,6 +547,7 @@ struct jit_opcode_info
 #define        JIT_OPCODE_IS_CALL                              0x00002000
 #define        JIT_OPCODE_IS_CALL_EXTERNAL             0x00004000
 #define        JIT_OPCODE_IS_REG                               0x00008000
+#define        JIT_OPCODE_IS_ADDROF_LABEL              0x00010000
 #define        JIT_OPCODE_OPER_MASK                    0x01F00000
 #define        JIT_OPCODE_OPER_NONE                    0x00000000
 #define        JIT_OPCODE_OPER_ADD                             0x00100000
index 9517e0ec4d95ef7a6e759f853b95cf945f0774ba..ae9cb9049dcf88657b6b63c24cac627cde48ad2c 100644 (file)
@@ -43,8 +43,6 @@ void _jit_block_free(jit_function_t func)
 {
        jit_block_t current = func->builder->first_block;
        jit_block_t next;
-       jit_block_eh_t current_eh;
-       jit_block_eh_t next_eh;
        while(current != 0)
        {
                next = current->next;
@@ -52,19 +50,10 @@ void _jit_block_free(jit_function_t func)
                jit_free(current);
                current = next;
        }
-       current_eh = func->builder->exception_handlers;
-       while(current_eh != 0)
-       {
-               next_eh = current_eh->next;
-               jit_free(current_eh);
-               current_eh = next_eh;
-       }
        func->builder->first_block = 0;
        func->builder->last_block = 0;
        func->builder->entry = 0;
        func->builder->current_block = 0;
-       func->builder->exception_handlers = 0;
-       func->builder->current_handler = 0;
 }
 
 jit_block_t _jit_block_create(jit_function_t func, jit_label_t *label)
@@ -100,9 +89,6 @@ jit_block_t _jit_block_create(jit_function_t func, jit_label_t *label)
                block->label = jit_label_undefined;
        }
 
-       /* Set the exception handling context for this block */
-       block->block_eh = func->builder->current_handler;
-
        /* Add the block to the end of the function's list */
        block->next = 0;
        block->prev = func->builder->last_block;
@@ -481,11 +467,6 @@ void _jit_block_peephole_branch(jit_block_t block)
                {
                        break;
                }
-               if(new_block->block_eh != block->block_eh && insn->opcode != JIT_OP_BR)
-               {
-                       /* Conditional branches must never cross an exception context */
-                       break;
-               }
                if(new_block->first_insn < new_block->last_insn)
                {
                        /* There is more than one instruction in this block,
index 2a504e6661340c31e997c28e7948f1df990b5fe3..a48134cb3bee18d4d89bd737fabd26fc5c0265aa 100644 (file)
@@ -406,6 +406,12 @@ void jit_dump_insn(FILE *stream, jit_function_t func, jit_insn_t insn)
                putc(')', stream);
                return;
        }
+       else if((flags & JIT_OPCODE_IS_ADDROF_LABEL) != 0)
+       {
+               fprintf(stream, "address_of_label .L%ld",
+                               (long)(jit_insn_get_label(insn)));
+               return;
+       }
 
        /* Output the destination information */
        if((flags & JIT_OPCODE_DEST_MASK) != JIT_OPCODE_DEST_EMPTY &&
@@ -598,7 +604,8 @@ static void dump_interp_code(FILE *stream, void **pc, void **end)
 
                        default:
                        {
-                               if((info->flags & JIT_OPCODE_IS_BRANCH) != 0)
+                               if((info->flags & (JIT_OPCODE_IS_BRANCH |
+                                                                  JIT_OPCODE_IS_ADDROF_LABEL)) != 0)
                                {
                                        fprintf(stream, " %08lX",
                                                        (long)(jit_nint)((pc - 1) + (jit_nint)(*pc)));
index 7a63942ae174893a5bee7f8227b18c362efd04fd..2f34bf76d9b5d622c2f22f2a616eb147cd7a29dd 100644 (file)
@@ -485,7 +485,7 @@ void _jit_unwind_push_setjmp(jit_jmp_buf *jbuf)
        if(control)
        {
                jbuf->trace = control->backtrace_head;
-               jbuf->catcher = 0;
+               jbuf->catch_pc = 0;
                jbuf->parent = control->setjmp_head;
                control->setjmp_head = jbuf;
        }
index ac222291957ce4c97d71a079ad1e0622d0e52cf3..a8313264ada6edd0c6d8563db8af1e39756a93d3 100644 (file)
@@ -431,66 +431,6 @@ jit_function_t jit_function_get_nested_parent(jit_function_t func)
        }
 }
 
-/*
- * Call "finally" blocks that are relevant for a transition from
- * "src" to "dest".  "dest" should be NULL for a return instruction.
- */
-static void call_finally_blocks(jit_gencode_t gen, jit_function_t func,
-                                                               jit_block_eh_t src, jit_block_eh_t dest)
-{
-       jit_block_eh_t temp;
-
-       /* Bail out if we are branching to an inner scope, because we
-          don't need to call "finally" clauses to go further in */
-       temp = dest;
-       while(temp != 0)
-       {
-               if(temp == src)
-               {
-                       return;
-               }
-               temp = temp->parent;
-       }
-
-       /* Find the common ancestor of "src" and "dest" */
-       while(dest != 0)
-       {
-               temp = src;
-               while(temp != 0 && temp != dest)
-               {
-                       temp = temp->parent;
-               }
-               if(temp != 0)
-               {
-                       break;
-               }
-               dest = dest->parent;
-       }
-
-       /* Output all finally blocks between "src" and "dest" */
-       while(src != dest)
-       {
-               if(src->catch_label != jit_label_undefined &&
-                  !(src->finally_on_fault))
-               {
-                       /* Call "finally" from the body of the "try" */
-                       if(src->finally_label != jit_label_undefined)
-                       {
-                               _jit_gen_call_finally(gen, func, src->finally_label);
-                       }
-               }
-               else if(src->catch_label == jit_label_undefined)
-               {
-                       /* Call "finally" from the body of the "catch" */
-                       if(src->finally_label != jit_label_undefined)
-                       {
-                               _jit_gen_call_finally(gen, func, src->finally_label);
-                       }
-               }
-               src = src->parent;
-       }
-}
-
 /*
  * Compile a single basic block within a function.
  */
@@ -499,7 +439,6 @@ static void compile_block(jit_gencode_t gen, jit_function_t func,
 {
        jit_insn_iter_t iter;
        jit_insn_t insn;
-       jit_block_t branch_block;
 
        /* Iterate over all blocks in the function */
        jit_insn_iter_init(&iter, block);
@@ -519,28 +458,6 @@ static void compile_block(jit_gencode_t gen, jit_function_t func,
                        }
                        break;
 
-                       case JIT_OP_PREPARE_FOR_LEAVE:
-                       {
-                               /* Call the finally clauses that are relevant to the
-                                  "JIT_OP_BR" instruction that follows */
-                               _jit_regs_spill_all(gen);
-                               insn = jit_insn_iter_next(&iter);
-                               branch_block = jit_block_from_label
-                                       (func, (jit_label_t)(insn->dest));
-                               call_finally_blocks
-                                       (gen, func, block->block_eh, branch_block->block_eh);
-                               _jit_gen_insn(gen, func, block, insn);
-                       }
-                       break;
-
-                       case JIT_OP_PREPARE_FOR_RETURN:
-                       {
-                               /* Call all finally clauses on the way out of the function */
-                               _jit_regs_spill_all(gen);
-                               call_finally_blocks(gen, func, block->block_eh, 0);
-                       }
-                       break;
-
                        case JIT_OP_INCOMING_REG:
                        {
                                /* Assign a register to an incoming value */
@@ -626,10 +543,6 @@ int jit_function_compile(jit_function_t func)
        void *recompilable_start = 0;
        void *end;
        jit_block_t block;
-       jit_block_eh_t eh;
-       jit_block_eh_t new_eh;
-       jit_cache_eh_t cache_eh;
-       jit_cache_eh_t cache_new_eh;
        int result;
 #ifdef JIT_PROLOG_SIZE
        int have_prolog;
@@ -708,8 +621,6 @@ int jit_function_compile(jit_function_t func)
 
                /* Generate code for the blocks in the function */
                block = 0;
-               eh = 0;
-               cache_eh = 0;
                while((block = jit_block_next(func, block)) != 0)
                {
                        /* If this block is never entered, then discard it */
@@ -718,34 +629,6 @@ int jit_function_compile(jit_function_t func)
                                continue;
                        }
 
-                       /* Start a new exception region in the cache if necessary */
-                       new_eh = block->block_eh;
-                       if(new_eh && new_eh->catch_label == jit_label_undefined)
-                       {
-                               new_eh = 0;
-                       }
-                       if(new_eh != eh)
-                       {
-                               eh = new_eh;
-                               cache_new_eh = _jit_cache_alloc
-                                       (&(gen.posn), sizeof(struct jit_cache_eh));
-                               if(cache_new_eh)
-                               {
-                                       if(eh)
-                                       {
-                                               cache_new_eh->handler_label = eh->catch_label;
-                                       }
-                                       else
-                                       {
-                                               cache_new_eh->handler_label = jit_label_undefined;
-                                       }
-                                       cache_new_eh->handler = 0;
-                                       cache_new_eh->previous = cache_eh;
-                                       _jit_cache_new_region(&(gen.posn), cache_new_eh);
-                                       cache_eh = cache_new_eh;
-                               }
-                       }
-
                        /* Notify the back end that the block is starting */
                        _jit_gen_start_block(&gen, block);
        
@@ -762,20 +645,6 @@ int jit_function_compile(jit_function_t func)
                        _jit_regs_init_for_block(&gen);
                }
 
-               /* Fix up the labels for the exception regions */
-               while(cache_eh != 0)
-               {
-                       if(cache_eh->handler_label != jit_label_undefined)
-                       {
-                               block = jit_block_from_label(func, cache_eh->handler_label);
-                               if(block)
-                               {
-                                       cache_eh->handler = (unsigned char *)(block->address);
-                               }
-                       }
-                       cache_eh = cache_eh->previous;
-               }
-
                /* Output the function epilog.  All return paths will jump to here */
                _jit_gen_epilog(&gen, func);
                end = gen.posn.ptr;
index c65d5b96b4a51a13c18cd5ac476d06b4e46ac618..5ad7c0a64594b21c39e3167456512244713aa571 100644 (file)
@@ -946,6 +946,11 @@ jit_label_t jit_insn_get_label(jit_insn_t insn)
        {
                return (jit_label_t)(insn->dest);
        }
+       else if(insn && (insn->flags & JIT_INSN_VALUE1_IS_LABEL) != 0)
+       {
+               /* "address_of_label" instruction */
+               return (jit_label_t)(insn->value1);
+       }
        else
        {
                return 0;
@@ -3439,33 +3444,6 @@ jit_value_t jit_insn_sign(jit_function_t func, jit_value_t value1)
        }
 }
 
-/*
- * Output instructions to handle "finally" clauses in the current context.
- */
-static int handle_finally(jit_function_t func, int opcode)
-{
-       jit_block_eh_t eh = func->builder->current_handler;
-       while(eh != 0)
-       {
-               if(eh->finally_on_fault)
-               {
-                       /* The "finally" clause only applies to the "catch" block */
-                       if(!(eh->in_try_body) &&
-                          eh->finally_label != jit_label_undefined)
-                       {
-                               return create_noarg_note(func, opcode);
-                       }
-               }
-               else if(eh->finally_label != jit_label_undefined)
-               {
-                       /* The "finally" clause applies to "try" body and the "catch" */
-                       return create_noarg_note(func, opcode);
-               }
-               eh = eh->parent;
-       }
-       return 1;
-}
-
 /*@
  * @deftypefun int jit_insn_branch (jit_function_t func, {jit_label_t *} label)
  * Terminate the current block by branching unconditionally
@@ -3484,10 +3462,6 @@ int jit_insn_branch(jit_function_t func, jit_label_t *label)
        {
                return 0;
        }
-       if(!handle_finally(func, JIT_OP_PREPARE_FOR_LEAVE))
-       {
-               return 0;
-       }
        insn = _jit_block_add_insn(func->builder->current_block);
        if(!insn)
        {
@@ -3936,6 +3910,42 @@ jit_value_t jit_insn_address_of(jit_function_t func, jit_value_t value1)
        return result;
 }
 
+/*@
+ * @deftypefun jit_value_t jit_insn_address_of_label (jit_function_t func, {jit_label_t *} label)
+ * Get the address of @code{label} into a new temporary.  This is typically
+ * used for exception handling, to track where in a function an exception
+ * was actually thrown.
+ * @end deftypefun
+@*/
+jit_value_t jit_insn_address_of_label(jit_function_t func, jit_label_t *label)
+{
+       jit_value_t dest;
+       jit_insn_t insn;
+       if(!_jit_function_ensure_builder(func) || !label)
+       {
+               return 0;
+       }
+       if(*label == jit_label_undefined)
+       {
+               *label = (func->builder->next_label)++;
+       }
+       insn = _jit_block_add_insn(func->builder->current_block);
+       if(!insn)
+       {
+               return 0;
+       }
+       dest = jit_value_create(func, jit_type_void_ptr);
+       if(!dest)
+       {
+               return 0;
+       }
+       insn->opcode = (short)JIT_OP_ADDRESS_OF_LABEL;
+       insn->flags = JIT_INSN_VALUE1_IS_LABEL;
+       insn->dest = dest;
+       insn->value1 = (jit_value_t)label;
+       return dest;
+}
+
 /*
  * Information about the opcodes for a particular conversion.
  */
@@ -4708,13 +4718,9 @@ static int setup_eh_frame_for_call(jit_function_t func, int flags)
        jit_type_free(type);
 #endif
 
-       /* 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)
+       /* Update the "catch_pc" value to reflect the current context */
+       if(func->builder->setjmp_value != 0)
        {
-               /* Set the "catcher" field within "setjmp_value" to the catcher */
                args[0] = jit_value_create(func, jit_type_void_ptr);
                if(!(args[0]))
                {
@@ -4725,14 +4731,12 @@ static int setup_eh_frame_for_call(jit_function_t func, int flags)
                {
                        return 0;
                }
-               jit_value_ref(func, args[1]);
-               insn->opcode = JIT_OP_LOAD_CATCHER_PC;
-               insn->flags |= JIT_INSN_VALUE1_IS_LABEL;
+               jit_value_ref(func, args[0]);
+               insn->opcode = JIT_OP_LOAD_PC;
                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]))
+                        jit_jmp_catch_pc_offset, args[0]))
                {
                        return 0;
                }
@@ -4784,13 +4788,9 @@ static int restore_eh_frame_after_call(jit_function_t func, int flags)
        jit_type_free(type);
 #endif
 
-       /* 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)
+       /* Clear the "catch_pc" value for the current context */
+       if(func->builder->setjmp_value != 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]))
                {
@@ -4798,7 +4798,7 @@ static int restore_eh_frame_after_call(jit_function_t func, int flags)
                }
                if(!jit_insn_store_relative
                        (func, jit_insn_address_of(func->builder->setjmp_value),
-                        jit_jmp_catcher_offset, args[0]))
+                        jit_jmp_catch_pc_offset, args[0]))
                {
                        return 0;
                }
@@ -5873,12 +5873,6 @@ int jit_insn_return(jit_function_t func, jit_value_t value)
        type = jit_type_promote_int(type);
        if(!value || type == jit_type_void)
        {
-               /* Handle "finally" clauses if necessary */
-               if(!handle_finally(func, JIT_OP_PREPARE_FOR_RETURN))
-               {
-                       return 0;
-               }
-
                /* This function returns "void" */
                if(!create_noarg_note(func, JIT_OP_RETURN))
                {
@@ -5894,12 +5888,6 @@ int jit_insn_return(jit_function_t func, jit_value_t value)
                        return 0;
                }
 
-               /* Handle "finally" clauses if necessary */
-               if(!handle_finally(func, JIT_OP_PREPARE_FOR_RETURN))
-               {
-                       return 0;
-               }
-
                /* Create the "return" instruction */
                switch(type->kind)
                {
@@ -6050,12 +6038,6 @@ int jit_insn_return_ptr
                case JIT_TYPE_STRUCT:
                case JIT_TYPE_UNION:
                {
-                       /* Handle "finally" clauses if necessary */
-                       if(!handle_finally(func, JIT_OP_PREPARE_FOR_RETURN))
-                       {
-                               return 0;
-                       }
-
                        /* Determine the kind of structure return to use */
                        return_ptr = jit_value_get_struct_pointer(func);
                        if(return_ptr)
@@ -6223,6 +6205,26 @@ jit_value_t jit_insn_get_call_stack(jit_function_t func)
        return value;
 }
 
+/*@
+ * @deftypefun jit_value_t jit_insn_thrown_exception (jit_function_t func)
+ * Get the value that holds the most recent thrown exception.  This is
+ * typically used in @code{catch} clauses.
+ * @end deftypefun
+@*/
+jit_value_t jit_insn_thrown_exception(jit_function_t func)
+{
+       if(!_jit_function_ensure_builder(func))
+       {
+               return 0;
+       }
+       if(!(func->builder->thrown_exception))
+       {
+               func->builder->thrown_exception =
+                       jit_value_create(func, jit_type_void_ptr);
+       }
+       return func->builder->thrown_exception;
+}
+
 /*
  * Initialize the "setjmp" setup block that is needed to catch exceptions
  * thrown back to this level of execution.  The block looks like this:
@@ -6233,10 +6235,10 @@ jit_value_t jit_insn_get_call_stack(jit_function_t func)
  *      _jit_unwind_push_setjmp(&jbuf);
  *      if(setjmp(&jbuf.buf))
  *             {
- *                     catcher = jbuf.catcher;
- *                     if(catcher)
+ *                     catch_pc = jbuf.catch_pc;
+ *                     if(catch_pc)
  *                     {
- *                             jbuf.catcher = 0;
+ *                             jbuf.catch_pc = 0;
  *                             goto *catcher;
  *                     }
  *                     else
@@ -6245,7 +6247,7 @@ jit_value_t jit_insn_get_call_stack(jit_function_t func)
  *                     }
  *             }
  *
- * The field "jbuf.catcher" will be set to the address of the relevant
+ * The field "jbuf.catch_pc" 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.
  *
@@ -6269,6 +6271,7 @@ static int initialize_setjmp_block(jit_function_t func)
                return 1;
        }
        func->builder->longjmp_label = jit_label_undefined;
+       func->builder->catcher_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))
@@ -6334,23 +6337,32 @@ static int initialize_setjmp_block(jit_function_t func)
                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 */
+       /* We need a value to hold the location of the thrown exception */
+       if((func->builder->thrown_pc =
+                       jit_value_create(func, jit_type_void_ptr)) == 0)
+       {
+               return 0;
+       }
+
+       /* Get the value of "catch_pc" from within "setjmp_value" and store it
+          into the current frame.  This indicates where the exception occurred */
        value = jit_insn_load_relative
                (func, jit_insn_address_of(func, func->builder->setjmp_value),
-                jit_jmp_catcher_offset, jit_type_void_ptr);
+                jit_jmp_catch_pc_offset, jit_type_void_ptr);
        if(!value)
        {
                return 0;
        }
+       if(!jit_insn_store(func, func->builder->thrown_pc, value))
+       {
+               return 0;
+       }
        if(!jit_insn_branch_if_not(func, value, &rethrow_label))
        {
                return 0;
        }
 
-       /* Clear the original "catcher" value within "setjmp_value" */
+       /* Clear the original "catch_pc" 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
@@ -6359,12 +6371,11 @@ static int initialize_setjmp_block(jit_function_t func)
                return 0;
        }
 
-       /* Jump to the address indicated by the catcher */
-       if(!create_unary_note(func, JIT_OP_JUMP_TO_CATCHER, value))
+       /* Jump to this function's exception catcher */
+       if(!jit_insn_branch(func, &(func->builder->catcher_label))
        {
                return 0;
        }
-       func->builder->current_block->ends_in_dead = 1;
 
        /* Mark the position of the rethrow label */
        if(!jit_insn_label(func, &rethrow_label))
@@ -6397,190 +6408,148 @@ static int initialize_setjmp_block(jit_function_t func)
        return jit_insn_move_blocks_to_start(func, start_label, end_label);
 #else
        /* The interpreter doesn't need the "setjmp" setup block */
+       func->builder->catcher_label = jit_label_undefined;
        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
- * within @code{func}.
- *
- * Whenever an exception occurs in the block, execution will jump to
- * @code{catch_label}.  When execution exits the @code{try} block's scope,
- * @code{finally_label} will be called.  If @code{finally_on_fault} is
- * non-zero, then @code{finally_label} will be called for exceptions,
- * but not when control exits the @code{try} block normally.
- *
- * The @code{finally_label} parameter may be NULL if the @code{try} block
- * does not have a @code{finally} clause associated with it.
- *
- * All of the blocks between @code{jit_insn_start_try} and
- * @code{jit_insn_start_catch} are covered by the @code{catch}
- * clause and the @code{finally} clause.  Blocks between
- * @code{jit_insn_start_catch} and @code{jit_insn_end_try} are
- * covered by the @code{finally} clause.
- *
- * Calls to @code{jit_insn_branch}, @code{jit_insn_return},
- * @code{jit_insn_throw} and @code{jit_insn_rethrow} will cause
- * additional code to be output to invoke the relevant @code{finally}
- * clauses.
- *
- * The destinations for @code{jit_insn_branch_if} and
- * @code{jit_insn_branch_if_not} must never be outside the current
- * @code{finally} context.  You should always use @code{jit_insn_branch}
- * to branch out of @code{finally} contexts.
- *
- * Note: you don't need to output calls to @code{finally} clauses
- * yourself as @code{libjit} can detect when it is necessary on its own.
+ * @deftypefun int jit_insn_uses_catcher (jit_function_t func)
+ * Notify the function building process that @code{func} contains
+ * some form of @code{catch} clause for catching exceptions.  This must
+ * be called before any instruction that is covered by a @code{try},
+ * ideally at the start of the function output process.
  * @end deftypefun
 @*/
-int jit_insn_start_try
-       (jit_function_t func, jit_label_t *catch_label,
-        jit_label_t *finally_label, int finally_on_fault)
+int jit_insn_uses_catcher(jit_function_t func)
 {
-       jit_block_eh_t eh;
-       jit_block_t block;
-
-       /* Ensure that we have a function builder */
-       if(!_jit_function_ensure_builder(func) || !catch_label)
+       if(!_jit_function_ensure_builder(func))
        {
                return 0;
        }
-
-       /* Allocate the label numbers */
-       if(*catch_label == jit_label_undefined)
-       {
-               *catch_label = (func->builder->next_label)++;
-       }
-       if(finally_label && *finally_label == jit_label_undefined)
+       if(func->has_try)
        {
-               *finally_label = (func->builder->next_label)++;
+               return 1;
        }
-
-       /* This function has a "try" block.  This flag helps native
-          back ends know when they must be careful about global
-          register allocation */
        func->has_try = 1;
+       func->builder->may_throw = 1;
+       func->builder->non_leaf = 1;
+       return initialize_setjmp_block(func);
+}
 
-       /* Make sure that the "setjmp" setup block is present in this function */
-       if(!initialize_setjmp_block(func))
+/*@
+ * @deftypefun jit_value_t jit_insn_start_catcher (jit_function_t func)
+ * Start the catcher block for @code{func}.  There should be exactly one
+ * catcher block for any function that involves a @code{try}.  All
+ * exceptions that are thrown within the function will cause control
+ * to jump to this point.  Returns a value that holds the exception
+ * that was thrown.
+ * @end deftypefun
+@*/
+jit_value_t jit_insn_start_catcher(jit_function_t func)
+{
+       jit_value_t value;
+       if(!_jit_function_ensure_builder(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)
+       if(!jit_insn_label(func, &(func->builder->catcher_label)))
        {
-               func->builder->non_leaf = 1;
+               return 0;
        }
-
-       /* Create a new exception handling context and populate it */
-       eh = jit_cnew(struct jit_block_eh);
-       if(!eh)
+       value = jit_insn_thrown_exception(func);
+       if(!value)
        {
                return 0;
        }
-       eh->parent = func->builder->current_handler;
-       eh->next = func->builder->exception_handlers;
-       func->builder->exception_handlers = eh;
-       eh->catch_label = *catch_label;
-       eh->finally_label = (finally_label ? *finally_label : jit_label_undefined);
-       eh->finally_on_fault = finally_on_fault;
-       eh->in_try_body = 1;
-       func->builder->current_handler = eh;
-
-       /* Start a new block, for the body of the "try" */
-       block = _jit_block_create(func, 0);
-       if(!block)
+#if defined(JIT_BACKEND_INTERP)
+       /* In the interpreter, the exception object will be on the top of
+          the operand stack when control reaches the catcher */
+       if(!jit_insn_incoming_reg(func, value, 0))
        {
                return 0;
        }
-       block->entered_via_top = 1;
-       return 1;
+#endif
+       return value;
 }
 
 /*@
- * @deftypefun jit_value_t jit_insn_start_catch (jit_function_t func, {jit_label_t *} catch_label)
- * Start the @code{catch} clause for the currently active @code{try}
- * block.  Returns a pointer @code{value} that indicates the exception
- * that is thrown.
- *
- * There can be only one @code{catch} clause per @code{try} block.
- * The front end is responsible for outputting instructions that
- * inspect the exception object, determine if it is appropriate to
- * the clause, and then either handle it or rethrow it.
- *
- * Every @code{try} block must have an associated @code{catch} clause,
- * even if all it does is rethrow the exception immediately.  Without a
- * @code{catch} clause, the correct @code{finally} logic will not be
- * performed for thrown exceptions.
+ * @deftypefun int jit_insn_branch_if_pc_not_in_range (jit_function_t func, jit_label_t start_label, jit_label_t end_label, {jit_label_t *} label)
+ * Branch to @code{label} if the program counter where an exception occurred
+ * does not fall between @code{start_label} and @code{end_label}.
  * @end deftypefun
 @*/
-jit_value_t jit_insn_start_catch
-       (jit_function_t func, jit_label_t *catch_label)
+int jit_insn_branch_if_pc_not_in_range
+       (jit_function_t func, jit_label_t start_label,
+        jit_label_t end_label, jit_label_t *label)
 {
-       jit_block_eh_t eh;
-       jit_block_eh_t new_eh;
+       jit_value_t value1;
+       jit_value_t value2;
 
-       /* Ensure that we have a function builder */
+       /* Ensure that we have a function builder and a try block */
        if(!_jit_function_ensure_builder(func))
        {
                return 0;
        }
+       if(!(func->has_try))
+       {
+               return 0;
+       }
 
-       /* Create a new exception handler to indicate that we are in a "catch" */
-       eh = func->builder->current_handler;
-       if(!eh)
+       /* Get the location where the exception occurred in this function */
+#if defined(JIT_BACKEND_INTERP)
+       value1 = create_dest_note
+               (func, JIT_OP_LOAD_EXCEPTION_PC, jit_type_void_ptr);
+#else
+       value1 = func->builder->thrown_pc;
+#endif
+       if(!value1)
        {
                return 0;
        }
-       new_eh = jit_cnew(struct jit_block_eh);
-       if(!new_eh)
+
+       /* Compare the location against the start and end labels */
+       value2 = jit_insn_address_of_label(func, &start_label);
+       if(!value2)
        {
                return 0;
        }
-       new_eh->parent = eh->parent;
-       new_eh->next = func->builder->exception_handlers;
-       func->builder->exception_handlers = new_eh;
-       if(eh->finally_label != jit_label_undefined)
+       if(!jit_insn_branch_if(func, jit_insn_lt(func, value1, value2), label))
        {
-               /* We will need a mini "catch" block to call the "finally"
-                  clause when an exception occurs within the "catch" */
-               new_eh->catch_label = (func->builder->next_label)++;
+               return 0;
        }
-       else
+       value2 = jit_insn_address_of_label(func, &end_label);
+       if(!value2)
        {
-               new_eh->catch_label = jit_label_undefined;
+               return 0;
        }
-       new_eh->finally_label = eh->finally_label;
-       new_eh->finally_on_fault = eh->finally_on_fault;
-       new_eh->in_try_body = 0;
-       func->builder->current_handler = new_eh;
-
-       /* Start a new block for the "catch" clause */
-       if(!jit_insn_label(func, catch_label))
+       if(!jit_insn_branch_if(func, jit_insn_ge(func, value1, value2), label))
        {
                return 0;
        }
 
-       /* Output an instruction to notice the caught value */
-       return create_dest_note(func, JIT_OP_ENTER_CATCH, jit_type_void_ptr);
+       /* If control gets here, then we have a location match */
+       return 1;
 }
 
 /*@
- * @deftypefun int jit_insn_end_try (jit_function_t func)
- * Mark the end of the @code{try} block and its associated @code{catch}
- * clause.  This is normally followed by a call to
- * @code{jit_insn_start_finally} to define the @code{finally} clause.
+ * @deftypefun int jit_insn_rethrow_unhandled (jit_function_t func)
+ * Rethrow the current exception because it cannot be handled by
+ * any of the @code{catch} blocks in the current function.
+ *
+ * Note: this is intended for use within catcher blocks.  It should not
+ * be used to rethrow exceptions in response to programmer requests
+ * (e.g. @code{throw;} in C#).  The @code{jit_insn_throw} function
+ * should be used for that purpose.
  * @end deftypefun
 @*/
-int jit_insn_end_try(jit_function_t func)
+int jit_insn_rethrow_unhandled(jit_function_t func)
 {
-       jit_block_eh_t eh;
        jit_block_t block;
        jit_value_t value;
+#if !defined(JIT_BACKEND_INTERP)
+       jit_type_t type;
+#endif
 
        /* Ensure that we have a function builder */
        if(!_jit_function_ensure_builder(func))
@@ -6588,48 +6557,69 @@ int jit_insn_end_try(jit_function_t func)
                return 0;
        }
 
-       /* Get the current exception handling context */
-       eh = func->builder->current_handler;
-       if(!eh)
+       /* Get the current exception value to be thrown */
+       value = jit_insn_thrown_exception(func);
+       if(!value)
        {
                return 0;
        }
 
-       /* We may need another mini "catch" block to invoke the "finally"
-          clause for exceptions that happen during the "catch" */
-       if(eh->catch_label != jit_label_undefined)
+#if defined(JIT_BACKEND_INTERP)
+
+       /* Rethrow the current exception (interpreter version) */
+       if(!create_unary_note(func, JIT_OP_RETHROW, value))
        {
-               /* TODO: not quite right */
-               if(!jit_insn_label(func, &(eh->catch_label)))
-               {
-                       return 0;
-               }
-               value = create_dest_note(func, JIT_OP_ENTER_CATCH, jit_type_void_ptr);
-               if(!value)
-               {
-                       return 0;
-               }
-               if(!jit_insn_throw(func, value))
-               {
-                       return 0;
-               }
+               return 0;
+       }
+
+#else /* !JIT_BACKEND_INTERP */
+
+       /* Call "_jit_unwind_pop_setjmp" to remove the current exception catcher */
+       if(!_jit_function_ensure_builder(func))
+       {
+               return 0;
+       }
+       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);
+
+       /* Call the "jit_exception_throw" function to effect the rethrow */
+       type = jit_type_void_ptr;
+       type = jit_type_create_signature
+               (jit_abi_cdecl, jit_type_void, &type, 1, 1);
+       if(!type)
+       {
+               return 0;
        }
+       jit_insn_call_native
+               (func, "jit_exception_throw",
+                (void *)jit_exception_throw, type, &value, 1,
+                JIT_CALL_NOTHROW | JIT_CALL_NORETURN);
+       jit_type_free(type);
 
-       /* Pop the current exception context */
-       func->builder->current_handler = eh->parent;
+#endif /* !JIT_BACKEND_INTERP */
 
-       /* Start a new block, covered by the next outer "try" context */
+       /* The current block ends in dead and we need to start a new block */
+       func->builder->current_block->ends_in_dead = 1;
        block = _jit_block_create(func, 0);
        if(!block)
        {
                return 0;
        }
+       func->builder->current_block = block;
        return 1;
 }
 
 /*@
  * @deftypefun int jit_insn_start_finally (jit_function_t func, {jit_label_t *} finally_label)
- * Start the @code{finally} clause for the preceding @code{try} block.
+ * Start a @code{finally} clause.
  * @end deftypefun
 @*/
 int jit_insn_start_finally(jit_function_t func, jit_label_t *finally_label)
@@ -6669,6 +6659,20 @@ int jit_insn_return_from_finally(jit_function_t func)
        return 1;
 }
 
+/*@
+ * @deftypefun int jit_insn_call_finally (jit_function_t func, {jit_label_t *} finally_label)
+ * Call a @code{finally} clause.
+ * @end deftypefun
+@*/
+int jit_insn_call_finally(jit_function_t func, jit_label_t *finally_label)
+{
+       if(!jit_insn_label(func, finally_label))
+       {
+               return 0;
+       }
+       return create_noarg_note(func, JIT_OP_CALL_FINALLY);
+}
+
 /*@
  * @deftypefun jit_value_t jit_insn_start_filter (jit_function_t func, {jit_label_t *} label, jit_type_t type)
  * Define the start of a filter.  Filters are embedded subroutines within
index 1993d832549f62e7665aaa937e775d70f5986c58..d044b46e21f3a81cd6e704156791a44769238fab 100644 (file)
@@ -169,20 +169,6 @@ struct _jit_meta
        jit_function_t          pool_owner;
 };
 
-/*
- * Exception handling information that is attached to blocks.
- */
-typedef struct jit_block_eh *jit_block_eh_t;
-struct jit_block_eh
-{
-       jit_block_eh_t          parent;
-       jit_block_eh_t          next;
-       jit_label_t                     catch_label;
-       jit_label_t                     finally_label;
-       int                                     finally_on_fault : 1;
-       int                                     in_try_body : 1;
-};
-
 /*
  * Internal structure of a block.
  */
@@ -195,7 +181,6 @@ struct _jit_block
        jit_block_t             next;
        jit_block_t             prev;
        jit_meta_t                      meta;
-       jit_block_eh_t          block_eh;
        int                                     entered_via_top : 1;
        int                                     entered_via_branch : 1;
        int                                     ends_in_dead : 1;
@@ -261,10 +246,11 @@ struct _jit_insn
 #define        JIT_INSN_DEST_IS_NATIVE                 0x0100
 #define        JIT_INSN_DEST_OTHER_FLAGS               0x01C0
 #define        JIT_INSN_VALUE1_IS_NAME                 0x0200
-#define        JIT_INSN_VALUE1_OTHER_FLAGS             0x0200
-#define        JIT_INSN_VALUE2_IS_SIGNATURE    0x0400
-#define        JIT_INSN_VALUE2_OTHER_FLAGS             0x0400
-#define        JIT_INSN_DEST_IS_VALUE                  0x0800
+#define        JIT_INSN_VALUE1_IS_LABEL                0x0400
+#define        JIT_INSN_VALUE1_OTHER_FLAGS             0x0600
+#define        JIT_INSN_VALUE2_IS_SIGNATURE    0x0800
+#define        JIT_INSN_VALUE2_OTHER_FLAGS             0x0800
+#define        JIT_INSN_DEST_IS_VALUE                  0x1000
 
 /*
  * Information that is associated with a function for building
@@ -295,11 +281,13 @@ struct _jit_builder
        jit_block_t                     init_block;
        int                                     init_insn;
 
-       /* Exception handlers for the function */
-       jit_block_eh_t          exception_handlers;
-       jit_block_eh_t          current_handler;
+       /* Exception handling definitions for the function */
        jit_value_t                     setjmp_value;
        jit_label_t                     longjmp_label;
+       jit_value_t                     thrown_exception;
+       jit_value_t                     thrown_pc;
+       jit_label_t                     catcher_label;
+       jit_value_t                     eh_frame_info;
 
        /* Flag that is set to indicate that this function is not a leaf */
        int                                     non_leaf : 1;
@@ -329,9 +317,6 @@ struct _jit_builder
        jit_value_t                     struct_return;
        jit_value_t                     parent_frame;
 
-       /* The value that holds the exception frame information for a callout */
-       jit_value_t                     eh_frame_info;
-
        /* Metadata that is stored only while the function is being built */
        jit_meta_t                      meta;
 
index f4937c30ab14a81217c82f50a4740d9b9551add6..1e24102c991f7c46436132e2765d63c0f3657e88 100644 (file)
@@ -241,6 +241,7 @@ void _jit_run_function(jit_function_interp_t func, jit_item *args,
        struct jit_backtrace call_trace;
        void *entry;
        void *exception_object = 0;
+       void *exception_pc = 0;
        void *handler;
        jit_jmp_buf *jbuf;
 
@@ -3553,6 +3554,7 @@ void _jit_run_function(jit_function_interp_t func, jit_item *args,
                        /* Throw an exception, which may be handled in this function */
                        exception_object = VM_STK_PTR0;
                handle_exception:
+                       exception_pc = pc;
                        if(jit_function_from_pc(func->func->context, pc, &handler)
                                        == func->func && handler != 0)
                        {
@@ -3570,6 +3572,14 @@ void _jit_run_function(jit_function_interp_t func, jit_item *args,
                }
                VMBREAK;
 
+               VMCASE(JIT_OP_RETHROW):
+               {
+                       /* Rethrow an exception to the caller */
+                       _jit_unwind_pop_setjmp();
+                       jit_exception_throw(VM_STK_PTR0);
+               }
+               VMBREAK;
+
                VMCASE(JIT_OP_LOAD_PC):
                {
                        /* Load the current program counter onto the stack */
@@ -3578,6 +3588,14 @@ void _jit_run_function(jit_function_interp_t func, jit_item *args,
                }
                VMBREAK;
 
+               VMCASE(JIT_OP_LOAD_EXCEPTION_PC):
+               {
+                       /* Load the address where the exception occurred onto the stack */
+                       VM_STK_PTRP = (void *)exception_pc;
+                       VM_MODIFY_PC_AND_STACK(1, -1);
+               }
+               VMBREAK;
+
                VMCASE(JIT_OP_LEAVE_FINALLY):
                {
                        /* Return from a "finally" handler */
@@ -3614,6 +3632,14 @@ void _jit_run_function(jit_function_interp_t func, jit_item *args,
                }
                VMBREAK;
 
+               VMCASE(JIT_OP_ADDRESS_OF_LABEL):
+               {
+                       /* Load the address of a label onto the stack */
+                       VM_STK_PTRP = VM_BR_TARGET;
+                       VM_MODIFY_PC_AND_STACK(2, -1);
+               }
+               VMBREAK;
+
                /******************************************************************
                 * Pointer-relative loads and stores.
                 ******************************************************************/
@@ -4472,13 +4498,9 @@ void _jit_run_function(jit_function_interp_t func, jit_item *args,
                VMCASE(JIT_OP_PUSH_FLOAT64):
                VMCASE(JIT_OP_PUSH_NFLOAT):
                VMCASE(JIT_OP_FLUSH_SMALL_STRUCT):
-               VMCASE(JIT_OP_ENTER_CATCH):
                VMCASE(JIT_OP_ENTER_FINALLY):
                VMCASE(JIT_OP_ENTER_FILTER):
                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);
index fdffa24cd20fa6c265cb8af8eef7c9fa5e52ee12..2939aeeedd0383a3b693b8991932bda1338d27cd 100644 (file)
@@ -167,11 +167,6 @@ struct jit_function_interp
 #define        JIT_OP_PUSH_CONST_FLOAT64                       (JIT_OP_NUM_OPCODES + 0x0036)
 #define        JIT_OP_PUSH_CONST_NFLOAT                        (JIT_OP_NUM_OPCODES + 0x0037)
 
-/*
- * Exception handling (interpreter-only).
- */
-#define        JIT_OP_CALL_FINALLY                                     (JIT_OP_NUM_OPCODES + 0x0038)
-
 /*
  * Marker opcode for the end of the interpreter-specific opcodes.
  */
index 65d297ddceeecafb9d8a4b5d5995cad221c5e4d8..a2621d452433a6fcdab140148b96d403a3561242 100644 (file)
@@ -419,17 +419,17 @@ jit_opcode_info_t const jit_opcodes[JIT_OP_NUM_OPCODES] = {
         * Exception handling.
         */
        {"throw",                                               F_(EMPTY, PTR, EMPTY)},
+       {"rethrow",                                             F_(EMPTY, PTR, EMPTY)},
        {"load_pc",                                             F_(PTR, EMPTY, EMPTY)},
-       {"enter_catch",                                 F_(PTR, EMPTY, EMPTY)},
+       {"load_exception_pc",                   F_(PTR, EMPTY, EMPTY)},
        {"enter_finally",                               F_(EMPTY, EMPTY, EMPTY)},
        {"leave_finally",                               F_(EMPTY, EMPTY, EMPTY)},
+       {"call_finally",                                B_(EMPTY, EMPTY)},
        {"enter_filter",                                F_(ANY, EMPTY, EMPTY)},
        {"leave_filter",                                F_(EMPTY, ANY, EMPTY)},
        {"call_filter",                                 B_(ANY, EMPTY)},
        {"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)},
+       {"address_of_label",                    JIT_OPCODE_IS_ADDROF_LABEL},
 
        /*
         * Data manipulation.
@@ -607,11 +607,6 @@ jit_opcode_info_t const _jit_interp_opcodes[JIT_OP_NUM_INTERP_OPCODES] = {
        {"push_const_float64",                  JIT_OPCODE_CONST_FLOAT64},
        {"push_const_nfloat",                   JIT_OPCODE_CONST_NFLOAT},
 
-       /*
-        * Exception handling (interpreter only).
-        */
-       {"call_finally",                                B_(EMPTY, EMPTY)},
-
        /*
         * Marker opcode for the end of a function.
         */
index 28bb7ebac1d3636eba2a808d9643aa0fd8698b83..7f3a228f149f606d744c31ce5390080486d08ed7 100644 (file)
@@ -655,15 +655,4 @@ void _jit_gen_end_block(jit_gencode_t gen, jit_block_t block)
        /* Nothing to do here for ARM */
 }
 
-void _jit_gen_call_finally
-       (jit_gencode_t gen, jit_function_t func, jit_label_t label)
-{
-       /* TODO */
-}
-
-void _jit_gen_unwind_stack(void *stacktop, void *catch_pc, void *object)
-{
-       /* TODO */
-}
-
 #endif /* JIT_BACKEND_ARM */
index b092adebfc42cbe1d5ca1488932bfd88595b9e8a..2b0bebcc5258891c62cfcce24da0e666f1a0d471 100644 (file)
@@ -886,6 +886,7 @@ void _jit_gen_insn(jit_gencode_t gen, jit_function_t func,
        switch(insn->opcode)
        {
                case JIT_OP_BR:
+               case JIT_OP_CALL_FINALLY:
                {
                        /* Unconditional branch */
                        _jit_regs_spill_all(gen);
@@ -1006,6 +1007,38 @@ void _jit_gen_insn(jit_gencode_t gen, jit_function_t func,
                }
                /* Not reached */
 
+               case JIT_OP_ADDRESS_OF_LABEL:
+               {
+                       /* Get the address of a particular label */
+                       if(_jit_regs_num_used(gen, 0) >= JIT_NUM_REGS)
+                       {
+                               _jit_regs_spill_all(gen);
+                       }
+                       reg = _jit_regs_new_top(gen, insn->dest, 0);
+                       adjust_working(gen, 1);
+                       label = (jit_label_t)(insn->value1);
+                       pc = (void **)(gen->posn.ptr);
+                       jit_cache_opcode(&(gen->posn), insn->opcode);
+                       block = jit_block_from_label(func, label);
+                       if(!block)
+                       {
+                               break;
+                       }
+                       if(block->address)
+                       {
+                               /* We already know the address of the block */
+                               jit_cache_native
+                                       (&(gen->posn), ((void **)(block->address)) - pc);
+                       }
+                       else
+                       {
+                               /* Record this position on the block's fixup list */
+                               jit_cache_native(&(gen->posn), block->fixup_list);
+                               block->fixup_list = (void *)pc;
+                       }
+               }
+               break;
+
                case JIT_OP_CALL:
                case JIT_OP_CALL_TAIL:
                {
@@ -1160,6 +1193,7 @@ void _jit_gen_insn(jit_gencode_t gen, jit_function_t func,
                break;
 
                case JIT_OP_LOAD_PC:
+               case JIT_OP_LOAD_EXCEPTION_PC:
                {
                        /* Load the current program counter onto the stack */
                        if(_jit_regs_num_used(gen, 0) >= JIT_NUM_REGS)
@@ -1172,7 +1206,6 @@ void _jit_gen_insn(jit_gencode_t gen, jit_function_t func,
                }
                break;
 
-               case JIT_OP_ENTER_CATCH:
                case JIT_OP_CALL_FILTER_RETURN:
                {
                        /* The top of stack currently contains "dest" */
@@ -1628,48 +1661,4 @@ void _jit_gen_end_block(jit_gencode_t gen, jit_block_t block)
        gen->working_area = 0;
 }
 
-/*@
- * @deftypefun void _jit_gen_call_finally (jit_gencode_t gen, jit_function_t func, jit_label_t label)
- * Call a @code{finally} clause at @code{label}.
- * @end deftypefun
-@*/
-void _jit_gen_call_finally
-       (jit_gencode_t gen, jit_function_t func, jit_label_t label)
-{
-       jit_block_t block;
-       void **pc;
-       _jit_regs_spill_all(gen);
-       pc = (void **)(gen->posn.ptr);
-       jit_cache_opcode(&(gen->posn), JIT_OP_CALL_FINALLY);
-       block = jit_block_from_label(func, label);
-       if(!block)
-       {
-               return;
-       }
-       if(block->address)
-       {
-               /* We already know the address of the block */
-               jit_cache_native
-                       (&(gen->posn), ((void **)(block->address)) - pc);
-       }
-       else
-       {
-               /* Record this position on the block's fixup list */
-               jit_cache_native(&(gen->posn), block->fixup_list);
-               block->fixup_list = (void *)pc;
-       }
-}
-
-/*@
- * @deftypefun void _jit_gen_unwind_stack ({void *} stacktop, {void *} catch_pc, {void *} object)
- * Unwind the stack back to @code{stacktop}, restore the frame, and
- * jump to @code{catch_pc}.  The registers are set up to arrange for
- * @code{object} to be in the right place for a @code{catch} clause.
- * @end deftypefun
-@*/
-void _jit_gen_unwind_stack(void *stacktop, void *catch_pc, void *object)
-{
-       /* Not used by the interpreted back end */
-}
-
 #endif /* JIT_BACKEND_INTERP */
index 441463536e420cfc01d2647f81b79d0c057a8818..ab3a56f508626cc2acdf403b9be4592f2e6781b9 100644 (file)
@@ -1544,75 +1544,4 @@ void _jit_gen_end_block(jit_gencode_t gen, jit_block_t block)
        /* Nothing to do here for x86 */
 }
 
-void _jit_gen_call_finally
-       (jit_gencode_t gen, jit_function_t func, jit_label_t label)
-{
-       /* TODO */
-}
-
-void _jit_gen_unwind_stack(void *stacktop, void *catch_pc, void *object)
-{
-       void *frame;
-
-       /* Fetch the proper EBP value from the stack, just before
-          where we need to unwind back to */
-       frame = ((void **)stacktop)[-2];
-
-       /* Unwind the stack and jump to "catch_pc" */
-#if defined(__GNUC__)
-       __asm__ (
-               "movl %0, %%edx\n\t"
-               "movl %1, %%eax\n\t"
-               "movl %2, %%ecx\n\t"
-               "movl %3, %%ebx\n\t"
-               "movl %%ebx, %%ebp\n\t"
-               "movl %%edx, %%esp\n\t"
-               "jmp *(%%eax)\n\t"
-               : : "m"(stacktop), "m"(catch_pc), "m"(object), "m"(frame)
-               : "eax", "ebx", "ecx", "edx"
-       );
-#elif defined(_MSC_VER)
-       __asm {
-               mov edx, dword ptr stacktop
-               mov eax, dword ptr catch_pc
-               mov ecx, dword ptr object
-               mov ebx, dword ptr frame
-               mov ebp, ebx
-               mov esp, edx
-               jmp [eax]
-       }
-#else
-       #error "Don't know how to unwind the stack under x86"
-#endif
-}
-
-void _jit_unwind_stack(void *frame, void *pc, void *object)
-{
-#if defined(__GNUC__)
-       __asm__ (
-               "movl %0, %%edx\n\t"
-               "movl %1, %%eax\n\t"
-               "movl %2, %%ecx\n\t"
-               "movl %%edx, %%ebp\n\t"
-               "popl %%ebp\n\t"
-               "popl %%edx\n\t"
-               "jmp *%%eax\n\t"
-               : : "m"(frame), "m"(pc), "m"(object)
-               : "eax", "ecx", "edx"
-       );
-#elif defined(_MSC_VER)
-       __asm {
-               mov edx, dword ptr frame
-               mov eax, dword ptr pc
-               mov ecx, dword ptr object
-               mov ebp, edx
-               pop ebp
-               pop edx
-               jmp eax
-       }
-#else
-       #error "Don't know how to unwind the stack on x86 platforms"
-#endif
-}
-
 #endif /* JIT_BACKEND_X86 */
index 0337f714046b37ce27ba4035d8ef3cd81d12ac98..7b48b5807f2d5e443b58264f3411add0c4e5f1e0 100644 (file)
@@ -181,9 +181,6 @@ void _jit_gen_insn(jit_gencode_t gen, jit_function_t func,
                                   jit_block_t block, jit_insn_t insn);
 void _jit_gen_start_block(jit_gencode_t gen, jit_block_t block);
 void _jit_gen_end_block(jit_gencode_t gen, jit_block_t block);
-void _jit_gen_call_finally
-       (jit_gencode_t gen, jit_function_t func, jit_label_t label);
-void _jit_gen_unwind_stack(void *stacktop, void *catch_pc, void *object);
 
 /*
  * Determine the byte number within a "jit_int" where the low
index b2baa65b971ed9c231eed23ca89d117ab131daff..1b0bafec8eba9047aa285293652bfb433c1b707c 100644 (file)
@@ -34,12 +34,12 @@ typedef struct jit_jmp_buf
 {
        jmp_buf                         buf;
        jit_backtrace_t         trace;
-       void                       *catcher;
+       void                       *catch_pc;
        struct jit_jmp_buf *parent;
 
 } jit_jmp_buf;
-#define        jit_jmp_catcher_offset  \
-                       ((jit_nint)&(((jit_jmp_buf *)0)->catcher))
+#define        jit_jmp_catch_pc_offset \
+                       ((jit_nint)&(((jit_jmp_buf *)0)->catch_pc))
 
 /*
  * Push a "setjmp" buffer onto the current thread's unwind stck.