Merge pull request #1588 from BrzVlad/feature-aot-wbarrier
authorZoltan Varga <vargaz@gmail.com>
Tue, 24 Mar 2015 09:29:29 +0000 (05:29 -0400)
committerZoltan Varga <vargaz@gmail.com>
Tue, 24 Mar 2015 09:29:29 +0000 (05:29 -0400)
AOT write barrier method

17 files changed:
mono/cil/cil-opcodes.xml
mono/cil/opcode.def
mono/metadata/boehm-gc.c
mono/metadata/gc-internal.h
mono/metadata/marshal.c
mono/metadata/method-builder.c
mono/metadata/method-builder.h
mono/metadata/null-gc.c
mono/metadata/sgen-conf.h
mono/metadata/sgen-gc.c
mono/metadata/sgen-gc.h
mono/metadata/sgen-nursery-allocator.c
mono/mini/aot-compiler.c
mono/mini/aot-runtime.c
mono/mini/method-to-ir.c
mono/mini/mini-runtime.c
mono/mini/patch-info.h

index 9114c85c54680f53e51a43cf12faebbcc3dfa24c..5f747c7a9b2458d76a8b1a276ebdd5413ec49f8f 100644 (file)
 <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>
index e9d998f1dd80489aae2c0df2fa62558ac8e277f2..560c1873dc23a423454ce0d0562d1b1f07cc2ef5 100644 (file)
@@ -313,6 +313,9 @@ OPDEF(CEE_MONO_MEMORY_BARRIER, "mono_memory_barrier", Pop0, Push0, InlineI, X, 2
 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)
index 59ca03b80adfd38d3129480c03375bb59b19bbae..e62c554ca1e3a66e8fd0497041bde6f52ea1c4ff 100644 (file)
@@ -1100,6 +1100,13 @@ mono_gc_get_write_barrier (void)
 
 #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)
 {
index 6e8c7351ce629398bc412c61a8718b4f78bdbb8a..956ed92b73f305ec94da20bc76147853dfad3204 100644 (file)
@@ -231,6 +231,7 @@ guint32 mono_gc_get_managed_allocator_types (void);
 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 */
index db333b21334d7b869291f04e5b7ec76f6f5feef3..d017c05bdae69826d5febde9ff428a573cea6302 100644 (file)
@@ -1987,7 +1987,8 @@ emit_thread_interrupt_checkpoint_call (MonoMethodBuilder *mb, gpointer checkpoin
 {
        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);
 
index cb249148882f861ad4723f0f1d52ec3d8afb0313..d66a0ad5b2b639d718f373c6e846713a6e4ce954 100644 (file)
@@ -329,6 +329,19 @@ mono_mb_emit_i4 (MonoMethodBuilder *mb, gint32 data)
        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)
 {
@@ -440,6 +453,13 @@ mono_mb_emit_icon (MonoMethodBuilder *mb, gint32 value)
        }
 }
 
+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)
 {
index 444745cb0b3e4aaaa64bebc92e4753331927439b..46df13a93ccc47ed584e5b8c4514c6c945cda50d 100644 (file)
@@ -113,6 +113,9 @@ mono_mb_emit_exception_full (MonoMethodBuilder *mb, const char *exc_nspace, cons
 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);
 
@@ -137,6 +140,9 @@ mono_mb_emit_i2 (MonoMethodBuilder *mb, gint16 data);
 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);
 
