Skip to content

Commit

Permalink
Revert "Merge pull request #1219 from panzone/los_partial_marking"
Browse files Browse the repository at this point in the history
This reverts commit 397176d, reversing
changes made to 33c345a.
  • Loading branch information
kumpera committed Aug 28, 2014
1 parent 7ec9786 commit 903c5e3
Show file tree
Hide file tree
Showing 9 changed files with 222 additions and 317 deletions.
177 changes: 176 additions & 1 deletion mono/metadata/sgen-descriptor.h
Expand Up @@ -160,6 +160,181 @@ sgen_gc_descr_has_references (mword desc)
#define GNUC_BUILTIN_CTZ(bmap) __builtin_ctzl(bmap)
#endif

#define SGEN_OBJECT_IS_VECTOR_V_REFS(o) ((((GCVTable*)(SGEN_LOAD_VTABLE(o)))->desc & 0xc007) == ( DESC_TYPE_VECTOR | VECTOR_SUBTYPE_REFS))
/* code using these macros must define a HANDLE_PTR(ptr) macro that does the work */
#define OBJ_RUN_LEN_FOREACH_PTR(desc,obj) do { \
if ((desc) & 0xffff0000) { \
/* there are pointers */ \
void **_objptr_end; \
void **_objptr = (void**)(obj); \
_objptr += ((desc) >> 16) & 0xff; \
_objptr_end = _objptr + (((desc) >> 24) & 0xff); \
HANDLE_PTR (_objptr, (obj)); \
_objptr ++; \
while (_objptr < _objptr_end) { \
HANDLE_PTR (_objptr, (obj)); \
_objptr++; \
} \
} \
} while (0)

#if defined(__GNUC__)
#define OBJ_BITMAP_FOREACH_PTR(desc,obj) do { \
/* there are pointers */ \
void **_objptr = (void**)(obj); \
gsize _bmap = (desc) >> 16; \
_objptr += OBJECT_HEADER_WORDS; \
{ \
int _index = GNUC_BUILTIN_CTZ (_bmap); \
_objptr += _index; \
_bmap >>= (_index + 1); \
HANDLE_PTR (_objptr, (obj)); \
_objptr ++; \
} \
while (_bmap) { \
int _index = GNUC_BUILTIN_CTZ (_bmap); \
_objptr += _index; \
_bmap >>= (_index + 1); \
HANDLE_PTR (_objptr, (obj)); \
_objptr ++; \
} \
} while (0)
#else
#define OBJ_BITMAP_FOREACH_PTR(desc,obj) do { \
/* there are pointers */ \
void **_objptr = (void**)(obj); \
gsize _bmap = (desc) >> 16; \
_objptr += OBJECT_HEADER_WORDS; \
while (_bmap) { \
if ((_bmap & 1)) { \
HANDLE_PTR (_objptr, (obj)); \
} \
_bmap >>= 1; \
++_objptr; \
} \
} while (0)
#endif

/* a bitmap desc means that there are pointer references or we'd have
* choosen run-length, instead: add an assert to check.
*/
#define OBJ_LARGE_BITMAP_FOREACH_PTR(desc,obj) do { \
/* there are pointers */ \
void **_objptr = (void**)(obj); \
gsize _bmap = (desc) >> LOW_TYPE_BITS; \
_objptr += OBJECT_HEADER_WORDS; \
while (_bmap) { \
if ((_bmap & 1)) { \
HANDLE_PTR (_objptr, (obj)); \
} \
_bmap >>= 1; \
++_objptr; \
} \
} while (0)

