* ProtectedConfigurationProvider.cs:
[mono.git] / mono / mini / mini.c
index 27a0e71037721f10fafe794404d94894ea0a1adb..353268e25e44155a22ab07fb6de8ecbf93411eae 100644 (file)
 #include <unistd.h>
 #include <math.h>
 
+#ifdef sun    // Solaris x86
+#include <sys/types.h>
+#include <sys/ucontext.h>
+#endif
+
 #ifdef HAVE_VALGRIND_MEMCHECK_H
 #include <valgrind/memcheck.h>
 #endif
@@ -54,7 +59,7 @@
  * this is used to determine when some branch optimizations are possible: we exclude FP compares
  * because they have weird semantics with NaNs.
  */
-#define MONO_IS_COND_BRANCH_OP(ins) (((ins)->opcode >= CEE_BEQ && (ins)->opcode <= CEE_BLT_UN) || ((ins)->opcode >= OP_LBEQ && (ins)->opcode <= OP_LBLT_UN) || ((ins)->opcode >= OP_FBEQ && (ins)->opcode <= OP_FBLT_UN))
+#define MONO_IS_COND_BRANCH_OP(ins) (((ins)->opcode >= CEE_BEQ && (ins)->opcode <= CEE_BLT_UN) || ((ins)->opcode >= OP_LBEQ && (ins)->opcode <= OP_LBLT_UN) || ((ins)->opcode >= OP_FBEQ && (ins)->opcode <= OP_FBLT_UN) || ((ins)->opcode >= OP_IBEQ && (ins)->opcode <= OP_IBLT_UN))
 #define MONO_IS_COND_BRANCH_NOFP(ins) (MONO_IS_COND_BRANCH_OP(ins) && (ins)->inst_left->inst_left->type != STACK_R8)
 
 #define MONO_CHECK_THIS(ins) (cfg->method->signature->hasthis && (ins)->ssa_op == MONO_SSA_LOAD && (ins)->inst_left->inst_c0 == 0)
@@ -87,11 +92,14 @@ static MonoMethodSignature *helper_sig_compile = NULL;
 static MonoMethodSignature *helper_sig_compile_virt = NULL;
 static MonoMethodSignature *helper_sig_obj_ptr = NULL;
 static MonoMethodSignature *helper_sig_obj_ptr_ptr = NULL;
+static MonoMethodSignature *helper_sig_obj_obj_ptr_ptr = NULL;
 static MonoMethodSignature *helper_sig_obj_void = NULL;
 static MonoMethodSignature *helper_sig_ptr_void = NULL;
+static MonoMethodSignature *helper_sig_void_void = NULL;
 static MonoMethodSignature *helper_sig_void_ptr = NULL;
 static MonoMethodSignature *helper_sig_void_obj = NULL;
 static MonoMethodSignature *helper_sig_void_obj_ptr_int = NULL;
+static MonoMethodSignature *helper_sig_void_obj_ptr_ptr_obj = NULL;
 static MonoMethodSignature *helper_sig_void_ptr_ptr = NULL;
 static MonoMethodSignature *helper_sig_void_ptr_ptr_ptr = NULL;
 static MonoMethodSignature *helper_sig_ptr_ptr_ptr = NULL;
@@ -168,6 +176,12 @@ print_method_from_ip (void *ip)
 
 }
 
+G_GNUC_UNUSED void
+mono_print_method_from_ip (void *ip)
+{
+       print_method_from_ip (ip);
+}
+       
 /* 
  * mono_method_same_domain:
  *
@@ -247,17 +261,31 @@ mono_jump_info_token_new (MonoMemPool *mp, MonoImage *image, guint32 token)
                (dest)->type = STACK_I4;        \
        } while (0)
 
-/* FIXME: have a different definition of NEW_PCONST for 64 bit systems */
+#if SIZEOF_VOID_P == 8
+#define NEW_PCONST(cfg,dest,val) do {  \
+               (dest) = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst));       \
+               (dest)->opcode = OP_I8CONST;    \
+               (dest)->inst_p0 = (val);        \
+               (dest)->type = STACK_PTR;       \
+       } while (0)
+#else
 #define NEW_PCONST(cfg,dest,val) do {  \
                (dest) = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst));       \
                (dest)->opcode = OP_ICONST;     \
                (dest)->inst_p0 = (val);        \
                (dest)->type = STACK_PTR;       \
        } while (0)
+#endif
+
+#if SIZEOF_VOID_P == 8
+#define OP_PCONST OP_I8CONST
+#else
+#define OP_PCONST OP_ICONST
+#endif
 
 #define NEW_CLASSCONST(cfg,dest,val) do {      \
                (dest) = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst));       \
-               (dest)->opcode = mono_compile_aot ? OP_AOTCONST : OP_ICONST;    \
+               (dest)->opcode = mono_compile_aot ? OP_AOTCONST : OP_PCONST;    \
                (dest)->inst_p0 = (val);        \
                (dest)->inst_i1 = (gpointer)MONO_PATCH_INFO_CLASS; \
                (dest)->type = STACK_PTR;       \
@@ -265,7 +293,7 @@ mono_jump_info_token_new (MonoMemPool *mp, MonoImage *image, guint32 token)
 
 #define NEW_IMAGECONST(cfg,dest,val) do {      \
                (dest) = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst));       \
-               (dest)->opcode = mono_compile_aot ? OP_AOTCONST : OP_ICONST;    \
+               (dest)->opcode = mono_compile_aot ? OP_AOTCONST : OP_PCONST;    \
                (dest)->inst_p0 = (val);        \
                (dest)->inst_i1 = (gpointer)MONO_PATCH_INFO_IMAGE; \
                (dest)->type = STACK_PTR;       \
@@ -273,7 +301,7 @@ mono_jump_info_token_new (MonoMemPool *mp, MonoImage *image, guint32 token)
 
 #define NEW_FIELDCONST(cfg,dest,field) do {    \
                (dest) = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst));       \
-               (dest)->opcode = mono_compile_aot ? OP_AOTCONST : OP_ICONST;    \
+               (dest)->opcode = mono_compile_aot ? OP_AOTCONST : OP_PCONST;    \
                (dest)->inst_p0 = (field);      \
                (dest)->inst_i1 = (gpointer)MONO_PATCH_INFO_FIELD; \
                (dest)->type = STACK_PTR;       \
@@ -281,7 +309,7 @@ mono_jump_info_token_new (MonoMemPool *mp, MonoImage *image, guint32 token)
 
 #define NEW_METHODCONST(cfg,dest,val) do {     \
                (dest) = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst));       \
-               (dest)->opcode = mono_compile_aot ? OP_AOTCONST : OP_ICONST;    \
+               (dest)->opcode = mono_compile_aot ? OP_AOTCONST : OP_PCONST;    \
                (dest)->inst_p0 = (val);        \
                (dest)->inst_i1 = (gpointer)MONO_PATCH_INFO_METHODCONST; \
                (dest)->type = STACK_PTR;       \
@@ -289,7 +317,7 @@ mono_jump_info_token_new (MonoMemPool *mp, MonoImage *image, guint32 token)
 
 #define NEW_VTABLECONST(cfg,dest,vtable) do {  \
                (dest) = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst));       \
-               (dest)->opcode = mono_compile_aot ? OP_AOTCONST : OP_ICONST;    \
+               (dest)->opcode = mono_compile_aot ? OP_AOTCONST : OP_PCONST;    \
                (dest)->inst_p0 = mono_compile_aot ? (gpointer)((vtable)->klass) : (vtable);    \
                (dest)->inst_i1 = (gpointer)MONO_PATCH_INFO_VTABLE; \
                (dest)->type = STACK_PTR;       \
@@ -297,7 +325,7 @@ mono_jump_info_token_new (MonoMemPool *mp, MonoImage *image, guint32 token)
 
 #define NEW_SFLDACONST(cfg,dest,field) do {    \
                (dest) = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst));       \
