123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469 |
- %
- % GC.RED - Compacting garbage collector for PSL
- %
- % Author: Martin Griss and Eric Benson
- % Symbolic Computation Group
- % Computer Science Dept.
- % University of Utah
- % Date: 28 August 1981
- % Copyright (c) 1981 University of Utah
- %
- % All data types have either explicit header tag in first item,
- % or are assumed to be 1st element of pair.
- % Revision History:
- % Edit by Cris Perdue, 16 Feb 1983 1407-PST
- % Fixed GtHeap and collector(s) to use only HeapLast, not HeapPreviousLast
- % Sets HeapTrapped to NIL now.
- % Using known-free-space function
- % Added check of Heap-Warn-Level after %Reclaim
- % Defined and used known-free-space function
- % <PSL.KERNEL>COMPACTING-GC.RED.9, 4-Oct-82 17:59:55, Edit by BENSON
- % Added GCTime!*
- % <PSL.KERNEL>COMPACTING-GC.RED.3, 21-Sep-82 10:43:21, Edit by BENSON
- % Flagged most functions internal
- % (M.L. Griss, March, 1977).
- % (Update to speed up, July 1978)
- % Converted to Syslisp July 1980
- % En-STRUCT-ed, Eric Benson April 1981
- % Added EVECT tag, M. Griss, 3 July 1982
- fluid '(!*GC % Controls printing of statistics
- GCTime!* % Total amount of time spent in GC
- GCKnt!* % count of # of GC's since system build
- heap!-warn!-level); % Continuable error if this much not
- % free after %Reclaim.
- LoadTime <<
- !*GC := T; % Do print GC messages (SL Rep says no)
- GCTime!* := 0;
- GCKnt!* := 0; % Initialize to zero
- Heap!-Warn!-Level := 1000;
- >>;
- on Syslisp;
- % Predicates for whether to follow pointers
- external WVar HeapLowerBound, % Bottom of heap
- HeapUpperBound, % Top of heap
- HeapLast, % Last item allocated
- HeapTrapped; % Boolean: has trap occurred since GC?
- CompileTime <<
- flag('(MarkFromAllBases BuildRelocationFields UpdateAllBases CompactHeap
- MarkFromOneSymbol MakeIDFreeList
- GCMessage MarkFromSymbols MarkFromRange MarkFromBase MarkFromVector
- GCError UpdateSymbols UpdateRegion UpdateItem UpdateHeap),
- 'InternalFunction);
- syslsp smacro procedure PointerTagP X;
- X > PosInt and X < Code;
- syslsp smacro procedure WithinHeapPointer X;
- X >= HeapLowerBound and X <= HeapLast;
- >>;
- % Marking primitives
- internal WConst GCMarkValue = 8#777,
- HSkip = Forward;
- CompileTime <<
- syslsp smacro procedure Mark X; % Get GC mark bits in item X points to
- GCField @X;
- syslsp smacro procedure SetMark X; % Set GC mark bits in item X points to
- GCField @X := GCMarkValue;
- syslsp smacro procedure ClearMark X; % Clear GC mark bits in item X points to
- GCField @X := if NegIntP @X then -1 else 0;
- syslsp smacro procedure Marked X; % Is item pointed to by X marked?
- Mark X eq GCMarkValue;
- syslsp smacro procedure MarkID X;
- Field(SymNam X, TagStartingBit, TagBitLength) := Forward;
- syslsp smacro procedure MarkedID X;
- Tag SymNam X eq Forward;
- syslsp smacro procedure ClearIDMark X;
- Field(SymNam X, TagStartingBit, TagBitLength) := STR;
- % Relocation primitives
- syslsp smacro procedure SkipLength X; % Stored in heap header
- Inf @X;
- syslsp smacro procedure PutSkipLength(X, L); % Store in heap header
- Inf @X := L;
- put('SkipLength, 'Assign!-Op, 'PutSkipLength);
- >>;
- internal WConst BitsInSegment = 13,
- SegmentLength = LShift(1, BitsInSegment),
- SegmentMask = SegmentLength - 1;
- internal WConst GCArraySize = LShift(HeapSize, -BitsInSegment) + 1;
- internal WArray GCArray[GCArraySize];
- CompileTime <<
- syslsp smacro procedure SegmentNumber X; % Get segment part of pointer
- LShift(X - HeapLowerBound, -BitsInSegment);
- syslsp smacro procedure OffsetInSegment X; % Get offset part of pointer
- LAnd(X - HeapLowerBound, SegmentMask);
- syslsp smacro procedure MovementWithinSegment X; % Reloc field in item
- GCField @X;
- syslsp smacro procedure PutMovementWithinSegment(X, M); % Store reloc field
- GCField @X := M;
- syslsp smacro procedure ClearMovementWithinSegment X; % Clear reloc field
- GCField @X := if NegIntP @X then -1 else 0;
- put('MovementWithinSegment, 'Assign!-Op, 'PutMovementWithinSegment);
- syslsp smacro procedure SegmentMovement X; % Segment table
- GCArray[X];
- syslsp smacro procedure PutSegmentMovement(X, M); % Store in seg table
- GCArray[X] := M;
- put('SegmentMovement, 'Assign!-Op, 'PutSegmentMovement);
- syslsp smacro procedure Reloc X; % Compute pointer adjustment
- X - (SegmentMovement SegmentNumber X + MovementWithinSegment X);
- >>;
- external WVar ST, % stack pointer
- StackLowerBound; % bottom of stack
- % Base registers marked from by collector
- % SymNam, SymPrp and SymVal are declared for all
- external WVar NextSymbol; % next ID number to be allocated
- external WVar BndStkLowerBound, % Bottom of binding stack
- BndStkPtr; % Binding stack pointer
- internal WVar StackEnd, % Holds address of bottom of stack
- StackStart, % Holds address of top of stack
- MarkTag, % Used by MarkFromBase only
- Hole, % First location moved in heap
- HeapShrink, % Total amount reclaimed
- StartingRealTime;
- syslsp procedure Reclaim(); %. User call to garbage collector
- << !%Reclaim();
- NIL >>;
- syslsp procedure !%Reclaim(); % Garbage collector
- << StackEnd := MakeAddressFromStackPointer ST - FrameSize();
- StackStart := StackLowerBound;
- if LispVar !*GC then ErrorPrintF "*** Garbage collection starting";
- StartingRealTime := TimC();
- LispVar GCKnt!* := LispVar GCKnt!* + 1; % must be INUM > 0, so needn't chk
- MarkFromAllBases();
- MakeIDFreeList();
- BuildRelocationFields();
- UpdateAllBases();
- CompactHeap();
- HeapLast := HeapLast - HeapShrink;
- StartingRealTime := TimC() - StartingRealTime;
- LispVar GCTime!* := Plus2(LispVar GCTime!*, StartingRealTime);
- if LispVar !*GC then GCMessage();
- HeapTrapped := NIL;
- if IntInf known!-free!-space() < IntInf (LispVar Heap!-Warn!-Level) then
- ContinuableError(99, "Heap space low", NIL);
- >>;
- syslsp procedure MarkFromAllBases();
- begin scalar B;
- MarkFromSymbols();
- MarkFromRange(StackStart, StackEnd);
- B := BndStkLowerBound;
- while << B := AdjustBndStkPtr(B, 1);
- B <= BndStkPtr >> do
- MarkFromBase @B;
- end;
- syslsp procedure MarkFromSymbols();
- begin scalar B;
- MarkFromOneSymbol 128; % mark NIL first
- for I := 0 step 1 until 127 do
- if not MarkedID I then MarkFromOneSymbol I;
- for I := 0 step 1 until MaxObArray do
- << B := ObArray I;
- if B > 0 and not MarkedID B then MarkFromOneSymbol B >>;
- end;
- syslsp procedure MarkFromOneSymbol X;
- % SymNam has to be marked from before marking ID, since the mark uses its tag
- % No problem since it's only a string, can't reference itself.
- << MarkFromBase SymNam X;
- MarkID X;
- MarkFromBase SymPrp X;
- MarkFromBase SymVal X >>;
- syslsp procedure MarkFromRange(Low, High);
- for Ptr := Low step 1 until High do MarkFromBase @Ptr;
- syslsp procedure MarkFromBase Base;
- begin scalar MarkInfo;
- MarkTag := Tag Base;
- if not PointerTagP MarkTag then return
- << if MarkTag = ID and not null Base then
- << MarkInfo := IDInf Base;
- if not MarkedID MarkInfo then MarkFromOneSymbol MarkInfo >> >>;
- MarkInfo := Inf Base;
- if not WithinHeapPointer MarkInfo
- or Marked MarkInfo then return;
- SetMark MarkInfo;
- CommentOutCode CheckAndSetMark MarkInfo;
- return if MarkTag eq VECT or MarkTag eq EVECT then
- MarkFromVector MarkInfo
- else if MarkTag eq PAIR then
- << MarkFromBase car Base;
- MarkFromBase cdr Base >>;
- end;
- CommentOutCode <<
- syslsp procedure CheckAndSetMark P;
- begin scalar HeadAtP;
- HeadAtP := Tag @P;
- case MarkTag of
- STR:
- if HeadAtP eq HBYTES then SetMark P;
- FIXN, FLTN, BIGN, WRDS:
- if HeadAtP eq HWRDS then SetMark P;
- VECT, EVECT:
- if HeadAtP eq HVECT then SetMark P;
- PAIR:
- SetMark P;
- default:
- GCError("Internal error in marking phase, at %o", P)
- end;
- end;
- >>;
- syslsp procedure MarkFromVector Info;
- begin scalar Uplim;
- CommentOutCode if Tag @Info neq HVECT then return;
- Uplim := &VecItm(Info, VecLen Info);
- for Ptr := &VecItm(Info, 0) step 1 until Uplim do
- MarkFromBase @Ptr;
- end;
- syslsp procedure MakeIDFreeList();
- begin scalar Previous;
- for I := 0 step 1 until 128 do
- ClearIDMark I;
- Previous := 129;
- while MarkedID Previous and Previous <= MaxSymbols do
- << ClearIDMark Previous;
- Previous := Previous + 1 >>;
- if Previous >= MaxSymbols then
- NextSymbol := 0
- else
- NextSymbol := Previous; % free list starts here
- for I := Previous + 1 step 1 until MaxSymbols do
- if MarkedID I then ClearIDMark I
- else
- << SymNam Previous := I;
- Previous := I >>;
- SymNam Previous := 0; % end of free list
- end;
- syslsp procedure BuildRelocationFields();
- %
- % Pass 2 - Turn off GC marks and Build SEGKNTs
- %
- begin scalar CurrentItem, SGCurrent, IGCurrent, TmpIG, DCount, SegLen;
- SGCurrent := IGCurrent := 0;
- SegmentMovement SGCurrent := 0; % Dummy
- Hole := HeapLowerBound - 1; % will be first hole
- DCount := HeapShrink := 0; % holes in current segment, total holes
- CurrentItem := HeapLowerBound;
- while CurrentItem < HeapLast do
- begin scalar Incr;
- SegLen := case Tag @CurrentItem of
- BTRTAG, CODE, NEGINT, POSINT, ID, UNBOUND,
- STR, BYTES, FIXN, FLTN, BIGN, WRDS, Halfwords, PAIR, VECT, EVECT:
- 2; % must be first of pair
- HBYTES:
- 1 + StrPack StrLen CurrentItem;
- HHalfwords:
- 1 + HalfWordPack StrLen CurrentItem;
- HWRDS:
- 1 + WrdPack WrdLen CurrentItem;
- HVECT:
- 1 + VectPack VecLen CurrentItem;
- HSKIP:
- SkipLength CurrentItem;
- default:
- GCError("Illegal item in heap at %o", CurrentItem)
- end; % case
- if Marked CurrentItem then % a hole
- if HeapShrink = 0 then
- ClearMark CurrentItem
- else % segment also clears mark
- << MovementWithinSegment CurrentItem := DCount; % incremental shift
- Incr := 0 >> % no shift
- else
- << @CurrentItem := MkItem(HSKIP, SegLen); % a skip mark
- Incr := 1; % more shift
- if Hole < HeapLowerBound then Hole := CurrentItem >>;
- TmpIG := IGCurrent + SegLen; % set SEG size
- CurrentItem := CurrentItem + SegLen;
- while TmpIG >= SegmentLength do
- begin scalar Tmp;
- Tmp := SegmentLength - IGCurrent; % Expand to next SEGMENT
- SegLen := SegLen - Tmp;
- if Incr eq 1 then HeapShrink := HeapShrink + Tmp;
- DCount := IGCurrent := 0;
- SGCurrent := SGCurrent + 1;
- SegmentMovement SGCurrent := HeapShrink; % Store Next Base
- TmpIG := TmpIG - SegmentLength;
- end;
- IGCurrent := TmpIG;
- if Incr eq 1 then
- << HeapShrink := HeapShrink + SegLen;
- DCount := DCount + SegLen >>; % Add in Hole Size
- end;
- SegmentMovement(SGCurrent + 1) := HeapShrink;
- end;
- syslsp procedure UpdateAllBases();
- begin scalar B;
- UpdateSymbols();
- UpdateRegion(StackStart, StackEnd);
- B := BndStkLowerBound;
- while << B := AdjustBndStkPtr(B, 1);
- B <= BndStkPtr >> do
- UpdateItem B;
- UpdateHeap() >>;
- syslsp procedure UpdateSymbols();
- for I := 0 step 1 until MaxSymbols do
- begin scalar NameLoc;
- NameLoc := &SymNam I;
- if StringP @NameLoc then
- << UpdateItem NameLoc;
- UpdateItem &SymVal I;
- UpdateItem &SymPrp I >>;
- end;
- syslsp procedure UpdateRegion(Low, High);
- for Ptr := Low step 1 until High do UpdateItem Ptr;
- syslsp procedure UpdateHeap();
- begin scalar CurrentItem;
- CurrentItem := HeapLowerBound;
- while CurrentItem < HeapLast do
- begin
- case Tag @CurrentItem of
- BTRTAG, CODE, NEGINT, POSINT, ID, UNBOUND:
- CurrentItem := CurrentItem + 1;
- STR, BYTES, FIXN, FLTN, BIGN, WRDS, Halfwords, PAIR, VECT, EVECT:
- << if Inf @CurrentItem >= Hole and Inf @CurrentItem <= HeapLast then
- Inf @CurrentItem := Reloc Inf @CurrentItem;
- CurrentItem := CurrentItem + 1 >>;
- HBYTES:
- CurrentItem := CurrentItem + 1 + StrPack StrLen CurrentItem;
- HHalfwords:
- CurrentItem := CurrentItem + 1 + HalfwordPack StrLen CurrentItem;
- HWRDS:
- CurrentItem := CurrentItem + 1 + WrdPack WrdLen CurrentItem;
- HVECT:
- begin scalar Tmp;
- Tmp := VecLen CurrentItem;
- CurrentItem := CurrentItem + 1; % Move over header
- for I := 0 step 1 until Tmp do % VecLen + 1 items
- begin scalar Tmp2, Tmp3;
- Tmp2 := @CurrentItem;
- Tmp3 := Tag Tmp2;
- if PointerTagP Tmp3
- and Inf Tmp2 >= Hole and Inf Tmp2 <= HeapLast then
- Inf @CurrentItem := Reloc Inf Tmp2;
- CurrentItem := CurrentItem + 1;
- end;
- end;
- HSKIP:
- CurrentItem := CurrentItem + SkipLength CurrentItem;
- default:
- GCError("Internal error in updating phase at %o", CurrentItem)
- end; % case
- end
- end;
- syslsp procedure UpdateItem Ptr;
- begin scalar Tg, Info;
- Tg := Tag @Ptr;
- if not PointerTagP Tg then return;
- Info := INF @Ptr;
- if Info < Hole or Info > HeapLast then return;
- Inf @Ptr := Reloc Info;
- end;
- syslsp procedure CompactHeap();
- begin scalar OldItemPtr, NewItemPtr, SegLen;
- if Hole < HeapLowerBound then return;
- NewItemPtr := OldItemPtr := Hole;
- while OldItemPtr < HeapLast do
- begin;
- case Tag @OldItemPtr of
- BTRTAG, CODE, NEGINT, POSINT, ID, UNBOUND,
- STR, BYTES, FIXN, FLTN, BIGN, WRDS, Halfwords, PAIR, VECT, EVECT:
- SegLen := PairPack OldItemPtr;
- HBYTES:
- SegLen := 1 + StrPack StrLen OldItemPtr;
- HHalfwords:
- SegLen := 1 + HalfWordPack HalfwordLen OldItemPtr;
- HWRDS:
- SegLen := 1 + WrdPack WrdLen OldItemPtr;
- HVECT:
- SegLen := 1 + VectPack VecLen OldItemPtr;
- HSKIP:
- << OldItemPtr := OldItemPtr + SkipLength OldItemPtr;
- goto WhileNext >>;
- default:
- GCError("Internal error in compaction at %o", OldItemPtr)
- end; % case
- ClearMovementWithinSegment OldItemPtr;
- for I := 1 step 1 until SegLen do
- << @NewItemPtr := @OldItemPtr;
- NewItemPtr := NewItemPtr + 1;
- OldItemPtr := OldItemPtr + 1 >>;
- WhileNext:
- end;
- end;
- syslsp procedure GCError(Message, P);
- << ErrorPrintF("***** Fatal error during garbage collection");
- ErrorPrintF(Message, P);
- while T do Quit; >>;
- syslsp procedure GCMessage();
- << ErrorPrintF("*** GC %w: time %d ms",
- LispVar GCKnt!*, StartingRealTime);
- ErrorPrintF("*** %d recovered, %d stable, %d active, %d free",
- HeapShrink, Hole - HeapLowerBound,
- HeapLast - Hole,
- intinf known!-free!-space() ) >>;
- off SysLisp;
- END;
|