From 1af91554252181f5f36b20ddedfc1f0a5e977682 Mon Sep 17 00:00:00 2001 From: dzaima Date: Thu, 23 Feb 2023 23:53:02 +0200 Subject: [PATCH] =?UTF-8?q?optional=20path=20arg=20for=20=E2=80=A2internal?= =?UTF-8?q?.HeapDump;=20STORE=5FJIT=5FMAP?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 + docs/system.md | 2 +- src/builtins/internal.c | 11 ++++++++-- src/jit/nvm_x86_64.c | 48 +++++++++++++++++++++++++++++++++++++---- src/load.c | 2 +- src/utils/file.c | 6 +++--- src/utils/file.h | 2 +- src/vm.c | 17 +++++++-------- 8 files changed, 68 insertions(+), 21 deletions(-) diff --git a/.gitignore b/.gitignore index 9e2006b4..279075cb 100644 --- a/.gitignore +++ b/.gitignore @@ -23,6 +23,7 @@ libcbqn.dylib CBQNHeapDump .cbqn_repl_history cbqn_repl.txt +cbqn-jit.bqn # test temporary files /test/ffi/ffiTest.o diff --git a/docs/system.md b/docs/system.md index 96357427..1a9a1a2a 100644 --- a/docs/system.md +++ b/docs/system.md @@ -105,7 +105,7 @@ Namespace of various internal functions. May change at any time. | `•internal.Refc` | Reference count of the argument, if it's heap-allocated | | `•internal.IsPure` | Whether the vm considers the argument pure (i.e. it can execute it safely for computing fills) | | `•internal.Info` | General internal info about the object; a left argument of `1` gives more details | -| `•internal.HeapDump` | Create a heap dump file | +| `•internal.HeapDump` | Create a heap dump file; saves to `•wdpath`-relative path `𝕩` or `CBQNHeapDump` if `𝕩` isn't an array | | `•internal.Squeeze` | Try to convert the argument to its most compact representation | | `•internal.DeepSqueeze` | Try to convert the argument and all its subarrays to its most compact representation; won't squeeze namespace fields | | `•internal.ListVariations` | List the possible type variations of the argument array | diff --git a/src/builtins/internal.c b/src/builtins/internal.c index e339f0ad..9f3ccfd2 100644 --- a/src/builtins/internal.c +++ b/src/builtins/internal.c @@ -2,6 +2,7 @@ #include "../utils/file.h" #include "../builtins.h" #include "../ns.h" +#include "../utils/cstr.h" B itype_c1(B t, B x) { B r; @@ -314,8 +315,14 @@ B internalTemp_c2(B t, B w, B x) { } B heapDump_c1(B t, B x) { - cbqn_heapDump(); - return m_c32(0); + if (!isArr(x)) { + cbqn_heapDump(NULL); + } else { + char* s = toCStr(x); + cbqn_heapDump(s); + freeCStr(s); + } + return x; } B unshare_c1(B t, B x) { diff --git a/src/jit/nvm_x86_64.c b/src/jit/nvm_x86_64.c index bd9540e6..390e856f 100644 --- a/src/jit/nvm_x86_64.c +++ b/src/jit/nvm_x86_64.c @@ -267,6 +267,9 @@ INS B i_RETD(Scope* sc) { FILE* perf_map; u32 perfid = 0; #endif +#if STORE_JIT_MAP +FILE* jit_map; +#endif static void* nvm_alloc(u64 sz) { // void* r = mmap(NULL, sz, PROT_EXEC|PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_32BIT, -1, 0); @@ -530,9 +533,7 @@ static void onJIT(Body* body, u8* binEx, u64 sz) { // printf("JIT %d:\n", perfid); // vm_printPos(body->comp, bcPos, -1); fprintf(perf_map, N64x" "N64x" JIT %d: BC@%u\n", (u64)binEx, sz, perfid++, bcPos); - #if PERF_MAP_FLUSH - fflush(perf_map); - #endif + fflush(perf_map); #endif #if WRITE_ASM write_asm(binEx, sz); @@ -540,6 +541,31 @@ static void onJIT(Body* body, u8* binEx, u64 sz) { #endif } +#if STORE_JIT_MAP +void print_BC(FILE* f, u32* p, i32 w); +static NOINLINE void print_jit_line(Body* body, usz* bc, usz bcpos) { + fprintf(jit_map, " "); + if (bc!=NULL) { + print_BC(jit_map, bc, 10); + fprintf(jit_map, " "); + } + fprintf(jit_map, "# %+d\n", (int)ASM_SIZE); + Comp* comp = body->bl->comp; + if (!q_N(comp->src) && !q_N(comp->indices)) { + fprintf(jit_map, " "); + B inds = IGetU(comp->indices, 0); usz cs = o2s(IGetU(inds,bcpos)); + B inde = IGetU(comp->indices, 1); usz ce = o2s(IGetU(inde,bcpos))+1; + B msg = toC32Any(vm_fmtPoint(comp->src, emptyCVec(), comp->path, cs, ce)); + u32* p = c32any_ptr(msg); + usz n = IA(msg); + for (ux i = 0; i < n; i++) { + if (p[i]=='\n') fprintf(jit_map, "\n "); + else fprintCodepoint(jit_map, p[i]); + } + fprintf(jit_map, "\n"); + } +} +#endif typedef B JITFn(B* cStack, Scope* sc); static inline i32 maxi32(i32 a, i32 b) { return a>b?a:b; } Nvm_res m_nvm(Body* body) { @@ -578,6 +604,12 @@ Nvm_res m_nvm(Body* body) { #define CCALL(F) CALLi((u64)(F)) u32* origBC = body->bc; + u32 bodyOff = origBC - (u32*)body->bl->bc; + #if STORE_JIT_MAP + if (!jit_map) jit_map = fopen("cbqn-jit.bqn", "wa"); + fprintf(jit_map, "{\n"); + print_jit_line(body, NULL, body->bl->map[bodyOff]); + #endif OptRes optRes = opt(origBC); i32 depth = 0; u32* bc = optRes.bc; @@ -588,7 +620,11 @@ Nvm_res m_nvm(Body* body) { u32* s = bc; u32* n = nextBC(bc); u32 bcpos = optRes.offset[s-optRes.bc]; - u32 bodyOff = origBC - (u32*)body->bl->bc; + #if STORE_JIT_MAP + print_jit_line(body, s, body->bl->map[bcpos+bodyOff]); + #endif + + u32* off = origBC + bcpos; bool ret = false; #define L64 ({ u64 r = bc[0] | ((u64)bc[1])<<32; bc+= 2; r; }) @@ -727,6 +763,10 @@ Nvm_res m_nvm(Body* body) { asm_write(binEx, sz); asm_free(); onJIT(body, binEx, sz); + #if STORE_JIT_MAP + fprintf(jit_map, " # start address: "N64d"\n}\n", ptr2u64(binEx)); + fflush(jit_map); + #endif return (Nvm_res){.p = binEx, .refs = optRes.refs}; } B evalJIT(Body* b, Scope* sc, u8* ptr) { // doesn't consume diff --git a/src/load.c b/src/load.c index 1b9a4256..108bf9e6 100644 --- a/src/load.c +++ b/src/load.c @@ -562,7 +562,7 @@ B bqn_execFile(B path, B args) { // consumes both void before_exit(void); void bqn_exit(i32 code) { #ifdef DUMP_ON_EXIT - cbqn_heapDump(); + cbqn_heapDump(NULL); #endif rtWrap_print(); CTR_FOR(CTR_PRINT) diff --git a/src/utils/file.c b/src/utils/file.c index dc541748..2602f34b 100644 --- a/src/utils/file.c +++ b/src/utils/file.c @@ -431,8 +431,8 @@ static u8 types_val[] = { #undef F }; -void cbqn_heapDump() { - char* name = "CBQNHeapDump"; +void cbqn_heapDump(char* name0) { + char* name = name0==NULL? "CBQNHeapDump" : name0; FILE* f = fopen(name, "w"); if (f==NULL) { fprintf(stderr, "Failed to dump heap - could not open file for writing\n"); @@ -470,6 +470,6 @@ void cbqn_heapDump() { mm_dumpHeap(f); mmX_dumpHeap(f); - fprintf(stderr, "Heap dumped to \"%s\"\n", name); + if (name0==NULL) fprintf(stderr, "Heap dumped to \"%s\"\n", name); fclose(f); } diff --git a/src/utils/file.h b/src/utils/file.h index 4ca24fd9..30fef0cb 100644 --- a/src/utils/file.h +++ b/src/utils/file.h @@ -29,4 +29,4 @@ void file_wBytes(FILE* file, B name, B x); // doesn't consume B path_list(B path); // consumes char path_type(B path); // consumes; errors only if path isn't a string B path_info(B path, i32 mode); // consumes; mode: 0:created 1:accessed 2:modified 3:size -void cbqn_heapDump(void); +void cbqn_heapDump(char* name); diff --git a/src/vm.c b/src/vm.c index 93cc66d5..88eb7f00 100644 --- a/src/vm.c +++ b/src/vm.c @@ -25,9 +25,9 @@ char* bc_repr(u32 p) { #undef F } } -void print_BC(u32* p, i32 w) { +void print_BC(FILE* f, u32* p, i32 w) { char* str = bc_repr(*p); - printf("%s", str); + fprintf(f, "%s", str); u32* n = nextBC(p); p++; i32 len = strlen(str); @@ -39,16 +39,16 @@ void print_BC(u32* p, i32 w) { buf[clen++] = (c&15)>9? 'A'+(c&15)-10 : '0'+(c&15); c>>= 4; } while(c); - putchar(' '); - for (i32 i = 0; i < clen; i++) putchar(buf[clen-i-1]); + fputc(' ', f); + for (i32 i = 0; i < clen; i++) fputc(buf[clen-i-1], f); len+= clen+1; } len = w-len; - while(len-->0) putchar(' '); + while(len-->0) fputc(' ', f); } -void print_BCStream(u32* p) { +void print_BCStream(FILE* f, u32* p) { while(true) { - print_BC(p, 10); putchar(10); + print_BC(f, p, 10); fputc(10, f); if (*p == RETD || *p == RETN) return; p = nextBC(p); } @@ -1357,8 +1357,7 @@ NOINLINE void vm_printPos(Comp* comp, i32 bcPos, i64 pos) { #endif if (CATCH) { freeThrown(); goto native_print; } - B s = emptyCVec(); - B msg = vm_fmtPoint(src, s, comp->path, cs, ce); + B msg = vm_fmtPoint(src, emptyCVec(), comp->path, cs, ce); fprintsB(stderr, msg); dec(msg); fputc('\n', stderr);