-- RefCountsImpl.Mesa
-- Last Edited by: Willie-Sue, December 10, 1982 11:48 am
-- Last Edited by: Paul Rovner, December 20, 1982 9:44 am


DIRECTORY
Inline USING[BITXOR, BITSHIFT, LowHalf, HighHalf],
Mopcodes USING[zMISC],
MiscAlpha USING[alpha],
RefCounts USING[], -- exports only
RTRefCounts USING[nRCEntry, ProbeIndex, GCState, rcAbsent, Residue, MapRcePiRef];

RefCountsImpl: MONITOR -- protects dump area in GCState
IMPORTS Inline, RTRefCounts
EXPORTS RefCounts
= BEGIN

GetCount: PUBLIC ENTRY PROC[ref: REF ANY]
RETURNS[count: NAT ← RTRefCounts.rcAbsent, markedAsOnStack: BOOLFALSE] =
{ ENABLE UNWIND => NULL;
pi: RTRefCounts.ProbeIndex;
res: RTRefCounts.Residue;
npi: CARDINAL;
[pi, res] ← MapRefPiRes[ref];
npi ← 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 ANYNIL, count: NAT ← 0, markedAsOnStack: BOOLFALSE] =
{ ENABLE UNWIND => NULL;
FOR pi: RTRefCounts.ProbeIndex IN RTRefCounts.ProbeIndex
DO
n: CARDINAL = 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;
};


aDUMPINDEX: MiscAlpha.alpha = 70B;

DUMPINDEX: PROC[pi: RTRefCounts.ProbeIndex] RETURNS[count: CARDINAL] =
MACHINE CODE {Mopcodes.zMISC, aDUMPINDEX};

MapRefPiRes: PROC[ref: REF]
RETURNS[pi: RTRefCounts.ProbeIndex, res: RTRefCounts.Residue] =
{res ← MapRefRes[ref];
pi← Inline.BITXOR[Inline.BITSHIFT[Inline.LowHalf[ref], -1], res]};

MapRefRes: PROC[ref: REF] RETURNS[RTRefCounts.Residue] =
{RETURN[Inline.HighHalf[ref]]};

END.