#define OBJ_COMPLEX_FOREACH_PTR(vt,obj) do { \
/* there are pointers */ \
void **_objptr = (void**)(obj); \
gsize *bitmap_data = sgen_get_complex_descriptor ((desc)); \
gsize bwords = (*bitmap_data) - 1; \
void **start_run = _objptr; \
bitmap_data++; \
if (0) { \
MonoObject *myobj = (MonoObject*)obj; \
g_print ("found %d at %p (0x%zx): %s.%s\n", bwords, (obj), (desc), myobj->vtable->klass->name_space, myobj->vtable->klass->name); \
} \
while (bwords-- > 0) { \
gsize _bmap = *bitmap_data++; \
_objptr = start_run; \
/*g_print ("bitmap: 0x%x/%d at %p\n", _bmap, bwords, _objptr);*/ \
while (_bmap) { \
if ((_bmap & 1)) { \
HANDLE_PTR (_objptr, (obj)); \
} \
_bmap >>= 1; \
++_objptr; \
} \
start_run += GC_BITS_PER_WORD; \
} \
} while (0)

/* this one is untested */
#define OBJ_COMPLEX_ARR_FOREACH_PTR(vt,obj) do { \
/* there are pointers */ \
gsize *mbitmap_data = sgen_get_complex_descriptor ((vt)->desc); \
gsize mbwords = (*mbitmap_data++) - 1; \
gsize el_size = mono_array_element_size (vt->klass); \
char *e_start = (char*)(obj) + G_STRUCT_OFFSET (MonoArray, vector); \
char *e_end = e_start + el_size * mono_array_length_fast ((MonoArray*)(obj)); \
if (0) \
g_print ("found %d at %p (0x%zx): %s.%s\n", mbwords, (obj), (vt)->desc, vt->klass->name_space, vt->klass->name); \
while (e_start < e_end) { \
void **_objptr = (void**)e_start; \
gsize *bitmap_data = mbitmap_data; \
gsize bwords = mbwords; \
while (bwords-- > 0) { \
gsize _bmap = *bitmap_data++; \
void **start_run = _objptr; \
/*g_print ("bitmap: 0x%x\n", _bmap);*/ \
while (_bmap) { \
if ((_bmap & 1)) { \
HANDLE_PTR (_objptr, (obj)); \
} \
_bmap >>= 1; \
++_objptr; \
} \
_objptr = start_run + GC_BITS_PER_WORD; \
} \
e_start += el_size; \
} \
} while (0)

#define OBJ_VECTOR_FOREACH_PTR(desc,obj) do { \
/* note: 0xffffc000 excludes DESC_TYPE_V_PTRFREE */ \
if ((desc) & 0xffffc000) { \
int el_size = ((desc) >> 3) & MAX_ELEMENT_SIZE; \
/* there are pointers */ \
int etype = (desc) & 0xc000; \
if (etype == (DESC_TYPE_V_REFS << 14)) { \
void **p = (void**)((char*)(obj) + G_STRUCT_OFFSET (MonoArray, vector)); \
void **end_refs = (void**)((char*)p + el_size * mono_array_length_fast ((MonoArray*)(obj))); \
/* Note: this code can handle also arrays of struct with only references in them */ \
while (p < end_refs) { \
HANDLE_PTR (p, (obj)); \
++p; \
} \
} else if (etype == DESC_TYPE_V_RUN_LEN << 14) { \
int offset = ((desc) >> 16) & 0xff; \
int num_refs = ((desc) >> 24) & 0xff; \
char *e_start = (char*)(obj) + G_STRUCT_OFFSET (MonoArray, vector); \
char *e_end = e_start + el_size * mono_array_length_fast ((MonoArray*)(obj)); \
while (e_start < e_end) { \
void **p = (void**)e_start; \
int i; \
p += offset; \
for (i = 0; i < num_refs; ++i) { \
HANDLE_PTR (p + i, (obj)); \
} \
e_start += el_size; \
} \
} else if (etype == DESC_TYPE_V_BITMAP << 14) { \
char *e_start = (char*)(obj) + G_STRUCT_OFFSET (MonoArray, vector); \
char *e_end = e_start + el_size * mono_array_length_fast ((MonoArray*)(obj)); \
while (e_start < e_end) { \
void **p = (void**)e_start; \
gsize _bmap = (desc) >> 16; \
/* Note: there is no object header here to skip */ \
while (_bmap) { \
if ((_bmap & 1)) { \
HANDLE_PTR (p, (obj)); \
} \
_bmap >>= 1; \
++p; \
} \
e_start += el_size; \
} \
} \
} \
} while (0)


