[jit] refactor basic block ordering in separate function
[mono.git] / mono / mini / mini.c
index fa3bb6bc4cb329ca05511b7b1d38933ab5ca96eb..850d2d68e45bfbe76c051e087833729d876a5441 100644 (file)
@@ -83,8 +83,8 @@ int mono_break_at_bb_bb_num;
 gboolean mono_do_x86_stack_align = TRUE;
 gboolean mono_using_xdebug;
 
-#define mono_jit_lock() mono_mutex_lock (&jit_mutex)
-#define mono_jit_unlock() mono_mutex_unlock (&jit_mutex)
+#define mono_jit_lock() mono_os_mutex_lock (&jit_mutex)
+#define mono_jit_unlock() mono_os_mutex_unlock (&jit_mutex)
 static mono_mutex_t jit_mutex;
 
 MonoBackend *current_backend;
@@ -214,8 +214,8 @@ typedef struct MonoJumpTableChunk {
 } MonoJumpTableChunk;
 
 static MonoJumpTableChunk* g_jumptable;
-#define mono_jumptable_lock() mono_mutex_lock (&jumptable_mutex)
-#define mono_jumptable_unlock() mono_mutex_unlock (&jumptable_mutex)
+#define mono_jumptable_lock() mono_os_mutex_lock (&jumptable_mutex)
+#define mono_jumptable_unlock() mono_os_mutex_unlock (&jumptable_mutex)
 static mono_mutex_t jumptable_mutex;
 
 static  MonoJumpTableChunk*
@@ -231,7 +231,7 @@ void
 mono_jumptable_init (void)
 {
        if (g_jumptable == NULL) {
-               mono_mutex_init_recursive (&jumptable_mutex);
+               mono_os_mutex_init_recursive (&jumptable_mutex);
                g_jumptable = mono_create_jumptable_chunk (DEFAULT_JUMPTABLE_CHUNK_ELEMENTS);
        }
 }
@@ -287,7 +287,7 @@ mono_jumptable_cleanup (void)
                        current = prev;
                }
                g_jumptable = NULL;
-               mono_mutex_destroy (&jumptable_mutex);
+               mono_os_mutex_destroy (&jumptable_mutex);
        }
 }
 
@@ -314,7 +314,7 @@ typedef struct {
 void
 mono_emit_unwind_op (MonoCompile *cfg, int when, int tag, int reg, int val)
 {
-       MonoUnwindOp *op = mono_mempool_alloc0 (cfg->mempool, sizeof (MonoUnwindOp));
+       MonoUnwindOp *op = (MonoUnwindOp *)mono_mempool_alloc0 (cfg->mempool, sizeof (MonoUnwindOp));
 
        op->op = tag;
        op->reg = reg;
@@ -465,7 +465,7 @@ mono_find_spvar_for_region (MonoCompile *cfg, int region)
 {
        region = mono_get_block_region_notry (cfg, region);
 
-       return g_hash_table_lookup (cfg->spvars, GINT_TO_POINTER (region));
+       return (MonoInst *)g_hash_table_lookup (cfg->spvars, GINT_TO_POINTER (region));
 }
 
 static void
@@ -666,6 +666,8 @@ mono_op_imm_to_op (int opcode)
                return OP_LSUB;
        case OP_IMUL_IMM:
                return OP_IMUL;
+       case OP_LMUL_IMM:
+               return OP_LMUL;
        case OP_AND_IMM:
 #if SIZEOF_REGISTER == 4
                return OP_IAND;
@@ -710,10 +712,16 @@ mono_op_imm_to_op (int opcode)
                return OP_LSHR_UN;
        case OP_IDIV_IMM:
                return OP_IDIV;
+       case OP_LDIV_IMM:
+               return OP_LDIV;
        case OP_IDIV_UN_IMM:
                return OP_IDIV_UN;
+       case OP_LDIV_UN_IMM:
+               return OP_LDIV_UN;
        case OP_IREM_UN_IMM:
                return OP_IREM_UN;
+       case OP_LREM_UN_IMM:
+               return OP_LREM_UN;
        case OP_IREM_IMM:
                return OP_IREM;
        case OP_LREM_IMM:
@@ -748,11 +756,9 @@ mono_op_imm_to_op (int opcode)
                return OP_ICOMPARE;
        case OP_LOCALLOC_IMM:
                return OP_LOCALLOC;
-       default:
-               printf ("%s\n", mono_inst_name (opcode));
-               g_assert_not_reached ();
-               return -1;
        }
+
+       return -1;
 }
 
 /*
@@ -763,17 +769,41 @@ mono_op_imm_to_op (int opcode)
 void
 mono_decompose_op_imm (MonoCompile *cfg, MonoBasicBlock *bb, MonoInst *ins)
 {
+       int opcode2 = mono_op_imm_to_op (ins->opcode);
        MonoInst *temp;
+       guint32 dreg;
+       const char *spec = INS_INFO (ins->opcode);
+
+       if (spec [MONO_INST_SRC2] == 'l') {
+               dreg = mono_alloc_lreg (cfg);
+
+               /* Load the 64bit constant using decomposed ops */
+               MONO_INST_NEW (cfg, temp, OP_ICONST);
+               temp->inst_c0 = ins->inst_ls_word;
+               temp->dreg = MONO_LVREG_LS (dreg);
+               mono_bblock_insert_before_ins (bb, ins, temp);
+
+               MONO_INST_NEW (cfg, temp, OP_ICONST);
+               temp->inst_c0 = ins->inst_ms_word;
+               temp->dreg = MONO_LVREG_MS (dreg);
+       } else {
+               dreg = mono_alloc_ireg (cfg);
+
+               MONO_INST_NEW (cfg, temp, OP_ICONST);
+               temp->inst_c0 = ins->inst_imm;
+               temp->dreg = dreg;
+       }
 
-       MONO_INST_NEW (cfg, temp, OP_ICONST);
-       temp->inst_c0 = ins->inst_imm;
-       temp->dreg = mono_alloc_ireg (cfg);
        mono_bblock_insert_before_ins (bb, ins, temp);
-       ins->opcode = mono_op_imm_to_op (ins->opcode);
+
+       if (opcode2 == -1)
+                g_error ("mono_op_imm_to_op failed for %s\n", mono_inst_name (ins->opcode));
+       ins->opcode = opcode2;
+
        if (ins->opcode == OP_LOCALLOC)
-               ins->sreg1 = temp->dreg;
+               ins->sreg1 = dreg;
        else
-               ins->sreg2 = temp->dreg;
+               ins->sreg2 = dreg;
 
        bb->max_vreg = MAX (bb->max_vreg, cfg->next_vreg);
 }
@@ -787,7 +817,7 @@ set_vreg_to_inst (MonoCompile *cfg, int vreg, MonoInst *inst)
 
                while (vreg >= cfg->vreg_to_inst_len)
                        cfg->vreg_to_inst_len = cfg->vreg_to_inst_len ? cfg->vreg_to_inst_len * 2 : 32;
-               cfg->vreg_to_inst = mono_mempool_alloc0 (cfg->mempool, sizeof (MonoInst*) * cfg->vreg_to_inst_len);
+               cfg->vreg_to_inst = (MonoInst **)mono_mempool_alloc0 (cfg->mempool, sizeof (MonoInst*) * cfg->vreg_to_inst_len);
                if (size)
                        memcpy (cfg->vreg_to_inst, tmp, size * sizeof (MonoInst*));
        }
