dotgnu-pnet-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[dotgnu-pnet-commits] [SCM] DotGNU Portable.NET engine, compilers and to


From: Klaus Treichel
Subject: [dotgnu-pnet-commits] [SCM] DotGNU Portable.NET engine, compilers and tools (pnet) branch, master, updated. c889429b348b4df74f4597ac5cd3bcc0b8db132d
Date: Sun, 02 Jan 2011 18:26:15 +0000

This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "DotGNU Portable.NET engine, compilers and tools (pnet)".

The branch, master has been updated
       via  c889429b348b4df74f4597ac5cd3bcc0b8db132d (commit)
      from  71286bbfa6b06a15aa797ec336b7eb613659830f (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
http://git.savannah.gnu.org/cgit/pnet.git/commit/?id=c889429b348b4df74f4597ac5cd3bcc0b8db132d

commit c889429b348b4df74f4597ac5cd3bcc0b8db132d
Author: Klaus Treichel <address@hidden>
Date:   Sun Jan 2 19:25:18 2011 +0100

    Complete rework of exception handling in verification, cvm and jit coder.

diff --git a/ChangeLog b/ChangeLog
index 0deb693..59ecdea 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,56 @@
+2011-01-02  Klaus Treichel  <address@hidden>
+
+       * engine/call.c (_ILCallMethod): Don't copy the currentException back
+       to the thrownException anymore if built with libjit.
+
+       * engine/cvm.c, engine/cvm_arith.c, engine/cvm_call.c, 
engine/cvm_except.c:
+       Change exception handling from code to unwind table based.
+       Fix catching exceptions in finally/fault blocks.
+       Add support for filter based exceptions.
+
+       * engine/cvm.h: Mark some prefixed opcodes for exception handling
+       obsolete or replace them by new ones.
+       Add declaration of the cvm unwind information structs.
+
+       * engine/cvm_lengths.c: Adjust to the opcode changes in cvm.h
+
+       * engine/cvmc.c: Adjust the cvm coder to match the new coder structure.
+
+       * engine/cvmc_except.c (CVMCoder_jsr, CVMCoder_RetFromJsr): removed
+       (CVMCoder_TryHandlerStart, CVMCoder_TryHandlerEnd): ditto
+       (CVMCoder_Catch, CVMCoder_EndCatchFinally, CVMCoder_Finally): ditto
+       (CVMCoder_CallFinally, CVMCoder_RetFromFinally): added
+       (CVMCoder_LeaveCatch, CVMCoder_RetFromFilter): ditto
+       (CVMCoder_OutputExceptionTable): Add function to convert the coder
+       exception structure to the cvm structure.
+
+       * engine/jitc.c: Adjust the jit coder to match the new coder structure.
+
+       * engine/jitc_branch.c (JITCoder_Label): Add handling of start labels of
+       catch and filter blocks.
+       (OutputCompare): Do some reformatting.
+
+       * engine/jitc_except.c: Rework generation of the exception handling 
code.
+
+       * engine/jitc_labels.c: Add label type for filter block starts.
+
+       * engine/null_coder.c: Adjust the null coder to match the new coder
+       structure.
+
+       * engine/verify.c: Add functions for creating the coder exception block
+       structure from the method's exception regions.
+       (_ILVerify): Create the coder exception structure from the method's
+       exception regions.
+       Add more verification checks of the exception regions.
+       Change the exceptional synchronized method exit handling to
+       adding an extra fault block for the whole method to exit the monitor.
+
+       * engine/verify_except.c: Rework verification and generation of 
exception
+       handling opcodes. Fix support for filters.
+
+       * include/il_coder.h: Add coder specific exception block structs.
+       Modify the coder structure and adjust the corresponding macros.
+
 2010-12-26  Klaus Treichel  <address@hidden>
 
        * engine/cvm_config.h: Add the vmbreak barrier definitions for arm
diff --git a/engine/call.c b/engine/call.c
index 9464c7e..0da6407 100644
--- a/engine/call.c
+++ b/engine/call.c
@@ -1150,8 +1150,6 @@ int _ILCallMethod(ILExecThread *thread, ILMethod *method,
                return 0;
        }
        /* If we get here there is an unhandled exception. */
-       /* We need to set the thread->thrownException. */
-       thread->thrownException = thread->currentException;
        return 1;
 }
 #else
diff --git a/engine/cvm.c b/engine/cvm.c
index 6a2131d..9aa2484 100644
--- a/engine/cvm.c
+++ b/engine/cvm.c
@@ -41,6 +41,51 @@ extern       "C" {
  * are now in "cvm_config.h".
  */
 
+/*
+ * Return values for ILCVMInterpreter.
+ */
+
+/*
+ * Return value for normal exit
+ */
+#define _CVM_EXIT_OK                                           0
+/*
+ * Return value for exit with an exception pending
+ */
+#define _CVM_EXIT_EXCEPT                                       1
+
+/*
+ * Additional return values for the interpreter function.
+ */
+/*
+ * Return value if an exception is thrown.
+ * Exception handling has to be performed.
+ */
+#define _CVM_EXIT_THROW                                                2
+/*
+ * Return value for propagating a ThreadAbortException.
+ */
+#define _CVM_EXIT_PROPAGATE_ABORT                      3
+/*
+ * Return value for normal returning from a finally, fault or filter block.
+ */
+#define _CVM_EXIT_RETURN                                       4
+/*
+ * Return value from unwind to execute a handler by the caller.
+ */
+#define _CVM_EXIT_EXECUTE_HANDLER                      5
+/*
+ * Return value for continuing to unwind in the caller.
+ * This is for keeping the call nesting level as small as possible.
+ */
+#define _CVM_EXIT_CONTINUE_UNWIND                      6
+
+/*
+ * Return values from a filter call as specified in ECMA
+ */
+#define _CVM_EXCEPTION_CONTINUE_SEARCH         0
+#define _CVM_EXCEPTION_EXECUTE_HANDLER         1
+
 #if !defined(IL_NO_REGISTERS_USED)
 #if defined(CVM_X86) && defined(__GNUC__) && !defined(IL_NO_ASM)
        /*
@@ -231,16 +276,12 @@ extern    "C" {
        #define END_NULL_CHECK()
 #else
        #define BEGIN_NULL_CHECK(x) \
-               if ((x) != 0) \
+               if ((x) == 0) goto throwNullReferenceException; \
                {
 
        #define BEGIN_NULL_CHECK_STMT(x) BEGIN_NULL_CHECK(x)
 
        #define END_NULL_CHECK() \
-               } \
-               else \
-               { \
-                       NULL_POINTER_EXCEPTION(); \
                }
 #endif
 
@@ -303,11 +344,7 @@ extern     "C" {
  */
 #define        OVERFLOW_EXCEPTION()    \
                        do { \
-                               COPY_STATE_TO_THREAD(); \
-                               stacktop[0].ptrValue = \
-                                       _ILSystemException(thread, 
"System.OverflowException"); \
-                               stacktop += 1; \
-                               goto throwException; \
+                               goto throwOverflowException; \
                        } while (0)
 
 /*
@@ -315,11 +352,7 @@ extern     "C" {
  */
 #define        ARITHMETIC_EXCEPTION()  \
                        do { \
-                               COPY_STATE_TO_THREAD(); \
-                               stacktop[0].ptrValue = \
-                                       _ILSystemException(thread, 
"System.ArithmeticException"); \
-                               stacktop += 1; \
-                               goto throwException; \
+                               goto throwArithmeticException; \
                        } while (0)
 
 /*
@@ -327,12 +360,7 @@ extern     "C" {
  */
 #define        ZERO_DIV_EXCEPTION()    \
                        do { \
-                               COPY_STATE_TO_THREAD(); \
-                               stacktop[0].ptrValue = \
-                                       _ILSystemException(thread, \
-                                                                          
"System.DivideByZeroException"); \
-                               stacktop += 1; \
-                               goto throwException; \
+                               goto throwDivideByZeroException; \
                        } while (0)
 
 /*
@@ -340,12 +368,7 @@ extern     "C" {
  */
 #define        NULL_POINTER_EXCEPTION()        \
                        do { \
-                               COPY_STATE_TO_THREAD(); \
-                               stacktop[0].ptrValue = \
-                                       _ILSystemException(thread, \
-                                                                          
"System.NullReferenceException"); \
-                               stacktop += 1; \
-                               goto throwException; \
+                               goto throwNullReferenceException; \
                        } while (0)
 
 /*
@@ -353,12 +376,7 @@ extern     "C" {
  */
 #define        STACK_OVERFLOW_EXCEPTION()      \
                        do { \
-                               COPY_STATE_TO_THREAD(); \
-                               stacktop[0].ptrValue = \
-                                       _ILSystemException(thread, \
-                                                                          
"System.StackOverflowException"); \
-                               stacktop += 1; \
-                               goto throwException; \
+                               goto throwStackOverflowException; \
                        } while (0)
 
 /*
@@ -366,12 +384,7 @@ extern     "C" {
  */
 #define        MISSING_METHOD_EXCEPTION()      \
                        do { \
-                               COPY_STATE_TO_THREAD(); \
-                               stacktop[0].ptrValue = \
-                                       _ILSystemException(thread, \
-                                                                          
"System.MissingMethodException"); \
-                               stacktop += 1; \
-                               goto throwException; \
+                               goto throwMissingMethodException; \
                        } while (0)
 
 /*
@@ -389,11 +402,7 @@ extern     "C" {
  */
 #define        INVALID_CAST_EXCEPTION()        \
                        do { \
-                               COPY_STATE_TO_THREAD(); \
-                               stacktop[0].ptrValue = \
-                                       _ILSystemException(thread, 
"System.InvalidCastException"); \
-                               stacktop += 1; \
-                               goto throwException; \
+                               goto throwInvalidCastException; \
                        } while (0)
 
 /*
@@ -401,12 +410,7 @@ extern     "C" {
  */
 #define        ARRAY_INDEX_EXCEPTION() \
                        do { \
-                               COPY_STATE_TO_THREAD(); \
-                               stacktop[0].ptrValue = \
-                                       _ILSystemException(thread, \
-                                                                          
"System.IndexOutOfRangeException"); \
-                               stacktop += 1; \
-                               goto throwException; \
+                               goto throwIndexOutOfRangeException; \
                        } while (0)
 
 /*
@@ -566,7 +570,7 @@ static IL_INLINE void *ReadPointer(unsigned char *pc)
  */
 CVM_DEFINE_TABLES();
 
-int _ILCVMInterpreter(ILExecThread *thread)
+static int Interpreter(ILExecThread *thread)
 {
        CVM_REGISTER_ASM_PC(unsigned char *IL_PC_VOLATILE pc);
        CVM_REGISTER_ASM_STACK(CVMWord *IL_STACKTOP_VOLATILE stacktop);
@@ -954,6 +958,494 @@ int _ILCVMInterpreter(ILExecThread *thread)
 
        /* We should never get here, but keep the compiler happy */
        return 0;
+
+       /*
+        * Jump target to throw a NullReferenceException
+        */
+throwNullReferenceException:
+       COPY_STATE_TO_THREAD();
+       tempptr = _ILSystemException(thread, "System.NullReferenceException");
+       goto throwException;
+
+       /*
+        * Jump target to throw an ArithmeticException
+        */
+throwArithmeticException:
+       COPY_STATE_TO_THREAD();
+       tempptr = _ILSystemException(thread, "System.ArithmeticException");
+       goto throwException;
+
+       /*
+        * Jump target to throw an OverflowException
+        */
+throwOverflowException:
+       COPY_STATE_TO_THREAD();
+       tempptr = _ILSystemException(thread, "System.OverflowException");
+       goto throwException;
+
+       /*
+        * Jump target to throw a DivideByZeroException
+        */
+throwDivideByZeroException:
+       COPY_STATE_TO_THREAD();
+       tempptr = _ILSystemException(thread, "System.DivideByZeroException");
+       goto throwException;
+
+       /*
+        * Jump target to throw a StackOverflowException
+        */
+throwStackOverflowException:
+       COPY_STATE_TO_THREAD();
+       tempptr = _ILSystemException(thread, "System.StackOverflowException");
+       goto throwException;
+
+       /*
+        * Jump target to throw a MissingMethodException
+        */
+throwMissingMethodException:
+       COPY_STATE_TO_THREAD();
+       tempptr = _ILSystemException(thread, "System.MissingMethodException");
+       goto throwException;
+
+       /*
+        * Jump target to throw an InvalidCastException
+        */
+throwInvalidCastException:
+       COPY_STATE_TO_THREAD();
+       tempptr = _ILSystemException(thread, "System.InvalidCastException");
+       goto throwException;
+
+       /*
+        * Jump target to throw an IndexOutOfRangeException
+        */
+throwIndexOutOfRangeException:
+       COPY_STATE_TO_THREAD();
+       tempptr = _ILSystemException(thread, "System.IndexOutOfRangeException");
+       goto throwException;
+       /*
+        * Label that we jump to when the engine throws an exception.
+        * The exception thrown is expected to be in tempptr.
+        */
+throwException:
+       /* Pop the exception object from the stack and store it to the thread. 
*/
+       thread->thrownException = tempptr;
+#ifdef IL_DUMP_CVM
+       fputs("Throw ", IL_DUMP_CVM_STREAM);
+       DUMP_STACK();
+#endif
+       return _CVM_EXIT_THROW;
+}
+
+/*
+ * Forward declarations.
+ */
+static int unwind(ILExecThread *thread,
+                                 ILCVMExceptionContext 
*callerExceptionContext);
+
+/*
+ * Call an exception filter.
+ * NOTE: Exceptions are caught at exit from a filter and interpreted
+ * as a 0 return value (continue search) as specified by ECMA.
+ */
+static int CallFilter(ILExecThread *thread,
+                                         ILCVMExceptionContext 
*callerExceptionContext)
+{
+       int result;
+
+       do
+       {
+               result = Interpreter(thread);
+               if(result == _CVM_EXIT_THROW)
+               {
+                       /*
+                        * Perform exception handling.
+                        */
+                       result = unwind(thread, callerExceptionContext);
+               }
+       } while(result == _CVM_EXIT_EXECUTE_HANDLER);
+       if(result == _CVM_EXIT_RETURN)
+       {
+               CVMWord *stacktop;
+               /*
+                * We returned from en ENDFILTER opcode.
+                */
+
+               /*
+                * Pop the result of the filter call.
+                * The result is on top of the stack.
+                */
+               stacktop = thread->stackTop;
+               if(stacktop[-1].intValue)
+               {
+                       return _CVM_EXCEPTION_EXECUTE_HANDLER;
+               }
+       }
+       return _CVM_EXCEPTION_CONTINUE_SEARCH;
+}
+
+/*
+ * Call a catch clause while thread abort is in effect.
+ */
+static int CallHandler(ILExecThread *thread,
+                                          ILCVMExceptionContext 
*callerExceptionContext)
+{
+       int result;
+
+       do
+       {
+               result = Interpreter(thread);
+               if(result == _CVM_EXIT_THROW)
+               {
+                       /*
+                        * Perform exception handling.
+                        */
+                       result = unwind(thread, callerExceptionContext);
+               }
+       } while(result == _CVM_EXIT_EXECUTE_HANDLER);
+       return result;
+}
+
+/*
+ * Perform normal exception unwinding
+ */
+static int unwind(ILExecThread *thread,
+                                 ILCVMExceptionContext *callerExceptionContext)
+{
+       unsigned char *pc;
+       CVMWord *stacktop;
+       CVMWord *frame;
+       ILCallFrame *callFrame;
+       ILMethod *method;
+       ILObject *exception;
+       ILCVMExceptionContext exceptionContext;
+       const ILCVMUnwind *unwind;
+       int threadIsAborting;
+
+       /*
+        * Get the state from the thread.
+        */
+       pc = thread->pc;
+       frame = thread->frame;
+       stacktop = thread->stackTop;
+       method = thread->method;
+       exception = thread->thrownException;
+       thread->thrownException = 0;
+
+       threadIsAborting = 0;
+       /*
+        * Check if the thread is aborting
+        */
+       if (thread->aborting)
+       {
+               if (exception && ILExecThreadIsThreadAbortException(thread, 
exception))
+               {
+                       threadIsAborting = 1;
+               }
+       }
+
+       unwind = (ILCVMUnwind *)ILCoderPCToHandler(thread->process->coder, pc, 
0);
+       do
+       {
+               ILCVMContext context;
+
+               if(unwind)
+               {
+                       const ILCVMUnwind *exceptUnwind;
+                       /*
+                        * Locate the unwind block ehere the exceptionPc is 
located
+                        * and adjust the stacktop accordingly.
+                        */
+                       context.pc = pc;
+                       context.frame = frame;
+                       context.stackTop = frame;
+                       exceptUnwind = FindUnwindBlock(unwind, &context);
+                       while(exceptUnwind)
+                       {
+                               if(exceptUnwind->flags ==  
_IL_CVM_UNWIND_TYPE_TRY)
+                               {
+                                       const ILCVMUnwind *handler;
+                                       const ILCVMUnwind *filter;
+
+                                       
if(exceptUnwind->un.tryBlock.firstHandler >= 0)
+                                       {
+                                               int stopExecuteHandlers;
+                                               int result;
+
+                                               /*
+                                                * Process the handlers for 
this try block.
+                                                */
+                                               result = _CVM_EXIT_OK;
+                                               stopExecuteHandlers = 0;
+                                               handler = 
&(unwind[exceptUnwind->un.tryBlock.firstHandler]);
+                                               while(handler)
+                                               {
+                                                       switch(handler->flags)
+                                                       {
+                                                               case 
_IL_CVM_UNWIND_TYPE_CATCH:
+                                                               {
+                                                                       /*
+                                                                        * A 
typed exception handler.
+                                                                        */
+                                                                       
if(stopExecuteHandlers)
+                                                                       {
+                                                                               
break;
+                                                                       }
+                                                                       
+                                                                       
if(exception && CanCastClass(ILProgramItem_Image(method),
+                                                                               
                                                 GetObjectClass(exception),
+                                                                               
                                                 
handler->un.handlerBlock.un.exceptionClass))
+                                                                       {
+                                                                       
executeHandler:
+                                                                               
stacktop = context.stackTop;
+                                                                               
/*
+                                                                               
 * Push the flag for propagating
+                                                                               
 * a ThreadAbortException on the stack.
+                                                                               
 */
+                                                                               
stacktop[0].ptrValue = (threadIsAborting ? IL_INVALID_PC : 0);
+                                                                               
++stacktop;
+                                                                               
/*
+                                                                               
 * Push the exception object on the stack.
+                                                                               
 */
+                                                                               
stacktop[0].ptrValue = exception;
+                                                                               
++stacktop;
+                                                                               
/*
+                                                                               
 * Store the exception in the frame for
+                                                                               
 * rethrowing the exception.
+                                                                               
 */
+                                                                               
if(exceptUnwind->exceptionSlot != IL_MAX_UINT32)
+                                                                               
{
+                                                                               
        frame[exceptUnwind->exceptionSlot].ptrValue = exception;
+                                                                               
}
+                                                                               
/*
+                                                                               
 * and jump to the handler.
+                                                                               
 */
+                                                                               
thread->pc = handler->start;
+                                                                               
thread->stackTop = stacktop;
+                                                                               
thread->frame = context.frame;
+                                                                               
thread->method = method;
+                                                                               
if(threadIsAborting)
+                                                                               
{
+                                                                               
        exceptionContext.exception = exception;
+                                                                               
        exceptionContext.context = &context;
+                                                                               
        exceptionContext.unwind = handler;
+                                                                               
        result = CallHandler(thread, &exceptionContext);
+                                                                               
        if(result == _CVM_EXIT_PROPAGATE_ABORT)
+                                                                               
        {
+                                                                               
                /*
+                                                                               
                 * Don't execute any handlers for this try block anymore.
+                                                                               
                 * Remaining finally or fault blocks should be executed.
+                                                                               
                 */
+                                                                               
                stopExecuteHandlers = 1;
+                                                                               
        }
+                                                                               
}
+                                                                               
else
+                                                                               
{
+                                                                               
        return _CVM_EXIT_EXECUTE_HANDLER;
+                                                                               
}
+                                                                       }
+                                                               }
+                                                               break;
+
+                                                               case 
_IL_CVM_UNWIND_TYPE_FILTEREDCATCH:
+                                                               {
+                                                                       
if(stopExecuteHandlers)
+                                                                       {
+                                                                               
break;
+                                                                       }
+
+                                                                       filter 
= &(unwind[handler->un.handlerBlock.un.filter]);
+                                                                       /*
+                                                                        * Push 
the exception object on the stack.
+                                                                        */
+                                                                       
stacktop = context.stackTop;
+                                                                       
stacktop[0].ptrValue = exception;
+                                                                       
++stacktop;
+                                                                       /*
+                                                                        * and 
execute the filter.
+                                                                        */
+                                                                       
thread->pc = filter->start;
+                                                                       
thread->stackTop = stacktop;
+                                                                       
thread->frame = context.frame;
+                                                                       
thread->method = method;
+                                                                       
exceptionContext.exception = exception;
+                                                                       
exceptionContext.context = &context;
+                                                                       
exceptionContext.unwind = filter;
+                                                                       
if(CallFilter(thread, &exceptionContext) == _CVM_EXCEPTION_EXECUTE_HANDLER)
+                                                                       {
+                                                                               
/*
+                                                                               
 * The handler should be called
+                                                                               
 */
+                                                                               
goto executeHandler;
+                                                                       }
+                                                               }
+                                                               break;
+
+                                                               case 
_IL_CVM_UNWIND_TYPE_FINALLY:
+                                                               case 
_IL_CVM_UNWIND_TYPE_FAULT:
+                                                               {
+                                                                       /*
+                                                                        * Call 
a cleanup handler.
+                                                                        */
+                                                                       /*
+                                                                        * Push 
the return address on the stack.
+                                                                        * 
IL_INVALID_PC is pushed so that the
+                                                                        * 
interpreter knows that the finally block
+                                                                        * was 
called during exception handling and
+                                                                        * is 
left on returning from the finally block.
+                                                                        */
+                                                                       
stacktop = context.stackTop;
+                                                                       
stacktop[0].ptrValue = IL_INVALID_PC;
+                                                                       
++stacktop;
+                                                                       /*
+                                                                        * and 
jump to the handler.
+                                                                        */
+                                                                       
thread->pc = handler->start;
+                                                                       
thread->stackTop = stacktop;
+                                                                       
thread->frame = context.frame;
+                                                                       
thread->method = method;
+                                                                       
exceptionContext.exception = exception;
+                                                                       
exceptionContext.context = &context;
+                                                                       
exceptionContext.unwind = handler;
+                                                                       result 
= CallHandler(thread, &exceptionContext);
+                                                               }
+                                                               break;
+                                                       }
+                                                       /*
+                                                        * Check if aborting 
the thread has been reset.
+                                                        */
+                                                       if(threadIsAborting)
+                                                       {
+                                                               
if(!thread->aborting)
+                                                               {
+                                                                       /*
+                                                                        * The 
abort has been aborted.
+                                                                        * So 
reset the threadIsAborting flag.
+                                                                        */
+                                                                       
threadIsAborting = 0;
+                                                               }
+                                                       }
+                                                       if(result == 
_CVM_EXIT_CONTINUE_UNWIND)
+                                                       {
+                                                               /*
+                                                                * An exception 
has been thrown while
+                                                                * performing 
the unwinding.
+                                                                * So continue 
unwinding using this
+                                                                * exception if 
the thread is not aborted.
+                                                                */
+                                                               
if(!threadIsAborting)
+                                                               {
+                                                                       
exception = exceptionContext.exception;
+                                                                       
if(thread->aborting)
+                                                                       {
+                                                                               
if(exception &&
+                                                                               
   ILExecThreadIsThreadAbortException(thread, exception))
+                                                                               
{
+                                                                               
        threadIsAborting = 1;
+                                                                               
}
+                                                                       }
+                                                               }
+                                                               break;
+                                                       }
+                                                       /*
+                                                        * Get the next handler.
+                                                        */
+                                                       
if(handler->un.handlerBlock.nextHandler >= 0)
+                                                       {
+                                                               handler = 
&(unwind[handler->un.handlerBlock.nextHandler]);
+                                                       }
+                                                       else
+                                                       {
+                                                               break;
+                                                       }
+                                               }
+                                       }
+                               }
+                               else if(callerExceptionContext)
+                               {
+                                       
if((callerExceptionContext->context->frame == frame) &&
+                                          (callerExceptionContext->unwind == 
exceptUnwind))
+                                       {
+                                               /*
+                                                * We are trying to unwind 
below the caller's position.
+                                                * So update the caller's 
exceptioncontext and let him
+                                                * decide what to do.
+                                                */
+                                               
callerExceptionContext->exception = exception;
+                                               
callerExceptionContext->context->pc = pc;
+                                               return 
_CVM_EXIT_CONTINUE_UNWIND;
+                                       }
+                               }
+                               /*
+                                * Walk up to the parent unwind block.
+                                */
+                               if(exceptUnwind->parent >= 0)
+                               {
+                                       context.stackTop -= 
exceptUnwind->stackChange;
+                                       exceptUnwind = 
&(unwind[exceptUnwind->parent]);
+                               }
+                               else
+                               {
+                                       break;
+                               }
+                       }
+               }
+               /*
+                * Walk the stack up to caller.
+                */
+               stacktop = frame;
+               callFrame = &(thread->frameStack[--(thread->numFrames)]);
+               pc = callFrame->pc;
+               frame = callFrame->frame;
+               method = callFrame->method;
+
+#ifdef IL_DUMP_CVM
+               if(method)
+               {
+                       fprintf(IL_DUMP_CVM_STREAM, "Throwing Back To %s::%s\n",
+                                   method->member.owner->className->name,
+                                   method->member.name);
+               }
+#endif
+
+               /* Should we return to an external method? */
+               if(callFrame->pc == IL_INVALID_PC)
+               {
+                       thread->thrownException = exception;
+                       COPY_STATE_TO_THREAD();
+                       return _CVM_EXIT_EXCEPT;
+               }
+               unwind = (ILCVMUnwind 
*)ILCoderPCToHandler(thread->process->coder, pc - 1, 1);
+       } while(1);
+}
+
+int _ILCVMInterpreter(ILExecThread *thread)
+{
+       int result;
+
+               if(!thread)
+       {
+               /*
+                * Export the goto label tables from the interpreter if 
necessary
+                */
+               return Interpreter(thread);
+       }
+
+       do
+       {
+               result = Interpreter(thread);
+               while(result == _CVM_EXIT_THROW)
+               {
+                       /*
+                        * Perform exception handling.
+                        */
+                       result = unwind(thread, 0);
+               }
+               if(result != _CVM_EXIT_EXECUTE_HANDLER)
+               {
+                       break;
+               }
+       } while(1);
+       return result;
 }
 
 #ifdef __cplusplus
diff --git a/engine/cvm.h b/engine/cvm.h
index eddc2b2..c31b4d4 100644
--- a/engine/cvm.h
+++ b/engine/cvm.h
@@ -412,9 +412,13 @@ extern     "C" {
 /*
  * Prefixed exception handling opcodes.
  */
-#define        COP_PREFIX_ENTER_TRY            0x1E
+/* Not needed anymore
+ * #define     COP_PREFIX_ENTER_TRY            0x1E
+ */
 #define        COP_PREFIX_THROW                        0x1F
-#define        COP_PREFIX_THROW_CALLER         0x20
+/* Not needed anymore
+ * #define     COP_PREFIX_THROW_CALLER         0x20
+ */
 #define        COP_PREFIX_SET_STACK_TRACE      0x21
 
 /*
@@ -532,9 +536,15 @@ extern     "C" {
 /*
  * More prefixed exception handling opcodes.
  */
-#define COP_PREFIX_START_CATCH                 0x62
-#define COP_PREFIX_START_FINALLY               0x63
-#define        COP_PREFIX_PROPAGATE_ABORT              0x64
+/*
+ * Those are not needed anymore
+ * #define COP_PREFIX_START_CATCH                      0x62
+ * #define COP_PREFIX_START_FINALLY            0x63
+ * #define     COP_PREFIX_PROPAGATE_ABORT              0x64
+ * and replaced by
+ */
+#define COP_PREFIX_LEAVE_CATCH                 0x62
+#define COP_PREFIX_RET_FROM_FILTER             0x63
 
 /*
  * More inline method replacements.
@@ -647,6 +657,105 @@ typedef union
  */
 #define        CVM_MAX_NATIVE_ARGS             32
 
+/*
+ * Unwind information for the cvm interpreter.
+ */
+
+/*
+ * Values for the flags member.
+ * For comments see il_coder.h
+ */
+#define _IL_CVM_UNWIND_TYPE_TRY                                0x00
+#define _IL_CVM_UNWIND_TYPE_CATCH                      0x01
+#define _IL_CVM_UNWIND_TYPE_FILTEREDCATCH      0x03
+#define _IL_CVM_UNWIND_TYPE_FINALLY                    0x04
+#define _IL_CVM_UNWIND_TYPE_FAULT                      0x06
+#define _IL_CVM_UNWIND_TYPE_FILTER                     0x02
+
+/*
+ * NOTE: Index fields with a value < 0 mark the end of the list.
+ */
+typedef struct _tagILCVMUnwindTry ILCVMUnwindTry;
+typedef struct _tagILCVMUnwindHandler ILCVMUnwindHandler;
+typedef struct _tagILCVMUnwind ILCVMUnwind;
+
+struct _tagILCVMUnwindTry
+{
+       ILInt32                         firstHandler;
+};
+
+struct _tagILCVMUnwindHandler
+{
+       ILInt32                         nextHandler;
+       union
+       {
+               ILInt32                 filter;
+               ILClass            *exceptionClass;
+       } un;
+};
+
+struct _tagILCVMUnwind
+{
+       unsigned char      *start;
+       unsigned char      *end;
+       ILUInt32                        flags;
+       /*
+        * Index of the surrounding unwind information block.
+        */
+       ILInt32                         parent;
+       /*
+        * Index of the first nested unwind information block.
+        */
+       ILInt32                         nested;
+        /*
+         * Index of the next nested unwind information block in a single
+         * linked list.
+         */
+       ILInt32                         nextNested;
+       /*
+        * The number of CVMWords the stackpointer is increased on entry
+        * of the block without taking temporary values on the stack into 
account.
+        * This value is 1 for example for finally and filter blocks
+        * (for the return pointer).
+        * The size of the stack needed for locals in the outer most block for
+        * a method.
+        */
+       ILInt32                         stackChange;
+       /*
+        * Local variable offset to store a caught exception.
+        * This is used for rethrowing an exception.
+        */
+       ILUInt32                        exceptionSlot;
+       
+       union
+       {
+               ILCVMUnwindTry          tryBlock;
+               ILCVMUnwindHandler      handlerBlock;   
+       } un;
+};
+
+/*
+ * Context definition for the cvm interpreter (aka ucontext)
+ */
+typedef struct _tagILCVMContext ILCVMContext;
+struct _tagILCVMContext
+{
+       unsigned char              *pc;
+       CVMWord                            *stackTop;
+       CVMWord                            *frame;
+};
+
+/*
+ * Exceptioncontext definition for the cvm interpreter.
+ */
+typedef struct _tagILCVMExceptionContext ILCVMExceptionContext;
+struct _tagILCVMExceptionContext
+{
+       ILObject                           *exception;
+       ILCVMContext               *context;
+       const ILCVMUnwind          *unwind;
+};
+
 #ifdef __cplusplus
 };
 #endif
diff --git a/engine/cvm_arith.c b/engine/cvm_arith.c
index b3fc0bb..554d729 100644
--- a/engine/cvm_arith.c
+++ b/engine/cvm_arith.c
@@ -1675,9 +1675,7 @@ VMCASE(COP_FFIXUP):
 VMCASE(COP_DFIXUP):
 {
        COPY_STATE_TO_THREAD();
-       stacktop[0].ptrValue =
-               _ILSystemException(thread, "System.NotImplementedException");
-       stacktop += 1;
+       tempptr = _ILSystemException(thread, "System.NotImplementedException");
        goto throwException;
 }
 /* Not reached */
@@ -2164,9 +2162,7 @@ VMCASE(COP_PREFIX_FWRITE_ELEM):
 VMCASE(COP_PREFIX_DWRITE_ELEM):
 {
        COPY_STATE_TO_THREAD();
-       stacktop[0].ptrValue =
-               _ILSystemException(thread, "System.NotImplementedException");
-       stacktop += 1;
+       tempptr = _ILSystemException(thread, "System.NotImplementedException");
        goto throwException;
 }
 /* Not reached */
diff --git a/engine/cvm_call.c b/engine/cvm_call.c
index 67ec6ad..6370914 100644
--- a/engine/cvm_call.c
+++ b/engine/cvm_call.c
@@ -105,9 +105,9 @@ ILCallFrame *_ILAllocCallFrame(ILExecThread *thread)
                        { \
                                
ILInterlockedAndU4(&(thread->managedSafePointFlags), \
                                                                   
~_IL_MANAGED_SAFEPOINT_THREAD_ABORT); \
-                               stacktop[0].ptrValue = thread->thrownException; 
\
+                               tempptr = thread->thrownException; \
                                thread->thrownException = 0; \
-                               stacktop += 1; \
+                               COPY_STATE_TO_THREAD(); \
                                goto throwException; \
                        } \
                } \
