Merge pull request #2246 from BrzVlad/feature-concurrent-evacuation
authorVlad Brezae <brezaevlad@gmail.com>
Mon, 7 Dec 2015 22:09:17 +0000 (17:09 -0500)
committerVlad Brezae <brezaevlad@gmail.com>
Mon, 7 Dec 2015 22:09:17 +0000 (17:09 -0500)
Feature evacuation with concurrent sgen

16 files changed:
mcs/class/corlib/Mono/Runtime.cs
mono/metadata/boehm-gc.c
mono/metadata/gc-internals.h
mono/metadata/gc.c
mono/metadata/icall-def.h
mono/metadata/null-gc.c
mono/metadata/sgen-client-mono.h
mono/metadata/sgen-mono.c
mono/sgen/sgen-cardtable.c
mono/sgen/sgen-gc.c
mono/sgen/sgen-gc.h
mono/sgen/sgen-marksweep-drain-gray-stack.h
mono/sgen/sgen-marksweep-scan-object-concurrent.h
mono/sgen/sgen-marksweep.c
mono/sgen/sgen-minor-scan-object.h
mono/sgen/sgen-protocol-def.h

index 80e56a559ac900ae0c4779d6a7e7bb66a58b177b..7a5f9887c6334fff01b0f7f9835659b44fac9be3 100644 (file)
@@ -59,7 +59,10 @@ namespace Mono {
                [MethodImplAttribute (MethodImplOptions.InternalCall)]
                static extern string GetNativeStackTrace (Exception exception);
 
-               [MethodImplAttribute (MethodImplOptions.InternalCall)]
-               public static extern bool SetGCAllowSynchronousMajor (bool flag);
+               public static bool SetGCAllowSynchronousMajor (bool flag)
+               {
+                       // No longer used
+                       return true;
+               }
        }
 }
index 0401c5cf2d777df2b013c8ec612d2a7842e17156..a29e83ed57b15d986ac30ed6c8ec943e078d6feb 100644 (file)
@@ -1427,11 +1427,6 @@ mono_gc_make_root_descr_user (MonoGCRootMarkFunc marker)
        return NULL;
 }
 
-gboolean
-mono_gc_set_allow_synchronous_major (gboolean flag)
-{
-       return flag;
-}
 /* Toggleref support */
 
 void
index b4ded9b5772bdfe5903425bf8274f25a45e2111a..bc9edcbe3ad1a1fb289d37dd8adc04e5fd2cb0e3 100644 (file)
@@ -80,7 +80,6 @@ gpointer    ves_icall_System_GCHandle_GetAddrOfPinnedObject (guint32 handle);
 void        ves_icall_System_GC_register_ephemeron_array (MonoObject *array);
 MonoObject  *ves_icall_System_GC_get_ephemeron_tombstone (void);
 
-MonoBoolean ves_icall_Mono_Runtime_SetGCAllowSynchronousMajor (MonoBoolean flag);
 
 extern void mono_gc_init (void);
 extern void mono_gc_base_init (void);
@@ -111,9 +110,6 @@ void mono_gchandle_set_target (guint32 gchandle, MonoObject *obj);
 /*Ephemeron functionality. Sgen only*/
 gboolean    mono_gc_ephemeron_array_add (MonoObject *obj);
 
-/* To disable synchronous, evacuating collections - concurrent SGen only */
-gboolean    mono_gc_set_allow_synchronous_major (gboolean flag);
-
 MonoBoolean
 mono_gc_GCHandle_CheckCurrentDomain (guint32 gchandle);
 
index a82c420111495eaecc0c7f5775fb246f31ecfea2..deca78d4e4ec2f64f50b47dde0042364e110d3db 100644 (file)
@@ -601,12 +601,6 @@ ves_icall_System_GCHandle_GetAddrOfPinnedObject (guint32 handle)
        return NULL;
 }
 
