ref: a600cca5ff367ca7e7c64a14a8e87ba376780f6d
dir: /libinterp/heap.c/
#include "lib9.h" #include "isa.h" #include "interp.h" #include "pool.h" #include "raise.h" void freearray(Heap*, int); void freelist(Heap*, int); void freemodlink(Heap*, int); void freechan(Heap*, int); Type Tarray = { 1, freearray, markarray, sizeof(Array) }; Type Tstring = { 1, freestring, noptrs, sizeof(String) }; Type Tlist = { 1, freelist, marklist, sizeof(List) }; Type Tmodlink = { 1, freemodlink, markheap, -1, 1, 0, 0, { 0x80 } }; Type Tchannel = { 1, freechan, markheap, sizeof(Channel), 1,0,0,{0x80} }; Type Tptr = { 1, 0, markheap, sizeof(WORD*), 1, 0, 0, { 0x80 } }; Type Tbyte = { 1, 0, 0, 1 }; Type Tword = { 1, 0, 0, sizeof(WORD) }; Type Tlong = { 1, 0, 0, sizeof(LONG) }; Type Treal = { 1, 0, 0, sizeof(REAL) }; extern Pool* heapmem; extern int mutator; void (*heapmonitor)(int, void*, ulong); #define BIT(bt, nb) (bt & (1<<nb)) void freeptrs(void *v, Type *t) { int c; WORD **w, *x; uchar *p, *ep; if(t->np == 0) return; w = (WORD**)v; p = t->map; ep = p + t->np; while(p < ep) { c = *p; if(c != 0) { if(BIT(c, 0) && (x = w[7]) != H) destroy(x); if(BIT(c, 1) && (x = w[6]) != H) destroy(x); if(BIT(c, 2) && (x = w[5]) != H) destroy(x); if(BIT(c, 3) && (x = w[4]) != H) destroy(x); if(BIT(c, 4) && (x = w[3]) != H) destroy(x); if(BIT(c, 5) && (x = w[2]) != H) destroy(x); if(BIT(c, 6) && (x = w[1]) != H) destroy(x); if(BIT(c, 7) && (x = w[0]) != H) destroy(x); } p++; w += 8; } } /* void nilptrs(void *v, Type *t) { int c, i; WORD **w; uchar *p, *ep; w = (WORD**)v; p = t->map; ep = p + t->np; while(p < ep) { c = *p; for(i = 0; i < 8; i++){ if(BIT(c, 7)) *w = H; c <<= 1; w++; } p++; } } */ void freechan(Heap *h, int swept) { Channel *c; USED(swept); c = H2D(Channel*, h); if(c->mover == movtmp) freetype(c->mid.t); killcomm(&c->send); killcomm(&c->recv); if (!swept && c->buf != H) destroy(c->buf); } void freestring(Heap *h, int swept) { String *s; USED(swept); s = H2D(String*, h); if(s->tmp != nil) free(s->tmp); } void freearray(Heap *h, int swept) { int i; Type *t; uchar *v; Array *a; a = H2D(Array*, h); t = a->t; if(!swept) { if(a->root != H) destroy(a->root); else if(t->np != 0) { v = a->data; for(i = 0; i < a->len; i++) { freeptrs(v, t); v += t->size; } } } if(t->ref-- == 1) { free(t->initialize); free(t); } } void freelist(Heap *h, int swept) { Type *t; List *l; Heap *th; l = H2D(List*, h); t = l->t; if(t != nil) { if(!swept && t->np) freeptrs(l->data, t); t->ref--; if(t->ref == 0) { free(t->initialize); free(t); } } if(swept) return; l = l->tail; while(l != (List*)H) { t = l->t; th = D2H(l); if(th->ref-- != 1) break; th->t->ref--; /* should be &Tlist and ref shouldn't go to 0 here nor be 0 already */ if(t != nil) { if (t->np) freeptrs(l->data, t); t->ref--; if(t->ref == 0) { free(t->initialize); free(t); } } l = l->tail; if(heapmonitor != nil) heapmonitor(1, th, 0); poolfree(heapmem, th); } } void freemodlink(Heap *h, int swept) { Modlink *ml; ml = H2D(Modlink*, h); if(ml->m->rt == DYNMOD) freedyndata(ml); else if(!swept) destroy(ml->MP); unload(ml->m); } int heapref(void *v) { return D2H(v)->ref; } void freeheap(Heap *h, int swept) { Type *t; if(swept) return; t = h->t; if (t->np) freeptrs(H2D(void*, h), t); } void destroy(void *v) { Heap *h; Type *t; if(v == H) return; h = D2H(v); { Bhdr *b; D2B(b, h); } /* consistency check */ if(--h->ref > 0 || gchalt > 64) /* Protect 'C' thread stack */ return; if(heapmonitor != nil) heapmonitor(1, h, 0); t = h->t; if(t != nil) { gclock(); t->free(h, 0); gcunlock(); freetype(t); } poolfree(heapmem, h); } Type* dtype(void (*destroy)(Heap*, int), int size, uchar *map, int mapsize) { Type *t; t = malloc(sizeof(Type)-sizeof(t->map)+mapsize); if(t != nil) { t->ref = 1; t->free = destroy; t->mark = markheap; t->size = size; t->np = mapsize; memmove(t->map, map, mapsize); } return t; } void* checktype(void *v, Type *t, char *name, int newref) { Heap *h; if(v == H || v == nil) error(exNilref); h = D2H(v); if(t == nil || h->t != t) errorf("%s: %s", exType, name); if(newref){ h->ref++; Setmark(h); } return v; } void freetype(Type *t) { if(t == nil || --t->ref > 0) return; free(t->initialize); free(t); } void incmem(void *vw, Type *t) { Heap *h; uchar *p; int i, c, m; WORD **w, **q, *wp; w = (WORD**)vw; p = t->map; for(i = 0; i < t->np; i++) { c = *p++; if(c != 0) { q = w; for(m = 0x80; m != 0; m >>= 1) { if((c & m) && (wp = *q) != H) { h = D2H(wp); h->ref++; Setmark(h); } q++; } } w += 8; } } void scanptrs(void *vw, Type *t, void (*f)(void*)) { uchar *p; int i, c, m; WORD **w, **q, *wp; w = (WORD**)vw; p = t->map; for(i = 0; i < t->np; i++) { c = *p++; if(c != 0) { q = w; for(m = 0x80; m != 0; m >>= 1) { if((c & m) && (wp = *q) != H) f(D2H(wp)); q++; } } w += 8; } } void initmem(Type *t, void *vw) { int c; WORD **w; uchar *p, *ep; w = (WORD**)vw; p = t->map; ep = p + t->np; while(p < ep) { c = *p; if(c != 0) { if(BIT(c, 0)) w[7] = H; if(BIT(c, 1)) w[6] = H; if(BIT(c, 2)) w[5] = H; if(BIT(c, 3)) w[4] = H; if(BIT(c, 4)) w[3] = H; if(BIT(c, 5)) w[2] = H; if(BIT(c, 6)) w[1] = H; if(BIT(c, 7)) w[0] = H; } p++; w += 8; } } Heap* nheap(int n) { Heap *h; h = poolalloc(heapmem, sizeof(Heap)+n); if(h == nil) error(exHeap); h->t = nil; h->ref = 1; h->color = mutator; if(heapmonitor != nil) heapmonitor(0, h, n); return h; } Heap* heapz(Type *t) { Heap *h; h = poolalloc(heapmem, sizeof(Heap)+t->size); if(h == nil) error(exHeap); h->t = t; t->ref++; h->ref = 1; h->color = mutator; memset(H2D(void*, h), 0, t->size); if(t->np) initmem(t, H2D(void*, h)); if(heapmonitor != nil) heapmonitor(0, h, t->size); return h; } Heap* heap(Type *t) { Heap *h; h = poolalloc(heapmem, sizeof(Heap)+t->size); if(h == nil) error(exHeap); h->t = t; t->ref++; h->ref = 1; h->color = mutator; if(t->np) initmem(t, H2D(void*, h)); if(heapmonitor != nil) heapmonitor(0, h, t->size); return h; } Heap* heaparray(Type *t, int sz) { Heap *h; Array *a; h = nheap(sizeof(Array) + (t->size*sz)); h->t = &Tarray; Tarray.ref++; a = H2D(Array*, h); a->t = t; a->len = sz; a->root = H; a->data = (uchar*)a + sizeof(Array); initarray(t, a); return h; } int hmsize(void *v) { return poolmsize(heapmem, v); } void initarray(Type *t, Array *a) { int i; uchar *p; t->ref++; if(t->np == 0) return; p = a->data; for(i = 0; i < a->len; i++) { initmem(t, p); p += t->size; } } void* arraycpy(Array *sa) { int i; Heap *dh; Array *da; uchar *elemp; void **sp, **dp; if(sa == H) return H; dh = nheap(sizeof(Array) + sa->t->size*sa->len); dh->t = &Tarray; Tarray.ref++; da = H2D(Array*, dh); da->t = sa->t; da->t->ref++; da->len = sa->len; da->root = H; da->data = (uchar*)da + sizeof(Array); if(da->t == &Tarray) { dp = (void**)da->data; sp = (void**)sa->data; /* * Maximum depth of this recursion is set by DADEPTH * in include/isa.h */ for(i = 0; i < sa->len; i++) dp[i] = arraycpy(sp[i]); } else { memmove(da->data, sa->data, da->len*sa->t->size); elemp = da->data; for(i = 0; i < sa->len; i++) { incmem(elemp, da->t); elemp += da->t->size; } } return da; } void newmp(void *dst, void *src, Type *t) { Heap *h; int c, i, m; void **uld, *wp, **q; memmove(dst, src, t->size); uld = dst; for(i = 0; i < t->np; i++) { c = t->map[i]; if(c != 0) { m = 0x80; q = uld; while(m != 0) { if((m & c) && (wp = *q) != H) { h = D2H(wp); if(h->t == &Tarray) *q = arraycpy(wp); else { h->ref++; Setmark(h); } } m >>= 1; q++; } } uld += 8; } }