xref: /inferno-os/libinterp/gc.c (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
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