#include #include #include #include #include #include "apl9.h" int arrayalloccounts = 0; int datumalloccounts = 0; int debugmem; void * emalloc(ulong size) { void *res = malloc(size); if(res == nil && size > 0){ print("Out of memory! :(\n"); threadexitsall("emalloc"); } return res; } void * emallocz(ulong size, int clr) { void *res = mallocz(size, clr); if(res == nil && size > 0){ print("Out of memory! :(\n"); threadexitsall("emallocz"); } return res; } void * erealloc(void *ptr, ulong size) { void *res = realloc(ptr, size); if(res == nil && size > 0){ print("Out of memory! :(\n"); threadexitsall("erealloc"); } return res; } void checkmem(char *where) { if(debugmem){ print("Checking memory at: %s\n", where); poolcheck(mainmem); } } void freearray(Array *a) { if(a == nil) return; if(GetRefs(a) == 0){ print("NEGATIVE REF COUNT (array)! %p\n", a); threadexitsall(nil); } SetRefs(a, GetRefs(a)-1); if(GetRefs(a) == 0){ if(GetType(a) == AtypeArray) for(int i = 0; i < GetSize(a); i++) freearray(a->arraydata[i]); free(a->shape); free(a->rawdata); free(a); arrayalloccounts--; } } Array * allocarray(arrayDataType t, int rank, int size) { Array *a = emalloc(sizeof(Array)); SetRank(a, rank); SetType(a, t); SetSize(a, size); SetStrand(a, 0); SetRefs(a, 1); a->shape = emalloc(sizeof(*a->shape) * rank); a->rawdata = emalloc(datasizes[t] * size); arrayalloccounts++; return a; } void incarrayref(Array *a) { SetRefs(a, GetRefs(a)+1); } Datum * allocdatum(int tag, int shy) { Datum *d = emallocz(sizeof(Datum), 1); d->refs = 1; d->tag = tag; d->shy = shy; datumalloccounts++; return d; } void freedatum(Datum *d) { if(d == nil) return; d->refs--; if(d->refs == 0){ /* print("FREE DATUM: %S\n", ppdatum(d)); */ switch(d->tag){ case ArrayTag: freearray(d->array); break; case FunctionTag: case BoundFunctionTag: freefunction(d->func); break; case HybridTag: break; case MonadicOpTag: case DyadicOpTag: freeoperator(d->operator); break; case LParTag: freestatement(d->stmt); break; case RParTag: break; case ArrowTag: break; case AssignmentTag: freestatement(d->names); break; case NameTag: free(d->name); break; default: print("Don't know how to free datum with tag: %d\n", d->tag); threadexitsall("freedatum"); } free(d); datumalloccounts--; }else if(d->refs < 0){ print("NEGATIVE REF COUNT (datum)! %p\n", d); threadexitsall(nil); } } void incdatumref(Datum *d) { d->refs++; } void freefunction(Function f) { freearray(f.left); switch(f.type){ case FunctypeDfn: free(f.dfn); break; case FunctypePrim: break; case FunctypeOp: freeoperator(f.operator); break; case FunctypeQuad: free(f.quad); break; case FunctypeHybrid: break; case FunctypeTrain: for(int i = 0; i < f.train.nfuncs; i++) freefunction(f.train.funcs[i]); free(f.train.funcs); break; default: print("Missing case in freefunction: %d\n", f.type); threadexitsall("freefunction"); } } void freeoperator(Operator o) { freedatum(o.left); freedatum(o.right); switch(o.type){ case OperatortypeDop: free(o.dop); break; case OperatortypePrim: case OperatortypeHybrid: break; default: print("Missing case in freeoperator: %d\n", o.type); threadexitsall("freeoperator"); } } void freestatement(Statement s) { for(int i = 0; i < s.ntoks; i++) freedatum(s.toks[i]); free(s.toks); if(s.guard) freestatement(*s.guard); } Function dupfunction(Function f) { Function g = f; if(g.left) incarrayref(g.left); switch(f.type){ case FunctypeDfn: g.dfn = runestrdup(f.dfn); break; case FunctypePrim: break; case FunctypeOp: g.operator = dupoperator(f.operator); break; case FunctypeQuad: g.quad = emalloc(sizeof(QuadnameDef)); *g.quad = *f.quad; break; case FunctypeHybrid: break; default: print("Missing case in dupfunction: %d\n", f.type); threadexitsall("dupfunction"); } return g; } Operator dupoperator(Operator o) { Operator p = o; if(p.left) incdatumref(p.left); if(p.right) incdatumref(p.right); switch(o.type){ case OperatortypeDop: p.dop = runestrdup(o.dop); break; case OperatortypePrim: case OperatortypeHybrid: break; default: print("Missing case in dupoperator: %d\n", o.type); threadexitsall("dupoperator"); } return p; }