From 3f13dafdcb617286aae542ab6a2e1ab91d228836 Mon Sep 17 00:00:00 2001 From: Leo Tenenbaum Date: Sat, 26 Oct 2019 17:02:00 -0400 Subject: fixed leaks --- eval.c | 73 ++++++++++++++++++++++++++++++++++++++++++---------------------- main.c | 2 -- scope.c | 5 +++-- test.toc | 36 +++++++++++--------------------- types.h | 4 +++- 5 files changed, 66 insertions(+), 54 deletions(-) diff --git a/eval.c b/eval.c index f742e0a..cbe7798 100644 --- a/eval.c +++ b/eval.c @@ -6,10 +6,15 @@ static void block_exit(Block *b, Statement *stmts); static void evalr_create(Evaluator *ev) { allocr_create(&ev->allocr); ev->returning = NULL; + ev->to_free = NULL; } static void evalr_free(Evaluator *ev) { allocr_free_all(&ev->allocr); + typedef void *VoidPtr; + arr_foreach(ev->to_free, VoidPtr, f) + free(*f); + arr_clear(&ev->to_free); } static inline void *evalr_malloc(Evaluator *ev, size_t bytes) { @@ -174,7 +179,7 @@ static void val_copy(Evaluator *ev, Value *dest, Value *src, Type *t) { } } -static void val_free(Value *v, Type *t) { +static void *val_ptr_to_free(Value *v, Type *t) { switch (t->kind) { case TYPE_BUILTIN: case TYPE_FN: @@ -182,14 +187,17 @@ static void val_free(Value *v, Type *t) { case TYPE_SLICE: case TYPE_VOID: case TYPE_UNKNOWN: - break; + return NULL; case TYPE_ARR: - free(v->arr); - break; + return v->arr; case TYPE_TUPLE: - free(v->tuple); - break; + return v->tuple; } + assert(0); return NULL; +} + +static void val_free(Value *v, Type *t) { + free(val_ptr_to_free(v, t)); } #define builtin_casts_to_int(x) \ @@ -850,7 +858,8 @@ static bool eval_expr(Evaluator *ev, Expression *e, Value *v) { } break; case EXPR_TUPLE: { size_t i, n = arr_len(e->tuple); - v->tuple = evalr_malloc(ev, n * sizeof *v->tuple); + v->tuple = err_malloc(n * sizeof *v->tuple); + *(void **)arr_add(&ev->to_free) = v->tuple; for (i = 0; i < n; i++) { if (!eval_expr(ev, &e->tuple[i], &v->tuple[i])) return false; @@ -908,9 +917,8 @@ static bool eval_expr(Evaluator *ev, Expression *e, Value *v) { return false; } if (ev->returning) { - *v = *ev->returning; - free(ev->returning); - ev->returning = NULL; + *v = ev->ret_val; + ev->returning = false; } fn_exit(fn); } break; @@ -965,25 +973,28 @@ static bool eval_expr(Evaluator *ev, Expression *e, Value *v) { static bool eval_decl(Evaluator *ev, Declaration *d) { Value val = {0}; int has_expr = d->flags & DECL_FLAG_HAS_EXPR; - if (has_expr) { + if (has_expr && (!(d->flags & DECL_FLAG_CONST) || !(d->flags & DECL_FLAG_FOUND_VAL))) { if (!eval_expr(ev, &d->expr, &val)) return false; - d->flags |= DECL_FLAG_HAS_EXPR; + d->flags |= DECL_FLAG_FOUND_VAL; } long index = 0; arr_foreach(d->idents, Identifier, i) { IdentDecl *id = ident_decl(*i); - if (has_expr && d->expr.kind == EXPR_TUPLE) { - val_copy(ev, &id->val, &val.tuple[index], &d->type.tuple[index]); + if (has_expr && d->type.kind == TYPE_TUPLE) { + val_copy(d->flags & DECL_FLAG_CONST ? ev : NULL, &id->val, &val.tuple[index], &d->type.tuple[index]); index++; } else if (!has_expr && d->type.kind == TYPE_ARR) { /* "stack" array */ id->val.arr = err_calloc(d->type.arr.n, compiler_sizeof(d->type.arr.of)); } else { - val_copy(ev, &id->val, &val, &d->type); + val_copy(d->flags & DECL_FLAG_CONST ? ev : NULL, &id->val, &val, &d->type); } id->flags |= IDECL_FLAG_HAS_VAL; } + if (d->expr.kind == EXPR_TUPLE) { + val_free(&val, &d->type); /* free the tuple */ + } return true; } @@ -997,32 +1008,44 @@ static bool eval_stmt(Evaluator *ev, Statement *stmt) { if (!eval_expr(ev, &stmt->expr, &unused)) return false; } break; - case STMT_RET: - ev->returning = err_malloc(sizeof *ev->returning); - if (!eval_expr(ev, &stmt->ret.expr, ev->returning)) + case STMT_RET: { + Value r; + if (!eval_expr(ev, &stmt->ret.expr, &r)) return false; - break; + val_copy(NULL, &ev->ret_val, &r, &stmt->ret.expr.type); + } break; } return true; } /* t is the type of the block. */ static bool eval_block(Evaluator *ev, Block *b, Type *t, Value *v) { + void **prev_to_free = ev->to_free; + ev->to_free = NULL; block_enter(b, b->stmts, 0); arr_foreach(b->stmts, Statement, stmt) { if (!eval_stmt(ev, stmt)) return false; if (ev->returning) break; } - Value *returning = ev->returning; - Value r; if (!ev->returning && b->ret_expr) { - returning = &r; - if (!eval_expr(ev, b->ret_expr, returning)) + Value r; + if (!eval_expr(ev, b->ret_expr, &r)) return false; + /* make a copy so that r's data isn't freed when we exit the block */ + val_copy(NULL, v, &r, &b->ret_expr->type); + void *free_ptr = val_ptr_to_free(v, t); + if (t->kind == TYPE_TUPLE) printf("WIll Free %p!!!\n",free_ptr); + if (free_ptr) + *(void **)arr_add(&prev_to_free) = free_ptr; } - if (returning) val_copy(NULL, v, returning, t); /* LEAK */adfjfhskjdahfkj block_exit(b, b->stmts); - + typedef void *VoidPtr; + arr_foreach(ev->to_free, VoidPtr, f) { + printf("Free %p\n", *f); + free(*f); + } + arr_clear(&ev->to_free); + ev->to_free = prev_to_free; return true; } diff --git a/main.c b/main.c index 1153983..468d6c8 100644 --- a/main.c +++ b/main.c @@ -1,7 +1,5 @@ /* TODO: -array/slice values -fix leaking of constant stack arrays make sure initializers for global variables are compile-time constants structs length of slice/arr with .len diff --git a/scope.c b/scope.c index 8aed1a8..42e446a 100644 --- a/scope.c +++ b/scope.c @@ -24,15 +24,16 @@ static bool add_ident_decls(Block *b, Declaration *d, U32 flags) { static void remove_ident_decls(Block *b, Declaration *d) { U64 i = 0; + bool is_tuple = d->type.kind == TYPE_TUPLE; arr_foreach(d->idents, Identifier, ident) { IdentTree *id_info = *ident; - IdentDecl **decls = &id_info->decls; + IdentDecl **decls = &id_info->decls; IdentDecl *last_decl = arr_last(*decls); if (last_decl && last_decl->scope == b) { if ((last_decl->flags & IDECL_FLAG_HAS_VAL) /* don't free const vals (there's only one per decl) */ && !(last_decl->decl->flags & DECL_FLAG_CONST)) { - val_free(&last_decl->decl->val, d->type.kind == TYPE_TUPLE ? &d->type.tuple[i++] : &d->type); + val_free(&last_decl->val, is_tuple ? &d->type.tuple[i++] : &d->type); } arr_remove_last(decls); /* remove that declaration */ } diff --git a/test.toc b/test.toc index b865734..c5af4fb 100644 --- a/test.toc +++ b/test.toc @@ -13,39 +13,27 @@ putf @= fn(x: float) { "); }; +asdf @= fn() (int, int) { +2,3}; -N @= 50; -pascal @= fn() [N][]int { - x: [N][]int; - i := 0; - while i < N { - x[i] = new(int, i+1); - i = i + 1; - } - i = 0; - while i < N { - x[i][0] = 1; - x[i][i] = 1; - j := 1; - while j < i { - x[i][j] = x[i-1][j-1] + x[i-1][j]; - j = j + 1; - } - i = i + 1; - } - x +fdsa @= fn() int { + x, y := asdf(); + x + y }; foo @= fn() [3]int { x : [3]int; - x[0] = 0; - x[1] = 1; - x[2] = 2; + x[0] = 1; + x[1] = 2; + x[2] = 3; x }; main @= fn() { // ptriangle @= pascal(); // puti(ptriangle[49][25]); - x @= foo(); + x : [fdsa()]int; + + A, B @= 3, 5; + ASDF @= foo(); }; diff --git a/types.h b/types.h index b0db0b1..2d4e7e4 100644 --- a/types.h +++ b/types.h @@ -509,7 +509,9 @@ typedef enum { typedef struct { Allocator allocr; - Value *returning; /* NULL = not returning anything */ + bool returning; + Value ret_val; + void **to_free; /* an array of data to free for this scope. */ } Evaluator; typedef struct Typer { -- cgit v1.2.3