diff options
| -rw-r--r-- | pez.c | 27 |
1 files changed, 19 insertions, 8 deletions
@@ -76,7 +76,10 @@ typedef struct Proto { const char *file; const uint8_t *code; const Val *con; - struct cmupval *upval; + union { + struct cmupval *upval; + struct Fn *fn0; /* closures with 0 upvalues are cached */ + }; char name[]; } Proto; @@ -471,7 +474,9 @@ delproto(PezContext *cx, Proto *pr) { cxfree(cx, (void *)pr->code, pr->ncode); cxfree(cx, (void *)pr->con, pr->ncon * sizeof(Val)); - cxfree(cx, (void *)pr->upval, pr->nupval * sizeof(struct cmupval)); + if (pr->nupval) { + cxfree(cx, (void *)pr->upval, pr->nupval * sizeof(struct cmupval)); + } } static void @@ -503,7 +508,11 @@ sizeoffn(Fn *fn) static Fn * newfn(PezContext *cx, Proto *pr, Val *args, Val *locals, Fn *parent) { - Fn *fn = newobj(cx, PEZ_TFn, sizeof *fn + pr->nupval * sizeof(struct Upval *)); + Fn *fn; + if (pr->nupval == 0 && pr->fn0) { + return pr->fn0; + } + fn = newobj(cx, PEZ_TFn, sizeof *fn + pr->nupval * sizeof(struct Upval *)); if (fn) { TRY(push(cx, box_obj(fn))); // gc keep fn->proto = pr; @@ -537,6 +546,9 @@ newfn(PezContext *cx, Proto *pr, Val *args, Val *locals, Fn *parent) } pop(cx); } + if (pr->nupval == 0) { + pr->fn0 = fn; + } return fn; } @@ -1979,7 +1991,7 @@ f_arrayfill(PezContext *cx, int argc) n = unbox_num(cx->stktop[-2]); if (!isnum(cx->stktop[-2]) || n < 0 || fixtrunc(n) != n) { pez_error(cx, "array#fill", "argument #1 should be positive integer"); - return 0; + return 0; } TRY(arr = newarr(cx, fixtoint(n))); arr->len = fixtoint(n); @@ -2054,10 +2066,9 @@ fincompfn(Comp *cm) pr->ncode = cm->code.len; pr->con = con; pr->ncon = cm->con.len; - pr->upval = cxalloc(cm->cx, cm->fenv.nupval * sizeof *pr->upval); - pr->nupval = cm->fenv.nupval; - // fprintf(stderr, "fini %s %d\n", pr->name, pr->nupval); - if (pr->upval) { + pr->upval = NULL; + if ((pr->nupval = cm->fenv.nupval) != 0) { + pr->upval = cxalloc(cm->cx, cm->fenv.nupval * sizeof *pr->upval); memcpy(pr->upval, cm->fenv.upvals, pr->nupval * sizeof(struct cmupval)); } memset(&cm->code, 0, sizeof cm->code); |