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)
|
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_inc = gc->inc_gen1;
|
||||||
save_check = gc->check_gen1;
|
save_check = gc->check_gen1;
|
||||||
|
|
||||||
gc->inc_gen1 = 1;
|
gc->inc_gen1 = 1;
|
||||||
gc->check_gen1 = 1;
|
gc->check_gen1 = 1;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
void *p;
|
void *p;
|
||||||
while (fuel && pop_ptr(gc, &p, 1)) {
|
while (fuel && pop_ptr(gc, &p, 1)) {
|
||||||
GCDEBUG((DEBUGOUTF, "Popped incremental pointer %p\n", p));
|
GCDEBUG((DEBUGOUTF, "Popped incremental pointer %p\n", p));
|
||||||
propagate_marks_worker(gc, p, 1);
|
propagate_marks_worker(gc, p, 1);
|
||||||
fuel--;
|
fuel--;
|
||||||
}
|
}
|
||||||
} while (do_emph
|
} while (do_emph && fuel && mark_ready_ephemerons(gc, 1));
|
||||||
&& (fuel || mark_stack_is_empty(gc->inc_mark_stack))
|
|
||||||
&& 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->inc_gen1 = save_inc;
|
||||||
gc->check_gen1 = save_check;
|
gc->check_gen1 = save_check;
|
||||||
}
|
|
||||||
|
|
||||||
return fuel;
|
return fuel;
|
||||||
}
|
}
|
||||||
|
@ -5782,6 +5778,8 @@ static int mark_and_finalize_all(NewGC *gc, int old_gen TIME_FORMAL_ARGS)
|
||||||
|
|
||||||
if (!old_gen)
|
if (!old_gen)
|
||||||
propagate_marks_plus_ephemerons(gc);
|
propagate_marks_plus_ephemerons(gc);
|
||||||
|
else
|
||||||
|
(void)propagate_incremental_marks(gc, 1, -1);
|
||||||
|
|
||||||
check_finalizers(gc, 1, old_gen);
|
check_finalizers(gc, 1, old_gen);
|
||||||
if (!old_gen)
|
if (!old_gen)
|
||||||
|
|
|
@ -474,7 +474,14 @@ static int mark_ephemeron(void *p, struct NewGC *gc)
|
||||||
eph->inc_next = gc->inc_ephemerons;
|
eph->inc_next = gc->inc_ephemerons;
|
||||||
gc->inc_ephemerons = eph;
|
gc->inc_ephemerons = eph;
|
||||||
} else if (gc->during_backpointer) {
|
} 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;
|
eph->next = gc->bp_ephemerons;
|
||||||
gc->bp_ephemerons = eph;
|
gc->bp_ephemerons = eph;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user