-               (dest)->opcode = mono_compile_aot ? OP_AOTCONST : OP_ICONST;    \
+               (dest)->opcode = mono_compile_aot ? OP_AOTCONST : OP_PCONST;    \
                (dest)->inst_p0 = (field);      \
                (dest)->inst_i1 = (gpointer)MONO_PATCH_INFO_SFLDA; \
                (dest)->type = STACK_PTR;       \
@@ -480,8 +508,8 @@ mono_jump_info_token_new (MonoMemPool *mp, MonoImage *image, guint32 token)
 
 #define ADD_BINCOND(next_block) do {   \
                MonoInst *cmp;  \
-               MONO_INST_NEW(cfg, cmp, OP_COMPARE);    \
                sp -= 2;                \
+               MONO_INST_NEW(cfg, cmp, OP_COMPARE);    \
                cmp->inst_i0 = sp [0];  \
                cmp->inst_i1 = sp [1];  \
                cmp->cil_code = ins->cil_code;  \
@@ -509,8 +537,8 @@ mono_jump_info_token_new (MonoMemPool *mp, MonoImage *image, guint32 token)
 /* FIXME: handle float, long ... */
 #define ADD_UNCOND(istrue) do {        \
                MonoInst *cmp;  \
-               MONO_INST_NEW(cfg, cmp, OP_COMPARE);    \
                sp--;           \
