[interpreter] clean up exported symbols and header organization
[mono.git] / mono / mini / interpreter / transform.c
index 8d35349d3c5933ca04dcdf8f3b5490bfacb1b44e..149b45278501a1c8431a2004038564f7dc895383 100644 (file)
 #include <mono/metadata/profiler-private.h>
 #include <mono/metadata/tabledefs.h>
 
-#define OPDEF(a,b,c,d,e,f,g,h,i,j) \
-       a = i,
-
-enum {
-#include "mono/cil/opcode.def"
-       CEE_LASTOP
-};
-#undef OPDEF
+#include <mono/mini/mini.h>
 
 #include "mintops.h"
+#include "interp-internals.h"
 #include "interp.h"
 
+// TODO: export from marshal.c
+MonoDelegate* mono_ftnptr_to_delegate (MonoClass *klass, gpointer ftn);
+
 #define DEBUG 0
 
 typedef struct
@@ -333,6 +330,9 @@ enum_type:
                        goto enum_type;
                } else
                        return MINT_TYPE_VT;
+       case MONO_TYPE_GENERICINST:
+               type = &type->data.generic_class->container_class->byval_arg;
+               goto enum_type;
        default:
                g_warning ("got type 0x%02x", type->type);
                g_assert_not_reached ();
@@ -436,30 +436,40 @@ load_arg(TransformData *td, int n)
 {
        int mt;
        MonoClass *klass = NULL;
-       if (n == 0 && mono_method_signature (td->method)->hasthis) {
-               if (td->method->klass->valuetype)
+       MonoType *type;
+
+       gboolean hasthis = mono_method_signature (td->method)->hasthis;
+       if (hasthis && n == 0)
+               type = &td->method->klass->byval_arg;
+       else
+               type = mono_method_signature (td->method)->params [hasthis ? n - 1 : n];
+
+       mt = mint_type (type);
+       if (mt == MINT_TYPE_VT) {
+               gint32 size;
+               klass = mono_class_from_mono_type (type);
+               if (mono_method_signature (td->method)->pinvoke)
+                       size = mono_class_native_size (klass, NULL);
+               else
+                       size = mono_class_value_size (klass, NULL);
+
+               if (hasthis && n == 0) {
                        mt = MINT_TYPE_P;
-               else {
-                       mt = MINT_TYPE_O;
-                       klass = td->method->klass;
+                       ADD_CODE (td, MINT_LDARG_P);
+                       ADD_CODE (td, td->rtm->arg_offsets [n]); /* FIX for large offset */
+                       klass = NULL;
+               } else {
+                       PUSH_VT (td, size);
+                       ADD_CODE (td, MINT_LDARG_VT);
+                       ADD_CODE (td, td->rtm->arg_offsets [n]); /* FIX for large offset */
+                       WRITE32 (td, &size);
                }
-               ADD_CODE(td, MINT_LDTHIS);
        } else {
-               MonoType *type;
-               n -= mono_method_signature (td->method)->hasthis;
-               type = mono_method_signature (td->method)->params [n];
-               mt = mint_type (type);
-               if (mt == MINT_TYPE_VT) {
-                       gint32 size;
-                       if (mono_method_signature (td->method)->pinvoke)
-                               size = mono_class_native_size (type->data.klass, NULL);
-                       else
-                               size = mono_class_value_size (type->data.klass, NULL);
-                       PUSH_VT(td, size);
-                       ADD_CODE(td, MINT_LDARG_VT);
-                       ADD_CODE(td, td->rtm->arg_offsets [n]); /* FIX for large offset */
-                       WRITE32(td, &size);             
-                       klass = type->data.klass;
+               if (hasthis && n == 0) {
+                       mt = MINT_TYPE_P;
+                       ADD_CODE (td, MINT_LDARG_P);
+                       ADD_CODE (td, td->rtm->arg_offsets [n]); /* FIX for large offset */
+                       klass = NULL;
                } else {
                        ADD_CODE(td, MINT_LDARG_I1 + (mt - MINT_TYPE_I1));
                        ADD_CODE(td, td->rtm->arg_offsets [n]); /* FIX for large offset */
@@ -475,28 +485,30 @@ store_arg(TransformData *td, int n)
 {
        int mt;
        CHECK_STACK (td, 1);
-       if (n == 0 && mono_method_signature (td->method)->hasthis)
-               ADD_CODE(td, MINT_STTHIS);
-       else {
-               MonoType *type;
-               n -= mono_method_signature (td->method)->hasthis;
-               type = mono_method_signature (td->method)->params [n];
-               mt = mint_type (type);
-               if (mt == MINT_TYPE_VT) {
-                       gint32 size;
-                       if (mono_method_signature (td->method)->pinvoke)
-                               size = mono_class_native_size (type->data.klass, NULL);
-                       else
-                               size = mono_class_value_size (type->data.klass, NULL);
-                       ADD_CODE(td, MINT_STARG_VT);
-                       ADD_CODE(td, n);
-                       WRITE32(td, &size);
-                       if (td->sp [-1].type == STACK_TYPE_VT)
-                               POP_VT(td, size);
-               } else {
-                       ADD_CODE(td, MINT_STARG_I1 + (mt - MINT_TYPE_I1));
-                       ADD_CODE(td, td->rtm->arg_offsets [n]);
-               }
+       MonoType *type;
+
+       gboolean hasthis = mono_method_signature (td->method)->hasthis;
+       if (hasthis && n == 0)
+               type = &td->method->klass->byval_arg;
+       else
+               type = mono_method_signature (td->method)->params [n - !!hasthis];
+
+       mt = mint_type (type);
+       if (mt == MINT_TYPE_VT) {
+               gint32 size;
+               g_error ("data.klass");
+               if (mono_method_signature (td->method)->pinvoke)
+                       size = mono_class_native_size (type->data.klass, NULL);
+               else
+                       size = mono_class_value_size (type->data.klass, NULL);
+               ADD_CODE(td, MINT_STARG_VT);
+               ADD_CODE(td, n);
+               WRITE32(td, &size);
+               if (td->sp [-1].type == STACK_TYPE_VT)
+                       POP_VT(td, size);
+       } else {
+               ADD_CODE(td, MINT_STARG_I1 + (mt - MINT_TYPE_I1));
+               ADD_CODE(td, td->rtm->arg_offsets [n]);
        }
        --td->sp;
 }
@@ -504,14 +516,26 @@ store_arg(TransformData *td, int n)
 static void 
 store_inarg(TransformData *td, int n)
 {
-       MonoType *type = mono_method_signature (td->method)->params [n];
+       MonoType *type;
+       gboolean hasthis = mono_method_signature (td->method)->hasthis;
+       if (hasthis && n == 0)
+               type = &td->method->klass->byval_arg;
+       else
+               type = mono_method_signature (td->method)->params [n - !!hasthis];
+
        int mt = mint_type (type);
+       if (hasthis && n == 0) {
+               ADD_CODE (td, MINT_STINARG_P);
+               ADD_CODE (td, n);
+               return;
+       }
        if (mt == MINT_TYPE_VT) {
+               MonoClass *klass = mono_class_from_mono_type (type);
                gint32 size;
                if (mono_method_signature (td->method)->pinvoke)
-                       size = mono_class_native_size (type->data.klass, NULL);
+                       size = mono_class_native_size (klass, NULL);
                else
-                       size = mono_class_value_size (type->data.klass, NULL);
+                       size = mono_class_value_size (klass, NULL);
                ADD_CODE(td, MINT_STINARG_VT);
                ADD_CODE(td, n);
                WRITE32(td, &size);
@@ -529,13 +553,14 @@ load_local(TransformData *td, int n)
        int offset = td->rtm->local_offsets [n];
        MonoClass *klass = NULL;
        if (mt == MINT_TYPE_VT) {
-               gint32 size = mono_class_value_size (type->data.klass, NULL);
+               klass = mono_class_from_mono_type (type);
+               gint32 size = mono_class_value_size (klass, NULL);
                PUSH_VT(td, size);
                ADD_CODE(td, MINT_LDLOC_VT);
                ADD_CODE(td, offset); /*FIX for large offset */
                WRITE32(td, &size);
-               klass = type->data.klass;
        } else {
+               g_assert (mt < MINT_TYPE_VT);
                if (mt == MINT_TYPE_I4 && !td->is_bb_start [td->in_start - td->il_code] && td->last_new_ip != NULL &&
                        td->last_new_ip [0] == MINT_STLOC_I4 && td->last_new_ip [1] == offset) {
                        td->last_new_ip [0] = MINT_STLOC_NP_I4;
@@ -571,13 +596,15 @@ store_local(TransformData *td, int n)
                        stack_type [mt], td->sp [-1].type);
        }
        if (mt == MINT_TYPE_VT) {
-               gint32 size = mono_class_value_size (type->data.klass, NULL);
+               MonoClass *klass = mono_class_from_mono_type (type);
+               gint32 size = mono_class_value_size (klass, NULL);
                ADD_CODE(td, MINT_STLOC_VT);
                ADD_CODE(td, offset); /*FIX for large offset */
                WRITE32(td, &size);
                if (td->sp [-1].type == STACK_TYPE_VT)
                        POP_VT(td, size);
        } else {
+               g_assert (mt < MINT_TYPE_VT);
                ADD_CODE(td, MINT_STLOC_I1 + (mt - MINT_TYPE_I1));
                ADD_CODE(td, offset); /*FIX for large offset */
        }
@@ -608,6 +635,207 @@ get_data_item_index (TransformData *td, void *ptr)
        return index;
 }
 
+static void
+interp_transform_call (TransformData *td, MonoMethod *method, MonoMethod *target_method, MonoDomain *domain, MonoGenericContext *generic_context, unsigned char *is_bb_start, int body_start_offset, MonoClass *constrained_class)
+{
+       MonoImage *image = method->klass->image;
+       MonoMethodSignature *csignature;
+       MonoError error;
+       int virtual = *td->ip == CEE_CALLVIRT;
+       int calli = *td->ip == CEE_CALLI || *td->ip == CEE_MONO_CALLI_EXTRA_ARG;
+       int i;
+       guint32 vt_stack_used = 0;
+       guint32 vt_res_size = 0;
+       int op = -1;
+       int native = 0;
+       int is_void = 0;
+
+       guint32 token = read32 (td->ip + 1);
+
+       if (target_method == NULL) {
+               if (calli) {
+                       CHECK_STACK(td, 1);
+                       native = (method->wrapper_type != MONO_WRAPPER_DELEGATE_INVOKE && td->sp [-1].type == STACK_TYPE_I);
+                       --td->sp;
+                       if (method->wrapper_type != MONO_WRAPPER_NONE)
+                               csignature = (MonoMethodSignature *)mono_method_get_wrapper_data (method, token);
+                       else
+                               csignature = mono_metadata_parse_signature (image, token);
+                       target_method = NULL;
+               } else {
+                       if (method->wrapper_type == MONO_WRAPPER_NONE)
+                               target_method = mono_get_method_full (image, token, NULL, generic_context);
+                       else
+                               target_method = (MonoMethod *)mono_method_get_wrapper_data (method, token);
+                       csignature = mono_method_signature (target_method);
+                       if (target_method->klass == mono_defaults.string_class) {
+                               if (target_method->name [0] == 'g') {
+                                       if (strcmp (target_method->name, "get_Chars") == 0)
+                                               op = MINT_GETCHR;
+                                       else if (strcmp (target_method->name, "get_Length") == 0)
+                                               op = MINT_STRLEN;
+                               }
+                       } else if (target_method->klass == mono_defaults.array_class) {
+                               if (strcmp (target_method->name, "get_Rank") == 0)
+                                       op = MINT_ARRAY_RANK;
+                               else if (strcmp (target_method->name, "get_Length") == 0)
+                                       op = MINT_LDLEN;
+                       }
+               }
+       } else {
+               csignature = mono_method_signature (target_method);
+       }
+
+       if (constrained_class) {
+               if (constrained_class->enumtype && !strcmp (target_method->name, "GetHashCode")) {
+                       /* Use the corresponding method from the base type to avoid boxing */
+                       MonoType *base_type = mono_class_enum_basetype (constrained_class);
+                       g_assert (base_type);
+                       constrained_class = mono_class_from_mono_type (base_type);
+                       target_method = mono_class_get_method_from_name (constrained_class, target_method->name, 0);
+                       g_assert (target_method);
+               }
+       }
+
+       if (constrained_class) {
+               mono_class_setup_vtable (constrained_class);
+#if DEBUG_INTERP
+               g_print ("CONSTRAINED.CALLVIRT: %s::%s.  %s (%p) ->\n", target_method->klass->name, target_method->name, mono_signature_full_name (target_method->signature), target_method);
+#endif
+               target_method = mono_get_method_constrained_with_method (image, target_method, constrained_class, generic_context, &error);
+#if DEBUG_INTERP
+               g_print ("                    : %s::%s.  %s (%p)\n", target_method->klass->name, target_method->name, mono_signature_full_name (target_method->signature), target_method);
+#endif
+               mono_error_cleanup (&error); /* FIXME: don't swallow the error */
+               mono_class_setup_vtable (target_method->klass);
+
+               if (constrained_class->valuetype && (target_method->klass == mono_defaults.object_class || target_method->klass == mono_defaults.enum_class->parent || target_method->klass == mono_defaults.enum_class)) {
+                       ADD_CODE (td, MINT_BOX);
+                       ADD_CODE (td, get_data_item_index (td, constrained_class));
+                       ADD_CODE (td, csignature->param_count);
+               } else if (!constrained_class->valuetype) {
+                       /* managed pointer on the stack, we need to deref that puppy */
+                       ADD_CODE (td, MINT_LDIND_I);
+                       ADD_CODE (td, csignature->param_count);
+               } else {
+                       g_assert (target_method->klass->valuetype);
+                       virtual = FALSE;
+               }
+       }
+
+       if (target_method)
+               mono_class_init (target_method->klass);
+
+       CHECK_STACK (td, csignature->param_count + csignature->hasthis);
+       if (!calli && (!virtual || (target_method->flags & METHOD_ATTRIBUTE_VIRTUAL) == 0) &&
+               (target_method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) == 0 && 
+               (target_method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) == 0) {
+               int called_inited = mono_class_vtable (domain, target_method->klass)->initialized;
+               MonoMethodHeader *mheader = mono_method_get_header (target_method);
+
+               if (/*mono_metadata_signature_equal (method->signature, target_method->signature) */ method == target_method && *(td->ip + 5) == CEE_RET) {
+                       int offset;
+                       if (mono_interp_traceopt)
+                               g_print ("Optimize tail call of %s.%s\n", target_method->klass->name, target_method->name);
+                       for (i = csignature->param_count - 1; i >= 0; --i)
+                               store_arg (td, i + csignature->hasthis);
+
+                       if (csignature->hasthis) {
+                               g_error ("STTHIS removal");
+                               // ADD_CODE(td, MINT_STTHIS);
+                               --td->sp;
+                       }
+                       ADD_CODE(td, MINT_BR_S);
+                       offset = body_start_offset - ((td->new_ip - 1) - td->new_code);
+                       ADD_CODE(td, offset);
+                       if (!is_bb_start [td->ip + 5 - td->il_code])
+                               ++td->ip; /* gobble the CEE_RET if it isn't branched to */                              
+                       td->ip += 5;
+                       return;
+               } else {
+                       /* mheader might not exist if this is a delegate invoc, etc */
+                       if (mheader && *mheader->code == CEE_RET && called_inited) {
+                               if (mono_interp_traceopt)
+                                       g_print ("Inline (empty) call of %s.%s\n", target_method->klass->name, target_method->name);
+                               for (i = 0; i < csignature->param_count; i++)
+                                       ADD_CODE(td, MINT_POP); /*FIX: vt */
+                               if (csignature->hasthis) {
+                                       if (virtual)
+                                               ADD_CODE(td, MINT_CKNULL);
+                                       ADD_CODE(td, MINT_POP);
+                               }
+                               td->sp -= csignature->param_count + csignature->hasthis;
+                               td->ip += 5;
+                               return;
+                       }
+               }
+       }
+       if (method->wrapper_type == MONO_WRAPPER_NONE && target_method != NULL) {
+               if (target_method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)
+                       target_method = mono_marshal_get_native_wrapper (target_method, FALSE, FALSE);
+               if (!virtual && target_method->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED)
+                       target_method = mono_marshal_get_synchronized_wrapper (target_method);
+       }
+       g_assert (csignature->call_convention == MONO_CALL_DEFAULT || csignature->call_convention == MONO_CALL_C);
+       td->sp -= csignature->param_count + !!csignature->hasthis;
+       for (i = 0; i < csignature->param_count; ++i) {
+               if (td->sp [i + !!csignature->hasthis].type == STACK_TYPE_VT) {
+                       gint32 size;
+                       MonoClass *klass = mono_class_from_mono_type (csignature->params [i]);
+                       if (csignature->pinvoke && method->wrapper_type != MONO_WRAPPER_NONE)
+                               size = mono_class_native_size (klass, NULL);
+                       else
+                               size = mono_class_value_size (klass, NULL);
+                       size = (size + 7) & ~7;
+                       vt_stack_used += size;
+               }
+       }
+
+       /* need to handle typedbyref ... */
+       if (csignature->ret->type != MONO_TYPE_VOID) {
+               int mt = mint_type(csignature->ret);
+               MonoClass *klass = mono_class_from_mono_type (csignature->ret);
+               if (mt == MINT_TYPE_VT) {
+                       if (csignature->pinvoke && method->wrapper_type != MONO_WRAPPER_NONE)
+                               vt_res_size = mono_class_native_size (klass, NULL);
+                       else
+                               vt_res_size = mono_class_value_size (klass, NULL);
+                       PUSH_VT(td, vt_res_size);
+               }
+               PUSH_TYPE(td, stack_type[mt], klass);
+       } else
+               is_void = TRUE;
+
+       if (op >= 0) {
+               ADD_CODE(td, op);
+#if SIZEOF_VOID_P == 8
+               if (op == MINT_LDLEN)
+                       ADD_CODE(td, MINT_CONV_I4_I8);
+#endif
+       } else {
+               if (calli)
+                       ADD_CODE(td, native ? MINT_CALLI_NAT : MINT_CALLI);
+               else if (virtual)
+                       ADD_CODE(td, is_void ? MINT_VCALLVIRT : MINT_CALLVIRT);
+               else
+                       ADD_CODE(td, is_void ? MINT_VCALL : MINT_CALL);
+               
+               if (calli) {
+                       ADD_CODE(td, get_data_item_index (td, (void *)csignature));
+               } else {
+                       ADD_CODE(td, get_data_item_index (td, (void *)mono_interp_get_runtime_method (domain, target_method, &error)));
+                       mono_error_cleanup (&error); /* FIXME: don't swallow the error */
+               }
+       }
+       td->ip += 5;
+       if (vt_stack_used != 0 || vt_res_size != 0) {
+               ADD_CODE(td, MINT_VTRESULT);
+               ADD_CODE(td, vt_res_size);
+               WRITE32(td, &vt_stack_used);
+               td->vt_sp -= vt_stack_used;
+       }
+}
+
 static void
 generate (MonoMethod *method, RuntimeMethod *rtm, unsigned char *is_bb_start)
 {
@@ -616,6 +844,7 @@ generate (MonoMethod *method, RuntimeMethod *rtm, unsigned char *is_bb_start)
        MonoImage *image = method->klass->image;
        MonoDomain *domain = mono_domain_get ();
        MonoGenericContext *generic_context = NULL;
+       MonoClass *constrained_class = NULL;
        MonoError error;
        int offset, mt;
        int i;
@@ -689,8 +918,10 @@ generate (MonoMethod *method, RuntimeMethod *rtm, unsigned char *is_bb_start)
                g_free (name);
        }
 
+       if (signature->hasthis)
+               store_inarg (&td, 0);
        for (i = 0; i < signature->param_count; i++)
-               store_inarg(&td, i);
+               store_inarg (&td, i + !!signature->hasthis);
 
        body_start_offset = td.new_ip - td.new_code;
 
@@ -799,12 +1030,15 @@ generate (MonoMethod *method, RuntimeMethod *rtm, unsigned char *is_bb_start)
                        td.ip += 2;
                        break;
                case CEE_LDARGA_S: {
+                       /* NOTE: n includes this */
                        int n = ((guint8 *)td.ip)[1];
-                       if (n == 0 && signature->hasthis) 
+                       if (n == 0 && signature->hasthis) {
+                               g_error ("LDTHISA: NOPE");
                                ADD_CODE(&td, MINT_LDTHISA);
+                       }
                        else {
                                ADD_CODE(&td, MINT_LDARGA);
-                               ADD_CODE(&td, td.rtm->arg_offsets [n - signature->hasthis]);
+                               ADD_CODE(&td, td.rtm->arg_offsets [n]);
                        }
                        PUSH_SIMPLE_TYPE(&td, STACK_TYPE_MP);
                        td.ip += 2;
@@ -947,165 +1181,24 @@ generate (MonoMethod *method, RuntimeMethod *rtm, unsigned char *is_bb_start)
                case CEE_CALLVIRT: /* Fall through */
                case CEE_CALLI:    /* Fall through */
                case CEE_CALL: {
-                       MonoMethod *m;
-                       MonoMethodSignature *csignature;
-                       int virtual = *td.ip == CEE_CALLVIRT;
-                       int calli = *td.ip == CEE_CALLI;
-                       int i;
-                       guint32 vt_stack_used = 0;
-                       guint32 vt_res_size = 0;
-                       int op = -1;
-                       int native = 0;
-                       int is_void = 0;
-
-                       token = read32 (td.ip + 1);
-                       if (calli) {
-                               CHECK_STACK(&td, 1);
-                               native = (method->wrapper_type != MONO_WRAPPER_DELEGATE_INVOKE && td.sp [-1].type == STACK_TYPE_I);
-                               --td.sp;
-                               if (method->wrapper_type != MONO_WRAPPER_NONE)
-                                       csignature = (MonoMethodSignature *)mono_method_get_wrapper_data (method, token);
-                               else
-                                       csignature = mono_metadata_parse_signature (image, token);
-                               m = NULL;
-                       } else {
-                               if (method->wrapper_type == MONO_WRAPPER_NONE)
-                                       m = mono_get_method_full (image, token, NULL, generic_context);
-                               else
-                                       m = (MonoMethod *)mono_method_get_wrapper_data (method, token);
-                               csignature = mono_method_signature (m);
-                               if (m->klass == mono_defaults.string_class) {
-                                       if (m->name [0] == 'g') {
-                                               if (strcmp (m->name, "get_Chars") == 0)
-                                                       op = MINT_GETCHR;
-                                               else if (strcmp (m->name, "get_Length") == 0)
-                                                       op = MINT_STRLEN;
-                                       }
-                               } else if (m->klass == mono_defaults.array_class) {
-                                       if (strcmp (m->name, "get_Rank") == 0)
-                                               op = MINT_ARRAY_RANK;
-                                       else if (strcmp (m->name, "get_Length") == 0)
-                                               op = MINT_LDLEN;
-                               }
-                       }
-                       CHECK_STACK(&td, csignature->param_count + csignature->hasthis);
-                       if (!calli && (!virtual || (m->flags & METHOD_ATTRIBUTE_VIRTUAL) == 0) &&
-                               (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) == 0 && 
-                               (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) == 0) {
-                               int called_inited = mono_class_vtable (domain, m->klass)->initialized;
-                               MonoMethodHeader *mheader = mono_method_get_header (m);
-
-                               if (/*mono_metadata_signature_equal (method->signature, m->signature) */ method == m && *(td.ip + 5) == CEE_RET) {
-                                       int offset;
-                                       if (mono_interp_traceopt)
-                                               g_print ("Optimize tail call of %s.%s\n", m->klass->name, m->name);
-                                       for (i = csignature->param_count - 1; i >= 0; --i)
-                                               store_arg (&td, i + csignature->hasthis);
-
-                                       if (csignature->hasthis) {
-                                               ADD_CODE(&td, MINT_STTHIS);
-                                               --td.sp;
-                                       }
-                                       ADD_CODE(&td, MINT_BR_S);
-                                       offset = body_start_offset - ((td.new_ip - 1) - td.new_code);
-                                       ADD_CODE(&td, offset);
-                                       if (!is_bb_start [td.ip + 5 - td.il_code])
-                                               ++td.ip; /* gobble the CEE_RET if it isn't branched to */                               
-                                       td.ip += 5;
-                                       break;
-                               } else {
-                                       /* mheader might not exist if this is a delegate invoc, etc */
-                                       if (mheader && *mheader->code == CEE_RET && called_inited) {
-                                               if (mono_interp_traceopt)
-                                                       g_print ("Inline (empty) call of %s.%s\n", m->klass->name, m->name);
-                                               for (i = 0; i < csignature->param_count; i++)
-                                                       ADD_CODE(&td, MINT_POP); /*FIX: vt */
-                                               if (csignature->hasthis) {
-                                                       if (virtual)
-                                                               ADD_CODE(&td, MINT_CKNULL);
-                                                       ADD_CODE(&td, MINT_POP);
-                                               }
-                                               td.sp -= csignature->param_count + csignature->hasthis;
-                                               td.ip += 5;
-                                               break;
-                                       }
-                               }
-                       }
-                       if (method->wrapper_type == MONO_WRAPPER_NONE && m != NULL) {
-                               if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)
-                                       m = mono_marshal_get_native_wrapper (m, FALSE, FALSE);
-                               if (!virtual && m->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED)
-                                       m = mono_marshal_get_synchronized_wrapper (m);
-                       }
-                       g_assert (csignature->call_convention == MONO_CALL_DEFAULT || csignature->call_convention == MONO_CALL_C);
-                       td.sp -= csignature->param_count + csignature->hasthis;
-                       for (i = 0; i < csignature->param_count; ++i) {
-                               if (td.sp [i + csignature->hasthis].type == STACK_TYPE_VT) {
-                                       gint32 size;
-                                       if (csignature->pinvoke && method->wrapper_type != MONO_WRAPPER_NONE)
-                                               size = mono_class_native_size (csignature->params [i]->data.klass, NULL);
-                                       else
-                                               size = mono_class_value_size (csignature->params [i]->data.klass, NULL);
-                                       size = (size + 7) & ~7;
-                                       vt_stack_used += size;
-                               }
-                       }
-
-                       /* need to handle typedbyref ... */
-                       if (csignature->ret->type != MONO_TYPE_VOID) {
-                               int mt = mint_type(csignature->ret);
-                               MonoClass *klass = NULL;
-                               if (mt == MINT_TYPE_VT) {
-                                       if (csignature->pinvoke && method->wrapper_type != MONO_WRAPPER_NONE)
-                                               vt_res_size = mono_class_native_size (csignature->ret->data.klass, NULL);
-                                       else
-                                               vt_res_size = mono_class_value_size (csignature->ret->data.klass, NULL);
-                                       PUSH_VT(&td, vt_res_size);
-                                       klass = csignature->ret->data.klass;
-                               } else if (mt == MINT_TYPE_O)
-                                       klass = mono_class_from_mono_type (csignature->ret);
-                               PUSH_TYPE(&td, stack_type[mt], klass);
-                       } else
-                               is_void = TRUE;
-
-                       if (op >= 0) {
-                               ADD_CODE(&td, op);
-#if SIZEOF_VOID_P == 8
-                               if (op == MINT_LDLEN)
-                                       ADD_CODE(&td, MINT_CONV_I4_I8);
-#endif
-                       } else {
-                               if (calli)
-                                       ADD_CODE(&td, native ? MINT_CALLI_NAT : MINT_CALLI);
-                               else if (virtual)
-                                       ADD_CODE(&td, is_void ? MINT_VCALLVIRT : MINT_CALLVIRT);
-                               else
-                                       ADD_CODE(&td, is_void ? MINT_VCALL : MINT_CALL);
-                               ADD_CODE(&td, get_data_item_index (&td,  calli? (void *)csignature : (void *)mono_interp_get_runtime_method (domain, m, &error)));
-                               mono_error_cleanup (&error); /* FIXME: don't swallow the error */
-                       }
-                       td.ip += 5;
-                       if (vt_stack_used != 0 || vt_res_size != 0) {
-                               ADD_CODE(&td, MINT_VTRESULT);
-                               ADD_CODE(&td, vt_res_size);
-                               WRITE32(&td, &vt_stack_used);
-                               td.vt_sp -= vt_stack_used;
-                       }
+                       interp_transform_call (&td, method, NULL, domain, generic_context, is_bb_start, body_start_offset, constrained_class);
+                       constrained_class = NULL;
                        break;
                }
                case CEE_RET: {
                        int vt_size = 0;
                        if (signature->ret->type != MONO_TYPE_VOID) {
                                --td.sp;
-                               if (mint_type(signature->ret) == MINT_TYPE_VT) {
-                                       vt_size = mono_class_value_size (signature->ret->data.klass, NULL);
+                               MonoClass *klass = mono_class_from_mono_type (signature->ret);
+                               if (mint_type (&klass->byval_arg) == MINT_TYPE_VT) {
+                                       vt_size = mono_class_value_size (klass, NULL);
                                        vt_size = (vt_size + 7) & ~7;
                                }
                        }
                        if (td.sp > td.stack)
                                g_warning ("%s.%s: CEE_RET: more values on stack: %d", td.method->klass->name, td.method->name, td.sp - td.stack);
                        if (td.vt_sp != vt_size)
-                               g_warning ("%s.%s: CEE_RET: value type stack: %d", td.method->klass->name, td.method->name, td.vt_sp);
+                               g_error ("%s.%s: CEE_RET: value type stack: %d vs. %d", td.method->klass->name, td.method->name, td.vt_sp, vt_size);
                        if (vt_size == 0)
                                SIMPLE_OP(td, signature->ret->type == MONO_TYPE_VOID ? MINT_RET_VOID : MINT_RET);
                        else {
@@ -1291,6 +1384,7 @@ generate (MonoMethod *method, RuntimeMethod *rtm, unsigned char *is_bb_start)
                case CEE_LDIND_I:
                        CHECK_STACK (&td, 1);
                        SIMPLE_OP (td, MINT_LDIND_I);
+                       ADD_CODE (&td, 0);
                        SET_SIMPLE_TYPE(td.sp - 1, STACK_TYPE_I);
                        break;
                case CEE_LDIND_R4:
@@ -1500,6 +1594,8 @@ generate (MonoMethod *method, RuntimeMethod *rtm, unsigned char *is_bb_start)
                                ADD_CODE(&td, MINT_CONV_U4_I8);
 #endif
                                break;
+                       case STACK_TYPE_MP:
+                               break;
                        default:
                                g_assert_not_reached ();
                        }
@@ -1683,7 +1779,7 @@ generate (MonoMethod *method, RuntimeMethod *rtm, unsigned char *is_bb_start)
 
                        ADD_CODE(&td, MINT_LDOBJ);
                        ADD_CODE(&td, get_data_item_index(&td, klass));
-                       if (klass->byval_arg.type == MONO_TYPE_VALUETYPE && !klass->byval_arg.data.klass->enumtype) {
+                       if (mint_type (&klass->byval_arg) == MINT_TYPE_VT) {
                                size = mono_class_value_size (klass, NULL);
                                PUSH_VT(&td, size);
                        }
@@ -1727,14 +1823,16 @@ generate (MonoMethod *method, RuntimeMethod *rtm, unsigned char *is_bb_start)
                        ADD_CODE(&td, MINT_NEWOBJ);
                        ADD_CODE(&td, get_data_item_index (&td, mono_interp_get_runtime_method (domain, m, &error)));
                        mono_error_cleanup (&error); /* FIXME: don't swallow the error */
-                       if (klass->byval_arg.type == MONO_TYPE_VALUETYPE) {
+
+                       if (mint_type (&klass->byval_arg) == MINT_TYPE_VT) {
                                vt_res_size = mono_class_value_size (klass, NULL);
-                               PUSH_VT(&td, vt_res_size);
+                               PUSH_VT (&td, vt_res_size);
                        }
                        for (i = 0; i < csignature->param_count; ++i) {
                                int mt = mint_type(csignature->params [i]);
                                if (mt == MINT_TYPE_VT) {
-                                       gint32 size = mono_class_value_size (csignature->params [i]->data.klass, NULL);
+                                       MonoClass *k = mono_class_from_mono_type (csignature->params [i]);
+                                       gint32 size = mono_class_value_size (k, NULL);
                                        size = (size + 7) & ~7;
                                        vt_stack_used += size;
                                }
@@ -1745,7 +1843,7 @@ generate (MonoMethod *method, RuntimeMethod *rtm, unsigned char *is_bb_start)
                                WRITE32(&td, &vt_stack_used);
                                td.vt_sp -= vt_stack_used;
                        }
-                       PUSH_TYPE(&td, stack_type [mint_type (&klass->byval_arg)], klass);
+                       PUSH_TYPE (&td, stack_type [mint_type (&klass->byval_arg)], klass);
                        break;
                }
                case CEE_CASTCLASS:
@@ -1789,11 +1887,41 @@ generate (MonoMethod *method, RuntimeMethod *rtm, unsigned char *is_bb_start)
                                klass = (MonoClass *)mono_method_get_wrapper_data (method, token);
                        else 
                                klass = mono_class_get_full (image, token, generic_context);
+
+                       if (mono_class_is_nullable (klass)) {
+                               g_error ("cee_unbox: implement Nullable");
+                       }
                        
                        ADD_CODE(&td, MINT_UNBOX);
                        ADD_CODE(&td, get_data_item_index (&td, klass));
                        SET_SIMPLE_TYPE(td.sp - 1, STACK_TYPE_MP);
                        td.ip += 5;
+                       break;
+               case CEE_UNBOX_ANY:
+                       CHECK_STACK (&td, 1);
+                       token = read32 (td.ip + 1);
+
+                       g_assert (method->wrapper_type == MONO_WRAPPER_NONE);
+                       klass = mono_class_get_full (image, token, generic_context);
+
+                       if (mini_type_is_reference (&klass->byval_arg)) {
+                               g_error ("unbox_any: generic class is reference type");
+                       } else if (mono_class_is_nullable (klass)) {
+                               MonoMethod *target_method = mono_class_get_method_from_name (klass, "Unbox", 1);
+                               /* td.ip is incremented by interp_transform_call */
+                               interp_transform_call (&td, method, target_method, domain, generic_context, is_bb_start, body_start_offset, NULL);
+                       } else {
+                               int mt = mint_type (&klass->byval_arg);
+                               ADD_CODE (&td, MINT_UNBOX);
+                               ADD_CODE (&td, get_data_item_index (&td, klass));
+                               SET_TYPE (td.sp - 1, stack_type [mt], klass);
+                               if (mt == MINT_TYPE_VT) {
+                                       int size = mono_class_value_size (klass, NULL);
+                                       PUSH_VT (&td, size);
+                               }
+                               td.ip += 5;
+                       }
+
                        break;
                case CEE_THROW:
                        CHECK_STACK (&td, 1);
@@ -1817,7 +1945,9 @@ generate (MonoMethod *method, RuntimeMethod *rtm, unsigned char *is_bb_start)
                        token = read32 (td.ip + 1);
                        field = mono_field_from_token (image, token, &klass, generic_context);
                        mono_class_init (klass);
-                       mt = mint_type(field->type);
+
+                       MonoClass *field_klass = mono_class_from_mono_type (field->type);
+                       mt = mint_type (&field_klass->byval_arg);
                        if (klass->marshalbyref) {
                                ADD_CODE(&td, mt == MINT_TYPE_VT ? MINT_LDRMFLD_VT :  MINT_LDRMFLD);
                                ADD_CODE(&td, get_data_item_index (&td, field));
@@ -1825,16 +1955,21 @@ generate (MonoMethod *method, RuntimeMethod *rtm, unsigned char *is_bb_start)
                                ADD_CODE(&td, MINT_LDFLD_I1 + mt - MINT_TYPE_I1);
                                ADD_CODE(&td, klass->valuetype ? field->offset - sizeof(MonoObject) : field->offset);
                        }
-                       klass = NULL;
                        if (mt == MINT_TYPE_VT) {
-                               int size = mono_class_value_size (field->type->data.klass, NULL);
+                               int size = mono_class_value_size (field_klass, NULL);
                                PUSH_VT(&td, size);
                                WRITE32(&td, &size);
-                               klass = field->type->data.klass;
-                       } else if (mt == MINT_TYPE_O)
-                               klass = mono_class_from_mono_type (field->type);
+                       }
+                       if (td.sp [-1].type == STACK_TYPE_VT) {
+                               int size = mono_class_value_size (klass, NULL);
+                               size = (size + 7) & ~7;
+                               td.vt_sp -= size;
+                               ADD_CODE (&td, MINT_VTRESULT);
+                               ADD_CODE (&td, 0);
+                               WRITE32 (&td, &size);
+                       }
                        td.ip += 5;
-                       SET_TYPE(td.sp - 1, stack_type [mt], klass);
+                       SET_TYPE(td.sp - 1, stack_type [mt], field_klass);
                        break;
                }
                case CEE_STFLD:
@@ -1851,7 +1986,8 @@ generate (MonoMethod *method, RuntimeMethod *rtm, unsigned char *is_bb_start)
                                ADD_CODE(&td, klass->valuetype ? field->offset - sizeof(MonoObject) : field->offset);
                        }
                        if (mt == MINT_TYPE_VT) {
-                               int size = mono_class_value_size (field->type->data.klass, NULL);
+                               MonoClass *klass = mono_class_from_mono_type (field->type);
+                               int size = mono_class_value_size (klass, NULL);
                                POP_VT(&td, size);
                                WRITE32(&td, &size);
                        }
@@ -1874,20 +2010,14 @@ generate (MonoMethod *method, RuntimeMethod *rtm, unsigned char *is_bb_start)
                        ADD_CODE(&td, get_data_item_index (&td, field));
                        klass = NULL;
                        if (mt == MINT_TYPE_VT) {
-                               int size = mono_class_value_size (field->type->data.klass, NULL);
+                               MonoClass *klass = mono_class_from_mono_type (field->type);
+                               int size = mono_class_value_size (klass, NULL);
                                PUSH_VT(&td, size);
                                WRITE32(&td, &size);
                                klass = field->type->data.klass;
                        } else {
                                if (mt == MINT_TYPE_O) 
                                        klass = mono_class_from_mono_type (field->type);
-                               if (!domain->special_static_fields || !g_hash_table_lookup (domain->special_static_fields, field)) {
-                                       if (mt == MINT_TYPE_O)
-                                               td.new_ip [-2] = MINT_LDSFLD_O;
-                                       else if (mt == MINT_TYPE_I4)
-                                               td.new_ip [-2] = MINT_LDSFLD_I4;
-                               }
-                               ADD_CODE(&td, get_data_item_index (&td, mono_class_vtable (domain, field->parent)));
                        }
                        td.ip += 5;
                        PUSH_TYPE(&td, stack_type [mt], klass);
@@ -1900,9 +2030,10 @@ generate (MonoMethod *method, RuntimeMethod *rtm, unsigned char *is_bb_start)
                        ADD_CODE(&td, mt == MINT_TYPE_VT ? MINT_STSFLD_VT : MINT_STSFLD);
                        ADD_CODE(&td, get_data_item_index (&td, field));
                        if (mt == MINT_TYPE_VT) {
-                               int size = mono_class_value_size (field->type->data.klass, NULL);
-                               POP_VT(&td, size);
-                               WRITE32(&td, &size);
+                               MonoClass *klass = mono_class_from_mono_type (field->type);
+                               int size = mono_class_value_size (klass, NULL);
+                               POP_VT (&td, size);
+                               WRITE32 (&td, &size);
                        }
                        td.ip += 5;
                        --td.sp;
@@ -1978,16 +2109,27 @@ generate (MonoMethod *method, RuntimeMethod *rtm, unsigned char *is_bb_start)
                                klass = (MonoClass *)mono_method_get_wrapper_data (method, token);
                        else
                                klass = mono_class_get_full (image, token, generic_context);
-                       g_assert (klass->valuetype);
-                       if (klass->byval_arg.type == MONO_TYPE_VALUETYPE && !klass->enumtype) {
-                               size = mono_class_value_size (klass, NULL);
-                               size = (size + 7) & ~7;
-                               td.vt_sp -= size;
+
+                       if (mono_class_is_nullable (klass)) {
+                               MonoMethod *target_method = mono_class_get_method_from_name (klass, "Box", 1);
+                               /* td.ip is incremented by interp_transform_call */
+                               interp_transform_call (&td, method, target_method, domain, generic_context, is_bb_start, body_start_offset, NULL);
+                       } else if (!klass->valuetype) {
+                               /* already boxed, do nothing. */
+                               td.ip += 5;
+                       } else {
+                               if (mint_type (&klass->byval_arg) == MINT_TYPE_VT && !klass->enumtype) {
+                                       size = mono_class_value_size (klass, NULL);
+                                       size = (size + 7) & ~7;
+                                       td.vt_sp -= size;
+                               }
+                               ADD_CODE(&td, MINT_BOX);
+                               ADD_CODE(&td, get_data_item_index (&td, klass));
+                               ADD_CODE (&td, 0);
+                               SET_TYPE(td.sp - 1, STACK_TYPE_O, klass);
+                               td.ip += 5;
                        }
-                       ADD_CODE(&td, MINT_BOX);
-                       ADD_CODE(&td, get_data_item_index (&td, klass));
-                       SET_TYPE(td.sp - 1, STACK_TYPE_O, klass);
-                       td.ip += 5;
+
                        break;
                }
                case CEE_NEWARR:
@@ -2102,6 +2244,39 @@ generate (MonoMethod *method, RuntimeMethod *rtm, unsigned char *is_bb_start)
                        --td.sp;
                        SET_SIMPLE_TYPE(td.sp - 1, STACK_TYPE_O);
                        break;
+               case CEE_LDELEM:
+                       CHECK_STACK (&td, 2);
+                       token = read32 (td.ip + 1);
+                       klass = mono_class_get_full (image, token, generic_context);
+                       switch (mint_type (&klass->byval_arg)) {
+                               case MINT_TYPE_I4:
+                                       ENSURE_I4 (&td, 1);
+                                       SIMPLE_OP (td, MINT_LDELEM_I4);
+                                       --td.sp;
+                                       SET_SIMPLE_TYPE(td.sp - 1, STACK_TYPE_I4);
+                                       break;
+                               case MINT_TYPE_VT: {
+                                       int size = mono_class_value_size (klass, NULL);
+                                       ENSURE_I4 (&td, 1);
+                                       SIMPLE_OP (td, MINT_LDELEM_VT);
+                                       ADD_CODE (&td, get_data_item_index (&td, klass));
+                                       WRITE32 (&td, &size);
+                                       --td.sp;
+                                       SET_SIMPLE_TYPE(td.sp - 1, STACK_TYPE_VT);
+                                       PUSH_VT (&td, size);
+                                       break;
+                               }
+                               default: {
+                                       GString *res = g_string_new ("");
+                                       mono_type_get_desc (res, &klass->byval_arg, TRUE);
+                                       g_print ("LDELEM: %s -> %d (%s)\n", klass->name, mint_type (&klass->byval_arg), res->str);
+                                       g_string_free (res, TRUE);
+                                       g_assert (0);
+                                       break;
+                               }
+                       }
+                       td.ip += 4;
+                       break;
                case CEE_STELEM_I:
                        CHECK_STACK (&td, 3);
                        ENSURE_I4 (&td, 2);
@@ -2150,11 +2325,39 @@ generate (MonoMethod *method, RuntimeMethod *rtm, unsigned char *is_bb_start)
                        SIMPLE_OP (td, MINT_STELEM_REF);
                        td.sp -= 3;
                        break;
+               case CEE_STELEM:
+                       CHECK_STACK (&td, 3);
+                       ENSURE_I4 (&td, 2);
+                       token = read32 (td.ip + 1);
+                       klass = mono_class_get_full (image, token, generic_context);
+                       switch (mint_type (&klass->byval_arg)) {
+                               case MINT_TYPE_I4:
+                                       SIMPLE_OP (td, MINT_STELEM_I4);
+                                       break;
+                               case MINT_TYPE_O:
+                                       SIMPLE_OP (td, MINT_STELEM_REF);
+                                       break;
+                               case MINT_TYPE_VT: {
+                                       int size = mono_class_value_size (klass, NULL);
+                                       SIMPLE_OP (td, MINT_STELEM_VT);
+                                       ADD_CODE (&td, get_data_item_index (&td, klass));
+                                       WRITE32 (&td, &size);
+                                       POP_VT (&td, size);
+                                       break;
+                               }
+                               default: {
+                                       GString *res = g_string_new ("");
+                                       mono_type_get_desc (res, &klass->byval_arg, TRUE);
+                                       g_print ("STELEM: %s -> %d (%s)\n", klass->name, mint_type (&klass->byval_arg), res->str);
+                                       g_string_free (res, TRUE);
+                                       g_assert (0);
+                                       break;
+                               }
+                       }
+                       td.ip += 4;
+                       td.sp -= 3;
+                       break;
 #if 0
-               case CEE_LDELEM: 
-               case CEE_STELEM: 
-               case CEE_UNBOX_ANY: 
-
                case CEE_CONV_OVF_U1:
 
                case CEE_CONV_OVF_I8:
@@ -2389,6 +2592,10 @@ generate (MonoMethod *method, RuntimeMethod *rtm, unsigned char *is_bb_start)
                case CEE_UNUSED41:
                        ++td.ip;
                        switch (*td.ip) {
+                               case CEE_MONO_CALLI_EXTRA_ARG:
+                                       /* Same as CEE_CALLI, llvm specific */
+                                       interp_transform_call (&td, method, NULL, domain, generic_context, is_bb_start, body_start_offset, NULL);
+                                       break;
                                case CEE_MONO_ICALL: {
                                        guint32 token;
                                        gpointer func;
@@ -2406,7 +2613,7 @@ generate (MonoMethod *method, RuntimeMethod *rtm, unsigned char *is_bb_start)
                                                if (MONO_TYPE_IS_VOID (info->sig->ret))
                                                        ADD_CODE (&td,MINT_ICALL_V_V);
                                                else
-                                                       g_assert_not_reached();
+                                                       ADD_CODE (&td, MINT_ICALL_V_P);
                                                break;
                                        case 1:
                                                if (MONO_TYPE_IS_VOID (info->sig->ret))
@@ -2437,11 +2644,11 @@ generate (MonoMethod *method, RuntimeMethod *rtm, unsigned char *is_bb_start)
                                        default:
                                                g_assert_not_reached ();
                                        }
-                                       g_error ("FIXME: ftnptr to delegate");
-#if 0
-                                       if (func == mono_ftnptr_to_delegate)
+
+                                       if (func == mono_ftnptr_to_delegate) {
+                                               g_error ("TODO: ?");
                                                func = mono_interp_ftnptr_to_delegate;
-#endif
+                                       }
                                        ADD_CODE(&td, get_data_item_index (&td, func));
                                        td.sp -= info->sig->param_count;
 
@@ -2516,6 +2723,12 @@ generate (MonoMethod *method, RuntimeMethod *rtm, unsigned char *is_bb_start)
                        case CEE_MONO_NOT_TAKEN:
                                ++td.ip;
                                break;
+                       case CEE_MONO_LDPTR_INT_REQ_FLAG:
+                               ADD_CODE (&td, MINT_MONO_LDPTR);
+                               ADD_CODE (&td, get_data_item_index (&td, mono_thread_interruption_request_flag ()));
+                               PUSH_TYPE (&td, STACK_TYPE_MP, NULL);
+                               ++td.ip;
+                               break;
                        default:
                                g_error ("transform.c: Unimplemented opcode: 0xF0 %02x at 0x%x\n", *td.ip, td.ip-header->code);
                        }
@@ -2619,11 +2832,13 @@ generate (MonoMethod *method, RuntimeMethod *rtm, unsigned char *is_bb_start)
                                break;
                        case CEE_LDARGA: {
                                int n = read16 (td.ip + 1);
-                               if (n == 0 && signature->hasthis) 
+                               if (n == 0 && signature->hasthis) {
+                                       g_error ("LDTHISA: NOPE");
                                        ADD_CODE(&td, MINT_LDTHISA);
+                               }
                                else {
                                        ADD_CODE(&td, MINT_LDARGA);
-                                       ADD_CODE(&td, td.rtm->arg_offsets [n - signature->hasthis]); /* FIX for large offsets */
+                                       ADD_CODE(&td, td.rtm->arg_offsets [n]); /* FIX for large offsets */
                                }
                                PUSH_SIMPLE_TYPE(&td, STACK_TYPE_MP);
                                td.ip += 3;
@@ -2692,16 +2907,12 @@ generate (MonoMethod *method, RuntimeMethod *rtm, unsigned char *is_bb_start)
                                td.sp -= 3;
                                ++td.ip;
                                break;
-#if 0
-                       case CEE_CONSTRAINED_: {
-                               guint32 token;
-                               /* FIXME: implement */
-                               ++ip;
-                               token = read32 (ip);
-                               ip += 4;
+                       case CEE_CONSTRAINED_:
+                               token = read32 (td.ip + 1);
+                               constrained_class = mono_class_get_full (image, token, generic_context);
+                               mono_class_init (constrained_class);
+                               td.ip += 5;
                                break;
-                       }
-#endif
                        case CEE_INITBLK:
                                CHECK_STACK(&td, 3);
                                ADD_CODE(&td, MINT_INITBLK);
@@ -2718,14 +2929,15 @@ generate (MonoMethod *method, RuntimeMethod *rtm, unsigned char *is_bb_start)
                                generating_code = 0;
                                break;
                        case CEE_SIZEOF: {
-                               guint32 align;
                                gint32 size;
                                token = read32 (td.ip + 1);
                                td.ip += 5;
                                if (mono_metadata_token_table (token) == MONO_TABLE_TYPESPEC) {
+                                       int align;
                                        MonoType *type = mono_type_create_from_typespec (image, token);
                                        size = mono_type_size (type, &align);
                                } else {
+                                       guint32 align;
                                        MonoClass *szclass = mono_class_get_full (image, token, generic_context);
                                        mono_class_init (szclass);
 #if 0
@@ -2863,21 +3075,13 @@ mono_interp_transform_method (RuntimeMethod *runtime_method, ThreadContext *cont
                }
 
                /* assumes all internal calls with an array this are built in... */
-               if (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL &&
-                       (! mono_method_signature (method)->hasthis || method->klass->rank == 0)) {
-                       runtime_method->code = g_malloc(sizeof(short));
-                       runtime_method->code[0] = MINT_CALLINT;
-                       if (((MonoMethodPInvoke*) method)->addr == NULL)
-                               ((MonoMethodPInvoke*) method)->addr = mono_lookup_internal_call (method);
-                       g_error ("FIXME: not available?");
-#if 0
-                       runtime_method->func = mono_arch_create_trampoline (mono_method_signature (method), method->string_ctor);
-#endif
+               if (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL && (! mono_method_signature (method)->hasthis || method->klass->rank == 0)) {
+                       nm = mono_marshal_get_native_wrapper (method, TRUE, FALSE);
+                       signature = mono_method_signature (nm);
                } else {
                        const char *name = method->name;
                        if (method->klass->parent == mono_defaults.multicastdelegate_class) {
                                if (*name == 'I' && (strcmp (name, "Invoke") == 0)) {
-                                       g_error ("FIXME: no del?");
                                        nm = mono_marshal_get_delegate_invoke (method, NULL);
                                } else if (*name == 'B' && (strcmp (name, "BeginInvoke") == 0)) {
                                        nm = mono_marshal_get_delegate_begin_invoke (method);
@@ -2895,7 +3099,6 @@ mono_interp_transform_method (RuntimeMethod *runtime_method, ThreadContext *cont
                        runtime_method->alloca_size = runtime_method->stack_size;
                        runtime_method->transformed = TRUE;
                        mono_os_mutex_unlock(&calc_section);
-                       g_error ("FIXME: no jinfo?");
                        mono_profiler_method_end_jit (method, NULL, MONO_PROFILE_OK);
                        return NULL;
                }
@@ -2954,7 +3157,7 @@ mono_interp_transform_method (RuntimeMethod *runtime_method, ThreadContext *cont
                                        // return mono_get_exception_missing_method ();
                                }
                                mono_class_init (m->klass);
-                               if (!(m->klass->flags & TYPE_ATTRIBUTE_INTERFACE))
+                               if (!mono_class_is_interface (m->klass))
                                        mono_class_vtable (domain, m->klass);
                        }
                        ip += 5;
@@ -3021,7 +3224,6 @@ mono_interp_transform_method (RuntimeMethod *runtime_method, ThreadContext *cont
        if (runtime_method->transformed) {
                mono_os_mutex_unlock(&calc_section);
                g_free (is_bb_start);
-               g_error ("FIXME: missing jinfo1");
                mono_profiler_method_end_jit (method, NULL, MONO_PROFILE_OK);
                return NULL;
        }
@@ -3041,17 +3243,28 @@ mono_interp_transform_method (RuntimeMethod *runtime_method, ThreadContext *cont
        runtime_method->locals_size = offset;
        g_assert (runtime_method->locals_size < 65536);
        offset = 0;
-       runtime_method->arg_offsets = g_malloc(signature->param_count * sizeof(guint32));
+       runtime_method->arg_offsets = g_malloc ((!!signature->hasthis + signature->param_count) * sizeof(guint32));
+
+       if (signature->hasthis) {
+               g_assert (!signature->pinvoke);
+               size = mono_type_stack_size (&method->klass->byval_arg, &align);
+               offset += align - 1;
+               offset &= ~(align - 1);
+               runtime_method->arg_offsets [0] = offset;
+               offset += size;
+       }
+
        for (i = 0; i < signature->param_count; ++i) {
                if (signature->pinvoke) {
-                       size = mono_type_native_stack_size (signature->params [i], &align);
+                       guint32 dummy;
+                       size = mono_type_native_stack_size (signature->params [i], &dummy);
                        align = 8;
                }
                else
                        size = mono_type_stack_size (signature->params [i], &align);
                offset += align - 1;
                offset &= ~(align - 1);
-               runtime_method->arg_offsets [i] = offset;
+               runtime_method->arg_offsets [i + !!signature->hasthis] = offset;
                offset += size;
        }
        offset = (offset + 7) & ~7;