@@ -190,10 +190,8 @@ ILCallFrame *_ILAllocCallFrame(ILExecThread *thread)
                                if(thread->thrownException != 0) \
                                { \
                                        /* An exception occurred, which we now 
must handle */ \
-                                       pc = thread->pc; \
-                                       stacktop[0].ptrValue = 
thread->thrownException; \
+                                       tempptr = thread->thrownException; \
                                        thread->thrownException = 0; \
-                                       stacktop += 1; \
                                        goto throwException; \
                                } \
                        } while (0)
@@ -926,7 +924,7 @@ VMCASE(COP_CALL_VIRTUAL):
 {
        /* Call a virtual method */
        tempptr = stacktop[-((ILInt32)CVM_ARG_DWIDE1_SMALL)].ptrValue;
-       BEGIN_NULL_CHECK(tempptr)
+       if(tempptr)
        {
                /* Locate the method to be called */
                methodToCall = (GetObjectClassPrivate(tempptr))
@@ -985,7 +983,10 @@ VMCASE(COP_CALL_VIRTUAL):
                        CVM_OPTIMIZE_BLOCK();
                }
        }
-       END_NULL_CHECK();
+       else
+       {
+               NULL_POINTER_EXCEPTION();
+       }
 }
 VMBREAK(COP_CALL_VIRTUAL);
 
@@ -1475,7 +1476,7 @@ VMCASE(COP_CALLI):
 
                        CONVERT_FAILED_EXCEPTION();
                }
-               
+
                END_NATIVE_CALL();
 
                /* Allocate a new call frame */
diff --git a/engine/cvm_except.c b/engine/cvm_except.c
index b4adc4b..141dab6 100644
--- a/engine/cvm_except.c
+++ b/engine/cvm_except.c
@@ -20,7 +20,48 @@
 
 #if defined(IL_CVM_GLOBALS)
 
-/* Moved to system.c */
+/*
+ * Find the most nested unwind information block where the pc.
+ * Returns NULL if no such exception block could be found.
+ */
+static const ILCVMUnwind *FindUnwindBlock(const ILCVMUnwind *unwind,
+                                                                               
  ILCVMContext *context)
+{
+       const unsigned char *pc;
+       ILInt32 index ;
+       CVMWord *stacktop;
+       const ILCVMUnwind *prevEB;
+
+       pc = context->pc;
+       stacktop = context->frame;
+       prevEB = 0;
+       index = 0;
+       while(index >= 0)
+       {
+               const ILCVMUnwind *block;
+
+               block = &(unwind[index]);
+               if(pc < block->start)
+               {
+                       break;
+               }
+               else if(pc >= block->end)
+               {
+                       index = block->nextNested;
+               }
+               else
+               {
+                       prevEB = block;
+                       stacktop += block->stackChange;
+                       index = block->nested;
+               }
+       }
+       /*
+        * Update the stacktop in the context structure.
+        */
+       context->stackTop = stacktop;
+       return prevEB;
+}
 
 #elif defined(IL_CVM_LOCALS)
 
@@ -72,61 +113,34 @@ VMBREAK(COP_JSR);
  *   <after>...</after>
  *
  *   <description>The <i>address</i> is popped from the stack as the
- *   type <code>ptr</code> and transferred into <i>pc</i>.</description>
+ *   type <code>ptr</code> and transferred into <i>pc</i>.
+ *   If the resultint pc is an invalid pc the finally block was called
+ *   during exception handling and the interpreter is left with an
+ *   return code.</description>
  *
- *   <notes>This instruction is used to implement <code>finally</code>
- *   blocks.</notes>
+ *   <notes>This instruction is used to implement returning from
+ *   <code>finally</code> blocks.</notes>
  * </opcode>
  */
 VMCASE(COP_RET_JSR):
 {
        /* Return from a subroutine within this method */
-       pc = (unsigned char *)(stacktop[-1].ptrValue);
-       stacktop -= 1;
+       if((unsigned char *)(stacktop[-1].ptrValue) == IL_INVALID_PC)
+       {
+               COPY_STATE_TO_THREAD();
+               return _CVM_EXIT_RETURN;
+       }
+       else
+       {
+               pc = (unsigned char *)(stacktop[-1].ptrValue);
+               stacktop -= 1;
+       }
 }
 VMBREAK(COP_RET_JSR);
 
 #elif defined(IL_CVM_PREFIX)
 
 /**
- * <opcode name="enter_try" group="Exception handling instructions">
- *   <operation>Enter <code>try</code> context for the
- *                             current method</operation>
- *
- *   <format>prefix<fsep/>enter_try</format>
- *   <dformat>{enter_try}</dformat>
- *
- *   <form name="enter_try" code="COP_PREFIX_ENTER_TRY"/>
- *
- *   <description>The exception frame height for the current method
- *   is set to the current height of the stack.</description>
- *
- *   <notes>This must be in the prolog of any method that includes
- *   <code>try</code> blocks.  It sets the "base height" of the stack
- *   so that <i>throw</i> instructions know where to unwind the stack
- *   to when an exception is thrown.</notes>
- * </opcode>
- */
-VMCASE(COP_PREFIX_ENTER_TRY):
-{
-       /* Enter a try context for this method */
-       thread->exceptHeight = stacktop;
-
-       MODIFY_PC_AND_STACK(CVMP_LEN_NONE, 0);
-}
-VMBREAK(COP_PREFIX_ENTER_TRY);
-
-/* Label that we jump to when the engine throws an internal exception */
-throwException:
-{
-       if(!ILCoderPCToHandler(thread->process->coder, pc, 0))
-       {
-               goto throwCaller;
-       }
-}
-/* Fall through */
-
-/**
  * <opcode name="throw" group="Exception handling instructions">
  *   <operation>Throw an exception</operation>
  *
@@ -155,116 +169,14 @@ throwException:
  */
 VMCASE(COP_PREFIX_THROW):
 {
-       /* Move the exception object down the stack to just above the locals */
-       thread->exceptHeight->ptrValue = stacktop[-1].ptrValue;
-       thread->currentException = stacktop[-1].ptrValue;
-       stacktop = thread->exceptHeight + 1;
-
-       /* Search the exception handler table for an applicable handler */
-searchForHandler:
-#ifdef IL_DUMP_CVM
-       fputs("Throw ", IL_DUMP_CVM_STREAM);
-       DUMP_STACK();
-#endif
-       
-       tempNum = (ILUInt32)(pc - (unsigned char *)(method->userData));
-       pc = ILCoderPCToHandler(thread->process->coder, pc, 0);
-       
-       while(tempNum < CVM_ARG_TRY_START || tempNum >= CVM_ARG_TRY_END)
-       {
-               pc += CVM_ARG_TRY_LENGTH;
-       }
-       pc += CVM_LEN_TRY;
+       --stacktop;
+       tempptr = stacktop[0].ptrValue;
+       COPY_STATE_TO_THREAD();
+       goto throwException;
 }
 VMBREAK(COP_PREFIX_THROW);
 
 /**
- * <opcode name="throw_caller" group="Exception handling instructions">
- *   <operation>Throw an exception to the caller of this method</operation>
- *
- *   <format>prefix<fsep/>throw_caller</format>
- *   <dformat>{throw_caller}</dformat>
- *
- *   <form name="throw_caller" code="COP_PREFIX_THROW_CALLER"/>
- *
- *   <before>..., working1, ..., workingN, object</before>
- *   <after>..., object</after>
- *
- *   <description>The <i>object</i> is popped from the stack as
- *   type <code>ptr</code>.  The call frame stack is then unwound
- *   until a call frame with a non-zero exception frame height is found.
- *   The stack is then reset to the specified exception frame height.
- *   Then, <i>object</i> is re-pushed onto the stack and control is
- *   passed to the call frame method's exception matching code.</description>
- *
- *   <notes>This is used to throw exceptions from within methods that
- *   do not have an <i>enter_try</i> instruction.  Use <i>throw</i>
- *   if the method does include <code>try</code> blocks.</notes>
- * </opcode>
- */
-VMCASE(COP_PREFIX_THROW_CALLER):
-{
-       /* Throw an exception to the caller of this method */
-throwCaller:
-#ifdef IL_DUMP_CVM
-       fputs("Throw Caller ", IL_DUMP_CVM_STREAM);
-       DUMP_STACK();
-#endif
-       tempptr = stacktop[-1].ptrValue;
-       thread->currentException = tempptr;
-       if(!tempptr)
-       {
-               --stacktop;
-               NULL_POINTER_EXCEPTION();
-       }
-
-       /* Locate a call frame that has an exception handler */
-       do
-       {
-               stacktop = frame;
-               callFrame = &(thread->frameStack[--(thread->numFrames)]);
-               methodToCall = callFrame->method;
-               pc = callFrame->pc;
-               thread->exceptHeight = callFrame->exceptHeight;
-               frame = callFrame->frame;
-               method = methodToCall;
-
-#ifdef IL_DUMP_CVM
-               if(methodToCall)
-               {
-                       BEGIN_NATIVE_CALL();
-                       fprintf(IL_DUMP_CVM_STREAM, "Throwing Back To %s::%s\n",
-                                   methodToCall->member.owner->className->name,
-                                   methodToCall->member.name);
-                       END_NATIVE_CALL();
-               }
-#endif
-
-               /* Should we return to an external method? */
-               if(callFrame->pc == IL_INVALID_PC)
-               {
-                       thread->thrownException = tempptr;
-                       COPY_STATE_TO_THREAD();
-                       return 1;
-               }
-       }
-       while(!ILCoderPCToHandler(thread->process->coder, pc, 1));
-
-       /* Copy the exception object into place */
-       stacktop = thread->exceptHeight;
-       stacktop[0].ptrValue = tempptr;
-       ++stacktop;
-
-       /* Back up one byte to ensure that the pc falls within
-          the exception region for the method */
-       --pc;
-
-       /* Search for an exception handler within this method */
-       goto searchForHandler;
-}
-/* Not reached */
-
-/**
  * <opcode name="set_stack_trace" group="Exception handling instructions">
  *   <operation>Set the stack trace in an exception object at
  *              the throw point</operation>
@@ -302,146 +214,63 @@ VMCASE(COP_PREFIX_SET_STACK_TRACE):
 VMBREAK(COP_PREFIX_SET_STACK_TRACE);
 
 /**
- * <opcode name="start_catch" group="Exception handling instructions">
- *   <operation>Save state information for Thread.Abort</operation>
+ * <opcode name="leave_catch" group="Exception handling instructions">
+ *   <operation>Leave a catch region and propagate a Thread.Abort 
exception</operation>
  *
- *   <format>prefix<fsep/>start_catch</format>
- *   <dformat>{set_stack_trace}</dformat>
+ *   <format>prefix<fsep/>leave_catch</format>
+ *   <dformat>{leave_catch}</dformat>
  *
- *   <form name="set_stack_trace" code="COP_PREFIX_START_CATCH"/>
+ *   <form name="leave_catch" code="COP_PREFIX_LEAVE_CATCH"/>
  *
- *   <before>...</before>
+ *   <before>...pointer</before>
  *   <after>...</after>
  *
- *   <description>
- *   If the thread is aborting and a <code>ThreadAbortException</code>
- *   has been thrown then save the current point where the
- *   <code>ThreadAbortException</code> was thrown.
- *   If the thread is aborting and the current exception isn't a 
- *   ThreadAbortException then reset the current exception to
- *   ThreadAbortException.  This happens if a thread throws an
- *   exception while it is being aborted (usually occurs in a finally clause).
+ *   <description>If the thread is aborting and a
+ *   <code>ThreadAbortException</code> has been thrown then there is an
+ *   invalid pc pushed on the stack by the exception handling mechanism
+ *   prior to invoking the handler. Otherwise a 0 pointer was pushed.
+ *   If the pointer on top of the stack is an invalid pc and the thread is 
+ *   still aborting then return from the interpreter with a propagate abort
+ *   returncode.
  *   </description>
  * </opcode>
  */
-VMCASE(COP_PREFIX_START_CATCH):
+VMCASE(COP_PREFIX_LEAVE_CATCH):
 {
-       if (thread->aborting)
+       --stacktop;
+       if((stacktop[0].ptrValue == IL_INVALID_PC) && (thread->aborting))
        {
-               if (thread->currentException
-                       && ILExecThreadIsThreadAbortException(thread, 
thread->currentException)
-                       && !thread->threadAbortException)
-               {
-                       /* Save info about the handler that noticed the abort */
-                       thread->threadAbortException = thread->currentException;
-                       thread->abortHandlerEndPC = CVMP_ARG_PTR(unsigned char 
*);
-                       thread->abortHandlerFrame = thread->numFrames;
-               }
-               else
-               {
-                       /* A non-thread abort exception has been caught so 
restore
-                          the "current exception" to be the 
ThreadAbortException */
-                       thread->currentException = thread->threadAbortException;
-               }
+               COPY_STATE_TO_THREAD();
+               return _CVM_EXIT_PROPAGATE_ABORT;
        }
-
-       MODIFY_PC_AND_STACK(CVMP_LEN_PTR, 0);
+       MODIFY_PC_AND_STACK(CVMP_LEN_NONE, 0);
 }