index 12f69e0df3f8f4f784b4e92a0416abbc5ce690c6..1b3fa62221993ebb7fb6f4d3a2608a43e1734cda 100644 (file)
@@ -308,6 +308,13 @@ mono_gc_get_restart_signal (void)
        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)
 {
index b74830f8f6db570e4448a5ea1c267225b10d5b3b..1cfcffb5128e536a1f3c44f5c9fb6eb7782f250d 100644 (file)
@@ -52,15 +52,6 @@ typedef guint64 mword;
  */
 #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
index 2ec945d91ca79c00f4f375ce70da7878d3bdecdf..532e1f74aa5287eba0508c99748a59418f28face 100644 (file)
@@ -1385,11 +1385,7 @@ alloc_nursery (void)
        /* 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;
@@ -1408,11 +1404,7 @@ void*
 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 ();
 }
 
@@ -4760,7 +4752,6 @@ mono_gc_base_init (void)
                                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;
@@ -4776,9 +4767,6 @@ mono_gc_base_init (void)
                                        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;
@@ -5056,97 +5044,67 @@ mono_gc_get_gc_name (void)
        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;
@@ -5158,19 +5116,27 @@ mono_gc_get_write_barrier (void)
 
        // 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;
@@ -5190,12 +5156,19 @@ mono_gc_get_write_barrier (void)
        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);
@@ -5203,7 +5176,7 @@ mono_gc_get_write_barrier (void)
        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]);
        }
@@ -5218,17 +5191,23 @@ mono_gc_get_write_barrier (void)
        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*
index 0a0d746c600a77d3a634de290273995c994373a8..0c99daf3d21fe66847435019e2251fb181a4b3ca 100644 (file)
@@ -243,34 +243,22 @@ extern int num_ready_finalizers;
 #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;
index 26731005a35a02ad27ba5242db19d95acc5cdb17..aa570ad1acd55a16b9dc944bdd9bc95bdd263dd4 100644 (file)
@@ -102,10 +102,8 @@ char *sgen_nursery_end;
 
 #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;
index ef86baa668933a35c545ba5054c6021094d4d883..650e05ca67022f92accf8c6d6f854f6a353a1820 100644 (file)
@@ -3543,6 +3543,12 @@ add_wrappers (MonoAotCompile *acfg)
                        }
                }
 
+               /* 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;
@@ -4499,6 +4505,9 @@ is_direct_callable (MonoAotCompile *acfg, MonoMethod *method, MonoJumpInfo *patc
                        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;
@@ -5073,6 +5082,7 @@ encode_patch (MonoAotCompile *acfg, MonoJumpInfo *patch_info, guint8 *buf, guint
        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);
@@ -5347,7 +5357,8 @@ emit_method_info (MonoAotCompile *acfg, MonoCompile *cfg)
                        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;
@@ -6867,6 +6878,7 @@ compile_method (MonoAotCompile *acfg, MonoMethod *method)
                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 */
@@ -9320,7 +9332,7 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
        {
                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;
 
@@ -9328,18 +9340,23 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
                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);
index df6a61cb9d139b11fd7dc770890c8cbffb8c232c..e429461931065c719b5549e1bce5c6862ddffaeb 100644 (file)
@@ -2020,14 +2020,18 @@ load_aot_module (MonoAssembly *assembly, gpointer user_data)
 
                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];
        }
 
        /*
@@ -3317,6 +3321,7 @@ decode_patch (MonoAotModule *aot_module, MonoMemPool *mp, MonoJumpInfo *ji, guin
        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:
index 2f25ae1d815baaecfe2b7bc6954090b5806c6a62..264cfbed25613d137fc4a0bebe9bb8330e2928c6 100755 (executable)
@@ -3144,7 +3144,7 @@ emit_write_barrier (MonoCompile *cfg, MonoInst *ptr, MonoInst *value)
                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;
@@ -12063,6 +12063,49 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
 
                                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;
 
@@ -12071,13 +12114,6 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                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;
index b29dd830e1b27b5ae9c375900d9392a616e3c4c6..2252b339680f4d2d9852f966ae56553302bf3678 100755 (executable)
@@ -1149,6 +1149,7 @@ mono_patch_info_hash (gconstpointer data)
        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:
@@ -1606,6 +1607,13 @@ mono_resolve_patch_target (MonoMethod *method, MonoDomain *domain, guint8 *code,
                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;
index eebcd5e4e9735b2f83d49f36243eec2d55ac6378..063ebe7c7c1c403bc43defe0bbcff23113b647aa 100644 (file)
@@ -53,4 +53,5 @@ PATCH_INFO(TLS_OFFSET, "tls_offset")
 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")