-MonoBoolean
-ves_icall_Mono_Runtime_SetGCAllowSynchronousMajor (MonoBoolean flag)
-{
-       return mono_gc_set_allow_synchronous_major (flag);
-}
-
 MonoBoolean
 mono_gc_GCHandle_CheckCurrentDomain (guint32 gchandle)
 {
index 489b5ded65b19fcf2edf5080854849470530a86d..88fb2539e83319225eda11d4e5f8247949b2eee9 100644 (file)
@@ -46,7 +46,6 @@ ICALL(COMPROX_2, "FindProxy", ves_icall_Mono_Interop_ComInteropProxy_FindProxy)
 ICALL_TYPE(RUNTIME, "Mono.Runtime", RUNTIME_1)
 ICALL(RUNTIME_1, "GetDisplayName", ves_icall_Mono_Runtime_GetDisplayName)
 ICALL(RUNTIME_12, "GetNativeStackTrace", ves_icall_Mono_Runtime_GetNativeStackTrace)
-ICALL(RUNTIME_13, "SetGCAllowSynchronousMajor", ves_icall_Mono_Runtime_SetGCAllowSynchronousMajor)
 
 #ifndef PLATFORM_RO_FS
 ICALL_TYPE(KPAIR, "Mono.Security.Cryptography.KeyPairPersistence", KPAIR_1)
index 773410ad7b6fcfb9c073ebc42025e51dd1e22400..e5c16e1e9a46b2eab51c6249b54115f6ed82bad6 100644 (file)
@@ -528,12 +528,6 @@ mono_gc_register_altstack (gpointer stack, gint32 stack_size, gpointer altstack,
 {
 }
 
-gboolean
-mono_gc_set_allow_synchronous_major (gboolean flag)
-{
-       return TRUE;
-}
-
 gboolean
 mono_gc_is_null (void)
 {
index 7dcf6ce4009ead67e36860bd8e9e90a5159187ca..d1e92469b744e4f4d865a6e70e05f39199c663c2 100644 (file)
@@ -560,6 +560,11 @@ sgen_client_binary_protocol_global_remset (gpointer ptr, gpointer value, gpointe
 #endif
 }
 
+static void G_GNUC_UNUSED
+sgen_client_binary_protocol_mod_union_remset (gpointer obj, gpointer ptr, gpointer value, gpointer value_vtable)
+{
+}
+
 static void G_GNUC_UNUSED
 sgen_client_binary_protocol_ptr_update (gpointer ptr, gpointer old_value, gpointer new_value, gpointer vtable, size_t size)
 {
index a133f91030f05fa31fe6f79c734dfb0b29211203..456fe45c7ee19efb176f231af0837f2e035419ae 100644 (file)
@@ -2687,12 +2687,6 @@ sgen_client_ensure_weak_gchandles_accessible (void)
                mono_gc_wait_for_bridge_processing ();
 }
 
-gboolean
-mono_gc_set_allow_synchronous_major (gboolean flag)
-{
-       return sgen_set_allow_synchronous_major (flag);
-}
-
 void*
 mono_gc_invoke_with_gc_lock (MonoGCLockedCallbackFunc func, void *data)
 {
index 21da2d0df848ba32e69c2126d1d8d9fb3ffeee3e..a5bc104d98b5f8ae04ab1e1a9d6c72a571619428 100644 (file)
@@ -292,8 +292,11 @@ static void
 update_mod_union (guint8 *dest, guint8 *start_card, size_t num_cards)
 {
        int i;
-       for (i = 0; i < num_cards; ++i)
-               dest [i] |= start_card [i];
+       /* Marking from another thread can happen while we mark here */
+       for (i = 0; i < num_cards; ++i) {
+               if (start_card [i])
+                       dest [i] = 1;
+       }
 }
 
 guint8*
index d559a9285ee4fdea5299d0b674adaa01531c5a67..7189811c50e98cacd2faa9ecbe9d3db45fae72a4 100644 (file)
@@ -239,12 +239,6 @@ static gboolean do_concurrent_checks = FALSE;
    each collection */
 static gboolean do_scan_starts_check = FALSE;
 
-/*
- * If the major collector is concurrent and this is FALSE, we will
- * never initiate a synchronous major collection, unless requested via
- * GC.Collect().
- */
-static gboolean allow_synchronous_major = TRUE;
 static gboolean disable_minor_collections = FALSE;
 static gboolean disable_major_collections = FALSE;
 static gboolean do_verify_nursery = FALSE;
@@ -2244,17 +2238,6 @@ sgen_perform_collection (size_t requested_size, int generation_to_collect, const
                goto done;
        }
 
-       /*
-        * If we've been asked to do a major collection, and the major collector wants to
-        * run synchronously (to evacuate), we set the flag to do that.
-        */
-       if (generation_to_collect == GENERATION_OLD &&
-                       allow_synchronous_major &&
-                       major_collector.want_synchronous_collection &&
-                       *major_collector.want_synchronous_collection) {
-               wait_to_finish = TRUE;
-       }
-
        SGEN_ASSERT (0, !concurrent_collection_in_progress, "Why did this not get handled above?");
 
        /*
@@ -2726,16 +2709,6 @@ sgen_gc_get_used_size (void)
        return tot;
 }
 
-gboolean
-sgen_set_allow_synchronous_major (gboolean flag)
-{
-       if (!major_collector.is_concurrent)
-               return flag;
-
-       allow_synchronous_major = flag;
-       return TRUE;
-}
-
 void
 sgen_env_var_error (const char *env_var, const char *fallback, const char *description_format, ...)
 {
@@ -2952,23 +2925,6 @@ sgen_gc_init (void)
                                }
                                continue;
                        }
-                       if (g_str_has_prefix (opt, "allow-synchronous-major=")) {
-                               if (!major_collector.is_concurrent) {
-                                       sgen_env_var_error (MONO_GC_PARAMS_NAME, "Ignoring.", "`allow-synchronous-major` is only valid for the concurrent major collector.");
-                                       continue;
-                               }
-
-                               opt = strchr (opt, '=') + 1;
-
-                               if (!strcmp (opt, "yes")) {
-                                       allow_synchronous_major = TRUE;
-                               } else if (!strcmp (opt, "no")) {
-                                       allow_synchronous_major = FALSE;
-                               } else {
-                                       sgen_env_var_error (MONO_GC_PARAMS_NAME, "Using default value.", "`allow-synchronous-major` must be either `yes' or `no'.");
-                                       continue;
-                               }
-                       }
 
                        if (!strcmp (opt, "cementing")) {
                                cement_enabled = TRUE;
@@ -3001,8 +2957,6 @@ sgen_gc_init (void)
                        fprintf (stderr, "  minor=COLLECTOR (where COLLECTOR is `simple' or `split')\n");
                        fprintf (stderr, "  wbarrier=WBARRIER (where WBARRIER is `remset' or `cardtable')\n");
                        fprintf (stderr, "  [no-]cementing\n");
-                       if (major_collector.is_concurrent)
-                               fprintf (stderr, "  allow-synchronous-major=FLAG (where FLAG is `yes' or `no')\n");
                        if (major_collector.print_gc_param_usage)
                                major_collector.print_gc_param_usage ();
                        if (sgen_minor_collector.print_gc_param_usage)
index 0b5d182ff4a4290444afa3d34372c103af041aa0..089ba85a1fbebfb5cee6aa5f7ee5dfc0945dcc19 100644 (file)
@@ -599,13 +599,6 @@ struct _SgenMajorCollector {
        gboolean supports_cardtable;
        gboolean sweeps_lazily;
 
-       /*
-        * This is set to TRUE by the sweep if the next major
-        * collection should be synchronous (for evacuation).  For
-        * non-concurrent collectors, this should be NULL.
-        */
-       gboolean *want_synchronous_collection;
-
        void* (*alloc_heap) (mword nursery_size, mword nursery_align, int nursery_bits);
        gboolean (*is_object_live) (GCObject *obj);
        GCObject* (*alloc_small_pinned_obj) (GCVTable vtable, size_t size, gboolean has_references);
index dce3be7344ad528c712be144fd775d38becfa295..bfddff0d891dcfd36a2c1fb05e0f7c1a11ee6571 100644 (file)
@@ -166,16 +166,21 @@ COPY_OR_MARK_FUNCTION_NAME (GCObject **ptr, GCObject *obj, SgenGrayQueue *queue)
 
                        block = MS_BLOCK_FOR_OBJ (obj);
 
+#ifdef COPY_OR_MARK_CONCURRENT
+                       if (G_UNLIKELY (major_block_is_evacuating (block))) {
+                               /*
+                                * We don't copy within the concurrent phase. These objects will
+                                * be handled below in the finishing pause, by scanning the mod-union
+                                * card table.
+                                */
+                               return FALSE;
+                       }
+#endif
+
 #ifdef COPY_OR_MARK_WITH_EVACUATION
-                       {
-                               int size_index = block->obj_size_index;
-
-                               if (evacuate_block_obj_sizes [size_index] && !block->has_pinned) {
-                                       HEAVY_STAT (++stat_optimized_copy_major_small_evacuate);
-                                       if (block->is_to_space)
-                                               return FALSE;
-                                       goto do_copy_object;
-                               }
+                       if (major_block_is_evacuating (block)) {
+                               HEAVY_STAT (++stat_optimized_copy_major_small_evacuate);
+                               goto do_copy_object;
                        }
 #endif
 
@@ -218,19 +223,26 @@ SCAN_OBJECT_FUNCTION_NAME (GCObject *full_object, SgenDescriptor desc, SgenGrayQ
 #ifdef COPY_OR_MARK_CONCURRENT
 #define HANDLE_PTR(ptr,obj)    do {                                    \
                GCObject *__old = *(ptr);                               \
-               binary_protocol_scan_process_reference ((obj), (ptr), __old); \
+               binary_protocol_scan_process_reference ((full_object), (ptr), __old); \
                if (__old && !sgen_ptr_in_nursery (__old)) {            \
-                       PREFETCH_READ (__old);                          \
-                       COPY_OR_MARK_FUNCTION_NAME ((ptr), __old, queue); \
+                       MSBlockInfo *block = MS_BLOCK_FOR_OBJ (__old);  \
+                       if (G_UNLIKELY (!sgen_ptr_in_nursery (ptr) &&   \
+                                       sgen_safe_object_is_small (__old, sgen_obj_get_descriptor (__old) & DESC_TYPE_MASK) && \
+                                       major_block_is_evacuating (block))) { \
+                               mark_mod_union_card ((full_object), (void**)(ptr), __old); \
+                       } else {                                        \
+                               PREFETCH_READ (__old);                  \
+                               COPY_OR_MARK_FUNCTION_NAME ((ptr), __old, queue); \
+                       }                                               \
                } else {                                                \
                        if (G_UNLIKELY (sgen_ptr_in_nursery (__old) && !sgen_ptr_in_nursery ((ptr)))) \
-                               mark_mod_union_card ((full_object), (void**)(ptr)); \
+                               mark_mod_union_card ((full_object), (void**)(ptr), __old); \
                        }                                               \
                } while (0)
 #else
 #define HANDLE_PTR(ptr,obj)    do {                                    \
                void *__old = *(ptr);                                   \
-               binary_protocol_scan_process_reference ((obj), (ptr), __old); \
+               binary_protocol_scan_process_reference ((full_object), (ptr), __old); \
                if (__old) {                                            \
                        gboolean __still_in_nursery = COPY_OR_MARK_FUNCTION_NAME ((ptr), __old, queue); \
                        if (G_UNLIKELY (__still_in_nursery && !sgen_ptr_in_nursery ((ptr)) && !SGEN_OBJECT_IS_CEMENTED (*(ptr)))) { \
index 8ebd8eee2a14a2a05ae799eb74d6f12b6076bd73..ab234e126952acb6c0ce29ecf28ef371ec0740df 100644 (file)
@@ -33,9 +33,9 @@
 #undef HANDLE_PTR
 #define HANDLE_PTR(ptr,obj)     do {                                    \
                 void *__old = *(ptr);                                   \
-                binary_protocol_scan_process_reference ((obj), (ptr), __old); \
+                binary_protocol_scan_process_reference ((full_object), (ptr), __old); \
                 if (__old) {                                            \
-                        gboolean __still_in_nursery = major_copy_or_mark_object_no_evacuation ((ptr), __old, queue); \
+                        gboolean __still_in_nursery = major_copy_or_mark_object_with_evacuation ((ptr), __old, queue); \
                         if (G_UNLIKELY (__still_in_nursery && !sgen_ptr_in_nursery ((ptr)) && !SGEN_OBJECT_IS_CEMENTED (*(ptr)))) { \
                                 void *__copy = *(ptr);                  \
                                 sgen_add_to_global_remset ((ptr), __copy); \
index 780e4adff1ee62e73eef9eb02e94dd9a76de237e..5b344b6d6580c068ac38a6f2a0321337c909290d 100644 (file)
@@ -170,8 +170,6 @@ static int fast_block_obj_size_indexes [MS_NUM_FAST_BLOCK_OBJ_SIZE_INDEXES];
 
 static gboolean *evacuate_block_obj_sizes;
 static float evacuation_threshold = 0.666f;
-static float concurrent_evacuation_threshold = 0.666f;
-static gboolean want_evacuation = FALSE;
 
 static gboolean lazy_sweep = FALSE;
 
@@ -245,7 +243,6 @@ static MSBlockInfo * volatile *free_block_lists [MS_BLOCK_TYPE_MAX];
 static guint64 stat_major_blocks_alloced = 0;
 static guint64 stat_major_blocks_freed = 0;
 static guint64 stat_major_blocks_lazy_swept = 0;
-static guint64 stat_major_objects_evacuated = 0;
 
 #if SIZEOF_VOID_P != 8
 static guint64 stat_major_blocks_freed_ideal = 0;
@@ -533,10 +530,11 @@ ms_alloc_block (int size_index, gboolean pinned, gboolean has_references)
         * Blocks that are to-space are not evacuated from.  During an major collection
         * blocks are allocated for two reasons: evacuating objects from the nursery and
         * evacuating them from major blocks marked for evacuation.  In both cases we don't
-        * want further evacuation.
+        * want further evacuation. We also don't want to evacuate objects allocated during
+        * the concurrent mark since it would add pointless stress on the finishing pause.
         */
-       info->is_to_space = (sgen_get_current_collection_generation () == GENERATION_OLD);
-       info->state = (info->is_to_space || sgen_concurrent_collection_in_progress ()) ? BLOCK_STATE_MARKING : BLOCK_STATE_SWEPT;
+       info->is_to_space = (sgen_get_current_collection_generation () == GENERATION_OLD) || sgen_concurrent_collection_in_progress ();
+       info->state = info->is_to_space ? BLOCK_STATE_MARKING : BLOCK_STATE_SWEPT;
        SGEN_ASSERT (6, !sweep_in_progress () || info->state == BLOCK_STATE_SWEPT, "How do we add a new block to be swept while sweeping?");
        info->cardtable_mod_union = NULL;
 
@@ -1067,7 +1065,7 @@ major_get_cardtable_mod_union_for_reference (char *ptr)
  * Mark the mod-union card for `ptr`, which must be a reference within the object `obj`.
  */
 static void
-mark_mod_union_card (GCObject *obj, void **ptr)
+mark_mod_union_card (GCObject *obj, void **ptr, GCObject *value_obj)
 {
        int type = sgen_obj_get_descriptor (obj) & DESC_TYPE_MASK;
        if (sgen_safe_object_is_small (obj, type)) {
@@ -1077,6 +1075,18 @@ mark_mod_union_card (GCObject *obj, void **ptr)
        } else {
                sgen_los_mark_mod_union_card (obj, ptr);
        }
+
+       binary_protocol_mod_union_remset (obj, ptr, value_obj, SGEN_LOAD_VTABLE (value_obj));
+}
+
+static inline gboolean
+major_block_is_evacuating (MSBlockInfo *block)
+{
+       if (evacuate_block_obj_sizes [block->obj_size_index] &&
+                       !block->has_pinned &&
+                       !block->is_to_space)
+               return TRUE;
+       return FALSE;
 }
 
 #define LOAD_VTABLE    SGEN_LOAD_VTABLE
@@ -1166,8 +1176,6 @@ static guint64 stat_drain_prefetch_fill_failures;
 static guint64 stat_drain_loops;
 #endif
 
-static void major_scan_object_with_evacuation (GCObject *start, mword desc, SgenGrayQueue *queue);
-
 #define COPY_OR_MARK_FUNCTION_NAME     major_copy_or_mark_object_no_evacuation
 #define SCAN_OBJECT_FUNCTION_NAME      major_scan_object_no_evacuation
 #define DRAIN_GRAY_STACK_FUNCTION_NAME drain_gray_stack_no_evacuation
@@ -1221,7 +1229,7 @@ major_copy_or_mark_object_concurrent_canonical (GCObject **ptr, SgenGrayQueue *q
 static void
 major_copy_or_mark_object_concurrent_finish_canonical (GCObject **ptr, SgenGrayQueue *queue)
 {
-       major_copy_or_mark_object_no_evacuation (ptr, *ptr, queue);
+       major_copy_or_mark_object_with_evacuation (ptr, *ptr, queue);
 }
 
 static void
@@ -1610,8 +1618,6 @@ sweep_job_func (void *thread_data_untyped, SgenThreadPoolJob *job)
 static void
 sweep_finish (void)
 {
-       mword total_evacuate_heap = 0;
-       mword total_evacuate_saved = 0;
        int i;
 
        for (i = 0; i < num_block_obj_sizes; ++i) {
@@ -1625,16 +1631,8 @@ sweep_finish (void)
                } else {
                        evacuate_block_obj_sizes [i] = FALSE;
                }
-               {
-                       mword total_bytes = block_obj_sizes [i] * sweep_slots_available [i];
-                       total_evacuate_heap += total_bytes;
-                       if (evacuate_block_obj_sizes [i])
-                               total_evacuate_saved += total_bytes - block_obj_sizes [i] * sweep_slots_used [i];
-               }
        }
 
-       want_evacuation = (float)total_evacuate_saved / (float)total_evacuate_heap > (1 - concurrent_evacuation_threshold);
-
        set_sweep_state (SWEEP_STATE_SWEPT, SWEEP_STATE_COMPACTING);
 }
 
@@ -2411,7 +2409,6 @@ sgen_marksweep_init_internal (SgenMajorCollector *collector, gboolean is_concurr
        mono_counters_register ("# major blocks allocated", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &stat_major_blocks_alloced);
        mono_counters_register ("# major blocks freed", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &stat_major_blocks_freed);
        mono_counters_register ("# major blocks lazy swept", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &stat_major_blocks_lazy_swept);
-       mono_counters_register ("# major objects evacuated", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &stat_major_objects_evacuated);
 #if SIZEOF_VOID_P != 8
        mono_counters_register ("# major blocks freed ideally", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &stat_major_blocks_freed_ideal);
        mono_counters_register ("# major blocks freed less ideally", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &stat_major_blocks_freed_less_ideal);
@@ -2424,10 +2421,6 @@ sgen_marksweep_init_internal (SgenMajorCollector *collector, gboolean is_concurr
        concurrent_mark = is_concurrent;
        collector->is_concurrent = is_concurrent;
        collector->needs_thread_pool = is_concurrent || concurrent_sweep;
-       if (is_concurrent)
-               collector->want_synchronous_collection = &want_evacuation;
-       else
-               collector->want_synchronous_collection = NULL;
        collector->get_and_reset_num_major_objects_marked = major_get_and_reset_num_major_objects_marked;
        collector->supports_cardtable = TRUE;
 
@@ -2481,9 +2474,9 @@ sgen_marksweep_init_internal (SgenMajorCollector *collector, gboolean is_concurr
                collector->major_ops_concurrent_start.drain_gray_stack = drain_gray_stack_concurrent;
 
                collector->major_ops_concurrent_finish.copy_or_mark_object = major_copy_or_mark_object_concurrent_finish_canonical;
-               collector->major_ops_concurrent_finish.scan_object = major_scan_object_no_evacuation;
+               collector->major_ops_concurrent_finish.scan_object = major_scan_object_with_evacuation;
                collector->major_ops_concurrent_finish.scan_vtype = major_scan_vtype_concurrent_finish;
-               collector->major_ops_concurrent_finish.drain_gray_stack = drain_gray_stack_no_evacuation;
+               collector->major_ops_concurrent_finish.drain_gray_stack = drain_gray_stack;
        }
 
 #ifdef HEAVY_STATISTICS
@@ -2494,6 +2487,7 @@ sgen_marksweep_init_internal (SgenMajorCollector *collector, gboolean is_concurr
        mono_counters_register ("Optimized copy major", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &stat_optimized_copy_major);
        mono_counters_register ("Optimized copy major small fast", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &stat_optimized_copy_major_small_fast);
        mono_counters_register ("Optimized copy major small slow", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &stat_optimized_copy_major_small_slow);
+       mono_counters_register ("Optimized copy major small evacuate", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &stat_optimized_copy_major_small_evacuate);
        mono_counters_register ("Optimized copy major large", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &stat_optimized_copy_major_large);
        mono_counters_register ("Optimized major scan", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &stat_optimized_major_scan);
        mono_counters_register ("Optimized major scan no refs", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &stat_optimized_major_scan_no_refs);
index cda7746a44d8667b4403ae0f59a839b5d24df49c..b1895985dc34e340f32093abfb423f967711f44a 100644 (file)
@@ -38,7 +38,7 @@ extern guint64 stat_scan_object_called_nursery;
 #define HANDLE_PTR(ptr,obj)    do {    \
                void *__old = *(ptr);   \
                SGEN_OBJECT_LAYOUT_STATISTICS_MARK_BITMAP ((obj), (ptr)); \
-               binary_protocol_scan_process_reference ((obj), (ptr), __old); \
+               binary_protocol_scan_process_reference ((full_object), (ptr), __old); \
                if (__old) {    \
                        SERIAL_COPY_OBJECT_FROM_OBJ ((ptr), queue);     \
                        SGEN_COND_LOG (9, __old != *(ptr), "Overwrote field at %p with %p (was: %p)", (ptr), *(ptr), __old); \
@@ -46,9 +46,9 @@ extern guint64 stat_scan_object_called_nursery;
        } while (0)
 
 static void
-SERIAL_SCAN_OBJECT (GCObject *object, SgenDescriptor desc, SgenGrayQueue *queue)
+SERIAL_SCAN_OBJECT (GCObject *full_object, SgenDescriptor desc, SgenGrayQueue *queue)
 {
-       char *start = (char*)object;
+       char *start = (char*)full_object;
 
        SGEN_OBJECT_LAYOUT_STATISTICS_DECLARE_BITMAP;
 
index 91094fdc1aeea4dac629e7befa0acff6bd5edf1b..94acad1f56f8805235498ee88afb68161273bed0 100644 (file)
@@ -372,6 +372,13 @@ MATCH_INDEX (ptr == entry->cursor ? 1 : ptr == entry->value ? 2 : BINARY_PROTOCO
 IS_VTABLE_MATCH (FALSE)
 END_PROTOCOL_ENTRY_HEAVY
 
+BEGIN_PROTOCOL_ENTRY_HEAVY4 (binary_protocol_mod_union_remset, TYPE_POINTER, obj, TYPE_POINTER, ptr, TYPE_POINTER, value, TYPE_POINTER, value_vtable)
+DEFAULT_PRINT ()
+IS_ALWAYS_MATCH (FALSE)
+MATCH_INDEX (ptr == entry->obj ? 0 : ptr == entry->ptr ? 1 : ptr == entry->value ? 2 : BINARY_PROTOCOL_NO_MATCH)
+IS_VTABLE_MATCH (ptr == entry->value_vtable)
+END_PROTOCOL_ENTRY_HEAVY
+
 #undef BEGIN_PROTOCOL_ENTRY0
 #undef BEGIN_PROTOCOL_ENTRY1
 #undef BEGIN_PROTOCOL_ENTRY2