From c1b66c5982abac8aa50f5ee5141bf9111651ea84 Mon Sep 17 00:00:00 2001 From: dzaima Date: Sat, 23 Jul 2022 23:51:01 +0300 Subject: [PATCH] don't bother iterating through generic array items in cpy.*Arr on free --- src/core/fillarr.c | 2 ++ src/core/harr.c | 30 ++++++++++++++++++++++-------- src/h.h | 5 +++++ src/load.c | 11 ++++++++++- src/utils/mut.c | 37 +++++++++++++++++++------------------ 5 files changed, 58 insertions(+), 27 deletions(-) diff --git a/src/core/fillarr.c b/src/core/fillarr.c index ec5dd737..5a7befab 100644 --- a/src/core/fillarr.c +++ b/src/core/fillarr.c @@ -58,6 +58,7 @@ static void fillarr_visit(Value* x) { assert(x->type == t_fillarr); } static bool fillarr_canStore(B x) { return true; } +static void fillarr_freeT(Value* x) { FillArr* s=(void*)x; dec(s->fill); decSh(x); mm_free(x); } static void fillslice_visit(Value* x) { FillSlice* s=(void*)x; mm_visitP(s->p); mm_visit(s->fill); } static void fillslice_freeO(Value* x) { FillSlice* s=(void*)x; ptr_dec(s->p); dec(s->fill); decSh(x); } @@ -69,6 +70,7 @@ void fillarr_init() { TIi(t_fillarr,slice) = fillarr_slice; TIi(t_fillslice,slice) = fillslice_slice; TIi(t_fillarr,freeO) = fillarr_freeO; TIi(t_fillslice,freeO) = fillslice_freeO; TIi(t_fillarr,freeF) = fillarr_freeF; TIi(t_fillslice,freeF) = fillslice_freeF; + TIi(t_fillarr,freeT) = fillarr_freeT; TIi(t_fillarr,visit) = fillarr_visit; TIi(t_fillslice,visit) = fillslice_visit; TIi(t_fillarr,print) = farr_print; TIi(t_fillslice,print) = farr_print; TIi(t_fillarr,isArr) = true; TIi(t_fillslice,isArr) = true; diff --git a/src/core/harr.c b/src/core/harr.c index e16537d5..10809c61 100644 --- a/src/core/harr.c +++ b/src/core/harr.c @@ -130,15 +130,29 @@ static void harrP_print(FILE* f, B x) { fprintf(f, "⟩)"); } +#if DEBUG + static void harr_freeT(Value* x) { + B* p = ((HArr*)x)->a; + usz ia = ((Arr*)x)->ia; + for (usz i = 0; i < ia; i++) assert(!isVal(p[i])); + tyarr_freeF(x); + } +#endif + void harr_init() { - TIi(t_harr,get) = harr_get; TIi(t_hslice,get) = hslice_get; TIi(t_harrPartial,get) = harrP_get; - TIi(t_harr,getU) = harr_getU; TIi(t_hslice,getU) = hslice_getU; TIi(t_harrPartial,getU) = harrP_get; - TIi(t_harr,slice) = harr_slice; TIi(t_hslice,slice) = hslice_slice; - TIi(t_harr,freeO) = harr_freeO; TIi(t_hslice,freeO) = slice_freeO; TIi(t_harrPartial,freeO) = harrP_freeO; - TIi(t_harr,freeF) = harr_freeF; TIi(t_hslice,freeF) = slice_freeF; TIi(t_harrPartial,freeF) = harrP_freeF; - TIi(t_harr,visit) = harr_visit; TIi(t_hslice,visit) = slice_visit; TIi(t_harrPartial,visit) = harrP_visit; - TIi(t_harr,print) = farr_print; TIi(t_hslice,print) = farr_print; TIi(t_harrPartial,print) = harrP_print; - TIi(t_harr,isArr) = true; TIi(t_hslice,isArr) = true; + TIi(t_harr,get) = harr_get; TIi(t_hslice,get) = hslice_get; TIi(t_harrPartial,get) = harrP_get; + TIi(t_harr,getU) = harr_getU; TIi(t_hslice,getU) = hslice_getU; TIi(t_harrPartial,getU) = harrP_get; + TIi(t_harr,slice) = harr_slice; TIi(t_hslice,slice) = hslice_slice; + TIi(t_harr,freeO) = harr_freeO; TIi(t_hslice,freeO) = slice_freeO; TIi(t_harrPartial,freeO) = harrP_freeO; + TIi(t_harr,freeF) = harr_freeF; TIi(t_hslice,freeF) = slice_freeF; TIi(t_harrPartial,freeF) = harrP_freeF; + #if DEBUG + TIi(t_harr,freeT) = harr_freeT; + #else + TIi(t_harr,freeT) = tyarr_freeF; + #endif + TIi(t_harr,visit) = harr_visit; TIi(t_hslice,visit) = slice_visit; TIi(t_harrPartial,visit) = harrP_visit; + TIi(t_harr,print) = farr_print; TIi(t_hslice,print) = farr_print; TIi(t_harrPartial,print) = harrP_print; + TIi(t_harr,isArr) = true; TIi(t_hslice,isArr) = true; TIi(t_harr,canStore) = harr_canStore; bi_emptyHVec = m_harrUv(0).b; gc_add(bi_emptyHVec); } diff --git a/src/h.h b/src/h.h index beeb7d11..a204a87f 100644 --- a/src/h.h +++ b/src/h.h @@ -510,6 +510,7 @@ typedef B (*D2C2)(Md2D*, B, B); F(FB2v, print) /* doesn't consume */ \ F(V2v, visit) /* call mm_visit for all referents */ \ F(V2v, freeO) /* like freeF, but doesn't call mm_free for GC to be able to clear cycles */ \ + F(V2v, freeT) /* freeF, but assumes this is an array which consists of non-heap-allocated elements */ \ F(B2B, decompose) /* consumes; must return a HArr */ \ F(bool, isArr) /* whether this type would have an ARR_TAG tag, in cases where the tag is unknown */ \ F(bool, arrD1) /* is always an array with depth 1 */ \ @@ -573,6 +574,10 @@ static inline void decG(B x) { Value* vx = v(x); if(!--vx->refc) value_free(vx); } +FORCE_INLINE void ptr_decT(Arr* x) { // assumes argument is an array and consists of non-heap-allocated elements + if (x->refc==1) TIv(x,freeT)((Value*) x); + else x->refc--; +} static inline B incG(B x) { // inc for guaranteed heap-allocated objects assert(isVal(x)); v(VALIDATE(x))->refc++; diff --git a/src/load.c b/src/load.c index 1bea5bee..2b1e5b20 100644 --- a/src/load.c +++ b/src/load.c @@ -5,7 +5,7 @@ #include "ns.h" #include "builtins.h" -#define FOR_INIT(F) F(base) F(harr) F(mutF) F(fillarr) F(tyarr) F(hash) F(sfns) F(fns) F(arith) F(md1) F(md2) F(derv) F(comp) F(rtWrap) F(ns) F(nfn) F(sysfn) F(inverse) F(load) F(sysfnPost) F(dervPost) F(ffi) F(mmap) +#define FOR_INIT(F) F(base) F(harr) F(mutF) F(fillarr) F(tyarr) F(hash) F(sfns) F(fns) F(arith) F(md1) F(md2) F(derv) F(comp) F(rtWrap) F(ns) F(nfn) F(sysfn) F(inverse) F(load) F(sysfnPost) F(dervPost) F(ffi) F(mmap) F(typesFinished) #define F(X) void X##_init(void); FOR_INIT(F) #undef F @@ -595,6 +595,9 @@ void customObj_visit(Value* v) { ((CustomObj*)v)->visit(v); } void customObj_freeO(Value* v) { ((CustomObj*)v)->freeO(v); } void customObj_freeF(Value* v) { ((CustomObj*)v)->freeO(v); mm_free(v); } +void def_fallbackTriv(Value* v) { // used while vtables aren't yet fully loaded; should become completely unused after typesFinished_init + TIv(v,freeF)(v); +} static NOINLINE B m_bfn(BB2B c1, BBB2B c2, u8 id) { BFn* f = mm_alloc(sizeof(BFn), t_funBI); @@ -638,6 +641,7 @@ static NOINLINE B m_bm2(D2C1 c1, D2C2 c2, u8 id) { void base_init() { // very first init function for (u64 i = 0; i < t_COUNT; i++) { TIi(i,freeO) = def_freeO; + TIi(i,freeT) = def_fallbackTriv; TIi(i,freeF) = def_freeF; TIi(i,visit) = def_visit; TIi(i,get) = def_get; @@ -708,6 +712,11 @@ void base_init() { // very first init function #undef FM #undef FD } +void typesFinished_init() { + for (u64 i = 0; i < t_COUNT; i++) { + if (TIi(i,freeT) == def_fallbackTriv) TIi(i,freeT) = TIi(i,freeF); + } +} bool cbqn_initialized; void cbqn_init() { diff --git a/src/utils/mut.c b/src/utils/mut.c index ff9a099a..5ea3791b 100644 --- a/src/utils/mut.c +++ b/src/utils/mut.c @@ -213,34 +213,35 @@ DEF_G(void, copy, B, (void* a, usz ms, B x, usz xs, usz l), ms, x, x } #define COPY_FN(X,R) avx2_copy_##X##_##R - #define MAKE_CPY(MAKE, GET, WR, XRP, H2T, T, ...) \ - static copy_fn copy##T##Fns[10]; \ + #define MAKE_CPY(TY, MAKE, GET, WR, XRP, H2T, T, ...) \ + static copy_fn copy##T##Fns[10]; \ static void cpy##T##Arr_B(u8* xp, u8* rp, u64 ia, u8* xRaw) { \ - Arr* xa = (Arr*)xRaw; B* bxp = arrV_bptr(xa); \ - if (bxp!=NULL && sizeof(B)==sizeof(f64)) { \ - H2T; \ - } else { AS2B fn = TIv(xa,GET); \ - for (usz i=0; iia; \ MAKE; arr_shCopy(r, x); \ if (ia>0) { \ copy##T##Fns[TI(x,elType)](tyany_ptr(x), (u8*)(XRP), ia, (u8*)a(x)); \ } \ - decG(x); \ + if (TY) ptr_decT(a(x)); \ + else decG(x); \ return (T##Arr*)r; \ } #define BIT_PUT(V) bitp_set((u64*)rp, i, o2bu(V)) #define H2T_COPY(T) copy##T##Fns[el_MAX]((u8*)bxp, rp, ia, xRaw) - #define MAKE_TYCPY(T, E, F, ...) MAKE_CPY(T##Atom* rp; Arr* r = m_##E##arrp(&rp, ia), getU, ((T##Atom*)rp)[i] = F, rp, H2T_COPY(T), T, __VA_ARGS__) + #define MAKE_TYCPY(T, E, F, ...) MAKE_CPY(1, T##Atom* rp; Arr* r = m_##E##arrp(&rp, ia), getU, ((T##Atom*)rp)[i] = F, rp, H2T_COPY(T), T, __VA_ARGS__) #define MAKE_CCPY(T,E) MAKE_TYCPY(T, E, o2cu, {badCopy, badCopy, badCopy, badCopy, badCopy, COPY_FN(c8,E),COPY_FN(c16,E),COPY_FN(c32,E),cpy##T##Arr_B,COPY_FN(B,E)}) #define MAKE_ICPY(T,E) MAKE_TYCPY(T, E, o2fu, {COPY_FN(1,E),COPY_FN(i8,E),COPY_FN(i16,E),COPY_FN(i32,E),COPY_FN(f64,E),badCopy, badCopy, badCopy, cpy##T##Arr_B,COPY_FN(f64,E)}) - MAKE_CPY(HArr_p p = m_harrUp(ia); Arr* r = (Arr*)p.c, get, ((B*)rp)[i] =, p.a, for (usz i=0; i