xref: /inferno-os/libinterp/heap.c (revision 4d5741c99d03109e40fcb809811368ccd4aa911b)
1 #include "lib9.h"
2 #include "isa.h"
3 #include "interp.h"
4 #include "pool.h"
5 #include "raise.h"
6 
7 void	freearray(Heap*, int);
8 void	freelist(Heap*, int);
9 void	freemodlink(Heap*, int);
10 void	freechan(Heap*, int);
11 Type	Tarray = { 1, freearray, markarray, sizeof(Array) };
12 Type	Tstring = { 1, freestring, noptrs, sizeof(String) };
13 Type	Tlist = { 1, freelist, marklist, sizeof(List) };
14 Type	Tmodlink = { 1, freemodlink, markheap, -1, 1, 0, 0, { 0x80 } };
15 Type	Tchannel = { 1, freechan, markheap, sizeof(Channel), 1,0,0,{0x80} };
16 Type	Tptr = { 1, 0, markheap, sizeof(WORD*), 1, 0, 0, { 0x80 } };
17 Type	Tbyte = { 1, 0, 0, 1 };
18 Type Tword = { 1, 0, 0, sizeof(WORD) };
19 Type Tlong = { 1, 0, 0, sizeof(LONG) };
20 Type Treal = { 1, 0, 0, sizeof(REAL) };
21 
22 extern	Pool*	heapmem;
23 extern	int	mutator;
24 
25 void	(*heapmonitor)(int, void*, ulong);
26 
27 #define	BIT(bt, nb)	(bt & (1<<nb))
28 
29 void
freeptrs(void * v,Type * t)30 freeptrs(void *v, Type *t)
31 {
32 	int c;
33 	WORD **w, *x;
34 	uchar *p, *ep;
35 
36 	if(t->np == 0)
37 		return;
38 
39 	w = (WORD**)v;
40 	p = t->map;
41 	ep = p + t->np;
42 	while(p < ep) {
43 		c = *p;
44 		if(c != 0) {
45  			if(BIT(c, 0) && (x = w[7]) != H) destroy(x);
46 			if(BIT(c, 1) && (x = w[6]) != H) destroy(x);
47  			if(BIT(c, 2) && (x = w[5]) != H) destroy(x);
48 			if(BIT(c, 3) && (x = w[4]) != H) destroy(x);
49 			if(BIT(c, 4) && (x = w[3]) != H) destroy(x);
50 			if(BIT(c, 5) && (x = w[2]) != H) destroy(x);
51 			if(BIT(c, 6) && (x = w[1]) != H) destroy(x);
52 			if(BIT(c, 7) && (x = w[0]) != H) destroy(x);
53 		}
54 		p++;
55 		w += 8;
56 	}
57 }
58 
59 /*
60 void
61 nilptrs(void *v, Type *t)
62 {
63 	int c, i;
64 	WORD **w;
65 	uchar *p, *ep;
66 
67 	w = (WORD**)v;
68 	p = t->map;
69 	ep = p + t->np;
70 	while(p < ep) {
71 		c = *p;
72 		for(i = 0; i < 8; i++){
73 			if(BIT(c, 7)) *w = H;
74 			c <<= 1;
75 			w++;
76 		}
77 		p++;
78 	}
79 }
80 */
81 
82 void
freechan(Heap * h,int swept)83 freechan(Heap *h, int swept)
84 {
85 	Channel *c;
86 
87 	USED(swept);
88 	c = H2D(Channel*, h);
89 	if(c->mover == movtmp)
90 		freetype(c->mid.t);
91 	killcomm(&c->send);
92 	killcomm(&c->recv);
93 	if (!swept && c->buf != H)
94 		destroy(c->buf);
95 }
96 
97 void
freestring(Heap * h,int swept)98 freestring(Heap *h, int swept)
99 {
100 	String *s;
101 
102 	USED(swept);
103 	s = H2D(String*, h);
104 	if(s->tmp != nil)
105 		free(s->tmp);
106 }
107 
108 void
freearray(Heap * h,int swept)109 freearray(Heap *h, int swept)
110 {
111 	int i;
112 	Type *t;
113 	uchar *v;
114 	Array *a;
115 
116 	a = H2D(Array*, h);
117 	t = a->t;
118 
119 	if(!swept) {
120 		if(a->root != H)
121 			destroy(a->root);
122 		else
123 		if(t->np != 0) {
124 			v = a->data;
125 			for(i = 0; i < a->len; i++) {
126 				freeptrs(v, t);
127 				v += t->size;
128 			}
129 		}
130 	}
131 	if(t->ref-- == 1) {
132 		free(t->initialize);
133 		free(t);
134 	}
135 }
136 
137 void
freelist(Heap * h,int swept)138 freelist(Heap *h, int swept)
139 {
140 	Type *t;
141 	List *l;
142 	Heap *th;
143 
144 	l = H2D(List*, h);
145 	t = l->t;
146 
147 	if(t != nil) {
148 		if(!swept && t->np)
149 			freeptrs(l->data, t);
150 		t->ref--;
151 		if(t->ref == 0) {
152 			free(t->initialize);
153 			free(t);
154 		}
155 	}
156 	if(swept)
157 		return;
158 	l = l->tail;
159 	while(l != (List*)H) {
160 		t = l->t;
161 		th = D2H(l);
162 		if(th->ref-- != 1)
163 			break;
164 		th->t->ref--;	/* should be &Tlist and ref shouldn't go to 0 here nor be 0 already */
165 		if(t != nil) {
166 			if (t->np)
167 				freeptrs(l->data, t);
168 			t->ref--;
169 			if(t->ref == 0) {
170 				free(t->initialize);
171 				free(t);
172 			}
173 		}
174 		l = l->tail;
175 		if(heapmonitor != nil)
176 			heapmonitor(1, th, 0);
177 		poolfree(heapmem, th);
178 	}
179 }
180 
181 void
freemodlink(Heap * h,int swept)182 freemodlink(Heap *h, int swept)
183 {
184 	Modlink *ml;
185 
186 	ml = H2D(Modlink*, h);
187 	if(ml->m->rt == DYNMOD)
188 		freedyndata(ml);
189 	else if(!swept)
190 		destroy(ml->MP);
191 	unload(ml->m);
192 }
193 
194 int
heapref(void * v)195 heapref(void *v)
196 {
197 	return D2H(v)->ref;
198 }
199 
200 void
freeheap(Heap * h,int swept)201 freeheap(Heap *h, int swept)
202 {
203 	Type *t;
204 
205 	if(swept)
206 		return;
207 
208 	t = h->t;
209 	if (t->np)
210 		freeptrs(H2D(void*, h), t);
211 }
212 
213 void
destroy(void * v)214 destroy(void *v)
215 {
216 	Heap *h;
217 	Type *t;
218 
219 	if(v == H)
220 		return;
221 
222 	h = D2H(v);
223 	{ Bhdr *b; D2B(b, h); }		/* consistency check */
224 
225 	if(--h->ref > 0 || gchalt > 64) 	/* Protect 'C' thread stack */
226 		return;
227 
228 	if(heapmonitor != nil)
229 		heapmonitor(1, h, 0);
230 	t = h->t;
231 	if(t != nil) {
232 		gclock();
233 		t->free(h, 0);
234 		gcunlock();
235 		freetype(t);
236 	}
237 	poolfree(heapmem, h);
238 }
239 
240 Type*
dtype(void (* destroy)(Heap *,int),int size,uchar * map,int mapsize)241 dtype(void (*destroy)(Heap*, int), int size, uchar *map, int mapsize)
242 {
243 	Type *t;
244 
245 	t = malloc(sizeof(Type)-sizeof(t->map)+mapsize);
246 	if(t != nil) {
247 		t->ref = 1;
248 		t->free = destroy;
249 		t->mark = markheap;
250 		t->size = size;
251 		t->np = mapsize;
252 		memmove(t->map, map, mapsize);
253 	}
254 	return t;
255 }
256 
257 void*
checktype(void * v,Type * t,char * name,int newref)258 checktype(void *v, Type *t, char *name, int newref)
259 {
260 	Heap *h;
261 
262 	if(v == H || v == nil)
263 		error(exNilref);
264 	h = D2H(v);
265 	if(t == nil || h->t != t)
266 		errorf("%s: %s", exType, name);
267 	if(newref){
268 		h->ref++;
269 		Setmark(h);
270 	}
271 	return v;
272 }
273 
274 void
freetype(Type * t)275 freetype(Type *t)
276 {
277 	if(t == nil || --t->ref > 0)
278 		return;
279 
280 	free(t->initialize);
281 	free(t);
282 }
283 
284 void
incmem(void * vw,Type * t)285 incmem(void *vw, Type *t)
286 {
287 	Heap *h;
288 	uchar *p;
289 	int i, c, m;
290 	WORD **w, **q, *wp;
291 
292 	w = (WORD**)vw;
293 	p = t->map;
294 	for(i = 0; i < t->np; i++) {
295 		c = *p++;
296 		if(c != 0) {
297 			q = w;
298 			for(m = 0x80; m != 0; m >>= 1) {
299 				if((c & m) && (wp = *q) != H) {
300 					h = D2H(wp);
301 					h->ref++;
302 					Setmark(h);
303 				}
304 				q++;
305 			}
306 		}
307 		w += 8;
308 	}
309 }
310 
311 void
scanptrs(void * vw,Type * t,void (* f)(void *))312 scanptrs(void *vw, Type *t, void (*f)(void*))
313 {
314 	uchar *p;
315 	int i, c, m;
316 	WORD **w, **q, *wp;
317 
318 	w = (WORD**)vw;
319 	p = t->map;
320 	for(i = 0; i < t->np; i++) {
321 		c = *p++;
322 		if(c != 0) {
323 			q = w;
324 			for(m = 0x80; m != 0; m >>= 1) {
325 				if((c & m) && (wp = *q) != H)
326 					f(D2H(wp));
327 				q++;
328 			}
329 		}
330 		w += 8;
331 	}
332 }
333 
334 void
initmem(Type * t,void * vw)335 initmem(Type *t, void *vw)
336 {
337 	int c;
338 	WORD **w;
339 	uchar *p, *ep;
340 
341 	w = (WORD**)vw;
342 	p = t->map;
343 	ep = p + t->np;
344 	while(p < ep) {
345 		c = *p;
346 		if(c != 0) {
347  			if(BIT(c, 0)) w[7] = H;
348 			if(BIT(c, 1)) w[6] = H;
349 			if(BIT(c, 2)) w[5] = H;
350 			if(BIT(c, 3)) w[4] = H;
351 			if(BIT(c, 4)) w[3] = H;
352 			if(BIT(c, 5)) w[2] = H;
353 			if(BIT(c, 6)) w[1] = H;
354 			if(BIT(c, 7)) w[0] = H;
355 		}
356 		p++;
357 		w += 8;
358 	}
359 }
360 
361 Heap*
nheap(int n)362 nheap(int n)
363 {
364 	Heap *h;
365 
366 	h = poolalloc(heapmem, sizeof(Heap)+n);
367 	if(h == nil)
368 		error(exHeap);
369 
370 	h->t = nil;
371 	h->ref = 1;
372 	h->color = mutator;
373 	if(heapmonitor != nil)
374 		heapmonitor(0, h, n);
375 
376 	return h;
377 }
378 
379 Heap*
heapz(Type * t)380 heapz(Type *t)
381 {
382 	Heap *h;
383 
384 	h = poolalloc(heapmem, sizeof(Heap)+t->size);
385 	if(h == nil)
386 		error(exHeap);
387 
388 	h->t = t;
389 	t->ref++;
390 	h->ref = 1;
391 	h->color = mutator;
392 	memset(H2D(void*, h), 0, t->size);
393 	if(t->np)
394 		initmem(t, H2D(void*, h));
395 	if(heapmonitor != nil)
396 		heapmonitor(0, h, t->size);
397 	return h;
398 }
399 
400 Heap*
heap(Type * t)401 heap(Type *t)
402 {
403 	Heap *h;
404 
405 	h = poolalloc(heapmem, sizeof(Heap)+t->size);
406 	if(h == nil)
407 		error(exHeap);
408 
409 	h->t = t;
410 	t->ref++;
411 	h->ref = 1;
412 	h->color = mutator;
413 	if(t->np)
414 		initmem(t, H2D(void*, h));
415 	if(heapmonitor != nil)
416 		heapmonitor(0, h, t->size);
417 	return h;
418 }
419 
420 Heap*
heaparray(Type * t,int sz)421 heaparray(Type *t, int sz)
422 {
423 	Heap *h;
424 	Array *a;
425 
426 	h = nheap(sizeof(Array) + (t->size*sz));
427 	h->t = &Tarray;
428 	Tarray.ref++;
429 	a = H2D(Array*, h);
430 	a->t = t;
431 	a->len = sz;
432 	a->root = H;
433 	a->data = (uchar*)a + sizeof(Array);
434 	initarray(t, a);
435 	return h;
436 }
437 
438 int
hmsize(void * v)439 hmsize(void *v)
440 {
441 	return poolmsize(heapmem, v);
442 }
443 
444 void
initarray(Type * t,Array * a)445 initarray(Type *t, Array *a)
446 {
447 	int i;
448 	uchar *p;
449 
450 	t->ref++;
451 	if(t->np == 0)
452 		return;
453 
454 	p = a->data;
455 	for(i = 0; i < a->len; i++) {
456 		initmem(t, p);
457 		p += t->size;
458 	}
459 }
460 
461 void*
arraycpy(Array * sa)462 arraycpy(Array *sa)
463 {
464 	int i;
465 	Heap *dh;
466 	Array *da;
467 	uchar *elemp;
468 	void **sp, **dp;
469 
470 	if(sa == H)
471 		return H;
472 
473 	dh = nheap(sizeof(Array) + sa->t->size*sa->len);
474 	dh->t = &Tarray;
475 	Tarray.ref++;
476 	da = H2D(Array*, dh);
477 	da->t = sa->t;
478 	da->t->ref++;
479 	da->len = sa->len;
480 	da->root = H;
481 	da->data = (uchar*)da + sizeof(Array);
482 	if(da->t == &Tarray) {
483 		dp = (void**)da->data;
484 		sp = (void**)sa->data;
485 		/*
486 		 * Maximum depth of this recursion is set by DADEPTH
487 		 * in include/isa.h
488 		 */
489 		for(i = 0; i < sa->len; i++)
490 			dp[i] = arraycpy(sp[i]);
491 	}
492 	else {
493 		memmove(da->data, sa->data, da->len*sa->t->size);
494 		elemp = da->data;
495 		for(i = 0; i < sa->len; i++) {
496 			incmem(elemp, da->t);
497 			elemp += da->t->size;
498 		}
499 	}
500 	return da;
501 }
502 
503 void
newmp(void * dst,void * src,Type * t)504 newmp(void *dst, void *src, Type *t)
505 {
506 	Heap *h;
507 	int c, i, m;
508 	void **uld, *wp, **q;
509 
510 	memmove(dst, src, t->size);
511 	uld = dst;
512 	for(i = 0; i < t->np; i++) {
513 		c = t->map[i];
514 		if(c != 0) {
515 			m = 0x80;
516 			q = uld;
517 			while(m != 0) {
518 				if((m & c) && (wp = *q) != H) {
519 					h = D2H(wp);
520 					if(h->t == &Tarray)
521 						*q = arraycpy(wp);
522 					else {
523 						h->ref++;
524 						Setmark(h);
525 					}
526 				}
527 				m >>= 1;
528 				q++;
529 			}
530 		}
531 		uld += 8;
532 	}
533 }
534