diff --git a/mps/code/global.c b/mps/code/global.c index aab86d2dcc4..1ff5ac8f151 100644 --- a/mps/code/global.c +++ b/mps/code/global.c @@ -871,7 +871,7 @@ Res ArenaDefinalize(Arena arena, Ref obj) } -/* Peek / Poke */ +/* ArenaPeek -- read a single reference, possibly through a barrier */ Ref ArenaPeek(Arena arena, Ref *p) { @@ -888,74 +888,19 @@ Ref ArenaPeek(Arena arena, Ref *p) return ref; } +/* ArenaPeekSeg -- as ArenaPeek, but p must be in seg. */ + Ref ArenaPeekSeg(Arena arena, Seg seg, Ref *p) { Ref ref; - - AVERT(Arena, arena); - AVERT(Seg, seg); - - AVER(SegBase(seg) <= (Addr)p); - AVER((Addr)p < SegLimit(seg)); - /* TODO: Consider checking p's alignment using seg->pool->alignment */ - - ShieldExpose(arena, seg); - ref = *p; - ShieldCover(arena, seg); - return ref; -} - -void ArenaPoke(Arena arena, Ref *p, Ref ref) -{ - Seg seg; - - AVERT(Arena, arena); - /* Can't check p as it is arbitrary */ - /* Can't check ref as it is arbitrary */ - - if (SegOfAddr(&seg, arena, (Addr)p)) - ArenaPokeSeg(arena, seg, p, ref); - else - *p = ref; -} - -void ArenaPokeSeg(Arena arena, Seg seg, Ref *p, Ref ref) -{ - RefSet summary; - - AVERT(Arena, arena); - AVERT(Seg, seg); - AVER(SegBase(seg) <= (Addr)p); - AVER((Addr)p < SegLimit(seg)); - /* TODO: Consider checking p's alignment using seg->pool->alignment */ - /* ref is arbitrary and can't be checked */ - - ShieldExpose(arena, seg); - *p = ref; - summary = SegSummary(seg); - summary = RefSetAdd(arena, summary, (Addr)ref); - SegSetSummary(seg, summary); - ShieldCover(arena, seg); -} - - -/* ArenaRead -- read a single reference, possibly through a barrier - * - * This forms part of a software barrier. It provides fine-grain access - * to single references in segments. - * - * See also PoolSingleAccess and PoolSegAccess. */ - -Ref ArenaRead(Arena arena, Ref *p) -{ - Bool b; - Seg seg = NULL; /* suppress "may be used uninitialized" */ Rank rank; AVERT(Arena, arena); - - b = SegOfAddr(&seg, arena, (Addr)p); - AVER(b == TRUE); + AVERT(Seg, seg); + AVER(PoolArena(SegPool(seg)) == arena); + AVER(SegBase(seg) <= (Addr)p); + AVER((Addr)p < SegLimit(seg)); + /* TODO: Consider checking p's alignment using seg->pool->alignment */ /* .read.flipped: We AVER that the reference that we are reading */ /* refers to an object for which all the traces that the object is */ @@ -977,11 +922,81 @@ Ref ArenaRead(Arena arena, Ref *p) /* We don't need to update the Seg Summary as in PoolSingleAccess * because we are not changing it after it has been scanned. */ + + ShieldExpose(arena, seg); + ref = *p; + ShieldCover(arena, seg); + return ref; +} + +/* ArenaPoke -- write a single reference, possibly through a barrier */ + +void ArenaPoke(Arena arena, Ref *p, Ref ref) +{ + Seg seg; + + AVERT(Arena, arena); + /* Can't check p as it is arbitrary */ + /* Can't check ref as it is arbitrary */ + + if (SegOfAddr(&seg, arena, (Addr)p)) + ArenaPokeSeg(arena, seg, p, ref); + else + *p = ref; +} + +/* ArenaPokeSeg -- as ArenaPoke, but p must be in seg. */ + +void ArenaPokeSeg(Arena arena, Seg seg, Ref *p, Ref ref) +{ + RefSet summary; + + AVERT(Arena, arena); + AVERT(Seg, seg); + AVER(PoolArena(SegPool(seg)) == arena); + AVER(SegBase(seg) <= (Addr)p); + AVER((Addr)p < SegLimit(seg)); + /* TODO: Consider checking p's alignment using seg->pool->alignment */ + /* ref is arbitrary and can't be checked */ + + ShieldExpose(arena, seg); + *p = ref; + summary = SegSummary(seg); + summary = RefSetAdd(arena, summary, (Addr)ref); + SegSetSummary(seg, summary); + ShieldCover(arena, seg); +} + +/* ArenaRead -- like ArenaPeek, but reference known to be owned by arena */ + +Ref ArenaRead(Arena arena, Ref *p) +{ + Bool b; + Seg seg = NULL; /* suppress "may be used uninitialized" */ + + AVERT(Arena, arena); + + b = SegOfAddr(&seg, arena, (Addr)p); + AVER(b == TRUE); - /* get the possibly fixed reference */ return ArenaPeekSeg(arena, seg, p); } +/* ArenaWrite -- like ArenaPoke, but reference known to be owned by arena */ + +void ArenaWrite(Arena arena, Ref *p, Ref ref) +{ + Bool b; + Seg seg = NULL; /* suppress "may be used uninitialized" */ + + AVERT(Arena, arena); + + b = SegOfAddr(&seg, arena, (Addr)p); + AVER(b == TRUE); + + ArenaPokeSeg(arena, seg, p, ref); +} + /* GlobalsDescribe -- describe the arena globals */ diff --git a/mps/code/mpm.h b/mps/code/mpm.h index 4bb6638abbf..a031792ffc4 100644 --- a/mps/code/mpm.h +++ b/mps/code/mpm.h @@ -563,37 +563,32 @@ extern void ControlFree(Arena arena, void *base, size_t size); extern Res ControlDescribe(Arena arena, mps_lib_FILE *stream, Count depth); -/* Peek/Poke +/* Peek/Poke/Read/Write -- read/write possibly through barrier * * These are provided so that modules in the MPS can make occasional - * access to client data. They perform the appropriate shield and - * summary manipulations that are necessary. + * access to client data, and to implement a software barrier for + * segments that are not handed out to the mutator. They protect the + * necessary colour, shield and summary invariants. * - * Note that Peek and Poke can be called with address that may or - * may not be in arena managed memory. */ + * Note that Peek and Poke can be called with an address that may or + * may not be in memory managed by arena, whereas Read and Write + * assert this is the case. + */ /* Peek reads a value */ extern Ref ArenaPeek(Arena arena, Ref *p); +/* Same, but p known to be owned by arena */ +extern Ref ArenaRead(Arena arena, Ref *p); /* Same, but p must be in seg */ extern Ref ArenaPeekSeg(Arena arena, Seg seg, Ref *p); /* Poke stores a value */ extern void ArenaPoke(Arena arena, Ref *p, Ref ref); +/* Same, but p known to be owned by arena */ +extern void ArenaWrite(Arena arena, Ref *p, Ref ref); /* Same, but p must be in seg */ extern void ArenaPokeSeg(Arena arena, Seg seg, Ref *p, Ref ref); -/* Read/Write - * - * These simulate mutator reads and writes to locations. - * They are effectively a software barrier, and maintain the tricolor - * invariant (hence performing any scanning or color manipulation - * necessary). - * - * Only Read provided right now. */ - -Ref ArenaRead(Arena arena, Ref *p); - - extern Size ArenaReserved(Arena arena); extern Size ArenaCommitted(Arena arena); extern Size ArenaSpareCommitted(Arena arena); diff --git a/mps/code/poolmrg.c b/mps/code/poolmrg.c index 12bbf6b2953..a54758c5599 100644 --- a/mps/code/poolmrg.c +++ b/mps/code/poolmrg.c @@ -74,7 +74,8 @@ typedef struct RefPartStruct { } RefPartStruct; -/* MRGRefPartRef,MRGRefPartSetRef -- Peek and poke the reference +/* MRGRefPartRef,MRGRefPartSetRef -- read and write the reference + * using the software barrier * * Might be more efficient to take a seg, rather than calculate it * every time. @@ -87,7 +88,7 @@ static Ref MRGRefPartRef(Arena arena, RefPart refPart) AVER(refPart != NULL); - ref = ArenaPeek(arena, &refPart->ref); + ref = ArenaRead(arena, &refPart->ref); return ref; } @@ -102,7 +103,7 @@ static void MRGRefPartSetRef(Arena arena, RefPart refPart, Ref ref) { AVER(refPart != NULL); - ArenaPoke(arena, &refPart->ref, ref); + ArenaWrite(arena, &refPart->ref, ref); } @@ -166,7 +167,7 @@ typedef struct MRGRefSegStruct { /* forward declarations */ DECLARE_CLASS(Seg, MRGLinkSeg, Seg); -DECLARE_CLASS(Seg, MRGRefSeg, MutatorSeg); +DECLARE_CLASS(Seg, MRGRefSeg, GCSeg); /* MRGLinkSegCheck -- check a link segment @@ -296,7 +297,7 @@ DEFINE_CLASS(Seg, MRGLinkSeg, klass) DEFINE_CLASS(Seg, MRGRefSeg, klass) { - INHERIT_CLASS(klass, MRGRefSeg, MutatorSeg); + INHERIT_CLASS(klass, MRGRefSeg, GCSeg); SegClassMixInNoSplitMerge(klass); /* no support for this */ klass->size = sizeof(MRGRefSegStruct); klass->init = MRGRefSegInit; diff --git a/mps/code/seg.c b/mps/code/seg.c index 5177913ea3c..3debf913d67 100644 --- a/mps/code/seg.c +++ b/mps/code/seg.c @@ -1247,7 +1247,7 @@ static void gcSegSetWhite(Seg seg, TraceSet white) AVER_CRITICAL(trseg == seg); TractSetWhite(tract, BS_BITFIELD(Trace, white)); } - AVER(addr == limit); + AVER_CRITICAL(addr == limit); seg->white = BS_BITFIELD(Trace, white); } @@ -1339,7 +1339,7 @@ static void gcSegSetSummary(Seg seg, RefSet summary) gcseg->summary = summary; - AVER(seg->rankSet != RankSetEMPTY); + AVER_CRITICAL(seg->rankSet != RankSetEMPTY); } @@ -1371,7 +1371,7 @@ static void gcSegSetRankSummary(Seg seg, RankSet rankSet, RefSet summary) AVER_CRITICAL(&gcseg->segStruct == seg); /* rankSet == RankSetEMPTY implies summary == RefSetEMPTY */ - AVER(rankSet != RankSetEMPTY || summary == RefSetEMPTY); + AVER_CRITICAL(rankSet != RankSetEMPTY || summary == RefSetEMPTY); seg->rankSet = BS_BITFIELD(Rank, rankSet); gcseg->summary = summary; diff --git a/mps/design/finalize.txt b/mps/design/finalize.txt index f75cb3ccd24..65f82562494 100644 --- a/mps/design/finalize.txt +++ b/mps/design/finalize.txt @@ -74,30 +74,11 @@ then ``ArenaDestroy()`` destroys the final pool. _`.impl.access`: ``mps_message_finalization_ref()`` needs to access the finalization message to retrieve the reference and then write it to where the client asks. This must be done carefully, in order to -avoid hitting the write barrier or invalidating collection invariants -such as the segment summary. +avoid invalidating collection invariants such as the segment summary. -_`.impl.invariants`: We protect the invariants by using special -routines ``ArenaRead()`` and ``ArenaPoke()`` to read and write the -reference. This works as long as there's no write-barrier collection. - -.. note:: - - Instead of ``ArenaPoke()``, we could put in an ``ArenaWrite()`` - that would be identical to ``ArenaPoke()``, except that it would - ``AVER()`` the invariant (or it can just ``AVER()`` that there are - no busy traces unflipped). When we get write-barrier collection, - we could change it to do the real thing, but in the absence of a - write-barrier, it's functionally identical to ``ArenaPoke()``. - Pekka P. Pirinen, 1997-12-09. - -.. note:: - - There is no need to maintain a write barrier on segments belonging - to the MRG pool, as these segments are never given to the mutator. - See job004030_. - - .. _job004030: https://www.ravenbrook.com/project/mps/issue/job004030/ +_`.impl.invariants`: We protect the invariants by using +``ArenaRead()`` and ``ArenaWrite()`` to read and write the reference +via the software barrier. External interface