}
}
+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;
+
+#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);
+ } else {
+ MONO_INST_NEW (cfg, dummy_use, OP_DUMMY_USE);
+ dummy_use->sreg1 = value_reg;
+ MONO_ADD_INS (cfg->cbb, dummy_use);
+ }
+#endif
+}
+
static gboolean
mono_emit_wb_aware_memcpy (MonoCompile *cfg, MonoClass *klass, MonoInst *iargs[4], int size, int align)
{
MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOAD_MEMBASE, tmp_reg, srcreg, offset);
MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREP_MEMBASE_REG, dest_ptr_reg, 0, tmp_reg);
- if (need_wb & 0x1) {
- MonoInst *dummy_use;
-
- MonoMethod *write_barrier = mono_gc_get_write_barrier ();
- mono_emit_method_call (cfg, write_barrier, &iargs [0], NULL);
-
- MONO_INST_NEW (cfg, dummy_use, OP_DUMMY_USE);
- dummy_use->sreg1 = dest_ptr_reg;
- MONO_ADD_INS (cfg->cbb, dummy_use);
- }
-
+ if (need_wb & 0x1)
+ emit_write_barrier (cfg, iargs [0], NULL, tmp_reg);
offset += SIZEOF_VOID_P;
size -= SIZEOF_VOID_P;
g_assert_not_reached ();
}
- if (cfg->gen_write_barriers && is_ref) {
- MonoInst *dummy_use;
- MonoMethod *write_barrier = mono_gc_get_write_barrier ();
- mono_emit_method_call (cfg, write_barrier, &args [0], NULL);
- EMIT_NEW_DUMMY_USE (cfg, dummy_use, args [1]);
- }
+ if (cfg->gen_write_barriers && is_ref)
+ emit_write_barrier (cfg, args [0], args [1], -1);
}
#endif /* MONO_ARCH_HAVE_ATOMIC_EXCHANGE */
} else {
/* g_assert_not_reached (); */
}
- if (cfg->gen_write_barriers && is_ref) {
- MonoInst *dummy_use;
- MonoMethod *write_barrier = mono_gc_get_write_barrier ();
- mono_emit_method_call (cfg, write_barrier, &args [0], NULL);
- EMIT_NEW_DUMMY_USE (cfg, dummy_use, args [1]);
- }
+ if (cfg->gen_write_barriers && is_ref)
+ emit_write_barrier (cfg, args [0], args [1], -1);
}
#endif /* MONO_ARCH_HAVE_ATOMIC_CAS */
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);
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;
/* FIXME: check the signature matches */
cmethod = mini_get_method (cfg, method, token, NULL, generic_context);
- if (!cmethod)
+ if (!cmethod || mono_loader_get_last_error ())
goto load_error;
if (cfg->generic_sharing_context && mono_method_check_context_used (cmethod))
cil_method = cmethod;
}
- if (!cmethod)
+ if (!cmethod || mono_loader_get_last_error ())
goto load_error;
if (!dont_verify && !cfg->skip_visibility) {
MonoMethod *target_method = cil_method;
ins_flag = 0;
MONO_ADD_INS (bblock, ins);
- if (cfg->gen_write_barriers && *ip == CEE_STIND_REF && method->wrapper_type != MONO_WRAPPER_WRITE_BARRIER && !((sp [1]->opcode == OP_PCONST) && (sp [1]->inst_p0 == 0))) {
- MonoInst *dummy_use;
- /* insert call to write barrier */
- MonoMethod *write_barrier = mono_gc_get_write_barrier ();
- mono_emit_method_call (cfg, write_barrier, sp, NULL);
- EMIT_NEW_DUMMY_USE (cfg, dummy_use, sp [1]);
- }
+ if (cfg->gen_write_barriers && *ip == CEE_STIND_REF && method->wrapper_type != MONO_WRAPPER_WRITE_BARRIER && !((sp [1]->opcode == OP_PCONST) && (sp [1]->inst_p0 == 0)))
+ emit_write_barrier (cfg, sp [0], sp [1], -1);
inline_costs += 1;
++ip;
store->flags |= ins_flag;
MONO_ADD_INS (cfg->cbb, store);
- if (cfg->gen_write_barriers && cfg->method->wrapper_type != MONO_WRAPPER_WRITE_BARRIER) {
- MonoInst *dummy_use;
- MonoMethod *write_barrier = mono_gc_get_write_barrier ();
- mono_emit_method_call (cfg, write_barrier, sp, NULL);
- EMIT_NEW_DUMMY_USE (cfg, dummy_use, sp [1]);
- }
+ if (cfg->gen_write_barriers && cfg->method->wrapper_type != MONO_WRAPPER_WRITE_BARRIER)
+ emit_write_barrier (cfg, sp [0], sp [1], -1);
} else {
mini_emit_stobj (cfg, sp [0], sp [1], klass, FALSE);
}
CHECK_OPSIZE (5);
token = read32 (ip + 1);
cmethod = mini_get_method (cfg, method, token, NULL, generic_context);
- if (!cmethod)
+ if (!cmethod || mono_loader_get_last_error ())
goto load_error;
fsig = mono_method_get_signature (cmethod, image, token);
if (!fsig)
if (cfg->gen_write_barriers && mini_type_to_stind (cfg, field->type) == CEE_STIND_REF && !(sp [1]->opcode == OP_PCONST && sp [1]->inst_c0 == 0)) {
/* insert call to write barrier */
- MonoMethod *write_barrier = mono_gc_get_write_barrier ();
- MonoInst *iargs [2], *dummy_use;
+ MonoInst *ptr;
int dreg;
dreg = alloc_preg (cfg);
- EMIT_NEW_BIALU_IMM (cfg, iargs [0], OP_PADD_IMM, dreg, sp [0]->dreg, foffset);
- iargs [1] = sp [1];
- mono_emit_method_call (cfg, write_barrier, iargs, NULL);
-
- EMIT_NEW_DUMMY_USE (cfg, dummy_use, sp [1]);
+ EMIT_NEW_BIALU_IMM (cfg, ptr, OP_PADD_IMM, dreg, sp [0]->dreg, foffset);
+ emit_write_barrier (cfg, ptr, sp [1], -1);
}
store->flags |= ins_flag;
EMIT_NEW_STORE_MEMBASE_TYPE (cfg, ins, &klass->byval_arg, sp [0]->dreg, 0, sp [1]->dreg);
if (cfg->gen_write_barriers && cfg->method->wrapper_type != MONO_WRAPPER_WRITE_BARRIER &&
generic_class_is_reference_type (cfg, klass)) {
- MonoInst *dummy_use;
/* insert call to write barrier */
- MonoMethod *write_barrier = mono_gc_get_write_barrier ();
- mono_emit_method_call (cfg, write_barrier, sp, NULL);
- EMIT_NEW_DUMMY_USE (cfg, dummy_use, sp [1]);
+ emit_write_barrier (cfg, sp [0], sp [1], -1);
}
ins_flag = 0;
ip += 5;
CHECK_OPSIZE (6);
n = read32 (ip + 2);
cmethod = mini_get_method (cfg, method, n, NULL, generic_context);
- if (!cmethod)
+ if (!cmethod || mono_loader_get_last_error ())
goto load_error;
mono_class_init (cmethod->klass);
CHECK_OPSIZE (6);
n = read32 (ip + 2);
cmethod = mini_get_method (cfg, method, n, NULL, generic_context);
- if (!cmethod)
+ if (!cmethod || mono_loader_get_last_error ())
goto load_error;
mono_class_init (cmethod->klass);