We emit two write barriers, for the case of the concurrent and non-concurrent collector in the mscorlib image. All calls to the write barrier are made through the plt, calls which are resolved according to the GC configuration at runtime.
<opcode name="mono_jit_detach" input="Pop0" output="Push0" args="InlineNone" o1="0xF0" o2="0x12" flow="next" />
<opcode name="mono_jit_icall_addr" input="Pop0" output="PushI" args="InlineI" o1="0xF0" o2="0x13" flow="next" />
<opcode name="mono_ldptr_int_req_flag" input="Pop0" output="PushI" args="InlineNone" o1="0xF0" o2="0x14" flow="next" />
+<opcode name="mono_ldptr_card_table" input="Pop0" output="PushI" args="InlineNone" o1="0xF0" o2="0x15" flow="next" />
+<opcode name="mono_ldptr_nursery_start" input="Pop0" output="PushI" args="InlineNone" o1="0xF0" o2="0x16" flow="next" />
</opdesc>
OPDEF(CEE_MONO_JIT_DETACH, "mono_jit_detach", Pop0, Push0, InlineNone, X, 2, 0xF0, 0x12, NEXT)
OPDEF(CEE_MONO_JIT_ICALL_ADDR, "mono_jit_icall_addr", Pop0, Push0, InlineNone, X, 2, 0xF0, 0x13, NEXT)
OPDEF(CEE_MONO_LDPTR_INT_REQ_FLAG, "mono_ldptr_int_req_flag", Pop0, PushI, InlineNone, X, 2, 0xF0, 0x14, NEXT)
+OPDEF(CEE_MONO_LDPTR_CARD_TABLE, "mono_ldptr_card_table", Pop0, PushI, InlineNone, X, 2, 0xF0, 0x15, NEXT)
+OPDEF(CEE_MONO_LDPTR_NURSERY_START, "mono_ldptr_nursery_start", Pop0, PushI, InlineNone, X, 2, 0xF0, 0x16, NEXT)
#ifndef OPALIAS
#define _MONO_CIL_OPALIAS_DEFINED_
#define OPALIAS(a,s,r)
mb->pos += 4;
}
+void
+mono_mb_emit_i8 (MonoMethodBuilder *mb, gint64 data)
+{
+ if ((mb->pos + 8) >= mb->code_size) {
+ mb->code_size += mb->code_size >> 1;
+ mb->code = g_realloc (mb->code, mb->code_size);
+ }
+
+ mono_mb_patch_addr (mb, mb->pos, data);
+ mono_mb_patch_addr (mb, mb->pos + 4, data >> 32);
+ mb->pos += 8;
+}
+
void
mono_mb_emit_i2 (MonoMethodBuilder *mb, gint16 data)
{
}
}
+void
+mono_mb_emit_icon8 (MonoMethodBuilder *mb, gint64 value)
+{
+ mono_mb_emit_byte (mb, CEE_LDC_I8);
+ mono_mb_emit_i8 (mb, value);
+}
+
int
mono_mb_get_label (MonoMethodBuilder *mb)
{
void
mono_mb_emit_icon (MonoMethodBuilder *mb, gint32 value);
+void
+mono_mb_emit_icon8 (MonoMethodBuilder *mb, gint64 value);
+
guint32
mono_mb_emit_branch (MonoMethodBuilder *mb, guint8 op);
void
mono_mb_emit_i4 (MonoMethodBuilder *mb, gint32 data);
+void
+mono_mb_emit_i8 (MonoMethodBuilder *mb, gint64 data);
+
void
mono_mb_emit_op (MonoMethodBuilder *mb, guint8 op, gpointer data);
static void
emit_nursery_check (MonoMethodBuilder *mb, int *nursery_check_return_labels, gboolean is_concurrent)
{
+ int shifted_nursery_start = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
+
memset (nursery_check_return_labels, 0, sizeof (int) * 2);
// if (ptr_in_nursery (ptr)) return;
/*
* Masking out the bits might be faster, but we would have to use 64 bit
* immediates, which might be slower.
*/
+ mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
+ mono_mb_emit_byte (mb, CEE_MONO_LDPTR_NURSERY_START);
+ mono_mb_emit_icon (mb, DEFAULT_NURSERY_BITS);
+ mono_mb_emit_byte (mb, CEE_SHR_UN);
+ mono_mb_emit_stloc (mb, shifted_nursery_start);
+
mono_mb_emit_ldarg (mb, 0);
mono_mb_emit_icon (mb, DEFAULT_NURSERY_BITS);
mono_mb_emit_byte (mb, CEE_SHR_UN);
- mono_mb_emit_ptr (mb, (gpointer)((mword)sgen_get_nursery_start () >> DEFAULT_NURSERY_BITS));
+ mono_mb_emit_ldloc (mb, shifted_nursery_start);
nursery_check_return_labels [0] = mono_mb_emit_branch (mb, CEE_BEQ);
if (!is_concurrent) {
mono_mb_emit_byte (mb, CEE_LDIND_I);
mono_mb_emit_icon (mb, DEFAULT_NURSERY_BITS);
mono_mb_emit_byte (mb, CEE_SHR_UN);
- mono_mb_emit_ptr (mb, (gpointer)((mword)sgen_get_nursery_start () >> DEFAULT_NURSERY_BITS));
+ mono_mb_emit_ldloc (mb, shifted_nursery_start);
nursery_check_return_labels [1] = mono_mb_emit_branch (mb, CEE_BNE_UN);
}
}
ldc_i4_1
stind_i1
*/
- mono_mb_emit_ptr (mb, sgen_cardtable);
+ mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
+ mono_mb_emit_byte (mb, CEE_MONO_LDPTR_CARD_TABLE);
mono_mb_emit_ldarg (mb, 0);
mono_mb_emit_icon (mb, CARD_BITS);
mono_mb_emit_byte (mb, CEE_SHR_UN);
+ mono_mb_emit_byte (mb, CEE_CONV_I);
#ifdef SGEN_HAVE_OVERLAPPING_CARDS
- mono_mb_emit_ptr (mb, (gpointer)CARD_MASK);
+#if SIZEOF_VOID_P == 8
+ mono_mb_emit_icon8 (mb, CARD_MASK);
+#else
+ mono_mb_emit_icon (mb, CARD_MASK);
+#endif
+ mono_mb_emit_byte (mb, CEE_CONV_I);
mono_mb_emit_byte (mb, CEE_AND);
#endif
mono_mb_emit_byte (mb, CEE_ADD);
}
}
+ /* write barriers */
+ if (mono_gc_is_moving ()) {
+ add_method (acfg, mono_gc_get_specific_write_barrier (FALSE));
+ add_method (acfg, mono_gc_get_specific_write_barrier (TRUE));
+ }
+
/* Stelemref wrappers */
{
MonoMethod **wrappers;
if (callee_cfg->method->wrapper_type == MONO_WRAPPER_ALLOC)
/* sgen does some initialization when the allocator method is created */
direct_callable = FALSE;
+ if (callee_cfg->method->wrapper_type == MONO_WRAPPER_WRITE_BARRIER)
+ /* we don't know at compile time whether sgen is concurrent or not */
+ direct_callable = FALSE;
if (direct_callable)
return TRUE;
case MONO_PATCH_INFO_MSCORLIB_GOT_ADDR:
case MONO_PATCH_INFO_JIT_TLS_ID:
case MONO_PATCH_INFO_GC_CARD_TABLE_ADDR:
+ case MONO_PATCH_INFO_GC_NURSERY_START:
break;
case MONO_PATCH_INFO_CASTCLASS_CACHE:
encode_value (patch_info->data.index, p, &p);
continue;
}
- if (patch_info->type == MONO_PATCH_INFO_GC_CARD_TABLE_ADDR) {
+ if (patch_info->type == MONO_PATCH_INFO_GC_CARD_TABLE_ADDR ||
+ patch_info->type == MONO_PATCH_INFO_GC_NURSERY_START) {
/* Stored in a GOT slot initialized at module load time */
patch_info->type = MONO_PATCH_INFO_NONE;
continue;
case MONO_PATCH_INFO_GOT_OFFSET:
case MONO_PATCH_INFO_NONE:
case MONO_PATCH_INFO_GC_CARD_TABLE_ADDR:
+ case MONO_PATCH_INFO_GC_NURSERY_START:
break;
case MONO_PATCH_INFO_IMAGE:
/* The assembly is stored in GOT slot 0 */
get_got_offset (acfg, FALSE, ji);
get_got_offset (acfg, TRUE, ji);
+ ji = mono_mempool_alloc0 (acfg->mempool, sizeof (MonoJumpInfo));
+ ji->type = MONO_PATCH_INFO_GC_NURSERY_START;
+ get_got_offset (acfg, FALSE, ji);
+ get_got_offset (acfg, TRUE, ji);
+
ji = mono_mempool_alloc0 (acfg->mempool, sizeof (MonoJumpInfo));
ji->type = MONO_PATCH_INFO_JIT_TLS_ID;
get_got_offset (acfg, FALSE, ji);
memset (&ji, 0, sizeof (ji));
ji.type = MONO_PATCH_INFO_GC_CARD_TABLE_ADDR;
-
amodule->got [2] = mono_resolve_patch_target (NULL, mono_get_root_domain (), NULL, &ji, FALSE);
+
+ memset (&ji, 0, sizeof (ji));
+ ji.type = MONO_PATCH_INFO_GC_NURSERY_START;
+ amodule->got [3] = mono_resolve_patch_target (NULL, mono_get_root_domain (), NULL, &ji, FALSE);
}
if (amodule->llvm_got) {
amodule->llvm_got [0] = amodule->got [0];
amodule->llvm_got [1] = amodule->got [1];
amodule->llvm_got [2] = amodule->got [2];
+ amodule->llvm_got [3] = amodule->got [3];
}
/*
case MONO_PATCH_INFO_MONITOR_ENTER_V4:
case MONO_PATCH_INFO_MONITOR_EXIT:
case MONO_PATCH_INFO_GC_CARD_TABLE_ADDR:
+ case MONO_PATCH_INFO_GC_NURSERY_START:
case MONO_PATCH_INFO_JIT_TLS_ID:
break;
case MONO_PATCH_INFO_CASTCLASS_CACHE:
break;
}
+ case CEE_MONO_LDPTR_CARD_TABLE: {
+ int shift_bits;
+ gpointer card_mask;
+ CHECK_STACK_OVF (1);
+
+ if (cfg->compile_aot)
+ EMIT_NEW_AOTCONST (cfg, ins, MONO_PATCH_INFO_GC_CARD_TABLE_ADDR, NULL);
+ else
+ EMIT_NEW_PCONST (cfg, ins, mono_gc_get_card_table (&shift_bits, &card_mask));
+
+ *sp++ = ins;
+ ip += 2;
+ inline_costs += 10 * num_calls++;
+ break;
+ }
+ case CEE_MONO_LDPTR_NURSERY_START: {
+ int shift_bits;
+ size_t size;
+ CHECK_STACK_OVF (1);
+
+ if (cfg->compile_aot)
+ EMIT_NEW_AOTCONST (cfg, ins, MONO_PATCH_INFO_GC_NURSERY_START, NULL);
+ else
+ EMIT_NEW_PCONST (cfg, ins, mono_gc_get_nursery (&shift_bits, &size));
+
+ *sp++ = ins;
+ ip += 2;
+ inline_costs += 10 * num_calls++;
+ break;
+ }
case CEE_MONO_LDPTR_INT_REQ_FLAG: {
CHECK_STACK_OVF (1);
case MONO_PATCH_INFO_INTERRUPTION_REQUEST_FLAG:
case MONO_PATCH_INFO_MSCORLIB_GOT_ADDR:
case MONO_PATCH_INFO_GC_CARD_TABLE_ADDR:
+ case MONO_PATCH_INFO_GC_NURSERY_START:
case MONO_PATCH_INFO_JIT_TLS_ID:
case MONO_PATCH_INFO_MONITOR_ENTER:
case MONO_PATCH_INFO_MONITOR_ENTER_V4:
target = mono_gc_get_card_table (&card_table_shift_bits, &card_table_mask);
break;
}
+ case MONO_PATCH_INFO_GC_NURSERY_START: {
+ int shift_bits;
+ size_t size;
+
+ target = mono_gc_get_nursery (&shift_bits, &size);
+ break;
+ }
case MONO_PATCH_INFO_CASTCLASS_CACHE: {
target = mono_domain_alloc0 (domain, sizeof (gpointer));
break;
PATCH_INFO(OBJC_SELECTOR_REF, "objc_selector_ref")
PATCH_INFO(METHOD_CODE_SLOT, "method_code_slot")
PATCH_INFO(LDSTR_LIT, "ldstr_lit")
+PATCH_INFO(GC_NURSERY_START, "gc_nursery_start")
PATCH_INFO(NONE, "none")