-VMBREAK(COP_PREFIX_START_CATCH);
+VMBREAK(COP_PREFIX_LEAVE_CATCH);
 
 /**
- * <opcode name="start_finally" group="Exception handling instructions">
- *   <operation>Save state information for Thread.Abort</operation>
+ * <opcode name="ret_from_filter" group="Exception handling instructions">
+ *   <operation>Return from an exception filter</operation>
  *
- *   <format>prefix<fsep/>start_finally</format>
- *   <dformat>{set_stack_trace}</dformat>
+ *   <format>prefix<fsep/>ret_from_filter</format>
+ *   <dformat>{ret_from_filter}</dformat>
  *
- *   <form name="set_stack_trace" code="COP_PREFIX_START_FINALLY"/>
+ *   <form name="ret_from_filter" code="COP_PREFIX_RET_FROM_FILTER"/>
  *
- *   <before>...</before>
+ *   <before>...int</before>
  *   <after>...</after>
  *
- *   <description>
- *   If the thread is aborting and a <code>ThreadAbortException</code>
- *   has been thrown then save the current point where the
- *   <code>ThreadAbortException</code> was thrown.
+ *   <description>Return to the exception handling with a <code>return</code>
+ *   returncode. The value on top of the stack will be examined there.
+ *   If the value is not 0 the corresponding catch handler will be invoked.
  *   </description>
  * </opcode>
  */
-VMCASE(COP_PREFIX_START_FINALLY):
+VMCASE(COP_PREFIX_RET_FROM_FILTER):
 {
-       if (thread->aborting)
-       {
-               if (thread->currentException
-                       && ILExecThreadIsThreadAbortException(thread, 
thread->currentException)
-                       && !thread->threadAbortException)
-               {
-                       /* Save info about the handler that noticed the abort */
-                       thread->threadAbortException = thread->currentException;
-                       thread->abortHandlerEndPC = CVMP_ARG_PTR(unsigned char 
*);
-                       thread->abortHandlerFrame = thread->numFrames;
-               }
-       }
-
-       MODIFY_PC_AND_STACK(CVMP_LEN_PTR, 0);
-}
-VMBREAK(COP_PREFIX_START_FINALLY);
-
-/**
- * <opcode name="propagate_abort" group="Exception handling instructions">
- *   <operation>Propagate ThreadAbortExceptions</operation>
- *
- *   <format>prefix<fsep/>propagate_abort</format>
-  *
- *   <form name="propagate_abort" code="COP_PREFIX_PROPAGATE_ABORT"/>
- *
- *   <before>...</before>
- *   <after>...</after>
- *
- *   <description>
- *   Check if the thread is aborting and propagate the ThreadAbortException
- *   if the thread is at the end (or past) the catch or finally clause that
- *   first detected the exception.
- *   </description>
- * </opcode>
- */
-VMCASE(COP_PREFIX_PROPAGATE_ABORT):
-{      
-       if (thread->aborting)
-       {
-               /* Check to see if we are at a point where the 
ThreadAbortException
-                  should be propagated */
-
-               if (
-                       /* Verify that currentException isn't null (it 
shouldn't be) */
-                       thread->currentException
-                       /* Make sure exception is a ThreadAbortException */
-                       && ILExecThreadIsThreadAbortException(thread, 
thread->currentException)
-                       && 
-                       /* Make sure we've reached or gone below (call stack 
wise) the catch/finally
-                          clause that first noticed the ThreadAbortException */
-                       ((pc >= thread->abortHandlerEndPC && thread->numFrames 
== thread->abortHandlerFrame)
-                       || 
-                       (thread->numFrames < thread->abortHandlerFrame)))
-               {
-                       /* Push the ThreadAbortException onto the stack */
-                       stacktop[0].ptrValue = thread->currentException;        
                                        
-                       
-                       /* Since we've reached the end of the abort handler, 
reset these for 
-                          the next time a catch/finally is entered */
-                       thread->threadAbortException = 0;
-                       thread->abortHandlerEndPC = 0;
-                       thread->abortHandlerFrame = 0;
-
-                       /* Move PC on and increment stack by 1 */
-                       MODIFY_PC_AND_STACK(CVMP_LEN_NONE, 1);
-
-                       goto throwException;
-               }
-       }
-
+       COPY_STATE_TO_THREAD();
        MODIFY_PC_AND_STACK(CVMP_LEN_NONE, 0);
+       return _CVM_EXIT_RETURN;
 }
-VMBREAK(COP_PREFIX_PROPAGATE_ABORT);
+VMBREAK(COP_PREFIX_RET_FROM_FILTER);
 
 #endif /* IL_CVM_PREFIX */