#endif
94 changes: 37 additions & 57 deletions mono/metadata/sgen-gc.c
Expand Up @@ -858,55 +858,35 @@ sgen_add_to_global_remset (gpointer ptr, gpointer obj)
* frequently after each object is copied, to achieve better locality and cache
* usage.
*/
#define CHECK_AND_LOG_OBJECT(obj) do{ \
if(!obj) \
return TRUE; \
SGEN_LOG (9, "Precise gray object scan (%p) (%s)", obj, safe_name (obj)); \
}while(0)

gboolean
sgen_drain_gray_stack (ScanCopyContext ctx)
{
char *obj;
char *offset;
ScanObjectFunc scan_func = ctx.scan_func;
GrayQueue *queue = ctx.queue;

if(sgen_get_major_collector()->is_parallel){
for (;;) {
GRAY_PARTIAL_OBJECT_DEQUEUE(queue, obj, offset);
CHECK_AND_LOG_OBJECT(obj);
scan_func (obj,queue);
}
}
else{
for (;;) {
GRAY_OBJECT_DEQUEUE(queue, &obj);
CHECK_AND_LOG_OBJECT(obj);
scan_func (obj,queue);
}
}
return FALSE;
}

/*This version is the drain_stack used by the parallel collector */

gboolean
sgen_drain_gray_stack_work_item (int max_objs, ScanCopyContext ctx)
sgen_drain_gray_stack (int max_objs, ScanCopyContext ctx)
{
char *obj;
char *offset;
ScanWorkFunc scan_work = ctx.scan_work;
GrayQueue *queue = ctx.queue;
int i;
char *obj;
ScanObjectFunc scan_func = ctx.scan_func;
GrayQueue *queue = ctx.queue;

g_assert(sgen_get_major_collector()->is_parallel);
for (i = 0; i != max_objs; ++i) {
GRAY_PARTIAL_OBJECT_DEQUEUE(queue,obj, offset);
CHECK_AND_LOG_OBJECT(obj);
scan_work(obj,(mword)offset,queue);
}
return FALSE;
if (max_objs == -1) {
for (;;) {
GRAY_OBJECT_DEQUEUE (queue, &obj);
if (!obj)
return TRUE;
SGEN_LOG (9, "Precise gray object scan %p (%s)", obj, safe_name (obj));
scan_func (obj, queue);
}
} else {
int i;

do {
for (i = 0; i != max_objs; ++i) {
GRAY_OBJECT_DEQUEUE (queue, &obj);
if (!obj)
return TRUE;
SGEN_LOG (9, "Precise gray object scan %p (%s)", obj, safe_name (obj));
scan_func (obj, queue);
}
} while (max_objs < 0);
return FALSE;
}
}

/*
Expand Down Expand Up @@ -1326,7 +1306,7 @@ precisely_scan_objects_from (void** start_root, void** end_root, char* n_start,
if ((desc & 1) && *start_root) {
copy_func (start_root, queue);
SGEN_LOG (9, "Overwrote root at %p with %p", start_root, *start_root);
sgen_drain_gray_stack (ctx);
sgen_drain_gray_stack (-1, ctx);
}
desc >>= 1;
start_root++;
Expand All @@ -1344,7 +1324,7 @@ precisely_scan_objects_from (void** start_root, void** end_root, char* n_start,
if ((bmap & 1) && *objptr) {
copy_func (objptr, queue);
SGEN_LOG (9, "Overwrote root at %p with %p", objptr, *objptr);
sgen_drain_gray_stack (ctx);
sgen_drain_gray_stack (-1, ctx);
}
bmap >>= 1;
++objptr;
Expand Down Expand Up @@ -1633,7 +1613,7 @@ finish_gray_stack (int generation, GrayQueue *queue)
* To achieve better cache locality and cache usage, we drain the gray stack
* frequently, after each object is copied, and just finish the work here.
*/
sgen_drain_gray_stack (ctx);
sgen_drain_gray_stack (-1, ctx);
TV_GETTIME (atv);
SGEN_LOG (2, "%s generation done", generation_name (generation));

