diff --git a/mps/src/amcss.c b/mps/src/amcss.c index 9282a2bae0f..cabcfed415c 100644 --- a/mps/src/amcss.c +++ b/mps/src/amcss.c @@ -1,6 +1,6 @@ /* impl.c.amcss: POOL CLASS AMC STRESS TEST * - * $HopeName: MMsrc!amcss.c(trunk.11) $ + * $HopeName: MMsrc!amcss.c(trunk.12) $ * Copyright (C) 1996 Harlequin Group, all rights reserved */ @@ -91,8 +91,9 @@ static void *test(void *arg, size_t s) collections = c; printf("\nCollection %u, %lu objects.\n", c, (unsigned long)i); - for(r=0; rpool); - /* .seg.check-little: all other fields can't be checked */ - return TRUE; -} /* preferences... */ @@ -548,14 +540,7 @@ static Res ChunkSegAlloc(Seg *segReturn, SegPref pref, Size pages, Pool pool, found: /* Initialize the generic segment structure. */ seg = &chunk->pageTable[base].the.head; - seg->pool = pool; - seg->p = NULL; - seg->rank = RankEXACT; /* exact by default */ - seg->condemned = TraceIdNONE; - - seg->pm = AccessSetEMPTY; /* see impl.c.shield */ - seg->sm = AccessSetEMPTY; - seg->depth = 0; + SegInit(seg, pool); /* Allocate the first page, and, if there is more than one page, * allocate the rest of the pages and store the multi-page information @@ -667,6 +652,8 @@ void SegFree(Space space, Seg seg) limit = SegLimit(space, seg); + SegFinish(seg); + /* Remember the base address of the segment so it can be */ /* unmapped .free.unmap */ base = PageBase(chunk, pi); diff --git a/mps/src/arenavm.c b/mps/src/arenavm.c index e8f4d3770e2..bb2488eb188 100644 --- a/mps/src/arenavm.c +++ b/mps/src/arenavm.c @@ -1,7 +1,7 @@ /* impl.c.arenavm: VIRTUAL MEMORY BASED ARENA IMPLEMENTATION * - * $HopeName: MMsrc!arenavm.c(trunk.13) $ - * Copyright (C) 1996,1997 Harlequin Group, all rights reserved. + * $HopeName: MMsrc!arenavm.c(trunk.14) $ + * Copyright (C) 1997 The Harlequin Group Limited. All rights reserved. * * This is the implementation of the Segment abstraction from the VM * abstraction. Use of this arena implies use of a VM. @@ -14,7 +14,7 @@ #include "mpm.h" -SRCID(arenavm, "$HopeName: MMsrc!arenavm.c(trunk.13) $"); +SRCID(arenavm, "$HopeName: MMsrc!arenavm.c(trunk.14) $"); /* Space Arena Projection @@ -262,18 +262,6 @@ Bool ArenaCheck(Arena arena) } -/* SegCheck -- check the consistency of a segment structure */ - -Bool SegCheck(Seg seg) -{ - CHECKU(Pool, seg->pool); - /* .seg.check-little: all other fields can't be checked */ - return TRUE; -} - - -/* preferences... */ - Bool SegPrefCheck(SegPref pref) { CHECKS(SegPref, pref); @@ -311,6 +299,7 @@ Res SegPrefExpress (SegPref sp, SegPrefKind kind, void *p) } } + /* SegAlloc -- allocate a segment from the arena */ Res SegAlloc(Seg *segReturn, SegPref pref, Space space, Size size, Pool pool) @@ -369,17 +358,7 @@ found: /* Initialize the generic segment structure. */ seg = &arena->pageTable[base].the.head; - seg->pool = pool; - seg->p = NULL; - seg->rank = RankEXACT; /* exact by default */ - seg->condemned = TraceIdNONE; - seg->grey = TraceSetEMPTY; - seg->buffer = NULL; - RingInit(&seg->poolRing); - - seg->pm = AccessSetEMPTY; /* see impl.c.shield */ - seg->sm = AccessSetEMPTY; - seg->depth = 0; + SegInit(seg, pool); /* Allocate the first page, and, if there is more than one page, * allocate the rest of the pages and store the multi-page information @@ -428,6 +407,8 @@ void SegFree(Space space, Seg seg) pi = page - arena->pageTable; AVER(pi <= arena->pages); + SegFinish(seg); + /* Remember the base address of the segment so it can be */ /* unmapped .free.unmap */ base = PageBase(arena, pi); diff --git a/mps/src/buffer.c b/mps/src/buffer.c index f4641e597a2..4369d5c2011 100644 --- a/mps/src/buffer.c +++ b/mps/src/buffer.c @@ -1,7 +1,7 @@ /* impl.c.buffer: ALLOCATION BUFFER IMPLEMENTATION * - * $HopeName: MMsrc!buffer.c(trunk.20) $ - * Copyright (C) 1996 Harlequin Group, all rights reserved + * $HopeName: MMsrc!buffer.c(MMdevel_action2.4) $ + * Copyright (C) 1997 The Harlequin Group Limited. All rights reserved. * * This is (part of) the implementation of allocation buffers. * @@ -29,108 +29,7 @@ #include "mpm.h" -SRCID(buffer, "$HopeName: MMsrc!buffer.c(trunk.20) $"); - - -/* BufferCreate -- create an allocation buffer in a pool - * - * design.mps.buffer.method.create - */ - -Res BufferCreate(Buffer *bufferReturn, Pool pool, Rank rank) -{ - Res res; - Buffer buffer; - Space space; - void *p; - - AVER(bufferReturn != NULL); - AVERT(Pool, pool); - /* The PoolClass should support buffer protocols */ - AVER((pool->class->attr & AttrBUF)); /* .trans.mod */ - AVER(RankCheck(rank)); - - space = PoolSpace(pool); - - /* Allocate the buffer structure. */ - res = SpaceAlloc(&p, space, sizeof(BufferStruct)); - if(res != ResOK) return res; - buffer = p; - - /* Initialize the buffer. See impl.h.mpmst for a definition of the - * structure */ - /* sig and serial comes later .init.sig-serial */ - buffer->space = space; - buffer->pool = pool; - buffer->seg = NULL; - buffer->rank = rank; - buffer->base = (Addr)0; - buffer->apStruct.init = (Addr)0; - buffer->apStruct.alloc = (Addr)0; - buffer->apStruct.limit = (Addr)0; - buffer->alignment = pool->alignment; /* .trans.mod */ - RingInit(&buffer->poolRing); - buffer->shieldMode = AccessSetEMPTY; - buffer->p = NULL; - buffer->i = 0; - - /* Dispatch to the pool class method to perform any extra */ - /* initialization of the buffer. */ - res = (*pool->class->bufferInit)(pool, buffer); - if(res != ResOK) { - SpaceFree(space, (Addr)buffer, sizeof(BufferStruct)); - return res; - } - - /* .init.sig-serial: Now that it's initialized, sign the buffer, - * give it a serial number, and check it. */ - buffer->sig = BufferSig; - buffer->serial = pool->bufferSerial; /* .trans.mod */ - ++pool->bufferSerial; - AVERT(Buffer, buffer); - - /* Attach the initialized buffer to the pool. */ - RingAppend(&pool->bufferRing, &buffer->poolRing); - - *bufferReturn = buffer; - return ResOK; -} - - -/* BufferDestroy -- destroy an allocation buffer - * - * design.mps.buffer.method.destroy - */ - -void BufferDestroy(Buffer buffer) -{ - Space space; - Pool pool; - - AVERT(Buffer, buffer); - - /* Make a copy of the space before the buffer gets finished. */ - space = buffer->space; - pool = buffer->pool; - - /* The PoolClass should support buffer protocols */ - AVER((pool->class->attr & AttrBUF)); /* .trans.mod */ - AVER(BufferIsReady(buffer)); - - /* Detach the buffer from its owning pool. */ - RingRemove(&buffer->poolRing); - - /* Dispatch to the pool class method to finish the buffer. */ - (*pool->class->bufferFinish)(pool, buffer); - - /* Unsign the finished buffer. */ - buffer->sig = SigInvalid; - - /* Finish off the generic buffer fields and deallocate the */ - /* buffer structure. */ - RingFinish(&buffer->poolRing); - SpaceFree(space, (Addr)buffer, sizeof(BufferStruct)); -} +SRCID(buffer, "$HopeName: MMsrc!buffer.c(MMdevel_action2.4) $"); /* BufferCheck @@ -145,29 +44,159 @@ Bool BufferCheck(Buffer buffer) CHECKL(buffer->serial < buffer->pool->bufferSerial); /* .trans.mod */ CHECKU(Space, buffer->space); CHECKU(Pool, buffer->pool); - /* seg and rank checked in anomalous order */ - CHECKL(RankCheck(buffer->rank)); /* design.mps.check.type.no-sig */ + CHECKL(RankSetCheck(buffer->rankSet)); if(buffer->seg != NULL) { - CHECKL(SegCheck(buffer->seg)); /* design.mps.check.type.no-sig */ + CHECKL(SegCheck(buffer->seg)); /* design.mps.check.type.no-sig */ CHECKL(buffer->seg->buffer == buffer); - CHECKL(buffer->rank == buffer->seg->rank); + CHECKL(buffer->rankSet == buffer->seg->rankSet); } CHECKL(buffer->base <= buffer->apStruct.init); CHECKL(buffer->apStruct.init <= buffer->apStruct.alloc); CHECKL(buffer->apStruct.alloc <= buffer->apStruct.limit || - buffer->apStruct.limit == 0); + buffer->apStruct.limit == 0); CHECKL(buffer->alignment == buffer->pool->alignment); CHECKL(AlignCheck(buffer->alignment)); CHECKL(AddrIsAligned(buffer->base, buffer->alignment)); CHECKL(AddrIsAligned(buffer->apStruct.init, buffer->alignment)); CHECKL(AddrIsAligned(buffer->apStruct.alloc, buffer->alignment)); CHECKL(AddrIsAligned(buffer->apStruct.limit, buffer->alignment)); - CHECKL(RingCheck(&buffer->poolRing)); /* design.mps.check.type.no-sig */ + CHECKL(RingCheck(&buffer->poolRing)); /* design.mps.check.type.no-sig */ /* buffer->p, and buffer->i are arbitrary and cannot be checked */ return TRUE; } +/* BufferCreate -- create an allocation buffer + * + * design.mps.buffer.method.create + */ + +Res BufferCreate(Buffer *bufferReturn, Pool pool, Rank rank) +{ + Res res; + Buffer buffer; + Space space; + void *p; + + AVER(bufferReturn != NULL); + AVERT(Pool, pool); + AVER(RankCheck(rank)); + + space = PoolSpace(pool); + + /* Allocate the buffer structure. */ + res = SpaceAlloc(&p, space, sizeof(BufferStruct)); + if(res != ResOK) goto failAlloc; + buffer = p; + + res = BufferInit(buffer, pool, rank); + if(res != ResOK) goto failInit; + + *bufferReturn = buffer; + return ResOK; + +failInit: + SpaceFree(space, (Addr)buffer, sizeof(BufferStruct)); +failAlloc: + return res; +} + + +/* BufferInit -- initialize an allocation buffer */ + +Res BufferInit(Buffer buffer, Pool pool, Rank rank) +{ + Res res; + + AVER(buffer != NULL); + AVERT(Pool, pool); + /* The PoolClass should support buffer protocols */ + AVER((pool->class->attr & AttrBUF)); /* .trans.mod */ + AVER(RankCheck(rank)); + + /* Initialize the buffer. See impl.h.mpmst for a definition of the */ + /* structure. sig and serial comes later .init.sig-serial */ + buffer->space = PoolSpace(pool); + buffer->pool = pool; + buffer->seg = NULL; + buffer->rankSet = RankSetSingle(rank); + buffer->base = (Addr)0; + buffer->apStruct.init = (Addr)0; + buffer->apStruct.alloc = (Addr)0; + buffer->apStruct.limit = (Addr)0; + buffer->alignment = pool->alignment; /* .trans.mod */ + RingInit(&buffer->poolRing); + buffer->p = NULL; + buffer->i = 0; + + /* Dispatch to the pool class method to perform any extra */ + /* initialization of the buffer. */ + res = (*pool->class->bufferInit)(pool, buffer); + if(res != ResOK) return res; + + /* .init.sig-serial: Now that it's initialized, sign the buffer, */ + /* give it a serial number, and check it. */ + buffer->sig = BufferSig; + buffer->serial = pool->bufferSerial; /* .trans.mod */ + ++pool->bufferSerial; + AVERT(Buffer, buffer); + + /* Attach the initialized buffer to the pool. */ + RingAppend(&pool->bufferRing, &buffer->poolRing); + + return ResOK; +} + + +/* BufferDestroy -- destroy an allocation buffer + * + * design.mps.buffer.method.destroy + */ + +void BufferDestroy(Buffer buffer) +{ + Space space; + + AVERT(Buffer, buffer); + + space = buffer->space; + BufferFinish(buffer); + SpaceFree(space, (Addr)buffer, sizeof(BufferStruct)); +} + + +/* BufferFinish -- finish an allocation buffer */ + +void BufferFinish(Buffer buffer) +{ + Pool pool; + + AVERT(Buffer, buffer); + + pool = buffer->pool; + + /* The PoolClass should support buffer protocols */ + AVER((pool->class->attr & AttrBUF)); /* .trans.mod */ + AVER(BufferIsReady(buffer)); + + /* Detach the buffer from its owning pool. */ + RingRemove(&buffer->poolRing); + + /* Dispatch to the pool class method to finish the buffer. */ + (*pool->class->bufferFinish)(pool, buffer); + + /* Pool should make sure buffer is not attached. */ + /* @@@@ Are there other conditions? */ + AVER(BufferIsReset(buffer)); + + /* Unsign the finished buffer. */ + buffer->sig = SigInvalid; + + /* Finish off the generic buffer fields. */ + RingFinish(&buffer->poolRing); +} + + /* BufferSet/Reset -- set/reset a buffer * * Set sets the buffer base, init, alloc, and limit fields so that @@ -182,9 +211,13 @@ Bool BufferCheck(Buffer buffer) void BufferSet(Buffer buffer, Seg seg, Addr base, Addr init, Addr limit) { AVERT(Buffer, buffer); - AVER(SegCheck(seg)); AVER(BufferIsReady(buffer)); - /* No check for base, init, limit */ + AVER(SegCheck(seg)); + AVER(seg->buffer == NULL); + AVER(SegBase(buffer->space, seg) <= base); + AVER(base <= init); + AVER(limit == 0 || init <= limit); + AVER(limit == 0 || limit <= SegLimit(buffer->space, seg)); buffer->seg = seg; seg->buffer = buffer; @@ -198,6 +231,7 @@ void BufferReset(Buffer buffer) { AVERT(Buffer, buffer); AVER(BufferIsReady(buffer)); + AVER(buffer->seg->buffer == buffer); buffer->seg->buffer = NULL; buffer->seg = NULL; @@ -419,12 +453,11 @@ Res BufferDescribe(Buffer buffer, mps_lib_FILE *stream) " Space $P\n", (WriteFP)buffer->space, " Pool $P\n", (WriteFP)buffer->pool, " Seg $P\n", (WriteFP)buffer->seg, - " rank $U\n", (WriteFU)buffer->rank, + " rankSet $U\n", (WriteFU)buffer->rankSet, " base $A init $A alloc $A limit $A\n", buffer->base, buffer->apStruct.init, buffer->apStruct.alloc, buffer->apStruct.limit, " alignment $W\n", (WriteFW)buffer->alignment, - " shieldMode $B\n", (WriteFB)buffer->shieldMode, " p $P i $U\n", buffer->p, (WriteFU)buffer->i, "} Buffer $P ($U)\n", (WriteFP)buffer, (WriteFU)buffer->serial, NULL); diff --git a/mps/src/misc.h b/mps/src/misc.h index a399e7334f0..113aaba051d 100644 --- a/mps/src/misc.h +++ b/mps/src/misc.h @@ -1,6 +1,6 @@ /* impl.h.misc: MISCELLANEOUS DEFINITIONS * - * $HopeName: MMsrc!misc.h(trunk.9) $ + * $HopeName: MMsrc!misc.h(MMdevel_action2.2) $ * Copyright (C) 1994,1995,1996 Harlequin Group, all rights reserved * * Small general things which are useful for C but aren't part of the @@ -126,7 +126,7 @@ typedef const struct SrcIdStruct { #define BS_DEL(ty, s, i) BS_DIFF(s, BS_SINGLE(ty, i)) #define BS_SUPER(s1, s2) (BS_INTER(s1, s2) == s2) #define BS_SUB(s1, s2) BS_SUPER(s2, s1) -#define BS_IS_SINGLE(s) (((s) & (s)-1) == 0) +#define BS_IS_SINGLE(s) (((s) & ((s)-1)) == 0) #endif /* misc_h */ diff --git a/mps/src/mpm.h b/mps/src/mpm.h index 6597da0e369..31b44f7f383 100644 --- a/mps/src/mpm.h +++ b/mps/src/mpm.h @@ -1,7 +1,7 @@ /* impl.h.mpm: MEMORY POOL MANAGER DEFINITIONS * - * $HopeName: MMsrc!mpm.h(trunk.22) $ - * Copyright (C) 1996,1997 Harlequin Group, all rights reserved. + * $HopeName: MMsrc!mpm.h(trunk.23) $ + * Copyright (C) 1997 The Harlequin Group Limited. All rights reserved. */ #ifndef mpm_h @@ -255,16 +255,13 @@ extern Res PoolCreateV(Pool *poolReturn, Space space, extern void PoolDestroy(Pool pool); extern Res PoolAlloc(Addr *pReturn, Pool pool, Size size); extern void PoolFree(Pool pool, Addr old, Size size); -extern Res PoolCondemn(RefSet *condemnedReturn, Pool pool, - Space space, TraceId ti); -extern void PoolGrey(Pool pool, Space space, TraceId ti); -extern Res PoolScan(ScanState ss, Pool pool, Bool *finishedReturn); +extern Res PoolCondemn(Pool pool, Trace trace, Seg seg); +extern void PoolGrey(Pool pool, Trace trace, Seg seg); +extern Res PoolScan(ScanState ss, Pool pool, Seg seg); extern Res (PoolFix)(Pool pool, ScanState ss, Seg seg, Addr *refIO); #define PoolFix(pool, ss, seg, refIO) \ ((*(pool)->class->fix)(pool, ss, seg, refIO)) - -extern void PoolReclaim(Pool pool, Space space, TraceId ti); -extern void PoolAccess(Pool pool, Seg seg, AccessSet mode); +extern void PoolReclaim(Pool pool, Trace trace, Seg seg); extern void PoolTrivFinish(Pool pool); extern Res PoolNoAlloc(Addr *pReturn, Pool pool, Size size); @@ -281,47 +278,50 @@ extern void PoolNoBufferExpose(Pool pool, Buffer buffer); extern void PoolNoBufferCover(Pool pool, Buffer buffer); extern Res PoolNoDescribe(Pool pool, mps_lib_FILE *stream); extern Res PoolTrivDescribe(Pool pool, mps_lib_FILE *stream); -extern Res PoolNoCondemn(RefSet *condemnedReturn, Pool pool, Space space, TraceId ti); -extern void PoolNoGrey(Pool pool, Space space, TraceId ti); -extern Res PoolNoScan(ScanState ss, Pool pool, Bool *finishedReturn); +extern Res PoolNoCondemn(Pool pool, Trace trace, Seg seg); +extern void PoolNoGrey(Pool pool, Trace trace, Seg seg); +extern void PoolTrivGrey(Pool pool, Trace trace, Seg seg); +extern Res PoolNoScan(ScanState ss, Pool pool, Seg seg); extern Res PoolNoFix(Pool pool, ScanState ss, Seg seg, Ref *refIO); -extern void PoolNoReclaim(Pool pool, Space space, TraceId ti); -extern void PoolNoAccess(Pool pool, Seg seg, AccessSet mode); +extern void PoolNoReclaim(Pool pool, Trace trace, Seg seg); /* Trace Interface -- see impl.c.trace */ +#define TraceSetSingle(ti) BS_SINGLE(TraceSet, ti) #define TraceSetIsMember(ts, ti)BS_IS_MEMBER(ts, ti) #define TraceSetAdd(ts, ti) BS_ADD(TraceSet, ts, ti) #define TraceSetDel(ts, ti) BS_DEL(TraceSet, ts, ti) #define TraceSetUnion(ts1, ts2) BS_UNION(ts1, ts2) +#define TraceSetInter(ts1, ts2) BS_INTER(ts1, ts2) +#define TraceSetDiff(ts1, ts2) BS_DIFF(ts1, ts2) +#define TraceSetSuper(ts1, ts2) BS_SUPER(ts1, ts2) extern TraceSet (TraceSetAdd)(TraceSet ts, TraceId id); extern TraceSet (TraceSetDel)(TraceSet ts, TraceId id); extern TraceSet (TraceSetUnion)(TraceSet ts1, TraceSet ts2); extern Bool (TraceSetIsMember)(TraceSet ts, TraceId id); -extern Res TraceCreate(TraceId *tiReturn, Space space); -extern void TraceDestroy(Space space, TraceId ti); - extern Bool ScanStateCheck(ScanState ss); extern Bool TraceIdCheck(TraceId id); extern Bool TraceSetCheck(TraceSet ts); +extern Bool TraceCheck(Trace trace); -extern Res TraceFlip(Space space, TraceId ti, RefSet condemned); -extern Size TracePoll(Space space, TraceId ti); - -extern Res TraceRunAtomic(Space space, TraceId ti); -extern Res TraceRun(Space space, TraceId ti, Bool *finishedReturn); +extern Res TraceCreate(Trace *traceReturn, Space space); +extern void TraceDestroy(Trace trace); +extern Res TraceStart(Trace trace, Pool pool); +extern Res TracePoll(Trace trace); +extern void TraceAccess(Space space, Seg seg, AccessSet mode); extern Res TraceFix(ScanState ss, Ref *refIO); +extern void TraceSegGreyen(Space space, Seg seg, TraceSet ts); /* Equivalent to impl.h.mps MPS_SCAN_BEGIN */ #define TRACE_SCAN_BEGIN(ss) \ BEGIN \ Shift SCANzoneShift = (ss)->zoneShift; \ - RefSet SCANcondemned = (ss)->condemned; \ + RefSet SCANwhite = (ss)->white; \ RefSet SCANsummary = (ss)->summary; \ Word SCANt; \ { @@ -331,7 +331,7 @@ extern Res TraceFix(ScanState ss, Ref *refIO); #define TRACE_FIX1(ss, ref) \ (SCANt = (Word)1<<((Word)(ref)>>SCANzoneShift&(MPS_WORD_WIDTH-1)), \ SCANsummary |= SCANt, \ - SCANcondemned & SCANt) + SCANwhite & SCANt) /* Equivalent to impl.h.mps MPS_FIX2 */ @@ -355,6 +355,14 @@ extern Res TraceScanArea(ScanState ss, Addr *base, Addr *limit); extern Res TraceScanAreaTagged(ScanState ss, Addr *base, Addr *limit); +/* Action Interface -- see design.mps.action */ + +extern Bool ActionCheck(Action action); +extern void ActionInit(Action action, Pool pool); +extern void ActionFinish(Action action); +extern void ActionPoll(Space space); + + /* Space Interface -- see impl.c.space */ extern Res SpaceCreate(Space *spaceReturn, Addr base, Size size); @@ -373,7 +381,8 @@ extern void SpaceFree(Space space, Addr base, Size size); #define SpaceTraceRing(space) (&(space)->traceRing) #define SpaceThreadRing(space) (&(space)->threadRing) #define SpaceEpoch(space) ((space)->epoch) /* .epoch.ts */ - +#define SpaceTrace(space, ti) (&(space)->trace[ti]) +#define SpaceZoneShift(space) ((space)->zoneShift) /* Arena Interface -- see impl.c.arena* */ @@ -401,6 +410,8 @@ extern Bool SegOfAddr(Seg *segReturn, Space space, Addr addr); extern Seg SegFirst(Space space); extern Seg SegNext(Space space, Seg seg); extern Bool SegCheck(Seg seg); +extern void SegInit(Seg seg, Pool pool); +extern void SegFinish(Seg seg); /* Buffer Interface -- see impl.c.buffer */ @@ -413,7 +424,7 @@ extern Res BufferReserve(Addr *pReturn, Buffer buffer, Size size); extern Res BufferFill(Addr *pReturn, Buffer buffer, Size size); extern Bool BufferCommit(Buffer buffer, Addr p, Size size); extern Bool BufferTrip(Buffer buffer, Addr p, Size size); -extern void BufferInit(Buffer buffer, Pool pool, Rank rank); +extern Res BufferInit(Buffer buffer, Pool pool, Rank rank); extern void BufferFinish(Buffer buffer); extern void BufferSet(Buffer buffer, Seg seg, Addr base, Addr init, Addr limit); extern void BufferReset(Buffer buffer); @@ -458,6 +469,11 @@ extern Res FormatDescribe(Format format, mps_lib_FILE *stream); /* Reference Interface -- see impl.c.ref */ extern Bool RankCheck(Rank rank); +extern Bool RankSetCheck(RankSet rankSet); + +#define RankSetIsMember(rs, r) BS_IS_MEMBER(rs, r) +#define RankSetSingle(r) BS_SINGLE(RankSet, r) +#define RankSetIsSingle(r) BS_IS_SINGLE(r) #define RefSetZone(space, addr) \ (((Word)(addr) >> space->zoneShift) & (MPS_WORD_WIDTH - 1)) @@ -522,7 +538,7 @@ extern Bool RootCheck(Root root); extern Res RootDescribe(Root root, mps_lib_FILE *stream); extern Bool RootIsAtomic(Root root); extern Rank RootRank(Root root); -extern void RootGrey(Root root, TraceId ti); +extern void RootGrey(Root root, Trace trace); extern Res RootScan(ScanState ss, Root root); extern Space RootSpace(Root root); diff --git a/mps/src/mpmst.h b/mps/src/mpmst.h index 4640b94d4a1..bd36befb641 100644 --- a/mps/src/mpmst.h +++ b/mps/src/mpmst.h @@ -1,7 +1,7 @@ /* impl.h.mpmst: MEMORY POOL MANAGER DATA STRUCTURES * - * $HopeName: MMsrc!mpmst.h(trunk.19) $ - * Copyright (C) 1996,1997 Harlequin Group, all rights reserved. + * $HopeName: MMsrc!mpmst.h(MMdevel_action2.11) $ + * Copyright (C) 1997 The Harlequin Group Limited. All rights reserved. * * .readership: MM developers. * @@ -94,11 +94,10 @@ typedef struct PoolClassStruct { PoolBufferExposeMethod bufferExpose; /* remove protection */ PoolBufferCoverMethod bufferCover; /* reinstate protection */ PoolCondemnMethod condemn; /* condemn (some or all) objects */ - PoolGreyMethod grey; /* grey uncondemned objects */ + PoolGreyMethod grey; /* grey non-white objects */ PoolScanMethod scan; /* find references during tracing */ PoolFixMethod fix; /* referent reachable during tracing */ PoolReclaimMethod reclaim; /* reclaim dead objects after tracing */ - PoolAccessMethod access; /* handle an access to shielded memory */ PoolDescribeMethod describe; /* describe the contents of the pool */ Sig endSig; /* .class.end-sig */ } PoolClassStruct; @@ -125,6 +124,8 @@ typedef struct PoolStruct { /* generic structure */ RingStruct bufferRing; /* allocation buffers are attached to pool */ Serial bufferSerial; /* serial of next buffer */ RingStruct segRing; /* segs are attached to pool */ + RingStruct actionRing; /* actions are attached to pool */ + Serial actionSerial; /* serial of next action */ Align alignment; /* alignment for units */ } PoolStruct; @@ -262,26 +263,20 @@ typedef struct VMStruct { /* SegStruct -- segment structure * * .seg: Segments are the basic units of memory allocation from - * the arena, and also the units of scanning, shielding, and colour - * for the MPM (pool classes may subdivide segments and be able to - * maintain colour on a finer grain (down to the object level for example)). - * - * .seg.pm: The pm field is used by both the shield (impl.c.shield) - * and the ANSI fake protection (impl.c.protan). - * - * .seg.pool: This field must be first. See - * design.mps.arena.vm.assume.pointer-conversion for why. + * the arena. See design.mps.seg. */ typedef struct SegStruct { /* segment structure */ - Pool pool; /* MUST BE FIRST, see .seg.pool */ + Pool pool; /* MUST BE FIRST (design.mps.seg.field.pool) */ Bool single; /* single page segment */ - Rank rank; /* rank of all references in this seg */ + RankSet rankSet; /* ranks of references in this seg */ AccessSet pm, sm; /* protection and shield modes */ Size depth; /* see impl.c.shield.def.depth */ void *p; /* pointer for use of owning pool */ - TraceId condemned; /* seg condemned? for which trace? */ + TraceSet black; /* traces for which seg is black */ TraceSet grey; /* traces for which seg is grey */ + TraceSet white; /* traces for which seg is white */ + RefSet summary; /* summary of references out of seg */ Buffer buffer; /* non-NULL if seg is buffered */ RingStruct poolRing; /* link in list of segs in pool */ } SegStruct; @@ -386,18 +381,13 @@ typedef struct BufferStruct { Space space; /* owning space */ Pool pool; /* owning pool */ Seg seg; /* segment being buffered */ - Rank rank; /* rank of references being created */ + Rank rankSet; /* ranks of references being created */ Addr base; /* base address of allocation buffer */ APStruct apStruct; /* the allocation point */ Align alignment; /* allocation alignment */ RingStruct poolRing; /* buffers are attached to pools */ - AccessSet shieldMode; /* shielding for allocated memory */ -#if 0 - Bool exposed; /* is buffer memory exposed? */ - TraceSet grey; /* colour for allocated memory */ -#endif - void *p; - int i; /* (p and i) closure variables (for pool) */ + void *p; /* closure variable for pool */ + int i; /* closure variable for pool */ } BufferStruct; @@ -511,7 +501,8 @@ typedef struct RootStruct { Space space; /* owning space */ RingStruct spaceRing; /* attachment to space */ Rank rank; /* rank of references in this root */ - TraceSet grey; /* marked but not scanned for per trace */ + TraceSet grey; /* traces for which root is grey */ + RefSet summary; /* summary of references in root */ RootVar var; /* union discriminator */ union RootUnion { struct { @@ -537,7 +528,7 @@ typedef struct RootStruct { } RootStruct; -/* ScanState and TraceStruct +/* ScanState * * .ss: See impl.c.trace. * @@ -545,16 +536,13 @@ typedef struct RootStruct { * external scan state structure (mps_ss_s) thus: * ss->fix mps_ss->fix * ss->zoneShift mps_ss->w0 - * ss->condemned mps_ss->w1 + * ss->white mps_ss->w1 * ss->summary mps_ss->w2 * See impl.h.mps.ss and impl.c.mpsi.check.ss. This is why the * Sig field is in the middle of this structure. * * .ss.zone: The zoneShift field is therefore declared as Word * rather than Shift. - * - * The weakSplat field forms part of the design for weakness. - * See design.mps.weakness. */ #define ScanStateSig ((Sig)0x5195CA95) @@ -562,21 +550,45 @@ typedef struct RootStruct { typedef struct ScanStateStruct { Res (*fix)(ScanState, Addr *);/* fix function */ Word zoneShift; /* copy of space->zoneShift. See .ss.zone */ - RefSet condemned; /* condemned set, for inline fix test */ + RefSet white; /* white set, for inline fix test */ RefSet summary; /* accumulated summary of scanned references */ Sig sig; /* design.mps.sig */ Space space; /* owning space */ - TraceId traceId; /* trace ID of scan */ + TraceSet traces; /* traces to scan for */ Rank rank; /* reference rank of scanning */ - Addr weakSplat; /* value of weak refs to unforwarded objects */ Bool wasMarked; /* design.mps.fix.protocol.was-ready */ } ScanStateStruct; + +/* TraceStruct -- tracer state structure */ + +#define TraceSig ((Sig)0x51924ACE) + typedef struct TraceStruct { - RefSet condemned; /* summary of comdemnded set */ + Sig sig; /* design.mps.sig */ + TraceId ti; /* index into TraceSets */ + Space space; /* owning space */ + RefSet white; /* superset of refs in white set */ + TraceState state; /* current state of trace */ + Size interval; /* polling interval */ } TraceStruct; +/* ActionStruct -- action structure + * + * See design.mps.action. + */ + +#define ActionSig ((Sig)0x519AC209) + +typedef struct ActionStruct { + Sig sig; /* design.mps.sig */ + Serial serial; /* from pool->actionSerial */ + Pool pool; /* owning pool */ + RingStruct poolRing; /* link in list of actions in pool */ +} ActionStruct; + + /* SpaceStruct -- the space structure * * See impl.c.space. @@ -599,6 +611,7 @@ typedef struct SpaceStruct { LockStruct lockStruct; /* space's lock */ Size pollThreshold; /* see impl.c.mpsi.poll and SpacePoll */ Bool insidePoll; /* prevent recursive polling, see SpacePoll */ + Size actionInterval; /* see SpacePoll */ /* arena fields (impl.c.arena*) */ ArenaStruct arenaStruct; /* the arena */ @@ -629,6 +642,7 @@ typedef struct SpaceStruct { /* trace fields (impl.c.trace) */ TraceSet busyTraces; /* set of running traces */ + TraceSet flippedTraces; /* set of running and flipped traces */ TraceStruct trace[TRACE_MAX]; /* trace structures. See design.mps.trace.intance.limit */ diff --git a/mps/src/mpmtypes.h b/mps/src/mpmtypes.h index eb1e57da594..4a3be46d7ff 100644 --- a/mps/src/mpmtypes.h +++ b/mps/src/mpmtypes.h @@ -1,7 +1,7 @@ /* impl.h.mpmtypes: MEMORY POOL MANAGER TYPES * - * $HopeName: MMsrc!mpmtypes.h(trunk.18) $ - * Copyright (C) 1996,1997 Harlequin Group, all rights reserved. + * $HopeName: MMsrc!mpmtypes.h(MMdevel_action2.9) $ + * Copyright (C) 1997 The Harlequin Group Limited. All rights reserved. * * .readership: MM developers. * .design: design.mps.type @@ -39,9 +39,11 @@ typedef Addr Ref; /* design.mps.type.ref */ typedef void *Pointer; /* design.mps.type.pointer */ typedef Word RefSet; /* design.mps.refset */ typedef unsigned Rank; /* design.mps.ref */ +typedef unsigned RankSet; typedef Size Epoch; /* design.mps.ld */ typedef unsigned TraceId; /* design.mps.tracer */ typedef unsigned TraceSet; /* design.mps.tracer */ +typedef unsigned TraceState; /* design.mps.tracer */ typedef unsigned AccessSet; /* design.mps.type.access-set */ typedef unsigned Attr; /* design.mps.type.attr */ typedef int RootVar; /* design.mps.type.rootvar */ @@ -66,6 +68,7 @@ typedef struct VMStruct *VM; /* impl.c.vm* */ typedef struct RootStruct *Root; /* impl.c.root */ typedef struct ThreadStruct *Thread; /* impl.c.th* */ typedef Word EventType; /* impl.c.event */ +typedef struct ActionStruct *Action; /* design.mps.action */ /* Pool*Method -- see design.mps.class-interface */ @@ -83,15 +86,12 @@ typedef Bool (*PoolBufferTripMethod) (Pool pool, Buffer buffer, typedef void (*PoolBufferExposeMethod) (Pool pool, Buffer buffer); typedef void (*PoolBufferCoverMethod) (Pool pool, Buffer buffer); typedef Res (*PoolDescribeMethod) (Pool pool, mps_lib_FILE *stream); -typedef Res (*PoolCondemnMethod) (RefSet *condemnedReturn, Pool pool, - Space space, TraceId ti); -typedef void (*PoolGreyMethod) (Pool pool, Space space, TraceId ti); -typedef Res (*PoolScanMethod) (ScanState ss, Pool pool, - Bool *finishedReturn); +typedef Res (*PoolCondemnMethod) (Pool pool, Trace trace, Seg seg); +typedef void (*PoolGreyMethod) (Pool pool, Trace trace, Seg seg); +typedef Res (*PoolScanMethod) (ScanState ss, Pool pool, Seg seg); typedef Res (*PoolFixMethod) (Pool pool, ScanState ss, Seg seg, Ref *refIO); -typedef void (*PoolReclaimMethod) (Pool pool, Space space, TraceId ti); -typedef void (*PoolAccessMethod) (Pool pool, Seg seg, AccessSet mode); +typedef void (*PoolReclaimMethod) (Pool pool, Trace trace, Seg seg); /* Format*Method -- see design.mps.format-interface */ @@ -125,7 +125,8 @@ typedef Res (*RootScanRegMethod)(ScanState ss, Thread thread, void *p, #define TraceIdNONE ((TraceId)-1) /* design.mps.tracer */ #define RefSetEMPTY BS_EMPTY(RefSet) #define RefSetUNIV BS_UNIV(RefSet) -#define TraceSetEMPTY BS_EMPTY(TraceSet) /* design.mps.tracer */ +#define TraceSetEMPTY BS_EMPTY(TraceSet) /* design.mps.tracer */ +#define RankSetEMPTY BS_EMPTY(RankSet) #define AttrFMT ((Attr)(1<<0)) /* design.mps.type.attr */ #define AttrSCAN ((Attr)(1<<1)) #define AttrPM_NO_READ ((Attr)(1<<2)) @@ -200,6 +201,17 @@ enum { }; +/* TraceStates -- see design.mps.tracer */ + +enum { + TraceINIT, + TraceUNFLIPPED, + TraceFLIPPED, + TraceRECLAIM, + TraceFINISHED +}; + + /* Types for WriteF formats */ /* These should be used with calls to WriteF. */ /* These must be unpromotable types. */ @@ -214,8 +226,11 @@ typedef void *(*WriteFF)(void); typedef int WriteFC; /* Promoted */ -/* These names are intended to be mnemonic. They are derived from selected - * letters as indicated, using the transliteration in design.mps.sig. +/* Event Codes -- see design.mps.telemetry + * + * These names are intended to be mnemonic. They are derived from + * selected letters as indicated, using the transliteration in + * guide.hex.trans. */ #define EventEventTime ((EventType)0xEF213E77) /* EVent TIME */ @@ -234,4 +249,5 @@ typedef int WriteFC; /* Promoted */ #define EventVMMap ((EventType)0xEFF33AB7) /* EVent VM MAP */ #define EventVMUnmap ((EventType)0xEFF3093B) /* EVent VM UNMaP */ + #endif /* mpmtypes_h */ diff --git a/mps/src/mpsi.c b/mps/src/mpsi.c index 6caad1fb765..b762637c5d4 100644 --- a/mps/src/mpsi.c +++ b/mps/src/mpsi.c @@ -1,7 +1,7 @@ /* impl.c.mpsi: MEMORY POOL SYSTEM C INTERFACE LAYER * - * $HopeName: MMsrc!mpsi.c(trunk.21) $ - * Copyright (C) 1996 Harlequin Group, all rights reserved. + * $HopeName: MMsrc!mpsi.c(MMdevel_action2.3) $ + * Copyright (C) 1997 The Harlequin Group Limited. All rights reserved. * * .purpose: This code bridges between the MPS interface to C, * impl.h.mps, and the internal MPM interfaces, as defined by @@ -52,7 +52,7 @@ #include "mpm.h" #include "mps.h" -SRCID(mpsi, "$HopeName: MMsrc!mpsi.c(trunk.21) $"); +SRCID(mpsi, "$HopeName: MMsrc!mpsi.c(MMdevel_action2.3) $"); /* mpsi_check -- check consistency of interface mappings @@ -139,7 +139,7 @@ static Bool mpsi_check(void) /* design.mps.interface.c.pun.addr. */ CHECKL(CHECKFIELDAPPROX(mps_ss_s, fix, ScanStateStruct, fix)); CHECKL(CHECKFIELD(mps_ss_s, w0, ScanStateStruct, zoneShift)); - CHECKL(CHECKFIELD(mps_ss_s, w1, ScanStateStruct, condemned)); + CHECKL(CHECKFIELD(mps_ss_s, w1, ScanStateStruct, white)); CHECKL(CHECKFIELD(mps_ss_s, w2, ScanStateStruct, summary)); /* Check ld_s/LDStruct compatibility by hand */ diff --git a/mps/src/o1alcc.gmk b/mps/src/o1alcc.gmk index d44588e12d6..8b6d4e8513c 100644 --- a/mps/src/o1alcc.gmk +++ b/mps/src/o1alcc.gmk @@ -1,7 +1,7 @@ # # BUILD FOR OSF/1, ALPHA, DIGITAL C PLATFORM # -# $HopeName: MMsrc!o1alcc.gmk(trunk.4) $ +# $HopeName: MMsrc!o1alcc.gmk(trunk.5) $ # # Copyright (C) 1995,1997 Harlequin Group, all rights reserved # @@ -18,7 +18,7 @@ MPM = assert.c ring.c mpsliban.c mpm.c bt.c \ arenavm.c space.c pool.c poolmfs.c \ poolmv.c root.c format.c buffer.c lockan.c ref.c \ trace.c than.c protan.c shield.c mpsi.c ld.c vmo1.c \ - mpsioan.c event.c + mpsioan.c event.c action.c seg.c MPMS = sso1al.s AMC = amc.c LO = lo.c diff --git a/mps/src/o1algc.gmk b/mps/src/o1algc.gmk index f9fc42fdef4..f790ae3dc9b 100644 --- a/mps/src/o1algc.gmk +++ b/mps/src/o1algc.gmk @@ -1,7 +1,7 @@ # # BUILD FOR OSF/1, ALPHA, GCC PLATFORM # -# $HopeName: MMsrc!o1algc.gmk(trunk.9) $ +# $HopeName: MMsrc!o1algc.gmk(trunk.10) $ # # Copyright (C) 1995,1997 Harlequin Group, all rights reserved # @@ -18,7 +18,7 @@ MPM = assert.c ring.c mpsliban.c mpm.c bt.c \ arenavm.c space.c pool.c poolmfs.c \ poolmv.c root.c format.c buffer.c lockan.c ref.c \ trace.c than.c protan.c shield.c mpsi.c ld.c vmo1.c \ - mpsioan.c event.c + mpsioan.c event.c action.c seg.c MPMS = sso1al.s AMC = amc.c LO = lo.c diff --git a/mps/src/pool.c b/mps/src/pool.c index 65a1a595e40..4e723dea972 100644 --- a/mps/src/pool.c +++ b/mps/src/pool.c @@ -1,7 +1,7 @@ /* impl.c.pool: POOL IMPLEMENTATION * - * $HopeName: MMsrc!pool.c(trunk.23) $ - * Copyright (C) 1994,1995,1996,1997 Harlequin Group, all rights reserved + * $HopeName: MMsrc!pool.c(MMdevel_action2.10) $ + * Copyright (C) 1997 The Harlequin Group Limited. All rights reserved. * * This is the implementation of the generic pool interface. The * functions here dispatch to pool-specific methods. @@ -12,7 +12,7 @@ #include "mpm.h" -SRCID(pool, "$HopeName: MMsrc!pool.c(trunk.23) $"); +SRCID(pool, "$HopeName: MMsrc!pool.c(MMdevel_action2.10) $"); Bool PoolClassCheck(PoolClass class) @@ -39,7 +39,6 @@ Bool PoolClassCheck(PoolClass class) CHECKL(FUNCHECK(class->scan)); CHECKL(FUNCHECK(class->fix)); CHECKL(FUNCHECK(class->reclaim)); - CHECKL(FUNCHECK(class->access)); CHECKL(FUNCHECK(class->describe)); CHECKL(class->endSig == PoolClassSig); return TRUE; @@ -55,6 +54,7 @@ Bool PoolCheck(Pool pool) CHECKL(RingCheck(&pool->spaceRing)); CHECKL(RingCheck(&pool->bufferRing)); CHECKL(RingCheck(&pool->segRing)); + CHECKL(RingCheck(&pool->actionRing)); /* Cannot check pool->bufferSerial */ CHECKL(AlignCheck(pool->alignment)); return TRUE; @@ -91,8 +91,10 @@ Res PoolInitV(Pool pool, Space space, RingInit(&pool->spaceRing); RingInit(&pool->bufferRing); RingInit(&pool->segRing); + RingInit(&pool->actionRing); + pool->bufferSerial = (Serial)0; + pool->actionSerial = (Serial)0; pool->alignment = MPS_PF_ALIGN; - RingAppend(SpacePoolRing(space), &pool->spaceRing); /* Initialise signature last; see design.mps.sig */ pool->sig = PoolSig; @@ -106,12 +108,16 @@ Res PoolInitV(Pool pool, Space space, if(res != ResOK) goto failInit; + /* Add initialized pool to list of pools in space. */ + RingAppend(SpacePoolRing(space), &pool->spaceRing); + EVENT3(PoolInit, pool, space, class); return ResOK; failInit: pool->sig = SigInvalid; /* Leave space->poolSerial incremented */ + RingFinish(&pool->actionRing); RingFinish(&pool->segRing); RingFinish(&pool->bufferRing); RingRemove(&pool->spaceRing); @@ -177,21 +183,12 @@ void PoolFinish(Pool pool) /* Do any class-specific finishing. */ (*pool->class->finish)(pool); - /* There must be no buffers attached to the pool at */ - /* this point. The class-specific finish method is */ - /* allowed to remove them. */ - AVER(RingCheckSingle(&pool->bufferRing)); - - /* There must be no segments attached to the pool at */ - /* this point. The class-specific finish method is */ - /* allowed to remove them. */ - AVER(RingCheckSingle(&pool->segRing)); - /* Detach the pool from the space, and unsig it. */ RingRemove(&pool->spaceRing); pool->sig = SigInvalid; /* .ring.finish: Finish the generic fields. See .ring.init */ + RingFinish(&pool->actionRing); RingFinish(&pool->segRing); RingFinish(&pool->bufferRing); RingFinish(&pool->spaceRing); @@ -250,34 +247,44 @@ void PoolFree(Pool pool, Addr old, Size size) EVENT3(PoolFree, (Word)pool, (Word)old, (Word)size); } -Res PoolCondemn(RefSet *condemnedReturn, Pool pool, - Space space, TraceId ti) +Res PoolCondemn(Pool pool, Trace trace, Seg seg) { - AVER(condemnedReturn != NULL); AVERT(Pool, pool); - AVERT(Space, space); - AVER(pool->space == space); - AVERT(TraceId, ti); - AVER(ti != TraceIdNONE); - return (*pool->class->condemn)(condemnedReturn, pool, space, ti); + AVERT(Trace, trace); + AVERT(Seg, seg); + AVER(pool->space == trace->space); + AVER(seg->pool == pool); + return (*pool->class->condemn)(pool, trace, seg); } -void PoolGrey(Pool pool, Space space, TraceId ti) +void PoolGrey(Pool pool, Trace trace, Seg seg) { AVERT(Pool, pool); - AVERT(Space, space); - AVER(pool->space == space); - AVERT(TraceId, ti); - AVER(ti != TraceIdNONE); - (*pool->class->grey)(pool, space, ti); + AVERT(Trace, trace); + AVERT(Seg, seg); + AVER(pool->space == trace->space); + AVER(seg->pool == pool); + (*pool->class->grey)(pool, trace, seg); } -Res PoolScan(ScanState ss, Pool pool, Bool *finishedReturn) +Res PoolScan(ScanState ss, Pool pool, Seg seg) { AVERT(ScanState, ss); AVERT(Pool, pool); - AVER(finishedReturn != NULL); - return (*pool->class->scan)(ss, pool, finishedReturn); + AVERT(Seg, seg); + AVER(ss->space == pool->space); + + /* The segment must belong to the pool. */ + AVER(pool == seg->pool); + + /* Should only scan for a rank for which there are references */ + /* in the segment. */ + AVER(RankSetIsMember(seg->rankSet, ss->rank)); + + /* Should only scan segments which contain grey objects. */ + AVER(TraceSetInter(seg->grey, ss->traces) != TraceSetEMPTY); + + return (*pool->class->scan)(ss, pool, seg); } /* See impl.h.mpm for macro version; see design.mps.pool.req.fix */ @@ -286,23 +293,30 @@ Res (PoolFix)(Pool pool, ScanState ss, Seg seg, Addr *refIO) AVERT(Pool, pool); AVERT(ScanState, ss); AVERT(Seg, seg); + AVER(pool == seg->pool); AVER(refIO != NULL); + + /* Should only be fixing references to white segments. */ + AVER(TraceSetInter(seg->white, ss->traces) != TraceSetEMPTY); + return PoolFix(pool, ss, seg, refIO); } -void PoolReclaim(Pool pool, Space space, TraceId ti) -{ - AVERT(Pool, pool); - AVERT(Space, space); - AVER(pool->space == space); - (*pool->class->reclaim)(pool, space, ti); -} - -void PoolAccess(Pool pool, Seg seg, AccessSet mode) +void PoolReclaim(Pool pool, Trace trace, Seg seg) { AVERT(Pool, pool); + AVERT(Trace, trace); AVERT(Seg, seg); - (*pool->class->access)(pool, seg, mode); + AVER(pool->space == trace->space); + AVER(seg->pool == pool); + + /* There shouldn't be any grey things left for this trace. */ + AVER(!TraceSetIsMember(seg->grey, trace->ti)); + + /* Should only be reclaiming segments which are still white. */ + AVER(TraceSetIsMember(seg->white, trace->ti)); + + (*pool->class->reclaim)(pool, trace, seg); } @@ -353,6 +367,12 @@ Space (PoolSpace)(Pool pool) } +/* PoolSegAlloc -- allocate a segment in a pool + * + * @@@@ There's no need for this routine. The segment could be + * attached in SegInit. + */ + Res PoolSegAlloc(Seg *segReturn, SegPref pref, Pool pool, Size size) { Res res; @@ -375,6 +395,12 @@ Res PoolSegAlloc(Seg *segReturn, SegPref pref, Pool pool, Size size) } +/* PoolSegFree -- free a segment from a pool + * + * @@@@ There's no need for this routine. The segment could be + * detached in SegFinish. + */ + void PoolSegFree(Pool pool, Seg seg) { Space space; @@ -477,32 +503,34 @@ void PoolTrivFree(Pool pool, Addr old, Size size) NOOP; /* trivial free has no effect */ } -Res PoolNoBufferInit(Pool pool, Buffer buf) +Res PoolNoBufferInit(Pool pool, Buffer buffer) { AVERT(Pool, pool); + UNUSED(buffer); NOTREACHED; return ResUNIMPL; } /* The generic method initialised all generic fields; */ /* This doesn't override any fields */ -Res PoolTrivBufferInit(Pool pool, Buffer buf) +Res PoolTrivBufferInit(Pool pool, Buffer buffer) { AVERT(Pool, pool); + UNUSED(buffer); return ResOK; } -void PoolNoBufferFinish(Pool pool, Buffer buf) +void PoolNoBufferFinish(Pool pool, Buffer buffer) { AVERT(Pool, pool); - AVERT(Buffer, buf); + AVERT(Buffer, buffer); NOTREACHED; } -void PoolTrivBufferFinish(Pool pool, Buffer buf) +void PoolTrivBufferFinish(Pool pool, Buffer buffer) { AVERT(Pool, pool); - AVERT(Buffer, buf); + AVERT(Buffer, buffer); NOOP; } @@ -555,29 +583,48 @@ Res PoolTrivDescribe(Pool pool, mps_lib_FILE *stream) return WriteF(stream, " No class-specific description available.\n", NULL); } -Res PoolNoCondemn(RefSet *condemnedReturn, Pool pool, Space space, TraceId ti) +Res PoolNoCondemn(Pool pool, Trace trace, Seg seg) { - AVER(condemnedReturn != NULL); AVERT(Pool, pool); - AVERT(Space, space); - AVER(TraceIdCheck(ti)); + AVERT(Trace, trace); + AVERT(Seg, seg); NOTREACHED; return ResUNIMPL; } -void PoolNoGrey(Pool pool, Space space, TraceId ti) +void PoolNoGrey(Pool pool, Trace trace, Seg seg) { AVERT(Pool, pool); - AVERT(Space, space); - AVER(TraceIdCheck(ti)); + AVERT(Trace, trace); + AVERT(Seg, seg); NOTREACHED; } -Res PoolNoScan(ScanState ss, Pool pool, Bool *finishedReturn) +void PoolTrivGrey(Pool pool, Trace trace, Seg seg) +{ + AVERT(Pool, pool); + AVERT(Trace, trace); + AVERT(Seg, seg); + + /* @@@@ The trivial grey method probably shouldn't exclude */ + /* the white segments, since they might also contain grey objects. */ + /* It's probably also the Tracer's responsibility to raise the */ + /* shield. */ + /* @@@@ This should be calculated by comparing colour */ + /* with the mutator colour. For the moment we assume */ + /* a read-barrier collector. */ + + if(!TraceSetIsMember(seg->white, trace->ti)) { + seg->grey = TraceSetAdd(seg->grey, trace->ti); + ShieldRaise(trace->space, seg, AccessREAD | AccessWRITE); + } +} + +Res PoolNoScan(ScanState ss, Pool pool, Seg seg) { AVERT(ScanState, ss); AVERT(Pool, pool); - AVER(finishedReturn != NULL); + AVERT(Seg, seg); NOTREACHED; return ResUNIMPL; } @@ -592,17 +639,10 @@ Res PoolNoFix(Pool pool, ScanState ss, Seg seg, Ref *refIO) return ResUNIMPL; } -void PoolNoReclaim(Pool pool, Space space, TraceId ti) -{ - AVERT(Pool, pool); - AVERT(Space, space); - AVER(TraceIdCheck(ti)); - NOTREACHED; -} - -void PoolNoAccess(Pool pool, Seg seg, AccessSet mode) +void PoolNoReclaim(Pool pool, Trace trace, Seg seg) { AVERT(Pool, pool); + AVERT(Trace, trace); AVERT(Seg, seg); NOTREACHED; } diff --git a/mps/src/poolmfs.c b/mps/src/poolmfs.c index 3072af3158e..6c345e89d16 100644 --- a/mps/src/poolmfs.c +++ b/mps/src/poolmfs.c @@ -1,6 +1,6 @@ /* impl.c.poolmfs: MANUAL FIXED SMALL UNIT POOL * - * $HopeName: MMsrc!poolmfs.c(trunk.15) $ + * $HopeName: MMsrc!poolmfs.c(trunk.16) $ * Copyright (C) 1994,1995,1996 Harlequin Group, all rights reserved * * This is the implementation of the MFS pool class. @@ -35,7 +35,7 @@ #include "mpm.h" #include "poolmfs.h" -SRCID(poolmfs, "$HopeName: MMsrc!poolmfs.c(trunk.15) $"); +SRCID(poolmfs, "$HopeName: MMsrc!poolmfs.c(trunk.16) $"); /* == Round up == @@ -282,7 +282,6 @@ static PoolClassStruct PoolClassMFSStruct = { PoolNoScan, /* scan */ PoolNoFix, /* fix */ PoolNoReclaim, /* reclaim */ - PoolNoAccess, /* access */ MFSDescribe, /* describe */ PoolClassSig /* impl.h.mpmst.class.end-sig */ }; diff --git a/mps/src/poolmrg.c b/mps/src/poolmrg.c index ed5f4efb5ee..48b2455c104 100644 --- a/mps/src/poolmrg.c +++ b/mps/src/poolmrg.c @@ -2,8 +2,8 @@ * * MANUAL RANK GUARDIAN POOL * - * $HopeName: MMsrc!poolmrg.c(trunk.5) $ - * Copyright(C) 1995,1997 Harlequin Group, all rights reserved + * $HopeName: MMsrc!poolmrg.c(MMdevel_action2.8) $ + * Copyright (C) 1997 The Harlequin Group Limited. All rights reserved. * * READERSHIP * @@ -29,7 +29,7 @@ #include "poolmrg.h" -SRCID(poolmrg, "$HopeName: MMsrc!poolmrg.c(trunk.5) $"); +SRCID(poolmrg, "$HopeName: MMsrc!poolmrg.c(MMdevel_action2.8) $"); #define MRGSig ((Sig)0x519B0349) @@ -83,8 +83,7 @@ static Index indexOfLinkPart(Addr a, Space space) typedef struct MRGGroupStruct { Sig sig; /* impl.h.misc.sig */ - RingStruct group; /* design.mps.poolmrg.group.group */ - TraceSet grey; /* design.mps.poolmrg.group.grey */ + RingStruct group; /* design.mps.poolmrg.group.group */ Seg refseg; /* design.mps.poolmrg.group.segs */ Seg linkseg; /* design.mps.poolmrg.group.segs */ } MRGGroupStruct; @@ -149,13 +148,13 @@ static Res MRGGroupCreate(MRGGroup *groupReturn, MRG mrg) } AVER((Addr)(&linkpart[i]) <= SegLimit(space, linkseg)); AVER((Addr)(&refpart[i]) <= SegLimit(space, refseg)); - refseg->rank = RankFINAL; + refseg->rankSet = RankSetSingle(RankFINAL); /* design.mps.seg.field.rankSet.start */ + refseg->summary = RefSetUNIV; /* design.mps.seg.field.summary.start */ group->refseg = refseg; group->linkseg = linkseg; refseg->p = group; linkseg->p = group; - group->grey = TraceSetEMPTY; RingInit(&group->group); RingAppend(&mrg->group, &group->group); group->sig = MRGGroupSig; @@ -180,9 +179,7 @@ static Res MRGGroupScan(ScanState ss, MRGGroup group, MRG mrg) space = PoolSpace(MRGPool(mrg)); - ShieldExpose(space, group->refseg); - - guardians = mrg->extendBy / sizeof(Addr); /* per seg */ + guardians = mrg->extendBy / sizeof(Addr); /* per seg */ AVER(guardians > 0); base = SegBase(space, group->refseg); refpart = (Addr *)base; @@ -202,10 +199,6 @@ static Res MRGGroupScan(ScanState ss, MRGGroup group, MRG mrg) } } TRACE_SCAN_END(ss); - group->grey = TraceSetDel(group->grey, ss->traceId); - ShieldLower(space, group->refseg, AccessREAD | AccessWRITE); - ShieldCover(space, group->refseg); - return ResOK; } @@ -385,97 +378,27 @@ static Res MRGDescribe(Pool pool, mps_lib_FILE *stream) return ResOK; } -static void MRGGrey(Pool pool, Space space, TraceId ti) -{ - MRG mrg; - Ring r; - - AVERT(Pool, pool); - mrg = PoolPoolMRG(pool); - AVERT(MRG, mrg); - AVERT(Space, space); - AVERT(TraceId, ti); - - RING_FOR(r, &mrg->group) { - MRGGroup group; - - group = RING_ELT(MRGGroup, group, r); - group->grey = TraceSetAdd(group->grey, ti); - ShieldRaise(space, group->refseg, AccessREAD | AccessWRITE); - } -} - -static Res MRGScan(ScanState ss, Pool pool, Bool *finishedReturn) +static Res MRGScan(ScanState ss, Pool pool, Seg seg) { MRG mrg; Res res; + MRGGroup group; AVERT(ScanState, ss); - AVERT(Pool, pool); - mrg = PoolPoolMRG(pool); - AVERT(MRG, mrg); - AVER(finishedReturn != NULL); - - if(ss->rank == RankFINAL) { - Ring r; - - RING_FOR(r, &mrg->group) { - MRGGroup group; - - group = RING_ELT(MRGGroup, group, r); - if(TraceSetIsMember(group->grey, ss->traceId)) { - res = MRGGroupScan(ss, group, mrg); - if(res != ResOK) { - return res; - } - *finishedReturn = FALSE; - return ResOK; - } - } - } - - *finishedReturn = TRUE; - return ResOK; -} - -/* .amc.copy: This code is an almost exact copy of the analogous - * method in impl.c.amc. This is worrying. - */ -static void MRGAccess(Pool pool, Seg seg, AccessSet mode) -{ - Space space; - MRG mrg; - MRGGroup group; - Res res; - ScanStateStruct ss; - AVERT(Pool, pool); mrg = PoolPoolMRG(pool); AVERT(MRG, mrg); AVERT(Seg, seg); - AVER(seg->pool == pool); - /* Cannot check AccessSet */ - - space = PoolSpace(pool); + AVER(seg->rankSet == RankSetSingle(RankFINAL)); + AVER(TraceSetInter(seg->grey, ss->traces) != TraceSetEMPTY); group = (MRGGroup)seg->p; + AVER(seg == group->refseg); - ss.fix = TraceFix; - ss.zoneShift = space->zoneShift; - ss.summary = RefSetEMPTY; - ss.space = space; - ss.sig = ScanStateSig; - ss.rank = RankEXACT; /* .access.exact */ - ss.weakSplat = (Addr)0xadd4badd; + res = MRGGroupScan(ss, group, mrg); + if(res != ResOK) return res; - /* impl.c.amc.access.multi (!) */ - for(ss.traceId = 0; ss.traceId < TRACE_MAX; ++ss.traceId) { - if(TraceSetIsMember(space->busyTraces, ss.traceId)) { - ss.condemned = space->trace[ss.traceId].condemned; - res = MRGGroupScan(&ss, group, mrg); - AVER(res == ResOK); /* impl.c.amc.access.error (!) */ - } - } + return ResOK; } static PoolClassStruct PoolClassMRGStruct = { @@ -495,11 +418,10 @@ static PoolClassStruct PoolClassMRGStruct = { PoolNoBufferExpose, /* bufferExpose */ PoolNoBufferCover, /* bufferCover */ PoolNoCondemn, /* condemn */ - MRGGrey, /* grey */ + PoolTrivGrey, /* grey */ MRGScan, /* scan */ PoolNoFix, /* fix */ PoolNoReclaim, /* reclaim */ - MRGAccess, /* access */ MRGDescribe, /* describe */ PoolClassSig /* impl.h.mpmst.class.end-sig */ }; diff --git a/mps/src/poolmv.c b/mps/src/poolmv.c index f4119378a41..1004bf0e855 100644 --- a/mps/src/poolmv.c +++ b/mps/src/poolmv.c @@ -1,7 +1,7 @@ /* impl.c.poolmv: MANUAL VARIABLE POOL * - * $HopeName: MMsrc!poolmv.c(trunk.17) $ - * Copyright (C) 1994, 1995 Harlequin Group, all rights reserved + * $HopeName: MMsrc!poolmv.c(MMdevel_action2.2) $ + * Copyright (C) 1997 The Harlequin Group Limited. All rights reserved. * * **** RESTRICTION: This pool may not allocate from the arena control * pool, since it is used to implement that pool. @@ -9,8 +9,8 @@ * poolPool. * * An observation: Freeing memory introduces more information - * into the system than allocating it. This causes the problem described - * in note 2. + * into the system than allocating it. This causes the problem + * described in note 2. * * Notes * 1. Need to measure typical fragmentation levels and adjust the @@ -37,7 +37,7 @@ #include "poolmfs.h" #include "mpscmv.h" -SRCID(poolmv, "$HopeName: MMsrc!poolmv.c(trunk.17) $"); +SRCID(poolmv, "$HopeName: MMsrc!poolmv.c(MMdevel_action2.2) $"); #define BLOCKPOOL(mv) (MFSPool(&(mv)->blockPoolStruct)) @@ -626,7 +626,6 @@ static PoolClassStruct PoolClassMVStruct = { PoolNoScan, /* scan */ PoolNoFix, /* fix */ PoolNoReclaim, /* relcaim */ - PoolNoAccess, /* access */ MVDescribe, /* describe */ PoolClassSig /* impl.h.mpmst.class.end-sig */ }; diff --git a/mps/src/pooln.c b/mps/src/pooln.c index cbd3c02d4a0..99a1c65db76 100644 --- a/mps/src/pooln.c +++ b/mps/src/pooln.c @@ -1,19 +1,16 @@ -/* impl.c.pooln +/* impl.c.pooln: NULL POOL * - * NULL POOL + * $HopeName: MMsrc!pooln.c(MMdevel_action2.7) $ + * Copyright(C) 1997 The Harlequin Group Limited. All rights reserved. * - * $HopeName: MMsrc!pooln.c(MMdevel_lib.2) $ - * - * Copyright(C) 1995 Harlequin Group, all rights reserved - * - * This is the implementation of the null pool class. Begin null it - * all functions are implemented in a trivial manner. + * This is the implementation of the null pool class. Begin null it + * all functions are implemented in a trivial manner. */ #include "mpm.h" #include "pooln.h" -SRCID(pooln, "$HopeName: MMsrc!pooln.c(MMdevel_lib.2) $"); +SRCID(pooln, "$HopeName: MMsrc!pooln.c(MMdevel_action2.7) $"); typedef struct PoolNStruct { @@ -90,6 +87,8 @@ static Res NBufferInit(Pool pool, Buffer buffer) poolN = PoolPoolN(pool); AVERT(PoolN, poolN); + UNUSED(buffer); + return ResLIMIT; /* limit of nil buffers exceeded */ } @@ -172,8 +171,7 @@ static Res NDescribe(Pool pool, mps_lib_FILE *stream) return ResOK; } -static Res NCondemn(RefSet *condemnedReturn, Pool pool, - Space space, TraceId ti) +static Res NCondemn(Pool pool, Trace trace, Seg seg) { PoolN poolN; @@ -181,13 +179,13 @@ static Res NCondemn(RefSet *condemnedReturn, Pool pool, poolN = PoolPoolN(pool); AVERT(PoolN, poolN); - AVER(condemnedReturn != NULL); - AVERT(Space, space); + AVERT(Trace, trace); + AVERT(Seg, seg); return ResOK; } -static void NMark(Pool pool, Space space, TraceId ti) +static void NGrey(Pool pool, Trace trace, Seg seg) { PoolN poolN; @@ -195,10 +193,11 @@ static void NMark(Pool pool, Space space, TraceId ti) poolN = PoolPoolN(pool); AVERT(PoolN, poolN); - AVERT(Space, space); + AVERT(Trace, trace); + AVERT(Seg, seg); } -static Res NScan(ScanState ss, Pool pool, Bool *finishedReturn) +static Res NScan(ScanState ss, Pool pool, Seg seg) { PoolN poolN; @@ -206,8 +205,8 @@ static Res NScan(ScanState ss, Pool pool, Bool *finishedReturn) poolN = PoolPoolN(pool); AVERT(PoolN, poolN); - AVER(finishedReturn != NULL); AVERT(ScanState, ss); + AVERT(Seg, seg); return ResOK; } @@ -221,25 +220,14 @@ static Res NFix(Pool pool, ScanState ss, Seg seg, Ref *refIO) AVERT(PoolN, poolN); AVERT(ScanState, ss); + UNUSED(refIO); AVERT(Seg, seg); NOTREACHED; /* since we don't allocate any objects, should never * be called upon to fix a reference */ return ResFAIL; } -static void NReclaim(Pool pool, Space space, TraceId ti) -{ - PoolN poolN; - - AVERT(Pool, pool); - poolN = PoolPoolN(pool); - AVERT(PoolN, poolN); - - AVERT(Space, space); - /* all unmarked and condemned objects reclaimed */ -} - -static void NAccess(Pool pool, Seg seg, AccessSet mode) +static void NReclaim(Pool pool, Trace trace, Seg seg) { PoolN poolN; @@ -247,9 +235,9 @@ static void NAccess(Pool pool, Seg seg, AccessSet mode) poolN = PoolPoolN(pool); AVERT(PoolN, poolN); + AVERT(Trace, trace); AVERT(Seg, seg); - UNUSED(mode); - /* deal with access to segment */ + /* all unmarked and white objects reclaimed */ } static PoolClassStruct PoolClassNStruct = { @@ -269,11 +257,10 @@ static PoolClassStruct PoolClassNStruct = { NBufferExpose, /* bufferExpose */ NBufferCover, /* bufferCover */ NCondemn, /* condemn */ - NMark, /* grey */ + NGrey, /* grey */ NScan, /* scan */ NFix, /* fix */ NReclaim, /* reclaim */ - NAccess, /* access */ NDescribe, /* describe */ PoolClassSig /* impl.h.mpmst.class.end-sig */ }; diff --git a/mps/src/protan.c b/mps/src/protan.c index 20b29e6866c..b1488b79b27 100644 --- a/mps/src/protan.c +++ b/mps/src/protan.c @@ -1,7 +1,7 @@ /* impl.c.protan: ANSI MEMORY PROTECTION * - * $HopeName: MMsrc!protan.c(trunk.2) $ - * Copyright (C) 1996,1997 Harlequin Group, all rights reserved. + * $HopeName: MMsrc!protan.c(trunk.3) $ + * Copyright (C) 1997 The Harlequin Group Limited. All rights reserved. * * READERSHIP * @@ -15,7 +15,7 @@ #include "mpm.h" -SRCID(protan, "$HopeName: MMsrc!protan.c(trunk.2) $"); +SRCID(protan, "$HopeName: MMsrc!protan.c(MMdevel_action2.2) $"); void ProtSetup(void) { @@ -46,7 +46,7 @@ void ProtSync(Space space) while(seg != NULL) { if(seg->pm != AccessSetEMPTY) { /* design.mps.protan.fun.sync.seg */ ShieldEnter(space); - PoolAccess(seg->pool, seg, seg->pm); + TraceAccess(space, seg, seg->pm); ShieldLeave(space); synced = FALSE; } diff --git a/mps/src/ref.c b/mps/src/ref.c index 1b08d241e4d..f51ae403905 100644 --- a/mps/src/ref.c +++ b/mps/src/ref.c @@ -1,7 +1,7 @@ /* impl.c.ref: REFERENCES * - * $HopeName: MMsrc!ref.c(trunk.5) $ - * Copyright (C) 1995 Harlequin Group, all rights reserved + * $HopeName: MMsrc!ref.c(MMdevel_action2.3) $ + * Copyright (C) 1997 The Harlequin Group Limited. All rights reserved * * Ref is an alias for Addr which can be used to document where * references are being passed. @@ -18,13 +18,13 @@ * for IsMember. Add is used to implement reference summaries, * which provide a remembered set. IsMember is used to inline part * of the Fix function, and provide good discrimination of the - * condemned set. It is expected that the discrimination provided + * white set. It is expected that the discrimination provided * will be useful for distinguishing segments and groups of segments. */ #include "mpm.h" -SRCID(ref, "$HopeName: MMsrc!ref.c(trunk.5) $"); +SRCID(ref, "$HopeName: MMsrc!ref.c(MMdevel_action2.3) $"); Bool RankCheck(Rank rank) { @@ -33,6 +33,13 @@ Bool RankCheck(Rank rank) } +Bool RankSetCheck(RankSet rankSet) +{ + CHECKL(rankSet < (1uL << RankMAX)); + return TRUE; +} + + /* RefSetOfSeg -- calculate the reference set of segment addresses * * .rsos.def: The reference set of a segment is the union of the diff --git a/mps/src/root.c b/mps/src/root.c index db64b22562a..d3122ab7170 100644 --- a/mps/src/root.c +++ b/mps/src/root.c @@ -1,21 +1,23 @@ -/* impl.c.root +/* impl.c.root: ROOT IMPLEMENTATION * - * ROOT IMPLEMENTATION + * $HopeName: MMsrc!root.c(MMdevel_action2.4) $ + * Copyright (C) 1997 The Harlequin Group Limited. All rights reserved. * - * $HopeName: MMsrc!root.c(trunk.18) $ - * - * Copyright (C) 1995,1996 Harlequin Group, all rights reserved - * - * .scope: This is the implementation of the root datatype. - * - * .design: For design, see design.mps.root and design.mps.root-interface + * .scope: This is the implementation of the root datatype. + * .design: For design, see design.mps.root and + * design.mps.root-interface */ #include "mpm.h" -SRCID(root, "$HopeName: MMsrc!root.c(trunk.18) $"); +SRCID(root, "$HopeName: MMsrc!root.c(MMdevel_action2.4) $"); + + +/* RootCheck -- check the consistency of a root structure + * + * .rootcheck: Keep synchonized with impl.h.mpmst.root + */ -/* .rootcheck: Keep synchonized with impl.h.mpmst.root */ Bool RootCheck(Root root) { CHECKS(Root, root); @@ -85,6 +87,7 @@ static Res create(Root *rootReturn, Space space, root->var = type; root->the = *theUnionP; root->grey = TraceSetEMPTY; + root->summary = RefSetUNIV; /* See design.mps.space.root-ring */ RingInit(&root->spaceRing); @@ -201,12 +204,12 @@ Rank RootRank(Root root) return root->rank; } -void RootGrey(Root root, TraceId ti) +void RootGrey(Root root, Trace trace) { AVERT(Root, root); - AVER(TraceIdCheck(ti)); + AVERT(Trace, trace); - root->grey = TraceSetAdd(root->grey, ti); + root->grey = TraceSetAdd(root->grey, trace->ti); } Res RootScan(ScanState ss, Root root) @@ -217,7 +220,7 @@ Res RootScan(ScanState ss, Root root) AVERT(ScanState, ss); AVER(root->rank == ss->rank); - if(!TraceSetIsMember(root->grey, ss->traceId)) + if(TraceSetInter(root->grey, ss->traces) == TraceSetEMPTY) return ResOK; switch(root->var) { @@ -251,7 +254,7 @@ Res RootScan(ScanState ss, Root root) NOTREACHED; } - root->grey = TraceSetDel(root->grey, ss->traceId); + root->grey = TraceSetDiff(root->grey, ss->traces); return ResOK; } @@ -275,11 +278,11 @@ Res RootDescribe(Root root, mps_lib_FILE *stream) (WriteFU)root->space->serial, " rank $U\n", (WriteFU)root->rank, " grey $B\n", (WriteFB)root->grey, + " summary $B\n", (WriteFB)root->summary, NULL); if(res != ResOK) return res; - switch(root->var) - { + switch(root->var) { case RootTABLE: res = WriteF(stream, " table base $A limit $A\n", diff --git a/mps/src/sos8gc.gmk b/mps/src/sos8gc.gmk index 3fe30ec6651..87f6bdae8b0 100644 --- a/mps/src/sos8gc.gmk +++ b/mps/src/sos8gc.gmk @@ -1,7 +1,7 @@ # # BUILD FOR SOLARIS/SPARC/GCC PLATFORM # -# $HopeName: MMsrc!sospgc.gmk(trunk.8) $ +# $HopeName: MMsrc!sospgc.gmk(trunk.9) $ # Copyright (C) 1995,1997 Harlequin Group, all rights reserved # # This is the GNU makefile for platform.sospgc. @@ -14,7 +14,7 @@ MPM = assert.c ring.c mpsliban.c mpm.c bt.c \ arenavm.c vmso.c space.c pool.c poolmfs.c \ poolmv.c root.c format.c buffer.c lockan.c ref.c \ trace.c than.c protso.c shield.c mpsi.c ld.c \ - mpsioan.c event.c + mpsioan.c event.c action.c seg.c MPMPS = sssosp.S AMC = amc.c LO = lo.c @@ -22,7 +22,8 @@ MRG = poolmrg.c DW = fmtdy.c dw.c SW = assert.c ring.c mpm.c arenacl.c space.c pool.c poolmfs.c \ poolmv.c root.c format.c buffer.c lockan.c ref.c \ - trace.c than.c protsw.c shield.c mpsisw.c ld.c ssan.c poolepdl.c + trace.c than.c protsw.c shield.c mpsisw.c ld.c ssan.c poolepdl.c \ + action.c seg.c LIBS = -lm TESTLIB = testlib.c diff --git a/mps/src/sos9sc.gmk b/mps/src/sos9sc.gmk index 5fbd6b552f8..17f59fa762f 100644 --- a/mps/src/sos9sc.gmk +++ b/mps/src/sos9sc.gmk @@ -1,7 +1,7 @@ # # BUILD FOR Solaris/UltraSPARC/SunPro C PLATFORM # -# $HopeName: MMsrc!soussc.gmk(trunk.5) $ +# $HopeName: MMsrc!soussc.gmk(trunk.6) $ # # This is the GNU makefile for platform.soussc # @@ -13,7 +13,7 @@ MPM = assert.c ring.c mpsliban.c mpm.c bt.c \ arenavm.c vmso.c space.c pool.c poolmfs.c \ poolmv.c root.c format.c buffer.c lockan.c ref.c \ trace.c than.c protso.c shield.c mpsi.c ld.c \ - mpsioan.c event.c + mpsioan.c event.c action.c seg.c MPMPS = ssussp.s AMC = amc.c MRG = poolmrg.c @@ -21,7 +21,8 @@ LO = lo.c DW = fmtdy.c dw.c SW = assert.c ring.c mpm.c arenacl.c space.c pool.c poolmfs.c \ poolmv.c root.c format.c buffer.c lockan.c ref.c \ - trace.c than.c protsw.c shield.c mpsisw.c ld.c ssan.c poolepdl.c + trace.c than.c protsw.c shield.c mpsisw.c ld.c ssan.c poolepdl.c \ + action.c seg.c LIBS = -lm TESTLIB = testlib.c diff --git a/mps/src/sus8gc.gmk b/mps/src/sus8gc.gmk index 0e948e8bbb5..2dd96e61496 100644 --- a/mps/src/sus8gc.gmk +++ b/mps/src/sus8gc.gmk @@ -1,11 +1,9 @@ +# impl.gmk.suspgc: BUILD FOR SUNOS/SPARC/GCC PLATFORM # -# BUILD FOR SUNOS/SPARC/GCC PLATFORM -# -# $HopeName: MMsrc!suspgc.gmk(trunk.24) $ -# Copyright (C) 1995,1997 Harlequin Group, all rights reserved -# -# This is the GNU makefile for platform.suspgc. +# $HopeName: MMsrc!suspgc.gmk(MMdevel_action2.4) $ +# Copyright (C) 1995,1996,1997 Harlequin Group, all rights reserved. # +# This is the GNU makefile for platform.suspgc. PFM = suspgc @@ -13,7 +11,7 @@ MPM = assert.c ring.c mpsliban.c mpm.c bt.c \ arenavm.c vmsu.c space.c pool.c poolmfs.c \ poolmv.c root.c format.c buffer.c lockan.c ref.c \ trace.c than.c protsu.c shield.c mpsi.c ld.c \ - mpsioan.c event.c + mpsioan.c event.c action.c seg.c MPMS = sssusp.s AMC = amc.c LO = lo.c @@ -21,7 +19,8 @@ MRG = poolmrg.c DW = fmtdy.c dw.c SW = assert.c ring.c mpm.c arenacl.c space.c pool.c poolmfs.c \ poolmv.c root.c format.c buffer.c lockan.c ref.c \ - trace.c than.c protsw.c shield.c mpsisw.c ld.c ssan.c poolepdl.c + trace.c than.c protsw.c shield.c mpsisw.c ld.c ssan.c \ + poolepdl.c action.c seg.c LIBS = -lm diff --git a/mps/src/sus8lc.gmk b/mps/src/sus8lc.gmk index 48539674f82..48e61e3fbec 100644 --- a/mps/src/sus8lc.gmk +++ b/mps/src/sus8lc.gmk @@ -1,7 +1,7 @@ # # BUILD FOR SUNOS/SPARC/LCC PLATFORM # -# $HopeName: MMsrc!susplc.gmk(trunk.4) $ +# $HopeName: MMsrc!susplc.gmk(trunk.5) $ # Copyright (C) 1996,1997 Harlequin Group, all rights reserved # # This is the GNU makefile for platform.susplc. @@ -13,7 +13,7 @@ MPM = assert.c ring.c mpsliban.c mpm.c bt.c \ arenavm.c vmsu.c space.c pool.c poolmfs.c \ poolmv.c root.c format.c buffer.c lockan.c ref.c \ trace.c than.c protsu.c shield.c mpsi.c ld.c \ - mpsioan.c event.c + mpsioan.c event.c action.c seg.c MPMS = sssusp.s AMC = amc.c LO = lo.c @@ -21,7 +21,8 @@ MRG = poolmrg.c DW = fmtdy.c dw.c SW = assert.c ring.c mpm.c arenacl.c space.c pool.c poolmfs.c \ poolmv.c root.c format.c buffer.c lockan.c ref.c \ - trace.c than.c protsw.c shield.c mpsisw.c ld.c ssan.c poolepdl.c + trace.c than.c protsw.c shield.c mpsisw.c ld.c ssan.c poolepdl.c \ + action.c seg.c TESTLIB = testlib.c diff --git a/mps/src/trace.c b/mps/src/trace.c index 16cd9620878..1e07dc85033 100644 --- a/mps/src/trace.c +++ b/mps/src/trace.c @@ -1,121 +1,349 @@ /* impl.c.trace: GENERIC TRACER IMPLEMENTATION * - * $HopeName: MMsrc!trace.c(trunk.18) $ + * $HopeName: MMsrc!trace.c(MMdevel_action2.15) $ + * Copyright (C) 1997 The Harlequin Group Limited. All rights reserved. */ #include "mpm.h" -SRCID(trace, "$HopeName: MMsrc!trace.c(trunk.18) $"); +SRCID(trace, "$HopeName: MMsrc!trace.c(MMdevel_action2.15) $"); + + +/* ScanStateCheck -- check consistency of a ScanState object */ Bool ScanStateCheck(ScanState ss) { + TraceId ti; + RefSet white; CHECKS(ScanState, ss); + CHECKL(FUNCHECK(ss->fix)); CHECKU(Space, ss->space); + CHECKL(TraceSetCheck(ss->traces)); + CHECKL(TraceSetSuper(ss->space->busyTraces, ss->traces)); + white = RefSetEMPTY; + for(ti = 0; ti < TRACE_MAX; ++ti) + if(TraceSetIsMember(ss->traces, ti)) + white = RefSetUnion(white, ss->space->trace[ti].white); + CHECKL(ss->white == white); CHECKL(ss->zoneShift == ss->space->zoneShift); CHECKL(RankCheck(ss->rank)); - CHECKL(ss->condemned == ss->space->trace[ss->traceId].condemned); + CHECKL(BoolCheck(ss->wasMarked)); return TRUE; } + +/* TraceIdCheck -- check that a TraceId is valid */ + Bool TraceIdCheck(TraceId ti) { CHECKL(ti == TraceIdNONE || ti < TRACE_MAX); return TRUE; } + +/* TraceSetCheck -- check that a TraceSet is valid */ + Bool TraceSetCheck(TraceSet ts) { CHECKL(ts < (1uL << TRACE_MAX)); return TRUE; } -Res TraceCreate(TraceId *tiReturn, Space space) + +/* TraceCheck -- check consistency of Trace object */ + +Bool TraceCheck(Trace trace) +{ + CHECKS(Trace, trace); + CHECKU(Space, trace->space); + CHECKL(TraceIdCheck(trace->ti)); + CHECKL(trace == &trace->space->trace[trace->ti]); + CHECKL(TraceSetIsMember(trace->space->busyTraces, trace->ti)); + /* Can't check trace->white -- not in O(1) anyway. */ + /* Use trace->state to check more invariants. */ + switch(trace->state) { + case TraceINIT: + /* @@@@ What can be checked here? */ + break; + + case TraceUNFLIPPED: + CHECKL(!TraceSetIsMember(trace->space->flippedTraces, trace->ti)); + /* @@@@ Assert that mutator is grey for trace. */ + break; + + case TraceFLIPPED: + CHECKL(TraceSetIsMember(trace->space->flippedTraces, trace->ti)); + /* @@@@ Assert that mutator is black for trace. */ + break; + + case TraceRECLAIM: + CHECKL(TraceSetIsMember(trace->space->flippedTraces, trace->ti)); + /* @@@@ Assert that grey set is empty for trace. */ + break; + + case TraceFINISHED: + CHECKL(TraceSetIsMember(trace->space->flippedTraces, trace->ti)); + /* @@@@ Assert that grey and white sets is empty for trace. */ + break; + + default: + NOTREACHED; + } + /* @@@@ Check trace->interval? */ + return TRUE; +} + + +/* TraceCreate -- create a Trace object + * + * Allocates and initializes a new Trace object with a TraceId + * which is not currently active. + * + * Returns ResLIMIT if there aren't any available trace IDs. + * + * Trace objects are allocated directly from a small array in the + * space structure which is indexed by the TraceId. This is so + * that it's always possible to start a trace (provided there's + * a free TraceId) even if there's no available memory. + * + * This code is written to be adaptable to allocating Trace + * objects dynamically. + */ + +Res TraceCreate(Trace *traceReturn, Space space) { TraceId ti; + Trace trace; - /* .single-collection */ - AVER(TRACE_MAX == 1); + AVER(TRACE_MAX == 1); /* .single-collection */ - AVER(tiReturn != NULL); + AVER(traceReturn != NULL); AVERT(Space, space); - /* allocate free TraceId */ + /* Find a free trace ID */ for(ti = 0; ti < TRACE_MAX; ++ti) if(!TraceSetIsMember(space->busyTraces, ti)) goto found; - return ResLIMIT; + + return ResLIMIT; /* no trace IDs available */ found: - space->trace[ti].condemned = RefSetEMPTY; + trace = SpaceTrace(space, ti); space->busyTraces = TraceSetAdd(space->busyTraces, ti); - *tiReturn = ti; + trace->space = space; + trace->white = RefSetEMPTY; + trace->ti = ti; + trace->state = TraceINIT; + trace->interval = (Size)4096; /* @@@@ should be progress control */ + + trace->sig = TraceSig; + AVERT(Trace, trace); + + *traceReturn = trace; return ResOK; } -void TraceDestroy(Space space, TraceId ti) + +/* TraceDestroy -- destroy a trace object + * + * Finish and deallocate a Trace object, freeing up a TraceId. + * + * This code does not allow a Trace to be destroyed while it is + * active. It would be possible to allow this, but the colours + * of segments etc. would need to be reset to black. + */ + +void TraceDestroy(Trace trace) { - AVERT(Space, space); - space->busyTraces = TraceSetDel(space->busyTraces, ti); + AVERT(Trace, trace); + AVER(trace->state == TraceFINISHED); + trace->sig = SigInvalid; + trace->space->busyTraces = + TraceSetDel(trace->space->busyTraces, trace->ti); + trace->space->flippedTraces = + TraceSetDel(trace->space->flippedTraces, trace->ti); } -Res TraceFlip(Space space, TraceId ti, RefSet condemned) + +/* TraceStart -- condemn a set of objects and start collection + * + * TraceStart should be passed a trace with state TraceINIT, i.e. + * recently returned from TraceCreate. + * + * .start.black: All segments are black w.r.t. a newly allocated trace. + * However, if TraceStart initialized segments to black when it + * calculated the grey set then this condition could be relaxed, making + * it easy to destroy traces half-way through. + */ + +Res TraceStart(Trace trace, Pool pool) { - Ring ring; - Ring node; - Trace trace; - ScanStateStruct ss; Res res; + Ring ring, node; + Space space; + Seg seg; - AVERT(Space, space); + AVERT(Trace, trace); + AVERT(Pool, pool); + AVER((pool->class->attr & AttrGC) != 0); + AVER(trace->state == TraceINIT); + AVER(trace->white == RefSetEMPTY); - ShieldSuspend(space); - - trace = &space->trace[ti]; - AVER(trace->condemned == RefSetEMPTY); - trace->condemned = condemned; - - /* Update location dependency structures. condemned is - * a conservative approximation of the refset of refs which - * may move during this collection. - * @@@@ It is too conservative. Not everything condemned will - * necessarily move. - */ - LDAge(space, condemned); - - /* Grey all the roots and pools. */ - - ring = SpacePoolRing(space); + /* Identify the condemned set and turn it white. */ + space = trace->space; + ring = PoolSegRing(pool); node = RingNext(ring); while(node != ring) { Ring next = RingNext(node); - Pool pool = RING_ELT(Pool, spaceRing, node); + seg = RING_ELT(Seg, poolRing, node); - if((pool->class->attr & AttrSCAN) != 0) - PoolGrey(pool, space, ti); /* implicitly excludes condemned set */ + AVER(!TraceSetIsMember(seg->white, trace->ti)); /* .start.black */ + + /* Give the pool the opportunity to turn the segment white. */ + /* If it fails, unwind. */ + res = PoolCondemn(pool, trace, seg); + if(res != ResOK) goto failCondemn; + + /* Add the segment to the approximation of the white set the */ + /* pool made it white. */ + if(TraceSetIsMember(seg->white, trace->ti)) + trace->white = RefSetUnion(trace->white, RefSetOfSeg(space, seg)); node = next; } + /* If there is nothing white then there can be nothing grey, */ + /* so everything is black and we can proceed straight to */ + /* reclaim. We have to reclaim because we want to guarantee */ + /* to the pool that for every condemn there will be a reclaim. */ + /* @@@@ We can also shortcut if there is nothing grey. */ + /* @@@@ This should be in design. */ + if(trace->white == RefSetEMPTY) { + space->flippedTraces = TraceSetAdd(space->flippedTraces, trace->ti); + trace->state = TraceRECLAIM; + return ResOK; + } + + /* Turn everything else grey. */ + + /* @@@@ Instead of iterating over all the segments, we could */ + /* iterate over all pools which are scannable and thence over */ + /* all their segments. This might be better if the minority */ + /* of segments are scannable. Perhaps we should choose */ + /* dynamically which method to use. */ + + seg = SegFirst(space); + while(seg != NULL) { + /* Segment should be either black or white by now. */ + AVER(!TraceSetIsMember(seg->grey, trace->ti)); + + /* A segment can only be grey if it contains some references. */ + /* This is indicated by the rankSet begin non-empty. Such */ + /* segments may only belong to scannable pools. */ + if(seg->rankSet != RankSetEMPTY) { + /* Segments with ranks may only belong to scannable pools. */ + AVER((seg->pool->class->attr & AttrSCAN) != 0); + + /* Turn the segment grey if there might be a reference in it */ + /* to the white set. This is done by seeing if the summary */ + /* of references in the segment intersects with the approximation */ + /* to the white set. */ + if(RefSetInter(seg->summary, trace->white) != RefSetEMPTY) + PoolGrey(pool, trace, seg); + } + + seg = SegNext(space, seg); + } + ring = SpaceRootRing(space); node = RingNext(ring); while(node != ring) { Ring next = RingNext(node); Root root = RING_ELT(Root, spaceRing, node); - RootGrey(root, ti); + if(RefSetInter(root->summary, trace->white) != RefSetEMPTY) + RootGrey(root, trace); node = next; } - ss.fix = TraceFix; - ss.zoneShift = space->zoneShift; - ss.condemned = space->trace[ti].condemned; - ss.summary = RefSetEMPTY; - ss.space = space; - ss.traceId = ti; - ss.weakSplat = (Addr)0xadd4badd; - ss.sig = ScanStateSig; + trace->state = TraceUNFLIPPED; + + return ResOK; + + /* PoolCodemn failed, possibly half-way through whitening the condemned */ + /* set. This loop empties the white set again. */ +failCondemn: + ring = PoolSegRing(pool); + node = RingNext(ring); + while(node != ring) { + Ring next = RingNext(node); + seg = RING_ELT(Seg, poolRing, node); + seg->white = TraceSetDel(seg->white, trace->ti); + node = next; + } + + return res; +} + + +/* TraceSetGreyen -- turn a segment more grey + * + * Adds the trace set ts to the greyness of the segment and adjusts + * the shielding on the segment appropriately. (If it causes the + * segment to become grey for a flipped trace the shield is raised.) + * @@@@ Why does it seem to be write and a read barrier? + */ + +void TraceSegGreyen(Space space, Seg seg, TraceSet ts) +{ + TraceSet grey; + + AVERT(Space, space); + AVERT(Seg, seg); + AVER(TraceSetCheck(ts)); + + grey = seg->grey; + grey = TraceSetUnion(grey, ts); + if(grey != seg->grey && + TraceSetInter(grey, space->flippedTraces) != TraceSetEMPTY) + ShieldRaise(space, seg, AccessREAD | AccessWRITE); + seg->grey = grey; +} + + +static Res TraceFlip(Trace trace) +{ + Ring ring; + Ring node; + Space space; + ScanStateStruct ss; + Res res; + + AVERT(Trace, trace); + + space = trace->space; + ShieldSuspend(space); + + AVER(trace->state == TraceUNFLIPPED); + + /* @@@@ MUST TRIP ALL BUFFERS to make sure they don't */ + /* contain unscanned objects. */ + + /* Update location dependency structures. white is */ + /* a conservative approximation of the refset of refs which */ + /* may move during this collection. */ + /* @@@@ It is too conservative. Not everything white will */ + /* necessarily move. */ + LDAge(space, trace->white); + + /* The trace is marked as flipped here, apparently prematurely, */ + /* so that TraceSegGreyen will DTRT when things are scanned below. */ + /* @@@@ This isn't right. When flippedTraces is changed _all_ */ + /* grey segments should have their shield modes fixed up anyway. */ + trace->state = TraceFLIPPED; + space->flippedTraces = TraceSetAdd(space->flippedTraces, trace->ti); /* At the moment we must scan all roots, because we don't have */ /* a mechanism for shielding them. There can't be any weak or */ @@ -125,10 +353,21 @@ Res TraceFlip(Space space, TraceId ti, RefSet condemned) /* @@@@ This isn't correct if there are higher ranking roots than */ /* data in pools. */ + ss.fix = TraceFix; + ss.zoneShift = SpaceZoneShift(space); + ss.white = trace->white; + ss.summary = RefSetEMPTY; + ss.space = space; + ss.traces = TraceSetSingle(trace->ti); + ss.wasMarked = TRUE; + ss.sig = ScanStateSig; + for(ss.rank = RankAMBIG; ss.rank <= RankEXACT; ++ss.rank) { ring = SpaceRootRing(space); node = RingNext(ring); + AVERT(ScanState, &ss); + while(node != ring) { Ring next = RingNext(node); Root root = RING_ELT(Root, spaceRing, node); @@ -153,45 +392,225 @@ Res TraceFlip(Space space, TraceId ti, RefSet condemned) return ResOK; } -static void TraceReclaim(Space space, TraceId ti) + +static void TraceReclaim(Trace trace) { - Ring node; + Space space; + Seg seg; - node = RingNext(&space->poolRing); - while(node != &space->poolRing) { - Ring next = RingNext(node); - Pool pool = RING_ELT(Pool, spaceRing, node); + AVERT(Trace, trace); + AVER(trace->state == TraceRECLAIM); - if((pool->class->attr & AttrGC) != 0) - PoolReclaim(pool, space, ti); + space = trace->space; + seg = SegFirst(space); + while(seg != NULL) { + Seg next = SegNext(space, seg); - node = next; + /* There shouldn't be any grey stuff left for this trace. */ + AVER(!TraceSetIsMember(seg->grey, trace->ti)); + + if(TraceSetIsMember(seg->white, trace->ti)) { + AVER((seg->pool->class->attr & AttrGC) != 0); + + PoolReclaim(seg->pool, trace, seg); + } + + seg = next; } + + trace->state = TraceFINISHED; } -Size TracePoll(Space space, TraceId ti) + +/* FindGrey -- find a grey segment + * + * This function finds a segment which is grey for any of the traces + * in ts and which does not have a higher rank than any other such + * segment (i.e. a next segment to scan). + * + * This is equivalent to choosing a grey node from the grey set + * of a partition. + * + * @@@@ This must be optimised by using better data structures at + * the cost of some bookkeeping elsewhere, esp. during fix. + */ + +static Bool FindGrey(Seg *segReturn, Rank *rankReturn, + Space space, TraceId ti) +{ + Rank rank; + Seg seg; + + AVER(segReturn != NULL); + AVERT(Space, space); + AVER(TraceIdCheck(ti)); + + for(rank = 0; rank < RankMAX; ++rank) + for(seg = SegFirst(space); seg != NULL; seg = SegNext(space, seg)) + if(RankSetIsMember(seg->rankSet, rank) && + TraceSetIsMember(seg->grey, ti)) { + *segReturn = seg; + *rankReturn = rank; + return TRUE; + } + + return FALSE; +} + + +/* TraceScan -- scan a segment to remove greyness */ + +static Res TraceScan(TraceSet ts, Rank rank, + Space space, Seg seg) { Res res; - Bool finished; - Trace trace; + ScanStateStruct ss; + TraceId ti; - trace = &space->trace[ti]; + AVER(TraceSetCheck(ts)); + AVER(RankCheck(rank)); + AVERT(Seg, seg); + + /* The reason for scanning a segment is that it's grey. */ + AVER(TraceSetInter(ts, seg->grey) != TraceSetEMPTY); - if(trace->condemned != RefSetEMPTY) { - res = TraceRun(space, ti, &finished); - AVER(res == ResOK); /* @@@@ */ - if(finished) { - TraceReclaim(space, ti); - TraceDestroy(space, ti); - return SPACE_POLL_MAX; - } + ss.rank = rank; + ss.traces = ts; + ss.fix = TraceFix; + ss.zoneShift = space->zoneShift; + ss.summary = RefSetEMPTY; + ss.space = space; + ss.wasMarked = TRUE; + ss.white = RefSetEMPTY; + for(ti = 0; ti < TRACE_MAX; ++ti) + if(TraceSetIsMember(ss.traces, ti)) + ss.white = RefSetUnion(ss.white, SpaceTrace(space, ti)->white); + ss.sig = ScanStateSig; + AVERT(ScanState, &ss); + + /* Expose the segment to make sure we can scan it. */ + ShieldExpose(space, seg); + + res = PoolScan(&ss, seg->pool, seg); + if(res != ResOK) { + ShieldCover(space, seg); + return res; } - /* We need to calculate a rate depending on the amount of work */ - /* remaining and the deadline for the collection to finish. */ - return (Size)4096; /* @@@@ */ + ss.sig = SigInvalid; /* just in case */ + + /* The segment has been scanned, so remove the greyness from it. */ + seg->grey = TraceSetDiff(seg->grey, ts); + + /* If the segment is no longer grey for any flipped trace it */ + /* doesn't need to be behind the read barrier. */ + if(TraceSetInter(seg->grey, space->flippedTraces) == TraceSetEMPTY) + ShieldLower(space, seg, AccessREAD | AccessWRITE); + + /* Cover the segment again, now it's been scanned. */ + ShieldCover(space, seg); + + return res; } + +void TraceAccess(Space space, Seg seg, AccessSet mode) +{ + Res res; + + AVERT(Space, space); + AVERT(Seg, seg); + UNUSED(mode); + + /* @@@@ Need to establish what it is necessary to do with the segment. */ + /* At the moment we're assuming that it must be scanned. What about */ + /* write barrier faults? */ + + /* The only reason we protect at the moment is for a read barrier. */ + /* In this case, the segment must be grey for a trace which is */ + /* flipped. */ + AVER(TraceSetInter(seg->grey, space->flippedTraces) != TraceSetEMPTY); + + /* design.mps.poolamc.access.multi */ + res = TraceScan(space->busyTraces, /* @@@@ Should just be flipped traces? */ + RankEXACT, /* @@@@ Surely this is conservative? */ + space, seg); + AVER(res == ResOK); /* design.mps.poolamc.access.error */ + + /* The pool should've done the job of removing the greyness that */ + /* was causing the segment to be protected, so that the mutator */ + /* can go ahead and access it. */ + AVER(TraceSetInter(seg->grey, space->flippedTraces) == TraceSetEMPTY); +} + + +static Res TraceRun(Trace trace) +{ + Res res; + Space space; + Seg seg; + Rank rank; + + AVERT(Trace, trace); + AVER(trace->state == TraceFLIPPED); + + space = trace->space; + + if(FindGrey(&seg, &rank, space, trace->ti)) { + AVER((seg->pool->class->attr & AttrSCAN) != 0); + res = TraceScan(TraceSetSingle(trace->ti), rank, + space, seg); + if(res != ResOK) return res; + } else + trace->state = TraceRECLAIM; + + return ResOK; +} + + +/* TracePoll -- make some progress in tracing + * + * @@@@ This should accept some sort of progress control. + */ + +Res TracePoll(Trace trace) +{ + Space space; + Res res; + + AVERT(Trace, trace); + + space = trace->space; + + switch(trace->state) { + case TraceUNFLIPPED: { + res = TraceFlip(trace); + if(res != ResOK) return res; + } break; + + case TraceFLIPPED: { + res = TraceRun(trace); + if(res != ResOK) return res; + } break; + + case TraceRECLAIM: { + TraceReclaim(trace); + } break; + + case TraceFINISHED: + case TraceINIT: + NOOP; + break; + + default: + NOTREACHED; + break; + } + + return ResOK; +} + + Res TraceFix(ScanState ss, Ref *refIO) { Ref ref; @@ -203,7 +622,7 @@ Res TraceFix(ScanState ss, Ref *refIO) ref = *refIO; if(SegOfAddr(&seg, ss->space, ref)) - if(ss->traceId == seg->condemned) { + if(TraceSetInter(seg->white, ss->traces) != TraceSetEMPTY) { pool = seg->pool; return PoolFix(pool, ss, seg, refIO); } @@ -211,11 +630,12 @@ Res TraceFix(ScanState ss, Ref *refIO) return ResOK; } -/* == Scan Area == + +/* TraceScanArea -- scan contiguous area of references * - * This is a convenience function for scanning the contiguous area - * [base, limit). i.e. it calls fix on all words from base up - * to limit, inclusive of base and exclusive of limit. + * This is a convenience function for scanning the contiguous area + * [base, limit). i.e. it calls fix on all words from base up + * to limit, inclusive of base and exclusive of limit. */ Res TraceScanArea(ScanState ss, Addr *base, Addr *limit) @@ -244,10 +664,11 @@ Res TraceScanArea(ScanState ss, Addr *base, Addr *limit) return ResOK; } -/* == Scan Area Tagged == + +/* TraceScanAreaTagged -- scan contiguous area of tagged references * - * This is as TraceScanArea except words are only fixed if they - * are multiples of four. i.e. look like 4-byte aligned pointers. + * This is as TraceScanArea except words are only fixed if they + * are multiples of four. i.e. look like 4-byte aligned pointers. */ Res TraceScanAreaTagged(ScanState ss, Addr *base, Addr *limit) @@ -277,57 +698,3 @@ Res TraceScanAreaTagged(ScanState ss, Addr *base, Addr *limit) return ResOK; } - -Res TraceRun(Space space, TraceId ti, Bool *finishedReturn) -{ - Res res; - ScanStateStruct ss; - - AVERT(Space, space); - AVER(finishedReturn != NULL); - - ss.fix = TraceFix; - ss.zoneShift = space->zoneShift; - ss.condemned = space->trace[ti].condemned; - ss.summary = RefSetEMPTY; - ss.space = space; - ss.traceId = ti; - ss.sig = ScanStateSig; - - for(ss.rank = 0; ss.rank < RankMAX; ++ss.rank) { - Ring ring; - Ring node; - - if(ss.rank == RankWEAK) { - ss.weakSplat = (Addr)0; - } else { - ss.weakSplat = (Addr)0xadd4badd; - } - - ring = SpacePoolRing(space); - node = RingNext(ring); - - while(node != ring) { - Ring next = RingNext(node); - Pool pool = RING_ELT(Pool, spaceRing, node); - Bool finished; - - if((pool->class->attr & AttrSCAN) != 0) { - res = PoolScan(&ss, pool, &finished); - if(res != ResOK) return res; - - if(!finished) { - *finishedReturn = FALSE; - return ResOK; - } - } - - node = next; - } - } - - ss.sig = SigInvalid; /* just in case */ - - *finishedReturn = TRUE; - return ResOK; -} diff --git a/mps/src/vman.c b/mps/src/vman.c index 5072fa3fc61..9275b895491 100644 --- a/mps/src/vman.c +++ b/mps/src/vman.c @@ -1,7 +1,7 @@ /* impl.c.vman: ANSI VM: MALLOC-BASED PSUEDO MEMORY MAPPING * - * $HopeName: MMsrc!vman.c(trunk.13) $ - * Copyright (C) 1996,1997 Harlequin Group, all rights reserved. + * $HopeName: MMsrc!vman.c(MMdevel_action2.2) $ + * Copyright (C) 1997 The Harlequin Group Limited. All rights reserved. */ #include "mpm.h" @@ -13,7 +13,7 @@ #include /* for malloc and free */ #include /* for memset */ -SRCID(vman, "$HopeName: MMsrc!vman.c(trunk.13) $"); +SRCID(vman, "$HopeName: MMsrc!vman.c(MMdevel_action2.2) $"); #define SpaceVM(_space) (&(_space)->arenaStruct.vmStruct) @@ -58,7 +58,7 @@ Res VMCreate(Space *spaceReturn, Size size, Addr base) vm->block = malloc((Size)(size + VMAN_ALIGN)); if(vm->block == NULL) { - free(vm); + free(space); return ResMEMORY; } diff --git a/mps/src/w3almv.nmk b/mps/src/w3almv.nmk index f5febdf04e9..e7eee964806 100644 --- a/mps/src/w3almv.nmk +++ b/mps/src/w3almv.nmk @@ -1,9 +1,10 @@ -# ==== NTI3MV NMAKE FILE ==== +# ==== NTALMV NMAKE FILE ==== # -# $HopeName: MMsrc!ntalmv.nmk(trunk.8) $ +# $HopeName: MMsrc!ntalmv.nmk(trunk.9) $ # # Copyright (C) 1995 Harlequin Group, all rights reserved # + PFM = ntalmv PFMDEFS = /DWIN32 /D_WINDOWS @@ -11,12 +12,13 @@ MPM = \ \ \ \ - + SW = \ \ \ \ - + \ + AMC = LO = MRG = diff --git a/mps/src/w3i3mv.nmk b/mps/src/w3i3mv.nmk index 1837efa7c62..b1d21c36b68 100644 --- a/mps/src/w3i3mv.nmk +++ b/mps/src/w3i3mv.nmk @@ -1,6 +1,6 @@ # ==== NTI3MV NMAKE FILE ==== # -# $HopeName: MMsrc!nti3mv.nmk(trunk.30) $ +# $HopeName: MMsrc!nti3mv.nmk(trunk.31) $ # # Copyright (C) 1995,1996,1997 Harlequin Group, all rights reserved # @@ -11,12 +11,14 @@ MPM = \ \ \ \ - + \ + SW = \ \ \ \ - + \ + AMC = LO = MRG = diff --git a/mps/src/w3ppmv.nmk b/mps/src/w3ppmv.nmk index 591e9cd1b26..919bc241532 100644 --- a/mps/src/w3ppmv.nmk +++ b/mps/src/w3ppmv.nmk @@ -1,6 +1,6 @@ -# ==== NTI3MV NMAKE FILE ==== +# ==== NTPPMV NMAKE FILE ==== # -# $HopeName: MMsrc!ntppmv.nmk(trunk.8) $ +# $HopeName: MMsrc!ntppmv.nmk(trunk.9) $ # # Copyright (C) 1995 Harlequin Group, all rights reserved # @@ -11,12 +11,14 @@ MPM = \ \ \ \ - + \ + SW = \ \ \ \ - + \ + AMC = LO = MRG =