Fix shared-space marked-page chaining

Fixes a problem with a4910716e4, and adjusts place-specific
major GCs to use the already constructed chain instead
of reconstructing it.
This commit is contained in:
Matthew Flatt 2015-09-11 07:45:01 -06:00
parent 50df879e79
commit c416db91c1

View File

@ -84,7 +84,7 @@ enum {
PAGE_PAIR = 4,
PAGE_BIG = 5,
/* the number of page types: */
PAGE_TYPES = 6,
PAGE_TYPES = 6
};
enum {
@ -120,7 +120,8 @@ enum {
enum {
AGE_GEN_0 = 0,
AGE_GEN_HALF = 1,
AGE_GEN_1 = 2
AGE_GEN_1 = 2,
AGE_VACATED = 3
};
static const char *type_name[PAGE_TYPES] = {
@ -1678,12 +1679,12 @@ int GC_allocate_phantom_bytes(void *pb, intptr_t request_size_bytes)
request_size_bytes = -request_size_bytes;
if (gc->memory_in_use > request_size_bytes)
gc->memory_in_use -= request_size_bytes;
if (!page || (page->generation != AGE_GEN_1)) {
if (!page || (page->generation < AGE_GEN_1)) {
if (gc->gen0_phantom_count > request_size_bytes)
gc->gen0_phantom_count -= request_size_bytes;
}
} else {
if (!page || (page->generation != AGE_GEN_1))
if (!page || (page->generation < AGE_GEN_1))
gc->gen0_phantom_count = add_no_overflow(gc->gen0_phantom_count, request_size_bytes);
gc->memory_in_use = add_no_overflow(gc->memory_in_use, request_size_bytes);
}
@ -4301,6 +4302,8 @@ mpage *allocate_compact_target(NewGC *gc, mpage *work)
npage->size_class = SIZE_CLASS_SMALL_PAGE;
npage->page_type = work->page_type;
npage->marked_on = 1;
npage->modified_next = gc->modified_next;
gc->modified_next = npage;
backtrace_new_page(gc, npage);
pagemap_add(gc->page_maps, npage);
gc->num_gen1_pages++;
@ -4411,6 +4414,9 @@ inline static void do_heap_compact(NewGC *gc)
/* push work onto gc->release_pages */
work->next = gc->release_pages;
gc->release_pages = work;
/* Setting the generation causes `work` to be ignored
in the `modified_next` chain: */
work->generation = AGE_VACATED;
work = prev;
} else {
@ -4490,7 +4496,9 @@ static int repair_mixed_page(NewGC *gc, mpage *page, void **end)
}
static void chain_marked_on(NewGC *gc)
/* add any page that is marked on to the `modified_next` chain */
/* add any page that is marked on to the `modified_next` chain; this
is needed for a master GC, because the place GCs do not register
marked master pages in the master GC's `modified_next` chain */
{
mpage *page;
int i, ty;
@ -4499,6 +4507,7 @@ static void chain_marked_on(NewGC *gc)
for (i = 0; i < PAGE_TYPES; i++) {
for (page = gc->gen1_pages[i]; page; page = page->next) {
GC_ASSERT(!page->marked_from);
if (page->marked_on) {
page->modified_next = gc->modified_next;
gc->modified_next = page;
@ -4509,6 +4518,7 @@ static void chain_marked_on(NewGC *gc)
for (ty = 0; ty < MED_PAGE_TYPES; ty++) {
for (i = 0; i < NUM_MED_PAGE_SIZES; i++) {
for (page = gc->med_pages[ty][i]; page; page = page->next) {
GC_ASSERT(!page->marked_from);
if (page->marked_on) {
page->modified_next = gc->modified_next;
gc->modified_next = page;
@ -4518,6 +4528,51 @@ static void chain_marked_on(NewGC *gc)
}
}
#if 0
# define CHECK_MARKED_ON_IN_MODIFIED_CHAIN
static void chain_marked_on_check(NewGC *gc)
{
mpage *page, *xpage;
int i, ty, found = 0;
for (i = 0; i < PAGE_TYPES; i++) {
for (page = gc->gen1_pages[i]; page; page = page->next) {
if (page->marked_on) {
for (xpage = gc->modified_next; xpage; xpage = xpage->modified_next) {
if (xpage == page)
break;
}
GC_ASSERT(xpage);
found++;
}
}
}
for (ty = 0; ty < MED_PAGE_TYPES; ty++) {
for (i = 0; i < NUM_MED_PAGE_SIZES; i++) {
for (page = gc->med_pages[ty][i]; page; page = page->next) {
if (page->marked_on) {
for (xpage = gc->modified_next; xpage; xpage = xpage->modified_next) {
if (xpage == page)
break;
}
GC_ASSERT(xpage);
found++;
}
}
}
}
for (xpage = gc->modified_next; xpage; xpage = xpage->modified_next) {
if (xpage->generation < AGE_VACATED)
--found;
}
GC_ASSERT(!found);
}
#else
static void chain_marked_on_check(NewGC *gc) { }
#endif
static void repair_heap(NewGC *gc)
{
uintptr_t memory_in_use;
@ -4538,6 +4593,9 @@ static void repair_heap(NewGC *gc)
for (; page; page = next) {
GC_ASSERT(page->marked_on || page->marked_from);
next = page->modified_next;
if (page->generation == AGE_VACATED) {
/* this page will be released later */
} else {
page->has_new = 0;
if (gc->gc_full)
page->marked_on = 1;
@ -4683,6 +4741,7 @@ static void repair_heap(NewGC *gc)
else
page->back_pointers = 0;
}
}
/* All gen-half pages count as modified: */
for (page = gc->gen_half.pages; page; page = page->next) {
@ -5154,8 +5213,10 @@ static void garbage_collect(NewGC *gc, int force_full, int no_full, int switchin
if (premaster_or_place_gc(gc))
GC_fixup_variable_stack(GC_variable_stack, 0, get_stack_base(gc), NULL);
TIME_STEP("reparied roots");
if (gc->gc_full && postmaster_and_place_gc(gc))
if (gc->gc_full && postmaster_and_master_gc(gc))
chain_marked_on(gc);
else if (gc->gc_full)
chain_marked_on_check(gc);
repair_heap(gc);
TIME_STEP("repaired");
clean_up_heap(gc);