-- 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.