<> <> <> DIRECTORY Allocator USING[FNHeaderP, NHeaderP, RefCount, maxSmallBlockSize, BlockSizeIndex, bsiEscape, NormalHeader], AllocatorOps USING[REFToNHP, NHPToREF], Basics USING[BITAND, BITOR, BITSHIFT, BITXOR, HighHalf, LowHalf], Collector USING[Disposition], PrincOpsUtils USING[ZERO], RCMicrocodeOps USING[], SafeStorage USING[Type, nullType], ZCT USING[FOSTableIndex, FOSTableLength, FOSTableResidue, fosWildCard, zctBlockWords, ZeroCountTable, zct, ZCTObject, FOSTableObject]; RCMicrocodeImpl: PROGRAM <> IMPORTS AllocatorOps, Basics, PrincOpsUtils, ZCT--zct-- EXPORTS RCMicrocodeOps = BEGIN OPEN Allocator, Collector, ZCT; <<>> <> checking: BOOL = TRUE; <> <<>> <> RCOverflowOccurred: PUBLIC ERROR = CODE; RCUnderflowOccurred: PUBLIC ERROR = CODE; LookFurtherAtReclaimedRef: PUBLIC ERROR = CODE; ZCTFull: PUBLIC ERROR = CODE; NormalFreeListEmpty: PUBLIC ERROR = CODE; <<>> <> <> <> < Allocator.maxSmallBlockSize>> <> ALLOCATE: PUBLIC --INTERNAL-- PROC[--requested--size: CARDINAL, type: SafeStorage.Type] RETURNS[r: REF _ NIL] = { <> IF size <= maxSmallBlockSize THEN { bsi: BlockSizeIndex = zct.sizeToBSI[size]; fnhp: FNHeaderP _ zct.bsiToFreeList[bsi]; nhp: NHeaderP; IF fnhp = NIL THEN ERROR NormalFreeListEmpty; <> nhp _ @fnhp.fnh; r _ AllocatorOps.NHPToREF[nhp]; <<>> <> OnZ[nhp]; -- may pageFault or raise ZCTFull; ifso, no changes have been made <<>> <> zct.bsiToFreeList[bsi] _ fnhp.nextFree; fnhp.nextFree _ NIL; -- CLEAR THE NEW OBJECT nhp.type _ type; nhp.maybeOnStack _ zct.markingDecrements; }; }; <> <> <> FREEPLEASE: PUBLIC --INTERNAL-- PROC[nhp: NHeaderP] RETURNS[success: BOOL _ FALSE] = { <> bsi: BlockSizeIndex = nhp.blockSizeIndex; IF (success _ bsi # bsiEscape) THEN { fnhp: FNHeaderP = LOOPHOLE[nhp, FNHeaderP]; PrincOpsUtils.ZERO[nhp + SIZE[NormalHeader], zct.bsiToSize[bsi] - SIZE[NormalHeader]]; fnhp.fnh.type _ SafeStorage.nullType; -- mark the object as free fnhp.nextFree _ zct.bsiToFreeList[bsi]; zct.bsiToFreeList[bsi] _ fnhp; }; }; <> <> <> ASSIGNREF: PUBLIC --INTERNAL-- PROC[rhs: REF, lhs: LONG POINTER TO REF] = { lhsRef: REF; rnhp: NHeaderP; rrc: RefCount; <> <> lhsRef _ lhs^; IF rhs # NIL THEN { <> IF lhsRef = rhs THEN RETURN;--no-op. Bug: x_x. Either do this check or re-read rrc below rnhp _ AllocatorOps.REFToNHP[rhs]; -- subtract 2 rrc _ rnhp.refCount; IF rrc = LAST[RefCount] THEN ERROR RCOverflowOccurred; <> <> <> }; IF lhsRef # NIL THEN { lnhp: NHeaderP = AllocatorOps.REFToNHP[lhsRef]; lrc: RefCount _ lnhp.refCount; CheckForRCUnderflow[lnhp]; -- might raise RCUnderflowOccurred IF lrc = 1 AND NOT lnhp.rcOverflowed THEN OnZ[lnhp]; -- might raise ZCTFull <> lnhp.maybeOnStack _ zct.markingDecrements--ASSUME zct^ is pinned--; <> lnhp.refCount _ lrc - 1; }; <> IF rhs # NIL THEN { rnhp.refCount _ rrc + 1; -- COMMITTED NOW to finish this call rnhp.maybeOnStack _ FALSE; }; lhs^ _ rhs; -- NOT counted }; -- end ASSIGNREF <<>> <> <> <> <> <> <> OnZ: PUBLIC --INTERNAL-- PROC [nhp: NHeaderP] = { wp: LONG POINTER TO NHeaderP; IF nhp.inZCT THEN RETURN; wp _ zct.wp; wp^ _ nhp; -- might pageFault <> IF Basics.BITAND[Basics.LowHalf[LOOPHOLE[wp, LONG CARDINAL]], zctBlockWords - 1] = zctBlockWords - 2*SIZE[LONG POINTER] THEN { -- wp points to the cell before the link to the next zctBlock IF (wp _ LOOPHOLE[(wp+SIZE[LONG POINTER])^, -- pick up the link LONG POINTER TO NHeaderP]) = NIL THEN ERROR ZCTFull -- i.e. XXX TRAP with trapParam = 4 ELSE zct.wp _ wp; <> } ELSE zct.wp _ wp + SIZE[LONG POINTER]; -- will NOT pageFault nhp.inZCT _ TRUE; -- will NOT pagefault }; <<>> <> CREATEREF: PUBLIC --INTERNAL-- PROC[nhp: NHeaderP] = { <> IF checking AND (nhp.refCount # 0 OR nhp.rcOverflowed) THEN ERROR; nhp.maybeOnStack _ zct.markingDecrements; OnZ[nhp]; -- may pageFault or raise ZCTFull; ifso, no changes have been made }; <> <> RECLAIMABLEREF: PUBLIC --INTERNAL-- PROC[nhp: NHeaderP] RETURNS[Disposition] = { <> RETURN[MCRECLAIMABLEREF[nhp, FALSE]]; }; <<>> <> <> <> MCRECLAIMABLEREF: PROC[nhp: NHeaderP, decrPending: BOOL] RETURNS[d: Disposition _ continue] = { rc: RefCount _ nhp.refCount; IF decrPending THEN rc _ rc - 1; -- won't underflow IF rc # 0 OR nhp.inZCT OR nhp.rcOverflowed THEN RETURN; -- leave it alone IF nhp.maybeOnStack OR FoundInFHSnapshot[nhp] THEN OnZ[nhp] -- put it back; this may pageFault or raise ZCTFull ELSE d _ (IF nhp.f THEN finalizeIt ELSE reclaimIt); }; <<>> <> <> FoundInFHSnapshot: PROC[nhp: NHeaderP] RETURNS[found: BOOL _ FALSE] = { index: FOSTableIndex; residue, entry: FOSTableResidue; fosTable: LONG POINTER TO FOSTableObject = LOOPHOLE[zct+SIZE[ZCTObject], LONG POINTER TO FOSTableObject]; [index, residue] _ FOSTableHash[nhp]; entry _ fosTable[index]; RETURN[entry = residue OR entry = fosWildCard]; }; <> FOSTableHash: PUBLIC PROC[nhp: NHeaderP--maybe bogus--] RETURNS[x: FOSTableIndex, r: FOSTableResidue] = { OPEN Basics; lc: LONG CARDINAL = LOOPHOLE[nhp, LONG CARDINAL]; r _ BITOR[BITSHIFT[HighHalf[lc], 3], BITSHIFT[LowHalf[lc], -13]]; <> x _ BITAND[BITXOR[BITSHIFT[LowHalf[lc], -1], r], FOSTableLength-1]; < NHeaderP's are even>> <> }; <<>> <> <> <> <> RECLAIMEDREF: PUBLIC -- INTERNAL-- PROC[ref: REF] RETURNS[ans: REF ANY _ NIL] = { nhp: NHeaderP = AllocatorOps.REFToNHP[ref]; <> CheckForRCUnderflow[nhp]; -- might raise RCUnderflowOccurred SELECT MCRECLAIMABLEREF[nhp, TRUE] FROM continue => NULL; reclaimIt => ans _ ref; finalizeIt => ERROR LookFurtherAtReclaimedRef; --ReclaimedRef MISC TRAP, trapParam = 6 ENDCASE => ERROR; nhp.refCount _ nhp.refCount - 1; }; <<>> <> <> CheckForRCUnderflow: PROC[nhp: NHeaderP] = { rc: RefCount _ nhp.refCount; IF checking AND rc = 0 AND NOT nhp.rcOverflowed THEN ERROR; <> IF rc = 0 --was RCMicrocodeOps.rcBottom-- AND nhp.rcOverflowed THEN ERROR RCUnderflowOccurred; -- no changes have been made <> }; <> <> DISABLEMICROCODE: PUBLIC -- INTERNAL-- PROC[z: ZeroCountTable] = { <> NULL; -- the real uc: ucDisabled _ TRUE }; <<>> <> <> ENABLEMICROCODE: PUBLIC -- INTERNAL-- PROC[z: ZeroCountTable] RETURNS[ucVersion: NAT] = { RETURN[0]; -- the real uc: ucDisabled _ FALSE }; END.