xref: /inferno-os/libinterp/heap.c (revision d0e1d143ef6f03c75c008c7ec648859dd260cbab)
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
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
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
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
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
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((ulong)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
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
195 heapref(void *v)
196 {
197 	return D2H(v)->ref;
198 }
199 
200 void
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
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 void
241 freetype(Type *t)
242 {
243 	if(t == nil || --t->ref > 0)
244 		return;
245 
246 	free(t->initialize);
247 	free(t);
248 }
249 
250 void
251 incmem(void *vw, Type *t)
252 {
253 	Heap *h;
254 	uchar *p;
255 	int i, c, m;
256 	WORD **w, **q, *wp;
257 
258 	w = (WORD**)vw;
259 	p = t->map;
260 	for(i = 0; i < t->np; i++) {
261 		c = *p++;
262 		if(c != 0) {
263 			q = w;
264 			for(m = 0x80; m != 0; m >>= 1) {
265 				if((c & m) && (wp = *q) != H) {
266 					h = D2H(wp);
267 					h->ref++;
268 					Setmark(h);
269 				}
270 				q++;
271 			}
272 		}
273 		w += 8;
274 	}
275 }
276 
277 void
278 scanptrs(void *vw, Type *t, void (*f)(void*))
279 {
280 	uchar *p;
281 	int i, c, m;
282 	WORD **w, **q, *wp;
283 
284 	w = (WORD**)vw;
285 	p = t->map;
286 	for(i = 0; i < t->np; i++) {
287 		c = *p++;
288 		if(c != 0) {
289 			q = w;
290 			for(m = 0x80; m != 0; m >>= 1) {
291 				if((c & m) && (wp = *q) != H)
292 					f(D2H(wp));
293 				q++;
294 			}
295 		}
296 		w += 8;
297 	}
298 }
299 
300 void
301 initmem(Type *t, void *vw)
302 {
303 	int c;
304 	WORD **w;
305 	uchar *p, *ep;
306 
307 	w = (WORD**)vw;
308 	p = t->map;
309 	ep = p + t->np;
310 	while(p < ep) {
311 		c = *p;
312 		if(c != 0) {
313  			if(BIT(c, 0)) w[7] = H;
314 			if(BIT(c, 1)) w[6] = H;
315 			if(BIT(c, 2)) w[5] = H;
316 			if(BIT(c, 3)) w[4] = H;
317 			if(BIT(c, 4)) w[3] = H;
318 			if(BIT(c, 5)) w[2] = H;
319 			if(BIT(c, 6)) w[1] = H;
320 			if(BIT(c, 7)) w[0] = H;
321 		}
322 		p++;
323 		w += 8;
324 	}
325 }
326 
327 Heap*
328 nheap(int n)
329 {
330 	Heap *h;
331 
332 	h = poolalloc(heapmem, sizeof(Heap)+n);
333 	if(h == nil)
334 		error(exHeap);
335 
336 	h->t = nil;
337 	h->ref = 1;
338 	h->color = mutator;
339 	if(heapmonitor != nil)
340 		heapmonitor(0, h, n);
341 
342 	return h;
343 }
344 
345 Heap*
346 heapz(Type *t)
347 {
348 	Heap *h;
349 
350 	h = poolalloc(heapmem, sizeof(Heap)+t->size);
351 	if(h == nil)
352 		error(exHeap);
353 
354 	h->t = t;
355 	t->ref++;
356 	h->ref = 1;
357 	h->color = mutator;
358 	memset(H2D(void*, h), 0, t->size);
359 	if(t->np)
360 		initmem(t, H2D(void*, h));
361 	if(heapmonitor != nil)
362 		heapmonitor(0, h, t->size);
363 	return h;
364 }
365 
366 Heap*
367 heap(Type *t)
368 {
369 	Heap *h;
370 
371 	h = poolalloc(heapmem, sizeof(Heap)+t->size);
372 	if(h == nil)
373 		error(exHeap);
374 
375 	h->t = t;
376 	t->ref++;
377 	h->ref = 1;
378 	h->color = mutator;
379 	if(t->np)
380 		initmem(t, H2D(void*, h));
381 	if(heapmonitor != nil)
382 		heapmonitor(0, h, t->size);
383 	return h;
384 }
385 
386 Heap*
387 heaparray(Type *t, int sz)
388 {
389 	Heap *h;
390 	Array *a;
391 
392 	h = nheap(sizeof(Array) + (t->size*sz));
393 	h->t = &Tarray;
394 	Tarray.ref++;
395 	a = H2D(Array*, h);
396 	a->t = t;
397 	a->len = sz;
398 	a->root = H;
399 	a->data = (uchar*)a + sizeof(Array);
400 	initarray(t, a);
401 	return h;
402 }
403 
404 int
405 hmsize(void *v)
406 {
407 	return poolmsize(heapmem, v);
408 }
409 
410 void
411 initarray(Type *t, Array *a)
412 {
413 	int i;
414 	uchar *p;
415 
416 	t->ref++;
417 	if(t->np == 0)
418 		return;
419 
420 	p = a->data;
421 	for(i = 0; i < a->len; i++) {
422 		initmem(t, p);
423 		p += t->size;
424 	}
425 }
426 
427 void*
428 arraycpy(Array *sa)
429 {
430 	int i;
431 	Heap *dh;
432 	Array *da;
433 	uchar *elemp;
434 	void **sp, **dp;
435 
436 	if(sa == H)
437 		return H;
438 
439 	dh = nheap(sizeof(Array) + sa->t->size*sa->len);
440 	dh->t = &Tarray;
441 	Tarray.ref++;
442 	da = H2D(Array*, dh);
443 	da->t = sa->t;
444 	da->t->ref++;
445 	da->len = sa->len;
446 	da->root = H;
447 	da->data = (uchar*)da + sizeof(Array);
448 	if(da->t == &Tarray) {
449 		dp = (void**)da->data;
450 		sp = (void**)sa->data;
451 		/*
452 		 * Maximum depth of this recursion is set by DADEPTH
453 		 * in include/isa.h
454 		 */
455 		for(i = 0; i < sa->len; i++)
456 			dp[i] = arraycpy(sp[i]);
457 	}
458 	else {
459 		memmove(da->data, sa->data, da->len*sa->t->size);
460 		elemp = da->data;
461 		for(i = 0; i < sa->len; i++) {
462 			incmem(elemp, da->t);
463 			elemp += da->t->size;
464 		}
465 	}
466 	return da;
467 }
468 
469 void
470 newmp(void *dst, void *src, Type *t)
471 {
472 	Heap *h;
473 	int c, i, m;
474 	void **uld, *wp, **q;
475 
476 	memmove(dst, src, t->size);
477 	uld = dst;
478 	for(i = 0; i < t->np; i++) {
479 		c = t->map[i];
480 		if(c != 0) {
481 			m = 0x80;
482 			q = uld;
483 			while(m != 0) {
484 				if((m & c) && (wp = *q) != H) {
485 					h = D2H(wp);
486 					if(h->t == &Tarray)
487 						*q = arraycpy(wp);
488 					else {
489 						h->ref++;
490 						Setmark(h);
491 					}
492 				}
493 				m >>= 1;
494 				q++;
495 			}
496 		}
497 		uld += 8;
498 	}
499 }
500