From 9b4efca29b8f83799a1dbde98ca5c859edabba83 Mon Sep 17 00:00:00 2001 From: Vlad Brezae Date: Mon, 30 May 2016 05:02:17 +0300 Subject: [PATCH] [sgen] Add CAS object marking for concurrent workers When marking an object we need to make sure we are not unmarking other objects (since marking is stored as bits). This also allows us to make sure that we never enqueue the same object multiple times on separate gray queues. --- mono/sgen/sgen-marksweep-drain-gray-stack.h | 4 +++ mono/sgen/sgen-marksweep.c | 29 +++++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/mono/sgen/sgen-marksweep-drain-gray-stack.h b/mono/sgen/sgen-marksweep-drain-gray-stack.h index 6a3eb84fc42..787e3f555c0 100644 --- a/mono/sgen/sgen-marksweep-drain-gray-stack.h +++ b/mono/sgen/sgen-marksweep-drain-gray-stack.h @@ -174,7 +174,11 @@ COPY_OR_MARK_FUNCTION_NAME (GCObject **ptr, GCObject *obj, SgenGrayQueue *queue) } #endif +#ifdef COPY_OR_MARK_PARALLEL + MS_MARK_OBJECT_AND_ENQUEUE_PAR (obj, desc, block, queue); +#else MS_MARK_OBJECT_AND_ENQUEUE (obj, desc, block, queue); +#endif } else { HEAVY_STAT (++stat_optimized_copy_major_large); diff --git a/mono/sgen/sgen-marksweep.c b/mono/sgen/sgen-marksweep.c index d6c4b66785b..72a70c69302 100644 --- a/mono/sgen/sgen-marksweep.c +++ b/mono/sgen/sgen-marksweep.c @@ -134,6 +134,20 @@ typedef struct { #define MS_MARK_BIT(bl,w,b) ((bl)->mark_words [(w)] & (ONE_P << (b))) #define MS_SET_MARK_BIT(bl,w,b) ((bl)->mark_words [(w)] |= (ONE_P << (b))) +#define MS_SET_MARK_BIT_PAR(bl,w,b,first) do { \ + guint32 tmp_mark_word = (bl)->mark_words [(w)]; \ + guint32 old_mark_word; \ + first = FALSE; \ + while (!(tmp_mark_word & (ONE_P << (b)))) { \ + old_mark_word = tmp_mark_word; \ + tmp_mark_word = InterlockedCompareExchange ((volatile gint32*)&(bl)->mark_words [w], old_mark_word | (ONE_P << (b)), old_mark_word); \ + if (tmp_mark_word == old_mark_word) { \ + first = TRUE; \ + break; \ + } \ + } \ + } while (0) + #define MS_OBJ_ALLOCED(o,b) (*(void**)(o) && (*(char**)(o) < MS_BLOCK_FOR_BLOCK_INFO (b) || *(char**)(o) >= MS_BLOCK_FOR_BLOCK_INFO (b) + MS_BLOCK_SIZE)) @@ -1084,6 +1098,21 @@ major_block_is_evacuating (MSBlockInfo *block) INC_NUM_MAJOR_OBJECTS_MARKED (); \ } \ } while (0) +#define MS_MARK_OBJECT_AND_ENQUEUE_PAR(obj,desc,block,queue) do { \ + int __word, __bit; \ + gboolean first; \ + MS_CALC_MARK_BIT (__word, __bit, (obj)); \ + SGEN_ASSERT (9, MS_OBJ_ALLOCED ((obj), (block)), "object %p not allocated", obj); \ + MS_SET_MARK_BIT_PAR ((block), __word, __bit, first); \ + if (first) { \ + if (sgen_gc_descr_has_references (desc)) \ + GRAY_OBJECT_ENQUEUE ((queue), (obj), (desc)); \ + binary_protocol_mark ((obj), (gpointer)SGEN_LOAD_VTABLE ((obj)), sgen_safe_object_get_size ((obj))); \ + INC_NUM_MAJOR_OBJECTS_MARKED (); \ + } \ + } while (0) + + static void pin_major_object (GCObject *obj, SgenGrayQueue *queue) -- 2.25.1