Skip to content

Commit

Permalink
Hack to estimate the number of slots we will be freeing
Browse files Browse the repository at this point in the history
  • Loading branch information
peterzhu2118 committed Aug 22, 2020
1 parent bcbbce2 commit cfeaf65
Showing 1 changed file with 65 additions and 53 deletions.
118 changes: 65 additions & 53 deletions gc.c
Original file line number Diff line number Diff line change
Expand Up @@ -2106,6 +2106,51 @@ heap_get_freeobj(rb_objspace_t *objspace, rb_heap_t *heap)
}
}

static int
is_garbage_slot(VALUE obj)
{
return !!MARKED_IN_BITMAP(GET_HEAP_GARBAGE_BITS(obj), obj);
}

static int
free_garbage(rb_objspace_t *objspace, VALUE garbage)
{
GC_ASSERT(BUILTIN_TYPE(garbage) == T_GARBAGE);

int length = RANY(garbage)->as.garbage.length;
GC_ASSERT(length > 0);

struct heap_page *page = GET_HEAP_PAGE(garbage);

for (int i = 0; i < length; i++) {
VALUE p = garbage + i * sizeof(RVALUE);

GC_ASSERT(RANY(p) - page->start < page->total_slots);

CLEAR_IN_BITMAP(GET_HEAP_GARBAGE_BITS(p), p);
heap_page_add_freeobj(objspace, page, p);
}

GC_ASSERT(objspace->garbage_slots >= length);

page->free_slots += length;
objspace->garbage_slots -= length;

return length;
}

static int
maybe_free_garbage_for(rb_objspace_t *objspace, VALUE obj)
{
VALUE next = obj + sizeof(RVALUE);

if (GET_PAGE_BODY(obj) == GET_PAGE_BODY(next) && is_garbage_slot(next)) {
return free_garbage(objspace, next);
}

return 0;
}

