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(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 Type* 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* 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 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 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 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 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* 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* 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* 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* 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 439 hmsize(void *v) 440 { 441 return poolmsize(heapmem, v); 442 } 443 444 void 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* 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 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