make heapverify run on GC_VISIT_V2
also make it able to track shape object leaks
This commit is contained in:
parent
c6c0b8925e
commit
a928277e8c
@ -93,6 +93,7 @@ DEF_FREE(harr) {
|
||||
for (usz i = 0; i < ia; i++) dec(p[i]);
|
||||
}
|
||||
static void harr_visit(Value* x) {
|
||||
VISIT_SHAPE(x);
|
||||
usz ia = PIA((Arr*)x); B* p = ((HArr*)x)->a;
|
||||
for (usz i = 0; i < ia; i++) mm_visit(p[i]);
|
||||
}
|
||||
|
||||
@ -30,11 +30,18 @@ void heap_getReferents(Value* v) {
|
||||
TIv(v,visit)(v);
|
||||
}
|
||||
void gc_visitRoots(void);
|
||||
void gcv2_runHeapverify(i32);
|
||||
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 GC_VISIT_V2
|
||||
gcv2_runHeapverify(0);
|
||||
mm_forHeap(heapVerify_checkFn);
|
||||
gcv2_runHeapverify(1);
|
||||
#else
|
||||
heapVerify_mode=0; mm_forHeap(heapVerify_callVisit); gc_visitRoots();
|
||||
mm_forHeap(heapVerify_checkFn);
|
||||
heapVerify_mode=1; mm_forHeap(heapVerify_callVisit); gc_visitRoots();
|
||||
#endif
|
||||
if (heap_observed) {
|
||||
printf("refc of last: %d\n", heap_observed->refc);
|
||||
// heapVerify_mode=2; mm_forHeap(heap_getReferents);
|
||||
|
||||
@ -44,6 +44,9 @@ NOINLINE B c2F(B f, B w, B x) { dec(w); dec(x);
|
||||
NOINLINE void value_freeF(Value* x) { value_free(x); }
|
||||
NOINLINE void decA_F(B x) { dec(x); }
|
||||
void noop_visit(Value* x) { }
|
||||
#if HEAP_VERIFY && GC_VISIT_V2
|
||||
void arr_visit(Value* x) { VISIT_SHAPE(x); }
|
||||
#endif
|
||||
NOINLINE B c1_bad(B f, B x) { thrM("This function can't be called monadically"); }
|
||||
NOINLINE B c2_bad(B f, B w, B x) { thrM("This function can't be called dyadically"); }
|
||||
NOINLINE B m1c1_bad(Md1D* d, B x) { thrM("This 1-modifier can't be called monadically"); }
|
||||
@ -583,7 +586,7 @@ void tyarr_freeO(Value* x) { decSh(x); }
|
||||
void slice_freeO(Value* x) { ptr_dec(((Slice*)x)->p); decSh(x); }
|
||||
void tyarr_freeF(Value* x) { tyarr_freeO(x); mm_free(x); }
|
||||
void slice_freeF(Value* x) { slice_freeO(x); mm_free(x); }
|
||||
void slice_visit(Value* x) { mm_visitP(((Slice*)x)->p); }
|
||||
void slice_visit(Value* x) { mm_visitP(((Slice*)x)->p); VISIT_SHAPE(x); }
|
||||
void slice_print(B x) { arr_print(x); }
|
||||
|
||||
char* type_repr(u8 u) {
|
||||
|
||||
@ -222,6 +222,13 @@ B def_fn_ix(B t, B w, B x);
|
||||
|
||||
B def_decompose(B x);
|
||||
void noop_visit(Value* x);
|
||||
#if HEAP_VERIFY && GC_VISIT_V2
|
||||
void arr_visit(Value* x);
|
||||
#define VISIT_SHAPE(X) ({ if (PRNK(X)>1) mm_visitP(shObjP(X)); })
|
||||
#else
|
||||
#define arr_visit noop_visit
|
||||
#define VISIT_SHAPE(X)
|
||||
#endif
|
||||
|
||||
#define CMP(W,X) ({ AUTO wt = (W); AUTO xt = (X); (wt>xt?1:0)-(wt<xt?1:0); })
|
||||
NOINLINE i32 compareF(B w, B x);
|
||||
|
||||
@ -86,7 +86,7 @@ static void bitarr_init(void) {
|
||||
TIi(t_bitarr,slice) = bitarr_slice;
|
||||
TIi(t_bitarr,freeO) = tyarr_freeO;
|
||||
TIi(t_bitarr,freeF) = tyarr_freeF;
|
||||
TIi(t_bitarr,visit) = noop_visit;
|
||||
TIi(t_bitarr,visit) = arr_visit;
|
||||
TIi(t_bitarr,print) = farr_print;
|
||||
TIi(t_bitarr,isArr) = true;
|
||||
TIi(t_bitarr,arrD1) = true;
|
||||
|
||||
@ -21,7 +21,7 @@ static void TP(,arr_init)() {
|
||||
TIi(T_ARR,slice) = TP(,arr_slice); TIi(T_SLICE,slice) = TP(,slice_slice);
|
||||
TIi(T_ARR,freeO) = tyarr_freeO; TIi(T_SLICE,freeO) = slice_freeO; // typed array slice frees calling the generic function is relied on by mmap & •bit._cast
|
||||
TIi(T_ARR,freeF) = tyarr_freeF; TIi(T_SLICE,freeF) = slice_freeF;
|
||||
TIi(T_ARR,visit) = noop_visit; TIi(T_SLICE,visit) = slice_visit;
|
||||
TIi(T_ARR,visit) = arr_visit; TIi(T_SLICE,visit) = slice_visit;
|
||||
TIi(T_ARR,print) = farr_print; TIi(T_SLICE,print) = farr_print;
|
||||
TIi(T_ARR,isArr) = true; TIi(T_SLICE,isArr) = true;
|
||||
TIi(T_ARR,arrD1) = true; TIi(T_SLICE,arrD1) = true;
|
||||
|
||||
12
src/opt/gc.c
12
src/opt/gc.c
@ -82,6 +82,7 @@ static void gc_tryFree(Value* v) {
|
||||
GC_DEC_REFC, // decrement refcount
|
||||
GC_INC_REFC, // increment refcount
|
||||
GC_MARK, // if unmarked, mark & visit
|
||||
GC_LISTBAD, //
|
||||
};
|
||||
|
||||
void gc_onVisit(Value* x) {
|
||||
@ -100,6 +101,16 @@ static void gc_tryFree(Value* v) {
|
||||
}
|
||||
}
|
||||
|
||||
static void gcv2_visit(Value* x) { TIv(x,visit)(x); }
|
||||
|
||||
#if HEAP_VERIFY
|
||||
void gcv2_runHeapverify(i32 mode) {
|
||||
visit_mode = mode==0? GC_DEC_REFC : GC_INC_REFC;
|
||||
mm_forHeap(gcv2_visit);
|
||||
gc_visitRoots();
|
||||
}
|
||||
#endif
|
||||
|
||||
static Value** gcv2_bufS;
|
||||
static Value** gcv2_bufC;
|
||||
static Value** gcv2_bufE;
|
||||
@ -124,7 +135,6 @@ static void gc_tryFree(Value* v) {
|
||||
if (gcv2_bufC == gcv2_bufE) return gcv2_storeRemainingR(x);
|
||||
gcv2_storeRemainingEnd(x);
|
||||
}
|
||||
static void gcv2_visit(Value* x) { TIv(x,visit)(x); }
|
||||
|
||||
static void gc_run() {
|
||||
visit_mode = GC_DEC_REFC;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user