more refcount fixes
This commit is contained in:
parent
c820b4b3a5
commit
2d43489cd2
@ -46,8 +46,8 @@ B m_c32slice(B p, u32* ptr) {
|
||||
return tag(r, ARR_TAG);
|
||||
}
|
||||
|
||||
B c32arr_slice (B x, usz s) {return m_c32slice(x , c(C32Arr ,x)->a+s); }
|
||||
B c32slice_slice(B x, usz s) { B r = m_c32slice(inc(c(C32Slice,x)->p), c(C32Slice,x)->a+s); dec(x); return r; }
|
||||
B c32arr_slice (B x, usz s) {return m_c32slice(x , c(C32Arr ,x)->a+s); }
|
||||
B c32slice_slice(B x, usz s) { B r = m_c32slice(inc(c(Slice,x)->p), c(C32Slice,x)->a+s); dec(x); return r; }
|
||||
|
||||
|
||||
B c32arr_get (B x, usz n) { VT(x,t_c32arr ); return m_c32(c(C32Arr ,x)->a[n]); }
|
||||
|
||||
@ -50,8 +50,8 @@ B m_fillslice(B p, B* ptr) {
|
||||
}
|
||||
|
||||
B* fillarr_ptr(B x) { VT(x,t_fillarr); return c(FillArr,x)->a; }
|
||||
B fillarr_slice (B x, usz s) {return m_fillslice(x , c(FillArr ,x)->a+s); }
|
||||
B fillslice_slice(B x, usz s) { B r = m_fillslice(inc(c(FillSlice,x)->p), c(FillSlice,x)->a+s); dec(x); return r; }
|
||||
B fillarr_slice (B x, usz s) {return m_fillslice(x , c(FillArr ,x)->a+s); }
|
||||
B fillslice_slice(B x, usz s) { B r = m_fillslice(inc(c(Slice,x)->p), c(FillSlice,x)->a+s); dec(x); return r; }
|
||||
|
||||
|
||||
B fillarr_get (B x, usz n) { VT(x,t_fillarr ); return inc(c(FillArr ,x)->a[n]); }
|
||||
|
||||
74
src/h.h
74
src/h.h
@ -31,10 +31,12 @@ CTR_FOR(CTR_DEF)
|
||||
|
||||
#ifdef DEBUG
|
||||
#include<assert.h>
|
||||
#define VALIDATE(x) validate(x) // preferred validating level
|
||||
#define VALIDATE(x) validate(x)
|
||||
#define VALIDATEP(x) validateP(x)
|
||||
#else
|
||||
#define assert(x) {if (!(x)) __builtin_unreachable();}
|
||||
#define VALIDATE(x) (x)
|
||||
#define VALIDATEP(x) (x)
|
||||
#endif
|
||||
|
||||
#define fsizeof(T,F,E,n) (offsetof(T, F) + sizeof(E)*(n)) // type; FAM name; FAM type; amount
|
||||
@ -71,7 +73,7 @@ enum Type {
|
||||
|
||||
/*21*/ t_comp, t_block, t_body, t_scope,
|
||||
/*25*/ t_freed,
|
||||
Type_MAX
|
||||
t_COUNT
|
||||
};
|
||||
char* format_type(u8 u) {
|
||||
switch(u) { default: return"(unknown type)";
|
||||
@ -207,10 +209,7 @@ B m_v4(B a, B b, B c, B d);
|
||||
void print_vmStack();
|
||||
#ifdef DEBUG
|
||||
B validate(B x);
|
||||
B recvalidate(B x);
|
||||
#else
|
||||
#define validate(x) (x)
|
||||
#define recvalidate(x) (x)
|
||||
Value* validateP(Value* x);
|
||||
#endif
|
||||
B err(char* s) {
|
||||
puts(s); fflush(stdout);
|
||||
@ -254,10 +253,11 @@ void arr_shVec(B x, usz ia) {
|
||||
srnk(x, 1);
|
||||
a(x)->sh = &a(x)->ia;
|
||||
}
|
||||
bool gotShape[t_COUNT];
|
||||
usz* arr_shAlloc(B x, usz ia, usz r) {
|
||||
a(x)->ia = ia;
|
||||
srnk(x,r);
|
||||
if (r>1) return a(x)->sh = c(ShArr,mm_alloc(fsizeof(ShArr, a, usz, r), t_shape, ftag(OBJ_TAG)))->a;
|
||||
if (r>1) return a(x)->sh = ((ShArr*)mm_allocN(fsizeof(ShArr, a, usz, r), t_shape))->a;
|
||||
a(x)->sh = &a(x)->ia;
|
||||
return 0;
|
||||
}
|
||||
@ -268,8 +268,8 @@ void arr_shCopy(B n, B o) { // copy shape from o to n
|
||||
if (r<=1) {
|
||||
a(n)->sh = &a(n)->ia;
|
||||
} else {
|
||||
a(n)->sh = a(o)->sh;
|
||||
ptr_inc(shObj(o));
|
||||
a(n)->sh = a(o)->sh;
|
||||
}
|
||||
}
|
||||
bool shEq(B w, B x) { assert(isArr(w)); assert(isArr(x));
|
||||
@ -341,7 +341,7 @@ typedef struct TypeInfo {
|
||||
B2B decompose; // consumes; must return a HArr
|
||||
bool isArr;
|
||||
} TypeInfo;
|
||||
TypeInfo ti[Type_MAX];
|
||||
TypeInfo ti[t_COUNT];
|
||||
#define TI(x) (ti[v(x)->type])
|
||||
|
||||
|
||||
@ -349,6 +349,7 @@ void do_nothing(B x) { }
|
||||
void empty_free(B x) { err("FREEING EMPTY\n"); }
|
||||
void builtin_free(B x) { err("FREEING BUILTIN\n"); }
|
||||
void def_visit(B x) { printf("(no visit for %d=%s)\n", v(x)->type, format_type(v(x)->type)); }
|
||||
void freeed_visit(B x) { err("visiting t_freed\n"); }
|
||||
void def_print(B x) { printf("(%d=%s)", v(x)->type, format_type(v(x)->type)); }
|
||||
B def_get (B x, usz n) { return inc(x); }
|
||||
B def_getU(B x, usz n) { return x; }
|
||||
@ -359,7 +360,7 @@ B def_decompose(B x) { return m_v2(m_i32((isFun(x)|isMd(x))? 0 : -1),x); }
|
||||
bool def_canStore(B x) { return false; }
|
||||
B bi_nothing, bi_noVar, bi_badHdr, bi_optOut, bi_noFill;
|
||||
void hdr_init() {
|
||||
for (i32 i = 0; i < Type_MAX; i++) {
|
||||
for (i32 i = 0; i < t_COUNT; i++) {
|
||||
ti[i].free = do_nothing;
|
||||
ti[i].visit = def_visit;
|
||||
ti[i].get = def_get;
|
||||
@ -374,6 +375,7 @@ void hdr_init() {
|
||||
}
|
||||
ti[t_empty].free = empty_free;
|
||||
ti[t_freed].free = do_nothing;
|
||||
ti[t_freed].visit = freeed_visit;
|
||||
ti[t_shape].visit = do_nothing;
|
||||
ti[t_fun_def].visit = ti[t_md1_def].visit = ti[t_md2_def].visit = do_nothing;
|
||||
ti[t_fun_def].free = ti[t_md1_def].free = ti[t_md2_def].free = builtin_free;
|
||||
@ -404,11 +406,11 @@ B inc(B x) {
|
||||
if (isVal(VALIDATE(x))) v(x)->refc++;
|
||||
return 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++; }
|
||||
void ptr_decR(void* x) { if(!--((Value*)x)->refc) value_freeR1(x); }
|
||||
void ptr_dec(void* x) { if(!--VALIDATEP((Value*)x)->refc) value_free(tag(x, OBJ_TAG), x); }
|
||||
void ptr_inc(void* x) { VALIDATEP((Value*)x)->refc++; }
|
||||
void ptr_decR(void* x) { if(!--VALIDATEP((Value*)x)->refc) value_freeR1(x); }
|
||||
void decR(B x) {
|
||||
if (!isVal(x)) return;
|
||||
if (!isVal(VALIDATE(x))) return;
|
||||
Value* vx = v(x);
|
||||
if(!--vx->refc) value_freeR2(vx, x);
|
||||
}
|
||||
@ -572,31 +574,26 @@ u64 nsTime() {
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
B validate(B x) {
|
||||
if (!isVal(x)) return x;
|
||||
if (v(x)->refc<=0 || (v(x)->refc>>28) == 'a') {
|
||||
printf("bad refcount for type %d: %d; val=%p\nattempting to print: ", v(x)->type, v(x)->refc, (void*)x.u); fflush(stdout);
|
||||
print(x); puts(""); fflush(stdout);
|
||||
Value* validateP(Value* x) {
|
||||
if (x->refc<=0 || (x->refc>>28) == 'a' || x->type==t_empty) {
|
||||
printf("bad refcount for type %d: %d\nattempting to print: ", x->type, x->refc); fflush(stdout);
|
||||
print(tag(x,OBJ_TAG)); puts(""); fflush(stdout);
|
||||
err("");
|
||||
}
|
||||
if (isArr(x) && v(x)->type!=t_freed) {
|
||||
ur r = rnk(x);
|
||||
if (r<=1) assert(a(x)->sh == &a(x)->ia);
|
||||
else validate(tag(shObj(x),OBJ_TAG));
|
||||
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));
|
||||
}
|
||||
return x;
|
||||
}
|
||||
B recvalidate(B x) {
|
||||
validate(x);
|
||||
if (isArr(x)) {
|
||||
BS2B xget = TI(x).get;
|
||||
usz ia = a(x)->ia;
|
||||
for (usz i = 0; i < ia; i++) {
|
||||
B c = xget(x,i);
|
||||
assert(c.u!=x.u);
|
||||
recvalidate(c);
|
||||
dec(c);
|
||||
}
|
||||
B validate(B x) {
|
||||
if (!isVal(x)) return x;
|
||||
validateP(v(x));
|
||||
if(isArr(x)!=TI(x).isArr && v(x)->type!=t_freed) {
|
||||
printf("wat %d %p\n", v(x)->type, (void*)x.u);
|
||||
print(x);
|
||||
err("\nk");
|
||||
}
|
||||
return x;
|
||||
}
|
||||
@ -617,12 +614,12 @@ static inline void onAlloc(usz sz, u8 type) {
|
||||
if (!ctr_a) {
|
||||
#ifdef ALLOC_SIZES
|
||||
actrs = malloc(sizeof(u32*)*actrc);
|
||||
for (i32 i = 0; i < actrc; i++) actrs[i] = calloc(Type_MAX, sizeof(u32));
|
||||
for (i32 i = 0; i < actrc; i++) actrs[i] = calloc(t_COUNT, sizeof(u32));
|
||||
#endif
|
||||
ctr_a = calloc(Type_MAX, sizeof(u64));
|
||||
ctr_f = calloc(Type_MAX, sizeof(u64));
|
||||
ctr_a = calloc(t_COUNT, sizeof(u64));
|
||||
ctr_f = calloc(t_COUNT, sizeof(u64));
|
||||
}
|
||||
assert(type<Type_MAX);
|
||||
assert(type<t_COUNT);
|
||||
#ifdef ALLOC_SIZES
|
||||
actrs[(sz+3)/4>=actrc? actrc-1 : (sz+3)/4][type]++;
|
||||
#endif
|
||||
@ -635,6 +632,7 @@ static inline void onFree(Value* x) {
|
||||
ctr_f[x->type]++;
|
||||
#endif
|
||||
#ifdef DEBUG
|
||||
if (x->type==t_empty) err("double-free");
|
||||
// u32 undef;
|
||||
// x->refc = undef;
|
||||
x->refc = -1431655000;
|
||||
|
||||
@ -77,8 +77,8 @@ B m_hslice(B p, B* ptr) {
|
||||
return tag(r, ARR_TAG);
|
||||
}
|
||||
|
||||
B harr_slice (B x, usz s) {return m_hslice(x , c(HArr ,x)->a+s); }
|
||||
B hslice_slice(B x, usz s) { B r = m_hslice(inc(c(HSlice,x)->p), c(HSlice,x)->a+s); dec(x); return r; }
|
||||
B harr_slice (B x, usz s) {return m_hslice(x , c(HArr ,x)->a+s); }
|
||||
B hslice_slice(B x, usz s) { B r = m_hslice(inc(c(Slice,x)->p), c(HSlice,x)->a+s); dec(x); return r; }
|
||||
|
||||
|
||||
B harr_get (B x, usz n) { VT(x,t_harr ); return inc(c(HArr ,x)->a[n]); }
|
||||
|
||||
54
src/heap.c
54
src/heap.c
@ -1,6 +1,3 @@
|
||||
u32 heapVerify_mode = -1;
|
||||
|
||||
|
||||
u64 heapUsed_ctr;
|
||||
void heapUsedFn(Value* p) { heapUsed_ctr+= mm_size(p); }
|
||||
u64 mm_heapUsed() {
|
||||
@ -10,30 +7,25 @@ u64 mm_heapUsed() {
|
||||
}
|
||||
|
||||
|
||||
void heap_checkFn(Value* v) {
|
||||
|
||||
#ifdef HEAP_VERIFY
|
||||
u32 heapVerify_mode = -1;
|
||||
|
||||
Value* heap_observed;
|
||||
Value* heap_curr;
|
||||
void heapVerify_checkFn(Value* v) {
|
||||
if (v->refc!=0) {
|
||||
#ifdef OBJ_COUNTER
|
||||
printf("delta %d for %s, uid %ld: ", v->refc, format_type(v->type), v->uid);
|
||||
#else
|
||||
printf("delta %d for %s: ", (i32)v->refc, format_type(v->type));
|
||||
#endif
|
||||
heap_observed = v;
|
||||
print(tag(v,OBJ_TAG)); puts("");
|
||||
}
|
||||
}
|
||||
void heap_callVisit(Value* v) {
|
||||
ti[v->type].visit(tag(v,OBJ_TAG));
|
||||
}
|
||||
void heapVerify() {
|
||||
#ifndef HEAP_VERIFY
|
||||
err("heapVerify() HEAP_VERIFY to be defined");
|
||||
#endif
|
||||
heapVerify_mode=0; mm_forHeap(heap_callVisit); gc_visitRoots();
|
||||
mm_forHeap(heap_checkFn);
|
||||
heapVerify_mode=1; mm_forHeap(heap_callVisit); gc_visitRoots();
|
||||
heapVerify_mode=-1;
|
||||
}
|
||||
|
||||
#ifdef HEAP_VERIFY
|
||||
|
||||
bool heapVerify_visit(B x) {
|
||||
if (heapVerify_mode==-1) return false;
|
||||
if (isVal(x)) mm_visitP(v(x));
|
||||
@ -42,8 +34,32 @@ bool heapVerify_visit(B x) {
|
||||
bool heapVerify_visitP(void* x) {
|
||||
if(heapVerify_mode==-1) return false;
|
||||
Value* v = x;
|
||||
if(heapVerify_mode==0) { v->refc--; if(ti[v->type].isArr && rnk(tag(v,OBJ_TAG))>1)heapVerify_visitP(shObj(tag(v,OBJ_TAG))); }
|
||||
if(heapVerify_mode==1) { v->refc++; if(ti[v->type].isArr && rnk(tag(v,OBJ_TAG))>1)heapVerify_visitP(shObj(tag(v,OBJ_TAG))); }
|
||||
if(heapVerify_mode==0) v->refc--;
|
||||
else if(heapVerify_mode==1) v->refc++;
|
||||
else if(heapVerify_mode==2) if (x==heap_observed) { printf("referee: %p ", heap_curr); print(tag(heap_curr,OBJ_TAG)); puts(""); }
|
||||
return true;
|
||||
}
|
||||
|
||||
void heapVerify_callVisit(Value* v) {
|
||||
if (ti[v->type].isArr && rnk(tag(v,ARR_TAG))>1) heapVerify_visitP(shObj(tag(v,ARR_TAG)));
|
||||
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)));
|
||||
ti[v->type].visit(tag(v,OBJ_TAG));
|
||||
}
|
||||
void heapVerify() {
|
||||
heap_observed = 0;
|
||||
heapVerify_mode=0; mm_forHeap(heapVerify_callVisit); gc_visitRoots();
|
||||
mm_forHeap(heapVerify_checkFn);
|
||||
heapVerify_mode=1; mm_forHeap(heapVerify_callVisit); gc_visitRoots();
|
||||
if (heap_observed) {
|
||||
printf("refc of last: %d\n", heap_observed->refc);
|
||||
heapVerify_mode=2; mm_forHeap(heap_getReferents);
|
||||
}
|
||||
heapVerify_mode=-1;
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -54,8 +54,8 @@ B m_i32slice(B p, i32* ptr) {
|
||||
return tag(r, ARR_TAG);
|
||||
}
|
||||
|
||||
B i32arr_slice (B x, usz s) {return m_i32slice(x , c(I32Arr ,x)->a+s); }
|
||||
B i32slice_slice(B x, usz s) { B r = m_i32slice(inc(c(I32Slice,x)->p), c(I32Slice,x)->a+s); dec(x); return r; }
|
||||
B i32arr_slice (B x, usz s) {return m_i32slice(x , c(I32Arr ,x)->a+s); }
|
||||
B i32slice_slice(B x, usz s) { B r = m_i32slice(inc(c(Slice,x)->p), c(I32Slice,x)->a+s); dec(x); return r; }
|
||||
|
||||
|
||||
B i32arr_get (B x, usz n) { VT(x,t_i32arr ); return m_i32(c(I32Arr ,x)->a[n]); }
|
||||
|
||||
12
src/main.c
12
src/main.c
@ -54,19 +54,19 @@ void printAllocStats() {
|
||||
printf("total ever allocated: %lu\n", talloc);
|
||||
printf("allocated heap size: %ld\n", mm_heapAllocated());
|
||||
printf("used heap size: %ld\n", mm_heapUsed());
|
||||
printf("ctrA←"); for (i64 i = 0; i < Type_MAX; i++) { if(i)printf("‿"); printf("%lu", ctr_a[i]); } printf("\n");
|
||||
printf("ctrF←"); for (i64 i = 0; i < Type_MAX; i++) { if(i)printf("‿"); printf("%lu", ctr_f[i]); } printf("\n");
|
||||
printf("ctrA←"); for (i64 i = 0; i < t_COUNT; i++) { if(i)printf("‿"); printf("%lu", ctr_a[i]); } printf("\n");
|
||||
printf("ctrF←"); for (i64 i = 0; i < t_COUNT; i++) { if(i)printf("‿"); printf("%lu", ctr_f[i]); } printf("\n");
|
||||
u64 leakedCount = 0;
|
||||
for (i64 i = 0; i < Type_MAX; i++) leakedCount+= ctr_a[i]-ctr_f[i];
|
||||
for (i64 i = 0; i < t_COUNT; i++) leakedCount+= ctr_a[i]-ctr_f[i];
|
||||
printf("leaked object count: %ld\n", leakedCount);
|
||||
#ifdef ALLOC_SIZES
|
||||
for(i64 i = 0; i < actrc; i++) {
|
||||
u32* c = actrs[i];
|
||||
bool any = false;
|
||||
for (i64 j = 0; j < Type_MAX; j++) if (c[j]) any=true;
|
||||
for (i64 j = 0; j < t_COUNT; j++) if (c[j]) any=true;
|
||||
if (any) {
|
||||
printf("%ld", i*4);
|
||||
for (i64 k = 0; k < Type_MAX; k++) printf("‿%u", c[k]);
|
||||
for (i64 k = 0; k < t_COUNT; k++) printf("‿%u", c[k]);
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
@ -117,7 +117,7 @@ int main() {
|
||||
dec(c1(rtFinish, m_v2(inc(bi_decp), inc(bi_primInd)))); dec(rtFinish);
|
||||
|
||||
|
||||
B compArg = m_v2(FAKE_RUNTIME? frtObj : rtObj, inc(bi_sys)); dec(FAKE_RUNTIME? rtObj : frtObj);
|
||||
B compArg = m_v2(FAKE_RUNTIME? frtObj : rtObj, inc(bi_sys)); gc_add(FAKE_RUNTIME? rtObj : frtObj);
|
||||
gc_add(compArg);
|
||||
|
||||
|
||||
|
||||
@ -23,7 +23,7 @@ B shape_c2(B t, B w, B x) {
|
||||
if (reusable(x)) { r = x; decSh(x); }
|
||||
else r = TI(x).slice(x, 0);
|
||||
usz* sh = arr_shAlloc(r, nia, nr);
|
||||
if (sh) for (i32 i = 0; i < nr; i++) sh[i] = o2i(wget(w,i));
|
||||
if (sh) for (i32 i = 0; i < nr; i++) sh[i] = o2s(wget(w,i));
|
||||
dec(w);
|
||||
return r;
|
||||
} else return err("reshaping non-array");
|
||||
|
||||
@ -86,7 +86,7 @@ B grOrd_c2(B t, B w, B x) {
|
||||
usz wia = a(w)->ia;
|
||||
usz xia = a(x)->ia;
|
||||
if (wia==0) { dec(w); dec(x); return c1(bi_ud, m_i32(0)); }
|
||||
if (xia==0) { dec(w); dec(x); return x; }
|
||||
if (xia==0) { dec(w); return x; }
|
||||
BS2B wget = TI(w).get;
|
||||
BS2B xget = TI(x).get;
|
||||
usz tmp[wia];
|
||||
@ -145,9 +145,9 @@ void sysfn_init() { bm(type) bm(decp) bm(primInd) bm(glyph) ba(fill) ba(grLen) b
|
||||
B sys_c1(B t, B x) {
|
||||
assert(isArr(x));
|
||||
HArr_p r = m_harrc(x);
|
||||
BS2B xget = TI(x).get;
|
||||
BS2B xgetU = TI(x).getU;
|
||||
for (usz i = 0; i < a(x)->ia; i++) {
|
||||
B c = xget(x,i);
|
||||
B c = xgetU(x,i);
|
||||
if (eqStr(c, U"internal")) r.a[i] = inc(bi_internal);
|
||||
else if (eqStr(c, U"eq")) r.a[i] = inc(bi_feq);
|
||||
else if (eqStr(c, U"decompose")) r.a[i] = inc(bi_decp);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user