incremental GC: fix handling of ephemerons
Fix the case that an old-generation finalizer ends up on a modified page after all old-generation marking is complete. Also, make sure epehemerons are checked after previous marking that may have left the stack empty.
This commit is contained in:
parent
03302c3f30
commit
bef34606cb
|
@ -4163,33 +4163,29 @@ static void propagate_marks_plus_ephemerons(NewGC *gc)
|
|||
|
||||
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;
|
||||
int save_inc, save_check, init_fuel = fuel;
|
||||
|
||||
GC_ASSERT(gc->mark_gen1);
|
||||
GC_ASSERT(gc->mark_gen1);
|
||||
|
||||
save_inc = gc->inc_gen1;
|
||||
save_check = gc->check_gen1;
|
||||
save_inc = gc->inc_gen1;
|
||||
save_check = gc->check_gen1;
|
||||
|
||||
gc->inc_gen1 = 1;
|
||||
gc->check_gen1 = 1;
|
||||
gc->inc_gen1 = 1;
|
||||
gc->check_gen1 = 1;
|
||||
|
||||
do {
|
||||
void *p;
|
||||
while (fuel && pop_ptr(gc, &p, 1)) {
|
||||
GCDEBUG((DEBUGOUTF, "Popped incremental pointer %p\n", p));
|
||||
propagate_marks_worker(gc, p, 1);
|
||||
fuel--;
|
||||
}
|
||||
} while (do_emph
|
||||
&& (fuel || mark_stack_is_empty(gc->inc_mark_stack))
|
||||
&& mark_ready_ephemerons(gc, 1));
|
||||
do {
|
||||
void *p;
|
||||
while (fuel && pop_ptr(gc, &p, 1)) {
|
||||
GCDEBUG((DEBUGOUTF, "Popped incremental pointer %p\n", p));
|
||||
propagate_marks_worker(gc, p, 1);
|
||||
fuel--;
|
||||
}
|
||||
} while (do_emph && fuel && mark_ready_ephemerons(gc, 1));
|
||||
|
||||
gc->inc_prop_count += (init_fuel - fuel);
|
||||
gc->inc_prop_count += (init_fuel - fuel);
|
||||
|
||||
gc->inc_gen1 = save_inc;
|
||||
gc->check_gen1 = save_check;
|
||||
}
|
||||
gc->inc_gen1 = save_inc;
|
||||
gc->check_gen1 = save_check;
|
||||
|
||||
return fuel;
|
||||
}
|
||||
|
@ -5782,6 +5778,8 @@ static int mark_and_finalize_all(NewGC *gc, int old_gen TIME_FORMAL_ARGS)
|
|||
|
||||
if (!old_gen)
|
||||
propagate_marks_plus_ephemerons(gc);
|
||||
else
|
||||
(void)propagate_incremental_marks(gc, 1, -1);
|
||||
|
||||
check_finalizers(gc, 1, old_gen);
|
||||
if (!old_gen)
|
||||
|
|
|
@ -474,7 +474,14 @@ static int mark_ephemeron(void *p, struct NewGC *gc)
|
|||
eph->inc_next = gc->inc_ephemerons;
|
||||
gc->inc_ephemerons = eph;
|
||||
} else if (gc->during_backpointer) {
|
||||
if (!gc->gc_full) {
|
||||
if (!gc->gc_full
|
||||
/* If this old-generation object is not yet marked
|
||||
and we're finishing an incremental pass, then
|
||||
it won't get marked (and it can only refer to
|
||||
other old-generation objects), so ignore in that case */
|
||||
&& (gc->mark_gen1
|
||||
|| !gc->started_incremental
|
||||
|| !gc->finishing_incremental)) {
|
||||
eph->next = gc->bp_ephemerons;
|
||||
gc->bp_ephemerons = eph;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user