Disabling write barrier deferral in config.h, uncovered a second
problem: mps/test/function/eph1.c fails because segments aren't scanned
if the segment's summary doesn't intersect with the white set.
* mps/code/trace.c (traceFindGrey): Force rescanning by adding the white
set to the segments summary.
In traceScanSegRes, the assertion
AVER(RefSetSub(ScanStateUnfixedSummary(ss), SegSummary(seg)));
can fail if we call MPS_FIX1 on a reference but not MPS_FIX2. In a
normal Emacs session that tends to happen after ~10 minutes. If "write
barrier deferral" is disabled in config.h, then the tests in
mps/test/function/eph1.c will also run into this assertion.
I failed to create a reproducible test with write barrier deferral
enabled. Obvioulsy, I don't understand this issue fully.
* mps/code/poolawl.c (aephFixKey): Include the key in the SegSummary.
(aephIsWhite): Return the new reference, so that we can avoid calling
MPS_FIX2 twice.
* mps/code/trace.c (TraceRankForAccess): While in the ephemeron band,
use RankFINAL for final segments and RankEXACT for the others.
* mps/test/function/eph5.c: New Test.
* mps/test/testsets/passing: Include eph5.c.
* mps/test/test/testlib/ephfmt.h (union header): Use a one-word header.
* mps/test/test/testlib/ephfmt.c: Update accordingly.
* mps/test/function/eph1.c: Update accordingly.
Ephemerons solve the key-in-value problem for weak key/value pairs. It
seems that it's not possible to solve that problem with weak pointers or
finalizers. Basically we want a weak key/value pair that implements the
rule:
The value is reachable, if the key is reachable.
The key-in-value problem occurs if all paths to the key go through the
value. In this situation, the key is considered reachable only if the
value is "externally reachable", i.e. the value is reachable through a
path other than through the weak pair.
Such weak pairs seem to need an extra phase in the GC algorithm. See
[1] for some variants of the algorithm.
https://www.haible.de/bruno/papers/cs/weak/WeakDatastructures-writeup.html
* mps/code/mpmst.h (SegStruct): Add fields propagationNeeded,
marksChanged, and propagationFinished.
* mps/code/mpmtypes.h (RANK_LIST): Add EPHEMERON rank.
* mps/code/mps.s (mps_rank_ephemeron): New prototype.
* mps/code/mpscawl.h (mps_class_aeph, mps_fix_weak_pair)
(mps_fix_weak_or_pair, mps_fix_weak_and_pair): New prototypes.
* mps/code/mpsi.c (mps_rank_ephemeron): New function.
* mps/code/poolawl.c (AEPHSegStruct, AEPHPoolStruct): New. The
implementation the ephemeron pool.
* mps/code/seg.c (segAbsInit): Initialize propagationNeeded,
marksChanged, and propagationFinished.
* mps/code/trace.c (traceBandRetreat, tracePropagateToLowerRanks)
(moveSegToEndOfGreyRing): New helpers.
(TraceRankForAccess): Handle the RankEPHEMERON.
(traceFindGrey, traceScanSegRes): Add special handling for ephemeron
segments.
* mps/test/function/eph1.c: New test file.
* mps/test/function/eph2.c: New test file.
* mps/test/function/eph3.c: New test file.
* mps/test/function/eph4.c: New test file.
* mps/test/test/testlib/ephfmt.c: New file.
* mps/test/test/testlib/ephfmt.h: New file.
* mps/test/test/testlib/manifest: Add ephfmt.c.
* mps/test/testsets/passing: Include eph{1,2,3,4}.c.
Mostly boilerplate code to override the SegAccess method of AWLSeg.
* mps/code/poolawl.c (AWL0Pool, AWL0Seg): New classes.
(awl0SegAccess, awl0BufferFill): New methods.
* mps/code/eventsql.c (PRINTF_ARCHETYPE) [__MINGW32__]: Define as
__gnu_printf__ for MinGW builds, to support ANSI- and GNU-compatible
format specs.
(vlog, evlog, error): Use PRINTF_ARCHETYPE.
* mps/code/mingw.gmk (CFLAGSCOMPILERSTRICT): Use gnu99, not gnu89.
* mps/configure.ac (EXEEXT): Define and use for program names.
(i*86-*-mingw*/no, x86_64-*-mingw*/no): Add definitions for MinGW.
* mps/example/scheme/Makefile.in (VPATH): Set VPATH.
* mps/Makefile.in (COMMON_OPTS): New. Pass SRCDIR down to sub-make.
* mps/code/comm.gmk (VPATH): Set VPATH from SRCDIR parameter
* mps/configure.ac (AC_CONFIG_COMMANDS): Copy .gmk makefiles and some
other things to the biuld directory.
* mps/code/comm.gmk (LIB_TARGETS, TEST_TARGETS, EVENT_TARGETS)
(TEST_SUITES, testmmqa): If VARIETY is not defined, then disable
parallism with .NOTPARALLEL. Otherwise, avoid the recursive make with
a static pattern rule.
(clean-testansi, clean-testpollnone): New.
* mps/Makefile.in (build-via-make): Invoke submake explicit
VARIETY argument to allow more parallelism.
(test-make-build): Use clean-testansi and clean-testpollnone.