diff --git a/src/arith.c b/src/arith.c index 8a879023..b3ea59d3 100644 --- a/src/arith.c +++ b/src/arith.c @@ -56,7 +56,7 @@ B div_c1(B t, B x) { if (isF64(x)) return m_f64( 1/x.f ); return err("getti B pow_c1(B t, B x) { if (isF64(x)) return m_f64( exp(x.f)); return err("getting exp of non-number"); } B floor_c1(B t, B x) { if (isF64(x)) return m_f64(floor(x.f)); return err("getting floor of non-number"); } B log_c1(B t, B x) { if (isF64(x)) return m_f64( log(x.f)); return err("getting log of non-number"); } -B eq_c1(B t, B x) { B r = m_i32(isArr(x)? rnk(x) : 0); dec(x); return r; } +B eq_c1(B t, B x) { B r = m_i32(isArr(x)? rnk(x) : 0); decR(x); return r; } diff --git a/src/derv.c b/src/derv.c index 8ffa6d2a..1c71271a 100644 --- a/src/derv.c +++ b/src/derv.c @@ -47,11 +47,11 @@ B fork_c2(B t, B w, B x) { B g=c2(c(Fork,t)->h, inc(w), inc(x)); return c2(c(For B md2H_c1(B d, B x) { Md1D* m=c(Md1D,d); Md2H* t=c(Md2H,m->m1); return md2D_c1(m_md2D(t->m2, m->f, t->g), x); } B md2H_c2(B d, B w, B x) { Md1D* m=c(Md1D,d); Md2H* t=c(Md2H,m->m1); return md2D_c2(m_md2D(t->m2, m->f, t->g), w, x); } -B md1D_decompose(B x) { B r=m_v3(m_i32(4),inc(c(Md1D,x)->f),inc(c(Md1D,x)->m1) ); dec(x); return r; } -B md2D_decompose(B x) { B r=m_v4(m_i32(5),inc(c(Md2D,x)->f),inc(c(Md2D,x)->m2), inc(c(Md2D,x)->g)); dec(x); return r; } -B md2H_decompose(B x) { B r=m_v3(m_i32(6), inc(c(Md2H,x)->m2), inc(c(Md2H,x)->g)); dec(x); return r; } -B fork_decompose(B x) { B r=m_v4(m_i32(3),inc(c(Fork,x)->f),inc(c(Fork,x)->g ), inc(c(Fork,x)->h)); dec(x); return r; } -B atop_decompose(B x) { B r=m_v3(m_i32(2), inc(c(Atop,x)->g ), inc(c(Atop,x)->h)); dec(x); return r; } +B md1D_decompose(B x) { B r=m_v3(m_i32(4),inc(c(Md1D,x)->f),inc(c(Md1D,x)->m1) ); decR(x); return r; } +B md2D_decompose(B x) { B r=m_v4(m_i32(5),inc(c(Md2D,x)->f),inc(c(Md2D,x)->m2), inc(c(Md2D,x)->g)); decR(x); return r; } +B md2H_decompose(B x) { B r=m_v3(m_i32(6), inc(c(Md2H,x)->m2), inc(c(Md2H,x)->g)); decR(x); return r; } +B fork_decompose(B x) { B r=m_v4(m_i32(3),inc(c(Fork,x)->f),inc(c(Fork,x)->g ), inc(c(Fork,x)->h)); decR(x); return r; } +B atop_decompose(B x) { B r=m_v3(m_i32(2), inc(c(Atop,x)->g ), inc(c(Atop,x)->h)); decR(x); return r; } // consume all args B m_md1D(B m, B f ) { B r = mm_alloc(sizeof(Md1D), t_md1D, ftag(FUN_TAG)); c(Md1D,r)->f = f; c(Md1D,r)->m1 = m; c(Md1D,r)->c1=md1D_c1; c(Md1D,r)->c2=md1D_c2; c(Md1D,r)->extra=pf_md1d; return r; } diff --git a/src/h.h b/src/h.h index 53e0f5a3..0bd78a74 100644 --- a/src/h.h +++ b/src/h.h @@ -319,10 +319,12 @@ bool isNothing(B b) { return b.u==bi_nothing.u; } // refcount -void value_free(B x, Value* vx) { +static inline void value_free(B x, Value* vx) { ti[vx->type].free(x); mm_free(vx); } +static NOINLINE void value_freeR1(Value* x) { value_free(tag(x, OBJ_TAG), x); } +static NOINLINE void value_freeR2(Value* vx, B x) { value_free(x, vx); } void dec(B x) { if (!isVal(VALIDATE(x))) return; Value* vx = v(x); @@ -334,8 +336,11 @@ B inc(B x) { } void ptr_dec(void* x) { if(!--((Value*)x)->refc) value_free(tag(x, OBJ_TAG), x); } void ptr_inc(void* x) { ((Value*)x)->refc++; } -static NOINLINE void value_free_rare(B x, Value* vx) { value_free(x, vx); } -void ptr_dec_rare(void* x) { if(!--((Value*)x)->refc) value_free_rare(tag(x, OBJ_TAG), x); } +void ptr_decR(void* x) { if(!--((Value*)x)->refc) value_freeR1(x); } +void decR(B x) { + if (!isVal(x)) return; Value* vx = v(x); + if(!--vx->refc) value_freeR2(vx, x); +} bool reusable(B x) { return v(x)->refc==1; } diff --git a/src/sysfn.c b/src/sysfn.c index d6f7baa9..d7ceaf97 100644 --- a/src/sysfn.c +++ b/src/sysfn.c @@ -9,7 +9,7 @@ B type_c1(B t, B x) { else if (isFun(x)) r = 3; else if (isMd1(x)) r = 4; else if (isMd2(x)) r = 5; - dec(x); + decR(x); if (r==-1) return err("getting type"); return m_i32(r); } diff --git a/src/vm.c b/src/vm.c index 3893d909..f929688d 100644 --- a/src/vm.c +++ b/src/vm.c @@ -204,7 +204,7 @@ Scope* scd(Scope* sc, u16 d) { return sc; } -B v_set(Scope* sc, B s, B x, bool upd) { // frees s, consumes x, returns previous value +B v_set(Scope* sc, B s, B x, bool upd) { // frees s; returns previous value if (isVar(s)) { sc = scd(sc, (u16)(s.u>>32)); B prev = sc->vars[(u32)s.u]; @@ -214,15 +214,19 @@ B v_set(Scope* sc, B s, B x, bool upd) { // frees s, consumes x, returns previou } else { if (prev.u!=bi_noVar.u) return err("redefining variable"); } - sc->vars[(u32)s.u] = x; + sc->vars[(u32)s.u] = inc(x); } else { VT(s, t_harr); if (!shEq(s, x)) return err("spread assignment: mismatched shape"); usz ia = a(x)->ia; B* sp = harr_ptr(s); BS2B xget = TI(x).get; - for (u64 i = 0; i < ia; i++) v_set(sc, sp[i], xget(x,i), upd); - dec(s); dec(x); + for (u64 i = 0; i < ia; i++) { + B c = xget(x,i); + v_set(sc, sp[i], c, upd); + decR(c); // should never free actually + } + dec(s); } return m_f64(0); } @@ -305,7 +309,7 @@ B evalBC(Body* b, Scope* sc) { break; } case FN1O: { P(f)P(x) - ADD(isNothing(x)? x : c1(f, x); dec(f)); + ADD(isNothing(x)? x : c1(f, x)); dec(f); break; } case FN2C: { P(w)P(f)P(x) @@ -352,12 +356,12 @@ B evalBC(Body* b, Scope* sc) { ADD(inc(scd(sc,d)->vars[p])); break; } - case SETN: { P(s) P(x) v_set(sc, s, inc(x), false); ADD(x); break; } - case SETU: { P(s) P(x) v_set(sc, s, inc(x), true ); ADD(x); break; } + case SETN: { P(s) P(x) v_set(sc, s, x, false); ADD(x); break; } + case SETU: { P(s) P(x) v_set(sc, s, x, true ); ADD(x); break; } case SETM: { P(s)P(f)P(x) B w = v_get(sc, s); B r = c2(f,w,x); dec(f); - v_set(sc, s, inc(r), true); + v_set(sc, s, r, true); ADD(r); break; } @@ -439,18 +443,18 @@ B m_md2Block(Block* bl, Scope* psc) { return r; } -void comp_free(B x) { Comp* c = c(Comp ,x); ptr_dec(c->objs); dec(c->bc); } -void body_free(B x) { Body* c = c(Body ,x); ptr_dec(c->comp); } -void block_free(B x) { Block* c = c(Block,x); ptr_dec(c->body); } +void comp_free(B x) { Comp* c = c(Comp ,x); ptr_decR(c->objs); decR(c->bc); } +void body_free(B x) { Body* c = c(Body ,x); ptr_decR(c->comp); } +void block_free(B x) { Block* c = c(Block,x); ptr_decR(c->body); } void scope_free(B x) { Scope* c = c(Scope,x); - if (c->psc) ptr_dec_rare(c->psc); + if (c->psc) ptr_decR(c->psc); u16 am = c->varAm; for (u32 i = 0; i < am; i++) dec(c->vars[i]); } -void funBl_free(B x) { FunBlock* c = c(FunBlock,x); ptr_dec_rare(c->sc); ptr_dec_rare(c->bl); } -void md1Bl_free(B x) { Md1Block* c = c(Md1Block,x); ptr_dec_rare(c->sc); ptr_dec_rare(c->bl); } -void md2Bl_free(B x) { Md2Block* c = c(Md2Block,x); ptr_dec_rare(c->sc); ptr_dec_rare(c->bl); } +void funBl_free(B x) { FunBlock* c = c(FunBlock,x); ptr_decR(c->sc); ptr_decR(c->bl); } +void md1Bl_free(B x) { Md1Block* c = c(Md1Block,x); ptr_decR(c->sc); ptr_decR(c->bl); } +void md2Bl_free(B x) { Md2Block* c = c(Md2Block,x); ptr_decR(c->sc); ptr_decR(c->bl); } void comp_print (B x) { printf("(%p: comp)",v(x)); } void body_print (B x) { printf("(%p: body varam=%d)",v(x),c(Body,x)->varAm); }