Merge branch 'master' of github.com:mono/mono
[mono.git] / mono / mini / method-to-ir.c
index 9ac1ab24100ed9fe23bd5643b8e6c84c54327d4e..e46bb852cd014837fe473a984438e1f2c61d6a9f 100644 (file)
@@ -2593,9 +2593,57 @@ create_write_barrier_bitmap (MonoClass *klass, unsigned *wb_bitmap, int offset)
 static void
 emit_write_barrier (MonoCompile *cfg, MonoInst *ptr, MonoInst *value, int value_reg)
 {
+#ifdef HAVE_SGEN_GC
+       int card_table_shift_bits;
+       gpointer card_table_mask;
+       guint8 *card_table = mono_gc_get_card_table (&card_table_shift_bits, &card_table_mask);
        MonoInst *dummy_use;
-       MonoMethod *write_barrier = mono_gc_get_write_barrier ();
-       mono_emit_method_call (cfg, write_barrier, &ptr, NULL);
+
+#ifdef MONO_ARCH_HAVE_CARD_TABLE_WBARRIER
+       int nursery_shift_bits;
+       size_t nursery_size;
+
+       mono_gc_get_nursery (&nursery_shift_bits, &nursery_size);
+
+       if (!cfg->compile_aot && card_table && nursery_shift_bits > 0) {
+               MonoInst *wbarrier;
+
+               MONO_INST_NEW (cfg, wbarrier, OP_CARD_TABLE_WBARRIER);
+               wbarrier->sreg1 = ptr->dreg;
+               if (value)
+                       wbarrier->sreg2 = value->dreg;
+               else
+                       wbarrier->sreg2 = value_reg;
+               MONO_ADD_INS (cfg->cbb, wbarrier);
+       } else
+#endif
+       if (card_table) {
+               int offset_reg = alloc_preg (cfg);
+               int card_reg  = alloc_preg (cfg);
+               MonoInst *ins;
+
+               MONO_EMIT_NEW_BIALU_IMM (cfg, OP_SHR_UN_IMM, offset_reg, ptr->dreg, card_table_shift_bits);
+               if (card_table_mask)
+                       MONO_EMIT_NEW_BIALU_IMM (cfg, OP_PAND_IMM, offset_reg, offset_reg, card_table_mask);
+
+               /*We can't use PADD_IMM since the cardtable might end up in high addresses and amd64 doesn't support
+                * IMM's larger than 32bits.
+                */
+               if (cfg->compile_aot) {
+                       MONO_EMIT_NEW_AOTCONST (cfg, card_reg, NULL, MONO_PATCH_INFO_GC_CARD_TABLE_ADDR);
+               } else {
+                       MONO_INST_NEW (cfg, ins, OP_PCONST);
+                       ins->inst_p0 = card_table;
+                       ins->dreg = card_reg;
+                       MONO_ADD_INS (cfg->cbb, ins);
+               }
+
+               MONO_EMIT_NEW_BIALU (cfg, OP_PADD, offset_reg, offset_reg, card_reg);
+               MONO_EMIT_NEW_STORE_MEMBASE_IMM (cfg, OP_STOREI1_MEMBASE_IMM, offset_reg, 0, 1);
+       } else {
+               MonoMethod *write_barrier = mono_gc_get_write_barrier ();
+               mono_emit_method_call (cfg, write_barrier, &ptr, NULL);
+       }
 
        if (value) {
                EMIT_NEW_DUMMY_USE (cfg, dummy_use, value);
@@ -2604,6 +2652,7 @@ emit_write_barrier (MonoCompile *cfg, MonoInst *ptr, MonoInst *value, int value_
                dummy_use->sreg1 = value_reg;
                MONO_ADD_INS (cfg->cbb, dummy_use);
        }
+#endif
 }
 
 static gboolean
@@ -4688,6 +4737,12 @@ inline_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig,
                return 0;
        }
 
+       /*Must verify before creating locals as it can cause the JIT to assert.*/
+       if (mono_compile_is_broken (cfg, cmethod, FALSE)) {
+               mono_metadata_free_mh (cheader);
+               return 0;
+       }
+
        /* allocate space to store the return value */
        if (!MONO_TYPE_IS_VOID (fsig->ret)) {
                rvar = mono_compile_create_var (cfg, fsig->ret, OP_LOCAL);
@@ -5388,9 +5443,6 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                dont_verify_stloc = TRUE;
        }
 
-       if (!dont_verify && mini_method_verify (cfg, method_definition))
-               goto exception_exit;
-
        if (mono_debug_using_mono_debugger ())
                cfg->keep_cil_nops = TRUE;