<opcode name="mono_jit_attach" input="Pop0" output="Push0" args="InlineNone" o1="0xF0" o2="0x11" flow="next" />
<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_ATTACH, "mono_jit_attach", Pop0, Push0, InlineNone, X, 2, 0xF0, 0x11, NEXT)
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)
#endif
+MonoMethod*
+mono_gc_get_specific_write_barrier (gboolean is_concurrent)
+{
+ g_assert_not_reached ();
+ return NULL;
+}
+
int
mono_gc_get_aligned_size_for_allocator (int size)
{
const char *mono_gc_get_gc_name (void);
/* Fast write barriers */
+MonoMethod* mono_gc_get_specific_write_barrier (gboolean is_concurrent);
MonoMethod* mono_gc_get_write_barrier (void);
/* Fast valuetype copy */
{
int pos_noabort, pos_noex;
- mono_mb_emit_ptr (mb, (gpointer) mono_thread_interruption_request_flag ());
+ mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
+ mono_mb_emit_byte (mb, CEE_MONO_LDPTR_INT_REQ_FLAG);
mono_mb_emit_byte (mb, CEE_LDIND_U4);
pos_noabort = mono_mb_emit_branch (mb, CEE_BRFALSE);
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);
return -1;
}
+MonoMethod*
+mono_gc_get_specific_write_barrier (gboolean is_concurrent)
+{
+ g_assert_not_reached ();
+ return NULL;
+}
+
MonoMethod*
mono_gc_get_write_barrier (void)
{
*/
#define USER_CONFIG 1
-
-/*
- * If this is set, the nursery is aligned to an address aligned to its size, ie.
- * a 1MB nursery will be aligned to an address divisible by 1MB. This allows us to
- * speed up ptr_in_nursery () checks which are very frequent. This requires the
- * nursery size to be a compile time constant.
- */
-#define SGEN_ALIGN_NURSERY 1
-
/*
* The binary protocol enables logging a lot of the GC ativity in a way that is not very
* intrusive and produces a compact file that can be searched using a custom tool. This
/* If there isn't enough space even for the nursery we should simply abort. */
g_assert (sgen_memgov_try_alloc_space (alloc_size, SPACE_NURSERY));
-#ifdef SGEN_ALIGN_NURSERY
data = major_collector.alloc_heap (alloc_size, alloc_size, DEFAULT_NURSERY_BITS);
-#else
- data = major_collector.alloc_heap (alloc_size, 0, DEFAULT_NURSERY_BITS);
-#endif
sgen_update_heap_boundaries ((mword)data, (mword)(data + sgen_nursery_size));
SGEN_LOG (4, "Expanding nursery size (%p-%p): %lu, total: %lu", data, data + alloc_size, (unsigned long)sgen_nursery_size, (unsigned long)mono_gc_get_heap_size ());
section->data = section->next_data = data;
mono_gc_get_nursery (int *shift_bits, size_t *size)
{
*size = sgen_nursery_size;
-#ifdef SGEN_ALIGN_NURSERY
*shift_bits = DEFAULT_NURSERY_BITS;
-#else
- *shift_bits = -1;
-#endif
return sgen_get_nursery_start ();
}
size_t val;
opt = strchr (opt, '=') + 1;
if (*opt && mono_gc_parse_environment_string_extract_number (opt, &val)) {
-#ifdef SGEN_ALIGN_NURSERY
if ((val & (val - 1))) {
sgen_env_var_error (MONO_GC_PARAMS_NAME, "Using default value.", "`nursery-size` must be a power of two.");
continue;
sgen_nursery_bits = 0;
while (ONE_P << (++ sgen_nursery_bits) != sgen_nursery_size)
;
-#else
- sgen_nursery_size = val;
-#endif
} else {
sgen_env_var_error (MONO_GC_PARAMS_NAME, "Using default value.", "`nursery-size` must be an integer.");
continue;
return "sgen";
}
-static MonoMethod *write_barrier_method;
+static MonoMethod *write_barrier_conc_method;
+static MonoMethod *write_barrier_noconc_method;
gboolean
sgen_is_critical_method (MonoMethod *method)
{
- return (method == write_barrier_method || sgen_is_managed_allocator (method));
+ return (method == write_barrier_conc_method || method == write_barrier_noconc_method || sgen_is_managed_allocator (method));
}
gboolean
sgen_has_critical_method (void)
{
- return write_barrier_method || sgen_has_managed_allocator ();
+ return write_barrier_conc_method || write_barrier_noconc_method || sgen_has_managed_allocator ();
}
#ifndef DISABLE_JIT
static void
-emit_nursery_check (MonoMethodBuilder *mb, int *nursery_check_return_labels)
+emit_nursery_check (MonoMethodBuilder *mb, int *nursery_check_return_labels, gboolean is_concurrent)
{
- memset (nursery_check_return_labels, 0, sizeof (int) * 3);
-#ifdef SGEN_ALIGN_NURSERY
+ 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 (!major_collector.is_concurrent) {
+ if (!is_concurrent) {
// if (!ptr_in_nursery (*ptr)) return;
mono_mb_emit_ldarg (mb, 0);
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);
}
-#else
- int label_continue1, label_continue2;
- int dereferenced_var;
-
- // if (ptr < (sgen_get_nursery_start ())) goto continue;
- mono_mb_emit_ldarg (mb, 0);
- mono_mb_emit_ptr (mb, (gpointer) sgen_get_nursery_start ());
- label_continue_1 = mono_mb_emit_branch (mb, CEE_BLT);
-
- // if (ptr >= sgen_get_nursery_end ())) goto continue;
- mono_mb_emit_ldarg (mb, 0);
- mono_mb_emit_ptr (mb, (gpointer) sgen_get_nursery_end ());
- label_continue_2 = mono_mb_emit_branch (mb, CEE_BGE);
-
- // Otherwise return
- nursery_check_return_labels [0] = mono_mb_emit_branch (mb, CEE_BR);
-
- // continue:
- mono_mb_patch_branch (mb, label_continue_1);
- mono_mb_patch_branch (mb, label_continue_2);
-
- // Dereference and store in local var
- dereferenced_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
- mono_mb_emit_ldarg (mb, 0);
- mono_mb_emit_byte (mb, CEE_LDIND_I);
- mono_mb_emit_stloc (mb, dereferenced_var);
-
- if (!major_collector.is_concurrent) {
- // if (*ptr < sgen_get_nursery_start ()) return;
- mono_mb_emit_ldloc (mb, dereferenced_var);
- mono_mb_emit_ptr (mb, (gpointer) sgen_get_nursery_start ());
- nursery_check_return_labels [1] = mono_mb_emit_branch (mb, CEE_BLT);
-
- // if (*ptr >= sgen_get_nursery_end ()) return;
- mono_mb_emit_ldloc (mb, dereferenced_var);
- mono_mb_emit_ptr (mb, (gpointer) sgen_get_nursery_end ());
- nursery_check_return_labels [2] = mono_mb_emit_branch (mb, CEE_BGE);
- }
-#endif
}
#endif
MonoMethod*
-mono_gc_get_write_barrier (void)
+mono_gc_get_specific_write_barrier (gboolean is_concurrent)
{
MonoMethod *res;
MonoMethodBuilder *mb;
MonoMethodSignature *sig;
+ MonoMethod **write_barrier_method_addr;
#ifdef MANAGED_WBARRIER
- int i, nursery_check_labels [3];
+ int i, nursery_check_labels [2];
#ifdef HAVE_KW_THREAD
int stack_end_offset = -1;
// FIXME: Maybe create a separate version for ctors (the branch would be
// correctly predicted more times)
- if (write_barrier_method)
- return write_barrier_method;
+ if (is_concurrent)
+ write_barrier_method_addr = &write_barrier_conc_method;
+ else
+ write_barrier_method_addr = &write_barrier_noconc_method;
+
+ if (*write_barrier_method_addr)
+ return *write_barrier_method_addr;
/* Create the IL version of mono_gc_barrier_generic_store () */
sig = mono_metadata_signature_alloc (mono_defaults.corlib, 1);
sig->ret = &mono_defaults.void_class->byval_arg;
sig->params [0] = &mono_defaults.int_class->byval_arg;
- mb = mono_mb_new (mono_defaults.object_class, "wbarrier", MONO_WRAPPER_WRITE_BARRIER);
+ if (is_concurrent)
+ mb = mono_mb_new (mono_defaults.object_class, "wbarrier_conc", MONO_WRAPPER_WRITE_BARRIER);
+ else
+ mb = mono_mb_new (mono_defaults.object_class, "wbarrier_noconc", MONO_WRAPPER_WRITE_BARRIER);
#ifndef DISABLE_JIT
#ifdef MANAGED_WBARRIER
- emit_nursery_check (mb, nursery_check_labels);
+ emit_nursery_check (mb, nursery_check_labels, is_concurrent);
/*
addr = sgen_cardtable + ((address >> CARD_BITS) & CARD_MASK)
*addr = 1;
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);
mono_mb_emit_byte (mb, CEE_STIND_I1);
// return;
- for (i = 0; i < 3; ++i) {
+ for (i = 0; i < 2; ++i) {
if (nursery_check_labels [i])
mono_mb_patch_branch (mb, nursery_check_labels [i]);
}
mono_mb_free (mb);
LOCK_GC;
- if (write_barrier_method) {
+ if (*write_barrier_method_addr) {
/* Already created */
mono_free_method (res);
} else {
/* double-checked locking */
mono_memory_barrier ();
- write_barrier_method = res;
+ *write_barrier_method_addr = res;
}
UNLOCK_GC;
- return write_barrier_method;
+ return *write_barrier_method_addr;
+}
+
+MonoMethod*
+mono_gc_get_write_barrier (void)
+{
+ return mono_gc_get_specific_write_barrier (major_collector.is_concurrent);
}
char*
#define HIDE_POINTER(p,t) ((gpointer)(~((size_t)(p)|((t)?1:0))))
#define REVEAL_POINTER(p) ((gpointer)((~(size_t)(p))&~3L))
-#ifdef SGEN_ALIGN_NURSERY
#define SGEN_PTR_IN_NURSERY(p,bits,start,end) (((mword)(p) & ~((1 << (bits)) - 1)) == (mword)(start))
-#else
-#define SGEN_PTR_IN_NURSERY(p,bits,start,end) ((char*)(p) >= (start) && (char*)(p) < (end))
-#endif
#ifdef USER_CONFIG
/* good sizes are 512KB-1MB: larger ones increase a lot memzeroing time */
#define DEFAULT_NURSERY_SIZE (sgen_nursery_size)
extern size_t sgen_nursery_size;
-#ifdef SGEN_ALIGN_NURSERY
/* The number of trailing 0 bits in DEFAULT_NURSERY_SIZE */
#define DEFAULT_NURSERY_BITS (sgen_nursery_bits)
extern int sgen_nursery_bits;
-#endif
#else
#define DEFAULT_NURSERY_SIZE (4*1024*1024)
-#ifdef SGEN_ALIGN_NURSERY
#define DEFAULT_NURSERY_BITS 22
-#endif
-
-#endif
-#ifndef SGEN_ALIGN_NURSERY
-#define DEFAULT_NURSERY_BITS -1
#endif
extern char *sgen_nursery_start;
#ifdef USER_CONFIG
size_t sgen_nursery_size = (1 << 22);
-#ifdef SGEN_ALIGN_NURSERY
int sgen_nursery_bits = 22;
#endif
-#endif
char *sgen_space_bitmap;
size_t sgen_space_bitmap_size;
}
}
+ /* 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 */
{
MonoJumpInfo *ji;
- ji = mono_mempool_alloc0 (acfg->mempool, sizeof (MonoAotCompile));
+ ji = mono_mempool_alloc0 (acfg->mempool, sizeof (MonoJumpInfo));
ji->type = MONO_PATCH_INFO_IMAGE;
ji->data.image = acfg->image;
get_got_offset (acfg, TRUE, ji);
/* Slot 1 is reserved for the mscorlib got addr */
- ji = mono_mempool_alloc0 (acfg->mempool, sizeof (MonoAotCompile));
+ ji = mono_mempool_alloc0 (acfg->mempool, sizeof (MonoJumpInfo));
ji->type = MONO_PATCH_INFO_MSCORLIB_GOT_ADDR;
get_got_offset (acfg, FALSE, ji);
get_got_offset (acfg, TRUE, ji);
/* This is very common */
- ji = mono_mempool_alloc0 (acfg->mempool, sizeof (MonoAotCompile));
+ ji = mono_mempool_alloc0 (acfg->mempool, sizeof (MonoJumpInfo));
ji->type = MONO_PATCH_INFO_GC_CARD_TABLE_ADDR;
get_got_offset (acfg, FALSE, ji);
get_got_offset (acfg, TRUE, ji);
- ji = mono_mempool_alloc0 (acfg->mempool, sizeof (MonoAotCompile));
+ 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);
get_got_offset (acfg, TRUE, 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:
wbarrier->sreg1 = ptr->dreg;
wbarrier->sreg2 = value->dreg;
MONO_ADD_INS (cfg->cbb, wbarrier);
- } else if (card_table) {
+ } else if (card_table && !cfg->compile_aot && !mono_gc_card_table_nursery_check ()) {
int offset_reg = alloc_preg (cfg);
int card_reg = alloc_preg (cfg);
MonoInst *ins;
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);
+
+ if (cfg->compile_aot)
+ EMIT_NEW_AOTCONST (cfg, ins, MONO_PATCH_INFO_INTERRUPTION_REQUEST_FLAG, NULL);
+ else
+ EMIT_NEW_PCONST (cfg, ins, mono_thread_interruption_request_flag ());
+
+ *sp++ = ins;
+ ip += 2;
+ inline_costs += 10 * num_calls++;
+ break;
+ }
case CEE_MONO_LDPTR: {
gpointer ptr;
token = read32 (ip + 2);
ptr = mono_method_get_wrapper_data (method, token);
- /* FIXME: Generalize this */
- if (cfg->compile_aot && ptr == mono_thread_interruption_request_flag ()) {
- EMIT_NEW_AOTCONST (cfg, ins, MONO_PATCH_INFO_INTERRUPTION_REQUEST_FLAG, NULL);
- *sp++ = ins;
- ip += 6;
- break;
- }
EMIT_NEW_PCONST (cfg, ins, ptr);
*sp++ = ins;
ip += 6;
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")