void
rb_objspace_set_event_hook(const rb_event_flag_t event)
{
Expand Down Expand Up @@ -2250,7 +2295,6 @@ newobj_init_garbage(rb_objspace_t *objspace, VALUE obj, int length)

VALUE next = obj + sizeof(RVALUE);


GC_ASSERT(length > 0);

if (GET_PAGE_BODY(next) == GET_PAGE_BODY(obj) && has_empty_slots(next, length)) {
Expand Down Expand Up @@ -2279,11 +2323,10 @@ newobj_init_garbage(rb_objspace_t *objspace, VALUE obj, int length)
#if RGENGC_CHECK_MODE
for (int i = 0; i < length; i++) {
VALUE p = next + i * sizeof(RVALUE);
GC_ASSERT(RVALUE_MARKED(p) == FALSE);
GC_ASSERT(RVALUE_MARKING(p) == FALSE);
GC_ASSERT(RVALUE_UNCOLLECTIBLE(p) == FALSE);
GC_ASSERT(RVALUE_OLD_P(p) == FALSE);
GC_ASSERT(RVALUE_WB_UNPROTECTED(p) == FALSE);
GC_ASSERT(RVALUE_MARK_BITMAP(obj) == 0);
GC_ASSERT(RVALUE_MARKING_BITMAP(obj) == FALSE);
GC_ASSERT(RVALUE_UNCOLLECTIBLE_BITMAP(p) == FALSE);
GC_ASSERT(RVALUE_WB_UNPROTECTED_BITMAP(p) == FALSE);
}
#endif
} else {
Expand Down Expand Up @@ -3646,8 +3689,8 @@ finalize_list(rb_objspace_t *objspace, VALUE zombie)

if (LIKELY(heap_pages_final_objects)) heap_pages_final_objects--;
page->final_objects--;
page->free_slots++;
heap_page_add_freeobj(objspace, GET_HEAP_PAGE(zombie), zombie);
page->free_slots += maybe_free_garbage_for(objspace, zombie) + 1;

objspace->profile.total_freed_objects++;

Expand Down Expand Up @@ -4413,34 +4456,6 @@ gc_setup_mark_bits(struct heap_page *page)
memcpy(&page->mark_bits[0], &page->uncollectible_bits[0], HEAP_PAGE_BITMAP_SIZE);
}

static inline int
gc_free_garbage(rb_objspace_t *objspace, VALUE garbage)
{
GC_ASSERT(BUILTIN_TYPE(garbage) == T_GARBAGE);

int length = RANY(garbage)->as.garbage.length;
GC_ASSERT(length > 0);

struct heap_page *page = GET_HEAP_PAGE(garbage);

for (int i = 0; i < length; i++) {
VALUE p = garbage + i * sizeof(RVALUE);

GC_ASSERT(RANY(p) - page->start < page->total_slots);

heap_page_add_freeobj(objspace, page, p);
}

GC_ASSERT(objspace->garbage_slots >= length);

page->free_slots += length;
objspace->garbage_slots -= length;

return length;
}

static int is_garbage_slot(VALUE obj);

static inline int
gc_page_sweep(rb_objspace_t *objspace, rb_heap_t *heap, struct heap_page *sweep_page)
{
Expand All @@ -4466,7 +4481,7 @@ gc_page_sweep(rb_objspace_t *objspace, rb_heap_t *heap, struct heap_page *sweep_
}

for (i=0; i < HEAP_PAGE_BITMAP_LIMIT; i++) {
bitset = ~bits[i];
bitset = ~(bits[i] | sweep_page->garbage_bits[i]);
if (bitset) {
p = offset + i * BITS_BITLENGTH;
do {
Expand All @@ -4482,17 +4497,16 @@ gc_page_sweep(rb_objspace_t *objspace, rb_heap_t *heap, struct heap_page *sweep_
if (rgengc_remembered_sweep(objspace, vp)) rb_bug("page_sweep: %p - remembered.", (void *)p);
}
#endif
if (!is_garbage_slot(vp)) {
if (obj_free(objspace, vp)) {
final_objects++;
}
else {
(void)VALGRIND_MAKE_MEM_UNDEFINED((void*)p, sizeof(RVALUE));
heap_page_add_freeobj(objspace, sweep_page, vp);
gc_report(3, objspace, "page_sweep: %s is added to freelist\n", obj_info(vp));
freed_slots++;
asan_poison_object(vp);
}
if (obj_free(objspace, vp)) {
final_objects++;
}
else {
(void)VALGRIND_MAKE_MEM_UNDEFINED((void*)p, sizeof(RVALUE));
heap_page_add_freeobj(objspace, sweep_page, vp);
gc_report(3, objspace, "page_sweep: %s is added to freelist\n", obj_info(vp));
freed_slots += maybe_free_garbage_for(objspace, vp); // Demo freeing garbage slots
freed_slots++;
asan_poison_object(vp);
}
break;

Expand Down Expand Up @@ -6726,6 +6740,9 @@ gc_marks_finish(rb_objspace_t *objspace)
rb_heap_t *heap = heap_eden;
size_t total_slots = heap_allocatable_pages * HEAP_PAGE_OBJ_LIMIT + heap->total_slots;
size_t sweep_slots = total_slots - objspace->garbage_slots - objspace->marked_slots; /* will be swept slots */
// Temp hack to get TestGc#test_expand_heap passing because every slot in
// sweep_slots will probably free 4 slots (1 slot object + 3 slots garbage).
sweep_slots *= 4;
size_t max_free_slots = (size_t)(total_slots * gc_params.heap_free_slots_max_ratio);
size_t min_free_slots = (size_t)(total_slots * gc_params.heap_free_slots_min_ratio);
int full_marking = is_full_marking(objspace);
Expand Down Expand Up @@ -7381,6 +7398,7 @@ rb_gc_force_recycle(VALUE obj)
objspace->profile.total_freed_objects++;

heap_page_add_freeobj(objspace, GET_HEAP_PAGE(obj), obj);
objspace->profile.total_freed_objects += maybe_free_garbage_for(objspace, obj); // Demo freeing garbage slots

/* Disable counting swept_slots because there are no meaning.
* if (!MARKED_IN_BITMAP(GET_HEAP_MARK_BITS(p), p)) {
Expand Down Expand Up @@ -8116,12 +8134,6 @@ allocate_page_list(rb_objspace_t *objspace, page_compare_func_t *comparator)
return page_list;
}

static int
is_garbage_slot(VALUE obj)
{
return !!MARKED_IN_BITMAP(GET_HEAP_GARBAGE_BITS(obj), obj);
}

static void
gc_compact_heap(rb_objspace_t *objspace, page_compare_func_t *comparator, struct RMoved * moved_list)
{
Expand Down

0 comments on commit cfeaf65

Please sign in to comment.