@@ -870,7 +900,7 @@ mono_compile_create_var_for_vreg (MonoCompile *cfg, MonoType *type, int opcode,
                 */
 
                if (cfg->verbose_level >= 4) {
-                       printf ("  Create LVAR R%d (R%d, R%d)\n", inst->dreg, inst->dreg + 1, inst->dreg + 2);
+                       printf ("  Create LVAR R%d (R%d, R%d)\n", inst->dreg, MONO_LVREG_LS (inst->dreg), MONO_LVREG_MS (inst->dreg));
                }
 
                if (mono_arch_is_soft_float () && cfg->opt & MONO_OPT_SSA) {
@@ -880,7 +910,7 @@ mono_compile_create_var_for_vreg (MonoCompile *cfg, MonoType *type, int opcode,
 
                /* Allocate a dummy MonoInst for the first vreg */
                MONO_INST_NEW (cfg, tree, OP_LOCAL);
-               tree->dreg = inst->dreg + 1;
+               tree->dreg = MONO_LVREG_LS (inst->dreg);
                if (cfg->opt & MONO_OPT_SSA)
                        tree->flags = MONO_INST_VOLATILE;
                tree->inst_c0 = num;
@@ -888,11 +918,11 @@ mono_compile_create_var_for_vreg (MonoCompile *cfg, MonoType *type, int opcode,
                tree->inst_vtype = &mono_defaults.int32_class->byval_arg;
                tree->klass = mono_class_from_mono_type (tree->inst_vtype);
 
-               set_vreg_to_inst (cfg, inst->dreg + 1, tree);
+               set_vreg_to_inst (cfg, MONO_LVREG_LS (inst->dreg), tree);
 
                /* Allocate a dummy MonoInst for the second vreg */
                MONO_INST_NEW (cfg, tree, OP_LOCAL);
-               tree->dreg = inst->dreg + 2;
+               tree->dreg = MONO_LVREG_MS (inst->dreg);
                if (cfg->opt & MONO_OPT_SSA)
                        tree->flags = MONO_INST_VOLATILE;
                tree->inst_c0 = num;
@@ -900,7 +930,7 @@ mono_compile_create_var_for_vreg (MonoCompile *cfg, MonoType *type, int opcode,
                tree->inst_vtype = &mono_defaults.int32_class->byval_arg;
                tree->klass = mono_class_from_mono_type (tree->inst_vtype);
 
-               set_vreg_to_inst (cfg, inst->dreg + 2, tree);
+               set_vreg_to_inst (cfg, MONO_LVREG_MS (inst->dreg), tree);
        }
 
        cfg->num_varinfo++;
@@ -949,7 +979,7 @@ mono_mark_vreg_as_ref (MonoCompile *cfg, int vreg)
 
                while (vreg >= cfg->vreg_is_ref_len)
                        cfg->vreg_is_ref_len = cfg->vreg_is_ref_len ? cfg->vreg_is_ref_len * 2 : 32;
-               cfg->vreg_is_ref = mono_mempool_alloc0 (cfg->mempool, sizeof (gboolean) * cfg->vreg_is_ref_len);
+               cfg->vreg_is_ref = (gboolean *)mono_mempool_alloc0 (cfg->mempool, sizeof (gboolean) * cfg->vreg_is_ref_len);
                if (size)
                        memcpy (cfg->vreg_is_ref, tmp, size * sizeof (gboolean));
        }
@@ -965,7 +995,7 @@ mono_mark_vreg_as_mp (MonoCompile *cfg, int vreg)
 
                while (vreg >= cfg->vreg_is_mp_len)
                        cfg->vreg_is_mp_len = cfg->vreg_is_mp_len ? cfg->vreg_is_mp_len * 2 : 32;
-               cfg->vreg_is_mp = mono_mempool_alloc0 (cfg->mempool, sizeof (gboolean) * cfg->vreg_is_mp_len);
+               cfg->vreg_is_mp = (gboolean *)mono_mempool_alloc0 (cfg->mempool, sizeof (gboolean) * cfg->vreg_is_mp_len);
                if (size)
                        memcpy (cfg->vreg_is_mp, tmp, size * sizeof (gboolean));
        }
@@ -1079,10 +1109,10 @@ mono_add_ins_to_end (MonoBasicBlock *bb, MonoInst *inst)
 void
 mono_create_jump_table (MonoCompile *cfg, MonoInst *label, MonoBasicBlock **bbs, int num_blocks)
 {
-       MonoJumpInfo *ji = mono_mempool_alloc (cfg->mempool, sizeof (MonoJumpInfo));
+       MonoJumpInfo *ji = (MonoJumpInfo *)mono_mempool_alloc (cfg->mempool, sizeof (MonoJumpInfo));
        MonoJumpInfoBBTable *table;
 
-       table = mono_mempool_alloc (cfg->mempool, sizeof (MonoJumpInfoBBTable));
+       table = (MonoJumpInfoBBTable *)mono_mempool_alloc (cfg->mempool, sizeof (MonoJumpInfoBBTable));
        table->table = bbs;
        table->table_size = num_blocks;
        
@@ -1104,7 +1134,7 @@ mono_get_array_new_va_signature (int arity)
        if (!sighash) {
                sighash = g_hash_table_new (NULL, NULL);
        }
-       else if ((res = g_hash_table_lookup (sighash, GINT_TO_POINTER (arity)))) {
+       else if ((res = (MonoMethodSignature *)g_hash_table_lookup (sighash, GINT_TO_POINTER (arity)))) {
                mono_jit_unlock ();
                return res;
        }
@@ -1178,7 +1208,7 @@ mini_assembly_can_skip_verification (MonoDomain *domain, MonoMethod *method)
 /*
  * mini_method_verify:
  * 
- * Verify the method using the new verfier.
+ * Verify the method using the verfier.
  * 
  * Returns true if the method is invalid. 
  */
@@ -1187,7 +1217,6 @@ mini_method_verify (MonoCompile *cfg, MonoMethod *method, gboolean fail_compile)
 {
        GSList *tmp, *res;
        gboolean is_fulltrust;
-       MonoLoaderError *error;
 
        if (method->verification_success)
                return FALSE;
@@ -1200,11 +1229,13 @@ mini_method_verify (MonoCompile *cfg, MonoMethod *method, gboolean fail_compile)
 
        res = mono_method_verify_with_current_settings (method, cfg->skip_visibility, is_fulltrust);
 
-       if ((error = mono_loader_get_last_error ())) {
-               if (fail_compile)
-                       cfg->exception_type = error->exception_type;
-               else
+       if (mono_loader_get_last_error ()) {
+               if (fail_compile) {
+                       mono_cfg_set_exception (cfg, MONO_EXCEPTION_MONO_ERROR);
+                       mono_error_set_from_loader_error (&cfg->error);
+               } else {
                        mono_loader_clear_error ();
+               }
                if (res)
                        mono_free_verify_list (res);
                return TRUE;
@@ -1226,8 +1257,21 @@ mini_method_verify (MonoCompile *cfg, MonoMethod *method, gboolean fail_compile)
                        if (info->info.status == MONO_VERIFY_NOT_VERIFIABLE && (!is_fulltrust || info->exception_type == MONO_EXCEPTION_METHOD_ACCESS || info->exception_type == MONO_EXCEPTION_FIELD_ACCESS)) {
                                if (fail_compile) {
                                        char *method_name = mono_method_full_name (method, TRUE);
-                                       cfg->exception_type = info->exception_type;
-                                       cfg->exception_message = g_strdup_printf ("Error verifying %s: %s", method_name, info->info.message);
+                                       char *msg = g_strdup_printf ("Error verifying %s: %s", method_name, info->info.message);
+
+                                       if (info->exception_type == MONO_EXCEPTION_METHOD_ACCESS)
+                                               mono_error_set_generic_error (&cfg->error, "System", "MethodAccessException", "%s", msg);
+                                       else if (info->exception_type == info->exception_type == MONO_EXCEPTION_FIELD_ACCESS)
+                                               mono_error_set_generic_error (&cfg->error, "System", "FieldAccessException", "%s", msg);
+                                       else if (info->exception_type == MONO_EXCEPTION_UNVERIFIABLE_IL)
+                                               mono_error_set_generic_error (&cfg->error, "System.Security", "VerificationException", msg);
+                                       if (!mono_error_ok (&cfg->error)) {
+                                               mono_cfg_set_exception (cfg, MONO_EXCEPTION_MONO_ERROR);
+                                               g_free (msg);
+                                       } else {
+                                               cfg->exception_type = info->exception_type;
+                                               cfg->exception_message = msg;
+                                       }
                                        g_free (method_name);
                                }
                                mono_free_verify_list (res);
@@ -1269,7 +1313,7 @@ mono_dynamic_code_hash_lookup (MonoDomain *domain, MonoMethod *method)
        MonoJitDynamicMethodInfo *res;
 
        if (domain_jit_info (domain)->dynamic_code_hash)
-               res = g_hash_table_lookup (domain_jit_info (domain)->dynamic_code_hash, method);
+               res = (MonoJitDynamicMethodInfo *)g_hash_table_lookup (domain_jit_info (domain)->dynamic_code_hash, method);
        else
                res = NULL;
        return res;
@@ -1319,11 +1363,11 @@ mono_allocate_stack_slots2 (MonoCompile *cfg, gboolean backward, guint32 *stack_
 
        LSCAN_DEBUG (printf ("Allocate Stack Slots 2 for %s:\n", mono_method_full_name (cfg->method, TRUE)));
 
-       scalar_stack_slots = mono_mempool_alloc0 (cfg->mempool, sizeof (StackSlotInfo) * MONO_TYPE_PINNED);
+       scalar_stack_slots = (StackSlotInfo *)mono_mempool_alloc0 (cfg->mempool, sizeof (StackSlotInfo) * MONO_TYPE_PINNED);
        vtype_stack_slots = NULL;
        nvtypes = 0;
 
-       offsets = mono_mempool_alloc (cfg->mempool, sizeof (gint32) * cfg->num_varinfo);
+       offsets = (gint32 *)mono_mempool_alloc (cfg->mempool, sizeof (gint32) * cfg->num_varinfo);
        for (i = 0; i < cfg->num_varinfo; ++i)
                offsets [i] = -1;
 
@@ -1355,7 +1399,7 @@ mono_allocate_stack_slots2 (MonoCompile *cfg, gboolean backward, guint32 *stack_
        offset = 0;
        *stack_align = 0;
        for (unhandled = vars; unhandled; unhandled = unhandled->next) {
-               MonoMethodVar *current = unhandled->data;
+               MonoMethodVar *current = (MonoMethodVar *)unhandled->data;
 
                vmv = current;
                inst = cfg->varinfo [vmv->idx];
@@ -1393,7 +1437,7 @@ mono_allocate_stack_slots2 (MonoCompile *cfg, gboolean backward, guint32 *stack_
                        /* Fall through */
                case MONO_TYPE_VALUETYPE:
                        if (!vtype_stack_slots)
-                               vtype_stack_slots = mono_mempool_alloc0 (cfg->mempool, sizeof (StackSlotInfo) * 256);
+                               vtype_stack_slots = (StackSlotInfo *)mono_mempool_alloc0 (cfg->mempool, sizeof (StackSlotInfo) * 256);
                        for (i = 0; i < nvtypes; ++i)
                                if (t->data.klass == vtype_stack_slots [i].vtype)
                                        break;
@@ -1632,11 +1676,11 @@ mono_allocate_stack_slots (MonoCompile *cfg, gboolean backward, guint32 *stack_s
        if ((cfg->num_varinfo > 0) && MONO_VARINFO (cfg, 0)->interval)
                return mono_allocate_stack_slots2 (cfg, backward, stack_size, stack_align);
 
-       scalar_stack_slots = mono_mempool_alloc0 (cfg->mempool, sizeof (StackSlotInfo) * MONO_TYPE_PINNED);
+       scalar_stack_slots = (StackSlotInfo *)mono_mempool_alloc0 (cfg->mempool, sizeof (StackSlotInfo) * MONO_TYPE_PINNED);
        vtype_stack_slots = NULL;
        nvtypes = 0;
 
-       offsets = mono_mempool_alloc (cfg->mempool, sizeof (gint32) * cfg->num_varinfo);
+       offsets = (gint32 *)mono_mempool_alloc (cfg->mempool, sizeof (gint32) * cfg->num_varinfo);
        for (i = 0; i < cfg->num_varinfo; ++i)
                offsets [i] = -1;
 
@@ -1654,7 +1698,7 @@ mono_allocate_stack_slots (MonoCompile *cfg, gboolean backward, guint32 *stack_s
        offset = 0;
        *stack_align = sizeof(mgreg_t);
        for (l = vars; l; l = l->next) {
-               vmv = l->data;
+               vmv = (MonoMethodVar *)l->data;
                inst = cfg->varinfo [vmv->idx];
 
                t = mono_type_get_underlying_type (inst->inst_vtype);
@@ -1692,7 +1736,7 @@ mono_allocate_stack_slots (MonoCompile *cfg, gboolean backward, guint32 *stack_s
                        /* Fall through */
                case MONO_TYPE_VALUETYPE:
                        if (!vtype_stack_slots)
-                               vtype_stack_slots = mono_mempool_alloc0 (cfg->mempool, sizeof (StackSlotInfo) * 256);
+                               vtype_stack_slots = (StackSlotInfo *)mono_mempool_alloc0 (cfg->mempool, sizeof (StackSlotInfo) * 256);
                        for (i = 0; i < nvtypes; ++i)
                                if (t->data.klass == vtype_stack_slots [i].vtype)
                                        break;
@@ -1893,8 +1937,8 @@ mini_register_opcode_emulation (int opcode, const char *name, const char *sigstr
        if (emul_opcode_num >= emul_opcode_alloced) {
                int incr = emul_opcode_alloced? emul_opcode_alloced/2: 16;
                emul_opcode_alloced += incr;
-               emul_opcode_map = g_realloc (emul_opcode_map, sizeof (emul_opcode_map [0]) * emul_opcode_alloced);
-               emul_opcode_opcodes = g_realloc (emul_opcode_opcodes, sizeof (emul_opcode_opcodes [0]) * emul_opcode_alloced);
+               emul_opcode_map = (MonoJitICallInfo **)g_realloc (emul_opcode_map, sizeof (emul_opcode_map [0]) * emul_opcode_alloced);
+               emul_opcode_opcodes = (short *)g_realloc (emul_opcode_opcodes, sizeof (emul_opcode_opcodes [0]) * emul_opcode_alloced);
        }
        emul_opcode_map [emul_opcode_num] = info;
        emul_opcode_opcodes [emul_opcode_num] = opcode;
@@ -2070,7 +2114,7 @@ mono_destroy_compile (MonoCompile *cfg)
        if (cfg->exvars)
                g_hash_table_destroy (cfg->exvars);
        for (l = cfg->headers_to_free; l; l = l->next)
-               mono_metadata_free_mh (l->data);
+               mono_metadata_free_mh ((MonoMethodHeader *)l->data);
        g_list_free (cfg->ldstr_list);
        g_hash_table_destroy (cfg->token_info_hash);
        if (cfg->abs_patches)
@@ -2174,7 +2218,7 @@ mono_get_lmf_addr_intrinsic (MonoCompile* cfg)
 void
 mono_add_patch_info (MonoCompile *cfg, int ip, MonoJumpInfoType type, gconstpointer target)
 {
-       MonoJumpInfo *ji = mono_mempool_alloc0 (cfg->mempool, sizeof (MonoJumpInfo));
+       MonoJumpInfo *ji = (MonoJumpInfo *)mono_mempool_alloc0 (cfg->mempool, sizeof (MonoJumpInfo));
 
        ji->ip.i = ip;
        ji->type = type;
@@ -2187,7 +2231,7 @@ mono_add_patch_info (MonoCompile *cfg, int ip, MonoJumpInfoType type, gconstpoin
 void
 mono_add_patch_info_rel (MonoCompile *cfg, int ip, MonoJumpInfoType type, gconstpointer target, int relocation)
 {
-       MonoJumpInfo *ji = mono_mempool_alloc0 (cfg->mempool, sizeof (MonoJumpInfo));
+       MonoJumpInfo *ji = (MonoJumpInfo *)mono_mempool_alloc0 (cfg->mempool, sizeof (MonoJumpInfo));
 
        ji->ip.i = ip;
        ji->type = type;
@@ -2225,7 +2269,7 @@ mono_add_seq_point (MonoCompile *cfg, MonoBasicBlock *bb, MonoInst *ins, int nat
 void
 mono_add_var_location (MonoCompile *cfg, MonoInst *var, gboolean is_reg, int reg, int offset, int from, int to)
 {
-       MonoDwarfLocListEntry *entry = mono_mempool_alloc0 (cfg->mempool, sizeof (MonoDwarfLocListEntry));
+       MonoDwarfLocListEntry *entry = (MonoDwarfLocListEntry *)mono_mempool_alloc0 (cfg->mempool, sizeof (MonoDwarfLocListEntry));
 
        if (is_reg)
                g_assert (offset == 0);
@@ -2261,7 +2305,7 @@ mono_compile_create_vars (MonoCompile *cfg)
        if (cfg->verbose_level > 2)
                g_print ("creating vars\n");
 
-       cfg->args = mono_mempool_alloc0 (cfg->mempool, (sig->param_count + sig->hasthis) * sizeof (MonoInst*));
+       cfg->args = (MonoInst **)mono_mempool_alloc0 (cfg->mempool, (sig->param_count + sig->hasthis) * sizeof (MonoInst*));
 
        if (sig->hasthis)
                cfg->args [0] = mono_compile_create_var (cfg, &cfg->method->klass->this_arg, OP_ARG);
@@ -2288,7 +2332,7 @@ mono_compile_create_vars (MonoCompile *cfg)
        }
 
        cfg->locals_start = cfg->num_varinfo;
-       cfg->locals = mono_mempool_alloc0 (cfg->mempool, header->num_locals * sizeof (MonoInst*));
+       cfg->locals = (MonoInst **)mono_mempool_alloc0 (cfg->mempool, header->num_locals * sizeof (MonoInst*));
 
        if (cfg->verbose_level > 2)
                g_print ("creating locals\n");
@@ -2299,7 +2343,14 @@ mono_compile_create_vars (MonoCompile *cfg)
        if (cfg->verbose_level > 2)
                g_print ("locals done\n");
 
+#ifdef ENABLE_LLVM
+       if (COMPILE_LLVM (cfg))
+               mono_llvm_create_vars (cfg);
+       else
+               mono_arch_create_vars (cfg);
+#else
        mono_arch_create_vars (cfg);
+#endif
 
        if (cfg->method->save_lmf && cfg->create_lmf_var) {
                MonoInst *lmf_var = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_LOCAL);
@@ -2348,7 +2399,7 @@ mono_postprocess_patches (MonoCompile *cfg)
 
                        if (patch_info->type == MONO_PATCH_INFO_ABS) {
                                if (cfg->abs_patches) {
-                                       MonoJumpInfo *abs_ji = g_hash_table_lookup (cfg->abs_patches, patch_info->data.target);
+                                       MonoJumpInfo *abs_ji = (MonoJumpInfo *)g_hash_table_lookup (cfg->abs_patches, patch_info->data.target);
                                        if (abs_ji) {
                                                patch_info->type = abs_ji->type;
                                                patch_info->data.target = abs_ji->data.target;
@@ -2367,9 +2418,9 @@ mono_postprocess_patches (MonoCompile *cfg)
                        table = g_malloc0 (sizeof(gpointer) * patch_info->data.table->table_size);
 #else
                        if (cfg->method->dynamic) {
-                               table = mono_code_manager_reserve (cfg->dynamic_info->code_mp, sizeof (gpointer) * patch_info->data.table->table_size);
+                               table = (void **)mono_code_manager_reserve (cfg->dynamic_info->code_mp, sizeof (gpointer) * patch_info->data.table->table_size);
                        } else {
-                               table = mono_domain_code_reserve (cfg->domain, sizeof (gpointer) * patch_info->data.table->table_size);
+                               table = (void **)mono_domain_code_reserve (cfg->domain, sizeof (gpointer) * patch_info->data.table->table_size);
                        }
 #endif
 
@@ -2397,9 +2448,9 @@ mono_postprocess_patches (MonoCompile *cfg)
 #endif
 
                        mono_domain_lock (domain);
-                       jlist = g_hash_table_lookup (domain_jit_info (domain)->jump_target_hash, patch_info->data.method);
+                       jlist = (MonoJumpList *)g_hash_table_lookup (domain_jit_info (domain)->jump_target_hash, patch_info->data.method);
                        if (!jlist) {
-                               jlist = mono_domain_alloc0 (domain, sizeof (MonoJumpList));
+                               jlist = (MonoJumpList *)mono_domain_alloc0 (domain, sizeof (MonoJumpList));
                                g_hash_table_insert (domain_jit_info (domain)->jump_target_hash, patch_info->data.method, jlist);
                        }
                        jlist->list = g_slist_prepend (jlist->list, ip);
@@ -2515,11 +2566,11 @@ mono_codegen (MonoCompile *cfg)
 
                if (mono_using_xdebug)
                        /* See the comment for cfg->code_domain */
-                       code = mono_domain_code_reserve (code_domain, cfg->code_size + cfg->thunk_area + unwindlen);
+                       code = (guint8 *)mono_domain_code_reserve (code_domain, cfg->code_size + cfg->thunk_area + unwindlen);
                else
-                       code = mono_code_manager_reserve (cfg->dynamic_info->code_mp, cfg->code_size + cfg->thunk_area + unwindlen);
+                       code = (guint8 *)mono_code_manager_reserve (cfg->dynamic_info->code_mp, cfg->code_size + cfg->thunk_area + unwindlen);
        } else {
-               code = mono_domain_code_reserve (code_domain, cfg->code_size + cfg->thunk_area + unwindlen);
+               code = (guint8 *)mono_domain_code_reserve (code_domain, cfg->code_size + cfg->thunk_area + unwindlen);
        }
 #if defined(__native_client_codegen__) && defined(__native_client__)
        nacl_allow_target_modification (TRUE);
@@ -2558,11 +2609,14 @@ mono_codegen (MonoCompile *cfg)
 #endif
  
        if (cfg->verbose_level > 0) {
-               char* nm = mono_method_full_name (cfg->method, TRUE);
-               g_print ("Method %s emitted at %p to %p (code length %d) [%s]\n", 
+               char* nm = mono_method_get_full_name (cfg->method);
+               char *opt_descr = mono_opt_descr (cfg->opt);
+               g_print ("Method %s emitted at %p to %p (code length %d) [%s] with opts %s\n", 
                                 nm, 
-                                cfg->native_code, cfg->native_code + cfg->code_len, cfg->code_len, cfg->domain->friendly_name);
+                                cfg->native_code, cfg->native_code + cfg->code_len, cfg->code_len, cfg->domain->friendly_name,
+                                opt_descr);
                g_free (nm);
+               g_free (opt_descr);
        }
 
        {
@@ -2657,6 +2711,42 @@ compute_reachable (MonoBasicBlock *bb)
        }
 }
 
+static void mono_bb_ordering (MonoCompile *cfg)
+{
+       int dfn = 0;
+       /* Depth-first ordering on basic blocks */
+       cfg->bblocks = (MonoBasicBlock **)mono_mempool_alloc (cfg->mempool, sizeof (MonoBasicBlock*) * (cfg->num_bblocks + 1));
+
+       cfg->max_block_num = cfg->num_bblocks;
+
+       df_visit (cfg->bb_entry, &dfn, cfg->bblocks);
+       if (cfg->num_bblocks != dfn + 1) {
+               MonoBasicBlock *bb;
+
+               cfg->num_bblocks = dfn + 1;
+
+               /* remove unreachable code, because the code in them may be 
+                * inconsistent  (access to dead variables for example) */
+               for (bb = cfg->bb_entry; bb; bb = bb->next_bb)
+                       bb->flags &= ~BB_VISITED;
+               compute_reachable (cfg->bb_entry);
+               for (bb = cfg->bb_entry; bb; bb = bb->next_bb)
+                       if (bb->flags & BB_EXCEPTION_HANDLER)
+                               compute_reachable (bb);
+               for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
+                       if (!(bb->flags & BB_VISITED)) {
+                               if (cfg->verbose_level > 1)
+                                       g_print ("found unreachable code in BB%d\n", bb->block_num);
+                               bb->code = bb->last_ins = NULL;
+                               while (bb->out_count)
+                                       mono_unlink_bblock (cfg, bb, bb->out_bb [0]);
+                       }
+               }
+               for (bb = cfg->bb_entry; bb; bb = bb->next_bb)
+                       bb->flags &= ~BB_VISITED;
+       }
+}
+
 static void
 mono_handle_out_of_line_bblock (MonoCompile *cfg)
 {
@@ -2685,7 +2775,7 @@ create_jit_info (MonoCompile *cfg, MonoMethod *method_to_compile)
        header = cfg->header;
 
        if (cfg->gshared)
-               flags |= JIT_INFO_HAS_GENERIC_JIT_INFO;
+               flags = (MonoJitInfoFlags)(flags | JIT_INFO_HAS_GENERIC_JIT_INFO);
 
        if (cfg->arch_eh_jit_info) {
                MonoJitArgumentInfo *arg_info;
@@ -2699,18 +2789,18 @@ create_jit_info (MonoCompile *cfg, MonoMethod *method_to_compile)
                stack_size = mono_arch_get_argument_info (sig, sig->param_count, arg_info);
 
                if (stack_size)
-                       flags |= JIT_INFO_HAS_ARCH_EH_INFO;
+                       flags = (MonoJitInfoFlags)(flags | JIT_INFO_HAS_ARCH_EH_INFO);
        }
 
        if (cfg->has_unwind_info_for_epilog && !(flags & JIT_INFO_HAS_ARCH_EH_INFO))
-               flags |= JIT_INFO_HAS_ARCH_EH_INFO;
+               flags = (MonoJitInfoFlags)(flags | JIT_INFO_HAS_ARCH_EH_INFO);
 
        if (cfg->thunk_area)
-               flags |= JIT_INFO_HAS_THUNK_INFO;
+               flags = (MonoJitInfoFlags)(flags | JIT_INFO_HAS_THUNK_INFO);
 
        if (cfg->try_block_holes) {
                for (tmp = cfg->try_block_holes; tmp; tmp = tmp->next) {
-                       TryBlockHole *hole = tmp->data;
+                       TryBlockHole *hole = (TryBlockHole *)tmp->data;
                        MonoExceptionClause *ec = hole->clause;
                        int hole_end = hole->basic_block->native_offset + hole->basic_block->native_length;
                        MonoBasicBlock *clause_last_bb = cfg->cil_offset_to_bb [ec->try_offset + ec->try_len];
@@ -2721,7 +2811,7 @@ create_jit_info (MonoCompile *cfg, MonoMethod *method_to_compile)
                                ++num_holes;
                }
                if (num_holes)
-                       flags |= JIT_INFO_HAS_TRY_BLOCK_HOLES;
+                       flags = (MonoJitInfoFlags)(flags | JIT_INFO_HAS_TRY_BLOCK_HOLES);
                if (G_UNLIKELY (cfg->verbose_level >= 4))
                        printf ("Number of try block holes %d\n", num_holes);
        }
@@ -2732,9 +2822,9 @@ create_jit_info (MonoCompile *cfg, MonoMethod *method_to_compile)
                num_clauses = header->num_clauses;
 
        if (cfg->method->dynamic)
-               jinfo = g_malloc0 (mono_jit_info_size (flags, num_clauses, num_holes));
+               jinfo = (MonoJitInfo *)g_malloc0 (mono_jit_info_size (flags, num_clauses, num_holes));
        else
-               jinfo = mono_domain_alloc0 (cfg->domain, mono_jit_info_size (flags, num_clauses, num_holes));
+               jinfo = (MonoJitInfo *)mono_domain_alloc0 (cfg->domain, mono_jit_info_size (flags, num_clauses, num_holes));
        mono_jit_info_init (jinfo, cfg->method_to_register, cfg->native_code, cfg->code_len, flags, num_clauses, num_holes);
        jinfo->domain_neutral = (cfg->opt & MONO_OPT_SHARED) != 0;
 
@@ -2752,7 +2842,7 @@ create_jit_info (MonoCompile *cfg, MonoMethod *method_to_compile)
                if (cfg->method->dynamic)
                        gi->generic_sharing_context = g_new0 (MonoGenericSharingContext, 1);
                else
-                       gi->generic_sharing_context = mono_domain_alloc0 (cfg->domain, sizeof (MonoGenericSharingContext));
+                       gi->generic_sharing_context = (MonoGenericSharingContext *)mono_domain_alloc0 (cfg->domain, sizeof (MonoGenericSharingContext));
                mini_init_gsctx (cfg->method->dynamic ? NULL : cfg->domain, NULL, cfg->gsctx_context, gi->generic_sharing_context);
 
                if ((method_to_compile->flags & METHOD_ATTRIBUTE_STATIC) ||
@@ -2782,9 +2872,9 @@ create_jit_info (MonoCompile *cfg, MonoMethod *method_to_compile)
 
                        gi->nlocs = g_slist_length (loclist);
                        if (cfg->method->dynamic)
-                               gi->locations = g_malloc0 (gi->nlocs * sizeof (MonoDwarfLocListEntry));
+                               gi->locations = (MonoDwarfLocListEntry *)g_malloc0 (gi->nlocs * sizeof (MonoDwarfLocListEntry));
                        else
-                               gi->locations = mono_domain_alloc0 (cfg->domain, gi->nlocs * sizeof (MonoDwarfLocListEntry));
+                               gi->locations = (MonoDwarfLocListEntry *)mono_domain_alloc0 (cfg->domain, gi->nlocs * sizeof (MonoDwarfLocListEntry));
                        i = 0;
                        for (l = loclist; l; l = l->next) {
                                memcpy (&(gi->locations [i]), l->data, sizeof (MonoDwarfLocListEntry));
@@ -2825,7 +2915,7 @@ create_jit_info (MonoCompile *cfg, MonoMethod *method_to_compile)
                for (tmp = cfg->try_block_holes; tmp; tmp = tmp->next) {
                        guint32 start_bb_offset;
                        MonoTryBlockHoleJitInfo *hole;
-                       TryBlockHole *hole_data = tmp->data;
+                       TryBlockHole *hole_data = (TryBlockHole *)tmp->data;
                        MonoExceptionClause *ec = hole_data->clause;
                        int hole_end = hole_data->basic_block->native_offset + hole_data->basic_block->native_length;
                        MonoBasicBlock *clause_last_bb = cfg->cil_offset_to_bb [ec->try_offset + ec->try_len];
@@ -2933,7 +3023,7 @@ create_jit_info (MonoCompile *cfg, MonoMethod *method_to_compile)
                        ei->handler_start = cfg->native_code + tblock->native_offset;
 
                        for (tmp = cfg->try_block_holes; tmp; tmp = tmp->next) {
-                               TryBlockHole *hole = tmp->data;
+                               TryBlockHole *hole = (TryBlockHole *)tmp->data;
                                gpointer hole_end = cfg->native_code + (hole->basic_block->native_offset + hole->basic_block->native_length);
                                if (hole->clause == ec && hole_end == ei->try_end) {
                                        if (G_UNLIKELY (cfg->verbose_level >= 4))
@@ -3247,7 +3337,7 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, JitFl
        MonoMethodSignature *sig;
        MonoError err;
        MonoCompile *cfg;
-       int dfn, i, code_size_ratio;
+       int i, code_size_ratio;
        gboolean try_generic_shared, try_llvm = FALSE;
        MonoMethod *method_to_compile, *method_to_register;
        gboolean method_is_gshared = FALSE;
@@ -3405,9 +3495,10 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, JitFl
                cfg->gsctx_context = context;
 
                cfg->gsharedvt = TRUE;
-               // FIXME:
-               cfg->disable_llvm = TRUE;
-               cfg->exception_message = g_strdup ("gsharedvt");
+               if (!cfg->llvm_only) {
+                       cfg->disable_llvm = TRUE;
+                       cfg->exception_message = g_strdup ("gsharedvt");
+               }
        }
 
        if (cfg->gshared) {
@@ -3431,13 +3522,11 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, JitFl
 
        header = cfg->header;
        if (!header) {
-               MonoLoaderError *error;
-
-               if ((error = mono_loader_get_last_error ())) {
-                       cfg->exception_type = error->exception_type;
+               if (mono_loader_get_last_error ()) {
+                       mono_cfg_set_exception (cfg, MONO_EXCEPTION_MONO_ERROR);
+                       mono_error_set_from_loader_error (&cfg->error);
                } else {
-                       cfg->exception_type = MONO_EXCEPTION_INVALID_PROGRAM;
-                       cfg->exception_message = g_strdup_printf ("Missing or incorrect header for method %s", cfg->method->name);
+                       mono_cfg_set_exception_invalid_program (cfg, g_strdup_printf ("Missing or incorrect header for method %s", cfg->method->name));
                }
                if (MONO_METHOD_COMPILE_END_ENABLED ())
                        MONO_PROBE_METHOD_COMPILE_END (method, FALSE);
@@ -3487,11 +3576,6 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, JitFl
 
                cfg->extend_live_ranges = TRUE;
 
-               /* Temporarily disable this when running in the debugger until we have support
-                * for this in the debugger. */
-               /* This is no longer needed with sdb */
-               //cfg->disable_omit_fp = TRUE;
-
                /* The debugger needs all locals to be on the stack or in a global register */
                cfg->disable_vreg_to_lvreg = TRUE;
 
@@ -3499,13 +3583,10 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, JitFl
                 * may still want to view them. */
                cfg->disable_deadce_vars = TRUE;
 
-               // cfg->opt |= MONO_OPT_SHARED;
                cfg->opt &= ~MONO_OPT_DEADCE;
                cfg->opt &= ~MONO_OPT_INLINE;
                cfg->opt &= ~MONO_OPT_COPYPROP;
                cfg->opt &= ~MONO_OPT_CONSPROP;
-               /* This is no longer needed with sdb */
-               //cfg->opt &= ~MONO_OPT_GSHARED;
 
                /* This is needed for the soft debugger, which doesn't like code after the epilog */
                cfg->disable_out_of_line_bblocks = TRUE;
@@ -3550,12 +3631,12 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, JitFl
                }
        }
 
-       cfg->intvars = mono_mempool_alloc0 (cfg->mempool, sizeof (guint16) * STACK_MAX * header->max_stack);
+       cfg->intvars = (guint16 *)mono_mempool_alloc0 (cfg->mempool, sizeof (guint16) * STACK_MAX * header->max_stack);
 
        if (cfg->verbose_level > 0) {
                char *method_name;
 
-               method_name = mono_method_full_name (method, TRUE);
+               method_name = mono_method_get_full_name (method);
                g_print ("converting %s%s%smethod %s\n", COMPILE_LLVM (cfg) ? "llvm " : "", cfg->gsharedvt ? "gsharedvt " : "", (cfg->gshared && !cfg->gsharedvt) ? "gshared " : "", method_name);
                /*
                if (COMPILE_LLVM (cfg))
@@ -3675,7 +3756,12 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, JitFl
        /* Should be done before branch opts */
        if (cfg->opt & (MONO_OPT_CONSPROP | MONO_OPT_COPYPROP))
                mono_local_cprop (cfg);
-
+       /*
+        * Should be done after cprop which can do strength reduction on
+        * some of these ops, after propagating immediates.
+        */
+       if (cfg->has_emulated_ops)
+               mono_local_emulate_ops (cfg);
        if (cfg->opt & MONO_OPT_BRANCH)
                mono_optimize_branches (cfg);
 
@@ -3691,38 +3777,7 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, JitFl
 
        mono_threads_safepoint ();
 
-       /* Depth-first ordering on basic blocks */
-       cfg->bblocks = mono_mempool_alloc (cfg->mempool, sizeof (MonoBasicBlock*) * (cfg->num_bblocks + 1));
-
-       cfg->max_block_num = cfg->num_bblocks;
-
-       dfn = 0;
-       df_visit (cfg->bb_entry, &dfn, cfg->bblocks);
-       if (cfg->num_bblocks != dfn + 1) {
-               MonoBasicBlock *bb;
-
-               cfg->num_bblocks = dfn + 1;
-
-               /* remove unreachable code, because the code in them may be 
-                * inconsistent  (access to dead variables for example) */
-               for (bb = cfg->bb_entry; bb; bb = bb->next_bb)
-                       bb->flags &= ~BB_VISITED;
-               compute_reachable (cfg->bb_entry);
-               for (bb = cfg->bb_entry; bb; bb = bb->next_bb)
-                       if (bb->flags & BB_EXCEPTION_HANDLER)
-                               compute_reachable (bb);
-               for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
-                       if (!(bb->flags & BB_VISITED)) {
-                               if (cfg->verbose_level > 1)
-                                       g_print ("found unreachable code in BB%d\n", bb->block_num);
-                               bb->code = bb->last_ins = NULL;
-                               while (bb->out_count)
-                                       mono_unlink_bblock (cfg, bb, bb->out_bb [0]);
-                       }
-               }
-               for (bb = cfg->bb_entry; bb; bb = bb->next_bb)
-                       bb->flags &= ~BB_VISITED;
-       }
+       mono_bb_ordering (cfg);
 
        if (((cfg->num_varinfo > 2000) || (cfg->num_bblocks > 1000)) && !cfg->compile_aot) {
                /* 
@@ -3828,14 +3883,14 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, JitFl
                return cfg;
        }
 
+       if (cfg->llvm_only && cfg->gsharedvt)
+               mono_ssa_remove_gsharedvt (cfg);
+
 #ifdef MONO_ARCH_SOFT_FLOAT_FALLBACK
        if (COMPILE_SOFT_FLOAT (cfg))
                mono_decompose_soft_float (cfg);
 #endif
-       if (COMPILE_LLVM (cfg))
-               mono_decompose_vtype_opts_llvm (cfg);
-       else
-               mono_decompose_vtype_opts (cfg);
+       mono_decompose_vtype_opts (cfg);
        if (cfg->flags & MONO_CFG_HAS_ARRAY_ACCESS)
                mono_decompose_array_access_opts (cfg);
 
@@ -3910,6 +3965,9 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, JitFl
                MonoBasicBlock *bb;
                gboolean need_local_opts;
 
+               if (cfg->gsharedvt)
+                       mono_allocate_gsharedvt_vars (cfg);
+
                if (!COMPILE_LLVM (cfg)) {
                        mono_spill_global_vars (cfg, &need_local_opts);
 
@@ -3935,7 +3993,7 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, JitFl
 
                                        bb->last_ins->opcode = mono_reverse_branch_op (bb->last_ins->opcode);
                                } else {                        
-                                       MonoInst *inst = mono_mempool_alloc0 (cfg->mempool, sizeof (MonoInst));
+                                       MonoInst *inst = (MonoInst *)mono_mempool_alloc0 (cfg->mempool, sizeof (MonoInst));
                                        inst->opcode = OP_BR;
                                        inst->inst_target_bb = bb->last_ins->inst_false_bb;
                                        mono_bblock_add_inst (bb, inst);
@@ -4080,7 +4138,7 @@ mono_arch_instrument_epilog (MonoCompile *cfg, void *func, void *p, gboolean ena
 void
 mono_cfg_add_try_hole (MonoCompile *cfg, MonoExceptionClause *clause, guint8 *start, MonoBasicBlock *bb)
 {
-       TryBlockHole *hole = mono_mempool_alloc (cfg->mempool, sizeof (TryBlockHole));
+       TryBlockHole *hole = (TryBlockHole *)mono_mempool_alloc (cfg->mempool, sizeof (TryBlockHole));
        hole->clause = clause;
        hole->start_offset = start - cfg->native_code;
        hole->basic_block = bb;
@@ -4094,6 +4152,14 @@ mono_cfg_set_exception (MonoCompile *cfg, int type)
        cfg->exception_type = type;
 }
 
+/* Assumes ownership of the MSG argument */
+void
+mono_cfg_set_exception_invalid_program (MonoCompile *cfg, char *msg)
+{
+       mono_cfg_set_exception (cfg, MONO_EXCEPTION_MONO_ERROR);
+       mono_error_set_generic_error (&cfg->error, "System", "InvalidProgramException", msg);
+}
+
 #endif /* DISABLE_JIT */
 
 static MonoJitInfo*
@@ -4111,7 +4177,7 @@ create_jit_info_for_trampoline (MonoMethod *wrapper, MonoTrampInfo *info)
                uw_info = mono_unwind_ops_encode (info->unwind_ops, &info_len);
        }
 
-       jinfo = mono_domain_alloc0 (domain, MONO_SIZEOF_JIT_INFO);
+       jinfo = (MonoJitInfo *)mono_domain_alloc0 (domain, MONO_SIZEOF_JIT_INFO);
        jinfo->d.method = wrapper;
        jinfo->code_start = info->code;
        jinfo->code_size = info->code_size;
@@ -4123,13 +4189,38 @@ create_jit_info_for_trampoline (MonoMethod *wrapper, MonoTrampInfo *info)
        return jinfo;
 }
 
+GTimer *mono_time_track_start ()
+{
+       return g_timer_new ();
+}
+
+void mono_time_track_end (double *time, GTimer *timer)
+{
+       g_timer_stop (timer);
+       *time += g_timer_elapsed (timer, NULL);
+       g_timer_destroy (timer);
+}
+
+void mono_update_jit_stats (MonoCompile *cfg)
+{
+       mono_jit_stats.allocate_var += cfg->stat_allocate_var;
+       mono_jit_stats.locals_stack_size += cfg->stat_locals_stack_size;
+       mono_jit_stats.basic_blocks += cfg->stat_basic_blocks;
+       mono_jit_stats.max_basic_blocks = MAX (cfg->stat_basic_blocks, mono_jit_stats.max_basic_blocks);
+       mono_jit_stats.cil_code_size += cfg->stat_cil_code_size;
+       mono_jit_stats.regvars += cfg->stat_n_regvars;
+       mono_jit_stats.inlineable_methods += cfg->stat_inlineable_methods;
+       mono_jit_stats.inlined_methods += cfg->stat_inlined_methods;
+       mono_jit_stats.code_reallocs += cfg->stat_code_reallocs;
+}
+
 /*
  * mono_jit_compile_method_inner:
  *
  *   Main entry point for the JIT.
  */
 gpointer
-mono_jit_compile_method_inner (MonoMethod *method, MonoDomain *target_domain, int opt, MonoException **jit_ex)
+mono_jit_compile_method_inner (MonoMethod *method, MonoDomain *target_domain, int opt, MonoError *error)
 {
        MonoCompile *cfg;
        gpointer code = NULL;
@@ -4140,6 +4231,8 @@ mono_jit_compile_method_inner (MonoMethod *method, MonoDomain *target_domain, in
        GTimer *jit_timer;
        MonoMethod *prof_method, *shared;
 
+       mono_error_init (error);
+
        if ((method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
            (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)) {
                MonoMethod *nm;
@@ -4159,9 +4252,9 @@ mono_jit_compile_method_inner (MonoMethod *method, MonoDomain *target_domain, in
                }
                nm = mono_marshal_get_native_wrapper (method, TRUE, mono_aot_only);
                code = mono_get_addr_from_ftnptr (mono_compile_method (nm));
-               jinfo = mono_jit_info_table_find (target_domain, code);
+               jinfo = mono_jit_info_table_find (target_domain, (char *)code);
                if (!jinfo)
-                       jinfo = mono_jit_info_table_find (mono_domain_get (), code);
+                       jinfo = mono_jit_info_table_find (mono_domain_get (), (char *)code);
                if (jinfo)
                        mono_profiler_method_end_jit (method, jinfo, MONO_PROFILE_OK);
                return code;
@@ -4202,7 +4295,8 @@ mono_jit_compile_method_inner (MonoMethod *method, MonoDomain *target_domain, in
 
                full_name = mono_method_full_name (method, TRUE);
                msg = g_strdup_printf ("Unrecognizable runtime implemented method '%s'", full_name);
-               *jit_ex = mono_exception_from_name_msg (mono_defaults.corlib, "System", "InvalidProgramException", msg);
+               ex = mono_exception_from_name_msg (mono_defaults.corlib, "System", "InvalidProgramException", msg);
+               mono_error_set_exception_instance (error, ex);
                g_free (full_name);
                g_free (msg);
                return NULL;
@@ -4245,21 +4339,19 @@ mono_jit_compile_method_inner (MonoMethod *method, MonoDomain *target_domain, in
                char *fullname = mono_method_full_name (method, TRUE);
                char *msg = g_strdup_printf ("Attempting to JIT compile method '%s' while running with --aot-only. See http://docs.xamarin.com/ios/about/limitations for more information.\n", fullname);
 
-               *jit_ex = mono_get_exception_execution_engine (msg);
+               ex = mono_get_exception_execution_engine (msg);
+               mono_error_set_exception_instance (error, ex);
                g_free (fullname);
                g_free (msg);
                
                return NULL;
        }
 
-       jit_timer = g_timer_new ();
-
+       jit_timer = mono_time_track_start ();
        cfg = mini_method_compile (method, opt, target_domain, JIT_FLAG_RUN_CCTORS, 0, -1);
-       prof_method = cfg->method;
+       mono_time_track_end (&mono_jit_stats.jit_time, jit_timer);
 
-       g_timer_stop (jit_timer);
-       mono_jit_stats.jit_time += g_timer_elapsed (jit_timer, NULL);
-       g_timer_destroy (jit_timer);
+       prof_method = cfg->method;
 
        switch (cfg->exception_type) {
        case MONO_EXCEPTION_NONE:
@@ -4270,53 +4362,26 @@ mono_jit_compile_method_inner (MonoMethod *method, MonoDomain *target_domain, in
        case MONO_EXCEPTION_FILE_NOT_FOUND:
        case MONO_EXCEPTION_BAD_IMAGE: {
                /* Throw a type load exception if needed */
-               MonoLoaderError *error = mono_loader_get_last_error ();
-
-               if (error) {
-                       ex = mono_loader_error_prepare_exception (error);
+               if (cfg->exception_ptr) {
+                       ex = mono_class_get_exception_for_failure ((MonoClass *)cfg->exception_ptr);
                } else {
-                       if (cfg->exception_ptr) {
-                               ex = mono_class_get_exception_for_failure (cfg->exception_ptr);
-                       } else {
-                               if (cfg->exception_type == MONO_EXCEPTION_MISSING_FIELD)
-                                       ex = mono_exception_from_name_msg (mono_defaults.corlib, "System", "MissingFieldException", cfg->exception_message);
-                               else if (cfg->exception_type == MONO_EXCEPTION_MISSING_METHOD)
-                                       ex = mono_exception_from_name_msg (mono_defaults.corlib, "System", "MissingMethodException", cfg->exception_message);
-                               else if (cfg->exception_type == MONO_EXCEPTION_TYPE_LOAD)
-                                       ex = mono_exception_from_name_msg (mono_defaults.corlib, "System", "TypeLoadException", cfg->exception_message);
-                               else if (cfg->exception_type == MONO_EXCEPTION_FILE_NOT_FOUND)
-                                       ex = mono_exception_from_name_msg (mono_defaults.corlib, "System.IO", "FileNotFoundException", cfg->exception_message);
-                               else if (cfg->exception_type == MONO_EXCEPTION_BAD_IMAGE)
-                                       ex = mono_get_exception_bad_image_format (cfg->exception_message);
-                               else
-                                       g_assert_not_reached ();
-                       }
+                       if (cfg->exception_type == MONO_EXCEPTION_MISSING_FIELD)
+                               ex = mono_exception_from_name_msg (mono_defaults.corlib, "System", "MissingFieldException", cfg->exception_message);
+                       else if (cfg->exception_type == MONO_EXCEPTION_MISSING_METHOD)
+                               ex = mono_exception_from_name_msg (mono_defaults.corlib, "System", "MissingMethodException", cfg->exception_message);
+                       else if (cfg->exception_type == MONO_EXCEPTION_TYPE_LOAD)
+                               ex = mono_exception_from_name_msg (mono_defaults.corlib, "System", "TypeLoadException", cfg->exception_message);
+                       else if (cfg->exception_type == MONO_EXCEPTION_FILE_NOT_FOUND)
+                               ex = mono_exception_from_name_msg (mono_defaults.corlib, "System.IO", "FileNotFoundException", cfg->exception_message);
+                       else if (cfg->exception_type == MONO_EXCEPTION_BAD_IMAGE)
+                               ex = mono_get_exception_bad_image_format (cfg->exception_message);
+                       else
+                               g_assert_not_reached ();
                }
                break;
        }
-       case MONO_EXCEPTION_INVALID_PROGRAM:
-               ex = mono_exception_from_name_msg (mono_defaults.corlib, "System", "InvalidProgramException", cfg->exception_message);
-               break;
-       case MONO_EXCEPTION_UNVERIFIABLE_IL:
-               ex = mono_exception_from_name_msg (mono_defaults.corlib, "System.Security", "VerificationException", cfg->exception_message);
-               break;
-       case MONO_EXCEPTION_METHOD_ACCESS:
-               ex = mono_exception_from_name_msg (mono_defaults.corlib, "System", "MethodAccessException", cfg->exception_message);
-               break;
-       case MONO_EXCEPTION_FIELD_ACCESS:
-               ex = mono_exception_from_name_msg (mono_defaults.corlib, "System", "FieldAccessException", cfg->exception_message);
-               break;
-       case MONO_EXCEPTION_OBJECT_SUPPLIED: {
-               MonoException *exp = cfg->exception_ptr;
-               MONO_GC_UNREGISTER_ROOT (cfg->exception_ptr);
-
-               ex = exp;
-               break;
-       }
-       case MONO_EXCEPTION_OUT_OF_MEMORY:
-               ex = mono_domain_get ()->out_of_memory_ex;
-               break;
        case MONO_EXCEPTION_MONO_ERROR:
+               // FIXME: MonoError has no copy ctor
                g_assert (!mono_error_ok (&cfg->error));
                ex = mono_error_convert_to_exception (&cfg->error);
                break;
@@ -4329,7 +4394,7 @@ mono_jit_compile_method_inner (MonoMethod *method, MonoDomain *target_domain, in
                        mono_profiler_method_end_jit (method, NULL, MONO_PROFILE_FAILED);
 
                mono_destroy_compile (cfg);
-               *jit_ex = ex;
+               mono_error_set_exception_instance (error, ex);
 
                return NULL;
        }
@@ -4374,15 +4439,7 @@ mono_jit_compile_method_inner (MonoMethod *method, MonoDomain *target_domain, in
         * Update global stats while holding a lock, instead of doing many
         * InterlockedIncrement operations during JITting.
         */
-       mono_jit_stats.allocate_var += cfg->stat_allocate_var;
-       mono_jit_stats.locals_stack_size += cfg->stat_locals_stack_size;
-       mono_jit_stats.basic_blocks += cfg->stat_basic_blocks;
-       mono_jit_stats.max_basic_blocks = MAX (cfg->stat_basic_blocks, mono_jit_stats.max_basic_blocks);
-       mono_jit_stats.cil_code_size += cfg->stat_cil_code_size;
-       mono_jit_stats.regvars += cfg->stat_n_regvars;
-       mono_jit_stats.inlineable_methods += cfg->stat_inlineable_methods;
-       mono_jit_stats.inlined_methods += cfg->stat_inlined_methods;
-       mono_jit_stats.code_reallocs += cfg->stat_code_reallocs;
+       mono_update_jit_stats (cfg);
 
        mono_destroy_compile (cfg);
 
@@ -4391,7 +4448,7 @@ mono_jit_compile_method_inner (MonoMethod *method, MonoDomain *target_domain, in
                MonoJumpInfo patch_info;
                MonoJumpList *jlist;
                GSList *tmp;
-               jlist = g_hash_table_lookup (domain_jit_info (target_domain)->jump_target_hash, method);
+               jlist = (MonoJumpList *)g_hash_table_lookup (domain_jit_info (target_domain)->jump_target_hash, method);
                if (jlist) {
                        patch_info.next = NULL;
                        patch_info.ip.i = 0;
@@ -4405,8 +4462,8 @@ mono_jit_compile_method_inner (MonoMethod *method, MonoDomain *target_domain, in
 #endif
 #ifdef MONO_ARCH_HAVE_PATCH_CODE_NEW
                        for (tmp = jlist->list; tmp; tmp = tmp->next) {
-                               gpointer target = mono_resolve_patch_target (NULL, target_domain, tmp->data, &patch_info, TRUE);
-                               mono_arch_patch_code_new (NULL, target_domain, tmp->data, &patch_info, target);
+                               gpointer target = mono_resolve_patch_target (NULL, target_domain, (guint8 *)tmp->data, &patch_info, TRUE);
+                               mono_arch_patch_code_new (NULL, target_domain, (guint8 *)tmp->data, &patch_info, target);
                        }
 #else
                        for (tmp = jlist->list; tmp; tmp = tmp->next)
@@ -4426,7 +4483,7 @@ mono_jit_compile_method_inner (MonoMethod *method, MonoDomain *target_domain, in
        if (!vtable) {
                ex = mono_class_get_exception_for_failure (method->klass);
                g_assert (ex);
-               *jit_ex = ex;
+               mono_error_set_exception_instance (error, ex);
                return NULL;
        }
 
@@ -4446,7 +4503,7 @@ mono_jit_compile_method_inner (MonoMethod *method, MonoDomain *target_domain, in
 
        ex = mono_runtime_class_init_full (vtable, FALSE);
        if (ex) {
-               *jit_ex = ex;
+               mono_error_set_exception_instance (error, ex);
                return NULL;
        }
        return code;
@@ -4468,7 +4525,7 @@ mini_get_underlying_type (MonoType *type)
 void
 mini_jit_init (void)
 {
-       mono_mutex_init_recursive (&jit_mutex);
+       mono_os_mutex_init_recursive (&jit_mutex);
 #ifndef DISABLE_JIT
        current_backend = g_new0 (MonoBackend, 1);
        init_backend (current_backend);