Expand All @@ -1655,15 +1635,15 @@ finish_gray_stack (int generation, GrayQueue *queue)
done_with_ephemerons = 0;
do {
done_with_ephemerons = mark_ephemerons_in_range (ctx);
sgen_drain_gray_stack (ctx);
sgen_drain_gray_stack (-1, ctx);
++ephemeron_rounds;
} while (!done_with_ephemerons);

sgen_mark_togglerefs (start_addr, end_addr, ctx);

if (sgen_need_bridge_processing ()) {
/*Make sure the gray stack is empty before we process bridge objects so we get liveness right*/
sgen_drain_gray_stack (ctx);
sgen_drain_gray_stack (-1, ctx);
sgen_collect_bridge_objects (generation, ctx);
if (generation == GENERATION_OLD)
sgen_collect_bridge_objects (GENERATION_NURSERY, ctx);
Expand All @@ -1687,7 +1667,7 @@ finish_gray_stack (int generation, GrayQueue *queue)
Make sure we drain the gray stack before processing disappearing links and finalizers.
If we don't make sure it is empty we might wrongly see a live object as dead.
*/
sgen_drain_gray_stack (ctx);
sgen_drain_gray_stack (-1, ctx);

/*
We must clear weak links that don't track resurrection before processing object ready for
Expand All @@ -1708,15 +1688,15 @@ finish_gray_stack (int generation, GrayQueue *queue)
sgen_finalize_in_range (GENERATION_NURSERY, ctx);
/* drain the new stack that might have been created */
SGEN_LOG (6, "Precise scan of gray area post fin");
sgen_drain_gray_stack (ctx);
sgen_drain_gray_stack (-1, ctx);

/*
* This must be done again after processing finalizable objects since CWL slots are cleared only after the key is finalized.
*/
done_with_ephemerons = 0;
do {
done_with_ephemerons = mark_ephemerons_in_range (ctx);
sgen_drain_gray_stack (ctx);
sgen_drain_gray_stack (-1, ctx);
++ephemeron_rounds;
} while (!done_with_ephemerons);

Expand Down Expand Up @@ -1751,7 +1731,7 @@ finish_gray_stack (int generation, GrayQueue *queue)
sgen_null_link_in_range (GENERATION_NURSERY, FALSE, ctx);
if (sgen_gray_object_queue_is_empty (queue))
break;
sgen_drain_gray_stack (ctx);
sgen_drain_gray_stack (-1, ctx);
}

g_assert (sgen_gray_object_queue_is_empty (queue));
Expand Down Expand Up @@ -2360,7 +2340,7 @@ collect_nursery (SgenGrayQueue *unpin_queue, gboolean finish_up_concurrent_mark)
ctx.scan_func = current_object_ops.scan_object;
ctx.copy_func = NULL;
ctx.queue = &gray_queue;
sgen_drain_gray_stack (ctx);
sgen_drain_gray_stack (-1, ctx);
}

if (mono_profiler_get_events () & MONO_PROFILE_GC_ROOTS)
Expand Down Expand Up @@ -2653,7 +2633,7 @@ major_copy_or_mark_from_roots (size_t *old_next_pin_slot, gboolean finish_up_con
}
sgen_los_pin_object (bigobj->data);
if (SGEN_OBJECT_HAS_REFERENCES (bigobj->data))
GRAY_PARTIAL_OBJECT_ENQUEUE (WORKERS_DISTRIBUTE_GRAY_QUEUE, bigobj->data);
GRAY_OBJECT_ENQUEUE (WORKERS_DISTRIBUTE_GRAY_QUEUE, bigobj->data);
if (G_UNLIKELY (do_pin_stats))
sgen_pin_stats_register_object ((char*) bigobj->data, safe_object_get_size ((MonoObject*) bigobj->data));
SGEN_LOG (6, "Marked large object %p (%s) size: %lu from roots", bigobj->data, safe_name (bigobj->data), (unsigned long)sgen_los_object_size (bigobj));
Expand Down

0 comments on commit 903c5e3

Please sign in to comment.