+               MONO_INST_NEW(cfg, cmp, OP_COMPARE);    \
                cmp->inst_i0 = sp [0];  \
                 switch (cmp->inst_i0->type) { \
                case STACK_I8: \
@@ -1074,37 +1102,37 @@ shift_table [STACK_MAX] [STACK_MAX] = {
 /* handles from CEE_ADD to CEE_SHR_UN (CEE_REM_UN for floats) */
 static const guint16
 binops_op_map [STACK_MAX] = {
-       0, 0, OP_LADD-CEE_ADD, OP_PADD-CEE_ADD, OP_FADD-CEE_ADD, 0
+       0, 0, OP_LADD-CEE_ADD, OP_PADD-CEE_ADD, OP_FADD-CEE_ADD, OP_PADD-CEE_ADD
 };
 
 /* handles from CEE_NEG to CEE_CONV_U8 */
 static const guint16
 unops_op_map [STACK_MAX] = {
-       0, 0, OP_LNEG-CEE_NEG, OP_PNEG-CEE_NEG, OP_FNEG-CEE_NEG, 0
+       0, 0, OP_LNEG-CEE_NEG, OP_PNEG-CEE_NEG, OP_FNEG-CEE_NEG, OP_PNEG-CEE_NEG
 };
 
 /* handles from CEE_CONV_U2 to CEE_SUB_OVF_UN */
 static const guint16
 ovfops_op_map [STACK_MAX] = {
-       0, 0, OP_LCONV_TO_U2-CEE_CONV_U2, OP_PCONV_TO_U2-CEE_CONV_U2, OP_FCONV_TO_U2-CEE_CONV_U2, 0
+       0, 0, OP_LCONV_TO_U2-CEE_CONV_U2, OP_PCONV_TO_U2-CEE_CONV_U2, OP_FCONV_TO_U2-CEE_CONV_U2, OP_PCONV_TO_U2-CEE_CONV_U2
 };
 
 /* handles from CEE_CONV_OVF_I1_UN to CEE_CONV_OVF_U_UN */
 static const guint16
 ovf2ops_op_map [STACK_MAX] = {
-       0, 0, OP_LCONV_TO_OVF_I1_UN-CEE_CONV_OVF_I1_UN, OP_PCONV_TO_OVF_I1_UN-CEE_CONV_OVF_I1_UN, OP_FCONV_TO_OVF_I1_UN-CEE_CONV_OVF_I1_UN, 0
+       0, 0, OP_LCONV_TO_OVF_I1_UN-CEE_CONV_OVF_I1_UN, OP_PCONV_TO_OVF_I1_UN-CEE_CONV_OVF_I1_UN, OP_FCONV_TO_OVF_I1_UN-CEE_CONV_OVF_I1_UN, OP_PCONV_TO_OVF_I1_UN-CEE_CONV_OVF_I1_UN
 };
 
 /* handles from CEE_CONV_OVF_I1 to CEE_CONV_OVF_U8 */
 static const guint16
 ovf3ops_op_map [STACK_MAX] = {
-       0, 0, OP_LCONV_TO_OVF_I1-CEE_CONV_OVF_I1, OP_PCONV_TO_OVF_I1-CEE_CONV_OVF_I1, OP_FCONV_TO_OVF_I1-CEE_CONV_OVF_I1, 0
+       0, 0, OP_LCONV_TO_OVF_I1-CEE_CONV_OVF_I1, OP_PCONV_TO_OVF_I1-CEE_CONV_OVF_I1, OP_FCONV_TO_OVF_I1-CEE_CONV_OVF_I1, OP_PCONV_TO_OVF_I1-CEE_CONV_OVF_I1
 };
 
 /* handles from CEE_CEQ to CEE_CLT_UN */
 static const guint16
 ceqops_op_map [STACK_MAX] = {
-       0, 0, OP_LCEQ-CEE_CEQ, OP_PCEQ-CEE_CEQ, OP_FCEQ-CEE_CEQ, 0
+       0, 0, OP_LCEQ-CEE_CEQ, OP_PCEQ-CEE_CEQ, OP_FCEQ-CEE_CEQ, OP_LCEQ-CEE_CEQ
 };
 
 /*
@@ -1143,8 +1171,11 @@ type_from_op (MonoInst *ins) {
                ins->opcode += binops_op_map [ins->type];
                return;
        case OP_COMPARE:
+       case OP_LCOMPARE:
                /* FIXME: handle some specifics with ins->next->type */
                ins->type = bin_comp_table [ins->inst_i0->type] [ins->inst_i1->type] ? STACK_I4: STACK_INV;
+               if ((ins->inst_i0->type == STACK_I8) || ((sizeof (gpointer) == 8) && ((ins->inst_i0->type == STACK_PTR) || (ins->inst_i0->type == STACK_OBJ) || (ins->inst_i0->type == STACK_MP))))
+                       ins->opcode = OP_LCOMPARE;
                return;
        case OP_CEQ:
        case OP_CGT:
@@ -1576,23 +1607,24 @@ mono_compile_get_interface_var (MonoCompile *cfg, int slot, MonoInst *ins)
  */
 static int
 handle_stack_args (MonoCompile *cfg, MonoBasicBlock *bb, MonoInst **sp, int count) {
-       int i;
+       int i, bindex;
        MonoBasicBlock *outb;
        MonoInst *inst, **locals;
+       gboolean found;
 
        if (!count)
                return 0;
        if (cfg->verbose_level > 3)
                g_print ("%d item(s) on exit from B%d\n", count, bb->block_num);
        if (!bb->out_scount) {
-               int found = 0;
                bb->out_scount = count;
                //g_print ("bblock %d has out:", bb->block_num);
+               found = FALSE;
                for (i = 0; i < bb->out_count; ++i) {
                        outb = bb->out_bb [i];
                        //g_print (" %d", outb->block_num);
                        if (outb->in_stack) {
-                               found = 1;
+                               found = TRUE;
                                bb->out_stack = outb->in_stack;
                                break;
                        }
@@ -1601,19 +1633,34 @@ handle_stack_args (MonoCompile *cfg, MonoBasicBlock *bb, MonoInst **sp, int coun
                if (!found) {
                        bb->out_stack = mono_mempool_alloc (cfg->mempool, sizeof (MonoInst*) * count);
                        for (i = 0; i < count; ++i) {
-/* see bug#58863, but removing this code causes regressions in gtk-sharp build 
- * (SEGV running Method::Initialize() in gapi_codegen.exe) 
- */
-#if defined(__ppc__) || defined(__powerpc__)
-                               /* try to reuse temps already allocated for this purpouse, if they occupy the same 
-                                * stack slot and if they are of the same type. */
-                               bb->out_stack [i] = mono_compile_get_interface_var (cfg, i, sp [i]);
-#else
-                               bb->out_stack [i] = mono_compile_create_var (cfg, type_from_stack_type (sp [i]), OP_LOCAL);
-#endif
+                               /* 
+                                * try to reuse temps already allocated for this purpouse, if they occupy the same
+                                * stack slot and if they are of the same type.
+                                * This won't cause conflicts since if 'local' is used to 
+                                * store one of the values in the in_stack of a bblock, then
+                                * the same variable will be used for the same outgoing stack 
+                                * slot as well. 
+                                * This doesn't work when inlining methods, since the bblocks
+                                * in the inlined methods do not inherit their in_stack from
+                                * the bblock they are inlined to. See bug #58863 for an
+                                * example.
+                                */
+                               if (cfg->inlined_method)
+                                       bb->out_stack [i] = mono_compile_create_var (cfg, type_from_stack_type (sp [i]), OP_LOCAL);
+                               else
+                                       bb->out_stack [i] = mono_compile_get_interface_var (cfg, i, sp [i]);
                        }
                }
        }
+
+       for (i = 0; i < bb->out_count; ++i) {
+               outb = bb->out_bb [i];
+               if (outb->in_scount)
+                       continue; /* check they are the same locals */
+               outb->in_scount = count;
+               outb->in_stack = bb->out_stack;
+       }
+
        locals = bb->out_stack;
        for (i = 0; i < count; ++i) {
                /* add store ops at the end of the bb, before the branch */
@@ -1628,27 +1675,47 @@ handle_stack_args (MonoCompile *cfg, MonoBasicBlock *bb, MonoInst **sp, int coun
                if (cfg->verbose_level > 3)
                        g_print ("storing %d to temp %d\n", i, locals [i]->inst_c0);
        }
-       
-       for (i = 0; i < bb->out_count; ++i) {
-               outb = bb->out_bb [i];
-               if (outb->in_scount)
-                       continue; /* check they are the same locals */
-               outb->in_scount = count;
-               outb->in_stack = locals;
+
+       /*
+        * It is possible that the out bblocks already have in_stack assigned, and
+        * the in_stacks differ. In this case, we will store to all the different 
+        * in_stacks.
+        */
+
+       found = TRUE;
+       bindex = 0;
+       while (found) {
+               /* Find a bblock which has a different in_stack */
+               found = FALSE;
+               while (bindex < bb->out_count) {
+                       outb = bb->out_bb [bindex];
+                       if (outb->in_stack != locals) {
+                               /* 
+                                * Instead of storing sp [i] to locals [i], we need to store
+                                * locals [i] to <new locals>[i], since the sp [i] tree can't
+                                * be shared between trees.
+                                */
+                               for (i = 0; i < count; ++i)
+                                       mono_add_varcopy_to_end (cfg, bb, locals [i]->inst_c0, outb->in_stack [i]->inst_c0);
+                               locals = outb->in_stack;
+                               found = TRUE;
+                               break;
+                       }
+                       bindex ++;
+               }
        }
+       
        return 0;
 }
 
 static int
 ret_type_to_call_opcode (MonoType *type, int calli, int virt)
 {
-       int t = type->type;
-
        if (type->byref)
                return calli? OP_CALL_REG: virt? CEE_CALLVIRT: CEE_CALL;
 
 handle_enum:
-       switch (t) {
+       switch (type->type) {
        case MONO_TYPE_VOID:
                return calli? OP_VOIDCALL_REG: virt? OP_VOIDCALLVIRT: OP_VOIDCALL;
        case MONO_TYPE_I1:
@@ -1678,14 +1745,14 @@ handle_enum:
                return calli? OP_FCALL_REG: virt? OP_FCALLVIRT: OP_FCALL;
        case MONO_TYPE_VALUETYPE:
                if (type->data.klass->enumtype) {
-                       t = type->data.klass->enum_basetype->type;
+                       type = type->data.klass->enum_basetype;
                        goto handle_enum;
                } else
                        return calli? OP_VCALL_REG: virt? OP_VCALLVIRT: OP_VCALL;
        case MONO_TYPE_TYPEDBYREF:
                return calli? OP_VCALL_REG: virt? OP_VCALLVIRT: OP_VCALL;
        case MONO_TYPE_GENERICINST:
-               t = type->data.generic_inst->generic_type->type;
+               type = type->data.generic_inst->generic_type;
                goto handle_enum;
        default:
                g_error ("unknown type 0x%02x in ret_type_to_call_opcode", type->type);
@@ -1749,7 +1816,8 @@ handle_loaded_temps (MonoCompile *cfg, MonoBasicBlock *bblock, MonoInst **stack,
 static int
 check_call_signature (MonoCompile *cfg, MonoMethodSignature *sig, MonoInst **args)
 {
-       int i, simple_type;
+       MonoType *simple_type;
+       int i;
 
        if (sig->hasthis) {
                if (args [0]->type != STACK_OBJ && args [0]->type != STACK_MP && args [0]->type != STACK_PTR)
@@ -1781,9 +1849,9 @@ check_call_signature (MonoCompile *cfg, MonoMethodSignature *sig, MonoInst **arg
                                return 1;
                        continue;
                }
-               simple_type = sig->params [i]->type;
+               simple_type = sig->params [i];
 handle_enum:
-               switch (simple_type) {
+               switch (simple_type->type) {
                case MONO_TYPE_VOID:
                        return 1;
                        continue;
@@ -1823,8 +1891,8 @@ handle_enum:
                                return 1;
                        continue;
                case MONO_TYPE_VALUETYPE:
-                       if (sig->params [i]->data.klass->enumtype) {
-                               simple_type = sig->params [i]->data.klass->enum_basetype->type;
+                       if (simple_type->data.klass->enumtype) {
+                               simple_type = simple_type->data.klass->enum_basetype;
                                goto handle_enum;
                        }
                        if (args [i]->type != STACK_VTYPE)
@@ -1835,11 +1903,12 @@ handle_enum:
                                return 1;
                        continue;
                case MONO_TYPE_GENERICINST:
-                       simple_type = sig->params [i]->data.generic_inst->generic_type->type;
+                       simple_type = sig->params [i]->data.generic_inst->generic_type;
                        goto handle_enum;
 
                default:
-                       g_error ("unknown type 0x%02x in check_call_signature", simple_type);
+                       g_error ("unknown type 0x%02x in check_call_signature",
+                                simple_type->type);
                }
        }
        return 0;
@@ -2071,6 +2140,10 @@ mono_get_element_address_signature (int arity)
        res = mono_metadata_signature_alloc (mono_defaults.corlib, arity + 1);
 
        res->pinvoke = 1;
+#ifdef MONO_ARCH_VARARG_ICALLS
+       /* Only set this only some archs since not all backends can handle varargs+pinvoke */
+       res->call_convention = MONO_CALL_VARARG;
+#endif
        res->params [0] = &mono_defaults.array_class->byval_arg; 
        
        for (i = 1; i <= arity; i++)
@@ -2084,6 +2157,42 @@ mono_get_element_address_signature (int arity)
        return res;
 }
 
+static MonoMethodSignature *
+mono_get_array_new_va_signature (int arity)
+{
+       static GHashTable *sighash = NULL;
+       MonoMethodSignature *res;
+       int i;
+
+       EnterCriticalSection (&trampoline_hash_mutex);
+       if (!sighash) {
+               sighash = g_hash_table_new (NULL, NULL);
+       }
+       else if ((res = g_hash_table_lookup (sighash, (gpointer)arity))) {
+               LeaveCriticalSection (&trampoline_hash_mutex);
+               return res;
+       }
+
+       res = mono_metadata_signature_alloc (mono_defaults.corlib, arity + 1);
+
+       res->pinvoke = 1;
+#ifdef MONO_ARCH_VARARG_ICALLS
+       /* Only set this only some archs since not all backends can handle varargs+pinvoke */
+       res->call_convention = MONO_CALL_VARARG;
+#endif
+
+       res->params [0] = &mono_defaults.int_class->byval_arg;  
+       for (i = 0; i < arity; i++)
+               res->params [i + 1] = &mono_defaults.int_class->byval_arg;
+
+       res->ret = &mono_defaults.int_class->byval_arg;
+
+       g_hash_table_insert (sighash, (gpointer)arity, res);
+       LeaveCriticalSection (&trampoline_hash_mutex);
+
+       return res;
+}
+
 static void
 handle_stobj (MonoCompile *cfg, MonoBasicBlock *bblock, MonoInst *dest, MonoInst *src, const unsigned char *ip, MonoClass *klass, gboolean to_end, gboolean native) {
        MonoInst *iargs [3];
@@ -2186,7 +2295,7 @@ handle_box (MonoCompile *cfg, MonoBasicBlock *bblock, MonoInst *val, const gucha
        }
        NEW_TEMPLOAD (cfg, dest, temp);
        NEW_ICONST (cfg, vtoffset, sizeof (MonoObject));
-       MONO_INST_NEW (cfg, add, CEE_ADD);
+       MONO_INST_NEW (cfg, add, OP_PADD);
        add->inst_left = dest;
        add->inst_right = vtoffset;
        add->cil_code = ip;
@@ -2217,7 +2326,8 @@ mono_method_check_inlining (MonoCompile *cfg, MonoMethod *method)
        int i;
 
 #ifdef MONO_ARCH_HAVE_LMF_OPS
-       if ((method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) &&
+       if (((method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
+                (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)) &&
            !MONO_TYPE_ISSTRUCT (signature->ret) && (method->klass->parent != mono_defaults.array_class))
                return TRUE;
 #endif
@@ -2310,6 +2420,7 @@ mini_get_ldelema_ins (MonoCompile *cfg, MonoBasicBlock *bblock, MonoMethod *cmet
        }
 
        temp = mono_emit_native_call (cfg, bblock, mono_icall_get_wrapper (info), info->sig, sp, ip, FALSE);
+       cfg->flags |= MONO_CFG_HAS_VARARGS;
 
        NEW_TEMPLOAD (cfg, addr, temp);
        return addr;
@@ -2331,6 +2442,11 @@ mini_get_opcode_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSig
 {
        int pc, op;
        MonoInst *ins;
+       
+       static MonoClass *runtime_helpers_class = NULL;
+       if (! runtime_helpers_class)
+               runtime_helpers_class = mono_class_from_name (mono_defaults.corlib,
+                       "System.Runtime.CompilerServices", "RuntimeHelpers");
 
        if (cmethod->klass == mono_defaults.string_class) {
                if (cmethod->name [0] != 'g')
@@ -2353,6 +2469,12 @@ mini_get_opcode_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSig
                        op = CEE_LDLEN;
                else
                        return NULL;
+       } else if (cmethod->klass == runtime_helpers_class) {
+               if (strcmp (cmethod->name, "get_OffsetToStringData") == 0) {
+                       NEW_ICONST (cfg, ins, G_STRUCT_OFFSET (MonoString, chars));
+                       return ins;
+               } else
+                       return NULL;
        } else {
                op = mono_arch_get_opcode_for_method (cfg, cmethod, fsig, args);
                if (op < 0)
@@ -2421,6 +2543,7 @@ inline_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig,
        MonoMethodHeader *cheader;
        MonoBasicBlock *ebblock, *sbblock;
        int i, costs, new_locals_offset;
+       MonoMethod *prev_inlined_method;
 
        if (cfg->verbose_level > 2)
                g_print ("INLINE START %p %s -> %s\n", cmethod,  mono_method_full_name (cfg->method, TRUE), mono_method_full_name (cmethod, TRUE));
@@ -2449,8 +2572,13 @@ inline_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig,
        ebblock->block_num = cfg->num_bblocks++;
        ebblock->real_offset = real_offset;
 
+       prev_inlined_method = cfg->inlined_method;
+       cfg->inlined_method = cmethod;
+
        costs = mono_method_to_ir (cfg, cmethod, sbblock, ebblock, new_locals_offset, rvar, dont_inline, sp, real_offset, *ip == CEE_CALLVIRT);
 
+       cfg->inlined_method = prev_inlined_method;
+
        if ((costs >= 0 && costs < 60) || inline_allways) {
                if (cfg->verbose_level > 2)
                        g_print ("INLINE END %s -> %s\n", mono_method_full_name (cfg->method, TRUE), mono_method_full_name (cmethod, TRUE));
@@ -2527,7 +2655,9 @@ get_basic_blocks (MonoCompile *cfg, GHashTable *bbhash, MonoMethodHeader* header
 
        while (ip < end) {
                cli_addr = ip - start;
-               i = mono_opcode_value ((const guint8 **)&ip);
+               i = mono_opcode_value ((const guint8 **)&ip, end);
+               if (i < 0)
+                       goto unverified;
                opcode = &mono_opcodes [i];
                switch (opcode->argument) {
                case MonoInlineNone:
@@ -3043,7 +3173,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        *sp++ = ins;
                        break;
                case CEE_LDC_R4: {
-                       float *f = g_malloc (sizeof (float));
+                       float *f = mono_mempool_alloc (cfg->domain->mp, sizeof (float));
                        CHECK_OPSIZE (5);
                        CHECK_STACK_OVF (1);
                        MONO_INST_NEW (cfg, ins, OP_R4CONST);
@@ -3056,7 +3186,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        break;
                }
                case CEE_LDC_R8: {
-                       double *d = g_malloc (sizeof (double));
+                       double *d = mono_mempool_alloc (cfg->domain->mp, sizeof (double));
                        CHECK_OPSIZE (9);
                        CHECK_STACK_OVF (1);
                        MONO_INST_NEW (cfg, ins, OP_R8CONST);
@@ -3190,12 +3320,19 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                 * We have the `constrained.' prefix opcode.
                                 */
                                if (constrained_call->valuetype && !cmethod->klass->valuetype) {
+                                       MonoInst *load;
                                        /*
                                         * The type parameter is instantiated as a valuetype,
                                         * but that type doesn't override the method we're
                                         * calling, so we need to box `this'.
+                                        * sp [0] is a pointer to the data: we need the value
+                                        * in handle_box (), so load it here.
                                         */
-                                       sp [0] = handle_box (cfg, bblock, sp [0], ip, constrained_call);
+                                       MONO_INST_NEW (cfg, load, mono_type_to_ldind (&constrained_call->byval_arg));
+                                       type_to_eval_stack_type (&constrained_call->byval_arg, load);
+                                       load->cil_code = ip;
+                                       load->inst_left = sp [0];
+                                       sp [0] = handle_box (cfg, bblock, load, ip, constrained_call);
                                } else if (!constrained_call->valuetype) {
                                        MonoInst *ins;
 
@@ -3272,11 +3409,15 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                 !g_list_find (dont_inline, cmethod)) {
                                int costs;
                                MonoBasicBlock *ebblock;
+                               gboolean allways = FALSE;
 
-                               if (cmethod->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL)
+                               if ((cmethod->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
+                                       (cmethod->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)) {
                                        cmethod = mono_marshal_get_native_wrapper (cmethod);
+                                       allways = TRUE;
+                               }
 
-                               if ((costs = inline_method (cfg, cmethod, fsig, bblock, sp, ip, real_offset, dont_inline, &ebblock, FALSE))) {
+                               if ((costs = inline_method (cfg, cmethod, fsig, bblock, sp, ip, real_offset, dont_inline, &ebblock, allways))) {
                                        ip += 5;
                                        real_offset += 5;
 
@@ -3910,7 +4051,8 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
 
                        if (cmethod->klass->parent == mono_defaults.array_class) {
                                NEW_METHODCONST (cfg, *sp, cmethod);
-                               temp = mono_emit_native_call (cfg, bblock, mono_array_new_va, fsig, sp, ip, FALSE);
+                               temp = mono_emit_native_call (cfg, bblock, mono_array_new_va, mono_get_array_new_va_signature (fsig->param_count), sp, ip, FALSE);
+                               cfg->flags |= MONO_CFG_HAS_VARARGS;
 
                        } else if (cmethod->string_ctor) {
                                /* we simply pass a null pointer */
@@ -4093,7 +4235,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        ins->inst_newa_class = klass;
                        ins->cil_code = ip;
 
-                       MONO_INST_NEW (cfg, add, CEE_ADD);
+                       MONO_INST_NEW (cfg, add, OP_PADD);
                        NEW_ICONST (cfg, vtoffset, sizeof (MonoObject));
                        add->inst_left = ins;
                        add->inst_right = vtoffset;
@@ -4144,7 +4286,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        ins->inst_newa_class = klass;
                        ins->cil_code = ip;
 
-                       MONO_INST_NEW (cfg, add, CEE_ADD);
+                       MONO_INST_NEW (cfg, add, OP_PADD);
                        NEW_ICONST (cfg, vtoffset, sizeof (MonoObject));
                        add->inst_left = ins;
                        add->inst_right = vtoffset;
@@ -4274,7 +4416,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                } else {
                                        MonoInst *store;
                                        NEW_ICONST (cfg, offset_ins, foffset);
-                                       MONO_INST_NEW (cfg, ins, CEE_ADD);
+                                       MONO_INST_NEW (cfg, ins, OP_PADD);
                                        ins->cil_code = ip;
                                        ins->inst_left = *sp;
                                        ins->inst_right = offset_ins;
@@ -4344,7 +4486,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                        }
                                } else {
                                        NEW_ICONST (cfg, offset_ins, foffset);
-                                       MONO_INST_NEW (cfg, ins, CEE_ADD);
+                                       MONO_INST_NEW (cfg, ins, OP_PADD);
                                        ins->cil_code = ip;
                                        ins->inst_left = *sp;
                                        ins->inst_right = offset_ins;
@@ -4644,7 +4786,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        *sp++ = ins;
                        ip += 5;
                        break;
-               case CEE_LDELEM: {
+               case CEE_LDELEM_ANY: {
                        MonoInst *load;
                        CHECK_STACK (2);
                        sp -= 2;
@@ -4720,7 +4862,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        inline_costs += 1;
                        break;
                }
-               case CEE_STELEM: {
+               case CEE_STELEM_ANY: {
                        MonoInst *load;
                        /*
                         * translate to:
@@ -4734,14 +4876,15 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        klass = mono_class_get_full (image, token, generic_context);
                        mono_class_init (klass);
                        if (MONO_TYPE_IS_REFERENCE (&klass->byval_arg)) {
+                               MonoMethod* helper = mono_marshal_get_stelemref ();
                                MonoInst *iargs [3];
                                handle_loaded_temps (cfg, bblock, stack_start, sp);
 
                                iargs [2] = sp [2];
                                iargs [1] = sp [1];
                                iargs [0] = sp [0];
-                       
-                               mono_emit_jit_icall (cfg, bblock, helper_stelem_ref, iargs, ip);
+                               
+                               mono_emit_method_call_spilled (cfg, bblock, helper, helper->signature, iargs, ip, NULL);
                        } else {
                                NEW_LDELEMA (cfg, load, sp, klass);
                                load->cil_code = ip;
@@ -4764,6 +4907,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                }
                case CEE_STELEM_REF: {
                        MonoInst *iargs [3];
+                       MonoMethod* helper = mono_marshal_get_stelemref ();
 
                        CHECK_STACK (3);
                        sp -= 3;
@@ -4774,7 +4918,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        iargs [1] = sp [1];
                        iargs [0] = sp [0];
                        
-                       mono_emit_jit_icall (cfg, bblock, helper_stelem_ref, iargs, ip);
+                       mono_emit_method_call_spilled (cfg, bblock, helper, helper->signature, iargs, ip, NULL);
 
                        /*
                        MonoInst *group;
@@ -5046,158 +5190,30 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        CHECK_OPSIZE (2);
                        switch (ip [1]) {
 
-                       case CEE_MONO_FUNC1: {
+                       case CEE_MONO_ICALL: {
                                int temp;
-                               gpointer func = NULL;
-                               CHECK_STACK (1);
-                               sp--;
-
-                               CHECK_OPSIZE (3);
-                               switch (ip [2]) {
-                               case MONO_MARSHAL_CONV_STR_LPWSTR:
-                                       func = mono_string_to_utf16;
-                                       break;
-                               case MONO_MARSHAL_CONV_LPWSTR_STR:
-                                       func = mono_string_from_utf16;
-                                       break;
-                               case MONO_MARSHAL_CONV_LPSTR_STR:
-                                       func = mono_string_new_wrapper;
-                                       break;
-                               case MONO_MARSHAL_CONV_STR_LPTSTR:
-                               case MONO_MARSHAL_CONV_STR_LPSTR:
-                                       func = mono_string_to_utf8;
-                                       break;
-                               case MONO_MARSHAL_CONV_STR_BSTR:
-                                       func = mono_string_to_bstr;
-                                       break;
-                               case MONO_MARSHAL_CONV_STR_TBSTR:
-                               case MONO_MARSHAL_CONV_STR_ANSIBSTR:
-                                       func = mono_string_to_ansibstr;
-                                       break;
-                               case MONO_MARSHAL_CONV_SB_LPSTR:
-                               case MONO_MARSHAL_CONV_SB_LPTSTR:
-                                       func = mono_string_builder_to_utf8;
-                                       break;
-                               case MONO_MARSHAL_CONV_SB_LPWSTR:
-                                       func = mono_string_builder_to_utf16;
-                                       break;
-                               case MONO_MARSHAL_CONV_ARRAY_SAVEARRAY:
-                                       func = mono_array_to_savearray;
-                                       break;
-                               case MONO_MARSHAL_CONV_ARRAY_LPARRAY:
-                                       func = mono_array_to_lparray;
-                                       break;
-                               case MONO_MARSHAL_CONV_DEL_FTN:
-                                       func = mono_delegate_to_ftnptr;
-                                       break;
-                               case MONO_MARSHAL_CONV_STRARRAY_STRLPARRAY:
-                                       func = mono_marshal_string_array;
-                                       break;
-                               case MONO_MARSHAL_CONV_STRARRAY_STRWLPARRAY:
-                                       func = mono_marshal_string_array_to_unicode;
-                                       break;
-                               default:
-                                       g_warning ("unknown conversion %d\n", ip [2]);
-                                       g_assert_not_reached ();
-                               }
-
-                               temp = mono_emit_jit_icall (cfg, bblock, func, sp, ip);
-                               NEW_TEMPLOAD (cfg, *sp, temp);
-                               sp++;
-
-                               ip += 3;
-                               inline_costs += 10 * num_calls++;
-                               break;
-                       }
-
-                       case CEE_MONO_FUNC2: {
-                               int temp;
-                               gpointer func = NULL;
-                               CHECK_STACK (2);
-                               sp -= 2;
+                               gpointer func;
+                               MonoJitICallInfo *info;
 
-                               CHECK_OPSIZE (3);
-                               switch (ip [2]) {
-                               case MONO_MARSHAL_CONV_ASANY:
-                                       func = mono_marshal_asany;
-                                       break;
-                               case MONO_MARSHAL_CONV_FTN_DEL:
-                                       func = mono_ftnptr_to_delegate;
-                                       break;
-                               default:
-                                       g_warning ("unknown conversion %d\n", ip [2]);
-                                       g_assert_not_reached ();
-                               }
-                               temp = mono_emit_jit_icall (cfg, bblock, func, sp, ip);
-                               NEW_TEMPLOAD (cfg, *sp, temp);
-                               sp++;
-
-                               ip += 3;
-                               inline_costs += 10 * num_calls++;
-                               break;
-                       }
+                               token = read32 (ip + 2);
+                               func = mono_method_get_wrapper_data (method, token);
+                               info = mono_find_jit_icall_by_addr (func);
+                               g_assert (info);
 
-                       case CEE_MONO_PROC2: {
-                               gpointer func = NULL;
-                               CHECK_STACK (2);
-                               sp -= 2;
+                               CHECK_STACK (info->sig->param_count);
+                               sp -= info->sig->param_count;
 
-                               CHECK_OPSIZE (3);
-                               switch (ip [2]) {
-                               case MONO_MARSHAL_CONV_LPSTR_SB:
-                               case MONO_MARSHAL_CONV_LPTSTR_SB:
-                                       func = mono_string_utf8_to_builder;
-                                       break;
-                               case MONO_MARSHAL_CONV_LPWSTR_SB:
-                                       func = mono_string_utf16_to_builder;
-                                       break;
-                               case MONO_MARSHAL_FREE_ARRAY:
-                                       func = mono_marshal_free_array;
-                                       break;
-                               case MONO_MARSHAL_CONV_ASANY:
-                                       func = mono_marshal_asany;
-                                       break;
-                               default:
-                                       g_assert_not_reached ();
+                               temp = mono_emit_jit_icall (cfg, bblock, info->func, sp, ip);
+                               if (!MONO_TYPE_IS_VOID (info->sig->ret)) {
+                                       NEW_TEMPLOAD (cfg, *sp, temp);
+                                       sp++;
                                }
 
-                               mono_emit_jit_icall (cfg, bblock, func, sp, ip);
-                               ip += 3;
+                               ip += 6;
                                inline_costs += 10 * num_calls++;
-                               break;
-                       }
-                       case CEE_MONO_PROC3: {
-                               gpointer func = NULL;
-                               CHECK_STACK (3);
-                               sp -= 3;
-
-                               CHECK_OPSIZE (3);
-                               switch (ip [2]) {
-                               case MONO_MARSHAL_CONV_STR_BYVALSTR:
-                                       func = mono_string_to_byvalstr;
-                                       break;
-                               case MONO_MARSHAL_CONV_STR_BYVALWSTR:
-                                       func = mono_string_to_byvalwstr;
-                                       break;
-                               case MONO_MARSHAL_FREE_ASANY:
-                                       func = mono_marshal_free_asany;
-                                       break;
-                               default:
-                                       g_assert_not_reached ();
-                               }
 
-                               mono_emit_jit_icall (cfg, bblock, func, sp, ip);
-                               ip += 3;
-                               inline_costs += 10 * num_calls++;
                                break;
                        }
-                       case CEE_MONO_FREE:
-                               CHECK_STACK (1);
-                               sp -= 1;
-                               mono_emit_jit_icall (cfg, bblock, g_free, sp, ip);
-                               ip += 2;
-                               inline_costs += 10 * num_calls++;
-                               break;
                        case CEE_MONO_LDPTR:
                                CHECK_STACK_OVF (1);
                                CHECK_OPSIZE (6);
@@ -5357,7 +5373,10 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                cmp->cil_code = ip;
                                type_from_op (cmp);
                                CHECK_TYPE (cmp);
-                               cmp->opcode = OP_COMPARE;
+                               if ((sp [0]->type == STACK_I8) || ((sizeof (gpointer) == 8) && ((sp [0]->type == STACK_PTR) || (sp [0]->type == STACK_OBJ) || (sp [0]->type == STACK_MP))))
+                                       cmp->opcode = OP_LCOMPARE;
+                               else
+                                       cmp->opcode = OP_COMPARE;
                                ins->cil_code = ip;
                                ins->type = STACK_I4;
                                ins->inst_i0 = cmp;
@@ -5507,6 +5526,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                MONO_INST_NEW (cfg, ins, OP_LOCALLOC);
                                ins->inst_left = *sp;
                                ins->cil_code = ip;
+                               ins->type = STACK_MP;
 
                                cfg->flags |= MONO_CFG_HAS_ALLOCA;
                                if (header->init_locals)
@@ -5557,7 +5577,8 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                ip += 2;
                                break;
                        case CEE_TAIL_:
-                               ins_flag |= MONO_INST_TAILCALL;
+                               ins_flag   |= MONO_INST_TAILCALL;
+                               cfg->flags |= MONO_CFG_HAS_TAIL;
                                /* Can't inline tail calls at this time */
                                inline_costs += 100000;
                                ip += 2;
@@ -5929,81 +5950,11 @@ mono_print_tree_nl (MonoInst *tree)
        printf ("\n");
 }
 
-static MonoType*
-type_from_typename (char *typename)
-{
-       MonoClass *klass;
-
-       if (!strcmp (typename, "int"))
-               klass = mono_defaults.int_class;
-       else if (!strcmp (typename, "ptr"))
-               klass = mono_defaults.int_class;
-       else if (!strcmp (typename, "void"))
-               klass = mono_defaults.void_class;
-       else if (!strcmp (typename, "int32"))
-               klass = mono_defaults.int32_class;
-       else if (!strcmp (typename, "uint32"))
-               klass = mono_defaults.uint32_class;
-       else if (!strcmp (typename, "long"))
-               klass = mono_defaults.int64_class;
-       else if (!strcmp (typename, "ulong"))
-               klass = mono_defaults.uint64_class;
-       else if (!strcmp (typename, "float"))
-               klass = mono_defaults.single_class;
-       else if (!strcmp (typename, "double"))
-               klass = mono_defaults.double_class;
-       else if (!strcmp (typename, "object"))
-               klass = mono_defaults.object_class;
-       else {
-               g_error (typename);
-               g_assert_not_reached ();
-       }
-       return &klass->byval_arg;
-}
-
-static MonoMethodSignature*
-make_icall_sig (const char *sigstr)
-{
-       gchar **parts;
-       int i, len;
-       gchar **tmp;
-       MonoMethodSignature *res;
-
-       parts = g_strsplit (sigstr, " ", 256);
-
-       tmp = parts;
-       len = 0;
-       while (*tmp) {
-               len ++;
-               tmp ++;
-       }
-
-       res = mono_metadata_signature_alloc (mono_defaults.corlib, len - 1);
-       res->pinvoke = 1;
-
-#ifdef PLATFORM_WIN32
-       /* 
-        * Under windows, the default pinvoke calling convention is STDCALL but
-        * we need CDECL.
-        */
-       res->call_convention = MONO_CALL_C;
-#endif
-
-       res->ret = type_from_typename (parts [0]);
-       for (i = 1; i < len; ++i) {
-               res->params [i - 1] = type_from_typename (parts [i]);
-       }
-
-       g_strfreev (parts);
-
-       return res;
-}
+#define make_icall_sig mono_create_icall_signature
 
 static void
 create_helper_signature (void)
 {
-
-       /* FIXME: set call conv */
        /* MonoArray * mono_array_new (MonoDomain *domain, MonoClass *klass, gint32 len) */
        helper_sig_newarr = make_icall_sig ("object ptr ptr int32");
 
@@ -6042,6 +5993,10 @@ create_helper_signature (void)
 
        helper_sig_obj_ptr_ptr = make_icall_sig ("object ptr ptr");
 
+       helper_sig_obj_obj_ptr_ptr = make_icall_sig ("object object ptr ptr");
+
+       helper_sig_void_void = make_icall_sig ("void");
+
        /* void amethod (intptr) */
        helper_sig_void_ptr = make_icall_sig ("void ptr");
 
@@ -6051,6 +6006,8 @@ create_helper_signature (void)
        /* void amethod (MonoObject *obj, void *ptr, int i) */
        helper_sig_void_obj_ptr_int = make_icall_sig ("void object ptr int");
 
+       helper_sig_void_obj_ptr_ptr_obj = make_icall_sig ("void object ptr ptr object");
+
        /* intptr amethod (void) */
        helper_sig_ptr_void = make_icall_sig ("ptr");
 
@@ -6114,35 +6071,6 @@ create_helper_signature (void)
        helper_sig_class_init_trampoline = make_icall_sig ("void");
 }
 
-static GHashTable *jit_icall_hash_name = NULL;
-static GHashTable *jit_icall_hash_addr = NULL;
-
-MonoJitICallInfo *
-mono_find_jit_icall_by_name (const char *name)
-{
-       MonoJitICallInfo *info;
-       g_assert (jit_icall_hash_name);
-
-       //printf ("lookup addr %s %p\n", name, g_hash_table_lookup (jit_icall_hash_name, name));
-       EnterCriticalSection (&trampoline_hash_mutex);
-       info = g_hash_table_lookup (jit_icall_hash_name, name);
-       LeaveCriticalSection (&trampoline_hash_mutex);
-       return info;
-}
-
-MonoJitICallInfo *
-mono_find_jit_icall_by_addr (gconstpointer addr)
-{
-       MonoJitICallInfo *info;
-       g_assert (jit_icall_hash_addr);
-
-       EnterCriticalSection (&trampoline_hash_mutex);
-       info = g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
-       LeaveCriticalSection (&trampoline_hash_mutex);
-
-       return info;
-}
-
 gconstpointer
 mono_icall_get_wrapper (MonoJitICallInfo* callinfo)
 {
@@ -6158,56 +6086,16 @@ mono_icall_get_wrapper (MonoJitICallInfo* callinfo)
        /* Must be domain neutral since there is only one copy */
        code = mono_jit_compile_method_with_opt (wrapper, default_opt | MONO_OPT_SHARED);
 
-       EnterCriticalSection (&trampoline_hash_mutex);
        if (!callinfo->wrapper) {
                callinfo->wrapper = code;
-               g_hash_table_insert (jit_icall_hash_addr, (gpointer)callinfo->wrapper, callinfo);
+               mono_register_jit_icall_wrapper (callinfo, code);
+               mono_debug_add_icall_wrapper (wrapper, callinfo);
        }
-       LeaveCriticalSection (&trampoline_hash_mutex);
 
        g_free (name);
        return callinfo->wrapper;
 }
 
-MonoJitICallInfo *
-mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
-{
-       MonoJitICallInfo *info;
-       
-       g_assert (func);
-       g_assert (name);
-
-       EnterCriticalSection (&trampoline_hash_mutex);
-
-       if (!jit_icall_hash_name) {
-               jit_icall_hash_name = g_hash_table_new (g_str_hash, g_str_equal);
-               jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
-       }
-
-       if (g_hash_table_lookup (jit_icall_hash_name, name)) {
-               g_warning ("jit icall already defined \"%s\"\n", name);
-               g_assert_not_reached ();
-       }
-
-       info = g_new (MonoJitICallInfo, 1);
-       
-       info->name = name;
-       info->func = func;
-       info->sig = sig;
-
-       if (is_save) {
-               info->wrapper = func;
-       } else {
-               info->wrapper = NULL;
-       }
-
-       g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
-       g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
-
-       LeaveCriticalSection (&trampoline_hash_mutex);
-       return info;
-}
-
 gpointer
 mono_create_class_init_trampoline (MonoVTable *vtable)
 {
@@ -6270,7 +6158,7 @@ mono_create_jump_trampoline (MonoDomain *domain, MonoMethod *method,
         * trampoline address, so we save it here.
         */
 
-       mono_jit_info_table_add (mono_root_domain, ji);
+       mono_jit_info_table_add (mono_get_root_domain (), ji);
 
        if (!jump_trampoline_hash)
                jump_trampoline_hash = g_hash_table_new (NULL, NULL);
@@ -6401,7 +6289,7 @@ print_dfn (MonoCompile *cfg) {
 
        for (i = 0; i < cfg->num_bblocks; ++i) {
                bb = cfg->bblocks [i];
-               if (bb->cil_code) {
+               /*if (bb->cil_code) {
                        char* code1, *code2;
                        code1 = mono_disasm_code_one (NULL, cfg->method, bb->cil_code, NULL);
                        if (bb->last_ins->cil_code)
@@ -6413,7 +6301,7 @@ print_dfn (MonoCompile *cfg) {
                        code = g_strdup_printf ("%s -> %s", code1, code2);
                        g_free (code1);
                        g_free (code2);
-               } else
+               } else*/
                        code = g_strdup ("\n");
                g_print ("\nBB%d DFN%d (len: %d): %s", bb->block_num, i, bb->cil_length, code);
                if (bb->code) {
@@ -6787,7 +6675,8 @@ dec_foreach (MonoInst *tree, MonoCompile *cfg) {
                                && tree->inst_left->inst_left->type == STACK_I4
                                && (tree->inst_right->opcode == CEE_CONV_I8 
                                        || tree->inst_right->opcode == CEE_CONV_U8)
-                               && tree->inst_right->inst_left->type == STACK_I4) {
+                               && tree->inst_right->inst_left->type == STACK_I4
+                               && tree->inst_left->opcode == tree->inst_right->opcode) {
                        tree->opcode = (tree->inst_left->opcode == CEE_CONV_I8 ? OP_BIGMUL: OP_BIGMUL_UN);
                        tree->inst_left = tree->inst_left->inst_left;
                        tree->inst_right = tree->inst_right->inst_left;
@@ -7036,10 +6925,12 @@ optimize_branches (MonoCompile *cfg)
                                            bbn->code->inst_target_bb->region == bb->region) {
                                                
                                                if (cfg->verbose_level > 2)
-                                                       g_print ("in %s branch to branch triggered %d -> %d\n", cfg->method->name, 
-                                                                bb->block_num, bbn->block_num);
-                                               
-                                               replace_basic_block (bb, bb->out_bb [0], bbn->code->inst_target_bb);
+                                                       g_print ("in %s branch to branch triggered %d -> %d -> %d\n", cfg->method->name, 
+                                                                bb->block_num, bbn->block_num, bbn->code->inst_target_bb->block_num);
+
+                                               replace_in_block (bbn, bb, NULL);
+                                               replace_out_block (bb, bbn, bbn->code->inst_target_bb);
+                                               link_bblock (cfg, bb, bbn->code->inst_target_bb);
                                                bb->last_ins->inst_target_bb = bbn->code->inst_target_bb;
                                                changed = TRUE;
                                                break;
@@ -7219,6 +7110,10 @@ mini_select_instructions (MonoCompile *cfg)
                OP_LBNE_UN, OP_LBLT, OP_LBLE, OP_LBGT, OP_LBGE,
                OP_LBEQ, OP_LBLT_UN, OP_LBLE_UN, OP_LBGT_UN, OP_LBGE_UN
        };
+       static const int reverse_imap [] = {
+               OP_IBNE_UN, OP_IBLT, OP_IBLE, OP_IBGT, OP_IBGE,
+               OP_IBEQ, OP_IBLT_UN, OP_IBLE_UN, OP_IBGT_UN, OP_IBGE_UN
+       };
 
        MonoBasicBlock *bb;
        
@@ -7243,6 +7138,8 @@ mini_select_instructions (MonoCompile *cfg)
                                        bb->last_ins->opcode = reverse_fmap [bb->last_ins->opcode - OP_FBEQ];
                                } else if (bb->last_ins->opcode >= OP_LBEQ && bb->last_ins->opcode <= OP_LBLT_UN) {
                                        bb->last_ins->opcode = reverse_lmap [bb->last_ins->opcode - OP_LBEQ];
+                               } else if (bb->last_ins->opcode >= OP_IBEQ && bb->last_ins->opcode <= OP_IBLT_UN) {
+                                       bb->last_ins->opcode = reverse_imap [bb->last_ins->opcode - OP_IBEQ];
                                }
                        } else {                        
                                MonoInst *inst = mono_mempool_alloc0 (cfg->mempool, sizeof (MonoInst));
@@ -7996,7 +7893,7 @@ mono_jit_compile_method_with_opt (MonoMethod *method, guint32 opt)
        gpointer p;
 
        if (opt & MONO_OPT_SHARED)
-               target_domain = mono_root_domain;
+               target_domain = mono_get_root_domain ();
        else 
                target_domain = domain;
 
@@ -8030,7 +7927,7 @@ mono_jit_find_compiled_method (MonoDomain *domain, MonoMethod *method)
        MonoJitInfo *info;
 
        if (default_opt & MONO_OPT_SHARED)
-               target_domain = mono_root_domain;
+               target_domain = mono_get_root_domain ();
        else 
                target_domain = domain;
 
@@ -8088,7 +7985,11 @@ mono_jit_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObjec
 #ifdef __sparc
 #define GET_CONTEXT \
     void *ctx = context;
-#elif defined(__ppc__) || defined (__powerpc__) || defined (__s390__)
+#elif defined(sun)    // Solaris x86
+#define GET_CONTEXT \
+    ucontext_t *uctx = context; \
+    struct sigcontext *ctx = (struct sigcontext *)&(uctx->uc_mcontext);
+#elif defined(__ppc__) || defined (__powerpc__) || defined (__s390__) || defined (MONO_ARCH_USE_SIGACTION)
 #define GET_CONTEXT \
     void *ctx = context;
 #else
@@ -8318,7 +8219,7 @@ mini_init (const char *filename)
 #endif
        mono_install_stack_walk (mono_jit_walk_stack);
 
-       domain = mono_init (filename);
+       domain = mono_init_from_assembly (filename, filename);
        mono_init_icall ();
 
        mono_add_internal_call ("System.Diagnostics.StackFrame::get_frame_info", 
@@ -8352,6 +8253,9 @@ mini_init (const char *filename)
        mono_register_jit_icall (mono_arch_get_throw_exception_by_name (), "mono_arch_throw_exception_by_name", 
                                 helper_sig_void_ptr, TRUE);
        mono_register_jit_icall (mono_thread_get_pending_exception, "mono_thread_get_pending_exception", helper_sig_obj_void, FALSE);
+       mono_register_jit_icall (mono_thread_interruption_checkpoint, "mono_thread_interruption_checkpoint", helper_sig_void_void, FALSE);
+       mono_register_jit_icall (mono_load_remote_field_new, "mono_load_remote_field_new", helper_sig_obj_obj_ptr_ptr, FALSE);
+       mono_register_jit_icall (mono_store_remote_field_new, "mono_store_remote_field_new", helper_sig_void_obj_ptr_ptr_obj, FALSE);
 
        /* 
         * NOTE, NOTE, NOTE, NOTE:
@@ -8420,28 +8324,6 @@ mini_init (const char *filename)
        mono_register_jit_icall (mono_object_new_fast, "mono_object_new_fast", helper_sig_object_new_specific, FALSE);
        mono_register_jit_icall (mono_array_new, "mono_array_new", helper_sig_newarr, FALSE);
        mono_register_jit_icall (mono_array_new_specific, "mono_array_new_specific", helper_sig_newarr_specific, FALSE);
-       mono_register_jit_icall (mono_string_to_utf16, "mono_string_to_utf16", helper_sig_ptr_obj, FALSE);
-       mono_register_jit_icall (mono_string_from_utf16, "mono_string_from_utf16", helper_sig_obj_ptr, FALSE);
-       mono_register_jit_icall (mono_string_new_wrapper, "mono_string_new_wrapper", helper_sig_obj_ptr, FALSE);
-       mono_register_jit_icall (mono_string_to_utf8, "mono_string_to_utf8", helper_sig_ptr_obj, FALSE);
-       mono_register_jit_icall (mono_string_to_bstr, "mono_string_to_bstr", helper_sig_ptr_obj, FALSE);
-       mono_register_jit_icall (mono_string_to_ansibstr, "mono_string_to_ansibstr", helper_sig_ptr_obj, FALSE);
-       mono_register_jit_icall (mono_string_builder_to_utf8, "mono_string_builder_to_utf8", helper_sig_ptr_obj, FALSE);
-       mono_register_jit_icall (mono_string_builder_to_utf16, "mono_string_builder_to_utf16", helper_sig_ptr_obj, FALSE);
-       mono_register_jit_icall (mono_array_to_savearray, "mono_array_to_savearray", helper_sig_ptr_obj, FALSE);
-       mono_register_jit_icall (mono_array_to_lparray, "mono_array_to_lparray", helper_sig_ptr_obj, FALSE);
-       mono_register_jit_icall (mono_delegate_to_ftnptr, "mono_delegate_to_ftnptr", helper_sig_ptr_obj, FALSE);
-       mono_register_jit_icall (mono_ftnptr_to_delegate, "mono_ftnptr_to_delegate", helper_sig_obj_ptr_ptr, FALSE);
-       mono_register_jit_icall (mono_marshal_string_array, "mono_marshal_string_array", helper_sig_ptr_obj, FALSE);
-       mono_register_jit_icall (mono_marshal_string_array_to_unicode, "mono_marshal_string_array_to_unicode", helper_sig_ptr_obj, FALSE);
-       mono_register_jit_icall (mono_marshal_asany, "mono_marshal_asany", helper_sig_ptr_obj_int, FALSE);
-       mono_register_jit_icall (mono_marshal_free_asany, "mono_marshal_free_asany", helper_sig_void_obj_ptr_int, FALSE);
-       mono_register_jit_icall (mono_string_utf8_to_builder, "mono_string_utf8_to_builder", helper_sig_void_ptr_ptr, FALSE);
-       mono_register_jit_icall (mono_string_utf16_to_builder, "mono_string_utf16_to_builder", helper_sig_void_ptr_ptr, FALSE);
-       mono_register_jit_icall (mono_marshal_free_array, "mono_marshal_free_array", helper_sig_void_ptr_ptr, FALSE);
-       mono_register_jit_icall (mono_string_to_byvalstr, "mono_string_to_byvalstr", helper_sig_void_ptr_ptr_ptr, FALSE);
-       mono_register_jit_icall (mono_string_to_byvalwstr, "mono_string_to_byvalwstr", helper_sig_void_ptr_ptr_ptr, FALSE);
-       mono_register_jit_icall (g_free, "g_free", helper_sig_void_ptr, FALSE);
        mono_register_jit_icall (mono_runtime_class_init, "mono_runtime_class_init", helper_sig_void_ptr, FALSE);
        mono_register_jit_icall (mono_ldftn, "mono_ldftn", helper_sig_compile, FALSE);
        mono_register_jit_icall (mono_ldftn_nosync, "mono_ldftn_nosync", helper_sig_compile, FALSE);
@@ -8533,19 +8415,17 @@ mono_set_defaults (int verbose_level, guint32 opts)
 static void
 mono_precompile_assembly (MonoAssembly *ass, void *user_data)
 {
-       MonoImage *image = ass->image;
-       MonoMethod *method;
+       MonoImage *image = mono_assembly_get_image (ass);
+       MonoMethod *method, *invoke;
        int i, count = 0;
 
        if (mini_verbose > 0)
-               printf ("PRECOMPILE: %s.\n", ass->image->name);
+               printf ("PRECOMPILE: %s.\n", mono_image_get_filename (image));
 
-       for (i = 0; i < image->tables [MONO_TABLE_METHOD].rows; ++i) {
+       for (i = 0; i < mono_image_get_table_rows (image, MONO_TABLE_METHOD); ++i) {
                method = mono_get_method (image, MONO_TOKEN_METHOD_DEF | (i + 1), NULL);
                if (method->flags & METHOD_ATTRIBUTE_ABSTRACT)
                        continue;
-               if (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL)
-                       continue;
 
                count++;
                if (mini_verbose > 1) {
@@ -8554,6 +8434,14 @@ mono_precompile_assembly (MonoAssembly *ass, void *user_data)
                        g_free (desc);
                }
                mono_compile_method (method);
+               if (strcmp (method->name, "Finalize") == 0) {
+                       invoke = mono_marshal_get_runtime_invoke (method);
+                       mono_compile_method (invoke);
+               }
+               if (method->klass->marshalbyref && method->signature->hasthis) {
+                       invoke = mono_marshal_get_remoting_invoke_with_check (method);
+                       mono_compile_method (invoke);
+               }
        }
 }