-- RefCountsImpl.Mesa
-- Last Edited by: Willie-Sue, December 10, 1982 11:48 am
-- Last Edited by: Paul Rovner, May 17, 1983 11:08 am
-- Last Edited by: Levin, August 8, 1983 5:13 pm
DIRECTORY
PrincOpsUtils USING[BITXOR, BITSHIFT, LowHalf, HighHalf],
RefCounts USING[], -- exports only
RTMicrocode USING[DUMPINDEX],
RTRefCounts USING[nRCEntry, ProbeIndex, GCState, rcAbsent, Residue, MapRcePiRef];
RefCountsImpl: MONITOR -- protects dump area in GCState
IMPORTS PrincOpsUtils, RTMicrocode, RTRefCounts
EXPORTS RefCounts
= BEGIN OPEN PrincOpsUtils;
GetCount: PUBLIC ENTRY PROC[ref: LONG POINTER--loopholed REF--]
RETURNS[count: NAT ← RTRefCounts.rcAbsent, markedAsOnStack: BOOL ← FALSE] =
{ ENABLE UNWIND => NULL;
pi: RTRefCounts.ProbeIndex;
res: RTRefCounts.Residue;
npi: CARDINAL;
[pi, res] ← MapRefPiRes[LOOPHOLE[ref]];
npi ← RTMicrocode.DUMPINDEX[pi];
FOR i: CARDINAL IN [0..npi)
DO e: RTRefCounts.nRCEntry = LOOPHOLE[RTRefCounts.GCState.dumpTable[i]];
IF e.res = res THEN RETURN[e.rc, (e.onStack = true)];
ENDLOOP;
};
-- BEWARE Enumerate is UNSAFE. See Paul Rovner before using it. ref arg may be invalid!
-- (ref = NIL) => not stopped
Enumerate: PUBLIC ENTRY PROC
[proc: PROC[ref: REF ANY, count: NAT, markedAsOnStack: BOOL] RETURNS[stop: BOOL]]
RETURNS[ref: REF ANY ← NIL, count: NAT ← 0, markedAsOnStack: BOOL ← FALSE] =
{ ENABLE UNWIND => NULL;
FOR pi: RTRefCounts.ProbeIndex IN RTRefCounts.ProbeIndex
DO
n: CARDINAL = RTMicrocode.DUMPINDEX[pi];
FOR i: CARDINAL IN [0..n)
DO e: RTRefCounts.nRCEntry = LOOPHOLE[RTRefCounts.GCState.dumpTable[i]];
ref ← RTRefCounts.MapRcePiRef[e, pi];
IF proc[ref, e.rc, (e.onStack = true)]
THEN RETURN[ref: ref,
count: e.rc,
markedAsOnStack: (e.onStack = true)];
ENDLOOP;
ENDLOOP;
};
MapRefPiRes: PROC[ref: REF]
RETURNS[pi: RTRefCounts.ProbeIndex, res: RTRefCounts.Residue] =
{res ← MapRefRes[ref];
pi← BITXOR[BITSHIFT[LowHalf[LOOPHOLE[ref, LONG POINTER]], -1], res]};
MapRefRes: PROC[ref: REF] RETURNS[RTRefCounts.Residue] =
{RETURN[HighHalf[LOOPHOLE[ref, LONG POINTER]]]};
END.