diff --git a/src/mono/mono/mini/interp/interp.c b/src/mono/mono/mini/interp/interp.c index 0061ed326151b6..f0cac7e5174bd5 100644 --- a/src/mono/mono/mini/interp/interp.c +++ b/src/mono/mono/mini/interp/interp.c @@ -413,7 +413,8 @@ get_context (void) context = g_new0 (ThreadContext, 1); context->stack_start = (guchar*)mono_valloc_aligned (INTERP_STACK_SIZE, MINT_STACK_ALIGNMENT, MONO_MMAP_READ | MONO_MMAP_WRITE, MONO_MEM_ACCOUNT_INTERP_STACK); // A bit for every pointer sized slot in the stack. FIXME don't allocate whole bit array - context->no_ref_slots = (guchar*)mono_valloc (NULL, INTERP_STACK_SIZE / (8 * sizeof (gpointer)), MONO_MMAP_READ | MONO_MMAP_WRITE, MONO_MEM_ACCOUNT_INTERP_STACK); + if (mono_interp_opt & INTERP_OPT_PRECISE_GC) + context->no_ref_slots = (guchar*)mono_valloc (NULL, INTERP_STACK_SIZE / (8 * sizeof (gpointer)), MONO_MMAP_READ | MONO_MMAP_WRITE, MONO_MEM_ACCOUNT_INTERP_STACK); context->stack_end = context->stack_start + INTERP_STACK_SIZE - INTERP_REDZONE_SIZE; context->stack_real_end = context->stack_start + INTERP_STACK_SIZE; /* We reserve a stack slot at the top of the interp stack to make temp objects visible to GC */ @@ -8013,6 +8014,8 @@ interp_parse_options (const char *options) #endif else if (strncmp (arg, "ssa", 3) == 0) opt = INTERP_OPT_SSA; + else if (strncmp (arg, "precise", 7) == 0) + opt = INTERP_OPT_PRECISE_GC; else if (strncmp (arg, "all", 3) == 0) opt = ~INTERP_OPT_NONE; @@ -8556,13 +8559,15 @@ interp_mark_stack (gpointer thread_data, GcScanFunc func, gpointer gc_data, gboo if (!context || !context->stack_start) return; - MonoLMF **lmf_addr = (MonoLMF**)info->tls [TLS_KEY_LMF_ADDR]; - if (lmf_addr) - interp_mark_no_ref_slots (context, *lmf_addr); + if (mono_interp_opt & INTERP_OPT_PRECISE_GC) { + MonoLMF **lmf_addr = (MonoLMF**)info->tls [TLS_KEY_LMF_ADDR]; + if (lmf_addr) + interp_mark_no_ref_slots (context, *lmf_addr); + } int slot_index = 0; for (gpointer *p = (gpointer*)context->stack_start; p < (gpointer*)context->stack_pointer; p++) { - if (context->no_ref_slots [slot_index / 8] & (1 << (slot_index % 8))) + if (context->no_ref_slots && (context->no_ref_slots [slot_index / 8] & (1 << (slot_index % 8)))) ;// This slot is marked as no ref, we don't scan it else func (p, gc_data); diff --git a/src/mono/mono/mini/interp/interp.h b/src/mono/mono/mini/interp/interp.h index 742e93bf06e59a..a09111c490bec4 100644 --- a/src/mono/mono/mini/interp/interp.h +++ b/src/mono/mono/mini/interp/interp.h @@ -42,7 +42,8 @@ enum { INTERP_OPT_JITERPRETER = 64, #endif INTERP_OPT_SSA = 128, - INTERP_OPT_DEFAULT = INTERP_OPT_INLINE | INTERP_OPT_CPROP | INTERP_OPT_SUPER_INSTRUCTIONS | INTERP_OPT_BBLOCKS | INTERP_OPT_TIERING | INTERP_OPT_SIMD | INTERP_OPT_SSA + INTERP_OPT_PRECISE_GC = 256, + INTERP_OPT_DEFAULT = INTERP_OPT_INLINE | INTERP_OPT_CPROP | INTERP_OPT_SUPER_INSTRUCTIONS | INTERP_OPT_BBLOCKS | INTERP_OPT_TIERING | INTERP_OPT_SIMD | INTERP_OPT_SSA | INTERP_OPT_PRECISE_GC #if HOST_BROWSER | INTERP_OPT_JITERPRETER #endif diff --git a/src/mono/mono/mini/interp/transform.c b/src/mono/mono/mini/interp/transform.c index 86f00bfdea0f80..1bc0d6d20ef901 100644 --- a/src/mono/mono/mini/interp/transform.c +++ b/src/mono/mono/mini/interp/transform.c @@ -8549,6 +8549,9 @@ interp_mark_ref_slots_for_vt (TransformData *td, int base_offset, MonoClass *kla void interp_mark_ref_slots_for_var (TransformData *td, int var) { + if (!(mono_interp_opt & INTERP_OPT_PRECISE_GC)) + return; + g_assert (td->vars [var].offset != -1); gsize max_index = (td->vars [var].offset + td->vars [var].size) / sizeof (gpointer);