diff --git a/src/h.h b/src/h.h index 20a490d9..84ad1320 100644 --- a/src/h.h +++ b/src/h.h @@ -115,10 +115,15 @@ typedef struct Arr { } Arr; // memory manager +typedef void (*V2v)(Value*); + void* mm_allocN(usz sz, u8 type); void mm_free(Value* x); void mm_visit(B x); -u64 mm_round(usz x); +u64 mm_round(usz x); +u64 mm_size(Value* x); +u64 mm_totalAllocated(); +void mm_forHeap(V2v f); B mm_alloc(usz sz, u8 type, u64 tag) { assert(tag>1LL<<16 || tag==0); // make sure it's `ftag`ged :| return b((u64)mm_allocN(sz,type) | tag); diff --git a/src/main.c b/src/main.c index e9a3cf97..b5bdb11e 100644 --- a/src/main.c +++ b/src/main.c @@ -44,6 +44,14 @@ u64 nsTime() { return t.tv_sec*1000000000ull + t.tv_nsec; } +u64 temp_heapUsage; +void heapUsedFn(Value* p) { temp_heapUsage+= mm_size(p); } +u64 heapUsed() { + temp_heapUsage = 0; + mm_forHeap(heapUsedFn); + return temp_heapUsage; +} + __ssize_t getline (char **__restrict __lineptr, size_t *restrict n, FILE *restrict stream); int main() { @@ -164,8 +172,12 @@ int main() { dec(rtRes); dec(comp); + + // printf("done\n");fflush(stdout); while(1); #ifdef ALLOC_STAT - printf("total bytes allocated: %lu\n", talloc); + printf("total ever allocated: %lu\n", talloc); + printf("final heap size: %ld\n", mm_totalAllocated()); + printf("leaked heap size: %ld\n", 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"); for(i64 i = 0; i < actrc; i++) { @@ -173,7 +185,7 @@ int main() { bool any = false; for (i64 j = 0; j < Type_MAX; j++) if (c[j]) any=true; if (any) { - printf("%ld", i); + printf("%ld", i*4); for (i64 k = 0; k < Type_MAX; k++) printf("‿%u", c[k]); printf("\n"); } diff --git a/src/mm_2buddy.c b/src/mm_2buddy.c index a8f27f49..5d5849ac 100644 --- a/src/mm_2buddy.c +++ b/src/mm_2buddy.c @@ -11,47 +11,55 @@ struct EmptyValue { // needs set: mmInfo; type=t_empty; next; everything else ca EmptyValue* next; }; -#define BSZ(x) (1ull<<(x)) -#define BSZI(x) (64-__builtin_clzl((x)-1ull)) -#define MMI(x) x -#define buckets b1_buckets -#define mm_free b1_free -#define mm_makeEmpty b1_makeEmpty -#define mm_allocL b1_allocL +#define BSZ(X) (1ull<<(X)) +#define BSZI(X) (64-__builtin_clzl((X)-1ull)) +#define MMI(X) X +#define BN(X) b1_##X +#define buckets b1_buckets #include "mm_buddyTemplate.c" #undef buckets -#undef mm_free -#undef mm_makeEmpty -#undef mm_allocL +#undef BN +#undef BSZ +#undef BSZI -#define BSZ(x) ((1ull<<(x))*3) -#define BSZI(x) (64-__builtin_clzl((x/3)-1ull)) -#define MMI(x) ((x)|64) -#define buckets b3_buckets -#define mm_free b3_free -#define mm_makeEmpty b3_makeEmpty -#define mm_allocL b3_allocL +#define BSZ(X) (3ull<<(X)) +#define BSZI(X) (64-__builtin_clzl((X)/3-1ull)) +#define MMI(X) ((X)|64) +#define BN(X) b3_##X +#define buckets b3_buckets #include "mm_buddyTemplate.c" #undef buckets -#undef mm_free -#undef mm_makeEmpty -#undef mm_allocL +#undef BN +#undef BSZ +#undef BSZI void* mm_allocN(usz sz, u8 type) { assert(sz>12); onAlloc(sz, type); u8 b1 = 64-__builtin_clzl(sz-1ull); - if (sz <= (1ull<<(b1-2)) * 3) return b3_allocL(b1-2, type); + if (sz <= (3ull<<(b1-2))) return b3_allocL(b1-2, type); return b1_allocL(b1, type); } void mm_free(Value* x) { if (x->mmInfo&64) b3_free(x); else b1_free(x); } +void mm_forHeap(V2v f) { + b1_forHeap(f); + b3_forHeap(f); +} -u64 mm_round(usz sz) { - u8 b1 = 64-__builtin_clzl(sz-1ull); - u64 s3 = (1ull<<(b1-2)) * 3; - if (sz<=s3) return s3; +u64 mm_round(usz x) { + u8 b1 = 64-__builtin_clzl(x-1ull); + u64 s3 = 3ull<<(b1-2); + if (x<=s3) return s3; return 1ull<mmInfo; + if (m&64) return 3ull<<(x->mmInfo&63); + else return 1ull<<(x->mmInfo&63); +} +u64 mm_totalAllocated() { + return b1_totalAllocated() + b3_totalAllocated(); +} diff --git a/src/mm_buddy.c b/src/mm_buddy.c index d0db403c..b77e5447 100644 --- a/src/mm_buddy.c +++ b/src/mm_buddy.c @@ -10,23 +10,29 @@ struct EmptyValue { // needs set: mmInfo; type=t_empty; next; everything else ca struct Value; EmptyValue* next; }; -#define BSZI2(x) (64-__builtin_clzl((x)-1ull)) -#define BSZ(x) (1ull<<(x)) -#define BSZI BSZI2 -#define MMI(x) x -u64 mm_round(usz sz) { - return BSZ(BSZI(sz)); -} +#define BSZ(x) (1ull<<(x)) +#define BSZI(x) (64-__builtin_clzl((x)-1ull)) +#define MMI(x) x +#define BN(x) mm_##x + +#include "mm_buddyTemplate.c" void mm_visit(B x) { } - -#include "mm_buddyTemplate.c" - void* mm_allocN(usz sz, u8 type) { assert(sz>8); onAlloc(sz, type); - return mm_allocL(BSZI2(sz), type); + return mm_allocL(BSZI(sz), type); } + +u64 mm_round(usz sz) { + return BSZ(BSZI(sz)); +} +u64 mm_size(Value* x) { + return BSZ(x->mmInfo&63); +} + +#undef BSZ +#undef BSZI \ No newline at end of file diff --git a/src/mm_buddyTemplate.c b/src/mm_buddyTemplate.c index 9515d675..943959a9 100644 --- a/src/mm_buddyTemplate.c +++ b/src/mm_buddyTemplate.c @@ -1,6 +1,18 @@ EmptyValue* buckets[64]; -static EmptyValue* mm_makeEmpty(u8 bucket) { // result->next is garbage +#define AllocInfo BN(AllocInfo) +#define al BN(al) +#define alCap BN(alCap) +#define alSize BN(alSize) +typedef struct AllocInfo { + Value* p; + u64 sz; +} AllocInfo; +AllocInfo* al; +u64 alCap; +u64 alSize; + +static EmptyValue* BN(makeEmpty)(u8 bucket) { // result->next is garbage u8 cb = bucket; EmptyValue* c; while (true) { @@ -14,6 +26,11 @@ static EmptyValue* mm_makeEmpty(u8 bucket) { // result->next is garbage if (cb >= 20) { u64 sz = BSZ(cb); c = mmap(NULL, sz, PROT_READ|PROT_WRITE, MAP_NORESERVE|MAP_PRIVATE|MAP_ANON, -1, 0); + if (alSize+1>=alCap) { + alCap = alCap? alCap*2 : 1024; + al = realloc(al, sizeof(AllocInfo)*alCap); + } + al[BN(alSize)++] = (AllocInfo){.p = (Value*)c, .sz = sz}; if (c==MAP_FAILED) { printf("failed to allocate memory\n"); exit(1); @@ -36,7 +53,7 @@ static EmptyValue* mm_makeEmpty(u8 bucket) { // result->next is garbage return c; } -void mm_free(Value* x) { +void BN(free)(Value* x) { onFree(x); EmptyValue* c = (EmptyValue*) x; c->type = t_empty; @@ -45,16 +62,34 @@ void mm_free(Value* x) { buckets[b] = c; } -void* mm_allocL(u8 bucket, u8 type) { +void* BN(allocL)(u8 bucket, u8 type) { EmptyValue* x = buckets[bucket]; - if (x==NULL) x = mm_makeEmpty(bucket); + if (x==NULL) x = BN(makeEmpty)(bucket); else buckets[bucket] = x->next; x->flags = x->extra = x->type = 0; x->refc = 1; x->type = type; return x; } +void BN(forHeap)(V2v f) { + for (u64 i = 0; i < alSize; i++) { + AllocInfo ci = al[i]; + Value* s = ci.p; + Value* e = ci.sz + (void*)ci.p; + while (s!=e) { + if (s->type!=t_empty) f(s); + s = BSZ(s->mmInfo&63) + (void*)s; + } + } +} +u64 BN(totalAllocated)() { + u64 res = 0; + for (u64 i = 0; i < alSize; i++) res+= al[i].sz; + return res; +} -#undef BSZ -#undef BSZI #undef MMI +#undef AllocInfo +#undef al +#undef alSize +#undef alCap \ No newline at end of file diff --git a/src/mm_malloc.c b/src/mm_malloc.c index 7964bffb..7576e75f 100644 --- a/src/mm_malloc.c +++ b/src/mm_malloc.c @@ -15,10 +15,8 @@ void* mm_allocN(usz sz, u8 type) { return x; } -u64 mm_round(usz sz) { - return sz; -} - -void mm_visit(B x) { - -} +void mm_visit(B x) { } +u64 mm_round(usz x) { return x; } +u64 mm_size(Value* x) { return -1; } +u64 mm_totalAllocated() { return -1; } +void mm_forHeap(V2v f) { } \ No newline at end of file diff --git a/src/vm.c b/src/vm.c index e1e03fe5..15addc33 100644 --- a/src/vm.c +++ b/src/vm.c @@ -259,8 +259,7 @@ void allocStack(u64 am) { if (am>left) { u64 n = gStackEnd-gStackStart + am + 500; u64 d = gStackStart-gStack; - if (gStack==NULL) gStackStart = malloc(n*sizeof(B)); - else gStackStart = realloc(gStackStart, n*sizeof(B)); + gStackStart = realloc(gStackStart, n*sizeof(B)); gStack = gStackStart+d; gStackEnd = gStackStart+n; }