[interp] Implement CEE_RETHROW properly by allocating a separate exception variable...
[mono.git] / mono / mini / interp / interp.c
index 0b530d8330a0b45321f15d8797b1931dc2507e63..556595081a57d99332cef860c693a0721903fe95 100644 (file)
@@ -284,6 +284,7 @@ mono_interp_get_runtime_method (MonoDomain *domain, MonoMethod *method, MonoErro
 
        rtm = mono_domain_alloc0 (domain, sizeof (RuntimeMethod));
        rtm->method = method;
+       rtm->domain = domain;
        rtm->param_count = sig->param_count;
        rtm->hasthis = sig->hasthis;
        rtm->rtype = mini_get_underlying_type (sig->ret);
@@ -332,17 +333,23 @@ interp_pop_lmf (MonoLMFExt *ext)
 }
 
 static inline RuntimeMethod*
-get_virtual_method (MonoDomain *domain, RuntimeMethod *runtime_method, MonoObject *obj)
+get_virtual_method (RuntimeMethod *runtime_method, MonoObject *obj)
 {
        MonoMethod *m = runtime_method->method;
+       MonoDomain *domain = runtime_method->domain;
+       RuntimeMethod *ret = NULL;
        MonoError error;
 
+#ifndef DISABLE_REMOTING
+       if (mono_object_is_transparent_proxy (obj)) {
+               ret = mono_interp_get_runtime_method (domain, mono_marshal_get_remoting_invoke (m), &error);
+               mono_error_assert_ok (&error);
+               return ret;
+       }
+#endif
+
        if ((m->flags & METHOD_ATTRIBUTE_FINAL) || !(m->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
-               RuntimeMethod *ret = NULL;
-               if (mono_object_is_transparent_proxy (obj)) {
-                       ret = mono_interp_get_runtime_method (domain, mono_marshal_get_remoting_invoke (m), &error);
-                       mono_error_cleanup (&error); /* FIXME: don't swallow the error */
-               } else if (m->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED) {
+               if (m->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED) {
                        ret = mono_interp_get_runtime_method (domain, mono_marshal_get_synchronized_wrapper (m), &error);
                        mono_error_cleanup (&error); /* FIXME: don't swallow the error */
                } else {
@@ -431,15 +438,19 @@ stackval_from_data (MonoType *type, stackval *result, char *data, gboolean pinvo
        case MONO_TYPE_U4:
                result->data.i = *(guint32*)data;
                return;
-       case MONO_TYPE_R4:
-               result->data.f = *(float*)data;
+       case MONO_TYPE_R4: {
+               float tmp;
+               /* memmove handles unaligned case */
+               memmove (&tmp, data, sizeof (float));
+               result->data.f = tmp;
                return;
+    }
        case MONO_TYPE_I8:
        case MONO_TYPE_U8:
-               result->data.l = *(gint64*)data;
+               memmove (&result->data.l, data, sizeof (gint64));
                return;
        case MONO_TYPE_R8:
-               result->data.f = *(double*)data;
+               memmove (&result->data.f, data, sizeof (double));
                return;
        case MONO_TYPE_STRING:
        case MONO_TYPE_SZARRAY:
@@ -576,7 +587,7 @@ fill_in_trace (MonoException *exception, MonoInvocation *frame)
 {
        MonoError error;
        char *stack_trace = dump_frame (frame);
-       MonoDomain *domain = mono_domain_get();
+       MonoDomain *domain = frame->runtime_method->domain;
        (exception)->stack_trace = mono_string_new_checked (domain, stack_trace, &error);
        mono_error_cleanup (&error); /* FIXME: don't swallow the error */
        (exception)->trace_ips = get_trace_ips (domain, frame);
@@ -585,14 +596,18 @@ fill_in_trace (MonoException *exception, MonoInvocation *frame)
 
 #define FILL_IN_TRACE(exception, frame) fill_in_trace(exception, frame)
 
-#define THROW_EX(exception,ex_ip)      \
+#define THROW_EX_GENERAL(exception,ex_ip,rethrow)              \
        do {\
                frame->ip = (ex_ip);            \
                frame->ex = (MonoException*)(exception);        \
-               FILL_IN_TRACE(frame->ex, frame); \
+               if (!rethrow) { \
+                       FILL_IN_TRACE(frame->ex, frame);        \
+               } \
                goto handle_exception;  \
        } while (0)
 
+#define THROW_EX(exception,ex_ip) THROW_EX_GENERAL ((exception), (ex_ip), FALSE)
+
 static MonoObject*
 ves_array_create (MonoInvocation *frame, MonoDomain *domain, MonoClass *klass, MonoMethodSignature *sig, stackval *values)
 {
@@ -981,10 +996,14 @@ ves_pinvoke_method (MonoInvocation *frame, MonoMethodSignature *sig, MonoFuncV a
 
        g_assert (!frame->runtime_method);
        if (!mono_interp_enter_icall_trampoline) {
-               MonoTrampInfo *info;
-               mono_interp_enter_icall_trampoline = mono_arch_get_enter_icall_trampoline (&info);
-               // TODO:
-               // mono_tramp_info_register (info, NULL);
+               if (mono_aot_only) {
+                       mono_interp_enter_icall_trampoline = mono_aot_get_trampoline ("enter_icall_trampoline");
+               } else {
+                       MonoTrampInfo *info;
+                       mono_interp_enter_icall_trampoline = mono_arch_get_enter_icall_trampoline (&info);
+                       // TODO:
+                       // mono_tramp_info_register (info, NULL);
+               }
        }
 
        InterpMethodArguments *margs = build_args_from_sig (sig, frame);
@@ -1003,8 +1022,6 @@ ves_pinvoke_method (MonoInvocation *frame, MonoMethodSignature *sig, MonoFuncV a
        interp_pop_lmf (&ext);
 
        context->managed_code = 1;
-       /* domain can only be changed by native code */
-       context->domain = mono_domain_get ();
 
        if (*mono_thread_interruption_request_flag ()) {
                MonoException *exc = mono_thread_interruption_checkpoint ();
@@ -1365,7 +1382,6 @@ mono_interp_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoOb
 
        if (setjmp(env)) {
                if (context != &context_struct) {
-                       context->domain = mono_domain_get ();
                        context->current_frame = old_frame;
                        context->managed_code = 0;
                } else
@@ -1386,7 +1402,7 @@ mono_interp_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoOb
        else
                old_frame = context->current_frame;
 
-       context->domain = mono_domain_get ();
+       MonoDomain *domain = mono_domain_get ();
 
        switch (sig->ret->type) {
        case MONO_TYPE_VOID:
@@ -1399,7 +1415,7 @@ mono_interp_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoOb
                isobject = 1;
                break;
        case MONO_TYPE_VALUETYPE:
-               retval = mono_object_new_checked (context->domain, klass, error);
+               retval = mono_object_new_checked (domain, klass, error);
                ret = mono_object_unbox (retval);
                if (!sig->ret->data.klass->enumtype)
                        result.data.vt = ret;
@@ -1408,7 +1424,7 @@ mono_interp_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoOb
                break;
        case MONO_TYPE_GENERICINST:
                if (!MONO_TYPE_IS_REFERENCE (sig->ret)) {
-                       retval = mono_object_new_checked (context->domain, klass, error);
+                       retval = mono_object_new_checked (domain, klass, error);
                        ret = mono_object_unbox (retval);
                        if (!sig->ret->data.klass->enumtype)
                                result.data.vt = ret;
@@ -1420,11 +1436,11 @@ mono_interp_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoOb
                break;
 
        case MONO_TYPE_PTR:
-               retval = mono_object_new_checked (context->domain, mono_defaults.int_class, error);
+               retval = mono_object_new_checked (domain, mono_defaults.int_class, error);
                ret = mono_object_unbox (retval);
                break;
        default:
-               retval = mono_object_new_checked (context->domain, klass, error);
+               retval = mono_object_new_checked (domain, klass, error);
                ret = mono_object_unbox (retval);
                break;
        }
@@ -1498,8 +1514,8 @@ handle_enum:
 
        if (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)
                method = mono_marshal_get_native_wrapper (method, FALSE, FALSE);
-       INIT_FRAME (&frame,context->current_frame,args,&result,mono_get_root_domain (),method,error);
 
+       INIT_FRAME (&frame,context->current_frame,args,&result,domain,method,error);
        if (exc)
                frame.invoke_trap = 1;
        context->managed_code = 1;
@@ -1570,7 +1586,6 @@ interp_entry (InterpEntryData *data)
        } else {
                old_frame = context->current_frame;
        }
-       context->domain = mono_domain_get ();
 
        args = alloca (sizeof (stackval) * (sig->param_count + (sig->hasthis ? 1 : 0)));
        if (sig->hasthis)
@@ -1821,6 +1836,240 @@ do_icall (ThreadContext *context, int op, stackval *sp, gpointer ptr)
        return sp;
 }
 
+static stackval *
+do_jit_call (stackval *sp, unsigned char *vt_sp, ThreadContext *context, MonoInvocation *frame, RuntimeMethod *rmethod)
+{
+       MonoMethodSignature *sig;
+       MonoFtnDesc ftndesc;
+       guint8 res_buf [256];
+       MonoType *type;
+       MonoLMFExt ext;
+
+       //printf ("%s\n", mono_method_full_name (rmethod->method, 1));
+
+       /*
+        * Call JITted code through a gsharedvt_out wrapper. These wrappers receive every argument
+        * by ref and return a return value using an explicit return value argument.
+        */
+       if (!rmethod->jit_wrapper) {
+               MonoMethod *method = rmethod->method;
+               MonoError error;
+
+               sig = mono_method_signature (method);
+               g_assert (sig);
+
+               MonoMethod *wrapper = mini_get_gsharedvt_out_sig_wrapper (sig);
+               //printf ("J: %s %s\n", mono_method_full_name (method, 1), mono_method_full_name (wrapper, 1));
+
+               gpointer jit_wrapper = mono_jit_compile_method_jit_only (wrapper, &error);
+               mono_error_assert_ok (&error);
+
+               gpointer addr = mono_jit_compile_method_jit_only (method, &error);
+               g_assert (addr);
+               mono_error_assert_ok (&error);
+
+               rmethod->jit_addr = addr;
+               rmethod->jit_sig = sig;
+               mono_memory_barrier ();
+               rmethod->jit_wrapper = jit_wrapper;
+
+       } else {
+               sig = rmethod->jit_sig;
+       }
+
+       sp -= sig->param_count;
+       if (sig->hasthis)
+               --sp;
+
+       ftndesc.addr = rmethod->jit_addr;
+       ftndesc.arg = NULL;
+
+       // FIXME: Optimize this
+
+       gpointer args [32];
+       int pindex = 0;
+       int stack_index = 0;
+       if (rmethod->hasthis) {
+               args [pindex ++] = sp [0].data.p;
+               stack_index ++;
+       }
+       type = rmethod->rtype;
+       if (type->type != MONO_TYPE_VOID) {
+               if (MONO_TYPE_ISSTRUCT (type))
+                       args [pindex ++] = vt_sp;
+               else
+                       args [pindex ++] = res_buf;
+       }
+       for (int i = 0; i < rmethod->param_count; ++i) {
+               MonoType *t = rmethod->param_types [i];
+               stackval *sval = &sp [stack_index + i];
+               if (sig->params [i]->byref) {
+                       args [pindex ++] = sval->data.p;
+               } else if (MONO_TYPE_ISSTRUCT (t)) {
+                       args [pindex ++] = sval->data.p;
+               } else if (MONO_TYPE_IS_REFERENCE (t)) {
+                       args [pindex ++] = &sval->data.p;
+               } else {
+                       switch (t->type) {
+                       case MONO_TYPE_I1:
+                       case MONO_TYPE_U1:
+                       case MONO_TYPE_I2:
+                       case MONO_TYPE_U2:
+                       case MONO_TYPE_I4:
+                       case MONO_TYPE_U4:
+                       case MONO_TYPE_VALUETYPE:
+                               args [pindex ++] = &sval->data.i;
+                               break;
+                       case MONO_TYPE_PTR:
+                       case MONO_TYPE_FNPTR:
+                       case MONO_TYPE_I:
+                       case MONO_TYPE_U:
+                       case MONO_TYPE_OBJECT:
+                               args [pindex ++] = &sval->data.p;
+                               break;
+                       case MONO_TYPE_I8:
+                       case MONO_TYPE_U8:
+                               args [pindex ++] = &sval->data.l;
+                               break;
+                       default:
+                               printf ("%s\n", mono_type_full_name (t));
+                               g_assert_not_reached ();
+                       }
+               }
+       }
+
+       interp_push_lmf (&ext, frame);
+
+       switch (pindex) {
+       case 0: {
+               void (*func)(gpointer) = rmethod->jit_wrapper;
+
+               func (&ftndesc);
+               break;
+       }
+       case 1: {
+               void (*func)(gpointer, gpointer) = rmethod->jit_wrapper;
+
+               func (args [0], &ftndesc);
+               break;
+       }
+       case 2: {
+               void (*func)(gpointer, gpointer, gpointer) = rmethod->jit_wrapper;
+
+               func (args [0], args [1], &ftndesc);
+               break;
+       }
+       case 3: {
+               void (*func)(gpointer, gpointer, gpointer, gpointer) = rmethod->jit_wrapper;
+
+               func (args [0], args [1], args [2], &ftndesc);
+               break;
+       }
+       case 4: {
+               void (*func)(gpointer, gpointer, gpointer, gpointer, gpointer) = rmethod->jit_wrapper;
+
+               func (args [0], args [1], args [2], args [3], &ftndesc);
+               break;
+       }
+       case 5: {
+               void (*func)(gpointer, gpointer, gpointer, gpointer, gpointer, gpointer) = rmethod->jit_wrapper;
+
+               func (args [0], args [1], args [2], args [3], args [4], &ftndesc);
+               break;
+       }
+       case 6: {
+               void (*func)(gpointer, gpointer, gpointer, gpointer, gpointer, gpointer, gpointer) = rmethod->jit_wrapper;
+
+               func (args [0], args [1], args [2], args [3], args [4], args [5], &ftndesc);
+               break;
+       }
+       case 7: {
+               void (*func)(gpointer, gpointer, gpointer, gpointer, gpointer, gpointer, gpointer, gpointer) = rmethod->jit_wrapper;
+
+               func (args [0], args [1], args [2], args [3], args [4], args [5], args [6], &ftndesc);
+               break;
+       }
+       default:
+               g_assert_not_reached ();
+               break;
+       }
+
+       interp_pop_lmf (&ext);
+
+       MonoType *rtype = rmethod->rtype;
+       switch (rtype->type) {
+       case MONO_TYPE_VOID:
+       case MONO_TYPE_OBJECT:
+       case MONO_TYPE_STRING:
+       case MONO_TYPE_CLASS:
+       case MONO_TYPE_ARRAY:
+       case MONO_TYPE_SZARRAY:
+       case MONO_TYPE_I:
+       case MONO_TYPE_U:
+               sp->data.p = *(gpointer*)res_buf;
+               break;
+       case MONO_TYPE_I1:
+               sp->data.i = *(gint8*)res_buf;
+               break;
+       case MONO_TYPE_U1:
+               sp->data.i = *(guint8*)res_buf;
+               break;
+       case MONO_TYPE_I2:
+               sp->data.i = *(gint16*)res_buf;
+               break;
+       case MONO_TYPE_U2:
+               sp->data.i = *(guint16*)res_buf;
+               break;
+       case MONO_TYPE_I4:
+               sp->data.i = *(gint32*)res_buf;
+               break;
+       case MONO_TYPE_U4:
+               sp->data.i = *(guint32*)res_buf;
+               break;
+       case MONO_TYPE_VALUETYPE:
+               /* The result was written to vt_sp */
+               sp->data.p = vt_sp;
+               break;
+       case MONO_TYPE_GENERICINST:
+               if (MONO_TYPE_IS_REFERENCE (rtype)) {
+                       sp->data.p = *(gpointer*)res_buf;
+               } else {
+                       /* The result was written to vt_sp */
+                       sp->data.p = vt_sp;
+               }
+               break;
+       default:
+               printf ("%s\n", mono_type_full_name (rtype));
+               g_assert_not_reached ();
+               break;
+       }
+
+       return sp;
+}
+
+static void
+do_debugger_tramp (void (*tramp) (void), MonoInvocation *frame)
+{
+       MonoLMFExt ext;
+       interp_push_lmf (&ext, frame);
+       tramp ();
+       interp_pop_lmf (&ext);
+}
+
+static void
+do_transform_method (MonoInvocation *frame, ThreadContext *context)
+{
+       MonoLMFExt ext;
+
+       /* Use the parent frame as the current frame is not complete yet */
+       interp_push_lmf (&ext, frame->parent);
+
+       frame->ex = mono_interp_transform_method (frame->runtime_method, context);
+       context->managed_code = 1;
+
+       interp_pop_lmf (&ext);
+}
+
 /*
  * These functions are the entry points into the interpreter from compiled code.
  * They are called by the interp_in wrappers. They have the following signature:
@@ -1988,13 +2237,12 @@ mono_interp_create_method_pointer (MonoMethod *method, MonoError *error)
        gpointer addr;
        MonoMethodSignature *sig = mono_method_signature (method);
        MonoMethod *wrapper;
-       RuntimeMethod *rmethod;
+       RuntimeMethod *rmethod = mono_interp_get_runtime_method (mono_domain_get (), method, error);
 
        /* HACK: method_ptr of delegate should point to a runtime method*/
        if (method->wrapper_type && method->wrapper_type == MONO_WRAPPER_DYNAMIC_METHOD)
-               return mono_interp_get_runtime_method (mono_domain_get (), method, error);
+               return rmethod;
 
-       rmethod = mono_interp_get_runtime_method (mono_domain_get (), method, error);
        if (rmethod->jit_entry)
                return rmethod->jit_entry;
        wrapper = mini_get_interp_in_wrapper (sig);
@@ -2030,9 +2278,10 @@ mono_interp_create_method_pointer (MonoMethod *method, MonoError *error)
         * rgctx register using a trampoline.
         */
 
-       // FIXME: AOT
-       g_assert (!mono_aot_only);
-       addr = mono_arch_get_static_rgctx_trampoline (ftndesc, jit_wrapper);
+       if (mono_aot_only)
+               addr = mono_aot_get_static_rgctx_trampoline (ftndesc, jit_wrapper);
+       else
+               addr = mono_arch_get_static_rgctx_trampoline (ftndesc, jit_wrapper);
 
        mono_memory_barrier ();
        rmethod->jit_entry = addr;
@@ -2136,16 +2385,7 @@ ves_exec_method_with_context (MonoInvocation *frame, ThreadContext *context, uns
                g_free (mn);
 #endif
 
-               MonoLMFExt ext;
-
-               /* Use the parent frame as the current frame is not complete yet */
-               interp_push_lmf (&ext, frame->parent);
-
-               frame->ex = mono_interp_transform_method (frame->runtime_method, context);
-               context->managed_code = 1;
-
-               interp_pop_lmf (&ext);
-
+               do_transform_method (frame, context);
                if (frame->ex) {
                        rtm = NULL;
                        ip = NULL;
@@ -2193,18 +2433,10 @@ ves_exec_method_with_context (MonoInvocation *frame, ThreadContext *context, uns
                MINT_IN_CASE(MINT_NOP)
                        ++ip;
                        MINT_IN_BREAK;
-               MINT_IN_CASE(MINT_BREAK) {
+               MINT_IN_CASE(MINT_BREAK)
                        ++ip;
-
-                       MonoLMFExt ext;
-
-                       interp_push_lmf (&ext, frame);
-
-                       mono_debugger_agent_user_break ();
-
-                       interp_pop_lmf (&ext);
+                       do_debugger_tramp (mono_debugger_agent_user_break, frame);
                        MINT_IN_BREAK;
-               }
                MINT_IN_CASE(MINT_LDNULL) 
                        sp->data.p = NULL;
                        ++ip;
@@ -2346,12 +2578,15 @@ ves_exec_method_with_context (MonoInvocation *frame, ThreadContext *context, uns
                                --sp;
                        child_frame.stack_args = sp;
 
+#ifndef DISABLE_REMOTING
                        /* `this' can be NULL for string:.ctor */
                        if (csignature->hasthis && sp->data.p && mono_object_is_transparent_proxy (sp->data.p)) {
-                               child_frame.runtime_method = mono_interp_get_runtime_method (context->domain, mono_marshal_get_remoting_invoke (child_frame.runtime_method->method), &error);
+                               child_frame.runtime_method = mono_interp_get_runtime_method (rtm->domain, mono_marshal_get_remoting_invoke (child_frame.runtime_method->method), &error);
                                mono_error_cleanup (&error); /* FIXME: don't swallow the error */
-                       } else if (child_frame.runtime_method->method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
-                               child_frame.runtime_method = mono_interp_get_runtime_method (context->domain, mono_marshal_get_native_wrapper (child_frame.runtime_method->method, FALSE, FALSE), &error);
+                       } else
+#endif
+                       if (child_frame.runtime_method->method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
+                               child_frame.runtime_method = mono_interp_get_runtime_method (rtm->domain, mono_marshal_get_native_wrapper (child_frame.runtime_method->method, FALSE, FALSE), &error);
                                mono_error_cleanup (&error); /* FIXME: don't swallow the error */
                        }
 
@@ -2456,11 +2691,13 @@ ves_exec_method_with_context (MonoInvocation *frame, ThreadContext *context, uns
                                --sp;
                        child_frame.stack_args = sp;
 
+#ifndef DISABLE_REMOTING
                        /* `this' can be NULL for string:.ctor */
                        if (child_frame.runtime_method->hasthis && !child_frame.runtime_method->method->klass->valuetype && sp->data.p && mono_object_is_transparent_proxy (sp->data.p)) {
-                               child_frame.runtime_method = mono_interp_get_runtime_method (context->domain, mono_marshal_get_remoting_invoke (child_frame.runtime_method->method), &error);
+                               child_frame.runtime_method = mono_interp_get_runtime_method (rtm->domain, mono_marshal_get_remoting_invoke (child_frame.runtime_method->method), &error);
                                mono_error_cleanup (&error); /* FIXME: don't swallow the error */
                        }
+#endif
 
                        ves_exec_method_with_context (&child_frame, context, NULL, NULL, -1);
 
@@ -2504,10 +2741,12 @@ ves_exec_method_with_context (MonoInvocation *frame, ThreadContext *context, uns
                        }
                        child_frame.stack_args = sp;
 
+#ifndef DISABLE_REMOTING
                        if (child_frame.runtime_method->hasthis && !child_frame.runtime_method->method->klass->valuetype && mono_object_is_transparent_proxy (sp->data.p)) {
-                               child_frame.runtime_method = mono_interp_get_runtime_method (context->domain, mono_marshal_get_remoting_invoke (child_frame.runtime_method->method), &error);
+                               child_frame.runtime_method = mono_interp_get_runtime_method (rtm->domain, mono_marshal_get_remoting_invoke (child_frame.runtime_method->method), &error);
                                mono_error_cleanup (&error); /* FIXME: don't swallow the error */
                        }
+#endif
 
                        ves_exec_method_with_context (&child_frame, context, NULL, NULL, -1);
 
@@ -2531,165 +2770,10 @@ ves_exec_method_with_context (MonoInvocation *frame, ThreadContext *context, uns
                }
 
                MINT_IN_CASE(MINT_JIT_CALL) {
-                       MonoMethodSignature *sig;
                        RuntimeMethod *rmethod = rtm->data_items [* (guint16 *)(ip + 1)];
-                       MonoFtnDesc ftndesc;
-                       guint8 res_buf [256];
-                       MonoType *type;
-                       MonoLMFExt ext;
-
-                       //printf ("%s\n", mono_method_full_name (rmethod->method, 1));
-
-                       /*
-                        * Call JITted code through a gsharedvt_out wrapper. These wrappers receive every argument
-                        * by ref and return a return value using an explicit return value argument.
-                        */
-                       if (!rmethod->jit_wrapper) {
-                               MonoMethod *method = rmethod->method;
-                               MonoError error;
-
-                               sig = mono_method_signature (method);
-                               g_assert (sig);
-
-                               MonoMethod *wrapper = mini_get_gsharedvt_out_sig_wrapper (sig);
-                               //printf ("J: %s %s\n", mono_method_full_name (method, 1), mono_method_full_name (wrapper, 1));
-
-                               gpointer jit_wrapper = mono_jit_compile_method_jit_only (wrapper, &error);
-                               mono_error_assert_ok (&error);
-
-                               gpointer addr = mono_jit_compile_method_jit_only (method, &error);
-                               g_assert (addr);
-                               mono_error_assert_ok (&error);
-
-                               rmethod->jit_addr = addr;
-                               rmethod->jit_sig = sig;
-                               mono_memory_barrier ();
-                               rmethod->jit_wrapper = jit_wrapper;
-
-                       } else {
-                               sig = rmethod->jit_sig;
-                       }
-
                        frame->ip = ip;
                        ip += 2;
-                       sp -= sig->param_count;
-                       if (sig->hasthis)
-                               --sp;
-
-                       ftndesc.addr = rmethod->jit_addr;
-                       ftndesc.arg = NULL;
-
-                       // FIXME: Optimize this
-
-                       gpointer args [32];
-                       int pindex = 0;
-                       int stack_index = 0;
-                       if (rmethod->hasthis) {
-                               args [pindex ++] = sp [0].data.p;
-                               stack_index ++;
-                       }
-                       type = rmethod->rtype;
-                       if (type->type != MONO_TYPE_VOID) {
-                               if (MONO_TYPE_ISSTRUCT (type))
-                                       args [pindex ++] = vt_sp;
-                               else
-                                       args [pindex ++] = res_buf;
-                       }
-                       for (int i = 0; i < rmethod->param_count; ++i) {
-                               MonoType *t = rmethod->param_types [i];
-                               stackval *sval = &sp [stack_index + i];
-                               if (sig->params [i]->byref) {
-                                       args [pindex ++] = sval->data.p;
-                               } else if (MONO_TYPE_ISSTRUCT (t)) {
-                                       args [pindex ++] = sval->data.p;
-                               } else if (MONO_TYPE_IS_REFERENCE (t)) {
-                                       args [pindex ++] = &sval->data.p;
-                               } else {
-                                       switch (t->type) {
-                                       case MONO_TYPE_I1:
-                                       case MONO_TYPE_U1:
-                                       case MONO_TYPE_I2:
-                                       case MONO_TYPE_U2:
-                                       case MONO_TYPE_I4:
-                                       case MONO_TYPE_U4:
-                                       case MONO_TYPE_VALUETYPE:
-                                               args [pindex ++] = &sval->data.i;
-                                               break;
-                                       case MONO_TYPE_PTR:
-                                       case MONO_TYPE_FNPTR:
-                                       case MONO_TYPE_I:
-                                       case MONO_TYPE_U:
-                                       case MONO_TYPE_OBJECT:
-                                               args [pindex ++] = &sval->data.p;
-                                               break;
-                                       case MONO_TYPE_I8:
-                                       case MONO_TYPE_U8:
-                                               args [pindex ++] = &sval->data.l;
-                                               break;
-                                       default:
-                                               printf ("%s\n", mono_type_full_name (t));
-                                               g_assert_not_reached ();
-                                       }
-                               }
-                       }
-
-                       interp_push_lmf (&ext, frame);
-
-                       switch (pindex) {
-                       case 0: {
-                               void (*func)(gpointer) = rmethod->jit_wrapper;
-
-                               func (&ftndesc);
-                               break;
-                       }
-                       case 1: {
-                               void (*func)(gpointer, gpointer) = rmethod->jit_wrapper;
-
-                               func (args [0], &ftndesc);
-                               break;
-                       }
-                       case 2: {
-                               void (*func)(gpointer, gpointer, gpointer) = rmethod->jit_wrapper;
-
-                               func (args [0], args [1], &ftndesc);
-                               break;
-                       }
-                       case 3: {
-                               void (*func)(gpointer, gpointer, gpointer, gpointer) = rmethod->jit_wrapper;
-
-                               func (args [0], args [1], args [2], &ftndesc);
-                               break;
-                       }
-                       case 4: {
-                               void (*func)(gpointer, gpointer, gpointer, gpointer, gpointer) = rmethod->jit_wrapper;
-
-                               func (args [0], args [1], args [2], args [3], &ftndesc);
-                               break;
-                       }
-                       case 5: {
-                               void (*func)(gpointer, gpointer, gpointer, gpointer, gpointer, gpointer) = rmethod->jit_wrapper;
-
-                               func (args [0], args [1], args [2], args [3], args [4], &ftndesc);
-                               break;
-                       }
-                       case 6: {
-                               void (*func)(gpointer, gpointer, gpointer, gpointer, gpointer, gpointer, gpointer) = rmethod->jit_wrapper;
-
-                               func (args [0], args [1], args [2], args [3], args [4], args [5], &ftndesc);
-                               break;
-                       }
-                       case 7: {
-                               void (*func)(gpointer, gpointer, gpointer, gpointer, gpointer, gpointer, gpointer, gpointer) = rmethod->jit_wrapper;
-
-                               func (args [0], args [1], args [2], args [3], args [4], args [5], args [6], &ftndesc);
-                               break;
-                       }
-                       default:
-                               g_assert_not_reached ();
-                               break;
-                       }
-
-                       interp_pop_lmf (&ext);
+                       sp = do_jit_call (sp, vt_sp, context, frame, rmethod);
 
                        if (context->has_resume_state) {
                                /*
@@ -2703,56 +2787,9 @@ ves_exec_method_with_context (MonoInvocation *frame, ThreadContext *context, uns
                                else
                                        goto exit_frame;
                        }
-
-                       MonoType *rtype = rmethod->rtype;
-                       switch (rtype->type) {
-                       case MONO_TYPE_VOID:
-                       case MONO_TYPE_OBJECT:
-                       case MONO_TYPE_STRING:
-                       case MONO_TYPE_CLASS:
-                       case MONO_TYPE_ARRAY:
-                       case MONO_TYPE_SZARRAY:
-                       case MONO_TYPE_I:
-                       case MONO_TYPE_U:
-                               sp->data.p = *(gpointer*)res_buf;
-                               break;
-                       case MONO_TYPE_I1:
-                               sp->data.i = *(gint8*)res_buf;
-                               break;
-                       case MONO_TYPE_U1:
-                               sp->data.i = *(guint8*)res_buf;
-                               break;
-                       case MONO_TYPE_I2:
-                               sp->data.i = *(gint16*)res_buf;
-                               break;
-                       case MONO_TYPE_U2:
-                               sp->data.i = *(guint16*)res_buf;
-                               break;
-                       case MONO_TYPE_I4:
-                               sp->data.i = *(gint32*)res_buf;
-                               break;
-                       case MONO_TYPE_U4:
-                               sp->data.i = *(guint32*)res_buf;
-                               break;
-                       case MONO_TYPE_VALUETYPE:
-                               /* The result was written to vt_sp */
-                               sp->data.p = vt_sp;
-                               break;
-                       case MONO_TYPE_GENERICINST:
-                               if (MONO_TYPE_IS_REFERENCE (rtype)) {
-                                       sp->data.p = *(gpointer*)res_buf;
-                               } else {
-                                       /* The result was written to vt_sp */
-                                       sp->data.p = vt_sp;
-                               }
-                               break;
-                       default:
-                               printf ("%s\n", mono_type_full_name (rtype));
-                               g_assert_not_reached ();
-                               break;
-                       }
-                       if (rtype->type != MONO_TYPE_VOID)
+                       if (rmethod->rtype->type != MONO_TYPE_VOID)
                                sp++;
+
                        MINT_IN_BREAK;
                }
 
@@ -2775,7 +2812,7 @@ ves_exec_method_with_context (MonoInvocation *frame, ThreadContext *context, uns
                        this_arg = sp->data.p;
                        if (!this_arg)
                                THROW_EX (mono_get_exception_null_reference(), ip - 2);
-                       child_frame.runtime_method = get_virtual_method (context->domain, child_frame.runtime_method, this_arg);
+                       child_frame.runtime_method = get_virtual_method (child_frame.runtime_method, this_arg);
 
                        MonoClass *this_class = this_arg->vtable->klass;
                        if (this_class->valuetype && child_frame.runtime_method->method->klass->valuetype) {
@@ -2830,7 +2867,7 @@ ves_exec_method_with_context (MonoInvocation *frame, ThreadContext *context, uns
                        this_arg = sp->data.p;
                        if (!this_arg)
                                THROW_EX (mono_get_exception_null_reference(), ip - 2);
-                       child_frame.runtime_method = get_virtual_method (context->domain, child_frame.runtime_method, this_arg);
+                       child_frame.runtime_method = get_virtual_method (child_frame.runtime_method, this_arg);
 
                        MonoClass *this_class = this_arg->vtable->klass;
                        if (this_class->valuetype && child_frame.runtime_method->method->klass->valuetype) {
@@ -3197,7 +3234,8 @@ ves_exec_method_with_context (MonoInvocation *frame, ThreadContext *context, uns
                        MINT_IN_BREAK;
                MINT_IN_CASE(MINT_LDIND_I8)
                        ++ip;
-                       sp[-1].data.l = *(gint64*)sp[-1].data.p;
+                       /* memmove handles unaligned case */
+                       memmove (&sp [-1].data.l, sp [-1].data.p, sizeof (gint64));
                        MINT_IN_BREAK;
                MINT_IN_CASE(MINT_LDIND_I) {
                        guint16 offset = * (guint16 *)(ip + 1);
@@ -3600,7 +3638,7 @@ ves_exec_method_with_context (MonoInvocation *frame, ThreadContext *context, uns
                        if (newobj_class->parent == mono_defaults.array_class) {
                                sp -= csig->param_count;
                                child_frame.stack_args = sp;
-                               o = ves_array_create (&child_frame, context->domain, newobj_class, csig, sp);
+                               o = ves_array_create (&child_frame, rtm->domain, newobj_class, csig, sp);
                                if (child_frame.ex)
                                        THROW_EX (child_frame.ex, ip);
                                goto array_constructed;
@@ -3628,7 +3666,7 @@ ves_exec_method_with_context (MonoInvocation *frame, ThreadContext *context, uns
                        } else {
                                if (newobj_class != mono_defaults.string_class) {
                                        context->managed_code = 0;
-                                       o = mono_object_new_checked (context->domain, newobj_class, &error);
+                                       o = mono_object_new_checked (rtm->domain, newobj_class, &error);
                                        mono_error_cleanup (&error); /* FIXME: don't swallow the error */
                                        context->managed_code = 1;
                                        if (*mono_thread_interruption_request_flag ())
@@ -3783,14 +3821,15 @@ array_constructed:
                                THROW_EX (mono_get_exception_null_reference (), ip);
                        field = rtm->data_items[* (guint16 *)(ip + 1)];
                        ip += 2;
+#ifndef DISABLE_REMOTING
                        if (mono_object_is_transparent_proxy (o)) {
                                MonoClass *klass = ((MonoTransparentProxy*)o)->remote_class->proxy_class;
 
                                addr = mono_load_remote_field_checked (o, klass, field, &tmp, &error);
                                mono_error_cleanup (&error); /* FIXME: don't swallow the error */
-                       } else {
+                       } else
+#endif
                                addr = (char*)o + field->offset;
-                       }                               
 
                        stackval_from_data (field->type, &sp [-1], addr, FALSE);
                        MINT_IN_BREAK;
@@ -3807,13 +3846,14 @@ array_constructed:
                        field = rtm->data_items[* (guint16 *)(ip + 1)];
                        i32 = READ32(ip + 2);
                        ip += 4;
+#ifndef DISABLE_REMOTING
                        if (mono_object_is_transparent_proxy (o)) {
                                MonoClass *klass = ((MonoTransparentProxy*)o)->remote_class->proxy_class;
                                addr = mono_load_remote_field_checked (o, klass, field, &tmp, &error);
                                mono_error_cleanup (&error); /* FIXME: don't swallow the error */
-                       } else {
+                       } else
+#endif
                                addr = (char*)o + field->offset;
-                       }                               
 
                        sp [-1].data.p = vt_sp;
                        memcpy(sp [-1].data.p, (char *)o + * (guint16 *)(ip + 1), i32);
@@ -3869,11 +3909,13 @@ array_constructed:
                        field = rtm->data_items[* (guint16 *)(ip + 1)];
                        ip += 2;
 
+#ifndef DISABLE_REMOTING
                        if (mono_object_is_transparent_proxy (o)) {
                                MonoClass *klass = ((MonoTransparentProxy*)o)->remote_class->proxy_class;
                                mono_store_remote_field_checked (o, klass, field, &sp [-1].data, &error);
                                mono_error_cleanup (&error); /* FIXME: don't swallow the error */
                        } else
+#endif
                                stackval_to_data (field->type, &sp [-1], (char*)o + field->offset, FALSE);
 
                        sp -= 2;
@@ -3889,11 +3931,13 @@ array_constructed:
                        i32 = READ32(ip + 2);
                        ip += 4;
 
+#ifndef DISABLE_REMOTING
                        if (mono_object_is_transparent_proxy (o)) {
                                MonoClass *klass = ((MonoTransparentProxy*)o)->remote_class->proxy_class;
                                mono_store_remote_field_checked (o, klass, field, &sp [-1].data, &error);
                                mono_error_cleanup (&error); /* FIXME: don't swallow the error */
                        } else
+#endif
                                memcpy((char*)o + field->offset, sp [-1].data.p, i32);
 
                        sp -= 2;
@@ -3902,14 +3946,14 @@ array_constructed:
                }
                MINT_IN_CASE(MINT_LDSFLDA) {
                        MonoClassField *field = rtm->data_items[*(guint16 *)(ip + 1)];
-                       sp->data.p = mono_class_static_field_address (context->domain, field);
+                       sp->data.p = mono_class_static_field_address (rtm->domain, field);
                        ip += 2;
                        ++sp;
                        MINT_IN_BREAK;
                }
                MINT_IN_CASE(MINT_LDSFLD) {
                        MonoClassField *field = rtm->data_items [* (guint16 *)(ip + 1)];
-                       gpointer addr = mono_class_static_field_address (context->domain, field);
+                       gpointer addr = mono_class_static_field_address (rtm->domain, field);
                        stackval_from_data (field->type, sp, addr, FALSE);
                        ip += 2;
                        ++sp;
@@ -3917,7 +3961,7 @@ array_constructed:
                }
                MINT_IN_CASE(MINT_LDSFLD_VT) {
                        MonoClassField *field = rtm->data_items [* (guint16 *)(ip + 1)];
-                       gpointer addr = mono_class_static_field_address (context->domain, field);
+                       gpointer addr = mono_class_static_field_address (rtm->domain, field);
                        int size = READ32 (ip + 2);
                        ip += 4;
 
@@ -3929,7 +3973,7 @@ array_constructed:
                }
                MINT_IN_CASE(MINT_STSFLD) {
                        MonoClassField *field = rtm->data_items [* (guint16 *)(ip + 1)];
-                       gpointer addr = mono_class_static_field_address (context->domain, field);
+                       gpointer addr = mono_class_static_field_address (rtm->domain, field);
                        ip += 2;
                        --sp;
                        stackval_to_data (field->type, sp, addr, FALSE);
@@ -3937,7 +3981,7 @@ array_constructed:
                }
                MINT_IN_CASE(MINT_STSFLD_VT) {
                        MonoClassField *field = rtm->data_items [* (guint16 *)(ip + 1)];
-                       gpointer addr = mono_class_static_field_address (context->domain, field);
+                       gpointer addr = mono_class_static_field_address (rtm->domain, field);
                        int size = READ32 (ip + 2);
                        ip += 4;
 
@@ -4015,20 +4059,20 @@ array_constructed:
 
                        if (c->byval_arg.type == MONO_TYPE_VALUETYPE && !c->enumtype) {
                                int size = mono_class_value_size (c, NULL);
-                               sp [-1 - offset].data.p = mono_value_box_checked (context->domain, c, sp [-1 - offset].data.p, &error);
+                               sp [-1 - offset].data.p = mono_value_box_checked (rtm->domain, c, sp [-1 - offset].data.p, &error);
                                mono_error_cleanup (&error); /* FIXME: don't swallow the error */
                                size = (size + 7) & ~7;
                                vt_sp -= size;
                        } else {
                                stackval_to_data (&c->byval_arg, &sp [-1 - offset], (char *) &sp [-1 - offset], FALSE);
-                               sp [-1 - offset].data.p = mono_value_box_checked (context->domain, c, &sp [-1 - offset], &error);
+                               sp [-1 - offset].data.p = mono_value_box_checked (rtm->domain, c, &sp [-1 - offset], &error);
                                mono_error_cleanup (&error); /* FIXME: don't swallow the error */
                        }
                        ip += 3;
                        MINT_IN_BREAK;
                }
                MINT_IN_CASE(MINT_NEWARR)
-                       sp [-1].data.p = (MonoObject*) mono_array_new_checked (context->domain, rtm->data_items[*(guint16 *)(ip + 1)], sp [-1].data.i, &error);
+                       sp [-1].data.p = (MonoObject*) mono_array_new_checked (rtm->domain, rtm->data_items[*(guint16 *)(ip + 1)], sp [-1].data.i, &error);
                        if (!mono_error_ok (&error)) {
                                THROW_EX (mono_error_convert_to_exception (&error), ip);
                        }
@@ -4534,7 +4578,7 @@ array_constructed:
                        ++sp;
                        MINT_IN_BREAK;
                MINT_IN_CASE(MINT_MONO_NEWOBJ)
-                       sp->data.p = mono_object_new_checked (context->domain, rtm->data_items [*(guint16 *)(ip + 1)], &error);
+                       sp->data.p = mono_object_new_checked (rtm->domain, rtm->data_items [*(guint16 *)(ip + 1)], &error);
                        mono_error_cleanup (&error); /* FIXME: don't swallow the error */
                        ip += 2;
                        sp++;
@@ -4567,8 +4611,8 @@ array_constructed:
                        MonoDomain *tls_domain = (MonoDomain *) ((gpointer (*)()) mono_tls_get_tls_getter (TLS_KEY_DOMAIN, FALSE)) ();
                        gpointer tls_jit = ((gpointer (*)()) mono_tls_get_tls_getter (TLS_KEY_DOMAIN, FALSE)) ();
 
-                       if (tls_domain != context->domain || !tls_jit)
-                               context->original_domain = mono_jit_thread_attach (context->domain);
+                       if (tls_domain != rtm->domain || !tls_jit)
+                               context->original_domain = mono_jit_thread_attach (rtm->domain);
                        MINT_IN_BREAK;
                }
                MINT_IN_CASE(MINT_MONO_JIT_DETACH)
@@ -4577,7 +4621,6 @@ array_constructed:
                        MINT_IN_BREAK;
                MINT_IN_CASE(MINT_SDB_INTR_LOC)
                        if (G_UNLIKELY (ss_enabled)) {
-                               MonoLMFExt ext;
                                static void (*ss_tramp) (void);
 
                                if (!ss_tramp) {
@@ -4592,14 +4635,12 @@ array_constructed:
                                 */
                                frame->ip = ip + 1;
 
-                               interp_push_lmf (&ext, frame);
                                /*
                                 * Use the same trampoline as the JIT. This ensures that
                                 * the debugger has the context for the last interpreter
                                 * native frame.
                                 */
-                               ss_tramp ();
-                               interp_pop_lmf (&ext);
+                               do_debugger_tramp (ss_tramp, frame);
 
                                if (context->has_resume_state) {
                                        if (frame == context->handler_frame)
@@ -4615,8 +4656,6 @@ array_constructed:
                        ++ip;
                        MINT_IN_BREAK;
                MINT_IN_CASE(MINT_SDB_BREAKPOINT) {
-                       MonoLMFExt ext;
-
                        static void (*bp_tramp) (void);
                        if (!bp_tramp) {
                                void *tramp = mini_get_breakpoint_trampoline ();
@@ -4626,10 +4665,8 @@ array_constructed:
 
                        frame->ip = ip;
 
-                       interp_push_lmf (&ext, frame);
                        /* Use the same trampoline as the JIT */
-                       bp_tramp ();
-                       interp_pop_lmf (&ext);
+                       do_debugger_tramp (bp_tramp, frame);
 
                        if (context->has_resume_state) {
                                if (frame == context->handler_frame)
@@ -4739,7 +4776,7 @@ array_constructed:
                        if (!sp->data.p)
                                THROW_EX (mono_get_exception_null_reference (), ip - 2);
                                
-                       sp->data.p = get_virtual_method (context->domain, m, sp->data.p);
+                       sp->data.p = get_virtual_method (m, sp->data.p);
                        ++sp;
                        MINT_IN_BREAK;
                }
@@ -4941,7 +4978,7 @@ array_constructed:
                        ip += 2;
                        MINT_IN_BREAK;
 #endif
-               MINT_IN_CASE(MINT_RETHROW)
+          MINT_IN_CASE(MINT_RETHROW) {
                        /* 
                         * need to clarify what this should actually do:
                         * start the search from the last found handler in
@@ -4952,9 +4989,11 @@ array_constructed:
                         * We need to NULL frame->ex_handler for the later code to
                         * actually run the new found handler.
                         */
+                       int exvar_offset = *(guint16*)(ip + 1);
                        frame->ex_handler = NULL;
-                       THROW_EX (frame->ex, ip - 1);
+                       THROW_EX_GENERAL (*(MonoException**)(frame->locals + exvar_offset), ip - 1, TRUE);
                        MINT_IN_BREAK;
+          }
                MINT_IN_DEFAULT
                        g_print ("Unimplemented opcode: %04x %s at 0x%x\n", *ip, mono_interp_opname[*ip], ip-rtm->code);
                        THROW_EX (mono_get_exception_execution_engine ("Unimplemented opcode"), ip);
@@ -5022,6 +5061,7 @@ array_constructed:
                                                        g_print ("* Matched Filter at '%s'\n", method->name);
 #endif
                                                inv->ex_handler = clause;
+                                               *(MonoException**)(inv->locals + inv->runtime_method->exvar_offsets [i]) = frame->ex;
                                                goto handle_finally;
                                        }
                                } else if (clause->flags == MONO_EXCEPTION_CLAUSE_NONE) {
@@ -5037,6 +5077,7 @@ array_constructed:
                                                        g_print ("* Found handler at '%s'\n", method->name);
 #endif
                                                inv->ex_handler = clause;
+                                               *(MonoException**)(inv->locals + inv->runtime_method->exvar_offsets [i]) = frame->ex;
                                                goto handle_finally;
                                        }
                                }
@@ -5168,6 +5209,7 @@ ves_exec_method (MonoInvocation *frame)
 {
        ThreadContext *context = mono_native_tls_get_value (thread_context_id);
        ThreadContext context_struct;
+       MonoDomain *domain = frame->runtime_method->domain;
        MonoError error;
        jmp_buf env;
 
@@ -5179,7 +5221,6 @@ ves_exec_method (MonoInvocation *frame)
        }
        if (context == NULL) {
                context = &context_struct;
-               context_struct.domain = mono_domain_get ();
                context_struct.base_frame = frame;
                context_struct.current_frame = NULL;
                context_struct.env_frame = frame;
@@ -5190,7 +5231,7 @@ ves_exec_method (MonoInvocation *frame)
        }
        frame->ip = NULL;
        frame->parent = context->current_frame;
-       frame->runtime_method = mono_interp_get_runtime_method (context->domain, frame->method, &error);
+       frame->runtime_method = mono_interp_get_runtime_method (domain, frame->method, &error);
        mono_error_cleanup (&error); /* FIXME: don't swallow the error */
        context->managed_code = 1;
        ves_exec_method_with_context (frame, context, NULL, NULL, -1);