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