1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128
|
/*======================================================================
GCSI(s,EACSTACK)
Garbage collection, system independent.
Inputs
s : a BETA-digit, the size in bytes at which data is aligned on the
stack.
EACSTACK : a C pointer, the address of the last element on the stack.
Side effects
Active variables are marked. Then a new available cell list is formed
from the unmarked cells and the marks are removed.
If GCM=1 a report is written out. If the number of reclaimed cells
is no more than NU / RHO then a message is written and a failure
occurs.
======================================================================*/
#include "replacesac.h"
#include <cstdio>
extern "C" {
extern void gcw_MARK();
}
void GCSI(Word s, char *EACSTACK)
{
Word I,L,N,N1,Np,Np1,T,T1,c,inc;
char *a;
/* hide I,L,N,N1,Np,Np1,T,T1,c,inc,a; */
Step1: /* Setup. */
if (GCM == 1) {
SWRITE("\nThe "); GWRITE(GCC+1);
SWRITE("--th garbage collection....\n");
}
T1 = CLOCK();
Step3: /* Mark the global variables. */
L = GCGLOBALS;
while (L != NIL) {
c = *((Word *)PTRFIRST(L));
if ((ISLIST(c) || ISGCA(c)) && !ISNIL(c)) MARK(c);
L = PTRRED(L);
}
Step2: /* Mark the cells in the GCGLOBALS list. */
L = GCGLOBALS;
while (L != NIL) {
I = RED(L);
SRED(L,-I);
L = I;
}
Step3b: /* Mark the GCWord variables. */
gcw_MARK();
Step4: /* Mark the cells accessible from the system stack. */
if (((BACSTACK - EACSTACK) % s) != 0)
FAIL("GCSI (marking stack)","Alignment error",BACSTACK,EACSTACK);
if (EACSTACK > BACSTACK)
inc = s;
else
inc = -s;
for (a = BACSTACK; a != EACSTACK; a += inc) {
c = *((Word *) a);
if ((ISLIST(c) || ISGCA(c)) && !ISNIL(c)) MARK(c);
}
Step5: /* Unmark the cells in the AVAIL and GCAAVAIL lists. */
for (L=AVAIL,N1=0; L!=NIL; L=RED(L),N1++)
if (RED(L) <= -BETA)
SRED(L,-RED(L));
for (L=GCAAVAIL,Np1=0; L!=NIL; L=GCASPACEBp[L].next,Np1++)
if (GCASPACEBp[L].next <= -BETA)
GCASPACEBp[L].next = -GCASPACEBp[L].next;
Step6: /* Reclaim unmarked cells */
AVAIL = NIL;
N = 0;
for (L = BETA+NU-1; L > BETA; L -= 2) {
if (RED(L) > 0) {
SRED(L,AVAIL);
SFIRST(L,0);
AVAIL = L;
N++;
}
else
SRED(L,-RED(L));
}
GCAAVAIL = NIL;
Np = 0;
for (I = BETApp-1; I > BETAp; I--) {
if (GCASPACEBp[I].next > 0) {
GCAFREE(I);
Np++;
}
else
GCASPACEBp[I].next = -GCASPACEBp[I].next;
}
Step7: /* Increment counters. */
T = CLOCK() - T1;
TAU = TAU + T;
GCC = GCC + 1;
GCCC = GCCC + N - N1;
GCAC = GCAC + Np - Np1;
Step8: /* Optional report. */
if (GCM == 1 || N <= NU / RHO) {
SWRITE("\n** ");
GWRITE(N); SWRITE(" cells, ");
GWRITE(Np); SWRITE(" arrays in ");
GWRITE(T); SWRITE(" milliseconds.\n");
}
Step9: /* Too few cells or arrays? */
if (N <= NU / RHO)
FAIL("GCSI (final check)","Too few cells reclaimed.",N,NU,RHO);
if (Np == 0)
FAIL("GCSI (final check)","No arrays reclaimed.",N,NU,RHO);
Return: /* Prepare for return. */
return;
}
|