summaryrefslogtreecommitdiff
path: root/libinterp/heap.c
diff options
context:
space:
mode:
authorCharles.Forsyth <devnull@localhost>2006-12-22 17:07:39 +0000
committerCharles.Forsyth <devnull@localhost>2006-12-22 17:07:39 +0000
commit37da2899f40661e3e9631e497da8dc59b971cbd0 (patch)
treecbc6d4680e347d906f5fa7fca73214418741df72 /libinterp/heap.c
parent54bc8ff236ac10b3eaa928fd6bcfc0cdb2ba46ae (diff)
20060303a
Diffstat (limited to 'libinterp/heap.c')
-rw-r--r--libinterp/heap.c499
1 files changed, 499 insertions, 0 deletions
diff --git a/libinterp/heap.c b/libinterp/heap.c
new file mode 100644
index 00000000..5eff79a5
--- /dev/null
+++ b/libinterp/heap.c
@@ -0,0 +1,499 @@
+#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((ulong)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);
+}
+
+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;
+ }
+}