From 6ed5b9f6d3fdeeed8ecd43b18bae642ec1ec24b1 Mon Sep 17 00:00:00 2001 From: Peter Mikkelsen Date: Wed, 9 Feb 2022 01:16:03 +0000 Subject: Add much better memory handling (We now track and free Datum * structs) --- memory.c | 223 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 208 insertions(+), 15 deletions(-) (limited to 'memory.c') diff --git a/memory.c b/memory.c index 4606ef2..33c30d7 100644 --- a/memory.c +++ b/memory.c @@ -1,20 +1,44 @@ #include #include +#include #include #include #include "apl9.h" -int alloccounts = 0; +int arrayalloccounts = 0; +int datumalloccounts = 0; int debugmem; void * emalloc(ulong size) { void *res = malloc(size); - if(res == nil){ + if(res == nil && size > 0){ print("Out of memory! :(\n"); - exits("emalloc"); + 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; } @@ -36,19 +60,18 @@ freearray(Array *a) a->refs--; if(a->refs == 0){ - /* print("Freeing array: %S (%p)\n", pparray(a), a); */ if(a->type == AtypeArray) for(int i = 0; i < a->size; i++) freearray(a->arraydata[i]); free(a->shape); + free(a->rawdata); free(a); - alloccounts--; - }else if(a->refs > 0){ - /* print("Not freeing (refs=%d): %S (%p)\n", a->refs, pparray(a), a); */ - }else{ - print("NEGATIVE REF COUNT! %p\n", a); - exits(nil); + arrayalloccounts--; + }else if(a->refs < 0){ + print("NEGATIVE REF COUNT (array)! %p\n", a); + threadexitsall(nil); } + } Array * @@ -63,16 +86,186 @@ allocarray(arrayDataType t, int rank, int size) a->rawdata = emalloc(datasizes[t] * size); a->type = t; a->refs = 1; - alloccounts++; + arrayalloccounts++; return a; } void incarrayref(Array *a) { - /* print("INCREF %d->%d %S\n", a->refs, a->refs+1, pparray(a)); */ a->refs++; - if(a->type == AtypeArray) - for(int i = 0; i < a->size; i++) - incarrayref(a->arraydata[i]); +} + +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; } \ No newline at end of file -- cgit v1.2.3