mirror of
git://git.sv.gnu.org/emacs.git
synced 2025-12-27 07:41:28 -08:00
Merge branch/2018-06-18/mrgseg into the master sources.
Copied from Perforce Change: 194453
This commit is contained in:
commit
551d35fa0a
20 changed files with 311 additions and 216 deletions
|
|
@ -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 */
|
||||
|
||||
|
|
|
|||
|
|
@ -605,11 +605,11 @@ static void PoolGenAccountForAlloc(PoolGen pgen, Size size)
|
|||
|
||||
/* PoolGenAlloc -- allocate a segment in a pool generation
|
||||
*
|
||||
* Allocate a GCSeg, attach it to the generation, and update the
|
||||
* accounting.
|
||||
* Allocate a segment belong to klass (which must be GCSegClass or a
|
||||
* subclass), attach it to the generation, and update the accounting.
|
||||
*/
|
||||
|
||||
Res PoolGenAlloc(Seg *segReturn, PoolGen pgen, SegClass class, Size size,
|
||||
Res PoolGenAlloc(Seg *segReturn, PoolGen pgen, SegClass klass, Size size,
|
||||
ArgList args)
|
||||
{
|
||||
LocusPrefStruct pref;
|
||||
|
|
@ -621,7 +621,8 @@ Res PoolGenAlloc(Seg *segReturn, PoolGen pgen, SegClass class, Size size,
|
|||
|
||||
AVER(segReturn != NULL);
|
||||
AVERT(PoolGen, pgen);
|
||||
AVERT(SegClass, class);
|
||||
AVERT(SegClass, klass);
|
||||
AVER(IsSubclass(klass, GCSeg));
|
||||
AVER(size > 0);
|
||||
AVERT(ArgList, args);
|
||||
|
||||
|
|
@ -633,7 +634,7 @@ Res PoolGenAlloc(Seg *segReturn, PoolGen pgen, SegClass class, Size size,
|
|||
pref.high = FALSE;
|
||||
pref.zones = zones;
|
||||
pref.avoid = ZoneSetBlacklist(arena);
|
||||
res = SegAlloc(&seg, class, &pref, size, pgen->pool, args);
|
||||
res = SegAlloc(&seg, klass, &pref, size, pgen->pool, args);
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
|
||||
|
|
|
|||
|
|
@ -551,37 +551,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);
|
||||
|
|
@ -651,6 +646,7 @@ extern Bool SegNext(Seg *segReturn, Arena arena, Seg seg);
|
|||
extern Bool SegNextOfRing(Seg *segReturn, Arena arena, Pool pool, Ring next);
|
||||
extern void SegSetWhite(Seg seg, TraceSet white);
|
||||
extern void SegSetGrey(Seg seg, TraceSet grey);
|
||||
extern void SegFlip(Seg seg, Trace trace);
|
||||
extern void SegSetRankSet(Seg seg, RankSet rankSet);
|
||||
extern void SegSetRankAndSummary(Seg seg, RankSet rankSet, RefSet summary);
|
||||
extern Res SegMerge(Seg *mergedSegReturn, Seg segLo, Seg segHi);
|
||||
|
|
@ -684,6 +680,7 @@ extern Bool SegClassCheck(SegClass klass);
|
|||
DECLARE_CLASS(Inst, SegClass, InstClass);
|
||||
DECLARE_CLASS(Seg, Seg, Inst);
|
||||
DECLARE_CLASS(Seg, GCSeg, Seg);
|
||||
DECLARE_CLASS(Seg, MutatorSeg, GCSeg);
|
||||
#define SegGCSeg(seg) MustBeA(GCSeg, (seg))
|
||||
extern void SegClassMixInNoSplitMerge(SegClass klass);
|
||||
|
||||
|
|
|
|||
|
|
@ -191,6 +191,7 @@ typedef struct SegClassStruct {
|
|||
SegSetBufferMethod setBuffer; /* set the segment buffer */
|
||||
SegUnsetBufferMethod unsetBuffer; /* unset the segment buffer */
|
||||
SegSetGreyMethod setGrey; /* change greyness of segment */
|
||||
SegFlipMethod flip; /* raise barrier for a flipped trace */
|
||||
SegSetWhiteMethod setWhite; /* change whiteness of segment */
|
||||
SegSetRankSetMethod setRankSet; /* change rank set of segment */
|
||||
SegSetRankSummaryMethod setRankSummary; /* change rank set & summary */
|
||||
|
|
|
|||
|
|
@ -153,6 +153,7 @@ typedef void (*FreeBlockVisitor)(Addr base, Addr limit, Pool pool, void *p);
|
|||
typedef Res (*SegInitMethod)(Seg seg, Pool pool, Addr base, Size size,
|
||||
ArgList args);
|
||||
typedef void (*SegSetGreyMethod)(Seg seg, TraceSet grey);
|
||||
typedef void (*SegFlipMethod)(Seg seg, Trace trace);
|
||||
typedef void (*SegSetWhiteMethod)(Seg seg, TraceSet white);
|
||||
typedef void (*SegSetRankSetMethod)(Seg seg, RankSet rankSet);
|
||||
typedef void (*SegSetRankSummaryMethod)(Seg seg, RankSet rankSet,
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ typedef AMC AMCPool;
|
|||
DECLARE_CLASS(Pool, AMCPool, AMCZPool);
|
||||
|
||||
DECLARE_CLASS(Buffer, amcBuf, SegBuf);
|
||||
DECLARE_CLASS(Seg, amcSeg, GCSeg);
|
||||
DECLARE_CLASS(Seg, amcSeg, MutatorSeg);
|
||||
|
||||
|
||||
/* amcGenStruct -- pool AMC generation descriptor */
|
||||
|
|
@ -351,7 +351,7 @@ static Res AMCSegDescribe(Inst inst, mps_lib_FILE *stream, Count depth)
|
|||
|
||||
DEFINE_CLASS(Seg, amcSeg, klass)
|
||||
{
|
||||
INHERIT_CLASS(klass, amcSeg, GCSeg);
|
||||
INHERIT_CLASS(klass, amcSeg, MutatorSeg);
|
||||
SegClassMixInNoSplitMerge(klass); /* no support for this (yet) */
|
||||
klass->instClassStruct.describe = AMCSegDescribe;
|
||||
klass->instClassStruct.finish = amcSegFinish;
|
||||
|
|
|
|||
|
|
@ -615,7 +615,7 @@ static Res AMSSegDescribe(Inst inst, mps_lib_FILE *stream, Count depth)
|
|||
|
||||
DEFINE_CLASS(Seg, AMSSeg, klass)
|
||||
{
|
||||
INHERIT_CLASS(klass, AMSSeg, GCSeg);
|
||||
INHERIT_CLASS(klass, AMSSeg, MutatorSeg);
|
||||
klass->instClassStruct.describe = AMSSegDescribe;
|
||||
klass->instClassStruct.finish = AMSSegFinish;
|
||||
klass->size = sizeof(AMSSegStruct);
|
||||
|
|
|
|||
|
|
@ -172,7 +172,7 @@ DECLARE_CLASS(Pool, AMSPool, AbstractCollectPool);
|
|||
typedef AMS AMSDebugPool;
|
||||
DECLARE_CLASS(Pool, AMSDebugPool, AMSPool);
|
||||
|
||||
DECLARE_CLASS(Seg, AMSSeg, GCSeg);
|
||||
DECLARE_CLASS(Seg, AMSSeg, MutatorSeg);
|
||||
|
||||
|
||||
#endif /* poolams_h */
|
||||
|
|
|
|||
|
|
@ -111,10 +111,7 @@ typedef AWL AWLPool;
|
|||
DECLARE_CLASS(Pool, AWLPool, AbstractCollectPool);
|
||||
|
||||
|
||||
/* AWLSegStruct -- AWL segment subclass
|
||||
*
|
||||
* Subclass of GCSeg
|
||||
*/
|
||||
/* AWLSegStruct -- AWL segment subclass */
|
||||
|
||||
#define AWLSegSig ((Sig)0x519A3759) /* SIGnature AWL SeG */
|
||||
|
||||
|
|
@ -134,7 +131,7 @@ typedef struct AWLSegStruct {
|
|||
Sig sig; /* <code/misc.h#sig> */
|
||||
} AWLSegStruct, *AWLSeg;
|
||||
|
||||
DECLARE_CLASS(Seg, AWLSeg, GCSeg);
|
||||
DECLARE_CLASS(Seg, AWLSeg, MutatorSeg);
|
||||
|
||||
ATTRIBUTE_UNUSED
|
||||
static Bool AWLSegCheck(AWLSeg awlseg)
|
||||
|
|
@ -277,7 +274,7 @@ static void AWLSegFinish(Inst inst)
|
|||
|
||||
DEFINE_CLASS(Seg, AWLSeg, klass)
|
||||
{
|
||||
INHERIT_CLASS(klass, AWLSeg, GCSeg);
|
||||
INHERIT_CLASS(klass, AWLSeg, MutatorSeg);
|
||||
SegClassMixInNoSplitMerge(klass); /* no support for this (yet) */
|
||||
klass->instClassStruct.finish = AWLSegFinish;
|
||||
klass->size = sizeof(AWLSegStruct);
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ typedef struct LOStruct {
|
|||
typedef LO LOPool;
|
||||
#define LOPoolCheck LOCheck
|
||||
DECLARE_CLASS(Pool, LOPool, AbstractSegBufPool);
|
||||
DECLARE_CLASS(Seg, LOSeg, GCSeg);
|
||||
DECLARE_CLASS(Seg, LOSeg, MutatorSeg);
|
||||
|
||||
|
||||
/* forward declaration */
|
||||
|
|
@ -71,7 +71,7 @@ static void loSegWalk(Seg seg, Format format, FormattedObjectsVisitor f,
|
|||
|
||||
DEFINE_CLASS(Seg, LOSeg, klass)
|
||||
{
|
||||
INHERIT_CLASS(klass, LOSeg, GCSeg);
|
||||
INHERIT_CLASS(klass, LOSeg, MutatorSeg);
|
||||
SegClassMixInNoSplitMerge(klass);
|
||||
klass->instClassStruct.finish = loSegFinish;
|
||||
klass->size = sizeof(LOSegStruct);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ typedef SNC SNCPool;
|
|||
#define SNCPoolCheck SNCCheck
|
||||
DECLARE_CLASS(Pool, SNCPool, AbstractSegBufPool);
|
||||
|
||||
DECLARE_CLASS(Seg, SNCSeg, GCSeg);
|
||||
DECLARE_CLASS(Seg, SNCSeg, MutatorSeg);
|
||||
DECLARE_CLASS(Buffer, SNCBuf, RankBuf);
|
||||
static Bool SNCCheck(SNC snc);
|
||||
static void sncPopPartialSegChain(SNC snc, Buffer buf, Seg upTo);
|
||||
|
|
@ -171,7 +171,7 @@ DEFINE_CLASS(Buffer, SNCBuf, klass)
|
|||
|
||||
/* SNCSegStruct -- SNC segment subclass
|
||||
*
|
||||
* This subclass of GCSeg links segments in chains.
|
||||
* This subclass of MutatorSeg links segments in chains.
|
||||
*/
|
||||
|
||||
#define SNCSegSig ((Sig)0x51954C59) /* SIGSNCSeG */
|
||||
|
|
@ -247,7 +247,7 @@ static void sncSegFinish(Inst inst)
|
|||
|
||||
DEFINE_CLASS(Seg, SNCSeg, klass)
|
||||
{
|
||||
INHERIT_CLASS(klass, SNCSeg, GCSeg);
|
||||
INHERIT_CLASS(klass, SNCSeg, MutatorSeg);
|
||||
SegClassMixInNoSplitMerge(klass); /* no support for this (yet) */
|
||||
klass->instClassStruct.finish = sncSegFinish;
|
||||
klass->size = sizeof(SNCSegStruct);
|
||||
|
|
|
|||
230
mps/code/seg.c
230
mps/code/seg.c
|
|
@ -7,15 +7,8 @@
|
|||
*
|
||||
* PURPOSE
|
||||
*
|
||||
* .purpose: This is the implementation of the generic segment interface.
|
||||
* It defines the interface functions and two useful segment classes:
|
||||
* .purpose.class.seg: Class Seg is a class which is as simple
|
||||
* as efficiency demands permit. (It includes fields for storing colour
|
||||
* for efficiency). It may be subclassed by clients of the module.
|
||||
* .purpose.class.seg-gc: Class GCSeg is a concrete class support all
|
||||
* all current GC features, and providing full backwards compatibility
|
||||
* with "old-style" segments. It may be subclassed by clients of the
|
||||
* module.
|
||||
* .purpose: This is the implementation of the generic segment
|
||||
* interface and the segment classes Seg, GCSeg and MutatorSeg.
|
||||
*/
|
||||
|
||||
#include "tract.h"
|
||||
|
|
@ -113,7 +106,7 @@ void SegFree(Seg seg)
|
|||
|
||||
/* SegInit -- initialize a segment */
|
||||
|
||||
static Res SegAbsInit(Seg seg, Pool pool, Addr base, Size size, ArgList args)
|
||||
static Res segAbsInit(Seg seg, Pool pool, Addr base, Size size, ArgList args)
|
||||
{
|
||||
Arena arena;
|
||||
Addr addr, limit;
|
||||
|
|
@ -185,7 +178,7 @@ static Res SegInit(Seg seg, SegClass klass, Pool pool, Addr base, Size size, Arg
|
|||
|
||||
/* SegFinish -- finish a segment */
|
||||
|
||||
static void SegAbsFinish(Inst inst)
|
||||
static void segAbsFinish(Inst inst)
|
||||
{
|
||||
Seg seg = MustBeA(Seg, inst);
|
||||
Arena arena;
|
||||
|
|
@ -259,6 +252,22 @@ void SegSetGrey(Seg seg, TraceSet grey)
|
|||
greyness, or if the segment doesn't contain any references. */
|
||||
if (grey != SegGrey(seg) && SegRankSet(seg) != RankSetEMPTY)
|
||||
Method(Seg, seg, setGrey)(seg, grey);
|
||||
|
||||
EVENT3(SegSetGrey, PoolArena(SegPool(seg)), seg, grey);
|
||||
}
|
||||
|
||||
|
||||
/* SegFlip -- update barriers for trace that's about to flip */
|
||||
|
||||
void SegFlip(Seg seg, Trace trace)
|
||||
{
|
||||
AVERT(Seg, seg);
|
||||
AVERT(Trace, trace);
|
||||
|
||||
/* Don't dispatch to the class method unless the segment is grey for
|
||||
the trace that's about to flip, and contains references. */
|
||||
if (TraceSetIsMember(SegGrey(seg), trace) && SegRankSet(seg) != RankSetEMPTY)
|
||||
Method(Seg, seg, flip)(seg, trace);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -385,7 +394,7 @@ Addr SegBufferScanLimit(Seg seg)
|
|||
|
||||
/* SegDescribe -- describe a segment */
|
||||
|
||||
Res SegAbsDescribe(Inst inst, mps_lib_FILE *stream, Count depth)
|
||||
static Res segAbsDescribe(Inst inst, mps_lib_FILE *stream, Count depth)
|
||||
{
|
||||
Seg seg = CouldBeA(Seg, inst);
|
||||
Res res;
|
||||
|
|
@ -929,6 +938,16 @@ static void segNoSetGrey(Seg seg, TraceSet grey)
|
|||
}
|
||||
|
||||
|
||||
/* segTrivFlip -- ignore trace that's about to flip */
|
||||
|
||||
static void segTrivFlip(Seg seg, Trace trace)
|
||||
{
|
||||
AVERT(Seg, seg);
|
||||
AVERT(Trace, trace);
|
||||
AVER(seg->rankSet != RankSetEMPTY);
|
||||
}
|
||||
|
||||
|
||||
/* segNoSetWhite -- non-method to change the whiteness of a segment */
|
||||
|
||||
static void segNoSetWhite(Seg seg, TraceSet white)
|
||||
|
|
@ -1308,7 +1327,7 @@ static void segNoGreyen(Seg seg, Trace trace)
|
|||
}
|
||||
|
||||
|
||||
/* segNoGreyen -- blacken method for non-GC segs */
|
||||
/* segNoBlacken -- blacken method for non-GC segs */
|
||||
|
||||
static void segNoBlacken(Seg seg, TraceSet traceSet)
|
||||
{
|
||||
|
|
@ -1369,9 +1388,7 @@ static void segTrivWalk(Seg seg, Format format, FormattedObjectsVisitor f,
|
|||
}
|
||||
|
||||
|
||||
/* Class GCSeg -- Segment class with GC support
|
||||
*/
|
||||
|
||||
/* Class GCSeg -- collectable segment class */
|
||||
|
||||
/* GCSegCheck -- check the integrity of a GCSeg */
|
||||
|
||||
|
|
@ -1520,31 +1537,39 @@ static void gcSegSetGreyInternal(Seg seg, TraceSet oldGrey, TraceSet grey)
|
|||
|
||||
/* gcSegSetGrey -- GCSeg method to change the greyness of a segment
|
||||
*
|
||||
* Sets the segment greyness to the trace set grey and adjusts
|
||||
* the shielding on the segment appropriately.
|
||||
* Sets the segment greyness to the trace set grey.
|
||||
*/
|
||||
|
||||
static void gcSegSetGrey(Seg seg, TraceSet grey)
|
||||
{
|
||||
GCSeg gcseg;
|
||||
AVERT_CRITICAL(Seg, seg); /* .seg.method.check */
|
||||
AVERT_CRITICAL(TraceSet, grey); /* .seg.method.check */
|
||||
AVER_CRITICAL(seg->rankSet != RankSetEMPTY);
|
||||
|
||||
gcSegSetGreyInternal(seg, seg->grey, grey); /* do the work */
|
||||
}
|
||||
|
||||
|
||||
/* mutatorSegSetGrey -- MutatorSeg method to change greyness of segment
|
||||
*
|
||||
* As gcSegSetGrey, but also raise or lower the read barrier.
|
||||
*/
|
||||
|
||||
static void mutatorSegSetGrey(Seg seg, TraceSet grey)
|
||||
{
|
||||
TraceSet oldGrey, flippedTraces;
|
||||
Arena arena;
|
||||
|
||||
AVERT_CRITICAL(Seg, seg); /* .seg.method.check */
|
||||
AVERT_CRITICAL(TraceSet, grey); /* .seg.method.check */
|
||||
AVER(seg->rankSet != RankSetEMPTY);
|
||||
gcseg = SegGCSeg(seg);
|
||||
AVERT_CRITICAL(GCSeg, gcseg);
|
||||
AVER_CRITICAL(&gcseg->segStruct == seg);
|
||||
UNUSED(gcseg);
|
||||
|
||||
arena = PoolArena(SegPool(seg));
|
||||
oldGrey = seg->grey;
|
||||
gcSegSetGreyInternal(seg, oldGrey, grey); /* do the work */
|
||||
|
||||
NextMethod(Seg, MutatorSeg, setGrey)(seg, grey);
|
||||
|
||||
/* The read barrier is raised when the segment is grey for */
|
||||
/* some _flipped_ trace, i.e., is grey for a trace for which */
|
||||
/* the mutator is black. */
|
||||
arena = PoolArena(SegPool(seg));
|
||||
flippedTraces = arena->flippedTraces;
|
||||
if (TraceSetInter(oldGrey, flippedTraces) == TraceSetEMPTY) {
|
||||
if (TraceSetInter(grey, flippedTraces) != TraceSetEMPTY)
|
||||
|
|
@ -1553,8 +1578,31 @@ static void gcSegSetGrey(Seg seg, TraceSet grey)
|
|||
if (TraceSetInter(grey, flippedTraces) == TraceSetEMPTY)
|
||||
ShieldLower(arena, seg, AccessREAD);
|
||||
}
|
||||
}
|
||||
|
||||
EVENT3(SegSetGrey, arena, seg, grey);
|
||||
/* mutatorSegFlip -- update barriers for a trace that's about to flip */
|
||||
|
||||
static void mutatorSegFlip(Seg seg, Trace trace)
|
||||
{
|
||||
TraceSet flippedTraces;
|
||||
Arena arena;
|
||||
|
||||
NextMethod(Seg, MutatorSeg, flip)(seg, trace);
|
||||
|
||||
arena = PoolArena(SegPool(seg));
|
||||
flippedTraces = arena->flippedTraces;
|
||||
AVER(!TraceSetIsMember(flippedTraces, trace));
|
||||
|
||||
/* Raise the read barrier if the segment was not grey for any
|
||||
currently flipped trace. */
|
||||
if (TraceSetInter(SegGrey(seg), flippedTraces) == TraceSetEMPTY) {
|
||||
ShieldRaise(arena, seg, AccessREAD);
|
||||
} else {
|
||||
/* If the segment is grey for some currently flipped trace then
|
||||
the read barrier must already have been raised, either in this
|
||||
method or in mutatorSegSetGrey. */
|
||||
AVER(SegSM(seg) & AccessREAD);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1588,19 +1636,13 @@ 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);
|
||||
}
|
||||
|
||||
|
||||
/* gcSegSetRankSet -- GCSeg method to set the rank set of a segment
|
||||
*
|
||||
* If the rank set is made non-empty then the segment's summary is
|
||||
* now a subset of the mutator's (which is assumed to be RefSetUNIV)
|
||||
* so the write barrier must be imposed on the segment. If the
|
||||
* rank set is made empty then there are no longer any references
|
||||
* on the segment so the barrier is removed.
|
||||
*
|
||||
* The caller must set the summary to empty before setting the rank
|
||||
* set to empty. The caller must set the rank set to non-empty before
|
||||
|
|
@ -1609,38 +1651,62 @@ static void gcSegSetWhite(Seg seg, TraceSet white)
|
|||
|
||||
static void gcSegSetRankSet(Seg seg, RankSet rankSet)
|
||||
{
|
||||
GCSeg gcseg;
|
||||
RankSet oldRankSet;
|
||||
Arena arena;
|
||||
|
||||
AVERT_CRITICAL(Seg, seg); /* .seg.method.check */
|
||||
AVERT_CRITICAL(RankSet, rankSet); /* .seg.method.check */
|
||||
AVER_CRITICAL(rankSet == RankSetEMPTY
|
||||
|| RankSetIsSingle(rankSet)); /* .seg.method.check */
|
||||
gcseg = SegGCSeg(seg);
|
||||
AVERT_CRITICAL(GCSeg, gcseg);
|
||||
AVER_CRITICAL(&gcseg->segStruct == seg);
|
||||
|
||||
arena = PoolArena(SegPool(seg));
|
||||
oldRankSet = seg->rankSet;
|
||||
seg->rankSet = BS_BITFIELD(Rank, rankSet);
|
||||
}
|
||||
|
||||
|
||||
/* mutatorSegSetRankSet -- MutatorSeg method to set rank set of segment
|
||||
*
|
||||
* As gcSegSetRankSet, but also sets or clears the write barrier on
|
||||
* the segment.
|
||||
*
|
||||
* If the rank set is made non-empty then the segment's summary is now
|
||||
* a subset of the mutator's (which is assumed to be RefSetUNIV) so
|
||||
* the write barrier must be imposed on the segment. If the rank set
|
||||
* is made empty then there are no longer any references on the
|
||||
* segment so the barrier is removed.
|
||||
*/
|
||||
|
||||
static void mutatorSegSetRankSet(Seg seg, RankSet rankSet)
|
||||
{
|
||||
RankSet oldRankSet;
|
||||
|
||||
AVERT_CRITICAL(Seg, seg); /* .seg.method.check */
|
||||
oldRankSet = seg->rankSet;
|
||||
|
||||
NextMethod(Seg, MutatorSeg, setRankSet)(seg, rankSet);
|
||||
|
||||
if (oldRankSet == RankSetEMPTY) {
|
||||
if (rankSet != RankSetEMPTY) {
|
||||
AVER(gcseg->summary == RefSetEMPTY);
|
||||
ShieldRaise(arena, seg, AccessWRITE);
|
||||
AVER_CRITICAL(SegGCSeg(seg)->summary == RefSetEMPTY);
|
||||
ShieldRaise(PoolArena(SegPool(seg)), seg, AccessWRITE);
|
||||
}
|
||||
} else {
|
||||
if (rankSet == RankSetEMPTY) {
|
||||
AVER(gcseg->summary == RefSetEMPTY);
|
||||
ShieldLower(arena, seg, AccessWRITE);
|
||||
AVER_CRITICAL(SegGCSeg(seg)->summary == RefSetEMPTY);
|
||||
ShieldLower(PoolArena(SegPool(seg)), seg, AccessWRITE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void gcSegSyncWriteBarrier(Seg seg, Arena arena)
|
||||
/* mutatorSegSyncWriteBarrier -- raise or lower write barrier on segment
|
||||
*
|
||||
* We only need to raise the write barrier if the segment contains
|
||||
* references, and its summary is strictly smaller than the summary of
|
||||
* the unprotectable data (that is, the mutator). We don't maintain
|
||||
* such a summary, assuming that the mutator can access all
|
||||
* references, so its summary is RefSetUNIV.
|
||||
*/
|
||||
|
||||
static void mutatorSegSyncWriteBarrier(Seg seg)
|
||||
{
|
||||
Arena arena = PoolArena(SegPool(seg));
|
||||
/* Can't check seg -- this function enforces invariants tested by SegCheck. */
|
||||
if (SegSummary(seg) == RefSetUNIV)
|
||||
ShieldLower(arena, seg, AccessWRITE);
|
||||
|
|
@ -1649,40 +1715,41 @@ static void gcSegSyncWriteBarrier(Seg seg, Arena arena)
|
|||
}
|
||||
|
||||
|
||||
/* gcSegSetSummary -- GCSeg method to change the summary on a segment
|
||||
*
|
||||
* In fact, we only need to raise the write barrier if the
|
||||
* segment contains references, and its summary is strictly smaller
|
||||
* than the summary of the unprotectable data (i.e. the mutator).
|
||||
* We don't maintain such a summary, assuming that the mutator can
|
||||
* access all references, so its summary is RefSetUNIV.
|
||||
*/
|
||||
/* gcSegSetSummary -- GCSeg method to change the summary on a segment */
|
||||
|
||||
static void gcSegSetSummary(Seg seg, RefSet summary)
|
||||
{
|
||||
GCSeg gcseg;
|
||||
Arena arena;
|
||||
|
||||
AVERT_CRITICAL(Seg, seg); /* .seg.method.check */
|
||||
gcseg = SegGCSeg(seg);
|
||||
AVERT_CRITICAL(GCSeg, gcseg);
|
||||
AVER_CRITICAL(&gcseg->segStruct == seg);
|
||||
|
||||
arena = PoolArena(SegPool(seg));
|
||||
gcseg->summary = summary;
|
||||
|
||||
AVER(seg->rankSet != RankSetEMPTY);
|
||||
|
||||
gcSegSyncWriteBarrier(seg, arena);
|
||||
AVER_CRITICAL(seg->rankSet != RankSetEMPTY);
|
||||
}
|
||||
|
||||
|
||||
/* mutatorSegSetSummary -- MutatorSeg method to change summary on segment
|
||||
*
|
||||
* As gcSegSetSummary, but also raise or lower the write barrier.
|
||||
*/
|
||||
|
||||
static void mutatorSegSetSummary(Seg seg, RefSet summary)
|
||||
{
|
||||
NextMethod(Seg, MutatorSeg, setSummary)(seg, summary);
|
||||
mutatorSegSyncWriteBarrier(seg);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* gcSegSetRankSummary -- GCSeg method to set both rank set and summary */
|
||||
|
||||
static void gcSegSetRankSummary(Seg seg, RankSet rankSet, RefSet summary)
|
||||
{
|
||||
GCSeg gcseg;
|
||||
Arena arena;
|
||||
|
||||
AVERT_CRITICAL(Seg, seg); /* .seg.method.check */
|
||||
AVERT_CRITICAL(RankSet, rankSet); /* .seg.method.check */
|
||||
|
|
@ -1693,15 +1760,17 @@ static void gcSegSetRankSummary(Seg seg, RankSet rankSet, RefSet summary)
|
|||
AVER_CRITICAL(&gcseg->segStruct == seg);
|
||||
|
||||
/* rankSet == RankSetEMPTY implies summary == RefSetEMPTY */
|
||||
AVER(rankSet != RankSetEMPTY || summary == RefSetEMPTY);
|
||||
|
||||
arena = PoolArena(SegPool(seg));
|
||||
AVER_CRITICAL(rankSet != RankSetEMPTY || summary == RefSetEMPTY);
|
||||
|
||||
seg->rankSet = BS_BITFIELD(Rank, rankSet);
|
||||
gcseg->summary = summary;
|
||||
}
|
||||
|
||||
static void mutatorSegSetRankSummary(Seg seg, RankSet rankSet, RefSet summary)
|
||||
{
|
||||
NextMethod(Seg, MutatorSeg, setRankSummary)(seg, rankSet, summary);
|
||||
if (rankSet != RankSetEMPTY)
|
||||
gcSegSyncWriteBarrier(seg, arena);
|
||||
mutatorSegSyncWriteBarrier(seg);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1997,8 +2066,8 @@ Bool SegClassCheck(SegClass klass)
|
|||
CHECKL(FUNCHECK(klass->walk));
|
||||
|
||||
/* Check that segment classes override sets of related methods. */
|
||||
CHECKL((klass->init == SegAbsInit)
|
||||
== (klass->instClassStruct.finish == SegAbsFinish));
|
||||
CHECKL((klass->init == segAbsInit)
|
||||
== (klass->instClassStruct.finish == segAbsFinish));
|
||||
CHECKL((klass->init == gcSegInit)
|
||||
== (klass->instClassStruct.finish == gcSegFinish));
|
||||
CHECKL((klass->merge == segTrivMerge) == (klass->split == segTrivSplit));
|
||||
|
|
@ -2021,15 +2090,16 @@ DEFINE_CLASS(Inst, SegClass, klass)
|
|||
DEFINE_CLASS(Seg, Seg, klass)
|
||||
{
|
||||
INHERIT_CLASS(&klass->instClassStruct, Seg, Inst);
|
||||
klass->instClassStruct.describe = SegAbsDescribe;
|
||||
klass->instClassStruct.finish = SegAbsFinish;
|
||||
klass->instClassStruct.describe = segAbsDescribe;
|
||||
klass->instClassStruct.finish = segAbsFinish;
|
||||
klass->size = sizeof(SegStruct);
|
||||
klass->init = SegAbsInit;
|
||||
klass->init = segAbsInit;
|
||||
klass->setSummary = segNoSetSummary;
|
||||
klass->buffer = segNoBuffer;
|
||||
klass->setBuffer = segNoSetBuffer;
|
||||
klass->unsetBuffer = segNoUnsetBuffer;
|
||||
klass->setGrey = segNoSetGrey;
|
||||
klass->flip = segTrivFlip;
|
||||
klass->setWhite = segNoSetWhite;
|
||||
klass->setRankSet = segNoSetRankSet;
|
||||
klass->setRankSummary = segNoSetRankSummary;
|
||||
|
|
@ -2083,6 +2153,22 @@ DEFINE_CLASS(Seg, GCSeg, klass)
|
|||
}
|
||||
|
||||
|
||||
/* MutatorSegClass -- collectable mutator segment class definition */
|
||||
|
||||
typedef SegClassStruct MutatorSegClassStruct;
|
||||
|
||||
DEFINE_CLASS(Seg, MutatorSeg, klass)
|
||||
{
|
||||
INHERIT_CLASS(klass, MutatorSeg, GCSeg);
|
||||
klass->setSummary = mutatorSegSetSummary;
|
||||
klass->setGrey = mutatorSegSetGrey;
|
||||
klass->flip = mutatorSegFlip;
|
||||
klass->setRankSet = mutatorSegSetRankSet;
|
||||
klass->setRankSummary = mutatorSegSetRankSummary;
|
||||
AVERT(SegClass, klass);
|
||||
}
|
||||
|
||||
|
||||
/* SegClassMixInNoSplitMerge -- Mix-in for unsupported merge
|
||||
*
|
||||
* Classes which don't support segment splitting and merging
|
||||
|
|
|
|||
|
|
@ -590,15 +590,11 @@ static Res traceFlip(Trace trace)
|
|||
/* drj 2003-02-19) */
|
||||
|
||||
/* Now that the mutator is black we must prevent it from reading */
|
||||
/* grey objects so that it can't obtain white pointers. This is */
|
||||
/* achieved by read protecting all segments containing objects */
|
||||
/* which are grey for any of the flipped traces. */
|
||||
/* grey objects so that it can't obtain white pointers. */
|
||||
for(rank = RankMIN; rank < RankLIMIT; ++rank)
|
||||
RING_FOR(node, ArenaGreyRing(arena, rank), nextNode) {
|
||||
Seg seg = SegOfGreyRing(node);
|
||||
if(TraceSetInter(SegGrey(seg), arena->flippedTraces) == TraceSetEMPTY
|
||||
&& TraceSetIsMember(SegGrey(seg), trace))
|
||||
ShieldRaise(arena, seg, AccessREAD);
|
||||
SegFlip(seg, trace);
|
||||
}
|
||||
|
||||
/* @@@@ When write barrier collection is implemented, this is where */
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -350,7 +350,10 @@ Segments
|
|||
--------
|
||||
|
||||
_`.seg.class`: AMC allocates segments of class ``AMCSegClass``, which
|
||||
is a subclass of ``GCSegClass``.
|
||||
is a subclass of ``MutatorSegClass`` (see
|
||||
design.mps.seg.over.hierarchy.mutatorseg_).
|
||||
|
||||
.. _design.mps.seg.over.hierarchy.mutatorseg: seg#over-hierarchy-mutatorseg
|
||||
|
||||
_`.seg.gen`: AMC organizes the segments it manages into generations.
|
||||
|
||||
|
|
|
|||
|
|
@ -112,9 +112,9 @@ _`.poolstruct`: The class specific pool structure is::
|
|||
}
|
||||
|
||||
_`.awlseg`: The pool defines a segment class ``AWLSegClass``, which is
|
||||
a subclass of ``GCSegClass`` (see
|
||||
design.mps.seg.over.hierarchy.gcseg_). All segments allocated by the
|
||||
pool are instances of this class, and are of type ``AWLSeg``, for
|
||||
a subclass of ``MutatorSegClass`` (see
|
||||
design.mps.seg.over.hierarchy.mutatorseg_). All segments allocated by
|
||||
the pool are instances of this class, and are of type ``AWLSeg``, for
|
||||
which the structure is::
|
||||
|
||||
struct AWLSegStruct {
|
||||
|
|
@ -132,7 +132,7 @@ which the structure is::
|
|||
Sig sig; /* <code/misc.h#sig> */
|
||||
}
|
||||
|
||||
.. _design.mps.seg.over.hierarchy.gcseg: seg#over-hierarchy-gcseg
|
||||
.. _design.mps.seg.over.hierarchy.mutatorseg: seg#over-hierarchy-mutatorseg
|
||||
|
||||
_`.awlseg.bt`: The ``mark``, ``alloc``, and ``scanned`` fields are
|
||||
bit-tables (see design.mps.bt_). Each bit in the table corresponds to
|
||||
|
|
|
|||
|
|
@ -121,8 +121,12 @@ _`.poolstruct`: The class specific pool structure is::
|
|||
Sig sig; /* <code/misc.h#sig> */
|
||||
} LOStruct;
|
||||
|
||||
_`.loseg`: Every segment is an instance of segment class ``LOSegClass``, a
|
||||
subclass of ``GCSegClass``, and is an object of type ``LOSegStruct``.
|
||||
_`.loseg`: Every segment is an instance of segment class
|
||||
``LOSegClass``, a subclass of ``MutatorSegClass`` (see
|
||||
design.mps.seg.over.hierarchy.mutatorseg_), and is an object of type
|
||||
``LOSegStruct``.
|
||||
|
||||
.. _design.mps.seg.over.hierarchy.mutatorseg: seg#over-hierarchy-mutatorseg
|
||||
|
||||
_`.loseg.purpose`: The purpose of the ``LOSeg`` structure is to
|
||||
associate the bit tables used for recording allocation and mark
|
||||
|
|
|
|||
|
|
@ -336,7 +336,7 @@ the latter will be used to store the link parts of guardians (see
|
|||
one of each class, by the function ``MRGSegPairCreate()``. Each
|
||||
segment contains a link to its pair.
|
||||
|
||||
_`.mrgseg.ref`: ``MRGRefSegClass`` is a subclass of ``GCSegClass``.
|
||||
_`.mrgseg.ref`: ``MRGRefSegClass`` is a subclass of ``MutatorSegClass``.
|
||||
Instances are of type ``MRGRefSeg``, and contain:
|
||||
|
||||
- _`.mrgseg.ref.mrgring`: a field for the ring of ref part segments in
|
||||
|
|
|
|||
|
|
@ -51,9 +51,15 @@ subclass with additional properties.
|
|||
|
||||
.. _design.mps.protocol: protocol
|
||||
|
||||
_`.over.hierarchy.gcseg`: The segment module provides ``GCSeg`` - a
|
||||
subclass of ``Seg`` which has full support for GC including buffering
|
||||
and the ability to be linked onto the grey ring.
|
||||
_`.over.hierarchy.gcseg`: ``GCSeg`` is a subclass of ``Seg`` which
|
||||
implements garbage collection, including buffering and the ability to
|
||||
be linked onto the grey ring. It does not implement hardware barriers,
|
||||
and so can only be used with software barriers, for example internally
|
||||
in the MPS.
|
||||
|
||||
_`.over.hierarchy.mutatorseg`: ``MutatorSeg`` is a subclass of
|
||||
``GCSeg`` implementing hardware barriers. It is suitable for handing
|
||||
out to the mutator.
|
||||
|
||||
|
||||
Data Structure
|
||||
|
|
@ -345,6 +351,12 @@ in the walk. Segment classes need not provide this method. This
|
|||
method is called by the genetic function ``SegWalk()``, which is
|
||||
called by the heap walker ``mps_arena_formatted_objects_walk()``.
|
||||
|
||||
``typedef void (*SegFlipMethod)(Seg seg, Trace trace)``
|
||||
|
||||
_`.method.flip`: Raise the read barrier, if necessary, for a trace
|
||||
that's about to flip and for which the segment is grey and potentially
|
||||
contains references.
|
||||
|
||||
|
||||
Splitting and merging
|
||||
.....................
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue