[sgen] CAS on LOS marking
authorVlad Brezae <brezaevlad@gmail.com>
Mon, 30 May 2016 04:13:13 +0000 (07:13 +0300)
committerVlad Brezae <brezaevlad@gmail.com>
Thu, 19 Jan 2017 22:45:07 +0000 (00:45 +0200)
We make sure we don't double enqueue a large object.

mono/sgen/sgen-gc.h
mono/sgen/sgen-los.c
mono/sgen/sgen-marksweep-drain-gray-stack.h

index 1609d2386b6c4fa5eef21b11837bc2cd9dfe9a57..2ac2445b36645a3b51694e358f5fab2b4eafc382 100644 (file)
@@ -874,6 +874,7 @@ gboolean mono_sgen_los_describe_pointer (char *ptr);
 LOSObject* sgen_los_header_for_object (GCObject *data);
 mword sgen_los_object_size (LOSObject *obj);
 void sgen_los_pin_object (GCObject *obj);
+gboolean sgen_los_pin_object_par (GCObject *obj);
 gboolean sgen_los_object_is_pinned (GCObject *obj);
 void sgen_los_mark_mod_union_card (GCObject *mono_obj, void **ptr);
 
index 454cb89fda70eb88ce31bd6277b148fb323acf64..b1205cdcf0cd90935f6588395b11b165bf9dee0e 100644 (file)
@@ -722,6 +722,24 @@ sgen_los_pin_object (GCObject *data)
        binary_protocol_pin (data, (gpointer)SGEN_LOAD_VTABLE (data), sgen_safe_object_get_size (data));
 }
 
+gboolean
+sgen_los_pin_object_par (GCObject *data)
+{
+       LOSObject *obj = sgen_los_header_for_object (data);
+       mword old_size = obj->size;
+       if (old_size & 1)
+               return FALSE;
+#if SIZEOF_VOID_P == 4
+       old_size = InterlockedCompareExchange ((volatile gint32*)&obj->size, old_size | 1, old_size);
+#else
+       old_size = InterlockedCompareExchange64 ((volatile gint64*)&obj->size, old_size | 1, old_size);
+#endif
+       if (old_size & 1)
+               return FALSE;
+       binary_protocol_pin (data, (gpointer)SGEN_LOAD_VTABLE (data), sgen_safe_object_get_size (data));
+       return TRUE;
+}
+
 static void
 sgen_los_unpin_object (GCObject *data)
 {
index 787e3f555c0f73ce9d1df6d675f5c2812034d55c..505e20d967d31da5cbad7c3ea4be3a9b27f70307 100644 (file)
@@ -180,15 +180,22 @@ COPY_OR_MARK_FUNCTION_NAME (GCObject **ptr, GCObject *obj, SgenGrayQueue *queue)
                        MS_MARK_OBJECT_AND_ENQUEUE (obj, desc, block, queue);
 #endif
                } else {
+                       gboolean first = TRUE;
                        HEAVY_STAT (++stat_optimized_copy_major_large);
-
+#ifdef COPY_OR_MARK_PARALLEL
+                       first = sgen_los_pin_object_par (obj);
+#else
                        if (sgen_los_object_is_pinned (obj))
-                               return FALSE;
-                       binary_protocol_pin (obj, (gpointer)SGEN_LOAD_VTABLE (obj), sgen_safe_object_get_size (obj));
+                               first = FALSE;
+                       else
+                               sgen_los_pin_object (obj);
+#endif
 
-                       sgen_los_pin_object (obj);
-                       if (SGEN_OBJECT_HAS_REFERENCES (obj))
-                               GRAY_OBJECT_ENQUEUE (queue, obj, desc);
+                       if (first) {
+                               binary_protocol_pin (obj, (gpointer)SGEN_LOAD_VTABLE (obj), sgen_safe_object_get_size (obj));
+                               if (SGEN_OBJECT_HAS_REFERENCES (obj))
+                                       GRAY_OBJECT_ENQUEUE (queue, obj, desc);
+                       }
                }
                return FALSE;
        }