incremental GC: make finalization more incremental

This commit is contained in:
Matthew Flatt 2015-11-30 19:12:04 -07:00
parent f30d8bd562
commit 8363144818
2 changed files with 70 additions and 29 deletions

View File

@ -4158,7 +4158,7 @@ static void propagate_marks_plus_ephemerons(NewGC *gc)
} while (mark_ready_ephemerons(gc, 0));
}
static void propagate_incremental_marks(NewGC *gc, int do_emph, int fuel)
static int propagate_incremental_marks(NewGC *gc, int do_emph, int fuel)
{
if (gc->inc_mark_stack) {
int save_inc, save_check, init_fuel = fuel;
@ -4187,6 +4187,8 @@ static void propagate_incremental_marks(NewGC *gc, int do_emph, int fuel)
gc->inc_gen1 = save_inc;
gc->check_gen1 = save_check;
}
return fuel;
}
#ifdef MZ_USE_PLACES
@ -5767,16 +5769,23 @@ extern double scheme_get_inexact_milliseconds(void);
# define TIME_ARGS /**/
#endif
static void mark_and_finalize_all(NewGC *gc, int old_gen TIME_FORMAL_ARGS)
#define AS_100M(c) ((c / (1024 * 1024 * 100)) + 1)
static int mark_and_finalize_all(NewGC *gc, int old_gen TIME_FORMAL_ARGS)
{
int fuel = (INCREMENTAL_COLLECT_FUEL_PER_100M * AS_100M(gc->memory_in_use)) / 2;
if (!old_gen)
propagate_marks_plus_ephemerons(gc);
check_finalizers(gc, 1, old_gen);
if (!old_gen)
propagate_marks_plus_ephemerons(gc);
else
propagate_incremental_marks(gc, 1, -1);
else {
fuel = propagate_incremental_marks(gc, 1, fuel);
if (!fuel)
return 1;
}
TIME_STEP("marked");
@ -5785,8 +5794,16 @@ static void mark_and_finalize_all(NewGC *gc, int old_gen TIME_FORMAL_ARGS)
gc->fnl_gen1 = 1;
}
zero_weak_boxes(gc, 0, 0, old_gen);
zero_weak_arrays(gc, 0, old_gen);
fuel = zero_weak_boxes(gc, 0, 0, old_gen, (old_gen ? fuel : -1));
if (old_gen && !fuel) {
gc->fnl_gen1 = 0;
return 1;
}
fuel = zero_weak_arrays(gc, 0, old_gen, (old_gen ? fuel : -1));
if (old_gen && !fuel) {
gc->fnl_gen1 = 0;
return 1;
}
zero_remaining_ephemerons(gc, old_gen);
TIME_STEP("zeroed");
@ -5795,33 +5812,35 @@ static void mark_and_finalize_all(NewGC *gc, int old_gen TIME_FORMAL_ARGS)
if (!old_gen)
propagate_marks(gc);
else
propagate_incremental_marks(gc, 0, -1);
zero_weak_boxes(gc, 1, 0, old_gen);
(void)propagate_incremental_marks(gc, 0, -1);
(void)zero_weak_boxes(gc, 1, 0, old_gen, -1);
check_finalizers(gc, 3, old_gen);
if (!old_gen)
propagate_marks(gc);
else
propagate_incremental_marks(gc, 0, -1);
(void)propagate_incremental_marks(gc, 0, -1);
if (gc->GC_post_propagate_hook)
gc->GC_post_propagate_hook(gc);
/* for any new ones that appeared: */
zero_weak_boxes(gc, 0, 1, old_gen);
zero_weak_boxes(gc, 1, 1, old_gen);
zero_weak_arrays(gc, 1, old_gen);
(void)zero_weak_boxes(gc, 0, 1, old_gen, -1);
(void)zero_weak_boxes(gc, 1, 1, old_gen, -1);
(void)zero_weak_arrays(gc, 1, old_gen, -1);
zero_remaining_ephemerons(gc, old_gen);
if (old_gen)
gc->fnl_gen1 = 0;
TIME_STEP("finalized");
return 0;
}
static void mark_and_finalize_all_incremental(NewGC *gc TIME_FORMAL_ARGS)
static int mark_and_finalize_all_incremental(NewGC *gc TIME_FORMAL_ARGS)
{
int save_inc, save_check;
int save_inc, save_check, more_to_do;
GC_ASSERT(gc->mark_gen1);
@ -5831,10 +5850,12 @@ static void mark_and_finalize_all_incremental(NewGC *gc TIME_FORMAL_ARGS)
gc->inc_gen1 = 1;
gc->check_gen1 = 1;
mark_and_finalize_all(gc, 1 TIME_ARGS);
more_to_do = mark_and_finalize_all(gc, 1 TIME_ARGS);
gc->inc_gen1 = save_inc;
gc->check_gen1 = save_check;
return more_to_do;
}
/* Full GCs trigger finalization. Finalization releases data
@ -5987,7 +6008,7 @@ static void garbage_collect(NewGC *gc, int force_full, int no_full, int switchin
/* now propagate/repair the marks we got from these roots, and do the
finalizer passes */
mark_and_finalize_all(gc, 0 TIME_ARGS);
(void)mark_and_finalize_all(gc, 0 TIME_ARGS);
if (do_incremental) {
if (!gc->finishing_incremental) {
@ -5995,19 +6016,22 @@ static void garbage_collect(NewGC *gc, int force_full, int no_full, int switchin
if (!mark_stack_is_empty(gc->inc_mark_stack)) {
int fuel = (no_full
? INCREMENTAL_COLLECT_FUEL_PER_100M / INCREMENTAL_MINOR_REQUEST_DIVISOR
: INCREMENTAL_COLLECT_FUEL_PER_100M * ((gc->memory_in_use / (1024 * 1024 * 100)) + 1));
propagate_incremental_marks(gc, 1, fuel);
: INCREMENTAL_COLLECT_FUEL_PER_100M * AS_100M(gc->memory_in_use));
(void)propagate_incremental_marks(gc, 1, fuel);
TIME_STEP("incremented");
} else {
/* We ran out of incremental marking work, so
perform major-GC finalization in one go. */
mark_and_finalize_all_incremental(gc TIME_ARGS);
BTC_clean_up_gen1(gc);
reset_gen1_finalizer_tree(gc);
/* Switch to incrementally reparing pages before propagating
marks again. */
gc->finishing_incremental = 1;
gc->inc_repair_next = gc->inc_modified_next;
perform major-GC finalization */
if (mark_and_finalize_all_incremental(gc TIME_ARGS)) {
/* More finalizaton work to do */
reset_gen1_finalizer_tree(gc);
} else {
BTC_clean_up_gen1(gc);
reset_gen1_finalizer_tree(gc);
/* Switch to incrementally reparing pages */
gc->finishing_incremental = 1;
gc->inc_repair_next = gc->inc_modified_next;
}
}
check_inc_repair = 0;
} else
@ -6048,7 +6072,7 @@ static void garbage_collect(NewGC *gc, int force_full, int no_full, int switchin
if (check_inc_repair) {
int fuel = (no_full
? INCREMENTAL_REPAIR_FUEL_PER_100M / INCREMENTAL_MINOR_REQUEST_DIVISOR
: INCREMENTAL_REPAIR_FUEL_PER_100M * ((gc->memory_in_use / (1024 * 1024 * 100)) + 1));
: INCREMENTAL_REPAIR_FUEL_PER_100M * AS_100M(gc->memory_in_use));
incremental_repair_pages(gc, fuel);
TIME_STEP("inc-repaired");
}

View File

@ -167,7 +167,7 @@ static GC_Weak_Array *append_weak_arrays(GC_Weak_Array *wa, GC_Weak_Array *bp_wa
return bp_wa;
}
static void zero_weak_arrays(GCTYPE *gc, int force_zero, int from_inc)
static int zero_weak_arrays(GCTYPE *gc, int force_zero, int from_inc, int fuel)
{
GC_Weak_Array *wa;
int i, num_gen0;
@ -192,6 +192,8 @@ static void zero_weak_arrays(GCTYPE *gc, int force_zero, int from_inc)
else
data[i] = GC_resolve2(p, gc);
}
if (fuel > 0)
fuel = ((fuel > wa->count) ? (fuel - wa->count) : 0);
if (num_gen0 > 0) {
if (!is_in_generation_half(gc, wa)) {
@ -217,6 +219,8 @@ static void zero_weak_arrays(GCTYPE *gc, int force_zero, int from_inc)
gc->weak_arrays = NULL;
gc->bp_weak_arrays = NULL;
}
return fuel;
}
/******************************************************************************/
@ -367,7 +371,7 @@ static GC_Weak_Box *append_weak_boxes(GC_Weak_Box *wb, GC_Weak_Box *bp_wb, int *
return bp_wb;
}
static void zero_weak_boxes(GCTYPE *gc, int is_late, int force_zero, int from_inc)
static int zero_weak_boxes(GCTYPE *gc, int is_late, int force_zero, int from_inc, int fuel)
{
GC_Weak_Box *wb;
int num_gen0;
@ -426,7 +430,18 @@ static void zero_weak_boxes(GCTYPE *gc, int is_late, int force_zero, int from_in
wb = next;
} else
wb = wb->next;
num_gen0--;
if (fuel >= 0) {
if (fuel > 0)
fuel--;
else {
GC_ASSERT(from_inc);
gc->inc_weak_boxes[is_late] = wb;
return 0;
}
}
}
/* reset, in case we have a second round */
@ -436,6 +451,8 @@ static void zero_weak_boxes(GCTYPE *gc, int is_late, int force_zero, int from_in
gc->weak_boxes[is_late] = NULL;
gc->bp_weak_boxes[is_late] = NULL;
}
return fuel;
}
/******************************************************************************/