diff --git a/mps/code/buffer.c b/mps/code/buffer.c index 2e2ed0bc458..bd2f78e7752 100644 --- a/mps/code/buffer.c +++ b/mps/code/buffer.c @@ -30,10 +30,6 @@ SRCID(buffer, "$Id$"); -/* forward declarations */ -static void BufferFrameNotifyPopPending(Buffer buffer); - - /* BufferCheck -- check consistency of a buffer * * See .ap.async. */ @@ -52,15 +48,6 @@ Bool BufferCheck(Buffer buffer) CHECKL(buffer->emptySize <= buffer->fillSize); CHECKL(buffer->alignment == buffer->pool->alignment); CHECKL(AlignCheck(buffer->alignment)); - CHECKL(BoolCheck(buffer->ap_s._enabled)); - - if (buffer->ap_s._enabled) { - /* no useful check for frameptr - mutator may be updating it */ - CHECKL(BoolCheck(buffer->ap_s._lwpoppending)); - } else { - CHECKL(buffer->ap_s._lwpoppending == FALSE); - CHECKL(buffer->ap_s._frameptr == NULL); - } /* If any of the buffer's fields indicate that it is reset, make */ /* sure it is really reset. Otherwise, check various properties */ @@ -81,8 +68,6 @@ Bool BufferCheck(Buffer buffer) /* Nothing reliable to check for lightweight frame state */ CHECKL(buffer->poolLimit == (Addr)0); } else { - Addr aplimit; - /* The buffer is attached to a region of memory. */ /* Check consistency. */ CHECKL(buffer->mode & BufferModeATTACHED); @@ -101,14 +86,6 @@ Bool BufferCheck(Buffer buffer) CHECKL(AddrIsAligned(buffer->ap_s.limit, buffer->alignment)); CHECKL(AddrIsAligned(buffer->poolLimit, buffer->alignment)); - /* .lwcheck: If LW frames are enabled, the buffer may become */ - /* trapped asynchronously. It can't become untrapped */ - /* asynchronously, though. See . */ - /* Read a snapshot value of the limit field. Use this to determine */ - /* if we are trapped, and to permit more useful checking when not */ - /* yet trapped. */ - aplimit = buffer->ap_s.limit; - /* If the buffer isn't trapped then "limit" should be the limit */ /* set by the owning pool. Otherwise, "init" is either at the */ /* same place it was at flip (.commit.before) or has been set */ @@ -119,12 +96,10 @@ Bool BufferCheck(Buffer buffer) /* request.dylan.170429.sol.zero_). */ /* .. _request.dylan.170429.sol.zero: https://info.ravenbrook.com/project/mps/import/2001-11-05/mmprevol/request/dylan/170429 */ - if ((buffer->ap_s._enabled && aplimit == (Addr)0) /* see .lwcheck */ - || (!buffer->ap_s._enabled && BufferIsTrapped(buffer))) { + if (BufferIsTrapped(buffer)) { /* .check.use-trapped: This checking function uses BufferIsTrapped, */ /* So BufferIsTrapped can't do checking as that would cause an */ /* infinite loop. */ - CHECKL(aplimit == (Addr)0); if (buffer->mode & BufferModeFLIPPED) { CHECKL(buffer->ap_s.init == buffer->initAtFlip || buffer->ap_s.init == buffer->ap_s.alloc); @@ -133,7 +108,6 @@ Bool BufferCheck(Buffer buffer) } /* Nothing special to check in the logged mode. */ } else { - CHECKL(aplimit == buffer->poolLimit); /* see .lwcheck */ CHECKL(buffer->initAtFlip == (Addr)0); } } @@ -230,9 +204,6 @@ static Res BufferInit(Buffer buffer, BufferClass class, buffer->ap_s.init = (mps_addr_t)0; buffer->ap_s.alloc = (mps_addr_t)0; buffer->ap_s.limit = (mps_addr_t)0; - buffer->ap_s._frameptr = NULL; - buffer->ap_s._enabled = FALSE; - buffer->ap_s._lwpoppending = FALSE; buffer->poolLimit = (Addr)0; buffer->rampCount = 0; @@ -319,8 +290,6 @@ void BufferDetach(Buffer buffer, Pool pool) /* Ask the owning pool to do whatever it needs to before the */ /* buffer is detached (e.g. copy buffer state into pool state). */ (*pool->class->bufferEmpty)(pool, buffer, init, limit); - /* Use of lightweight frames must have been disabled by now */ - AVER(BufferFrameState(buffer) == BufferFrameDISABLED); /* run any class-specific detachment method */ buffer->class->detach(buffer); @@ -346,7 +315,6 @@ void BufferDetach(Buffer buffer, Pool pool) buffer->poolLimit = (Addr)0; buffer->mode &= ~(BufferModeATTACHED|BufferModeFLIPPED|BufferModeTRANSITION); - BufferFrameSetState(buffer, BufferFrameDISABLED); EVENT2(BufferEmpty, buffer, spare); } @@ -383,11 +351,6 @@ void BufferFinish(Buffer buffer) AVER(BufferIsReady(buffer)); - /* */ - if (BufferIsTrappedByMutator(buffer)) { - BufferFrameNotifyPopPending(buffer); - } - BufferDetach(buffer, pool); /* Dispatch to the buffer class method to perform any */ @@ -463,44 +426,6 @@ static void BufferSetUnflipped(Buffer buffer) } -/* BufferFrameState - * - * Returns the frame state of a buffer. See - * . */ - -FrameState BufferFrameState(Buffer buffer) -{ - AVERT(Buffer, buffer); - if (buffer->ap_s._enabled) { - if (buffer->ap_s._lwpoppending) { - return BufferFramePOP_PENDING; - } else { - AVER(buffer->ap_s._frameptr == NULL); - return BufferFrameVALID; - } - } else { - AVER(buffer->ap_s._frameptr == NULL); - AVER(buffer->ap_s._lwpoppending == FALSE); - return BufferFrameDISABLED; - } -} - - -/* BufferFrameSetState - * - * Sets the frame state of a buffer. Only the mutator may set the - * PopPending state. See . */ - -void BufferFrameSetState(Buffer buffer, FrameState state) -{ - AVERT(Buffer, buffer); - AVER(state == BufferFrameVALID || state == BufferFrameDISABLED); - buffer->ap_s._frameptr = NULL; - buffer->ap_s._lwpoppending = FALSE; - buffer->ap_s._enabled = (state == BufferFrameVALID); -} - - /* BufferSetAllocAddr * * Sets the init & alloc pointers of a buffer. */ @@ -518,32 +443,6 @@ void BufferSetAllocAddr(Buffer buffer, Addr addr) } -/* BufferFrameNotifyPopPending - * - * Notifies the pool when a lightweight frame pop operation has been - * deferred and needs to be processed. See - * . */ - -static void BufferFrameNotifyPopPending(Buffer buffer) -{ - AllocFrame frame; - Pool pool; - AVER(BufferIsTrappedByMutator(buffer)); - AVER(BufferFrameState(buffer) == BufferFramePOP_PENDING); - frame = (AllocFrame)buffer->ap_s._frameptr; - /* Unset PopPending state & notify the pool */ - BufferFrameSetState(buffer, BufferFrameVALID); - /* If the frame is no longer trapped, undo the trap by resetting */ - /* the AP limit pointer */ - if (!BufferIsTrapped(buffer)) { - buffer->ap_s.limit = buffer->poolLimit; - } - pool = BufferPool(buffer); - (*pool->class->framePopPending)(pool, buffer, frame); -} - - - /* BufferFramePush * * See . */ @@ -555,17 +454,12 @@ Res BufferFramePush(AllocFrame *frameReturn, Buffer buffer) AVER(frameReturn != NULL); - /* Process any flip or PopPending */ + /* Process any flip */ if (!BufferIsReset(buffer) && buffer->ap_s.limit == (Addr)0) { /* .fill.unflip: If the buffer is flipped then we unflip the buffer. */ if (buffer->mode & BufferModeFLIPPED) { BufferSetUnflipped(buffer); } - - /* check for PopPending */ - if (BufferIsTrappedByMutator(buffer)) { - BufferFrameNotifyPopPending(buffer); - } } pool = BufferPool(buffer); return (*pool->class->framePush)(frameReturn, pool, buffer); @@ -702,11 +596,6 @@ Res BufferFill(Addr *pReturn, Buffer buffer, Size size, BufferSetUnflipped(buffer); } - /* */ - if (BufferIsTrappedByMutator(buffer)) { - BufferFrameNotifyPopPending(buffer); - } - /* .fill.logged: If the buffer is logged then we leave it logged. */ next = AddrAdd(buffer->ap_s.alloc, size); if (next > (Addr)buffer->ap_s.alloc && @@ -807,8 +696,6 @@ Bool BufferTrip(Buffer buffer, Addr p, Size size) AVER(buffer->ap_s.limit == 0); /* Of course we should be trapped. */ AVER(BufferIsTrapped(buffer)); - /* But the mutator shouldn't have caused the trap */ - AVER(!BufferIsTrappedByMutator(buffer)); /* The init and alloc fields should be equal at this point, because */ /* the step .commit.update has happened. */ @@ -955,21 +842,7 @@ void BufferReassignSeg(Buffer buffer, Seg seg) Bool BufferIsTrapped(Buffer buffer) { /* Can't check buffer, see .check.use-trapped */ - return BufferIsTrappedByMutator(buffer) - || ((buffer->mode & (BufferModeFLIPPED|BufferModeLOGGED)) != 0); -} - - -/* BufferIsTrappedByMutator - * - * Indicates whether the mutator trapped the buffer. See - * and .ap.async. */ - -Bool BufferIsTrappedByMutator(Buffer buffer) -{ - AVER(!buffer->ap_s._lwpoppending || buffer->ap_s._enabled); - /* Can't check buffer, see .check.use-trapped */ - return buffer->ap_s._lwpoppending; + return (buffer->mode & (BufferModeFLIPPED|BufferModeLOGGED)) != 0; } diff --git a/mps/code/mpm.h b/mps/code/mpm.h index e5c11897a1f..b53acf252eb 100644 --- a/mps/code/mpm.h +++ b/mps/code/mpm.h @@ -273,8 +273,6 @@ extern Res PoolNoFramePush(AllocFrame *frameReturn, Pool pool, Buffer buf); extern Res PoolTrivFramePush(AllocFrame *frameReturn, Pool pool, Buffer buf); extern Res PoolNoFramePop(Pool pool, Buffer buf, AllocFrame frame); extern Res PoolTrivFramePop(Pool pool, Buffer buf, AllocFrame frame); -extern void PoolNoFramePopPending(Pool pool, Buffer buf, AllocFrame frame); -extern void PoolTrivFramePopPending(Pool pool, Buffer buf, AllocFrame frame); extern Res PoolNoAddrObject(Addr *pReturn, Pool pool, Seg seg, Addr addr); extern void PoolNoWalk(Pool pool, Seg seg, FormattedObjectsVisitor f, void *p, size_t s); @@ -800,7 +798,6 @@ extern Addr BufferScanLimit(Buffer buffer); extern void BufferReassignSeg(Buffer buffer, Seg seg); extern Bool BufferIsTrapped(Buffer buffer); -extern Bool BufferIsTrappedByMutator(Buffer buffer); extern void BufferRampBegin(Buffer buffer, AllocPattern pattern); extern Res BufferRampEnd(Buffer buffer); diff --git a/mps/code/mpmst.h b/mps/code/mpmst.h index ac59492bea5..bf3de9a8916 100644 --- a/mps/code/mpmst.h +++ b/mps/code/mpmst.h @@ -74,7 +74,6 @@ typedef struct mps_pool_class_s { PoolRampEndMethod rampEnd; /* end a ramp pattern */ PoolFramePushMethod framePush; /* push an allocation frame */ PoolFramePopMethod framePop; /* pop an allocation frame */ - PoolFramePopPendingMethod framePopPending; /* notify pending pop */ PoolAddrObjectMethod addrObject; /* find client pointer to object */ PoolWalkMethod walk; /* walk over a segment */ PoolFreeWalkMethod freewalk; /* walk over free blocks */ diff --git a/mps/code/mpmtypes.h b/mps/code/mpmtypes.h index c59b32adef5..6989ded5d8d 100644 --- a/mps/code/mpmtypes.h +++ b/mps/code/mpmtypes.h @@ -226,8 +226,6 @@ typedef Res (*PoolFramePushMethod)(AllocFrame *frameReturn, Pool pool, Buffer buf); typedef Res (*PoolFramePopMethod)(Pool pool, Buffer buf, AllocFrame frame); -typedef void (*PoolFramePopPendingMethod)(Pool pool, Buffer buf, - AllocFrame frame); typedef Res (*PoolAddrObjectMethod)(Addr *pReturn, Pool pool, Seg seg, Addr addr); typedef void (*PoolWalkMethod)(Pool pool, Seg seg, FormattedObjectsVisitor f, @@ -321,14 +319,6 @@ enum { #define BufferModeTRANSITION ((BufferMode)(1<<3)) -/* Buffer frame states. See */ -enum { - BufferFrameVALID = 1, - BufferFramePOP_PENDING, - BufferFrameDISABLED -}; - - /* Rank constants -- see */ /* These definitions must match . */ /* This is checked by . */ diff --git a/mps/code/mps.h b/mps/code/mps.h index fc3d4c62fb9..3298b6ccdc1 100644 --- a/mps/code/mps.h +++ b/mps/code/mps.h @@ -305,9 +305,6 @@ typedef struct mps_ap_s { /* allocation point descriptor */ mps_addr_t init; /* limit of initialized memory */ mps_addr_t alloc; /* limit of allocated memory */ mps_addr_t limit; /* limit of available memory */ - mps_addr_t _frameptr; /* lightweight frame pointer */ - mps_bool_t _enabled; /* lightweight frame status */ - mps_bool_t _lwpoppending; /* lightweight pop pending? */ } mps_ap_s; diff --git a/mps/code/mpsi.c b/mps/code/mpsi.c index 96b1b6937f7..4ce28a48626 100644 --- a/mps/code/mpsi.c +++ b/mps/code/mpsi.c @@ -950,7 +950,7 @@ mps_res_t (mps_ap_frame_push)(mps_frame_t *frame_o, mps_ap_t mps_ap) return MPS_RES_FAIL; } - if (!mps_ap->_lwpoppending && mps_ap->init < mps_ap->limit) { + if (mps_ap->init < mps_ap->limit) { /* Valid state for a lightweight push */ *frame_o = (mps_frame_t)mps_ap->init; return MPS_RES_OK; @@ -996,14 +996,12 @@ mps_res_t (mps_ap_frame_pop)(mps_ap_t mps_ap, mps_frame_t frame) buf = BufferOfAP(mps_ap); AVER(TESTT(Buffer, buf)); - if (mps_ap->_enabled - && BufferBase(buf) <= (Addr)frame + /* FIXME: is it thread-safe to read BufferBase here? */ + if (BufferBase(buf) <= (Addr)frame && (mps_addr_t)frame < mps_ap->init) { - /* Lightweight pop to address in same buffer */ - mps_ap->_frameptr = (mps_addr_t)frame; /* record pending pop */ - mps_ap->_lwpoppending = TRUE; - mps_ap->limit = (mps_addr_t)0; /* trap the buffer */ + /* Lightweight pop to earlier address in same buffer */ + mps_ap->init = mps_ap->alloc = (mps_addr_t)frame; return MPS_RES_OK; } else { diff --git a/mps/code/pool.c b/mps/code/pool.c index bbdacc68616..b9033d0003c 100644 --- a/mps/code/pool.c +++ b/mps/code/pool.c @@ -65,7 +65,6 @@ Bool PoolClassCheck(PoolClass class) CHECKL(FUNCHECK(class->rampEnd)); CHECKL(FUNCHECK(class->framePush)); CHECKL(FUNCHECK(class->framePop)); - CHECKL(FUNCHECK(class->framePopPending)); CHECKL(FUNCHECK(class->addrObject)); CHECKL(FUNCHECK(class->walk)); CHECKL(FUNCHECK(class->freewalk)); diff --git a/mps/code/poolabs.c b/mps/code/poolabs.c index 712f24152e5..b21d83b15ab 100644 --- a/mps/code/poolabs.c +++ b/mps/code/poolabs.c @@ -57,7 +57,6 @@ void PoolClassMixInBuffer(PoolClass class) /* By default, buffered pools treat frame operations as NOOPs */ class->framePush = PoolTrivFramePush; class->framePop = PoolTrivFramePop; - class->framePopPending = PoolTrivFramePopPending; class->bufferClass = BufferClassGet; } @@ -138,7 +137,6 @@ DEFINE_CLASS(AbstractPoolClass, class) class->rampEnd = PoolNoRampEnd; class->framePush = PoolNoFramePush; class->framePop = PoolNoFramePop; - class->framePopPending = PoolNoFramePopPending; class->addrObject = PoolNoAddrObject; class->walk = PoolNoWalk; class->freewalk = PoolTrivFreeWalk; @@ -598,16 +596,6 @@ Res PoolNoFramePop(Pool pool, Buffer buf, AllocFrame frame) } -void PoolNoFramePopPending(Pool pool, Buffer buf, AllocFrame frame) -{ - AVERT(Pool, pool); - AVERT(Buffer, buf); - /* frame is of an abstract type & can't be checked */ - UNUSED(frame); - NOTREACHED; -} - - Res PoolTrivFramePush(AllocFrame *frameReturn, Pool pool, Buffer buf) { AVER(frameReturn != NULL); @@ -627,16 +615,6 @@ Res PoolTrivFramePop(Pool pool, Buffer buf, AllocFrame frame) } -void PoolTrivFramePopPending(Pool pool, Buffer buf, AllocFrame frame) -{ - AVERT(Pool, pool); - AVERT(Buffer, buf); - /* frame is of an abstract type & can't be checked */ - UNUSED(frame); - NOOP; -} - - Res PoolNoAddrObject(Addr *pReturn, Pool pool, Seg seg, Addr addr) { AVER(pReturn != NULL); diff --git a/mps/code/poolsnc.c b/mps/code/poolsnc.c index 05d2875f2f6..25d0ae1de38 100644 --- a/mps/code/poolsnc.c +++ b/mps/code/poolsnc.c @@ -462,8 +462,6 @@ found: AVERT(Seg, seg); /* put the segment on the buffer chain */ sncRecordAllocatedSeg(buffer, seg); - /* Permit the use of lightweight frames - .lw-frame-state */ - BufferFrameSetState(buffer, BufferFrameVALID); *baseReturn = SegBase(seg); *limitReturn = SegLimit(seg); return ResOK; @@ -485,9 +483,6 @@ static void SNCBufferEmpty(Pool pool, Buffer buffer, AVER(SegLimit(seg) == limit); snc = PoolSNC(pool); AVERT(SNC, snc); - AVER(BufferFrameState(buffer) == BufferFrameVALID); - /* .lw-frame-state */ - BufferFrameSetState(buffer, BufferFrameDISABLED); arena = BufferArena(buffer); @@ -503,7 +498,7 @@ static void SNCBufferEmpty(Pool pool, Buffer buffer, /* SNCScanLimit -- limit of scannable objects in segment */ -static Addr SNCScanLimit(Arena arena, Seg seg) +static Addr SNCScanLimit(Seg seg) { Addr limit; Buffer buf; @@ -511,27 +506,9 @@ static Addr SNCScanLimit(Arena arena, Seg seg) if (buf == NULL) { /* Segment is unbuffered: entire segment scannable */ limit = SegLimit(seg); - } else if (BufferFrameState(buf) != BufferFramePOP_PENDING) { - /* No pop pending: scannable up to limit of initialized objects. */ - limit = BufferScanLimit(buf); } else { - Addr addr = (Addr)buf->ap_s._frameptr; - if (addr == NULL) { - /* Pop pending to bottom of stack */ - limit = BufferBase(buf); - } else { - Seg popSeg; - Bool foundSeg = SegOfAddr(&popSeg, arena, addr); - AVER(foundSeg); - if (popSeg == seg) { - /* Pop pending to address in same segment */ - AVER(addr <= BufferScanLimit(buf)); /* check direction of pop */ - limit = addr; - } else { - /* Pop pending to address in different segment */ - limit = BufferBase(buf); - } - } + /* Segment is buffered: scannable up to limit of initialized objects. */ + limit = BufferScanLimit(buf); } return limit; } @@ -553,7 +530,7 @@ static Res SNCScan(Bool *totalReturn, ScanState ss, Pool pool, Seg seg) format = pool->format; base = SegBase(seg); - limit = SNCScanLimit(PoolArena(pool), seg); + limit = SNCScanLimit(seg); if (base < limit) { res = (*format->scan)(&ss->ss_s, base, limit); @@ -575,16 +552,11 @@ static Res SNCScan(Bool *totalReturn, ScanState ss, Pool pool, Seg seg) static Res SNCFramePush(AllocFrame *frameReturn, Pool pool, Buffer buf) { - FrameState state; AVER(frameReturn != NULL); AVERT(Pool, pool); AVERT(Buffer, buf); - state = BufferFrameState(buf); - /* Should have been notified of pending pops before this */ - AVER(state == BufferFrameVALID || state == BufferFrameDISABLED); - if (state == BufferFrameDISABLED) { - AVER(BufferIsReset(buf)); /* The buffer must be reset */ + if (BufferIsReset(buf)) { AVER(sncBufferTopSeg(buf) == NULL); /* The stack must be empty */ /* Use NULL to indicate an empty stack. .lw-frame-null */ *frameReturn = NULL; @@ -609,7 +581,7 @@ static Res SNCFramePush(AllocFrame *frameReturn, Pool pool, Buffer buf) } -static void SNCFramePopPending(Pool pool, Buffer buf, AllocFrame frame) +static Res SNCFramePop(Pool pool, Buffer buf, AllocFrame frame) { Addr addr; SNC snc; @@ -618,8 +590,6 @@ static void SNCFramePopPending(Pool pool, Buffer buf, AllocFrame frame) /* frame is an Addr and can't be directly checked */ snc = PoolSNC(pool); AVERT(SNC, snc); - - AVER(BufferFrameState(buf) == BufferFrameVALID); if (frame == NULL) { /* corresponds to a pop to bottom of stack. .lw-frame-null */ @@ -646,19 +616,9 @@ static void SNCFramePopPending(Pool pool, Buffer buf, AllocFrame frame) BufferDetach(buf, pool); sncPopPartialSegChain(snc, buf, seg); BufferAttach(buf, SegBase(seg), SegLimit(seg), addr, (Size)0); - /* Permit the use of lightweight frames - .lw-frame-state */ - BufferFrameSetState(buf, BufferFrameVALID); } } -} - -static Res SNCFramePop(Pool pool, Buffer buf, AllocFrame frame) -{ - AVERT(Pool, pool); - AVERT(Buffer, buf); - BufferFrameSetState(buf, BufferFrameVALID); - SNCFramePopPending(pool, buf, frame); return ResOK; } @@ -683,7 +643,7 @@ static void SNCWalk(Pool pool, Seg seg, FormattedObjectsVisitor f, snc = PoolSNC(pool); AVERT(SNC, snc); format = pool->format; - limit = SNCScanLimit(PoolArena(pool), seg); + limit = SNCScanLimit(seg); while(object < limit) { (*f)(object, format, pool, p, s); @@ -759,7 +719,6 @@ DEFINE_POOL_CLASS(SNCPoolClass, this) this->scan = SNCScan; this->framePush = SNCFramePush; this->framePop = SNCFramePop; - this->framePopPending = SNCFramePopPending; this->walk = SNCWalk; this->bufferClass = SNCBufClassGet; this->totalSize = SNCTotalSize; diff --git a/mps/design/alloc-frame.txt b/mps/design/alloc-frame.txt index 9da25ed5b37..2275c09746d 100644 --- a/mps/design/alloc-frame.txt +++ b/mps/design/alloc-frame.txt @@ -170,11 +170,11 @@ as parameters. _`.op.obligatory`: The following operations are supported on any allocation point which supports allocation frames:- -_`.operation.push`: The ``PushFrame()`` operation creates a new +_`.operation.push`: The *FramePush* operation creates a new allocation frame of the currently chosen frame class, makes this new frame the current frame, and returns a handle for the frame. -_`.operation.pop`: The ``PopFrame()`` operation takes a frame handle +_`.operation.pop`: The *FramePop* operation takes a frame handle as a parameter. Some pool classes might insist or assume that this is the handle for the current frame. It finds the parent of that frame and makes it the current frame. The operation indicates that all @@ -190,23 +190,23 @@ allocation frames, but not all. Pools may choose to support some or all of these operations for certain frame classes. An unsupported operation will return a failure value:- -_`.operation.select`: The ``SelectFrame()`` operation takes a frame +_`.operation.select`: The *FrameSelect* operation takes a frame handle as a parameter and makes that frame the current frame. It does not indicate that any children of the current frame contain objects which are likely to be dead. -_`.operation.select-addr`: The ``SelectFrameOfAddr()`` operation takes +_`.operation.select-addr`: The *FrameSelectOfAddr* operation takes an address as a parameter and makes the frame of that address the current frame. It does not indicate that any children of the current frame contain objects which are likely to be dead. -_`.operation.in-frame`: The ``AddrInFrame()`` operation determines +_`.operation.in-frame`: The *FrameHasAddr()* operation determines whether the supplied address is the address of an object allocated in the supplied frame, or any child of that frame. -_`.operation.set`: The ``SetFrameClass()`` operation takes a frame +_`.operation.set`: The *SetFrameClass* operation takes a frame class and an allocation point as parameters, and makes that the -current frame class for the allocation point. The next ``PushFrame()`` +current frame class for the allocation point. The next *FramePush* operation will create a new frame of that class. @@ -231,32 +231,32 @@ External functions .................. _`.fn.client.push`: ``mps_ap_frame_push()`` is used by clients to -invoke the ``PushFrame()`` operation. For lightweight frames, this +invoke the *FramePush* operation. For lightweight frames, this might not invoke the corresponding internal function. _`.fn.client.pop`: ``mps_ap_frame_pop()`` is used by clients to invoke -the ``PopFrame()`` operation. For lightweight frames, this might not +the *FramePop* operation. For lightweight frames, this might not invoke the corresponding internal function. ``mps_res_t mps_ap_frame_select(mps_ap_t buf, mps_frame_t frame)`` _`.fn.client.select`: This following function is used by clients to -invoke the ``SelectFrame()`` operation. +invoke the *FrameSelect* operation. ``mps_res_t mps_ap_frame_select_from_addr(mps_ap_t buf, mps_addr_t addr)`` _`.fn.client.select-addr`: This function is used by clients to invoke -the ``SelectFrameOfAddr()`` operation. +the *FrameSelectOfAddr* operation. ``mps_res_t mps_ap_addr_in_frame(mps_bool_t *inframe_o, mps_ap_t buf, mps_addr_t *addrref, mps_frame_t frame)`` _`.fn.client.in-frame`: This function is used by clients to invoke the -``AddrInFrame()`` operation. +*FrameHasAddr()* operation. ``mps_res_t mps_ap_set_frame_class(mps_ap_t buf, mps_frame_class_t class)`` _`.fn.client.set`: This function is used by clients to invoke the -``SetFrameClass()`` operation. +*SetFrameClass* operation. ``mps_frame_class_t mps_alloc_frame_class_stack(void)`` @@ -278,32 +278,32 @@ _`.type.frame-class`: Frame classes are defined as an abstract type. ``typedef Res (*PoolFramePushMethod)(AllocFrame *frameReturn, Pool pool, Buffer buf)`` _`.fn.push`: A pool method of this type is called (if needed) to -invoke the ``PushFrame()`` operation. +invoke the *FramePush* operation. ``typedef Res (*PoolFramePopMethod)(Pool pool, Buffer buf, AllocFrame frame)`` _`.fn.pop`: A pool method of this type is called (if needed) -to invoke the PopFrame operation: +to invoke the *FramePop* operation: ``typedef Res (*PoolFrameSelectMethod)(Pool pool, Buffer buf, AllocFrame frame)`` _`.fn.select`: A pool method of this type is called to invoke the -``SelectFrame()`` operation. +*FrameSelect* operation. ``typedef Res (*PoolFrameSelectFromAddrMethod)(Pool pool, Buffer buf, Addr addr)`` _`.fn.select-addr`: A pool method of this type is called to invoke the -``SelectFrameOfAddr()`` operation. +*FrameSelectOfAddr* operation. -``typedef Res (*PoolAddrInFrameMethod)(Bool *inframeReturn, Pool pool, Seg seg, Addr *addrref, AllocFrame frame)`` +``typedef Res (*PoolFrameHasAddrMethod)(Bool *inframeReturn, Pool pool, Seg seg, Addr *addrref, AllocFrame frame)`` _`.fn.in-frame`: A pool method of this type is called to invoke the -``AddrInFrame()`` operation. +*FrameHasAddr()* operation. ``typedef Res (*PoolSetFrameClassMethod)(Pool pool, Buffer buf, AllocFrameClass class)`` _`.fn.set`: A pool method of this type is called to invoke the -``SetFrameClass()`` operation. +*SetFrameClass* operation. Lightweight frames @@ -313,96 +313,23 @@ Overview ........ _`.lw-frame.overview`: Allocation points provide direct support for -lightweight frames, and are designed to permit PushFrame and PopFrame -operations without the need for locking and delegation to the pool -method. Pools can disable this mechanism for any allocation point, so -that the pool method is always called. The pool method will be called -whenever synchronization is required for other reasons (e.g. the -buffer is tripped). +lightweight frames, and are designed to permit *FramePush* and +*FramePop* operations without the need for locking and delegation to +the pool method. The pool method will be called whenever +synchronization is required for other reasons (e.g. the buffer is +tripped). _`.lw-frame.model`: Lightweight frames offer direct support for a -particular model of allocation frame use, whereby the PushFrame +particular model of allocation frame use, whereby the *FramePush* operation returns the current allocation pointer as a frame handle, -and the PopFrame operation causes the allocation pointer to be reset +and the *FramePop* operation causes the allocation pointer to be reset to the address of the frame handle. This model should be suitable for -simple stack frames, where more advanced operations like SelectFrame +simple stack frames, where more advanced operations like *FrameSelect* are not supported. It may also be suitable for more advanced allocation frame models when they are being used simply. The use of a complex operation always involves synchronization via locking, and the pool may disable lightweight synchronization temporarily at this time. -State -..... - -_`.lw-frame.states`: Allocation points supporting lightweight frames -will be in one of the following states: - -============ ================================================================ -Valid Indicates that ``PushFrame()`` can be a lightweight - operation and need not be synchronized. -PopPending Indicates that there has been a ``PopFrame()`` operation - that the pool must respond to. -Disabled Indicates that the pool has disabled support for lightweight - operations for this AP. -============ ================================================================ - -These states are in addition to the state normally held by an AP for -allocation purposes. An AP will be in the Disabled state at creation. - -_`.lw-frame.transitions`: State transitions happen under the following -circumstances: - -======================= ==================================================== -Valid → PopPending As a result of a client ``PopFrame()`` - operation. -Valid → Disabled At the choice of the pool (for example, when - responding to a ``SelectFrame()`` operation). -PopPending → Valid At the choice of the pool, when processing a - ``PopFrame()``. -PopPending → Disabled At the choice of the pool, when processing a - ``PopFrame()``. -Disabled → Valid At the choice of the pool. -Disabled → Popframe Illegal. -======================= ==================================================== - -_`.lw-frame.state-impl`: Each AP contains 3 additional fields to hold this state:: - - mps_addr_t frameptr; - mps_bool_t enabled; - mps_bool_t lwPopPending; - -_`.lw-frame.enabled`: The ``enabled`` slot holds the following values for -each state: - -========== ========== -Valid ``TRUE`` -PopPending ``TRUE`` -Disabled ``FALSE`` -========== ========== - -_`.lw-frame.frameptr`: The ``frameptr`` slot holds the following values -for each state: - -========== ============================================ -Valid ``NULL`` -PopPending Frame handle for most recently popped frame. -Disabled ``NULL`` -========== ============================================ - -_`.lw-frame.lwPopPending`: The ``lwPopPending`` slot holds the -following values for each state: - -========== ========= -Valid ``FALSE`` -PopPending ``TRUE`` -Disabled ``FALSE`` -========== ========= - -_`.lw-frame.state-for-gc`: It is not necessary for the tracer, format -code, pool, or any other part of the GC support in MPS to read either -of the two additional AP fields in order to scan a segment which -supports a lightweight allocation frame. - Synchronization ............... @@ -414,61 +341,41 @@ operation on an AP may only be performed by a single mutator thread at a time. Each of the operations on allocation frames counts as an operation on an AP. -_`.lw-frame.sync.pool`: Pools are permitted to read or modify the -lightweight frame state of an AP only in response to an operation on -that AP. - -_`.lw-frame.sync.external`: The external functions -``mps_ap_frame_push()`` and ``mps_ap_frame_pop()`` are permitted to -read the values of the ``enabled`` and ``frameptr`` fields for the -supplied AP without claiming the arena lock. They are permitted to -modify the ``frameptr`` field if and only if ``enabled == FALSE``. - -_`.lw-frame.sync.trip`: When a buffer trip happens, and the trap -wasn't set by MPS itself (that is, it wasn't because of a flip or for -logging), then the buffer code must check whether the AP has state -PopPending. If it does, the buffer code must call the Pool. - Implementation .............. -_`.lw-frame.push`: The external ``PushFrame()`` operation +_`.lw-frame.push`: The external *FramePush* operation ``mps_ap_frame_push()`` performs the following operations:: - IF !APIsTrapped(ap) - AND StateOfFrame(ap) == Valid - AND ap->init == ap->alloc - AND ap->init < ap->limit - THEN + IF ap->init != ap->alloc + FAIL + ELSE IF ap->init < ap->limit *frame_o = ap->init; ELSE WITH_ARENA_LOCK - PerformInternalPushFrameOperation(...) + PerformInternalFramePushOperation(...) END END -_`.lw-frame.push.limit`: The reason for not using the lightweight -operation when ``ap->init == ap->limit`` is that a frame pointer at -the limit of a buffer (and possibly therefore of a segment) would be -ambiguous: is it at the limit of the segment, or at the base of the +_`.lw-frame.push.limit`: The reason for testing ``ap->init < +ap->limit`` and not ``ap->init <= ap->limit`` is that a frame pointer +at the limit of a buffer (and possibly therefore of a segment) would +be ambiguous: is it at the limit of the segment, or at the base of the segment that's adjacent in memory? The internal operation must handle this case, for example by refilling the buffer and setting the frame at the beginning. -_`.lw-frame.pop`: The external ``PopFrame()`` operation +_`.lw-frame.pop`: The external *FramePop* operation (``mps_ap_frame_pop()``) performs the following operations:: - IF StateOfFrame(ap) != Disabled - AND BufferBase(ap) <= frame - AND frame < ap->init - THEN - TrapAP(ap); /* ensure next allocation or push involves the pool */ - ap->frameptr = frame; - ap->lwpopPending = TRUE; + IF ap->init != ap->alloc + FAIL + ELSE IF BufferBase(ap) <= frame AND frame < ap->init + ap->init = ap->alloc = frame; ELSE WITH_ARENA_LOCK - PerformInternalPopFrameOperation(...) + PerformInternalFramePopOperation(...) END END