diff --git a/engine/cvm_lengths.c b/engine/cvm_lengths.c
index d1d5c58..f38af6d 100644
--- a/engine/cvm_lengths.c
+++ b/engine/cvm_lengths.c
@@ -546,9 +546,9 @@ unsigned char const _ILCVMLengths[512] = {
        /*
         * Reserved opcodes.
         */
-       /* start_catch */               CVMP_LEN_PTR,
-       /* start_finally */             CVMP_LEN_PTR,
-       /* propagate_abort */   CVMP_LEN_NONE,
+       /* leave_catch */               CVMP_LEN_NONE,
+       /* ret_from_finally */  CVMP_LEN_NONE,
+       /* preserved_64 */              CVMP_LEN_NONE,
        /* preserved_65 */              CVMP_LEN_NONE,
        /* preserved_66 */              CVMP_LEN_NONE,
        /* preserved_67 */              CVMP_LEN_NONE,
diff --git a/engine/cvmc.c b/engine/cvmc.c
index d14bb02..50997c0 100644
--- a/engine/cvmc.c
+++ b/engine/cvmc.c
@@ -591,13 +591,11 @@ ILCoderClass const _ILCVMCoderClass =
        CVMCoder_Throw,
        CVMCoder_SetStackTrace,
        CVMCoder_Rethrow,
-       CVMCoder_Jsr,
-       CVMCoder_RetFromJsr,
-       CVMCoder_TryHandlerStart,
-       CVMCoder_TryHandlerEnd,
-       CVMCoder_Catch,
-       CVMCoder_EndCatchFinally,
-       CVMCoder_Finally,
+       CVMCoder_CallFinally,
+       CVMCoder_RetFromFinally,
+       CVMCoder_LeaveCatch,
+       CVMCoder_RetFromFilter,
+       CVMCoder_OutputExceptionTable,
        CVMCoder_PCToHandler,
        CVMCoder_PCToMethod,
        CVMCoder_GetILOffset,
diff --git a/engine/cvmc_except.c b/engine/cvmc_except.c
index d4ee0a5..3db0635 100644
--- a/engine/cvmc_except.c
+++ b/engine/cvmc_except.c
@@ -24,29 +24,39 @@
 /*
  * Set up exception handling for the current method.
  */
-static void CVMCoder_SetupExceptions(ILCoder *_coder, ILException *exceptions,
+static void CVMCoder_SetupExceptions(ILCoder *_coder, ILCoderExceptions 
*exceptions,
                                                                         int 
hasRethrow)
 {
        ILCVMCoder *coder = (ILCVMCoder *)_coder;
+       ILCoderExceptionBlock *exception;
+       ILUInt32 index;
        ILUInt32 extraLocals;
 
-/* If the method uses "rethrow", then we need to allocate local
-          variables for each of the "catch" blocks, to hold the exception
-          object temporarily prior to the "rethrow" */
-       if(hasRethrow)
+
+       extraLocals = 0;
+       if(exceptions->numBlocks > 0)
        {
-               extraLocals = 0;
-               while(exceptions != 0)
+               index = 0;
+               while(index < exceptions->numBlocks)
                {
-                       if((exceptions->flags & (IL_META_EXCEPTION_FINALLY |
-                                                                        
IL_META_EXCEPTION_FAULT |
-                                                                        
IL_META_EXCEPTION_FILTER)) == 0)
+                       exception = &(exceptions->blocks[index]);
+                       exception->userData = IL_MAX_UINT32;
+                       if((exception->flags & IL_CODER_HANDLER_TYPE_CATCH) != 
0)
                        {
-                               exceptions->userData = extraLocals + 
coder->minHeight;
-
-                               ++extraLocals;
+                               
if(exception->un.handlerBlock.tryBlock->userData == IL_MAX_UINT32)
+                               {
+                                       
exception->un.handlerBlock.tryBlock->userData = extraLocals + coder->minHeight;
+                                       ++extraLocals;
+                               }
+                               exception->userData = 
exception->un.handlerBlock.tryBlock->userData;
+                       }
+                       else
+                       {
+                               /*
+                                * TODO: Look for the first parent catch block 
and use it's exception slot
+                                */
                        }
-                       exceptions = exceptions->next;
+                       ++index;
                }
                if(extraLocals == 1)
                {
@@ -74,7 +84,6 @@ static void CVMCoder_SetupExceptions(ILCoder *_coder, 
ILException *exceptions,
 
        /* Set up the method's frame to perform exception handling */
        coder->needTry = 1;
-       CVMP_OUT_NONE(COP_PREFIX_ENTER_TRY);
 }
 
 /*
@@ -82,14 +91,7 @@ static void CVMCoder_SetupExceptions(ILCoder *_coder, 
ILException *exceptions,
  */
 static void CVMCoder_Throw(ILCoder *coder, int inCurrentMethod)
 {
-       if(inCurrentMethod == 1)
-       {
-               CVMP_OUT_WORD(COP_PREFIX_THROW, 1);
-       }
-       else
-       {
-               CVMP_OUT_NONE(COP_PREFIX_THROW_CALLER);
-       }
+       CVMP_OUT_NONE(COP_PREFIX_THROW);
        CVM_ADJUST(-1);
 }
 
@@ -104,7 +106,7 @@ static void CVMCoder_SetStackTrace(ILCoder *coder)
 /*
  * Output a rethrow instruction.
  */
-static void CVMCoder_Rethrow(ILCoder *coder, ILException *exception)
+static void CVMCoder_Rethrow(ILCoder *coder, ILCoderExceptionBlock *exception)
 {
        /* Push the saved exception object back onto the stack */
        CVM_OUT_WIDE(COP_PLOAD, exception->userData);
@@ -116,9 +118,10 @@ static void CVMCoder_Rethrow(ILCoder *coder, ILException 
*exception)
 }
 
 /*
- * Output a "jump to subroutine" instruction.
+ * Output a "call to a finally ot fault subroutine" instruction.
  */
-static void CVMCoder_Jsr(ILCoder *coder, ILUInt32 dest)
+static void CVMCoder_CallFinally(ILCoder *coder, ILCoderExceptionBlock 
*exception,
+                                                                ILUInt32 dest)
 {
        OutputBranch(coder, COP_JSR, dest);
 }
@@ -126,121 +129,216 @@ static void CVMCoder_Jsr(ILCoder *coder, ILUInt32 dest)
 /*
  * Output a "return from subroutine" instruction.
  */
-static void CVMCoder_RetFromJsr(ILCoder *coder)
+static void CVMCoder_RetFromFinally(ILCoder *coder)
 {
        CVM_OUT_NONE(COP_RET_JSR);
 }
 
-/*
- * Start a "try" handler block for a region of code.
- */
-static void CVMCoder_TryHandlerStart(ILCoder *_coder,
-                                                                        
ILUInt32 start, ILUInt32 end)
+static void CVMCoder_LeaveCatch(ILCoder *coder,
+                                                               
ILCoderExceptionBlock *exception)
 {
-       ILCVMCoder *coder = (ILCVMCoder *)_coder;
-       ILCVMLabel *label;
-       
-       /* End the exception region if this is the first try block */
-       if(coder->needTry)
-       {
-               /* Don't need to do this again */
-               coder->needTry = 0;
+       CVMP_OUT_NONE(COP_PREFIX_LEAVE_CATCH);
+}
 
-               /* Set the cookie for the method's exception region
-                  to the current method position */
-               ILCacheSetCookie(&(coder->codePosn), CVM_POSN());
+static void CVMCoder_RetFromFilter(ILCoder *coder)
+{
+       CVMP_OUT_NONE(COP_PREFIX_RET_FROM_FILTER);
+}
+
+static void CVMCoder_OutputExceptionTable(ILCoder *_coder,
+                                                                               
  ILCoderExceptions *exceptions)
+{
+       ILCVMCoder *coder = (ILCVMCoder *)_coder;
+       ILCoderExceptionBlock *exception;
+       ILCVMUnwind *cvmUnwind;
+       ILCVMUnwind *unwind;
+       ILCVMLabel *startLabel;
+       ILCVMLabel *endLabel;
+       int parent;
+       int index;
 
-               /* End the exception region and start a normal region */
-               ILCacheNewRegion(&(coder->codePosn), 0);
+       if(exceptions->numBlocks == 0)
+       {
+               /* There is no exception handling needed for this method */
+               return;
        }
 
-       /* Output the start and end of the code covered by the handler */
-       coder->tryHandler = CVM_POSN();
-       if(start == 0 && end == IL_MAX_UINT32)
+       cvmUnwind = (ILCVMUnwind *)ILCacheAlloc(&(coder->codePosn),
+                                                                               
        (exceptions->numBlocks + 1) * sizeof(ILCVMUnwind));
+       if(!cvmUnwind)
        {
-               /* This handler is the last one in the table */
-               CVM_OUT_TRY(start, end);
+               return;
        }
-       else
+       
+       /* Clear the cvm unwind information */
+       ILMemZero(cvmUnwind, (exceptions->numBlocks + 1) * sizeof(ILCVMUnwind));
+
+       /*
+        * Set the cookie for the method's exception region
+        * to the unwind information.
+        */
+       ILCacheSetCookie(&(coder->codePosn), cvmUnwind);
+
+       /* Setup the unwind information for the method */
+       cvmUnwind[0].start = coder->start;
+       cvmUnwind[0].end = CVM_POSN();
+       cvmUnwind[0].flags = _IL_CVM_UNWIND_TYPE_TRY;
+       cvmUnwind[0].parent = -1;
+       cvmUnwind[0].nested = -1;
+       cvmUnwind[0].nextNested = -1;
+       cvmUnwind[0].stackChange = coder->minHeight;
+       cvmUnwind[0].exceptionSlot = -1;
+       cvmUnwind[0].un.tryBlock.firstHandler = -1;
+
+       parent = 0;
+       index = 0;
+       while(index < exceptions->numBlocks)
        {
-               /* Convert the IL offsets into CVM offsets.  We assume that
-                  the labels were created previously while generating the
-                  code for the body of the method */
-               label = GetLabel(coder, start);
-               if(!label)
+               exception = &(exceptions->blocks[index]);
+               startLabel = GetLabel(coder, exception->startOffset);
+               endLabel = GetLabel(coder, exception->endOffset);
+               if(!startLabel || !endLabel)
                {
+                       /*
+                        * This is a bug in the coder.
+                        * Both labels must be  defined at this point.
+                        */
                        return;
                }
-               start = label->offset;
-               label = GetLabel(coder, end);
-               if(!label)
+               unwind = &(cvmUnwind[index + 1]);
+               unwind->start = coder->start + startLabel->offset;
+               unwind->end = coder->start + endLabel->offset;
+               unwind->parent = -1;
+               unwind->nested = -1;
+               unwind->nextNested = -1;
+               unwind->stackChange = 0;
+               /*
+                * Copy the exception slot to the unwind information.
+                */
+               unwind->exceptionSlot = exception->userData;
+               /*
+                * And reuse the exception's userData for the index in the 
unwind information.
+                */
+               exception->userData = index + 1;
+               switch(exception->flags)
                {
-                       return;
-               }
-               end = label->offset;
-               CVM_OUT_TRY(start, end);
-       }
-}
-
-/*
- * End a "try" handler block for a region of code.
- */
-static void CVMCoder_TryHandlerEnd(ILCoder *coder)
-{
-       /* Back-patch the length value for the handler */       
-       CVM_BACKPATCH_TRY(((ILCVMCoder *)coder)->tryHandler);   
-}
+                       case IL_CODER_HANDLER_TYPE_TRY:
+                       {
+                               unwind->flags = _IL_CVM_UNWIND_TYPE_TRY;
+                               unwind->stackChange = 0;
+                               unwind->un.tryBlock.firstHandler = -1;
+                       }
+                       break;
 
-/*
- * Output instructions to match a "catch" clause.
- */
-static void CVMCoder_Catch(ILCoder *_coder, ILException *exception,
-                                                  ILClass *classInfo, int 
hasRethrow)
-{
-       ILCVMCoder *coder = (ILCVMCoder *)_coder;
-       unsigned char *temp;
+                       case IL_CODER_HANDLER_TYPE_CATCH:
+                       {
+                               unwind->flags = _IL_CVM_UNWIND_TYPE_CATCH;
+                               unwind->stackChange = 1; /* For the propagate 
abort flag */
+                               unwind->un.handlerBlock.nextHandler = -1;
+                               unwind->un.handlerBlock.un.exceptionClass =
+                                       
exception->un.handlerBlock.exceptionClass;
+                       }
+                       break;
 
-       /* Duplicate the exception object */
-       CVM_OUT_NONE(COP_DUP);
-       CVM_ADJUST(1);
+                       case IL_CODER_HANDLER_TYPE_FILTEREDCATCH:
+                       {
+                               unwind->flags = 
_IL_CVM_UNWIND_TYPE_FILTEREDCATCH;
+                               unwind->stackChange = 1; /* For the propagate 
abort flag */
+                               unwind->un.handlerBlock.nextHandler = -1;
+                       }
+                       break;
 
-       /* Determine if the object is an instance of the right class */
-       CVM_OUT_PTR(COP_ISINST, classInfo);
+                       case IL_CODER_HANDLER_TYPE_FINALLY:
+                       {
+                               unwind->flags = _IL_CVM_UNWIND_TYPE_FINALLY;
+                               unwind->stackChange = 1; /* For the return 
address */
+                               unwind->un.handlerBlock.nextHandler = -1;
+                       }
+                       break;
 
-       /* Branch to the next test if not an instance */
-       temp = CVM_POSN();
-       CVM_OUT_BRANCH_PLACEHOLDER(COP_BRNULL);
+                       case IL_CODER_HANDLER_TYPE_FAULT:
+                       {
+                               unwind->flags = _IL_CVM_UNWIND_TYPE_FAULT;
+                               unwind->stackChange = 1; /* For the return 
address */
+                               unwind->un.handlerBlock.nextHandler = -1;
+                       }
+                       break;
 
-       /* If the method contains "rethrow" instructions, then save
-          the object into a temporary local for this "catch" clause */
-       if(hasRethrow)
-       {
-               CVM_OUT_NONE(COP_DUP);
-               CVM_OUT_WIDE(COP_PSTORE, exception->userData);
+                       case IL_CODER_HANDLER_TYPE_FILTER:
+                       {
+                               unwind->flags = _IL_CVM_UNWIND_TYPE_FILTER;
+                               unwind->stackChange = 0;
+                       }
+                       break;
+               }
+               ++index;
        }
 
-       CVMP_OUT_PTR(COP_PREFIX_START_CATCH, exception->ptrUserData);
-       
-       /* Branch to the start of the "catch" clause */
-       OutputBranch(_coder, COP_BR, exception->handlerOffset);
-
-       /* Back-patch the "brnull" instruction */
-       CVM_BACKPATCH_BRANCH(temp, (ILInt32)(CVM_POSN() - temp));
-
-       /* Adjust the stack back to its original height */
-       CVM_ADJUST(-1);
-}
-
-static void CVMCoder_EndCatchFinally(ILCoder *coder, ILException *exception)
-{
-       exception->ptrUserData = CVM_POSN();    
-       CVMP_OUT_NONE(COP_PREFIX_PROPAGATE_ABORT);
-}
+       /*
+        * Now set the indexes in the blocks.
+        */
+       index = 0;
+       while(index < exceptions->numBlocks)
+       {
+               exception = &(exceptions->blocks[index]);
+               unwind = &(cvmUnwind[exception->userData]);
+               if(exception->parent)
+               {
+                       unwind->parent = exception->parent->userData;
+               }
+               else
+               {
+                       /*
+                        * Set the outermost block as parent.
+                        */
+                       unwind->parent = 0;
+               }
+               if(exception->nested)
+               {
+                       unwind->nested = exception->nested->userData;
+               }
+               if(exception->nextNested)
+               {
+                       unwind->nextNested = exception->nextNested->userData;
+               }
+               switch(exception->flags)
+               {
+                       case IL_CODER_HANDLER_TYPE_TRY:
+                       {
+                               if(exception->un.tryBlock.handlerBlock)
+                               {
+                                       unwind->un.tryBlock.firstHandler =
+                                               
exception->un.tryBlock.handlerBlock->userData;
+                               }
+                       }
+                       break;
 
-static void CVMCoder_Finally(ILCoder *coder, ILException *exception, int dest)
-{
-       CVMP_OUT_PTR(COP_PREFIX_START_FINALLY, exception->ptrUserData);
-       OutputBranch(coder, COP_JSR, dest);
+                       case IL_CODER_HANDLER_TYPE_CATCH:
+                       case IL_CODER_HANDLER_TYPE_FILTEREDCATCH:
+                       case IL_CODER_HANDLER_TYPE_FINALLY:
+                       case IL_CODER_HANDLER_TYPE_FAULT:
+                       {
+                               if(exception->un.handlerBlock.nextHandler)
+                               {
+                                       unwind->un.handlerBlock.nextHandler =
+                                               
exception->un.handlerBlock.nextHandler->userData;
+                               }
+                               if(exception->flags == 
IL_CODER_HANDLER_TYPE_FILTEREDCATCH)
+                               {
+                                       
if(exception->un.handlerBlock.filterBlock)
+                                       {
+                                               
unwind->un.handlerBlock.un.filter =
+                                                       
exception->un.handlerBlock.filterBlock->userData;
+                                       }
+                               }
+                       }
+               }
+               ++index;
+       }
+       /*
+        * Set the nested information for the function block.
+        */
+       cvmUnwind[0].nested = exceptions->firstBlock->userData;
 }
 
 /*
diff --git a/engine/jitc.c b/engine/jitc.c
index 2919fad..c0a8037 100755
--- a/engine/jitc.c
+++ b/engine/jitc.c
@@ -468,16 +468,12 @@ struct _tagILJITCoder
 #include "jitc_stack.c"
 #include "jitc_labels.c"
 #include "jitc_profile.c"
+#include "jitc_except.c"
 #undef IL_JITC_CODER_INSTANCE
 
        /* The current jitted function. */
        ILJitFunction   jitFunction;
 
-       /* Flag if the catcher is started. */
-       int                             isInCatcher;
-       jit_label_t     nextBlock;
-       jit_label_t     rethrowBlock;
-
        /* The manager for running the required cctors. */
        ILCCtorMgr              cctorMgr;
 
@@ -1551,7 +1547,7 @@ void ILRuntimeExceptionRethrow(ILObject *object)
 
                if(thread)
                {
-                       thread->currentException = object;
+                       thread->thrownException = object;
                        jit_exception_throw(object);
                }
        }
@@ -1570,7 +1566,7 @@ void ILRuntimeExceptionThrow(ILObject *object)
 
                if(thread)
                {
-                       thread->currentException = (ILObject *)exception;
+                       thread->thrownException = (ILObject *)exception;
                        exception->stackTrace = 
_ILJitGetExceptionStackTrace(thread);
                        jit_exception_throw(exception);
                }
@@ -1592,7 +1588,7 @@ void ILRuntimeExceptionThrowClass(ILClass *classInfo)
        /* thrown an OutOfMenory exception then. */
        if(thread)
        {
-               thread->currentException = (ILObject *)exception;
+               thread->thrownException = (ILObject *)exception;
                exception->stackTrace = _ILJitGetExceptionStackTrace(thread);
                jit_exception_throw(exception);
        }
@@ -1607,8 +1603,8 @@ void ILRuntimeExceptionThrowOutOfMemory()
 
        if(thread)
        {
-               thread->currentException = thread->process->outOfMemoryObject;
-               jit_exception_throw(thread->currentException);
+               thread->thrownException = thread->process->outOfMemoryObject;
+               jit_exception_throw(thread->thrownException);
                return;
        }
        jit_exception_builtin(JIT_RESULT_OUT_OF_MEMORY);
@@ -1623,9 +1619,7 @@ void ILRuntimeHandleManagedSafePointFlags(ILExecThread 
*thread)
        {
                if(_ILExecThreadSelfAborting(thread) == 0)
                {
-                       thread->currentException = thread->thrownException;
-                       thread->thrownException = 0;
-                       jit_exception_throw(thread->currentException);
+                       jit_exception_throw(thread->thrownException);
                }
        }
        else if(thread->managedSafePointFlags & 
_IL_MANAGED_SAFEPOINT_THREAD_SUSPEND)
@@ -1645,21 +1639,14 @@ void ILRuntimeHandleManagedSafePointFlags(ILExecThread 
*thread)
 static void _ILJitHandleThrownException(ILJitFunction func,
                                                                                
ILJitValue thread)
 { 
-       ILJitValue thrownException = jit_insn_load_relative(func, thread,
-                                                                       
offsetof(ILExecThread, thrownException),
-                                                                       
_IL_JIT_TYPE_VPTR);
-       ILJitValue nullException = jit_value_create_nint_constant(func,
-                                                                               
                                          _IL_JIT_TYPE_VPTR,
-                                                                               
                                      (jit_nint)0);
-       jit_label_t label = jit_label_undefined;
+       ILJitValue thrownException;
+       jit_label_t label;
 
+       label = jit_label_undefined;
+       thrownException = jit_insn_load_relative(func, thread,
+                                                                               
         offsetof(ILExecThread, thrownException),
+                                                                               
         _IL_JIT_TYPE_VPTR);
        jit_insn_branch_if_not(func, thrownException, &label);
-       jit_insn_store_relative(func, thread, 
-                                                       offsetof(ILExecThread, 
currentException),
-                                                       thrownException);
-       jit_insn_store_relative(func, thread, 
-                                                       offsetof(ILExecThread, 
thrownException),
-                                                       nullException);
        jit_insn_throw(func, thrownException);
        jit_insn_label(func, &label);
 }
@@ -2084,7 +2071,7 @@ void *_ILJitExceptionHandler(int exception_type)
                }
                break;
        }
-       thread->currentException = object;
+       thread->thrownException = object;
        return object;
 }
 
@@ -2093,21 +2080,14 @@ void *_ILJitExceptionHandler(int exception_type)
  */
 static void _ILJitThrowCurrentException(ILJITCoder *coder)
 {
-       ILJitValue thread = _ILJitCoderGetThread(coder);
-       ILJitValue thrownException = jit_insn_load_relative(coder->jitFunction,
-                                                                       thread,
-                                                                       
offsetof(ILExecThread, thrownException), 
-                                                                       
_IL_JIT_TYPE_VPTR);
-       ILJitValue nullException = 
jit_value_create_nint_constant(coder->jitFunction,
-                                                                               
                                          _IL_JIT_TYPE_VPTR,
-                                                                               
                                      (jit_nint)0);
-
-       jit_insn_store_relative(coder->jitFunction, thread, 
-                                                       offsetof(ILExecThread, 
currentException),
-                                                       thrownException);
-       jit_insn_store_relative(coder->jitFunction, thread, 
-                                                       offsetof(ILExecThread, 
thrownException),
-                                                       nullException);
+       ILJitValue thread;
+       ILJitValue thrownException;
+
+       thread = _ILJitCoderGetThread(coder);
+       thrownException = jit_insn_load_relative(coder->jitFunction,
+                                                                               
         thread,
+                                                                               
         offsetof(ILExecThread, thrownException), 
+                                                                               
         _IL_JIT_TYPE_VPTR);
        jit_insn_throw(coder->jitFunction, thrownException);
 }
 
@@ -2700,6 +2680,7 @@ static ILCoder *JITCoder_Create(ILExecProcess *process, 
ILUInt32 size,
 #include "jitc_stack.c"
 #include "jitc_labels.c"
 #include "jitc_profile.c"
+#include "jitc_except.c"
 #undef IL_JITC_CODER_INIT
 
        /* Ready to go */
@@ -5079,11 +5060,11 @@ void ILJitBacktrace(void *frame, void *pc, int 
numFrames)
 #include "jitc_ptr.c"
 #include "jitc_array.c"
 #include "jitc_branch.c"
+#include "jitc_profile.c"
 #include "jitc_except.c"
 #include "jitc_conv.c"
 #include "jitc_obj.c"
 #include "jitc_call.c"
-#include "jitc_profile.c"
 #undef IL_JITC_CODE
 
 /*
@@ -5173,13 +5154,11 @@ ILCoderClass const _ILJITCoderClass =
        JITCoder_Throw,
        JITCoder_SetStackTrace,
        JITCoder_Rethrow,
-       JITCoder_Jsr,
-       JITCoder_RetFromJsr,
-       JITCoder_TryHandlerStart,
-       JITCoder_TryHandlerEnd,
-       JITCoder_Catch,
-       JITCoder_EndCatchFinally,
-       JITCoder_Finally,
+       JITCoder_CallFinally,
+       JITCoder_RetFromFinally,
+       JITCoder_LeaveCatch,
+       JITCoder_RetFromFilter,
+       JITCoder_OutputExceptionTable,
        JITCoder_PCToHandler,
        JITCoder_PCToMethod,
        JITCoder_GetILOffset,
diff --git a/engine/jitc_branch.c b/engine/jitc_branch.c
index 466f0bb..6441035 100644
--- a/engine/jitc_branch.c
+++ b/engine/jitc_branch.c
@@ -25,13 +25,30 @@
  */
 static void JITCoder_Label(ILCoder *coder, ILUInt32 offset)
 {
-       ILJITCoder *jitCoder = _ILCoderToILJITCoder(coder);
-       ILJITLabel *label = _ILJitLabelGet(jitCoder, offset, 
_IL_JIT_LABEL_NORMAL);
+       ILJITCoder *jitCoder;
+       ILJITLabel *label;
 
+       jitCoder = _ILCoderToILJITCoder(coder);
+       label = _ILJitLabelGet(jitCoder, offset, _IL_JIT_LABEL_NORMAL);
        if(label)
        {
                _ILJitValuesResetNullChecked(jitCoder);
-               if(label->labelType == _IL_JIT_LABEL_STARTFINALLY)
+               if(label->labelType == _IL_JIT_LABEL_STARTCATCH)
+               {
+               #if !defined(IL_CONFIG_REDUCE_CODE) && 
!defined(IL_WITHOUT_TOOLS)
+                       if (jitCoder->flags & IL_CODER_FLAG_STATS)
+                       {
+                               ILMutexLock(globalTraceMutex);
+                               fprintf(stdout,
+                                       "StartCatcher: %i\n", 
+                                       offset);
+                               ILMutexUnlock(globalTraceMutex);
+                       }
+               #endif
+                       _ILJitLabelRestoreStack(jitCoder, label);
+                       jit_insn_label(jitCoder->jitFunction, &(label->label));
+               }
+               else if(label->labelType == _IL_JIT_LABEL_STARTFINALLY)
                {
                #if !defined(IL_CONFIG_REDUCE_CODE) && 
!defined(IL_WITHOUT_TOOLS)
                        if (jitCoder->flags & IL_CODER_FLAG_STATS)
@@ -45,6 +62,22 @@ static void JITCoder_Label(ILCoder *coder, ILUInt32 offset)
                #endif
                        jit_insn_start_finally(jitCoder->jitFunction, 
&(label->label));
                }
+               else if(label->labelType == _IL_JIT_LABEL_STARTFILTER)
+               {
+                       
+               #if !defined(IL_CONFIG_REDUCE_CODE) && 
!defined(IL_WITHOUT_TOOLS)
+                       if (jitCoder->flags & IL_CODER_FLAG_STATS)
+                       {
+                               ILMutexLock(globalTraceMutex);
+                               fprintf(stdout,
+                                       "StartFilter: %i\n", 
+                                       offset);
+                               ILMutexUnlock(globalTraceMutex);
+                       }
+               #endif
+                       jit_insn_start_filter(jitCoder->jitFunction, 
&(label->label),
+                                                                       
_IL_JIT_TYPE_INT32);
+               }
                else
                {
                #if !defined(IL_CONFIG_REDUCE_CODE) && 
!defined(IL_WITHOUT_TOOLS)
@@ -68,7 +101,7 @@ static void JITCoder_Label(ILCoder *coder, ILUInt32 offset)
  * The result value is returned.
  */
 static ILJitValue OutputCompare(ILJITCoder *coder, int opcode,
-                                                    ILJitValue *value1, 
ILJitValue *value2)
+                                                               ILJitValue 
*value1, ILJitValue *value2)
 {
        switch(opcode)
        {
diff --git a/engine/jitc_except.c b/engine/jitc_except.c
index c2ad401..af4f7cf 100644
--- a/engine/jitc_except.c
+++ b/engine/jitc_except.c
@@ -39,6 +39,36 @@ static void _ILJitThrowSystem(ILJitFunction jitFunction,
 
 #endif /* IL_JITC_DECLARATIONS */
 
+#ifdef IL_JITC_CODER_INSTANCE
+
+       /* Flag if the catcher is started. */
+       int                             isInCatcher;
+       jit_label_t     nextBlock;
+       jit_label_t     rethrowBlock;
+       ILJitValue              aborting;
+       ILJitValue              abortBlock;
+       ILJitValue              threadAbortException;
+
+#endif /* IL_JITC_CODER_INSTANCE */
+
+#ifdef IL_JITC_CODER_INIT
+
+       /* Initialize the exception stuff */
+       coder->isInCatcher = 0;
+       coder->nextBlock = 0;
+       coder->rethrowBlock = 0;
+       coder->aborting = 0;
+       coder->abortBlock = 0;
+       coder->threadAbortException = 0;
+
+#endif /* IL_JITC_CODER_INIT */
+
+#ifdef IL_JITC_CODER_DESTROY
+
+       /* Nothing to do here */
+
+#endif /* IL_JITC_CODER_DESTROY */
+
 #ifdef IL_JITC_FUNCTIONS
 
 /*
@@ -114,7 +144,7 @@ static void _ILJitThrowSystem(ILJitFunction jitFunction,
                }
                classInfo = ILClassResolve(classInfo);
                if(!(classInfo->userData) || 
-                       (((ILClassPrivate *)(classInfo->userData))->inLayout))
+                       (((ILClassPrivate *)(classInfo->userData))->inLayout))
                {
                        if(!_LayoutClass(_thread, classInfo))
                        {
@@ -133,121 +163,126 @@ static void _ILJitThrowSystem(ILJitFunction jitFunction,
 }
 
 /*
- * Check if the current exception thrown is a ThreadAblorException
- * and save it to the threadAbortException in the current ILExecThread.
+ * Output a table of exception matching directives.
+ * Each table entry specifies a region of code for the
+ * directive.  Whenever an exception occurs in this
+ * region, the method will jump to the instructions
+ * contained in the table entry.  These instructions
+ * will typically call "finally" handlers, and then
+ * attempt to match the exception against the rules.
+ *
+ * The code generated will be something like this
+ *
+ * if pc not in region1 goto check_for_region2
+ * if pc not in nested_region1 goto check_for_nested_region2
  * 
- * Because the ThreadAbortException is a sealed class we can simply compare the
- * two ILClass pointers.
+ * check_for_nested_region2:
+ * if pc not in nested_region2 goto call_handlers_for_region1
+ *
+ * call_handlers_for_region1:
+ * call handlers for region 1
+ * goto no_more_handlers
+ * check_for_region2:
+ * if pc not in region2 goto check_for_region3
+ *
+ * check_for_region3:
  */
-static void _ILJitSetThreadAbortException(ILJITCoder *jitCoder,
-                                                                               
  ILJitValue thread,
-                                                                               
  ILJitValue exception)
-{
-       ILJitValue threadAbortException;
-       ILJitValue exceptionClass;
-       ILJitValue temp;
-       jit_label_t allreadyAbortingLabel = jit_label_undefined;
-       ILJitValue threadAbortExceptionClass = 
-               jit_value_create_nint_constant(jitCoder->jitFunction,
-                                                                          
_IL_JIT_TYPE_VPTR,
-                                                                          
(jit_nint)jitCoder->process->threadAbortClass);
-
-       /* Get the current ThreadAbortException of the thread. */
-       threadAbortException = jit_insn_load_relative(jitCoder->jitFunction,
-                                                                               
                  thread,
-                                                                               
                  offsetof(ILExecThread, threadAbortException),
-                                                                               
                  _IL_JIT_TYPE_VPTR);
-
-       /* if there is one then there is nothing else todo. */
-       jit_insn_branch_if(jitCoder->jitFunction, 
-                                          threadAbortException,
-                                          &allreadyAbortingLabel);
-
-       /* Get the class of the current exception */
-       exceptionClass = _ILJitGetObjectClass(jitCoder->jitFunction, exception);
 
-       /* Is the class not the ThreadAbortException class ? */
-       temp = jit_insn_ne(jitCoder->jitFunction,
-                                          exceptionClass,
-                                          threadAbortExceptionClass);
-
-       /* If it's not a ThreadAbortException then we are ready. */
-       jit_insn_branch_if(jitCoder->jitFunction, 
-                                          temp,
-                                          &allreadyAbortingLabel);
-
-       /* otherwise save the exception to the threadAbortException in the */
-       /* current thread. */
-       jit_insn_store_relative(jitCoder->jitFunction,
-                                                       thread,
-                                                       offsetof(ILExecThread, 
threadAbortException),
-                                                       exception);
+static jit_label_t *GetNextParentHandlerLabel(ILCoderExceptions 
*coderExceptions,
+                                                                               
          ILCoderExceptionBlock *coderException)
+{
+       ILCoderExceptionBlock *currentCoderException;
 
-       jit_insn_label(jitCoder->jitFunction, &allreadyAbortingLabel);
+       currentCoderException = coderException->parent;
+       while(currentCoderException)
+       {
+               if(currentCoderException->flags == IL_CODER_HANDLER_TYPE_TRY)
+               {
+                       /* This is a try block */
+                       if(!currentCoderException->handlerLabel)
+                       {
+                               currentCoderException->handlerLabel = (void 
*)jit_label_undefined;
+                       }
+                       return (jit_label_t 
*)&(currentCoderException->handlerLabel);
+               }
+               currentCoderException = currentCoderException->parent;
+       }
+       /*
+        * If we get here there is no surrounding try block so return the
+        * label for rethrowing the exception.
+        */
+       if(!coderExceptions->rethrowLabel)
+       {
+               coderExceptions->rethrowLabel = (void *)jit_label_undefined;
+       }
+       return (jit_label_t *)&(coderExceptions->rethrowLabel);
 }
 
-/*
- * Propagate the ThreadAbortException if present.
- */
-static void _ILJitPropagateThreadAbort(ILJITCoder *jitCoder,
-                                                                          
ILException *exception)
+static jit_label_t *GetNextHandlerBlockStartLabel(ILCoderExceptions 
*coderExceptions,
+                                                                               
                  ILCoderExceptionBlock *handler)
 {
-       /* TODO: Handle the case if the thread is not in the signature.*/
-       ILJitValue thread = _ILJitCoderGetThread(jitCoder);
-       jit_label_t label = jit_label_undefined;
-       ILJitValue currentException = (ILJitValue)(exception->ptrUserData);
-       ILJitValue nullException = 
-                       jit_value_create_nint_constant(jitCoder->jitFunction,
-                                                                               
   _IL_JIT_TYPE_VPTR,
-                                                                              
(jit_nint)0);
-       ILJitValue exceptionObject;
-       ILJitValue temp;
+       ILCoderExceptionBlock *currentHandler;
 
-#if !defined(IL_CONFIG_REDUCE_CODE) && !defined(IL_WITHOUT_TOOLS)
-       if (jitCoder->flags & IL_CODER_FLAG_STATS)
+       currentHandler = handler->un.handlerBlock.nextHandler;
+       if(currentHandler)
        {
-               ILMutexLock(globalTraceMutex);
-               fprintf(stdout,
-                       "PropagateThreadAbortException\n");
-               ILMutexUnlock(globalTraceMutex);
+               if(!currentHandler->startLabel)
+               {
+                       currentHandler->startLabel = (void 
*)jit_label_undefined;
+               }
+               return (jit_label_t *)(&currentHandler->startLabel);
        }
-#endif
-
-       /* Check if the thread is aborting. */
-       temp = jit_insn_load_relative(jitCoder->jitFunction, thread,
-                                                                 
offsetof(ILExecThread, aborting),
-                                                                 
jit_type_sys_int);
-       jit_insn_branch_if_not(jitCoder->jitFunction,
-                                                  temp,
-                                                  &label);
-
-       /* Get the threadAbortException object. */
-       exceptionObject = jit_insn_load_relative(jitCoder->jitFunction, thread,
-                                                                               
         offsetof(ILExecThread, threadAbortException),
-                                                                               
         _IL_JIT_TYPE_VPTR);
-
-       /* Check if they are the same. */
-       temp = jit_insn_eq(jitCoder->jitFunction,
-                                          exceptionObject,
-                                          currentException);
-
-       jit_insn_branch_if_not(jitCoder->jitFunction,
-                                                  temp,
-                                                  &label);
-
-       /* Clear the ThreadAbortException. */
-       jit_insn_store_relative(jitCoder->jitFunction,
-                                                       thread,
-                                                       offsetof(ILExecThread, 
threadAbortException),
-                                                       nullException);
+       /*
+        * If we get here there is no other try block on the same level.
+        * So we return the label for calling the handlers of the first
+        * surrounding try block.
+        */
+       return GetNextParentHandlerLabel(coderExceptions, handler);
+}
 
-       jit_insn_call_native(jitCoder->jitFunction,
-                                                "ILRuntimeExceptionRethrow",
-                                                ILRuntimeExceptionRethrow,
-                                                
_ILJitSignature_ILRuntimeExceptionRethrow,
-                                                &exceptionObject, 1, 
JIT_CALL_NORETURN);
+static jit_label_t *GetNextTryBlockStartLabel(ILCoderExceptions 
*coderExceptions,
+                                                                               
          ILCoderExceptionBlock *coderException)
+{
+       ILCoderExceptionBlock *currentCoderException;
 
-       jit_insn_label(jitCoder->jitFunction, &label);
+       currentCoderException = coderException->nextNested;
+       while(currentCoderException)
+       {
+               if(currentCoderException->flags == IL_CODER_HANDLER_TYPE_TRY)
+               {
+                       /* This is a try block */
+                       if(!currentCoderException->startLabel)
+                       {
+                               currentCoderException->startLabel = (void 
*)jit_label_undefined;
+                       }
+                       return (jit_label_t 
*)&(currentCoderException->startLabel);
+               }
+               else
+               {
+                       /*
+                        * See if there is a nested block.
+                        */
+                       if(currentCoderException->nested)
+                       {
+                               /*
+                                * The first nested block must be a try block.
+                                */
+                               currentCoderException = 
currentCoderException->nested;
+                               if(!currentCoderException->startLabel)
+                               {
+                                       currentCoderException->startLabel = 
(void *)jit_label_undefined;
+                               }
+                               return (jit_label_t 
*)&(currentCoderException->startLabel);
+                       }
+               }
+               currentCoderException = currentCoderException->nextNested;
+       }
+       /*
+        * If we get here there is no other try block on the same level.
+        * So we return the label for calling the handlers of the first
+        * surrounding try block.
+        */
+       return GetNextParentHandlerLabel(coderExceptions, coderException);
 }
 
 #endif /* IL_JITC_FUNCTIONS */
@@ -257,10 +292,21 @@ static void _ILJitPropagateThreadAbort(ILJITCoder 
*jitCoder,
 /*
  * Set up exception handling for the current method.
  */
-static void JITCoder_SetupExceptions(ILCoder *_coder, ILException *exceptions,
+static void JITCoder_SetupExceptions(ILCoder *_coder,
+                                                                        
ILCoderExceptions *exceptions,
                                                                         int 
hasRethrow)
 {
        ILJITCoder *jitCoder = _ILCoderToILJITCoder(_coder);
+       ILJitValue nullPointer;
+       ILJitValue nullInt32;
+       int currentException;
+       int currentCatchBlock;
+
+       if(exceptions->numBlocks == 0)
+       {
+               /* Nothing to do here. */
+               return;
+       }
 
 #if !defined(IL_CONFIG_REDUCE_CODE) && !defined(IL_WITHOUT_TOOLS)
        if (jitCoder->flags & IL_CODER_FLAG_STATS)
@@ -278,52 +324,133 @@ static void JITCoder_SetupExceptions(ILCoder *_coder, 
ILException *exceptions,
        jitCoder->nextBlock = jit_label_undefined;
        jitCoder->rethrowBlock = jit_label_undefined;
 
-       /* We need to setup the filally labels first. */
-       while(exceptions != 0)
+       /*
+        * Initialize the values needed for exception handling.
+        */
+       nullPointer = jit_value_create_nint_constant(jitCoder->jitFunction,
+                                                                               
                 _IL_JIT_TYPE_VPTR,
+                                                                               
                 (jit_nint)0);
+       nullInt32 = jit_value_create_nint_constant(jitCoder->jitFunction,
+                                                                               
           _IL_JIT_TYPE_INT32, 0);
+
+       jitCoder->threadAbortException = 
jit_value_create(jitCoder->jitFunction, _IL_JIT_TYPE_VPTR);
+       jit_insn_store(jitCoder->jitFunction, jitCoder->threadAbortException, 
nullPointer);
+       jitCoder->abortBlock = jit_value_create(jitCoder->jitFunction, 
_IL_JIT_TYPE_INT32);
+       jit_insn_store(jitCoder->jitFunction, jitCoder->abortBlock, nullInt32);
+       jitCoder->aborting = jit_value_create(jitCoder->jitFunction, 
_IL_JIT_TYPE_INT32);
+       jit_insn_store(jitCoder->jitFunction, jitCoder->abortBlock, nullInt32);
+
+       /*
+        * Setup the labels for the entries of the exception blocks.
+        */
+       currentException = 0;
+       currentCatchBlock = 0;
+       while(currentException < exceptions->numBlocks)
        {
-               if((exceptions->flags & (IL_META_EXCEPTION_FINALLY |
-                                                                
IL_META_EXCEPTION_FAULT)) != 0)
+               ILCoderExceptionBlock *block;
+
+               block = &(exceptions->blocks[currentException]);
+               switch(block->flags)
                {
-               #if !defined(IL_CONFIG_REDUCE_CODE) && 
!defined(IL_WITHOUT_TOOLS)
-                       if (jitCoder->flags & IL_CODER_FLAG_STATS)
+                       case IL_CODER_HANDLER_TYPE_FINALLY:
+                       case IL_CODER_HANDLER_TYPE_FAULT:
                        {
-                               ILMutexLock(globalTraceMutex);
-                               fprintf(stdout,
-                                       "AddFinallyLabel for offset: %i\n", 
-                                       exceptions->handlerOffset);
-                               ILMutexUnlock(globalTraceMutex);
+                       #if !defined(IL_CONFIG_REDUCE_CODE) && 
!defined(IL_WITHOUT_TOOLS)
+                               if (jitCoder->flags & IL_CODER_FLAG_STATS)
+                               {
+                                       ILMutexLock(globalTraceMutex);
+                                       fprintf(stdout,
+                                               "AddFinallyLabel for offset: 
%i\n", 
+                                               block->startOffset);
+                                       ILMutexUnlock(globalTraceMutex);
+                               }
+                       #endif
+                               jitCoder->stackTop = 0;
+                               _ILJitLabelGet(jitCoder, block->startOffset,
+                                                                               
 _IL_JIT_LABEL_STARTFINALLY);
                        }
-               #endif
-                       _ILJitLabelGet(jitCoder, exceptions->handlerOffset,
-                                                                        
_IL_JIT_LABEL_STARTFINALLY);
-               }
-               else if ((exceptions->flags & IL_META_EXCEPTION_FILTER) == 0)
-               {
-                       /* Create the label for a catch block */
-                       /* We need one value on the stack for the exception 
object. */
-                       ILJitValue exception = 
jit_value_create(jitCoder->jitFunction,
-                                                                               
                        _IL_JIT_TYPE_VPTR);
+                       break;
+
+                       case IL_CODER_HANDLER_TYPE_CATCH:
+                       case IL_CODER_HANDLER_TYPE_FILTEREDCATCH:
+                       {
+                               /* Create the label for a catch block */
+                               ILJitValue exception;
+                               ILCoderExceptionBlock *tryBlock;
+
+                       #if !defined(IL_CONFIG_REDUCE_CODE) && 
!defined(IL_WITHOUT_TOOLS)
+                               if (jitCoder->flags & IL_CODER_FLAG_STATS)
+                               {
+                                       ILMutexLock(globalTraceMutex);
+                                       fprintf(stdout,
+                                               "AddCatchLabel for offset: 
%i\n", 
+                                               block->startOffset);
+                                       ILMutexUnlock(globalTraceMutex);
+                               }
+                       #endif
+                               /*
+                                * We save the created value in the exception 
for
+                                * rethrowing the exception.
+                                */
+                               tryBlock = block->un.handlerBlock.tryBlock;
+                               if(!tryBlock->ptrUserData)
+                               {
+                                       exception = 
jit_value_create(jitCoder->jitFunction,
+                                                                               
                 _IL_JIT_TYPE_VPTR);
+                                       tryBlock->ptrUserData = (void 
*)exception;
+                                       tryBlock->userData = 
++currentCatchBlock;
+                               }
+                               block->userData = tryBlock->userData;
+                               block->ptrUserData = tryBlock->ptrUserData;
+                               /*
+                                * Create the exception value that is on the 
stack on entry
+                                * of the catch block.
+                                */
+                               exception = 
jit_value_create(jitCoder->jitFunction,
+                                                                               
         _IL_JIT_TYPE_VPTR);
+                               _ILJitStackPushValue(jitCoder, exception);
+                               _ILJitLabelGet(jitCoder, block->startOffset,
+                                                          
_IL_JIT_LABEL_STARTCATCH);
+                               /*
+                                * and reset the stack top.
+                                */
+                               jitCoder->stackTop = 0;
+                       }
+                       break;
 
-               #if !defined(IL_CONFIG_REDUCE_CODE) && 
!defined(IL_WITHOUT_TOOLS)
-                       if (jitCoder->flags & IL_CODER_FLAG_STATS)
+                       case IL_CODER_HANDLER_TYPE_FILTER:
                        {
-                               ILMutexLock(globalTraceMutex);
-                               fprintf(stdout,
-                                       "AddCatchLabel for offset: %i\n", 
-                                       exceptions->handlerOffset);
-                               ILMutexUnlock(globalTraceMutex);
+                               /* Create the label for a filter block */
+                               /* We need one value on the stack for the 
exception object. */
+                               ILJitValue exception;
+
+                       #if !defined(IL_CONFIG_REDUCE_CODE) && 
!defined(IL_WITHOUT_TOOLS)
+                               if (jitCoder->flags & IL_CODER_FLAG_STATS)
+                               {
+                                       ILMutexLock(globalTraceMutex);
+                                       fprintf(stdout,
+                                               "AddFilterLabel for offset: 
%i\n", 
+                                               block->startOffset);
+                                       ILMutexUnlock(globalTraceMutex);
+                               }
+                       #endif
+                               /*
+                                * Create the exception value that is on the 
stack on entry
+                                * of the filter.
+                                */
+                               exception = 
jit_value_create(jitCoder->jitFunction,
+                                                                               
         _IL_JIT_TYPE_VPTR);
+                               _ILJitStackPushValue(jitCoder, exception);
+                               _ILJitLabelGet(jitCoder, block->startOffset,
+                                                          
_IL_JIT_LABEL_STARTFILTER);
+                               /*
+                                * and reset the stack top.
+                                */
+                               jitCoder->stackTop = 0;
                        }
-               #endif
-                       _ILJitStackPushValue(jitCoder, exception);
-                       _ILJitLabelGet(jitCoder, exceptions->handlerOffset,
-                                                                        
_IL_JIT_LABEL_STARTCATCH);
-                       jitCoder->stackTop = 0;
-
-                       /* We save the created value in the exception too for 
rethrow or */
-                       /* propagating a ThreadAbortException. */
-                       exceptions->ptrUserData = (void *)exception;
+                       break;
                }
-               exceptions = exceptions->next;
+               ++currentException;
        }
 }
 
@@ -345,19 +472,16 @@ static void JITCoder_Throw(ILCoder *coder, int 
inCurrentMethod)
        }
 #endif
 
-       if(!(jitCoder->isInCatcher))
-       {
-               _ILJitStackItemNew(exception);
+       _ILJitStackItemNew(exception);
 
-               _ILJitStackPop(jitCoder, exception);
+       _ILJitStackPop(jitCoder, exception);
 
-               jit_insn_call_native(jitCoder->jitFunction,
-                                                        
"ILRuntimeExceptionThrow",
-                                                        
ILRuntimeExceptionThrow,
-                                                        
_ILJitSignature_ILRuntimeExceptionThrow,
-                                                        
&(_ILJitStackItemValue(exception)), 1,
-                                                        JIT_CALL_NORETURN);
-       }
+       jit_insn_call_native(jitCoder->jitFunction,
+                                                "ILRuntimeExceptionThrow",
+                                                ILRuntimeExceptionThrow,
+                                                
_ILJitSignature_ILRuntimeExceptionThrow,
+                                                
&(_ILJitStackItemValue(exception)), 1,
+                                                JIT_CALL_NORETURN);
 }
 
 /*
@@ -370,11 +494,12 @@ static void JITCoder_SetStackTrace(ILCoder *coder)
 /*
  * Output a rethrow instruction.
  */
-static void JITCoder_Rethrow(ILCoder *coder, ILException *exception)
+static void JITCoder_Rethrow(ILCoder *coder, ILCoderExceptionBlock *exception)
 {
-       ILJITCoder *jitCoder = _ILCoderToILJITCoder(coder);
+       ILJITCoder *jitCoder;
        ILJitValue exceptionObject;
 
+       jitCoder = _ILCoderToILJITCoder(coder);
 #if !defined(IL_CONFIG_REDUCE_CODE) && !defined(IL_WITHOUT_TOOLS)
        if (jitCoder->flags & IL_CODER_FLAG_STATS)
        {
@@ -385,49 +510,47 @@ static void JITCoder_Rethrow(ILCoder *coder, ILException 
*exception)
        }
 #endif
 
-       /* The rethrow instruction is allowed in a catch block. */
-       if((exception->flags & (IL_META_EXCEPTION_FILTER |
-                                                       
IL_META_EXCEPTION_FINALLY |
-                                                       
IL_META_EXCEPTION_FAULT)) == 0)
-       {
-               /* Get the current exception object. */
-               /* We saved the exception in the userData of the ILException. */
-               exceptionObject = (ILJitValue)(exception->ptrUserData);
-
-               jit_insn_call_native(jitCoder->jitFunction,
-                                                        
"ILRuntimeExceptionRethrow",
-                                                        
ILRuntimeExceptionRethrow,
-                                                        
_ILJitSignature_ILRuntimeExceptionRethrow,
-                                                        &exceptionObject, 1, 
JIT_CALL_NORETURN);
-       }
-       /* If the instruction is outside a catch handler an exception should */
-       /* be thrown. */
-       /* TODO */
+       /*
+        * Get the current exception object.
+        * We saved the exception in the ptrUserData of the coder exception 
block.
+        */
+       exceptionObject = (ILJitValue)(exception->ptrUserData);
+
+       jit_insn_call_native(jitCoder->jitFunction,
+                                                "ILRuntimeExceptionRethrow",
+                                                ILRuntimeExceptionRethrow,
+                                                
_ILJitSignature_ILRuntimeExceptionRethrow,
+                                                &exceptionObject, 1, 
JIT_CALL_NORETURN);
 }
 
 /*
- * Output a "jump to subroutine" instruction.
+ * Output a "call a finally or fault subroutine" instruction.
  */
-static void JITCoder_Jsr(ILCoder *coder, ILUInt32 dest)
+static void JITCoder_CallFinally(ILCoder *coder,
+                                                                
ILCoderExceptionBlock *exception,
+                                                                ILUInt32 dest)
 {
        ILJITCoder *jitCoder = _ILCoderToILJITCoder(coder);
+       ILJITLabel *label = _ILJitLabelGet(jitCoder, dest,
+                                                                          
_IL_JIT_LABEL_STARTFINALLY);
 
 #if !defined(IL_CONFIG_REDUCE_CODE) && !defined(IL_WITHOUT_TOOLS)
        if (jitCoder->flags & IL_CODER_FLAG_STATS)
        {
                ILMutexLock(globalTraceMutex);
                fprintf(stdout,
-                       "Jsr: dest: %i\n", 
+                       "CallFinally: dest: %i\n",
                        dest);
                ILMutexUnlock(globalTraceMutex);
        }
 #endif
+       jit_insn_call_finally(jitCoder->jitFunction, &(label->label));
 }
 
 /*
- * Output a "return from subroutine" instruction.
+ * Output a "return from finally" instruction.
  */
-static void JITCoder_RetFromJsr(ILCoder *coder)
+static void JITCoder_RetFromFinally(ILCoder *coder)
 {
        ILJITCoder *jitCoder = _ILCoderToILJITCoder(coder);
 
@@ -436,224 +559,430 @@ static void JITCoder_RetFromJsr(ILCoder *coder)
        {
                ILMutexLock(globalTraceMutex);
                fprintf(stdout,
-                       "RetFromJsr: \n");
+                       "RetFromFinally: \n");
                ILMutexUnlock(globalTraceMutex);
        }
 #endif
+       jit_insn_return_from_finally(jitCoder->jitFunction);
 }
 
 /*
- * Start a "try" handler block for a region of code.
+ * Output a "return from filter" instruction.
  */
-static void JITCoder_TryHandlerStart(ILCoder *_coder,
-                                                                        
ILUInt32 start, ILUInt32 end)
+static void JITCoder_RetFromFilter(ILCoder *coder)
 {
-       ILJITCoder *jitCoder = _ILCoderToILJITCoder(_coder);
+       ILJITCoder *jitCoder;
+       _ILJitStackItemNew(value);
 
+       jitCoder = _ILCoderToILJITCoder(coder);
 #if !defined(IL_CONFIG_REDUCE_CODE) && !defined(IL_WITHOUT_TOOLS)
        if (jitCoder->flags & IL_CODER_FLAG_STATS)
        {
                ILMutexLock(globalTraceMutex);
                fprintf(stdout,
-                       "TryHandlerStart: start: %i end: %i\n", 
-                       start,
-                       end);
+                       "RetFromFilter: \n");
                ILMutexUnlock(globalTraceMutex);
        }
 #endif
-
-       if(!(jitCoder->isInCatcher))
-       {
-#ifndef IL_JIT_THREAD_IN_SIGNATURE
-               ILJitValue thread;
-#endif
-
-               /* Tell libjit that we are in the catcher. */
-               jit_insn_start_catcher(jitCoder->jitFunction);
-               
-               jitCoder->isInCatcher = 1;
-
-#ifndef IL_JIT_THREAD_IN_SIGNATURE
-               /* 
-                * We have to make sure the current thread is available at the 
start
-                * of a catch block.
-                * This is a NOP if the thread was loaded during execution of
-                * 'normal' code.
-                */
-               thread = _ILJitCoderGetThread(jitCoder);
-#endif
-       }
-       else
-       {
-               /* Insert the jump target for the previous block. */
-               jit_insn_label(jitCoder->jitFunction, &(jitCoder->nextBlock));
-       }
-       /* and reset the label so that it can be used with the next block. */
-       jitCoder->nextBlock = jit_label_undefined;
-
-       if(start == 0 && end == IL_MAX_UINT32)
-       {
-               /* This handler was the last one in the table */
-               jit_insn_label(jitCoder->jitFunction, 
&(jitCoder->rethrowBlock));
-               jit_insn_rethrow_unhandled(jitCoder->jitFunction);
-       }
-       else
-       {
-               ILJITLabel *startLabel = _ILJitLabelFind(jitCoder, start);;
-               ILJITLabel *endLabel = _ILJitLabelFind(jitCoder, end);
-               if(startLabel && endLabel)
-               {
-                       
jit_insn_branch_if_pc_not_in_range(jitCoder->jitFunction,
-                                                                               
           startLabel->label,
-                                                                               
           endLabel->label,
-                                                                               
           &(jitCoder->nextBlock));
-               }
-       }
+       _ILJitStackPop(jitCoder, value);
+       jit_insn_return_from_filter(jitCoder->jitFunction,
+                                                               
_ILJitStackItemValue(value));
 }
 
-/*
- * End a "try" handler block for a region of code.
- */
-static void JITCoder_TryHandlerEnd(ILCoder *coder)
+static void JITCoder_LeaveCatch(ILCoder *coder,
+                                                               
ILCoderExceptionBlock *exception)
 {
-       ILJITCoder *jitCoder = _ILCoderToILJITCoder(coder);
+       ILJITCoder *jitCoder;
+       ILJitValue thread;
+       jit_label_t label;
+       jit_label_t label1;
+       ILJitValue currentExceptionBlock;
+       ILJitValue temp;
 
+       jitCoder = _ILCoderToILJITCoder(coder);
 #if !defined(IL_CONFIG_REDUCE_CODE) && !defined(IL_WITHOUT_TOOLS)
        if (jitCoder->flags & IL_CODER_FLAG_STATS)
        {
                ILMutexLock(globalTraceMutex);
                fprintf(stdout,
-                       "TryHandlerEnd: \n");
+                               "LeaveCatch: \n");
                ILMutexUnlock(globalTraceMutex);
        }
 #endif
-       jit_insn_branch(jitCoder->jitFunction, &(jitCoder->rethrowBlock));
+       thread = _ILJitCoderGetThread(jitCoder);
+       label = jit_label_undefined;
+       /* Check if we are handling a thread abort */
+       jit_insn_branch_if_not(jitCoder->jitFunction, jitCoder->aborting, 
&label);
+       /* Check if the abort was handled by the current catcher */
+       currentExceptionBlock = 
jit_value_create_nint_constant(jitCoder->jitFunction,
+                                                                               
                                   _IL_JIT_TYPE_INT32,
+                                                                               
                                   exception->userData);
+       temp = jit_insn_eq(jitCoder->jitFunction, jitCoder->abortBlock,
+                                          currentExceptionBlock);
+       jit_insn_branch_if_not(jitCoder->jitFunction, temp, &label);
+       /* Check if the thread is still aborting */
+       temp = jit_insn_load_relative(jitCoder->jitFunction, thread,
+                                                                 
offsetof(ILExecThread, aborting),
+                                                                 
jit_type_sys_int);
+       label1 = jit_label_undefined;
+       jit_insn_branch_if_not(jitCoder->jitFunction, temp, &label1);
+       /* If it still aborting then rethrow the thread abort exception. */
+       jit_insn_call_native(jitCoder->jitFunction,
+                                                "ILRuntimeExceptionRethrow",
+                                                ILRuntimeExceptionRethrow,
+                                                
_ILJitSignature_ILRuntimeExceptionRethrow,
+                                                
&jitCoder->threadAbortException, 1,
+                                                JIT_CALL_NORETURN);
+       jit_insn_label(jitCoder->jitFunction, &label1);
+       /* Reset the aborting flag */
+       temp = jit_value_create_nint_constant(jitCoder->jitFunction,
+                                                                               
  _IL_JIT_TYPE_INT32,
+                                                                               
 0);
+       jit_insn_store(jitCoder->jitFunction, jitCoder->aborting, temp);
+       jit_insn_label(jitCoder->jitFunction, &label);
 }
 
-/*
- * Output instructions to match a "catch" clause.
- */
-static void JITCoder_Catch(ILCoder *_coder, ILException *exception,
-                                                  ILClass *classInfo, int 
hasRethrow)
+static void JITCoder_OutputExceptionTable(ILCoder *coder,
+                                                                               
  ILCoderExceptions *coderExceptions)
 {
-       ILJITCoder *jitCoder = _ILCoderToILJITCoder(_coder);
-       ILJitValue thread = _ILJitCoderGetThread(jitCoder);
-       ILJitValue currentException = (ILJitValue)(exception->ptrUserData);
-       ILJitValue classTo = 
jit_value_create_nint_constant(jitCoder->jitFunction,
-                                                                               
                                _IL_JIT_TYPE_VPTR,
-                                                                               
                                (jit_nint)classInfo);
-       ILJitValue method = 
jit_value_create_nint_constant(jitCoder->jitFunction,
-                                                                               
                           _IL_JIT_TYPE_VPTR,
-                                                                               
                           
(jit_nint)ILCCtorMgr_GetCurrentMethod(&(jitCoder->cctorMgr)));
-       ILJitValue nullException = 
jit_value_create_nint_constant(jitCoder->jitFunction,
-                                                                               
                                          _IL_JIT_TYPE_VPTR,
-                                                                               
                                      (jit_nint)0);
-
+       ILJITCoder *jitCoder;
+       ILJitValue thread;
+       ILJitValue temp;
+       ILJitValue newAbortException;
+       ILJitValue threadAbortExceptionClass;
+       ILJitValue exceptionClass;
        ILJitValue exceptionObject;
-       ILJitValue args[3];
-       ILJitValue returnValue;
-       ILJITLabel *catchBlock = 0;
-       jit_label_t label = jit_label_undefined;
+    ILJitValue nullException;
+       jit_label_t label;
+       jit_label_t label1;
+       int allowWalkUp;
+       ILCoderExceptionBlock *coderException;
+       ILCoderExceptionBlock *currentCoderException;
+       ILCoderExceptionBlock *prevCoderException;
+       
+       jitCoder = _ILCoderToILJITCoder(coder);
 
-#if !defined(IL_CONFIG_REDUCE_CODE) && !defined(IL_WITHOUT_TOOLS)
-       if (jitCoder->flags & IL_CODER_FLAG_STATS)
-       {
-               ILMutexLock(globalTraceMutex);
-               fprintf(stdout,
-                       "Catch: %s hasRethrow: %i at %i\n",
-                       ILClass_Name(classInfo),
-                       hasRethrow,
-                       exception->handlerOffset);
-               ILMutexUnlock(globalTraceMutex);
-       }
-#endif
+       /* Tell libjit that we are in the catcher. */
+       jit_insn_start_catcher(jitCoder->jitFunction);
+       jitCoder->isInCatcher = 1;
 
-       /* Get the thrown exception object. */
-       exceptionObject = jit_insn_load_relative(jitCoder->jitFunction,
-                                                                               
         thread,
-                                                                               
         offsetof(ILExecThread, currentException),
+       thread = _ILJitCoderGetThread(jitCoder);
+       /* Get the exception object. */
+       exceptionObject = jit_insn_load_relative(jitCoder->jitFunction, thread,
+                                                                               
         offsetof(ILExecThread, thrownException),
                                                                                
         _IL_JIT_TYPE_VPTR);
-
-       /* Save the thrown exception to the current exception block. */
-       jit_insn_store(jitCoder->jitFunction, currentException, 
exceptionObject);
-
-       /* Look if the object can be casted to the cought exception type. */
-       args[0] = method;
-       args[1] = currentException;
-       args[2] = classTo;
-       returnValue = jit_insn_call_native(jitCoder->jitFunction,
-                                                                          
"ILRuntimeCanCastClass",
-                                                                          
ILRuntimeCanCastClass,
-                                                                          
_ILJitSignature_ILRuntimeCanCastClass,
-                                                                          
args, 3, JIT_CALL_NOTHROW);
-       jit_insn_branch_if_not(jitCoder->jitFunction, returnValue, &label);
-
-       /* Save the exception in the threadAbortException if it is one. */
-       _ILJitSetThreadAbortException(jitCoder, thread, currentException);
-
-       /* Push the exception object on the stack. */
-       jitCoder->stackTop = 0;
-       _ILJitStackPushValue(jitCoder, currentException);
-       catchBlock = _ILJitLabelGet(jitCoder, exception->handlerOffset,
-                                                                               
  _IL_JIT_LABEL_STARTCATCH);
-
-       jit_insn_call_native(jitCoder->jitFunction, "jit_exception_clear_last",
-                                                                               
                jit_exception_clear_last,
-                                                                               
                _ILJitSignature_JitExceptionClearLast,
-                                                                               
                0, 0, JIT_CALL_NOTHROW);
-       jit_insn_store_relative(jitCoder->jitFunction, thread, 
-                                                       offsetof(ILExecThread, 
currentException),
+       /* And clear the exception */
+       nullException = jit_value_create_nint_constant(jitCoder->jitFunction,
+                                                                               
                   _IL_JIT_TYPE_VPTR,
+                                                                               
                   (jit_nint)0);
+       jit_insn_store_relative(jitCoder->jitFunction, thread,
+                                                       offsetof(ILExecThread, 
thrownException),
                                                        nullException);
-       jit_insn_branch(jitCoder->jitFunction, &(catchBlock->label));
+
+
+       temp = jit_value_create_nint_constant(jitCoder->jitFunction,
+                                                                               
  _IL_JIT_TYPE_INT32, 0);
+       newAbortException = jit_value_create(jitCoder->jitFunction,
+                                                                               
 _IL_JIT_TYPE_INT32);
+       jit_insn_store(jitCoder->jitFunction, newAbortException, temp);
+
+       /* Check if we have to handle a new thread abort. */
+       label = jit_label_undefined;
+       /*
+        * First check if we are not alteady handling a thread abort.
+        */
+       jit_insn_branch_if_not(jitCoder->jitFunction,
+                                                  jitCoder->aborting,
+                                                  &label);
+       temp = jit_insn_load_relative(jitCoder->jitFunction, thread,
+                                                                 
offsetof(ILExecThread, aborting),
+                                                                 
jit_type_sys_int);
+       /*
+        * Then check if the thread is aborting.
+        */
+       jit_insn_branch_if_not(jitCoder->jitFunction,
+                                                  temp, &label);
+       /*
+        * Check if the exception is a threadAbortException.
+        */
+       threadAbortExceptionClass = 
jit_value_create_nint_constant(jitCoder->jitFunction,
+                                                                               
                                           _IL_JIT_TYPE_VPTR,
+                                                                               
                                           
(jit_nint)jitCoder->process->threadAbortClass);
+
+       /* Get the class of the current exception */
+       exceptionClass = _ILJitGetObjectClass(jitCoder->jitFunction, 
exceptionObject);
+
+       /* Is the class not the ThreadAbortException class ? */
+       temp = jit_insn_ne(jitCoder->jitFunction,
+                                          exceptionClass,
+                                          threadAbortExceptionClass);
+
+       /* If it's not then this exception is thrown while handling an abort. */
+       jit_insn_branch_if(jitCoder->jitFunction, temp, &label);
+
+       /* Otherwise store the current exception object for later use */
+       jit_insn_store(jitCoder->jitFunction, jitCoder->threadAbortException, 
exceptionObject);
+       /* and set the flag that we are handling a thread abort. */
+       temp = jit_value_create_nint_constant(jitCoder->jitFunction, 
_IL_JIT_TYPE_INT32, 1);
+       jit_insn_store(jitCoder->jitFunction, jitCoder->aborting, temp);
+       jit_insn_store(jitCoder->jitFunction, newAbortException, temp);
+
        jit_insn_label(jitCoder->jitFunction, &label);
-}
 
-static void JITCoder_EndCatchFinally(ILCoder *coder, ILException *exception)
-{
-       ILJITCoder *jitCoder = _ILCoderToILJITCoder(coder);
-       
-       if((exception->flags & (IL_META_EXCEPTION_FINALLY |
-                                                        
IL_META_EXCEPTION_FAULT)) != 0)
+       /* Process all regions in the method */
+       prevCoderException = 0;
+       allowWalkUp = 1;
+       currentCoderException = coderExceptions->firstBlock;
+       while(currentCoderException)
        {
-       #if !defined(IL_CONFIG_REDUCE_CODE) && !defined(IL_WITHOUT_TOOLS)
-               if (jitCoder->flags & IL_CODER_FLAG_STATS)
+               if(allowWalkUp)
                {
-                       ILMutexLock(globalTraceMutex);
-                       fprintf(stdout,
-                               "EndFinally: \n");
-                       ILMutexUnlock(globalTraceMutex);
+                       if(currentCoderException->flags == 
IL_CODER_HANDLER_TYPE_TRY)
+                       {
+                               jit_label_t *label;
+                               ILJITLabel *startLabel;
+                               ILJITLabel *endLabel;
+
+                               /* This is a try block */
+                               if(currentCoderException->startLabel)
+                               {
+                                       /* This is a branch target */
+                                       jit_insn_label(jitCoder->jitFunction,
+                                                                  (jit_label_t 
*)&(currentCoderException->startLabel));
+                               }
+                               label = 
GetNextTryBlockStartLabel(coderExceptions,
+                                                                               
                  currentCoderException);
+                               startLabel = _ILJitLabelFind(jitCoder,
+                                                                               
         currentCoderException->startOffset);
+                               endLabel = _ILJitLabelFind(jitCoder,
+                                                                               
   currentCoderException->endOffset);
+                               if(startLabel && endLabel)
+                               {
+                                       
jit_insn_branch_if_pc_not_in_range(jitCoder->jitFunction,
+                                                                               
                           startLabel->label,
+                                                                               
                           endLabel->label,
+                                                                               
                           label);
+                               }
+                       }
+                       if(currentCoderException->nested)
+                       {
+                               /*
+                                * There are nested exception blocks.
+                                * So process them first.
+                                */
+                               currentCoderException = 
currentCoderException->nested;
+                               continue;
+                       }
+               }
+               /*
+                * Emit the handler code for this block.
+                */
+               if(currentCoderException->flags == IL_CODER_HANDLER_TYPE_TRY)
+               {
+                       /* This is a try block */
+                       ILJitValue currentExceptionBlock;
+                       jit_label_t *notHandledLabel;
+                       jit_label_t tempLabel;
+                       jit_label_t *tryBlockEndLabel;
+
+                       if(currentCoderException->handlerLabel)
+                       {
+                               /* This is a branch target */
+                               jit_insn_label(jitCoder->jitFunction,
+                                                          (jit_label_t 
*)&(currentCoderException->handlerLabel));
+                       }
+                       /*
+                        * Emit the handler code.
+                        */
+                       tempLabel = jit_label_undefined;
+                       tryBlockEndLabel = &tempLabel;
+                       notHandledLabel = 0;
+                       label = jit_label_undefined;
+                       /* Check if we are handling a thread abort */
+                       jit_insn_branch_if_not(jitCoder->jitFunction, 
newAbortException, &label);
+                       /* Store the current block that handles the abort */
+                       currentExceptionBlock = 
jit_value_create_nint_constant(jitCoder->jitFunction,
+                                                                               
                                                   _IL_JIT_TYPE_INT32,
+                                                                               
                                                   
currentCoderException->userData);
+                       jit_insn_store(jitCoder->jitFunction, 
jitCoder->abortBlock, currentExceptionBlock);
+                       jit_insn_label(jitCoder->jitFunction, &label);
+                       coderException = 
currentCoderException->un.tryBlock.handlerBlock;
+                       while(coderException)
+                       {
+                               if(coderException->startLabel)
+                               {
+                                       /* This is a branch target */
+                                       jit_insn_label(jitCoder->jitFunction,
+                                                                  (jit_label_t 
*)&(coderException->startLabel));
+                               }
+                               notHandledLabel = 
GetNextHandlerBlockStartLabel(coderExceptions,
+                                                                               
                                                coderException);
+                               if(coderException->un.handlerBlock.nextHandler 
== 0)
+                               {
+                                       tryBlockEndLabel = notHandledLabel;
+                                       notHandledLabel = &tempLabel;
+                               }
+                               switch(coderException->flags & 
IL_CODER_HANDLER_TYPE_MASK)
+                               {
+                                       case IL_CODER_HANDLER_TYPE_FINALLY:
+                                       case IL_CODER_HANDLER_TYPE_FAULT:
+                                       {
+                                               /*
+                                                * This is a finally or fault 
block.
+                                                */
+                                               JITCoder_CallFinally(coder, 
coderException,
+                                                                               
         coderException->startOffset);
+                                       }
+                                       break;
+
+                                       case IL_CODER_HANDLER_TYPE_CATCH:
+                                       {
+                                               /*
+                                                * This is a typed catch block.
+                                                */
+                                               ILJitValue method;
+                                               ILJitValue classTo;
+                                               ILJitValue args[3];
+                                               ILJitValue returnValue;
+                                               ILJITLabel *catchBlock = 0;
+
+                                               classTo = 
jit_value_create_nint_constant(jitCoder->jitFunction,
+                                                                               
                                                 _IL_JIT_TYPE_VPTR,
+                                                                               
                                                 
(jit_nint)coderException->un.handlerBlock.exceptionClass);
+                                               method = 
jit_value_create_nint_constant(jitCoder->jitFunction,
+                                                                               
                                                _IL_JIT_TYPE_VPTR,
+                                                                               
                                                
(jit_nint)ILCCtorMgr_GetCurrentMethod(&(jitCoder->cctorMgr)));
+                                               /* 
+                                                * Look if the object can be 
casted to the caught exception type.
+                                                */
+                                               args[0] = method;
+                                               args[1] = exceptionObject;
+                                               args[2] = classTo;
+                                               returnValue = 
jit_insn_call_native(jitCoder->jitFunction,
+                                                                               
                                   "ILRuntimeCanCastClass",
+                                                                               
                                   ILRuntimeCanCastClass,
+                                                                               
                                   _ILJitSignature_ILRuntimeCanCastClass,
+                                                                               
                                   args, 3, JIT_CALL_NOTHROW);
+                                               
jit_insn_branch_if_not(jitCoder->jitFunction, returnValue, notHandledLabel);
+                                               /*
+                                                * Save the current exception 
for a possible rethrow.
+                                                */
+                                               
jit_insn_store(jitCoder->jitFunction,
+                                                                          
(ILJitValue)coderException->ptrUserData,
+                                                                          
exceptionObject);
+                                               jitCoder->stackTop = 0;
+                                               _ILJitStackPushValue(jitCoder, 
exceptionObject);
+                                               catchBlock = 
_ILJitLabelGet(jitCoder,
+                                                                               
                        coderException->startOffset,
+                                                                               
                        _IL_JIT_LABEL_STARTCATCH);
+                                               
jit_insn_branch(jitCoder->jitFunction, &(catchBlock->label));
+                                               jitCoder->stackTop = 0;
+                                       }
+                                       break;
+
+                                       case 
IL_CODER_HANDLER_TYPE_FILTEREDCATCH:
+                                       {
+                                               /*
+                                                * This is a filtered catch 
block.
+                                                */
+                                               /*
+                                                * TODO: Handle catch blocks 
with filters.
+                                                */
+                                               
+                                               
+                                       }
+                                       break;
+                               }
+                               coderException = 
coderException->un.handlerBlock.nextHandler;
+                       }
+                       /*
+                        * Handle a thrown threadAbortException.
+                        */
+                       jit_insn_label(jitCoder->jitFunction, notHandledLabel);
+                       label = jit_label_undefined;
+                       label1 = jit_label_undefined;
+                       jit_insn_branch_if_not(jitCoder->jitFunction,
+                                                                  
jitCoder->aborting, &label);
+                       currentExceptionBlock = 
jit_value_create_nint_constant(jitCoder->jitFunction,
+                                                                               
                                                   _IL_JIT_TYPE_INT32,
+                                                                               
                                                   
currentCoderException->userData);
+                       temp = jit_insn_eq(jitCoder->jitFunction, 
jitCoder->abortBlock, currentExceptionBlock);
+                       jit_insn_branch_if_not(jitCoder->jitFunction, temp, 
&label);
+                       /*
+                        * The thread abort was last handled here.
+                        * Check if the thread is still aborting.
+                        */
+                       temp = jit_insn_load_relative(jitCoder->jitFunction, 
thread,
+                                                                               
  offsetof(ILExecThread, aborting),
+                                                                               
  jit_type_sys_int);
+                       jit_insn_branch_if_not(jitCoder->jitFunction,
+                                                                  temp, 
&label1);
+                       /*
+                        * The thread is still aborting.
+                        * So replace the current exception with the first 
threadAbortException.
+                        */
+                       jit_insn_store(jitCoder->jitFunction, exceptionObject,
+                                                  
jitCoder->threadAbortException);
+                       /*
+                        * And set the new thread abort again.
+                        */
+                       temp = 
jit_value_create_nint_constant(jitCoder->jitFunction, _IL_JIT_TYPE_INT32, 1);
+                       jit_insn_store(jitCoder->jitFunction, 
newAbortException, temp);
+                       jit_insn_branch(jitCoder->jitFunction, &label);
+                       jit_insn_label(jitCoder->jitFunction, &label1);
+                       /*
+                        * Reset the aborting flag.
+                        */
+                       temp = 
jit_value_create_nint_constant(jitCoder->jitFunction, _IL_JIT_TYPE_INT32, 0);
+                       jit_insn_store(jitCoder->jitFunction, 
jitCoder->aborting, temp);
+                       jit_insn_label(jitCoder->jitFunction, &label);
+                       jit_insn_branch(jitCoder->jitFunction, 
tryBlockEndLabel);
+               }
+               /*
+                * Look for the next block to process.
+                */
+               if(currentCoderException->nextNested)
+               {
+                       /*
+                        * An other exception block on the same level.
+                        */
+                       currentCoderException = 
currentCoderException->nextNested;
+                       allowWalkUp = 1;
+               }
+               else
+               {
+                       currentCoderException = currentCoderException->parent;
+                       allowWalkUp = 0;
                }
-       #endif
-               jit_insn_return_from_finally(jitCoder->jitFunction);
        }
-       else if((exception->flags & (IL_META_EXCEPTION_FILTER |
-                                                                
IL_META_EXCEPTION_FINALLY |
-                                                                
IL_META_EXCEPTION_FAULT)) == 0)
+
+       if(coderExceptions->rethrowLabel)
        {
-               _ILJitPropagateThreadAbort(jitCoder, exception);
+               /* This is a branch target */
+               jit_insn_label(jitCoder->jitFunction,
+                                          (jit_label_t 
*)&(coderExceptions->rethrowLabel));
        }
-}
 
-/*
- * Handle the leave opcodes.
- */
-static void JITCoder_Finally(ILCoder *coder, ILException *exception, int dest)
-{
-       ILJITCoder *jitCoder = _ILCoderToILJITCoder(coder);
-       ILJITLabel *label = _ILJitLabelGet(jitCoder, dest,
-                                                                          
_IL_JIT_LABEL_STARTFINALLY);
+       /*
+        * If execution gets here, then there were no applicable catch blocks,
+        * so we always throw the exception to the calling method.
+        */
 
-#if !defined(IL_CONFIG_REDUCE_CODE) && !defined(IL_WITHOUT_TOOLS)
-       if (jitCoder->flags & IL_CODER_FLAG_STATS)
+       /*
+        * Notify the coder to emit profiling for method end
+        */
+       if((jitCoder->flags & IL_CODER_FLAG_METHOD_PROFILE) != 0)
        {
-               ILMutexLock(globalTraceMutex);
-               fprintf(stdout,
-                       "CallFinally: dest: %i\n",
-                       dest);
-               ILMutexUnlock(globalTraceMutex);
+               JITCoder_ProfilingEnd(coder);
        }
-#endif
-       jit_insn_call_finally(jitCoder->jitFunction, &(label->label));
+
+       /*
+        * Restore the thrown exception and throw it to the caller.
+        */
+       jit_insn_store_relative(jitCoder->jitFunction, thread,
+                                                       offsetof(ILExecThread, 
thrownException),
+                                                       exceptionObject);
+       jit_insn_rethrow_unhandled(jitCoder->jitFunction);
 }
 
 /*
diff --git a/engine/jitc_labels.c b/engine/jitc_labels.c
index b563268..3ba53cb 100644
--- a/engine/jitc_labels.c
+++ b/engine/jitc_labels.c
@@ -26,6 +26,7 @@
 #define _IL_JIT_LABEL_NORMAL 1
 #define _IL_JIT_LABEL_STARTCATCH 2
 #define _IL_JIT_LABEL_STARTFINALLY 4
+#define _IL_JIT_LABEL_STARTFILTER 8
 
 /*
  * Define the structure of a JIT label.
diff --git a/engine/null_coder.c b/engine/null_coder.c
index 8f99fd4..da85594 100644
--- a/engine/null_coder.c
+++ b/engine/null_coder.c
@@ -336,7 +336,8 @@ static void Coder_LoadVirtualAddr(ILCoder *coder, ILMethod 
*methodInfo)
 static void Coder_LoadInterfaceAddr(ILCoder *coder, ILMethod *methodInfo)
 {
 }
-static void Coder_SetupExceptions(ILCoder *coder, ILException *exceptions,
+static void Coder_SetupExceptions(ILCoder *coder,
+                                                                 
ILCoderExceptions *exceptions,
                                                                  int 
hasRethrow)
 {
 }
@@ -346,29 +347,24 @@ static void Coder_Throw(ILCoder *coder, int 
inCurrentMethod)
 static void Coder_SetStackTrace(ILCoder *coder)
 {
 }
-static void Coder_Rethrow(ILCoder *coder, ILException *exception)
+static void Coder_Rethrow(ILCoder *coder, ILCoderExceptionBlock *exception)
 {
 }
-static void Coder_Jsr(ILCoder *coder, ILUInt32 dest)
+static void Coder_CallFinally(ILCoder *coder, ILCoderExceptionBlock *exception,
+                                                         ILUInt32 dest)
 {
 }
-static void Coder_RetFromJsr(ILCoder *coder)
+static void Coder_RetFromFinally(ILCoder *coder)
 {
 }
-static void Coder_TryHandlerStart(ILCoder *coder, ILUInt32 start, ILUInt32 end)
+static void Coder_LeaveCatch(ILCoder *coder, ILCoderExceptionBlock *exception)
 {
 }
-static void Coder_TryHandlerEnd(ILCoder *coder)
+static void Coder_RetFromFilter(ILCoder *coder)
 {
 }
-static void Coder_Catch(ILCoder *coder, ILException *exception,
-                                           ILClass *classInfo, int hasRethrow)
-{
-}
-static void Coder_EndCatchFinally(ILCoder *coder, ILException *exception)
-{
-}
-static void Coder_Finally(ILCoder *coder, ILException *exception, int dest)
+static void Coder_OutputExceptionTable(ILCoder *coder,
+                                                                          
ILCoderExceptions *exceptions)
 {
 }
 static void *Coder_PCToHandler(ILCoder *coder, void *pc, int beyond)
@@ -549,13 +545,11 @@ ILCoderClass const _ILNullCoderClass = {
        Coder_Throw,
        Coder_SetStackTrace,
        Coder_Rethrow,
-       Coder_Jsr,
-       Coder_RetFromJsr,
-       Coder_TryHandlerStart,
-       Coder_TryHandlerEnd,
-       Coder_Catch,
-       Coder_EndCatchFinally,
-       Coder_Finally,
+       Coder_CallFinally,
+       Coder_RetFromFinally,
+       Coder_LeaveCatch,
+       Coder_RetFromFilter,
+       Coder_OutputExceptionTable,
        Coder_PCToHandler,
        Coder_PCToMethod,
        Coder_GetILOffset,
diff --git a/engine/verify.c b/engine/verify.c
index 7ad68fb..ee9e8f3 100644
--- a/engine/verify.c
+++ b/engine/verify.c
@@ -34,6 +34,13 @@ extern       "C" {
 #endif
 
 /*
+ * Some error codes used during verification
+ */
+#define IL_VERIFY_OK                   0
+#define IL_VERIFY_BRANCH_ERR   1
+#define IL_VERIFY_TYPE_ERR             2
+
+/*
  * Temporary memory allocator.
  */
 typedef struct
@@ -634,6 +641,352 @@ static int IsSubClass(ILType *type, ILClass *classInfo)
        }
 }
 
+static int
+NestExceptionBlocks(ILCoderExceptionBlock *block,
+                                       ILCoderExceptionBlock *prevEB,
+                                       ILCoderExceptionBlock *firstNestedEB,
+                                       ILCoderExceptionBlock **firstEB)
+{
+       ILCoderExceptionBlock *lastNestedEB;
+       ILCoderExceptionBlock *nextEB;
+
+       block->nested = firstNestedEB;
+       block->parent = firstNestedEB->parent;
+       firstNestedEB->parent = block;
+       lastNestedEB = firstNestedEB;
+       nextEB = firstNestedEB->nextNested;
+       while(nextEB)
+       {
+               if(block->endOffset <= nextEB->startOffset)
+               {
+                       /*
+                        * The next block is not nested in the current block.
+                        */
+                       break;
+               }
+               if(block->endOffset >= nextEB->endOffset)
+               {
+                       /*
+                        * The next block is nested in the current block too.
+                        */
+                       nextEB->parent = block;
+                       lastNestedEB = nextEB;
+               }
+               else
+               {
+                       /* Partially overlapping blocks are not allowed */
+                       return 0;
+               }
+               nextEB = nextEB->nextNested;
+       }
+       block->nextNested = lastNestedEB->nextNested;
+       lastNestedEB->nextNested = 0;
+       if(prevEB)
+       {
+               prevEB->nextNested = block;
+       }
+       else
+       {
+               if(block->parent)
+               {
+                       nextEB = block->parent;
+                       nextEB->nested = block;
+               }
+               else
+               {
+                       nextEB = *firstEB;
+                       *firstEB = block;
+               }
+       }
+       return 1;
+}
+
+static int
+InsertExceptionBlock(ILCoderExceptions *coderExceptions,
+                                        ILCoderExceptionBlock *block)
+{
+       ILCoderExceptionBlock *prevEB;
+       ILCoderExceptionBlock *checkEB;
+
+       prevEB = 0;
+       checkEB = coderExceptions->firstBlock;
+       while(checkEB)
+       {
+               if(block->endOffset <= checkEB->startOffset)
+               {
+                       /* The current block is before the check block */
+                       if(prevEB)
+                       {
+                               block->nextNested = prevEB->nextNested;
+                               prevEB->nextNested = block;
+                               block->parent = prevEB->parent;
+                       }
+                       else
+                       {
+                               if(checkEB->parent)
+                               {
+                                       checkEB = checkEB->parent;
+                                       block->nextNested = checkEB->nested;
+                                       checkEB->nested = block;
+                                       block->parent = checkEB;
+                               }
+                               else
+                               {
+                                       block->nextNested = 
coderExceptions->firstBlock;
+                                       coderExceptions->firstBlock = block;
+                               }
+                       }
+                       break;
+               }
+               else if(block->startOffset >= checkEB->endOffset)
+               {
+                       /*
+                        * The current block starts after the check block.
+                        */
+                       if(checkEB->nextNested)
+                       {
+                               prevEB = checkEB;
+                               checkEB = checkEB->nextNested;
+                       }
+                       else
+                       {
+                               checkEB->nextNested = block;
+                               block->parent = checkEB->parent;
+                               break;
+                       }
+               }
+               else if(block->startOffset <= checkEB->startOffset &&
+                               block->endOffset >= checkEB->endOffset)
+               {
+                       /*
+                        * The current block encloses the check block.
+                        */
+                       if(!NestExceptionBlocks(block, prevEB, checkEB,
+                                                                       
&(coderExceptions->firstBlock)))
+                       {
+                               return 0;
+                       }
+                       break;
+               }
+               else if(block->startOffset >= checkEB->startOffset &&
+                               block->endOffset <= checkEB->endOffset)
+               {
+                       /*
+                        * The current try block is nested in the check try 
block.
+                        */
+                       if(checkEB->nested)
+                       {
+                               prevEB = 0;
+                               checkEB = checkEB->nested;
+                       }
+                       else
+                       {
+                               checkEB->nested = block;
+                               block->parent = checkEB;
+                               break;
+                       }
+               }
+               else
+               {
+                       /*
+                        * Partially overlapping blocks are not allowed.
+                        */
+                       return 0;
+               }
+       }
+       return 1;
+}
+
+static ILCoderExceptionBlock *
+FindOrAddTryBlock(ILCoderExceptions *coderExceptions,
+                                 ILUInt32 tryStart, ILUInt32 tryEnd)
+{
+       ILCoderExceptionBlock *block;
+       ILUInt32 current;
+       
+       current = 0;
+       while(current < coderExceptions->numBlocks)
+       {
+               block = &(coderExceptions->blocks[current]);
+               if((block->startOffset == tryStart) && (block->endOffset == 
tryEnd) &&
+                       (block->flags == IL_CODER_HANDLER_TYPE_TRY))
+               {
+                       return block;
+               }
+               ++current;
+       }
+       /* If we get here no matching try block was found */
+       block = &(coderExceptions->blocks[coderExceptions->numBlocks++]);
+       block->flags = IL_CODER_HANDLER_TYPE_TRY;
+       block->startOffset = tryStart;
+       block->endOffset = tryEnd;
+       block->un.tryBlock.handlerBlock = 0;
+       block->parent = 0;
+       block->nested = 0;
+       block->nextNested = 0;
+
+       /*
+        * Now insert the new try block at it's place in the exception block
+        * structure
+        */
+       if(!coderExceptions->firstBlock)
+       {
+               coderExceptions->firstBlock = block;
+       }
+       else
+       {
+               if(!InsertExceptionBlock(coderExceptions, block))
+               {
+                       --coderExceptions->numBlocks;
+                       return 0;
+               }
+       }
+       return block;
+}
+
+static void
+AddHandlerBlock(ILCoderExceptionBlock *tryBlock, ILCoderExceptionBlock 
*handler)
+{
+       if(!tryBlock->un.tryBlock.handlerBlock)
+       {
+               tryBlock->un.tryBlock.handlerBlock = handler;
+       }
+       else
+       {
+               ILCoderExceptionBlock *nextHandler;
+
+               nextHandler = tryBlock->un.tryBlock.handlerBlock;
+               while(nextHandler)
+               {
+                       if(!nextHandler->un.handlerBlock.nextHandler)
+                       {
+                               nextHandler->un.handlerBlock.nextHandler = 
handler;
+                               break;
+                       }
+                       nextHandler = nextHandler->un.handlerBlock.nextHandler;
+               }
+       }
+}
+
+static int
+AddExceptionBlock(ILCoderExceptions *coderExceptions,
+                                 ILMethod *method, ILException *exception)
+{
+       ILCoderExceptionBlock *tryBlock;
+       ILCoderExceptionBlock *handler;
+       ILUInt32 startOffset;
+       ILUInt32 endOffset;
+
+       startOffset = exception->tryOffset;
+       endOffset = exception->tryOffset + exception->tryLength;
+       if(endOffset < startOffset)
+       {
+               return IL_VERIFY_BRANCH_ERR;
+       }
+       /*
+        * Find the try block for this exception handler.
+        */
+       tryBlock = FindOrAddTryBlock(coderExceptions, startOffset, endOffset);
+       if(!tryBlock)
+       {
+               return IL_VERIFY_BRANCH_ERR;
+       }
+
+       startOffset = exception->handlerOffset;
+       endOffset = exception->handlerOffset + exception->handlerLength;
+       if(endOffset < startOffset)
+       {
+               return IL_VERIFY_BRANCH_ERR;
+       }
+
+       /*
+        * Allocate a new handler block.
+        */
+       handler = &(coderExceptions->blocks[coderExceptions->numBlocks++]);
+       handler->startOffset = startOffset;
+       handler->endOffset = endOffset;
+       handler->parent = 0;
+       handler->nested = 0;
+       handler->nextNested = 0;
+       handler->startLabel = 0;
+       handler->handlerLabel = 0;
+       if(exception->flags & (IL_META_EXCEPTION_FINALLY | 
IL_META_EXCEPTION_FAULT))
+       {
+               /*
+                * A finally or fault handler.
+                */
+               if(exception->flags & IL_META_EXCEPTION_FINALLY)
+               {
+                       handler->flags = IL_CODER_HANDLER_TYPE_FINALLY;
+               }
+               else
+               {
+                       handler->flags = IL_CODER_HANDLER_TYPE_FAULT;
+               }
+               handler->un.handlerBlock.nextHandler = 0;
+               handler->un.handlerBlock.filterBlock = 0;
+               handler->un.handlerBlock.exceptionClass = 0;
+               handler->un.handlerBlock.tryBlock = tryBlock;;
+       }
+       else
+       {
+               handler->un.handlerBlock.nextHandler = 0;
+               handler->un.handlerBlock.tryBlock = tryBlock;;
+               if(exception->flags & IL_META_EXCEPTION_FILTER)
+               {
+                       /*
+                        * A catch block with filter.
+                        */
+                       ILCoderExceptionBlock *filterBlock;
+
+                       filterBlock = 
&(coderExceptions->blocks[coderExceptions->numBlocks++]);
+                       filterBlock->flags = IL_CODER_HANDLER_TYPE_FILTER;
+                       filterBlock->startOffset = exception->extraArg;
+                       filterBlock->endOffset = exception->handlerOffset;
+                       filterBlock->parent = 0;
+                       filterBlock->nested = 0;
+                       filterBlock->nextNested = 0;
+                       filterBlock->startLabel = 0;
+                       filterBlock->handlerLabel = 0;
+                       if(!InsertExceptionBlock(coderExceptions, filterBlock))
+                       {
+                               return IL_VERIFY_BRANCH_ERR;
+                       }
+                       handler->flags = IL_CODER_HANDLER_TYPE_FILTEREDCATCH;
+                       handler->un.handlerBlock.filterBlock = filterBlock;
+                       handler->un.handlerBlock.exceptionClass = 0;
+               }
+               else
+               {
+                       /*
+                        * A catch block.
+                        */
+                       ILClass *classInfo;
+                       ILProgramItem *item;
+
+                       handler->flags = IL_CODER_HANDLER_TYPE_CATCH;
+                       handler->un.handlerBlock.filterBlock = 0;
+
+                       /* Validate the class token */
+                       item = ((ILProgramItem 
*)ILImageTokenInfo(ILProgramItem_Image(method),
+                                                                               
                          exception->extraArg));
+                       classInfo = ILProgramItemToClass(item);
+                       if(!classInfo ||
+                          !ILClassAccessible(classInfo, 
ILMethod_Owner(method)))
+                       {
+                               return IL_VERIFY_TYPE_ERR;
+                       }
+                       handler->un.handlerBlock.exceptionClass = classInfo;
+               }
+       }
+       if(!InsertExceptionBlock(coderExceptions, handler))
+       {
+               return IL_VERIFY_BRANCH_ERR;
+       }
+       AddHandlerBlock(tryBlock, handler);
+       return IL_VERIFY_OK;
+}
+
 /*
  * Push the appropriate synchronization object for a synchronized method.
  */
@@ -706,6 +1059,11 @@ int _ILVerify(ILCoder *coder, unsigned char **start, 
ILMethod *method,
                          ILMethodCode *code, int unsafeAllowed, ILExecThread 
*thread)
 {
        TempAllocator allocator;
+       ILCoderExceptions coderExceptions;
+       ILCoderExceptionBlock *coderException;
+       ILCoderExceptionBlock *currentCoderException;
+       int numHandlers;
+       int extraCodeLen;
        unsigned long *jumpMask;
        unsigned char *pc;
        ILUInt32 len;
@@ -733,7 +1091,7 @@ int _ILVerify(ILCoder *coder, unsigned char **start, 
ILMethod *method,
        ILType *localVars;
        int lastWasJump;
        ILException *exceptions;
-       ILException *exception, *currentException;
+       ILException *exception;
        int hasRethrow;
        int tryInlineType;
        int coderFlags;
@@ -769,22 +1127,147 @@ int _ILVerify(ILCoder *coder, unsigned char **start, 
ILMethod *method,
                return 0;
        }
 
+       /* Clear the exception management structure */
+       ILMemZero(&coderExceptions, sizeof(ILCoderExceptions));
+       /*
+        * Initialize the size of the additional code generated for
+        * synchronization.
+        */
+       extraCodeLen = 0;
+       /* And set the last label to the code length */
+       coderExceptions.lastLabel = code->codeLen;
+       
+       /* Initialize the memory allocator that is used for temporary
+          allocation during bytecode verification */
+       ILMemZero(allocator.buffer, sizeof(allocator.buffer));
+       allocator.posn = 0;
+       allocator.overflow = 0;
+
        coderFlags = ILCoderGetFlags(coder);
        optimizationLevel = ILCoderGetOptimizationLevel(coder);
        isStatic = ILMethod_IsStatic(method);
        isSynchronized = ILMethod_IsSynchronized(method);
 
+       result = 0;
+       if(exceptions || isSynchronized)
+       {
+               numHandlers = 0;
+               exception = exceptions;
+               while(exception)
+               {
+                       ++numHandlers;
+                       exception = exception->next;
+               }
+               if(isSynchronized)
+               {
+                       /* We'll need an extra try and flnally block for 
synchronization */
+                       ++numHandlers;
+               }
+               /*
+                * Allocate memory for the exception infos.
+                * There might be create 3 coder exception blocks for one
+                * IL exception.
+                * So we allocate memory for the worst case here.
+                */
+               coderExceptions.blocks = ILCalloc(sizeof(ILCoderExceptionBlock),
+                                                                               
  numHandlers * 3);
+               if(!coderExceptions.blocks)
+               {
+                       return 0;
+               }
+
+               /* Now setup the exception structure */
+               exception = exceptions;
+               while(exception)
+               {
+                       switch(AddExceptionBlock(&coderExceptions, method, 
exception))
+                       {
+                               case IL_VERIFY_BRANCH_ERR:
+                               {
+                                       VERIFY_BRANCH_ERROR();
+                               }
+                               break;
+
+                               case IL_VERIFY_TYPE_ERR:
+                               {
+                                       VERIFY_TYPE_ERROR();
+                               }
+                               break;
+                       }
+                       exception = exception->next;
+               }
+               /*
+                * Now check if all exception block limits are in the code.
+                */
+               len = code->codeLen;
+               coderException = coderExceptions.firstBlock;
+               if(coderException)
+               {
+                       /*
+                        * Check the start offset of the first exception block 
in the
+                        * lowest list.
+                        */
+                       if(coderException->startOffset > len)
+                       {
+                               VERIFY_BRANCH_ERROR();
+                       }
+                       /*
+                        * Look for the last exception block in the lowest list.
+                        */
+                       while(coderException->nextNested)
+                       {
+                               coderException = coderException->nextNested;
+                       }
+                       /*
+                        * Check the end offset of the last exception block in 
the
+                        * lowest list.
+                        * All other exceprion blocks end at or before this 
offset.
+                        */
+                       if(coderException->endOffset > len)
+                       {
+                               VERIFY_BRANCH_ERROR();
+                       }
+               }
+               if(isSynchronized)
+               {
+                       /*
+                        * Wrap the whole function in a try block with a fault 
handler.
+                        */
+                       ILException tempException;
+
+                       tempException.flags = IL_META_EXCEPTION_FAULT;
+                       tempException.tryOffset = 0;
+                       tempException.tryLength = len;
+                       tempException.handlerOffset = len;
+                       tempException.handlerLength = 1;
+                       tempException.extraArg = 0;
+                       tempException.userData = 0;
+                       tempException.ptrUserData = 0;
+                       tempException.next = 0;
+
+                       switch(AddExceptionBlock(&coderExceptions, method, 
&tempException))
+                       {
+                               case IL_VERIFY_BRANCH_ERR:
+                               {
+                                       VERIFY_BRANCH_ERROR();
+                               }
+                               break;
+
+                               case IL_VERIFY_TYPE_ERR:
+                               {
+                                       VERIFY_TYPE_ERROR();
+                               }
+                               break;
+                       }
+                       extraCodeLen = 2;
+               }
+       }
+
 restart:
        result = 0;
        labelList = 0;
        hasRethrow = 0;
 
-       /* Initialize the memory allocator that is used for temporary
-          allocation during bytecode verification */
-       ILMemZero(allocator.buffer, sizeof(allocator.buffer));
-       allocator.posn = 0;
-       allocator.overflow = 0;
-
        /* Reset the prefix information */
        ILMemZero(&prefixInfo, sizeof(ILCoderPrefixInfo));
 
@@ -801,7 +1284,7 @@ restart:
 
        /* Allocate the jump target mask */
        jumpMask = (unsigned long *)TempAllocate
-                                       (&allocator, 
BYTES_FOR_MASK(code->codeLen));
+                                       (&allocator, 
BYTES_FOR_MASK(code->codeLen + extraCodeLen));
        if(!jumpMask)
        {
                VERIFY_MEMORY_ERROR();
@@ -968,108 +1451,63 @@ restart:
        }
 
        /* Mark the start and end of exception blocks as special jump targets */
-       exception = exceptions;
-       while(exception != 0)
-       {
-               /* Mark the start and end of the try region */
-               if(exception->tryOffset >= code->codeLen ||
-                  (exception->tryOffset + exception->tryLength) <
-                               exception->tryOffset || /* Wrap-around check */
-                  (exception->tryOffset + exception->tryLength) > 
code->codeLen)
-               {
-                       VERIFY_BRANCH_ERROR();
-               }
-               MarkJumpTarget(jumpMask, exception->tryOffset);
-               MarkSpecialJumpTarget(jumpMask, exception->tryOffset);
-               MarkJumpTarget(jumpMask, exception->tryOffset + 
exception->tryLength);
-               MarkSpecialJumpTarget
-                       (jumpMask, exception->tryOffset + exception->tryLength);
-
-               /* The stack must be empty on entry to the try region */
-               SET_TARGET_STACK_EMPTY(exception->tryOffset);
-
-               /* What else do we need to do? */
-               if((exception->flags & IL_META_EXCEPTION_FILTER) != 0)
-               {
-                       /* This is an exception filter */
-                       if(exception->extraArg >= code->codeLen)
-                       {
-                               VERIFY_BRANCH_ERROR();
-                       }
-                       MarkJumpTarget(jumpMask, exception->extraArg);
-                       MarkSpecialJumpTarget(jumpMask, exception->extraArg);
-
-                       /* The filter label will be called with an object on 
the stack,
-                          so record that in the label list for later */
-                       classInfo = 
ILClassResolveSystem(ILProgramItem_Image(method), 0,
-                                                                               
         "Object", "System");
-                       if(!classInfo)
-                       {
-                               /* Ran out of memory trying to create 
"System.Object" */
-                               VERIFY_MEMORY_ERROR();
-                       }
-                       SET_TARGET_STACK(exception->extraArg, classInfo);
-               }
-               else if((exception->flags & IL_META_EXCEPTION_FINALLY) != 0 ||
-                       (exception->flags & IL_META_EXCEPTION_FAULT) != 0)
+       numHandlers = 0;
+       while(numHandlers < coderExceptions.numBlocks)
+       {
+               coderException = &(coderExceptions.blocks[numHandlers]);
+               MarkJumpTarget(jumpMask, coderException->startOffset);
+               MarkSpecialJumpTarget(jumpMask, coderException->startOffset);
+               MarkJumpTarget(jumpMask, coderException->endOffset);
+               MarkSpecialJumpTarget(jumpMask, coderException->endOffset);
+               switch(coderException->flags)
                {
-                       /* This is a finally or fault clause */
-                       if(exception->handlerOffset >= code->codeLen ||
-                          (exception->handlerOffset + 
exception->handlerLength) <
-                                       exception->handlerOffset || /* 
Wrap-around check */
-                          (exception->handlerOffset + 
exception->handlerLength) >
-                                       code->codeLen)
+                       case IL_CODER_HANDLER_TYPE_TRY:
                        {
-                               VERIFY_BRANCH_ERROR();
+                               /* Nothing to do here */
                        }
-                       MarkJumpTarget(jumpMask, exception->handlerOffset);
-                       MarkSpecialJumpTarget(jumpMask, 
exception->handlerOffset);
-                       MarkJumpTarget
-                               (jumpMask, exception->handlerOffset + 
exception->handlerLength);
-                       MarkSpecialJumpTarget
-                               (jumpMask, exception->handlerOffset + 
exception->handlerLength);
-
-                       /* The clause will be called with nothing on the stack 
*/
-                       SET_TARGET_STACK_EMPTY(exception->handlerOffset);
-               }
-               else
-               {
-                       /* This is a catch block */
-                       if(exception->handlerOffset >= code->codeLen ||
-                          (exception->handlerOffset + 
exception->handlerLength) <
-                                       exception->handlerOffset || /* 
Wrap-around check */
-                          (exception->handlerOffset + 
exception->handlerLength) >
-                                       code->codeLen)
+                       break;
+
+                       case IL_CODER_HANDLER_TYPE_CATCH:
                        {
-                               VERIFY_BRANCH_ERROR();
+                               /* This is a typed catch block */
+                               classInfo = 
coderException->un.handlerBlock.exceptionClass;
+                               /*
+                                * This block will be called with an object of 
the given
+                                * type on the stack.
+                                */
+                               SET_TARGET_STACK(coderException->startOffset, 
classInfo);
                        }
-                       MarkJumpTarget(jumpMask, exception->handlerOffset);
-                       MarkSpecialJumpTarget(jumpMask, 
exception->handlerOffset);
-                       MarkJumpTarget
-                               (jumpMask, exception->handlerOffset + 
exception->handlerLength);
-                       MarkSpecialJumpTarget
-                               (jumpMask, exception->handlerOffset + 
exception->handlerLength);
+                       break;
 
-                       /* Validate the class token */
-                       classInfo = ILProgramItemToClass
-                               ((ILProgramItem 
*)ILImageTokenInfo(ILProgramItem_Image(method),
-                                                                               
                   exception->extraArg));
-                       if(classInfo &&
-                          ILClassAccessible(classInfo, ILMethod_Owner(method)))
+                       case IL_CODER_HANDLER_TYPE_FINALLY:
+                       case IL_CODER_HANDLER_TYPE_FAULT:
                        {
-                               /* The handler label will be called with an 
object on the
-                                  stack, so record that in the label list for 
later */
-                               SET_TARGET_STACK(exception->handlerOffset, 
classInfo);
+                               /* This is a finally or fault clause */
+                               /* The clause will be called with nothing on 
the stack */
+                               
SET_TARGET_STACK_EMPTY(coderException->startOffset);
                        }
-                       else
+                       break;
+
+                       case IL_CODER_HANDLER_TYPE_FILTER:
+                       case IL_CODER_HANDLER_TYPE_FILTEREDCATCH:
                        {
-                               /* The class token is invalid, or not 
accessible to us */
-                               VERIFY_TYPE_ERROR();
+                               /* This is an exception filter or the 
corresponding catch block */
+                               /* 
+                                * The block will be called with an object on 
the stack,
+                                * so record that in the label list for later
+                                */
+                               classInfo = 
ILClassResolveSystem(ILProgramItem_Image(method),
+                                                                               
                 0, "Object", "System");
+                               if(!classInfo)
+                               {
+                                       /* Ran out of memory trying to create 
"System.Object" */
+                                       VERIFY_MEMORY_ERROR();
+                               }
+                               SET_TARGET_STACK(coderException->startOffset, 
classInfo);
                        }
+                       break;
                }
-
-               /* Move on to the next exception */
-               exception = exception->next;
+               ++numHandlers;
        }
 
        /* Make sure that all jump targets are instruction starts */
@@ -1127,7 +1565,7 @@ restart:
        /* Set up for exception handling if necessary */
        if(exceptions || isSynchronized)
        {
-               ILCoderSetupExceptions(coder, exceptions, hasRethrow);
+               ILCoderSetupExceptions(coder, &coderExceptions, hasRethrow);
        }
 
        /* Verify the code */
@@ -1253,13 +1691,47 @@ restart:
                VERIFY_INSN_ERROR();
        }
 
+       /*
+        * Generate the code for the fault block for synchronization.
+        */
+       if(isSynchronized)
+       {
+               coderException = FindExceptionBlock(&coderExceptions, 
code->codeLen);
+               /*
+                * This check is for catching bugs.
+                */
+               if(!coderException ||
+                  ((coderException->flags & IL_CODER_HANDLER_TYPE_FINALLY) == 
0))
+               {
+                       VERIFY_BRANCH_ERROR();
+               }
+               /*
+                * Insert the start label for the fault handler.
+                */
+               ILCoderLabel(coder, code->codeLen);
+
+               /*
+                * Call the Monitor.Exit method.
+                */
+               PUSH_SYNC_OBJECT();
+               ILCoderCallInlineable(coder, IL_INLINEMETHOD_MONITOR_EXIT, 0, 
0);
+               /*
+                * Leave the fault block.
+                */
+               ILCoderRetFromFinally(coder);
+               /*
+                * Insert the end label for the fault handler.
+                */
+               ILCoderLabel(coder, code->codeLen + 1);
+       }
+       
        /* Mark the end of the method */
        ILCoderMarkEnd(coder);
 
        /* Output the exception handler table, if necessary */
-       if(exceptions != 0 || isSynchronized)
+       if(coderExceptions.numBlocks > 0)
        {
-               OutputExceptionTable(coder, method, exceptions, hasRethrow, 
coderFlags);
+               ILCoderOutputExceptionTable(coder, &coderExceptions);
        }
 
        /* Finish processing using the coder */
@@ -1269,6 +1741,24 @@ restart:
        if(result == IL_CODER_END_RESTART)
        {
                TempAllocatorDestroy(&allocator);
+               /* Reinitialize the memory allocator that is used for temporary
+                  allocation during bytecode verification */
+               ILMemZero(allocator.buffer, sizeof(allocator.buffer));
+               allocator.posn = 0;
+               allocator.overflow = 0;
+
+               /*
+                * Reset the userdata in the exception blocks.
+                */
+               numHandlers = 0;
+               while(numHandlers < coderExceptions.numBlocks)
+               {
+                       coderException = &(coderExceptions.blocks[numHandlers]);
+                       coderException->userData = 0;
+                       coderException->ptrUserData = 0;
+                       ++numHandlers;
+               }
+               
                goto restart;
        }
 #ifdef IL_VERIFY_DEBUG
@@ -1293,6 +1783,11 @@ cleanup:
        {
                ILMethodFreeExceptions(exceptions);
        }
+       if(coderExceptions.blocks)
+       {
+               ILFree(coderExceptions.blocks);
+       }
+
        return result;
 }
 
diff --git a/engine/verify_except.c b/engine/verify_except.c
index b1f8c77..f83ccc2 100644
--- a/engine/verify_except.c
+++ b/engine/verify_except.c
@@ -21,137 +21,34 @@
 #if defined(IL_VERIFY_GLOBALS)
 
 /*
- * Output a table of exception matching directives.
- * Each table entry specifies a region of code for the
- * directive.  Whenever an exception occurs in this
- * region, the method will jump to the instructions
- * contained in the table entry.  These instructions
- * will typically call "finally" handlers, and then
- * attempt to match the exception against the rules.
+ * Find the most nested exception block where an offset is located.
+ * Returns NULL if no such exception block could be found.
  */
-static void OutputExceptionTable(ILCoder *coder, ILMethod *method,
-                                                                ILException 
*exceptions, int hasRethrow,
-                                                                int coderFlags)
+static ILCoderExceptionBlock *FindExceptionBlock(ILCoderExceptions 
*coderExceptions,
+                                                                               
                 ILUInt32 offset)
 {
-       ILUInt32 offset;
-       ILUInt32 end;
-       int isStatic;
-       ILException *exception;
-       ILClass *classInfo;
-       
-       /* Process all regions in the method */
-       offset = 0;
-       for(;;)
-       {
-               int handlerStarted;
-
-               handlerStarted = 0;
+       ILCoderExceptionBlock *block;
+       ILCoderExceptionBlock *prevEB;
 
-               /* Find the end of the region that starts at "offset" */
-               end = IL_MAX_UINT32;
-               exception = exceptions;
-               while(exception != 0)
-               {
-                       if(offset < exception->tryOffset)
-                       {
-                               /* We are in the code before this exception 
region */
-                               if(end > exception->tryOffset)
-                               {
-                                       end = exception->tryOffset;
-                               }
-                       }
-                       else if(offset >= exception->tryOffset &&
-                               offset < (exception->tryOffset + 
exception->tryLength))
-                       {
-                               /* We are in code in the middle of this 
exception region */
-                               if(end > (exception->tryOffset + 
exception->tryLength))
-                               {
-                                       end = exception->tryOffset + 
exception->tryLength;
-                               }
-                       }
-                       exception = exception->next;
-               }
-               if(end == IL_MAX_UINT32)
+       prevEB = 0;
+       block = coderExceptions->firstBlock;
+       while(block)
+       {
+               if(offset < block->startOffset)
                {
                        break;
                }
-
-               /* Output exception matching code for this region */
-               exception = exceptions;
-               while(exception != 0)
+               else if(offset >= block->endOffset)
                {
-                       if(offset >= exception->tryOffset &&
-                          offset < (exception->tryOffset + 
exception->tryLength))
-                       {
-                               if((exception->flags & 
(IL_META_EXCEPTION_FINALLY |
-                                                                               
IL_META_EXCEPTION_FAULT)) != 0)
-                               {
-                                       /* Call a "finally" or "fault" clause */
-                                       if(!handlerStarted)
-                                       {
-                                               /* Output the region 
information to the table */
-                                               ILCoderTryHandlerStart(coder, 
offset, end);
-                                               handlerStarted = 1;
-                                       }
-                                       ILCoderFinally(coder, exception, 
exception->handlerOffset);
-                               }
-                               else if((exception->flags & 
IL_META_EXCEPTION_FILTER) == 0)
-                               {
-                                       if(!handlerStarted)
-                                       {
-                                               /* Output the region 
information to the table */
-                                               ILCoderTryHandlerStart(coder, 
offset, end);
-                                               handlerStarted = 1;
-                                       }
-                                       /* Match against a "catch" clause */
-                                       classInfo = ILProgramItemToClass
-                                               ((ILProgramItem 
*)ILImageTokenInfo
-                                                       
(ILProgramItem_Image(method), exception->extraArg));
-
-                                       ILCoderCatch(coder, exception, 
classInfo, hasRethrow);
-                               }
-                               else
-                               {
-                                       /* TODO: handle a "filter" clause */
-                               }
-                       }
-                       exception = exception->next;
+                       block = block->nextNested;
                }
-
-               if(handlerStarted)
+               else
                {
-                       /* If execution falls off the end of the matching code,
-                          then throw the exception to the calling method */
-                       ILCoderThrow(coder, 0);
-
-                       /* Mark the end of the handler */
-                       ILCoderTryHandlerEnd(coder);
+                       prevEB = block;
+                       block = block->nested;
                }
-
-               /* Advance to the next region within the code */
-               offset = end;
-       }
-
-       /* If execution gets here, then there were no applicable catch blocks,
-          so we always throw the exception to the calling method */
-       ILCoderTryHandlerStart(coder, 0, IL_MAX_UINT32);
-       
-       if (ILMethod_IsSynchronized(method))
-       {
-               /* Exit the sync lock before throwing to the calling method */
-               isStatic = ILMethod_IsStatic(method);
-               PUSH_SYNC_OBJECT();
-               ILCoderCallInlineable(coder, IL_INLINEMETHOD_MONITOR_EXIT, 0, 
0);
        }
-
-       /* Notify the coder to emit profiling for method end */
-       if((coderFlags & IL_CODER_FLAG_METHOD_PROFILE) != 0)
-       {
-               ILCoderProfileEnd(coder);
-       }
-
-       ILCoderThrow(coder, 0);
-       ILCoderTryHandlerEnd(coder);
+       return prevEB;
 }
 
 /*
@@ -172,20 +69,23 @@ static IL_INLINE int InsideExceptionBlock(ILException 
*exception,
 }
 
 /*
- * Determine if an offset is inside an exception handler's "handle it" range.
+ * Determine the most nested catch block where the offset is in..
  */
-static IL_INLINE int InsideExceptionHandler(ILException *exception,
-                                                                               
    ILUInt32 offset)
+static IL_INLINE ILCoderExceptionBlock *
+InsideExceptionHandler(ILCoderExceptions *coderExceptions, ILUInt32 offset)
 {
-       if(offset >= exception->handlerOffset &&
-          offset < (exception->handlerOffset + exception->handlerLength))
-       {
-               return 1;
-       }
-       else
+       ILCoderExceptionBlock *block;
+
+       block = FindExceptionBlock(coderExceptions, offset);
+       while(block)
        {
-               return 0;
+               if(block->flags & IL_CODER_HANDLER_TYPE_CATCH)
+               {
+                       return block;
+               }
+               block = block->parent;
        }
+       return 0;
 }
 
 /*
@@ -249,7 +149,7 @@ case IL_OP_THROW:
                   the object to those handlers.  Otherwise throw directly
                   to the calling method */
                ILCoderSetStackTrace(coder);
-               if (exceptions)
+               if(coderExceptions.numBlocks > 0)
                {
                        /* Throw to the exception table */
                        ILCoderThrow(coder, 1);
@@ -285,21 +185,10 @@ break;
 case IL_OP_PREFIX + IL_PREFIX_OP_RETHROW:
 {
        /* Re-throw the current exception */
-       exception = exceptions;
-       while(exception != 0)
+       coderException = InsideExceptionHandler(&coderExceptions, offset);
+       if(coderException)
        {
-               if((exception->flags & (IL_META_EXCEPTION_FINALLY |
-                                                               
IL_META_EXCEPTION_FAULT |
-                                                               
IL_META_EXCEPTION_FILTER)) == 0 &&
-                  InsideExceptionHandler(exception, offset))
-               {
-                       break;
-               }
-               exception = exception->next;
-       }
-       if(exception != 0)
-       {
-               ILCoderRethrow(coder, exception);
+               ILCoderRethrow(coder, coderException);
                lastWasJump = 1;
        }
        else
@@ -314,34 +203,15 @@ case IL_OP_ENDFINALLY:
        /* End the current "finally" or "fault" clause */
        if(stackSize == 0)
        {
-               currentException = 0;
-               
-               exception = exceptions;
-
-               while(exception != 0)
-               {
-                       if (offset >= exception->handlerOffset 
-                               && offset <= (exception->handlerOffset + 
exception->handlerLength))
-                       {
-                               if (exception->flags & 
IL_META_EXCEPTION_FINALLY)
-                               {
-                                       /* This is a current exception clause 
that's leaving. */
-                                       currentException = exception;
-
-                                       break;
-                               }
-                       }
-
-                       exception = exception->next;
-               }
-
-               if (currentException == 0)
+               coderException = FindExceptionBlock(&coderExceptions, offset);
+               if(!coderException ||
+                  ((coderException->flags & IL_CODER_HANDLER_TYPE_FINALLY) == 
0))
                {
                        VERIFY_BRANCH_ERROR();
                }
-               
-               ILCoderEndCatchFinally(coder, currentException);
-               ILCoderRetFromJsr(coder);
+               /* We are in a finally or fault block */
+               ILCoderRetFromFinally(coder);
+               stackSize = 0;
                lastWasJump = 1;
        }
        else
@@ -353,9 +223,26 @@ break;
 
 case IL_OP_PREFIX + IL_PREFIX_OP_ENDFILTER:
 {
-       /* End the current "filter" clause */
-       /* TODO */
-       lastWasJump = 1;
+       /*
+        * End the current "filter" clause.
+        * There must be exactly one element on the evaluation stack of
+        * type int32.
+        */
+       if(stackSize == 1)
+       {
+               coderException = FindExceptionBlock(&coderExceptions, offset);
+               if(!coderException ||
+                  (coderException->flags != IL_CODER_HANDLER_TYPE_FILTER))
+               {
+                       VERIFY_BRANCH_ERROR();
+               }
+               ILCoderRetFromFilter(coder);
+               lastWasJump = 1;
+       }
+       else
+       {
+          VERIFY_STACK_ERROR();
+       }
 }
 break;
 
@@ -365,7 +252,7 @@ case IL_OP_LEAVE_S:
        dest = GET_SHORT_DEST();
 processLeave:
        
-       currentException = 0;
+       currentCoderException = 0;
        
        /* The stack must be empty when we leave the block */
        while(stackSize)
@@ -376,43 +263,58 @@ processLeave:
                stackSize--;
        }
 
-       /* Find the handler for this "leave" instruction*/
-       exception = exceptions;
-       while(exception != 0)
+       /* Call any applicable "finally" handlers, but not "fault" handlers */
+       coderException = FindExceptionBlock(&coderExceptions, offset);
+       while(coderException != 0)
        {
-               if (offset >= exception->handlerOffset 
-                       && offset < (exception->handlerOffset + 
exception->handlerLength))
+               /*
+                * If the leave target is inside this exception block then stop 
here.
+                */
+               if((coderException->startOffset <= dest) &&
+                  (coderException->endOffset > dest))
                {
-                       if (exception->flags == IL_META_EXCEPTION_FINALLY 
-                               || exceptions->flags == IL_META_EXCEPTION_CATCH)
-                       {
-                               currentException = exception;                   
        
-                       }                       
+                       break;
                }
-               
-               exception = exception->next;
-       }
-       
-       /* Call any applicable "finally" handlers, but not "fault" handlers */
-       exception = exceptions;
-       while(exception != 0)
-       {               
-               if((exception->flags & IL_META_EXCEPTION_FINALLY) != 0 &&
-                  InsideExceptionBlock(exception, offset) &&
-                  !InsideExceptionBlock(exception, dest))
+               switch(coderException->flags)
                {
-                       /* Call the "finally" clause for exiting this level */
-                       ILCoderFinally(coder, exception, 
exception->handlerOffset);
-               }
+                       case IL_CODER_HANDLER_TYPE_TRY:
+                       {
+                               currentCoderException = 
coderException->un.tryBlock.handlerBlock;
+                               while(currentCoderException)
+                               {
+                                       if(currentCoderException->flags == 
IL_CODER_HANDLER_TYPE_FINALLY)
+                                       {
+                                               /* Call the "finally" clause 
for exiting this level */
+                                               ILCoderCallFinally(coder, 
currentCoderException,
+                                                                               
   currentCoderException->startOffset);
+                                       }
+                                       currentCoderException = 
currentCoderException->un.handlerBlock.nextHandler;
+                               }
+                       }
+                       break;
 
-               exception = exception->next;
-       }
+                       case IL_CODER_HANDLER_TYPE_FINALLY:
+                       case IL_CODER_HANDLER_TYPE_FAULT:
+                       case IL_CODER_HANDLER_TYPE_FILTER:
+                       {
+                               /*
+                                * Finally, fault and filters are not allowed 
to be left with
+                                * a leave opcode.
+                                */
+                               VERIFY_BRANCH_ERROR();
+                       }
+                       break;
 
-       if (currentException)
-       {
-               ILCoderEndCatchFinally(coder, currentException);
+                       case IL_CODER_HANDLER_TYPE_CATCH:
+                       case IL_CODER_HANDLER_TYPE_FILTEREDCATCH:
+                       {
+                               ILCoderLeaveCatch(coder, coderException);
+                       }
+                       break;
+               }
+               coderException = coderException->parent;
        }
-       
+
        /* Output the branch instruction */
        ILCoderBranch(coder, opcode, dest, ILEngineType_I4, ILEngineType_I4);
        VALIDATE_BRANCH_STACK(dest);
diff --git a/include/il_coder.h b/include/il_coder.h
index 9fab3a2..da5eebd 100644
--- a/include/il_coder.h
+++ b/include/il_coder.h
@@ -1,7 +1,7 @@
 /*
  * il_coder.h - Interface to the "coder" within the runtime engine.
  *
- * Copyright (C) 2001  Southern Storm Software, Pty Ltd.
+ * Copyright (C) 2001, 2010  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
@@ -64,6 +64,75 @@ typedef enum
 #define        ILEngineType_ValidTypes 8
 
 /*
+ * Structures to keep track of the exception handling blocks
+ * during verification.
+ */
+
+/*
+ * Exceprion handler block types
+ *
+ * The values are choosen so that the different types can be determined
+ * easily.
+ * 1. try blocks: no bits are set
+ * 2. handler blocks (typed catch and filtered catch): bit 0x01 is set
+ * 3. cleanups (finally or fault): bit 0x04 is set
+ * 4. filters for filtered catch blocks: value is 0x02
+ */
+#define IL_CODER_HANDLER_TYPE_TRY                              0x00
+#define IL_CODER_HANDLER_TYPE_CATCH                            0x01
+#define IL_CODER_HANDLER_TYPE_FILTEREDCATCH            0x03
+#define IL_CODER_HANDLER_TYPE_FINALLY                  0x04
+#define IL_CODER_HANDLER_TYPE_FAULT                            0x06
+#define IL_CODER_HANDLER_TYPE_FILTER                   0x02
+#define IL_CODER_HANDLER_TYPE_MASK                             0x07
+
+typedef struct _tagILCoderExceptionBlock ILCoderExceptionBlock;
+typedef struct _tagILCoderHandlerBlock ILCoderHandlerBlock;
+typedef struct _tagILCoderTryBlock ILCoderTryBlock;
+typedef struct _tagILCoderExceptions ILCoderExceptions;
+
+struct _tagILCoderHandlerBlock
+{
+       ILCoderExceptionBlock      *nextHandler;
+       ILClass                                    *exceptionClass;
+       ILCoderExceptionBlock      *filterBlock;
+       ILCoderExceptionBlock      *tryBlock;
+};
+
+struct _tagILCoderTryBlock
+{
+       ILCoderExceptionBlock      *handlerBlock;
+};
+
+struct _tagILCoderExceptionBlock
+{
+       ILUInt32                                        flags;
+       ILUInt32                                        startOffset;
+       ILUInt32                                        endOffset;
+       ILUInt32                                        userData;
+       void                                       *ptrUserData;
+       void                                       *startLabel;
+       void                                       *handlerLabel;
+       ILCoderExceptionBlock      *parent;
+       ILCoderExceptionBlock      *nested;
+       ILCoderExceptionBlock      *nextNested;
+       union
+       {
+               ILCoderTryBlock                 tryBlock;
+               ILCoderHandlerBlock             handlerBlock;
+       } un;
+};
+
+struct _tagILCoderExceptions
+{
+       ILCoderExceptionBlock      *blocks;
+       ILCoderExceptionBlock      *firstBlock;
+       ILUInt32                                        numBlocks;
+       ILUInt32                                        lastLabel;
+       void                                       *rethrowLabel;
+};
+
+/*
  * Type that is used for stack items during verfication.
  */
 typedef struct
@@ -693,7 +762,7 @@ struct _tagILCoderClass
        /*
         * Set up exception handling for the current method.
         */
-       void (*setupExceptions)(ILCoder *coder, ILException *exceptions,
+       void (*setupExceptions)(ILCoder *coder, ILCoderExceptions 
*coderExceptions,
                                                        int hasRethrow);
 
        /*
@@ -713,45 +782,34 @@ struct _tagILCoderClass
        /*
         * Re-throw the current exception for a particular exception region.
         */
-       void (*rethrow)(ILCoder *coder, ILException *exception);
+       void (*rethrow)(ILCoder *coder, ILCoderExceptionBlock *exception);
 
        /*
         * Jump to a "finally" or "fault" sub-routine.
         */
-       void (*jsr)(ILCoder *coder, ILUInt32 dest);
+       void (*callFinally)(ILCoder *coder, ILCoderExceptionBlock *exception,
+                                               ILUInt32 dest);
 
        /*
         * Return from a "finally" or "fault" sub-routine.
         */
-       void (*retFromJsr)(ILCoder *coder);
+       void (*retFromFinally)(ILCoder *coder);
 
        /*
-        * Start a "try" handler block for a region of code.
+        * Leave a catch region with a leave opcode.
         */
-       void (*tryHandlerStart)(ILCoder *coder, ILUInt32 start, ILUInt32 end);
+       void (*leaveCatch)(ILCoder *coder, ILCoderExceptionBlock *exception);
 
        /*
-        * End the current "try" handler block.
+        * Return from a filter subroutine.
         */
-       void (*tryHandlerEnd)(ILCoder *coder);
+       void (*retFromFilter)(ILCoder *coder);
 
        /*
-        * Output instructions to match a "catch" clause.
-        * If "hasRethrow" is non-zero, then the method contains
-        * "rethrow" instructions and the object must be saved in
-        * a local variable before jumping to the catch clause.
+        * Build the exception handling table or code for this method.
         */
-       void (*catchClause)(ILCoder *coder, ILException *exception,
-                                               ILClass *classInfo, int 
hasRethrow);
-       
-       /*
-        * End a catch or finally clause.  Finally clauses are usually always a
-        * potential exit point while catch clauses are a potential exit point
-        * if there are no finally clauses in the try/catch region.
-        */
-       void (*endCatchFinallyClause)(ILCoder *coder, ILException *exception);
-
-       void (*finallyClause)(ILCoder *coder, ILException *exception, int dest);
+       void (*outputExceptionTable)(ILCoder *coder,
+                                                                
ILCoderExceptions *coderExceptions);
 
        /*
         * Convert a program counter into an exception handler address.
@@ -1141,22 +1199,16 @@ struct _tagILCoderClass
                        ((*((coder)->classInfo->setStackTrace))((coder)))
 #define        ILCoderRethrow(coder,exception) \
                        ((*((coder)->classInfo->rethrow))((coder), (exception)))
-#define        ILCoderJsr(coder,dest) \
-                       ((*((coder)->classInfo->jsr))((coder), (dest)))
-#define        ILCoderRetFromJsr(coder) \
-                       ((*((coder)->classInfo->retFromJsr))((coder)))
-#define        ILCoderTryHandlerStart(coder,start,end) \
-                       ((*((coder)->classInfo->tryHandlerStart))((coder), 
(start), (end)))
-#define        ILCoderTryHandlerEnd(coder) \
-                       ((*((coder)->classInfo->tryHandlerEnd))((coder)))
-#define        ILCoderCatch(coder,exception,info,hasRethrow) \
-                       ((*((coder)->classInfo->catchClause))((coder), 
(exception), \
-                                                                               
                  (info), (hasRethrow)))
-#define ILCoderEndCatchFinally(coder, exception) \
-                       
((*((coder)->classInfo->endCatchFinallyClause))((coder), \
-                                                                               
                  (exception)))
-#define ILCoderFinally(coder, exception, dest) \
-                       ((*((coder)->classInfo->finallyClause))((coder), 
(exception), (dest)))
+#define        ILCoderCallFinally(coder,exception,dest) \
+                       ((*((coder)->classInfo->callFinally))((coder), 
(exception), (dest)))
+#define        ILCoderRetFromFinally(coder) \
+                       ((*((coder)->classInfo->retFromFinally))((coder)))
+#define ILCoderLeaveCatch(coder, exception) \
+                       ((*((coder)->classInfo->leaveCatch))((coder), 
(exception)))
+#define ILCoderRetFromFilter(coder) \
+                       ((*((coder)->classInfo->retFromFilter))((coder)))
+#define ILCoderOutputExceptionTable(coder, exceptions) \
+                       ((*((coder)->classInfo->outputExceptionTable))((coder), 
(exceptions)))
 #define        ILCoderPCToHandler(coder,pc,beyond) \
                        ((*((coder)->classInfo->pcToHandler))((coder), (pc), 
(beyond)))
 #define        ILCoderPCToMethod(coder,pc,beyond) \

-----------------------------------------------------------------------

Summary of changes:
 ChangeLog              |   53 +++
 engine/call.c          |    2 -
 engine/cvm.c           |  594 +++++++++++++++++++++++++---
 engine/cvm.h           |  119 ++++++-
 engine/cvm_arith.c     |    8 +-
 engine/cvm_call.c      |   17 +-
 engine/cvm_except.c    |  361 +++++-------------
 engine/cvm_lengths.c   |    6 +-
 engine/cvmc.c          |   12 +-
 engine/cvmc_except.c   |  332 ++++++++++------
 engine/jitc.c          |   79 ++---
 engine/jitc_branch.c   |   41 ++-
 engine/jitc_except.c   | 1025 ++++++++++++++++++++++++++++++++----------------
 engine/jitc_labels.c   |    1 +
 engine/null_coder.c    |   36 +-
 engine/verify.c        |  699 ++++++++++++++++++++++++++++-----
 engine/verify_except.c |  310 +++++----------
 include/il_coder.h     |  132 +++++--
 18 files changed, 2593 insertions(+), 1234 deletions(-)


hooks/post-receive
-- 
DotGNU Portable.NET engine, compilers and tools (pnet)



reply via email to

[Prev in Thread] Current Thread [Next in Thread]