p-comp-gc.red 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473
  1. %
  2. % p-comp-GC.RED - Compacting garbage collector for PSL
  3. %
  4. % Author: Martin Griss and Eric Benson
  5. % Symbolic Computation Group
  6. % Computer Science Dept.
  7. % University of Utah
  8. % Date: 28 August 1981
  9. % Copyright (c) 1981 University of Utah
  10. %
  11. % WARNING! This file has not been parameterized using
  12. % AddressingUnitsPerItem. It will not work on machines that
  13. % address bytes. /csp 3-1-83
  14. % All data types have either explicit header tag in first item,
  15. % or are assumed to be 1st element of pair.
  16. % Revision History:
  17. % Edit by Griss, 17 March 1983.
  18. % Move major data structures to XXX-HEADER: GCArray
  19. % Edit by Cris Perdue, 16 Feb 1983 1407-PST
  20. % Fixed GtHeap and collector(s) to use only HeapLast, not HeapPreviousLast
  21. % Sets HeapTrapped to NIL now.
  22. % Using known-free-space function
  23. % Added check of Heap-Warn-Level after %Reclaim
  24. % Defined and used known-free-space function
  25. % <PSL.KERNEL>COMPACTING-GC.RED.9, 4-Oct-82 17:59:55, Edit by BENSON
  26. % Added GCTime!*
  27. % <PSL.KERNEL>COMPACTING-GC.RED.3, 21-Sep-82 10:43:21, Edit by BENSON
  28. % Flagged most functions internal
  29. % (M.L. Griss, March, 1977).
  30. % (Update to speed up, July 1978)
  31. % Converted to Syslisp July 1980
  32. % En-STRUCT-ed, Eric Benson April 1981
  33. % Added EVECT tag, M. Griss, 3 July 1982
  34. fluid '(!*GC % Controls printing of statistics
  35. GCTime!* % Total amount of time spent in GC
  36. GCKnt!* % count of # of GC's since system build
  37. heap!-warn!-level); % Continuable error if this much not
  38. % free after %Reclaim.
  39. LoadTime <<
  40. !*GC := T; % Do print GC messages (SL Rep says no)
  41. GCTime!* := 0;
  42. GCKnt!* := 0; % Initialize to zero
  43. Heap!-Warn!-Level := 1000;
  44. >>;
  45. on Syslisp;
  46. % Predicates for whether to follow pointers
  47. external WVar HeapLowerBound, % Bottom of heap
  48. HeapUpperBound, % Top of heap
  49. HeapLast, % Last item allocated
  50. HeapTrapped; % Boolean: has trap occurred since GC?
  51. CompileTime <<
  52. flag('(MarkFromAllBases BuildRelocationFields UpdateAllBases CompactHeap
  53. MarkFromOneSymbol MakeIDFreeList
  54. GCMessage MarkFromSymbols MarkFromRange MarkFromBase MarkFromVector
  55. GCError UpdateSymbols UpdateRegion UpdateItem UpdateHeap),
  56. 'NotYetInternalFunction);
  57. syslsp smacro procedure PointerTagP X;
  58. X > PosInt and X < Code;
  59. syslsp smacro procedure WithinHeapPointer X;
  60. X >= HeapLowerBound and X <= HeapLast;
  61. >>;
  62. % Marking primitives
  63. internal WConst GCMarkValue = 8#777,
  64. HSkip = Forward;
  65. CompileTime <<
  66. syslsp smacro procedure Mark X; % Get GC mark bits in item X points to
  67. GCField @X;
  68. syslsp smacro procedure SetMark X; % Set GC mark bits in item X points to
  69. GCField @X := GCMarkValue;
  70. syslsp smacro procedure ClearMark X; % Clear GC mark bits in item X points to
  71. GCField @X := if NegIntP @X then -1 else 0;
  72. syslsp smacro procedure Marked X; % Is item pointed to by X marked?
  73. Mark X eq GCMarkValue;
  74. syslsp smacro procedure MarkID X;
  75. Field(SymNam X, TagStartingBit, TagBitLength) := Forward;
  76. syslsp smacro procedure MarkedID X;
  77. Tag SymNam X eq Forward;
  78. syslsp smacro procedure ClearIDMark X;
  79. Field(SymNam X, TagStartingBit, TagBitLength) := STR;
  80. % Relocation primitives
  81. syslsp smacro procedure SkipLength X; % Stored in heap header
  82. Inf @X;
  83. syslsp smacro procedure PutSkipLength(X, L); % Store in heap header
  84. Inf @X := L;
  85. put('SkipLength, 'Assign!-Op, 'PutSkipLength);
  86. >>;
  87. internal WConst BitsInSegment = 13,
  88. SegmentLength = LShift(1, BitsInSegment),
  89. SegmentMask = SegmentLength - 1;
  90. External WArray GCArray;
  91. CompileTime <<
  92. syslsp smacro procedure SegmentNumber X; % Get segment part of pointer
  93. LShift(X - HeapLowerBound, -BitsInSegment);
  94. syslsp smacro procedure OffsetInSegment X; % Get offset part of pointer
  95. LAnd(X - HeapLowerBound, SegmentMask);
  96. syslsp smacro procedure MovementWithinSegment X; % Reloc field in item
  97. GCField @X;
  98. syslsp smacro procedure PutMovementWithinSegment(X, M); % Store reloc field
  99. GCField @X := M;
  100. syslsp smacro procedure ClearMovementWithinSegment X; % Clear reloc field
  101. GCField @X := if NegIntP @X then -1 else 0;
  102. put('MovementWithinSegment, 'Assign!-Op, 'PutMovementWithinSegment);
  103. syslsp smacro procedure SegmentMovement X; % Segment table
  104. GCArray[X];
  105. syslsp smacro procedure PutSegmentMovement(X, M); % Store in seg table
  106. GCArray[X] := M;
  107. put('SegmentMovement, 'Assign!-Op, 'PutSegmentMovement);
  108. syslsp smacro procedure Reloc X; % Compute pointer adjustment
  109. X - (SegmentMovement SegmentNumber X + MovementWithinSegment X);
  110. >>;
  111. external WVar ST, % stack pointer
  112. StackLowerBound; % bottom of stack
  113. % Base registers marked from by collector
  114. % SymNam, SymPrp and SymVal are declared for all
  115. external WVar NextSymbol; % next ID number to be allocated
  116. external WVar BndStkLowerBound, % Bottom of binding stack
  117. BndStkPtr; % Binding stack pointer
  118. internal WVar StackEnd, % Holds address of bottom of stack
  119. StackStart, % Holds address of top of stack
  120. MarkTag, % Used by MarkFromBase only
  121. Hole, % First location moved in heap
  122. HeapShrink, % Total amount reclaimed
  123. StartingRealTime;
  124. syslsp procedure Reclaim(); %. User call to garbage collector
  125. << !%Reclaim();
  126. NIL >>;
  127. syslsp procedure !%Reclaim(); % Garbage collector
  128. << StackEnd := MakeAddressFromStackPointer ST - FrameSize();
  129. StackStart := StackLowerBound;
  130. if LispVar !*GC then ErrorPrintF "*** Garbage collection starting";
  131. StartingRealTime := TimC();
  132. LispVar GCKnt!* := LispVar GCKnt!* + 1; % must be INUM > 0, so needn't chk
  133. MarkFromAllBases();
  134. MakeIDFreeList();
  135. BuildRelocationFields();
  136. UpdateAllBases();
  137. CompactHeap();
  138. HeapLast := HeapLast - HeapShrink;
  139. StartingRealTime := TimC() - StartingRealTime;
  140. LispVar GCTime!* := Plus2(LispVar GCTime!*, StartingRealTime);
  141. if LispVar !*GC then GCMessage();
  142. HeapTrapped := NIL;
  143. if IntInf known!-free!-space() < IntInf (LispVar Heap!-Warn!-Level) then
  144. ContinuableError(99, "Heap space low", NIL);
  145. >>;
  146. syslsp procedure MarkFromAllBases();
  147. begin scalar B;
  148. MarkFromSymbols();
  149. MarkFromRange(StackStart, StackEnd);
  150. B := BndStkLowerBound;
  151. while << B := AdjustBndStkPtr(B, 1);
  152. B <= BndStkPtr >> do
  153. MarkFromBase @B;
  154. end;
  155. syslsp procedure MarkFromSymbols();
  156. begin scalar B;
  157. MarkFromOneSymbol 128; % mark NIL first
  158. for I := 0 step 1 until 127 do
  159. if not MarkedID I then MarkFromOneSymbol I;
  160. for I := 0 step 1 until MaxObArray do
  161. << B := ObArray I;
  162. if B > 0 and not MarkedID B then MarkFromOneSymbol B >>;
  163. end;
  164. syslsp procedure MarkFromOneSymbol X;
  165. % SymNam has to be marked from before marking ID, since the mark uses its tag
  166. % No problem since it's only a string, can't reference itself.
  167. << MarkFromBase SymNam X;
  168. MarkID X;
  169. MarkFromBase SymPrp X;
  170. MarkFromBase SymVal X >>;
  171. syslsp procedure MarkFromRange(Low, High);
  172. for Ptr := Low step 1 until High do MarkFromBase @Ptr;
  173. syslsp procedure MarkFromBase Base;
  174. begin scalar MarkInfo;
  175. MarkTag := Tag Base;
  176. if not PointerTagP MarkTag then return
  177. << if MarkTag = ID and not null Base then
  178. << MarkInfo := IDInf Base;
  179. if not MarkedID MarkInfo then MarkFromOneSymbol MarkInfo >> >>;
  180. MarkInfo := Inf Base;
  181. if not WithinHeapPointer MarkInfo
  182. or Marked MarkInfo then return;
  183. SetMark MarkInfo;
  184. CommentOutCode CheckAndSetMark MarkInfo;
  185. return if MarkTag eq VECT or MarkTag eq EVECT then
  186. MarkFromVector MarkInfo
  187. else if MarkTag eq PAIR then
  188. << MarkFromBase car Base;
  189. MarkFromBase cdr Base >>;
  190. end;
  191. CommentOutCode <<
  192. syslsp procedure CheckAndSetMark P;
  193. begin scalar HeadAtP;
  194. HeadAtP := Tag @P;
  195. case MarkTag of
  196. STR:
  197. if HeadAtP eq HBYTES then SetMark P;
  198. FIXN, FLTN, BIGN, WRDS:
  199. if HeadAtP eq HWRDS then SetMark P;
  200. VECT, EVECT:
  201. if HeadAtP eq HVECT then SetMark P;
  202. PAIR:
  203. SetMark P;
  204. default:
  205. GCError("Internal error in marking phase, at %o", P)
  206. end;
  207. end;
  208. >>;
  209. syslsp procedure MarkFromVector Info;
  210. begin scalar Uplim;
  211. CommentOutCode if Tag @Info neq HVECT then return;
  212. Uplim := &VecItm(Info, VecLen Info);
  213. for Ptr := &VecItm(Info, 0) step 1 until Uplim do
  214. MarkFromBase @Ptr;
  215. end;
  216. syslsp procedure MakeIDFreeList();
  217. begin scalar Previous;
  218. for I := 0 step 1 until 128 do
  219. ClearIDMark I;
  220. Previous := 129;
  221. while MarkedID Previous and Previous <= MaxSymbols do
  222. << ClearIDMark Previous;
  223. Previous := Previous + 1 >>;
  224. if Previous >= MaxSymbols then
  225. NextSymbol := 0
  226. else
  227. NextSymbol := Previous; % free list starts here
  228. for I := Previous + 1 step 1 until MaxSymbols do
  229. if MarkedID I then ClearIDMark I
  230. else
  231. << SymNam Previous := I;
  232. Previous := I >>;
  233. SymNam Previous := 0; % end of free list
  234. end;
  235. syslsp procedure BuildRelocationFields();
  236. %
  237. % Pass 2 - Turn off GC marks and Build SEGKNTs
  238. %
  239. begin scalar CurrentItem, SGCurrent, IGCurrent, TmpIG, DCount, SegLen;
  240. SGCurrent := IGCurrent := 0;
  241. SegmentMovement SGCurrent := 0; % Dummy
  242. Hole := HeapLowerBound - 1; % will be first hole
  243. DCount := HeapShrink := 0; % holes in current segment, total holes
  244. CurrentItem := HeapLowerBound;
  245. while CurrentItem < HeapLast do
  246. begin scalar Incr;
  247. SegLen := case Tag @CurrentItem of
  248. BTRTAG, CODE, NEGINT, POSINT, ID, UNBOUND,
  249. STR, BYTES, FIXN, FLTN, BIGN, WRDS, Halfwords, PAIR, VECT, EVECT:
  250. 2; % must be first of pair
  251. HBYTES:
  252. 1 + StrPack StrLen CurrentItem;
  253. HHalfwords:
  254. 1 + HalfWordPack StrLen CurrentItem;
  255. HWRDS:
  256. 1 + WrdPack WrdLen CurrentItem;
  257. HVECT:
  258. 1 + VectPack VecLen CurrentItem;
  259. HSKIP:
  260. SkipLength CurrentItem;
  261. default:
  262. GCError("Illegal item in heap at %o", CurrentItem)
  263. end; % case
  264. if Marked CurrentItem then % a hole
  265. if HeapShrink = 0 then
  266. ClearMark CurrentItem
  267. else % segment also clears mark
  268. << MovementWithinSegment CurrentItem := DCount; % incremental shift
  269. Incr := 0 >> % no shift
  270. else
  271. << @CurrentItem := MkItem(HSKIP, SegLen); % a skip mark
  272. Incr := 1; % more shift
  273. if Hole < HeapLowerBound then Hole := CurrentItem >>;
  274. TmpIG := IGCurrent + SegLen; % set SEG size
  275. CurrentItem := CurrentItem + SegLen;
  276. while TmpIG >= SegmentLength do
  277. begin scalar Tmp;
  278. Tmp := SegmentLength - IGCurrent; % Expand to next SEGMENT
  279. SegLen := SegLen - Tmp;
  280. if Incr eq 1 then HeapShrink := HeapShrink + Tmp;
  281. DCount := IGCurrent := 0;
  282. SGCurrent := SGCurrent + 1;
  283. SegmentMovement SGCurrent := HeapShrink; % Store Next Base
  284. TmpIG := TmpIG - SegmentLength;
  285. end;
  286. IGCurrent := TmpIG;
  287. if Incr eq 1 then
  288. << HeapShrink := HeapShrink + SegLen;
  289. DCount := DCount + SegLen >>; % Add in Hole Size
  290. end;
  291. SegmentMovement(SGCurrent + 1) := HeapShrink;
  292. end;
  293. syslsp procedure UpdateAllBases();
  294. begin scalar B;
  295. UpdateSymbols();
  296. UpdateRegion(StackStart, StackEnd);
  297. B := BndStkLowerBound;
  298. while << B := AdjustBndStkPtr(B, 1);
  299. B <= BndStkPtr >> do
  300. UpdateItem B;
  301. UpdateHeap() >>;
  302. syslsp procedure UpdateSymbols();
  303. for I := 0 step 1 until MaxSymbols do
  304. begin scalar NameLoc;
  305. NameLoc := &SymNam I;
  306. if StringP @NameLoc then
  307. << UpdateItem NameLoc;
  308. UpdateItem &SymVal I;
  309. UpdateItem &SymPrp I >>;
  310. end;
  311. syslsp procedure UpdateRegion(Low, High);
  312. for Ptr := Low step 1 until High do UpdateItem Ptr;
  313. syslsp procedure UpdateHeap();
  314. begin scalar CurrentItem;
  315. CurrentItem := HeapLowerBound;
  316. while CurrentItem < HeapLast do
  317. begin
  318. case Tag @CurrentItem of
  319. BTRTAG, CODE, NEGINT, POSINT, ID, UNBOUND:
  320. CurrentItem := CurrentItem + 1;
  321. STR, BYTES, FIXN, FLTN, BIGN, WRDS, Halfwords, PAIR, VECT, EVECT:
  322. << if Inf @CurrentItem >= Hole and Inf @CurrentItem <= HeapLast then
  323. Inf @CurrentItem := Reloc Inf @CurrentItem;
  324. CurrentItem := CurrentItem + 1 >>;
  325. HBYTES:
  326. CurrentItem := CurrentItem + 1 + StrPack StrLen CurrentItem;
  327. HHalfwords:
  328. CurrentItem := CurrentItem + 1 + HalfwordPack StrLen CurrentItem;
  329. HWRDS:
  330. CurrentItem := CurrentItem + 1 + WrdPack WrdLen CurrentItem;
  331. HVECT:
  332. begin scalar Tmp;
  333. Tmp := VecLen CurrentItem;
  334. CurrentItem := CurrentItem + 1; % Move over header
  335. for I := 0 step 1 until Tmp do % VecLen + 1 items
  336. begin scalar Tmp2, Tmp3;
  337. Tmp2 := @CurrentItem;
  338. Tmp3 := Tag Tmp2;
  339. if PointerTagP Tmp3
  340. and Inf Tmp2 >= Hole and Inf Tmp2 <= HeapLast then
  341. Inf @CurrentItem := Reloc Inf Tmp2;
  342. CurrentItem := CurrentItem + 1;
  343. end;
  344. end;
  345. HSKIP:
  346. CurrentItem := CurrentItem + SkipLength CurrentItem;
  347. default:
  348. GCError("Internal error in updating phase at %o", CurrentItem)
  349. end; % case
  350. end
  351. end;
  352. syslsp procedure UpdateItem Ptr;
  353. begin scalar Tg, Info;
  354. Tg := Tag @Ptr;
  355. if not PointerTagP Tg then return;
  356. Info := INF @Ptr;
  357. if Info < Hole or Info > HeapLast then return;
  358. Inf @Ptr := Reloc Info;
  359. end;
  360. syslsp procedure CompactHeap();
  361. begin scalar OldItemPtr, NewItemPtr, SegLen;
  362. if Hole < HeapLowerBound then return;
  363. NewItemPtr := OldItemPtr := Hole;
  364. while OldItemPtr < HeapLast do
  365. begin;
  366. case Tag @OldItemPtr of
  367. BTRTAG, CODE, NEGINT, POSINT, ID, UNBOUND,
  368. STR, BYTES, FIXN, FLTN, BIGN, WRDS, Halfwords, PAIR, VECT, EVECT:
  369. SegLen := PairPack OldItemPtr;
  370. HBYTES:
  371. SegLen := 1 + StrPack StrLen OldItemPtr;
  372. HHalfwords:
  373. SegLen := 1 + HalfWordPack HalfwordLen OldItemPtr;
  374. HWRDS:
  375. SegLen := 1 + WrdPack WrdLen OldItemPtr;
  376. HVECT:
  377. SegLen := 1 + VectPack VecLen OldItemPtr;
  378. HSKIP:
  379. << OldItemPtr := OldItemPtr + SkipLength OldItemPtr;
  380. goto WhileNext >>;
  381. default:
  382. GCError("Internal error in compaction at %o", OldItemPtr)
  383. end; % case
  384. ClearMovementWithinSegment OldItemPtr;
  385. for I := 1 step 1 until SegLen do
  386. << @NewItemPtr := @OldItemPtr;
  387. NewItemPtr := NewItemPtr + 1;
  388. OldItemPtr := OldItemPtr + 1 >>;
  389. WhileNext:
  390. end;
  391. end;
  392. syslsp procedure GCError(Message, P);
  393. << ErrorPrintF("***** Fatal error during garbage collection");
  394. ErrorPrintF(Message, P);
  395. while T do Quit; >>;
  396. syslsp procedure GCMessage();
  397. << ErrorPrintF("*** GC %w: time %d ms",
  398. LispVar GCKnt!*, StartingRealTime);
  399. ErrorPrintF("*** %d recovered, %d stable, %d active, %d free",
  400. HeapShrink, Hole - HeapLowerBound,
  401. HeapLast - Hole,
  402. intinf known!-free!-space() ) >>;
  403. off SysLisp;
  404. END;