We make sure we don't double enqueue a large object.
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);
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)
{
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;
}