1*37da2899SCharles.Forsyth #include "lib9.h"
2*37da2899SCharles.Forsyth #include "interp.h"
3*37da2899SCharles.Forsyth #include "pool.h"
4*37da2899SCharles.Forsyth
5*37da2899SCharles.Forsyth enum
6*37da2899SCharles.Forsyth {
7*37da2899SCharles.Forsyth Quanta = 50, /* Allocated blocks to sweep each time slice usually */
8*37da2899SCharles.Forsyth MaxQuanta = 15*Quanta,
9*37da2899SCharles.Forsyth PTRHASH = (1<<5)
10*37da2899SCharles.Forsyth };
11*37da2899SCharles.Forsyth
12*37da2899SCharles.Forsyth static int quanta = Quanta;
13*37da2899SCharles.Forsyth static int gce, gct = 1;
14*37da2899SCharles.Forsyth
15*37da2899SCharles.Forsyth typedef struct Ptrhash Ptrhash;
16*37da2899SCharles.Forsyth struct Ptrhash
17*37da2899SCharles.Forsyth {
18*37da2899SCharles.Forsyth Heap *value;
19*37da2899SCharles.Forsyth Ptrhash *next;
20*37da2899SCharles.Forsyth };
21*37da2899SCharles.Forsyth
22*37da2899SCharles.Forsyth int nprop;
23*37da2899SCharles.Forsyth int gchalt;
24*37da2899SCharles.Forsyth int mflag;
25*37da2899SCharles.Forsyth int mutator = 0;
26*37da2899SCharles.Forsyth int gccolor = 3;
27*37da2899SCharles.Forsyth
28*37da2899SCharles.Forsyth ulong gcnruns;
29*37da2899SCharles.Forsyth ulong gcsweeps;
30*37da2899SCharles.Forsyth ulong gcbroken;
31*37da2899SCharles.Forsyth ulong gchalted;
32*37da2899SCharles.Forsyth ulong gcepochs;
33*37da2899SCharles.Forsyth uvlong gcdestroys;
34*37da2899SCharles.Forsyth uvlong gcinspects;
35*37da2899SCharles.Forsyth
36*37da2899SCharles.Forsyth static int marker = 1;
37*37da2899SCharles.Forsyth static int sweeper = 2;
38*37da2899SCharles.Forsyth static Bhdr* base;
39*37da2899SCharles.Forsyth static Bhdr* limit;
40*37da2899SCharles.Forsyth Bhdr* ptr;
41*37da2899SCharles.Forsyth static int visit;
42*37da2899SCharles.Forsyth extern Pool* heapmem;
43*37da2899SCharles.Forsyth static Ptrhash *ptrtab[PTRHASH];
44*37da2899SCharles.Forsyth static Ptrhash *ptrfree;
45*37da2899SCharles.Forsyth
46*37da2899SCharles.Forsyth #define HASHPTR(p) (((ulong)(p) >> 6) & (PTRHASH - 1))
47*37da2899SCharles.Forsyth
48*37da2899SCharles.Forsyth void
ptradd(Heap * v)49*37da2899SCharles.Forsyth ptradd(Heap *v)
50*37da2899SCharles.Forsyth {
51*37da2899SCharles.Forsyth int h;
52*37da2899SCharles.Forsyth Ptrhash *p;
53*37da2899SCharles.Forsyth
54*37da2899SCharles.Forsyth if ((p = ptrfree) != nil)
55*37da2899SCharles.Forsyth ptrfree = p->next;
56*37da2899SCharles.Forsyth else if ((p = malloc(sizeof (Ptrhash))) == nil)
57*37da2899SCharles.Forsyth error("ptradd malloc");
58*37da2899SCharles.Forsyth h = HASHPTR(v);
59*37da2899SCharles.Forsyth p->value = v;
60*37da2899SCharles.Forsyth p->next = ptrtab[h];
61*37da2899SCharles.Forsyth ptrtab[h] = p;
62*37da2899SCharles.Forsyth }
63*37da2899SCharles.Forsyth
64*37da2899SCharles.Forsyth void
ptrdel(Heap * v)65*37da2899SCharles.Forsyth ptrdel(Heap *v)
66*37da2899SCharles.Forsyth {
67*37da2899SCharles.Forsyth Ptrhash *p, **l;
68*37da2899SCharles.Forsyth
69*37da2899SCharles.Forsyth for (l = &ptrtab[HASHPTR(v)]; (p = *l) != nil; l = &p->next) {
70*37da2899SCharles.Forsyth if (p->value == v) {
71*37da2899SCharles.Forsyth *l = p->next;
72*37da2899SCharles.Forsyth p->next = ptrfree;
73*37da2899SCharles.Forsyth ptrfree = p;
74*37da2899SCharles.Forsyth return;
75*37da2899SCharles.Forsyth }
76*37da2899SCharles.Forsyth }
77*37da2899SCharles.Forsyth /* ptradd must have failed */
78*37da2899SCharles.Forsyth }
79*37da2899SCharles.Forsyth
80*37da2899SCharles.Forsyth static void
ptrmark(void)81*37da2899SCharles.Forsyth ptrmark(void)
82*37da2899SCharles.Forsyth {
83*37da2899SCharles.Forsyth int i;
84*37da2899SCharles.Forsyth Heap *h;
85*37da2899SCharles.Forsyth Ptrhash *p;
86*37da2899SCharles.Forsyth
87*37da2899SCharles.Forsyth for (i = 0; i < PTRHASH; i++) {
88*37da2899SCharles.Forsyth for (p = ptrtab[i]; p != nil; p = p->next) {
89*37da2899SCharles.Forsyth h = p->value;
90*37da2899SCharles.Forsyth Setmark(h);
91*37da2899SCharles.Forsyth }
92*37da2899SCharles.Forsyth }
93*37da2899SCharles.Forsyth }
94*37da2899SCharles.Forsyth
95*37da2899SCharles.Forsyth void
noptrs(Type * t,void * vw)96*37da2899SCharles.Forsyth noptrs(Type *t, void *vw)
97*37da2899SCharles.Forsyth {
98*37da2899SCharles.Forsyth USED(t);
99*37da2899SCharles.Forsyth USED(vw);
100*37da2899SCharles.Forsyth }
101*37da2899SCharles.Forsyth
102*37da2899SCharles.Forsyth static int markdepth;
103*37da2899SCharles.Forsyth
104*37da2899SCharles.Forsyth /* code simpler with a depth search compared to a width search*/
105*37da2899SCharles.Forsyth void
markheap(Type * t,void * vw)106*37da2899SCharles.Forsyth markheap(Type *t, void *vw)
107*37da2899SCharles.Forsyth {
108*37da2899SCharles.Forsyth Heap *h;
109*37da2899SCharles.Forsyth uchar *p;
110*37da2899SCharles.Forsyth int i, c, m;
111*37da2899SCharles.Forsyth WORD **w, **q;
112*37da2899SCharles.Forsyth Type *t1;
113*37da2899SCharles.Forsyth
114*37da2899SCharles.Forsyth if(t == nil || t->np == 0)
115*37da2899SCharles.Forsyth return;
116*37da2899SCharles.Forsyth
117*37da2899SCharles.Forsyth markdepth++;
118*37da2899SCharles.Forsyth w = (WORD**)vw;
119*37da2899SCharles.Forsyth p = t->map;
120*37da2899SCharles.Forsyth for(i = 0; i < t->np; i++) {
121*37da2899SCharles.Forsyth c = *p++;
122*37da2899SCharles.Forsyth if(c != 0) {
123*37da2899SCharles.Forsyth q = w;
124*37da2899SCharles.Forsyth for(m = 0x80; m != 0; m >>= 1) {
125*37da2899SCharles.Forsyth if((c & m) && *q != H) {
126*37da2899SCharles.Forsyth h = D2H(*q);
127*37da2899SCharles.Forsyth Setmark(h);
128*37da2899SCharles.Forsyth if(h->color == propagator && --visit >= 0 && markdepth < 64){
129*37da2899SCharles.Forsyth gce--;
130*37da2899SCharles.Forsyth h->color = mutator;
131*37da2899SCharles.Forsyth if((t1 = h->t) != nil)
132*37da2899SCharles.Forsyth t1->mark(t1, H2D(void*, h));
133*37da2899SCharles.Forsyth }
134*37da2899SCharles.Forsyth }
135*37da2899SCharles.Forsyth q++;
136*37da2899SCharles.Forsyth }
137*37da2899SCharles.Forsyth }
138*37da2899SCharles.Forsyth w += 8;
139*37da2899SCharles.Forsyth }
140*37da2899SCharles.Forsyth markdepth--;
141*37da2899SCharles.Forsyth }
142*37da2899SCharles.Forsyth
143*37da2899SCharles.Forsyth /*
144*37da2899SCharles.Forsyth * This routine should be modified to be incremental, but how?
145*37da2899SCharles.Forsyth */
146*37da2899SCharles.Forsyth void
markarray(Type * t,void * vw)147*37da2899SCharles.Forsyth markarray(Type *t, void *vw)
148*37da2899SCharles.Forsyth {
149*37da2899SCharles.Forsyth int i;
150*37da2899SCharles.Forsyth Heap *h;
151*37da2899SCharles.Forsyth uchar *v;
152*37da2899SCharles.Forsyth Array *a;
153*37da2899SCharles.Forsyth
154*37da2899SCharles.Forsyth USED(t);
155*37da2899SCharles.Forsyth
156*37da2899SCharles.Forsyth a = vw;
157*37da2899SCharles.Forsyth t = a->t;
158*37da2899SCharles.Forsyth if(a->root != H) {
159*37da2899SCharles.Forsyth h = D2H(a->root);
160*37da2899SCharles.Forsyth Setmark(h);
161*37da2899SCharles.Forsyth }
162*37da2899SCharles.Forsyth
163*37da2899SCharles.Forsyth if(t->np == 0)
164*37da2899SCharles.Forsyth return;
165*37da2899SCharles.Forsyth
166*37da2899SCharles.Forsyth v = a->data;
167*37da2899SCharles.Forsyth for(i = 0; i < a->len; i++) {
168*37da2899SCharles.Forsyth markheap(t, v);
169*37da2899SCharles.Forsyth v += t->size;
170*37da2899SCharles.Forsyth }
171*37da2899SCharles.Forsyth visit -= a->len;
172*37da2899SCharles.Forsyth }
173*37da2899SCharles.Forsyth
174*37da2899SCharles.Forsyth void
marklist(Type * t,void * vw)175*37da2899SCharles.Forsyth marklist(Type *t, void *vw)
176*37da2899SCharles.Forsyth {
177*37da2899SCharles.Forsyth List *l;
178*37da2899SCharles.Forsyth Heap *h;
179*37da2899SCharles.Forsyth
180*37da2899SCharles.Forsyth USED(t);
181*37da2899SCharles.Forsyth l = vw;
182*37da2899SCharles.Forsyth markheap(l->t, l->data);
183*37da2899SCharles.Forsyth while(visit > 0) {
184*37da2899SCharles.Forsyth l = l->tail;
185*37da2899SCharles.Forsyth if(l == H)
186*37da2899SCharles.Forsyth return;
187*37da2899SCharles.Forsyth h = D2H(l);
188*37da2899SCharles.Forsyth Setmark(h);
189*37da2899SCharles.Forsyth markheap(l->t, l->data);
190*37da2899SCharles.Forsyth visit--;
191*37da2899SCharles.Forsyth }
192*37da2899SCharles.Forsyth l = l->tail;
193*37da2899SCharles.Forsyth if(l != H) {
194*37da2899SCharles.Forsyth D2H(l)->color = propagator;
195*37da2899SCharles.Forsyth nprop = 1;
196*37da2899SCharles.Forsyth }
197*37da2899SCharles.Forsyth }
198*37da2899SCharles.Forsyth
199*37da2899SCharles.Forsyth static void
rootset(Prog * root)200*37da2899SCharles.Forsyth rootset(Prog *root)
201*37da2899SCharles.Forsyth {
202*37da2899SCharles.Forsyth Heap *h;
203*37da2899SCharles.Forsyth Type *t;
204*37da2899SCharles.Forsyth Frame *f;
205*37da2899SCharles.Forsyth Module *m;
206*37da2899SCharles.Forsyth Stkext *sx;
207*37da2899SCharles.Forsyth Modlink *ml;
208*37da2899SCharles.Forsyth uchar *fp, *sp, *ex, *mp;
209*37da2899SCharles.Forsyth
210*37da2899SCharles.Forsyth mutator = gccolor % 3;
211*37da2899SCharles.Forsyth marker = (gccolor-1)%3;
212*37da2899SCharles.Forsyth sweeper = (gccolor-2)%3;
213*37da2899SCharles.Forsyth
214*37da2899SCharles.Forsyth while(root != nil) {
215*37da2899SCharles.Forsyth ml = root->R.M;
216*37da2899SCharles.Forsyth h = D2H(ml);
217*37da2899SCharles.Forsyth Setmark(h);
218*37da2899SCharles.Forsyth mp = ml->MP;
219*37da2899SCharles.Forsyth if(mp != H) {
220*37da2899SCharles.Forsyth h = D2H(mp);
221*37da2899SCharles.Forsyth Setmark(h);
222*37da2899SCharles.Forsyth }
223*37da2899SCharles.Forsyth
224*37da2899SCharles.Forsyth sp = root->R.SP;
225*37da2899SCharles.Forsyth ex = root->R.EX;
226*37da2899SCharles.Forsyth while(ex != nil) {
227*37da2899SCharles.Forsyth sx = (Stkext*)ex;
228*37da2899SCharles.Forsyth fp = sx->reg.tos.fu;
229*37da2899SCharles.Forsyth while(fp != sp) {
230*37da2899SCharles.Forsyth f = (Frame*)fp;
231*37da2899SCharles.Forsyth t = f->t;
232*37da2899SCharles.Forsyth if(t == nil)
233*37da2899SCharles.Forsyth t = sx->reg.TR;
234*37da2899SCharles.Forsyth fp += t->size;
235*37da2899SCharles.Forsyth t->mark(t, f);
236*37da2899SCharles.Forsyth ml = f->mr;
237*37da2899SCharles.Forsyth if(ml != nil) {
238*37da2899SCharles.Forsyth h = D2H(ml);
239*37da2899SCharles.Forsyth Setmark(h);
240*37da2899SCharles.Forsyth mp = ml->MP;
241*37da2899SCharles.Forsyth if(mp != H) {
242*37da2899SCharles.Forsyth h = D2H(mp);
243*37da2899SCharles.Forsyth Setmark(h);
244*37da2899SCharles.Forsyth }
245*37da2899SCharles.Forsyth }
246*37da2899SCharles.Forsyth }
247*37da2899SCharles.Forsyth ex = sx->reg.EX;
248*37da2899SCharles.Forsyth sp = sx->reg.SP;
249*37da2899SCharles.Forsyth }
250*37da2899SCharles.Forsyth
251*37da2899SCharles.Forsyth root = root->next;
252*37da2899SCharles.Forsyth }
253*37da2899SCharles.Forsyth
254*37da2899SCharles.Forsyth for(m = modules; m != nil; m = m->link) {
255*37da2899SCharles.Forsyth if(m->origmp != H) {
256*37da2899SCharles.Forsyth h = D2H(m->origmp);
257*37da2899SCharles.Forsyth Setmark(h);
258*37da2899SCharles.Forsyth }
259*37da2899SCharles.Forsyth }
260*37da2899SCharles.Forsyth
261*37da2899SCharles.Forsyth ptrmark();
262*37da2899SCharles.Forsyth }
263*37da2899SCharles.Forsyth
264*37da2899SCharles.Forsyth static int
okbhdr(Bhdr * b)265*37da2899SCharles.Forsyth okbhdr(Bhdr *b)
266*37da2899SCharles.Forsyth {
267*37da2899SCharles.Forsyth if(b == nil)
268*37da2899SCharles.Forsyth return 0;
269*37da2899SCharles.Forsyth switch(b->magic) {
270*37da2899SCharles.Forsyth case MAGIC_A:
271*37da2899SCharles.Forsyth case MAGIC_F:
272*37da2899SCharles.Forsyth case MAGIC_E:
273*37da2899SCharles.Forsyth case MAGIC_I:
274*37da2899SCharles.Forsyth return 1;
275*37da2899SCharles.Forsyth }
276*37da2899SCharles.Forsyth return 0;
277*37da2899SCharles.Forsyth }
278*37da2899SCharles.Forsyth
279*37da2899SCharles.Forsyth static void
domflag(Heap * h)280*37da2899SCharles.Forsyth domflag(Heap *h)
281*37da2899SCharles.Forsyth {
282*37da2899SCharles.Forsyth int i;
283*37da2899SCharles.Forsyth Module *m;
284*37da2899SCharles.Forsyth
285*37da2899SCharles.Forsyth print("sweep h=0x%lux t=0x%lux c=%d", (ulong)h, (ulong)h->t, h->color);
286*37da2899SCharles.Forsyth for(m = modules; m != nil; m = m->link) {
287*37da2899SCharles.Forsyth for(i = 0; i < m->ntype; i++) {
288*37da2899SCharles.Forsyth if(m->type[i] == h->t) {
289*37da2899SCharles.Forsyth print(" module %s desc %d", m->name, i);
290*37da2899SCharles.Forsyth break;
291*37da2899SCharles.Forsyth }
292*37da2899SCharles.Forsyth }
293*37da2899SCharles.Forsyth }
294*37da2899SCharles.Forsyth print("\n");
295*37da2899SCharles.Forsyth if(mflag > 1)
296*37da2899SCharles.Forsyth abort();
297*37da2899SCharles.Forsyth }
298*37da2899SCharles.Forsyth
299*37da2899SCharles.Forsyth void
rungc(Prog * p)300*37da2899SCharles.Forsyth rungc(Prog *p)
301*37da2899SCharles.Forsyth {
302*37da2899SCharles.Forsyth Type *t;
303*37da2899SCharles.Forsyth Heap *h;
304*37da2899SCharles.Forsyth Bhdr *b;
305*37da2899SCharles.Forsyth
306*37da2899SCharles.Forsyth gcnruns++;
307*37da2899SCharles.Forsyth if(gchalt) {
308*37da2899SCharles.Forsyth gchalted++;
309*37da2899SCharles.Forsyth return;
310*37da2899SCharles.Forsyth }
311*37da2899SCharles.Forsyth if(base == nil) {
312*37da2899SCharles.Forsyth gcsweeps++;
313*37da2899SCharles.Forsyth b = poolchain(heapmem);
314*37da2899SCharles.Forsyth base = b;
315*37da2899SCharles.Forsyth ptr = b;
316*37da2899SCharles.Forsyth limit = B2LIMIT(b);
317*37da2899SCharles.Forsyth }
318*37da2899SCharles.Forsyth
319*37da2899SCharles.Forsyth /* Chain broken ? */
320*37da2899SCharles.Forsyth if(!okbhdr(ptr)) {
321*37da2899SCharles.Forsyth base = nil;
322*37da2899SCharles.Forsyth gcbroken++;
323*37da2899SCharles.Forsyth return;
324*37da2899SCharles.Forsyth }
325*37da2899SCharles.Forsyth
326*37da2899SCharles.Forsyth for(visit = quanta; visit > 0; ) {
327*37da2899SCharles.Forsyth if(ptr->magic == MAGIC_A) {
328*37da2899SCharles.Forsyth visit--;
329*37da2899SCharles.Forsyth gct++;
330*37da2899SCharles.Forsyth gcinspects++;
331*37da2899SCharles.Forsyth h = B2D(ptr);
332*37da2899SCharles.Forsyth t = h->t;
333*37da2899SCharles.Forsyth if(h->color == propagator) {
334*37da2899SCharles.Forsyth gce--;
335*37da2899SCharles.Forsyth h->color = mutator;
336*37da2899SCharles.Forsyth if(t != nil)
337*37da2899SCharles.Forsyth t->mark(t, H2D(void*, h));
338*37da2899SCharles.Forsyth }
339*37da2899SCharles.Forsyth else
340*37da2899SCharles.Forsyth if(h->color == sweeper) {
341*37da2899SCharles.Forsyth gce++;
342*37da2899SCharles.Forsyth if(0 && mflag)
343*37da2899SCharles.Forsyth domflag(h);
344*37da2899SCharles.Forsyth if(heapmonitor != nil)
345*37da2899SCharles.Forsyth heapmonitor(2, h, 0);
346*37da2899SCharles.Forsyth if(t != nil) {
347*37da2899SCharles.Forsyth gclock();
348*37da2899SCharles.Forsyth t->free(h, 1);
349*37da2899SCharles.Forsyth gcunlock();
350*37da2899SCharles.Forsyth freetype(t);
351*37da2899SCharles.Forsyth }
352*37da2899SCharles.Forsyth gcdestroys++;
353*37da2899SCharles.Forsyth poolfree(heapmem, h);
354*37da2899SCharles.Forsyth }
355*37da2899SCharles.Forsyth }
356*37da2899SCharles.Forsyth ptr = B2NB(ptr);
357*37da2899SCharles.Forsyth if(ptr >= limit) {
358*37da2899SCharles.Forsyth base = base->clink;
359*37da2899SCharles.Forsyth if(base == nil)
360*37da2899SCharles.Forsyth break;
361*37da2899SCharles.Forsyth ptr = base;
362*37da2899SCharles.Forsyth limit = B2LIMIT(base);
363*37da2899SCharles.Forsyth }
364*37da2899SCharles.Forsyth }
365*37da2899SCharles.Forsyth
366*37da2899SCharles.Forsyth quanta = (MaxQuanta+Quanta)/2 + ((MaxQuanta-Quanta)/20)*((100*gce)/gct);
367*37da2899SCharles.Forsyth if(quanta < Quanta)
368*37da2899SCharles.Forsyth quanta = Quanta;
369*37da2899SCharles.Forsyth if(quanta > MaxQuanta)
370*37da2899SCharles.Forsyth quanta = MaxQuanta;
371*37da2899SCharles.Forsyth
372*37da2899SCharles.Forsyth if(base != nil) /* Completed this iteration ? */
373*37da2899SCharles.Forsyth return;
374*37da2899SCharles.Forsyth if(nprop == 0) { /* Completed the epoch ? */
375*37da2899SCharles.Forsyth gcepochs++;
376*37da2899SCharles.Forsyth gccolor++;
377*37da2899SCharles.Forsyth rootset(p);
378*37da2899SCharles.Forsyth gce = 0;
379*37da2899SCharles.Forsyth gct = 1;
380*37da2899SCharles.Forsyth return;
381*37da2899SCharles.Forsyth }
382*37da2899SCharles.Forsyth nprop = 0;
383*37da2899SCharles.Forsyth }
384