more refcount fixes

This commit is contained in:
dzaima 2021-04-14 23:12:59 +03:00
parent c820b4b3a5
commit 2d43489cd2
9 changed files with 89 additions and 75 deletions

View File

@ -47,7 +47,7 @@ B m_c32slice(B p, u32* ptr) {
}
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 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]); }

View File

@ -51,7 +51,7 @@ 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 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
View File

@ -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;

View File

@ -78,7 +78,7 @@ B m_hslice(B p, B* ptr) {
}
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 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]); }

View File

@ -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

View File

@ -55,7 +55,7 @@ B m_i32slice(B p, i32* ptr) {
}
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 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]); }

View File

@ -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);

View File

@ -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");

View File

@ -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);