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