free should take pointer as arg
This commit is contained in:
parent
5dfa9e0e31
commit
fb7bfcf188
@ -79,7 +79,7 @@ B c32slice_slice(B x, usz s) { B r = m_c32slice(inc(c(Slice,x)->p), c(C32Slice,x
|
||||
|
||||
B c32arr_get (B x, usz n) { VT(x,t_c32arr ); return m_c32(c(C32Arr ,x)->a[n]); }
|
||||
B c32slice_get(B x, usz n) { VT(x,t_c32slice); return m_c32(c(C32Slice,x)->a[n]); }
|
||||
void c32arr_free(B x) { decSh(x); }
|
||||
void c32arr_free(Value* x) { decSh(x); }
|
||||
bool c32arr_canStore(B x) { return isC32(x); }
|
||||
|
||||
static inline void c32arr_init() {
|
||||
|
||||
10
src/derv.c
10
src/derv.c
@ -24,11 +24,11 @@ typedef struct Atop {
|
||||
B g, h;
|
||||
} Atop;
|
||||
|
||||
void md1D_free(B x) { dec(c(Md1D,x)->m1); dec(c(Md1D,x)->f); }
|
||||
void md2D_free(B x) { dec(c(Md2D,x)->m2); dec(c(Md2D,x)->f); dec(c(Md2D,x)->g); }
|
||||
void md2H_free(B x) { dec(c(Md2H,x)->m2); dec(c(Md2H,x)->g); }
|
||||
void fork_free(B x) { dec(c(Fork,x)->f ); dec(c(Fork,x)->g); dec(c(Fork,x)->h); }
|
||||
void atop_free(B x) { dec(c(Atop,x)->g); dec(c(Atop,x)->h); }
|
||||
void md1D_free(Value* x) { dec(((Md1D*)x)->m1); dec(((Md1D*)x)->f); }
|
||||
void md2D_free(Value* x) { dec(((Md2D*)x)->m2); dec(((Md2D*)x)->f); dec(((Md2D*)x)->g); }
|
||||
void md2H_free(Value* x) { dec(((Md2H*)x)->m2); dec(((Md2H*)x)->g); }
|
||||
void fork_free(Value* x) { dec(((Fork*)x)->f ); dec(((Fork*)x)->g); dec(((Fork*)x)->h); }
|
||||
void atop_free(Value* x) { dec(((Atop*)x)->g); dec(((Atop*)x)->h); }
|
||||
|
||||
void md1D_visit(B x) { mm_visit(c(Md1D,x)->m1); mm_visit(c(Md1D,x)->f); }
|
||||
void md2D_visit(B x) { mm_visit(c(Md2D,x)->m2); mm_visit(c(Md2D,x)->f); mm_visit(c(Md2D,x)->g); }
|
||||
|
||||
@ -63,7 +63,7 @@ B f64slice_slice(B x, usz s) { B r = m_f64slice(inc(c(Slice,x)->p), c(F64Slice,x
|
||||
|
||||
B f64arr_get (B x, usz n) { VT(x,t_f64arr ); return m_f64(c(F64Arr ,x)->a[n]); }
|
||||
B f64slice_get(B x, usz n) { VT(x,t_f64slice); return m_f64(c(F64Slice,x)->a[n]); }
|
||||
void f64arr_free(B x) { decSh(x); }
|
||||
void f64arr_free(Value* x) { decSh(x); }
|
||||
bool f64arr_canStore(B x) { return q_f64(x); }
|
||||
|
||||
static inline void f64arr_init() {
|
||||
|
||||
@ -80,11 +80,11 @@ B fillarr_get (B x, usz n) { VT(x,t_fillarr ); return inc(c(FillArr ,x)->a[n
|
||||
B fillslice_get (B x, usz n) { VT(x,t_fillslice); return inc(c(FillSlice,x)->a[n]); }
|
||||
B fillarr_getU (B x, usz n) { VT(x,t_fillarr ); return c(FillArr ,x)->a[n] ; }
|
||||
B fillslice_getU(B x, usz n) { VT(x,t_fillslice); return c(FillSlice,x)->a[n] ; }
|
||||
void fillarr_free(B x) {
|
||||
void fillarr_free(Value* x) {
|
||||
decSh(x);
|
||||
B* p = c(FillArr, x)->a;
|
||||
dec(c(FillArr, x)->fill);
|
||||
usz ia = a(x)->ia;
|
||||
B* p = ((FillArr*)x)->a;
|
||||
dec(((FillArr*)x)->fill);
|
||||
usz ia = ((Arr*)x)->ia;
|
||||
for (usz i = 0; i < ia; i++) dec(p[i]);
|
||||
}
|
||||
void fillarr_visit(B x) {
|
||||
|
||||
2
src/gc.c
2
src/gc.c
@ -71,7 +71,7 @@ void gc_tryFree(Value* v) {
|
||||
gc_freedBytes+= mm_size(v); gc_freedCount++;
|
||||
#endif
|
||||
v->type = t_freed;
|
||||
ti[t].free(tag(v, OBJ_TAG));
|
||||
ti[t].free(v);
|
||||
// Object may not be immediately freed if it's not a part of a cycle, but instead a descendant of one.
|
||||
// It will be freed when the cycle is freed, and the t_freed type ensures it doesn't double-free itself
|
||||
}
|
||||
|
||||
26
src/h.h
26
src/h.h
@ -319,8 +319,9 @@ typedef struct ShArr {
|
||||
struct Value;
|
||||
usz a[];
|
||||
} ShArr;
|
||||
ShArr* shObj(B x) { return (ShArr*)((u64)a(x)->sh-offsetof(ShArr,a)); }
|
||||
void decSh(B x) { if (rnk(x)>1) ptr_dec(shObj(x)); }
|
||||
ShArr* shObj (B x) { return (ShArr*)((u64)a(x)->sh-offsetof(ShArr,a)); }
|
||||
ShArr* shObjP(Value* x) { return (ShArr*)((u64)((Arr*)x)->sh-offsetof(ShArr,a)); }
|
||||
void decSh(Value* x) { if (prnk(x)>1) ptr_dec(shObjP(x)); }
|
||||
|
||||
void arr_shVec(B x, usz ia) {
|
||||
a(x)->ia = ia;
|
||||
@ -391,7 +392,7 @@ typedef struct Slice {
|
||||
struct Arr;
|
||||
B p;
|
||||
} Slice;
|
||||
void slice_free(B x) { dec(c(Slice,x)->p); decSh(x); }
|
||||
void slice_free(Value* x) { dec(((Slice*)x)->p); decSh(x); }
|
||||
void slice_visit(B x) { mm_visit(c(Slice,x)->p); }
|
||||
void slice_print(B x) { arr_print(x); }
|
||||
|
||||
@ -409,7 +410,7 @@ typedef B (*BBBBB2B)(B, B, B, B, B);
|
||||
typedef bool (*B2b)(B);
|
||||
|
||||
typedef struct TypeInfo {
|
||||
B2v free; // expects refc==0, type may be cleared to t_empty for garbage collection
|
||||
V2v free; // expects refc==0, type may be cleared to t_empty for garbage collection
|
||||
BS2B get; // increments result, doesn't consume arg; TODO figure out if this should never allocate, so GC wouldn't happen
|
||||
BS2B getU; // like get, but doesn't increment result (mostly equivalent to `B t=get(…); dec(t); t`)
|
||||
BB2B m1_d; // consume all args; (m, f)
|
||||
@ -437,23 +438,22 @@ bool isNothing(B b) { return b.u==bi_N.u; }
|
||||
|
||||
// refcount
|
||||
bool reusable(B x) { return v(x)->refc==1; }
|
||||
static inline void value_free(B x, Value* vx) {
|
||||
ti[vx->type].free(x);
|
||||
mm_free(vx);
|
||||
static inline void value_free(Value* x) {
|
||||
ti[x->type].free(x);
|
||||
mm_free(x);
|
||||
}
|
||||
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); }
|
||||
static NOINLINE void value_freeR(Value* x) { value_free(x); }
|
||||
void dec(B x) {
|
||||
if (!isVal(VALIDATE(x))) return;
|
||||
Value* vx = v(x);
|
||||
if(!--vx->refc) value_free(x, vx);
|
||||
if(!--vx->refc) value_free(vx);
|
||||
}
|
||||
void ptr_dec(void* x) { if(!--VALIDATEP((Value*)x)->refc) value_free(tag(x, OBJ_TAG), x); }
|
||||
void ptr_decR(void* x) { if(!--VALIDATEP((Value*)x)->refc) value_freeR1(x); }
|
||||
void ptr_dec(void* x) { if(!--VALIDATEP((Value*)x)->refc) value_free(x); }
|
||||
void ptr_decR(void* x) { if(!--VALIDATEP((Value*)x)->refc) value_freeR(x); }
|
||||
void decR(B x) {
|
||||
if (!isVal(VALIDATE(x))) return;
|
||||
Value* vx = v(x);
|
||||
if(!--vx->refc) value_freeR2(vx, x);
|
||||
if(!--vx->refc) value_freeR(vx);
|
||||
}
|
||||
B inc(B x) {
|
||||
if (isVal(VALIDATE(x))) v(x)->refc++;
|
||||
|
||||
14
src/harr.c
14
src/harr.c
@ -164,10 +164,10 @@ B harr_get (B x, usz n) { VT(x,t_harr ); return inc(c(HArr ,x)->a[n]); }
|
||||
B hslice_get (B x, usz n) { VT(x,t_hslice); return inc(c(HSlice,x)->a[n]); }
|
||||
B harr_getU (B x, usz n) { VT(x,t_harr ); return c(HArr ,x)->a[n] ; }
|
||||
B hslice_getU(B x, usz n) { VT(x,t_hslice); return c(HSlice,x)->a[n] ; }
|
||||
void harr_free(B x) {
|
||||
void harr_free(Value* x) {
|
||||
decSh(x);
|
||||
B* p = c(HArr,x)->a; // don't use harr_ptr so type isn't checked
|
||||
usz ia = a(x)->ia;
|
||||
B* p = ((HArr*)x)->a; // don't use harr_ptr so type isn't checked
|
||||
usz ia = ((Arr*)x)->ia;
|
||||
for (usz i = 0; i < ia; i++) dec(p[i]);
|
||||
}
|
||||
void harr_visit(B x) {
|
||||
@ -184,10 +184,10 @@ NOINLINE void harr_pfree(B x, usz am) { // am - item after last written
|
||||
for (usz i = 0; i < am; i++) dec(p[i]);
|
||||
mm_free(v(x));
|
||||
}
|
||||
void harrP_free(B x) { assert(v(x)->type==t_harrPartial|v(x)->type==t_freed);
|
||||
assert(rnk(x)>1? true : a(x)->sh!=&a(x)->ia);
|
||||
B* p = c(HArr,x)->a;
|
||||
usz am = *c(HArr,x)->sh;
|
||||
void harrP_free(Value* x) { assert(x->type==t_harrPartial|x->type==t_freed);
|
||||
assert(prnk(x)>1? true : ((Arr*)x)->sh!=&((Arr*)x)->ia);
|
||||
B* p = ((HArr*)x)->a;
|
||||
usz am = *((HArr*)x)->sh;
|
||||
// printf("partfree %d/%d %p\n", am, a(x)->ia, (void*)x.u);
|
||||
for (usz i = 0; i < am; i++) dec(p[i]);
|
||||
}
|
||||
|
||||
@ -41,13 +41,13 @@ bool heapVerify_visitP(void* x) {
|
||||
}
|
||||
|
||||
void heapVerify_callVisit(Value* v) {
|
||||
if (ti[v->type].isArr && rnk(tag(v,ARR_TAG))>1) heapVerify_visitP(shObj(tag(v,ARR_TAG)));
|
||||
if (ti[v->type].isArr && prnk(v)>1) heapVerify_visitP(shObjP(v));
|
||||
ti[v->type].visit(tag(v,OBJ_TAG));
|
||||
}
|
||||
|
||||
void heap_getReferents(Value* v) {
|
||||
heap_curr = v;
|
||||
if (ti[v->type].isArr && rnk(tag(v,ARR_TAG))>1) heapVerify_visitP(shObj(tag(v,ARR_TAG)));
|
||||
if (ti[v->type].isArr && prnk(v)>1) heapVerify_visitP(shObjP(v));
|
||||
ti[v->type].visit(tag(v,OBJ_TAG));
|
||||
}
|
||||
#ifdef CATCH_ERRORS
|
||||
|
||||
@ -63,7 +63,7 @@ B i32slice_slice(B x, usz s) { B r = m_i32slice(inc(c(Slice,x)->p), c(I32Slice,x
|
||||
|
||||
B i32arr_get (B x, usz n) { VT(x,t_i32arr ); return m_i32(c(I32Arr ,x)->a[n]); }
|
||||
B i32slice_get(B x, usz n) { VT(x,t_i32slice); return m_i32(c(I32Slice,x)->a[n]); }
|
||||
void i32arr_free(B x) { decSh(x); }
|
||||
void i32arr_free(Value* x) { decSh(x); }
|
||||
bool i32arr_canStore(B x) { return q_i32(x); }
|
||||
|
||||
static inline void i32arr_init() {
|
||||
|
||||
8
src/ns.c
8
src/ns.c
@ -63,8 +63,8 @@ B ns_nameList(NSDesc* d) {
|
||||
|
||||
|
||||
|
||||
void ns_free(B x) {
|
||||
NS* c = c(NS, x);
|
||||
void ns_free(Value* x) {
|
||||
NS* c = (NS*)x;
|
||||
ptr_decR(c->desc);
|
||||
ptr_decR(c->sc);
|
||||
}
|
||||
@ -93,8 +93,8 @@ void ns_print(B x) {
|
||||
putchar('}');
|
||||
}
|
||||
|
||||
void nsDesc_free(B x) {
|
||||
decR(c(NSDesc,x)->nameList);
|
||||
void nsDesc_free(Value* x) {
|
||||
decR(((NSDesc*)x)->nameList);
|
||||
}
|
||||
void nsDesc_visit(B x) {
|
||||
mm_visit(c(NSDesc,x)->nameList);
|
||||
|
||||
@ -148,7 +148,7 @@ B shape_c1(B t, B x) {
|
||||
if (isAtm(x)) thrM("⥊: deshaping non-array");
|
||||
usz ia = a(x)->ia;
|
||||
if (reusable(x)) {
|
||||
decSh(x);
|
||||
decSh(v(x));
|
||||
arr_shVec(x, ia);
|
||||
return x;
|
||||
}
|
||||
@ -165,7 +165,7 @@ B shape_c2(B t, B w, B x) {
|
||||
ur nr = (ur)wia;
|
||||
usz nia = a(x)->ia;
|
||||
B r;
|
||||
if (reusable(x)) { r = x; decSh(x); }
|
||||
if (reusable(x)) { r = x; decSh(v(x)); }
|
||||
else r = TI(x).slice(x, 0);
|
||||
usz* sh = arr_shAllocI(r, nia, nr);
|
||||
if (sh) for (u32 i = 0; i < nr; i++) sh[i] = o2s(wget(w,i));
|
||||
|
||||
13
src/stuff.c
13
src/stuff.c
@ -10,8 +10,9 @@
|
||||
#endif
|
||||
|
||||
|
||||
void empty_free(B x) { err("FREEING EMPTY\n"); }
|
||||
void builtin_free(B x) { err("FREEING BUILTIN\n"); }
|
||||
void empty_free(Value* x) { err("FREEING EMPTY\n"); }
|
||||
void builtin_free(Value* x) { err("FREEING BUILTIN\n"); }
|
||||
void def_free(Value* x) { }
|
||||
void def_visit(B x) { printf("(no visit for %d=%s)\n", v(x)->type, format_type(v(x)->type)); }
|
||||
void freed_visit(B x) {
|
||||
#ifndef CATCH_ERRORS
|
||||
@ -218,8 +219,8 @@ u8 fillElType(B x) {
|
||||
}
|
||||
if (ti[x->type].isArr) {
|
||||
Arr* a = (Arr*)x;
|
||||
if (rnk(tag(x,ARR_TAG))<=1) assert(a->sh == &a->ia);
|
||||
else VALIDATE(tag(shObj(tag(x,ARR_TAG)),OBJ_TAG));
|
||||
if (prnk(x)<=1) assert(a->sh == &a->ia);
|
||||
else VALIDATE(tag(shObjP(x),OBJ_TAG));
|
||||
}
|
||||
return x;
|
||||
}
|
||||
@ -245,7 +246,7 @@ u8 fillElType(B x) {
|
||||
|
||||
static inline void hdr_init() {
|
||||
for (i32 i = 0; i < t_COUNT; i++) {
|
||||
ti[i].free = do_nothing;
|
||||
ti[i].free = def_free;
|
||||
ti[i].visit = def_visit;
|
||||
ti[i].get = def_get;
|
||||
ti[i].getU = def_getU;
|
||||
@ -261,7 +262,7 @@ static inline void hdr_init() {
|
||||
ti[i].canStore = def_canStore;
|
||||
}
|
||||
ti[t_empty].free = empty_free;
|
||||
ti[t_freed].free = do_nothing;
|
||||
ti[t_freed].free = def_free;
|
||||
ti[t_freed].visit = freed_visit;
|
||||
ti[t_shape].visit = do_nothing;
|
||||
ti[t_funBI].visit = ti[t_md1BI].visit = ti[t_md2BI].visit = do_nothing;
|
||||
|
||||
20
src/vm.c
20
src/vm.c
@ -561,24 +561,24 @@ B m_md2Block(Block* bl, Scope* psc) {
|
||||
return r;
|
||||
}
|
||||
|
||||
void comp_free(B x) {
|
||||
Comp* c = c(Comp, x);
|
||||
void comp_free(Value* x) {
|
||||
Comp* c = (Comp*)x;
|
||||
ptr_decR(c->objs); decR(c->bc); decR(c->src); decR(c->indices);
|
||||
u32 am = c->blockAm; for(u32 i = 0; i < am; i++) ptr_dec(c->blocks[i]);
|
||||
}
|
||||
void scope_free(B x) {
|
||||
Scope* c = c(Scope,x);
|
||||
void scope_free(Value* x) {
|
||||
Scope* c = (Scope*)x;
|
||||
if (c->psc) ptr_decR(c->psc);
|
||||
ptr_decR(c->body);
|
||||
u16 am = c->varAm;
|
||||
for (u32 i = 0; i < am; i++) dec(c->vars[i]);
|
||||
}
|
||||
void body_free(B x) { Body* c = c(Body ,x); ptr_decR(c->comp); if(c->nsDesc)ptr_decR(c->nsDesc); }
|
||||
void block_free(B x) { Block* c = c(Block,x); ptr_decR(c->body); }
|
||||
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 alias_free(B x) { dec(c(FldAlias,x)->obj); }
|
||||
void body_free(Value* x) { Body* c = (Body*)x; ptr_decR(c->comp); if(c->nsDesc)ptr_decR(c->nsDesc); }
|
||||
void block_free(Value* x) { Block* c = (Block*)x; ptr_decR(c->body); }
|
||||
void funBl_free(Value* x) { FunBlock* c = (FunBlock*)x; ptr_decR(c->sc); ptr_decR(c->bl); }
|
||||
void md1Bl_free(Value* x) { Md1Block* c = (Md1Block*)x; ptr_decR(c->sc); ptr_decR(c->bl); }
|
||||
void md2Bl_free(Value* x) { Md2Block* c = (Md2Block*)x; ptr_decR(c->sc); ptr_decR(c->bl); }
|
||||
void alias_free(Value* x) { dec(((FldAlias*)x)->obj); }
|
||||
|
||||
void comp_visit(B x) {
|
||||
Comp* c = c(Comp,x);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user