Skip to content

Commit

Permalink
repair collector handling of ephemerons (#715)
Browse files Browse the repository at this point in the history
  • Loading branch information
mflatt authored Aug 25, 2023
1 parent 8f489d4 commit cadb1bf
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 6 deletions.
5 changes: 4 additions & 1 deletion LOG
Original file line number Diff line number Diff line change
Expand Up @@ -2398,6 +2398,9 @@
- reduce allocation and copying for certain cases in bytevector->string
mats/io.ms release_notes/release_notes.stex s/io.ss
- update zlib to version 1.3
- repair collector handling of weak pointers when the max target generation
- repair collector handling of weak pairs when the max target generation
is greater than the minimum target generation
c/gc.c mats/4.ms
- repair collector handling of ephemeron pairs that refer to objects in
younger generations
c/gc.c mats/4.ms
24 changes: 19 additions & 5 deletions c/gc.c
Original file line number Diff line number Diff line change
Expand Up @@ -524,6 +524,7 @@ static IGEN copy(ptr pp, seginfo *si, ptr *ppp FORMAL_CTGS) {
find_room(space_ephemeron, newg, type_pair, size_ephemeron, p);
INITCAR(p) = Scar(pp);
INITCDR(p) = Scdr(pp);
EPHEMERONNEXT(p) = Sfalse; /* #f => not yet swept */
} else {
ptr qq = Scdr(pp); ptr q;
if (qq != pp && TYPEBITS(qq) == type_pair && ptr_get_segment(qq) == ptr_get_segment(pp) && FWDMARKER(qq) != forward_marker && !locked(qq)) {
Expand Down Expand Up @@ -2212,9 +2213,18 @@ static void add_ephemeron_to_pending(ptr pe) {
through `pending_ephemerons` can dramatically decrease the number
of times that we have to trigger re-checking, especially since
check_pending_pehemerons() is run only after all other sweep
opportunities are exhausted. */
EPHEMERONNEXT(pe) = pending_ephemerons;
pending_ephemerons = pe;
opportunities are exhausted.
Guard against adding an empheron to the pending list a second
time. For example, an emphemeron can get swept twice if it's in
generation 2 and points to an inaccessible generation 0 object;
sweeping 2->0 will conservatively assume that the target will
end up in generation 1, which causes sweeping 2->1 to see the
same ephemeron again. (That might be the only way to sweep
an ephemeron twice, but I'm not sure.) */
if (EPHEMERONNEXT(pe) == Sfalse) {
EPHEMERONNEXT(pe) = pending_ephemerons;
pending_ephemerons = pe;
}
}

static void add_trigger_ephemerons_to_repending(ptr pe) {
Expand Down Expand Up @@ -2264,6 +2274,7 @@ static void check_pending_ephemerons(ONLY_FORMAL_CTGS) {
pending_ephemerons = NULL;
while (pe != NULL) {
next_pe = EPHEMERONNEXT(pe);
EPHEMERONNEXT(pe) = Sfalse;
check_ephemeron(pe, 1 ACTUAL_CTGS);
pe = next_pe;
}
Expand Down Expand Up @@ -2320,7 +2331,7 @@ static IGEN check_dirty_ephemeron(ptr pe, IGEN youngest FORMAL_CTGS) {
}

static void clear_trigger_ephemerons(void) {
ptr pe;
ptr pe, next_pe;

if (pending_ephemerons != NULL)
S_error_abort("clear_trigger_ephemerons(gc): non-empty pending list");
Expand All @@ -2333,6 +2344,7 @@ static void clear_trigger_ephemerons(void) {
} else {
seginfo *si;
ptr p = Scar(pe);

/* Key never became reachable, so clear key and value */
INITCAR(pe) = Sbwp_object;
INITCDR(pe) = Sbwp_object;
Expand All @@ -2341,6 +2353,8 @@ static void clear_trigger_ephemerons(void) {
si = SegInfo(ptr_get_segment(p));
si->trigger_ephemerons = NULL;
}
pe = EPHEMERONNEXT(pe);
next_pe = EPHEMERONNEXT(pe);
EPHEMERONNEXT(pe) = Sfalse;
pe = next_pe;
}
}
13 changes: 13 additions & 0 deletions mats/4.ms
Original file line number Diff line number Diff line change
Expand Up @@ -3964,6 +3964,19 @@
;; Check that the GC update the reference to `key2` in `e`:
(eq? (car e) key2))))))))

;; ----------------------------------------
;; Check mutation two generations back and interaction with collection
(or (equal? (current-eval) interpret)
(equal? (with-interrupts-disabled
(let ([pr (ephemeron-cons 1 2)])
(collect 0)
(collect 1) ; puts `pr` in gen 2
(let ([tl (list 1 2 3)])
(set-car! pr tl) ; gen 2 reference to gen 0
(collect 1 1 2)
pr)))
'(#!bwp . #!bwp)))

;; ----------------------------------------
;; Check fasl:
(let ([s (gensym)])
Expand Down
5 changes: 5 additions & 0 deletions release_notes/release_notes.stex
Original file line number Diff line number Diff line change
Expand Up @@ -1966,6 +1966,11 @@ The size of these string and bytevector buffers was previously hardcoded at 1024
%-----------------------------------------------------------------------------
\section{Bug Fixes}\label{section:bugfixes}

\subsection{Garbage collector incorrectly handles emphemerons (9.6.0)}

A bug where the garbage collector sometimes incorrectly handles epehemeron pairs has
been fixed.

\subsection{Garbage collector incorrectly handles mutated weak pairs (9.6.0)}

A bug where the garbage collector sometimes incorrectly handles mutated weak pairs has
Expand Down

0 comments on commit cadb1bf

Please sign in to comment.