diff --git a/src/boot/boot.janet b/src/boot/boot.janet index 21489763..84e4e756 100644 --- a/src/boot/boot.janet +++ b/src/boot/boot.janet @@ -2769,13 +2769,9 @@ # define variables available at breakpoint (def frame ((debug/stack fiber) 0)) - (def symbolslots ((disasm (frame :function)) :symbolslots)) (def pc (frame :pc)) - - (loop [[birth death slot sym] :in symbolslots] - (when (and (<= birth pc) - (< pc death)) - (put nextenv (symbol sym) @{:value (get-in frame [:slots slot])}))) + (eachp [local value] (get frame :locals) + (put nextenv local @{:value value})) (merge-into nextenv debugger-env) (defn debugger-chunks [buf p] diff --git a/src/core/asm.c b/src/core/asm.c index b182cbfc..a795466e 100644 --- a/src/core/asm.c +++ b/src/core/asm.c @@ -722,20 +722,20 @@ static JanetAssembleResult janet_asm1(JanetAssembler *parent, Janet source, int } /* Set symbolslots */ - def->symbolslots = NULL; - def->symbolslots_length = 0; + def->symbolmap = NULL; + def->symbolmap_length = 0; x = janet_get1(s, janet_ckeywordv("symbolslots")); if (janet_indexed_view(x, &arr, &count)) { - def->symbolslots_length = count; - def->symbolslots = janet_malloc(sizeof(JanetSymbolSlot) * (size_t) count); - if (NULL == def->symbolslots) { + def->symbolmap_length = count; + def->symbolmap = janet_malloc(sizeof(JanetSymbolMap) * (size_t)count); + if (NULL == def->symbolmap) { JANET_OUT_OF_MEMORY; } for (i = 0; i < count; i++) { const Janet *tup; Janet entry = arr[i]; - JanetSymbolSlot ss; + JanetSymbolMap ss; if (!janet_checktype(entry, JANET_TUPLE)) { janet_asm_error(&a, "expected tuple"); } @@ -756,8 +756,7 @@ static JanetAssembleResult janet_asm1(JanetAssembler *parent, Janet source, int ss.death_pc = janet_unwrap_integer(tup[1]); ss.slot_index = janet_unwrap_integer(tup[2]); ss.symbol = janet_unwrap_string(tup[3]); - - def->symbolslots[i] = ss; + def->symbolmap[i] = ss; } } @@ -923,11 +922,12 @@ static Janet janet_disasm_slotcount(JanetFuncDef *def) { } static Janet janet_disasm_symbolslots(JanetFuncDef *def) { - // *debug* was probably not true when compiling the function - if (def->symbolslots == NULL) { return janet_wrap_nil(); } - JanetArray *symbolslots = janet_array(def->symbolslots_length); - for (int32_t i = 0; i < def->symbolslots_length; i++) { - JanetSymbolSlot ss = def->symbolslots[i]; + if (def->symbolmap == NULL) { + return janet_wrap_nil(); + } + JanetArray *symbolslots = janet_array(def->symbolmap_length); + for (int32_t i = 0; i < def->symbolmap_length; i++) { + JanetSymbolMap ss = def->symbolmap[i]; Janet *t = janet_tuple_begin(4); t[0] = janet_wrap_integer(ss.birth_pc); t[1] = janet_wrap_integer(ss.death_pc); @@ -935,7 +935,7 @@ static Janet janet_disasm_symbolslots(JanetFuncDef *def) { t[3] = janet_cstringv((const char *) ss.symbol); symbolslots->data[i] = janet_wrap_tuple(janet_tuple_end(t)); } - symbolslots->count = def->symbolslots_length; + symbolslots->count = def->symbolmap_length; return janet_wrap_array(symbolslots); } diff --git a/src/core/bytecode.c b/src/core/bytecode.c index 54a80333..31faa5bf 100644 --- a/src/core/bytecode.c +++ b/src/core/bytecode.c @@ -218,7 +218,7 @@ JanetFuncDef *janet_funcdef_alloc(void) { def->closure_bitset = NULL; def->flags = 0; def->slotcount = 0; - def->symbolslots = NULL; + def->symbolmap = NULL; def->arity = 0; def->min_arity = 0; def->max_arity = INT32_MAX; @@ -230,7 +230,7 @@ JanetFuncDef *janet_funcdef_alloc(void) { def->constants_length = 0; def->bytecode_length = 0; def->environments_length = 0; - def->symbolslots_length = 0; + def->symbolmap_length = 0; return def; } diff --git a/src/core/compile.c b/src/core/compile.c index e41fa5bf..f0dc99f4 100644 --- a/src/core/compile.c +++ b/src/core/compile.c @@ -94,11 +94,12 @@ void janetc_freeslot(JanetCompiler *c, JanetSlot s) { void janetc_nameslot(JanetCompiler *c, const uint8_t *sym, JanetSlot s) { SymPair sp; sp.sym = sym; + sp.sym2 = sym; sp.slot = s; sp.keep = 0; sp.slot.flags |= JANET_SLOT_NAMED; - // -1 because c->buffer has already passed the `def`/`var` - sp.bytecode_pos = janet_v_count(c->buffer) - 1; + sp.birth_pc = janet_v_count(c->buffer); + sp.death_pc = UINT32_MAX; janet_v_push(c->scope->syms, sp); } @@ -161,42 +162,24 @@ void janetc_popscope(JanetCompiler *c) { if (oldscope->flags & JANET_SCOPE_CLOSURE) { newscope->flags |= JANET_SCOPE_CLOSURE; } - if (newscope->ra.max < oldscope->ra.max) + if (newscope->ra.max < oldscope->ra.max) { newscope->ra.max = oldscope->ra.max; + } - /* Keep upvalue slots */ + /* Keep upvalue slots and symbols for debugging. */ for (int32_t i = 0; i < janet_v_count(oldscope->syms); i++) { SymPair pair = oldscope->syms[i]; + /* The variable should not be lexically accessible */ + pair.sym = NULL; + if (pair.death_pc == UINT32_MAX) { + pair.death_pc = (uint32_t) janet_v_count(c->buffer); + } if (pair.keep) { - /* The variable should not be lexically accessible */ - pair.sym = NULL; - janet_v_push(newscope->syms, pair); + /* The variable should also not be included in the locals */ + pair.sym2 = NULL; janetc_regalloc_touch(&newscope->ra, pair.slot.index); } - } - } - - if (janet_truthy(janet_dyn("debug"))) { - bool top_level = (oldscope->flags & (JANET_SCOPE_FUNCTION | JANET_SCOPE_UNUSED)); - - /* push symbol slots */ - JanetSymbolSlot ss; - int32_t scope_end = top_level ? INT32_MAX : janet_v_count(c->buffer); - - janet_assert(janet_v_count(c->local_symbols) > 0, "c->local_symbols should not be empty"); - - // due to scopes being added "in reverse" (filo), we will reverse all symbols later. therefore we must first reverse the order of symbols inside each scope as well. - for (int32_t i = janet_v_count(oldscope->syms) - 1; i >= 0; i--) { - SymPair pair = oldscope->syms[i]; - - if (pair.sym != NULL) { - ss.birth_pc = pair.bytecode_pos; - ss.death_pc = scope_end; - ss.slot_index = pair.slot.index; - ss.symbol = pair.sym; - - janet_v_push(janet_v_last(c->local_symbols), ss); - } + janet_v_push(newscope->syms, pair); } } @@ -949,26 +932,27 @@ JanetFuncDef *janetc_pop_funcdef(JanetCompiler *c) { def->closure_bitset = chunks; } - /* Pop the scope */ - janetc_popscope(c); - - if (janet_truthy(janet_dyn("debug"))) { - JanetSymbolSlot *last_symbols = janet_v_last(c->local_symbols); - - def->symbolslots_length = janet_v_count(last_symbols); - - def->symbolslots = janet_malloc(sizeof(JanetSymbolSlot) * def->symbolslots_length); - if (NULL == def->bytecode) { - JANET_OUT_OF_MEMORY; - } - - // add in reverse, because scopes have been added filo - for (int i = 0; i < janet_v_count(last_symbols); i++) { - def->symbolslots[def->symbolslots_length - i - 1] = last_symbols[i]; + /* Capture symbol to local mapping */ + JanetSymbolMap *locals = NULL; + for (int32_t i = 0; i < janet_v_count(scope->syms); i++) { + SymPair pair = scope->syms[i]; + if (pair.sym2) { + if (pair.death_pc == UINT32_MAX) { + pair.death_pc = def->bytecode_length; + } + JanetSymbolMap jsm; + jsm.birth_pc = pair.birth_pc; + jsm.death_pc = pair.death_pc; + jsm.slot_index = pair.slot.index; + jsm.symbol = pair.sym2; + janet_v_push(locals, jsm); } } + def->symbolmap_length = janet_v_count(locals); + def->symbolmap = janet_v_flatten(locals); - janet_v_pop(c->local_symbols); + /* Pop the scope */ + janetc_popscope(c); return def; } @@ -980,7 +964,6 @@ static void janetc_init(JanetCompiler *c, JanetTable *env, const uint8_t *where, c->mapbuffer = NULL; c->recursion_guard = JANET_RECURSION_GUARD; c->env = env; - c->local_symbols = NULL; c->source = where; c->current_mapping.line = -1; c->current_mapping.column = -1; @@ -998,7 +981,6 @@ static void janetc_init(JanetCompiler *c, JanetTable *env, const uint8_t *where, static void janetc_deinit(JanetCompiler *c) { janet_v_free(c->buffer); janet_v_free(c->mapbuffer); - janet_v_free(c->local_symbols); c->env = NULL; } @@ -1012,7 +994,6 @@ JanetCompileResult janet_compile_lint(Janet source, janetc_init(&c, env, where, lints); /* Push a function scope */ - janet_v_push(c.local_symbols, NULL); janetc_scope(&rootscope, &c, JANET_SCOPE_FUNCTION | JANET_SCOPE_TOP, "root"); /* Set initial form options */ @@ -1031,9 +1012,6 @@ JanetCompileResult janet_compile_lint(Janet source, } else { c.result.error_mapping = c.current_mapping; janetc_popscope(&c); - if (janet_truthy(janet_dyn("debug"))) { - janet_v_pop(c.local_symbols); - } } janetc_deinit(&c); diff --git a/src/core/compile.h b/src/core/compile.h index db2d31a0..6e3b595c 100644 --- a/src/core/compile.h +++ b/src/core/compile.h @@ -111,14 +111,16 @@ struct JanetSlot { typedef struct SymPair { JanetSlot slot; const uint8_t *sym; + const uint8_t *sym2; int keep; - int32_t bytecode_pos; + uint32_t birth_pc; + uint32_t death_pc; } SymPair; /* A lexical scope during compilation */ struct JanetScope { - /* For debugging */ + /* For debugging the compiler */ const char *name; /* Scopes are doubly linked list */ @@ -161,8 +163,6 @@ struct JanetCompiler { /* Hold the environment */ JanetTable *env; - JanetSymbolSlot **local_symbols; - /* Name of source to attach to generated functions */ const uint8_t *source; diff --git a/src/core/debug.c b/src/core/debug.c index 71c85ff1..81965beb 100644 --- a/src/core/debug.c +++ b/src/core/debug.c @@ -329,6 +329,18 @@ static Janet doframe(JanetStackFrame *frame) { safe_memcpy(slots->data, stack, sizeof(Janet) * def->slotcount); slots->count = def->slotcount; janet_table_put(t, janet_ckeywordv("slots"), janet_wrap_array(slots)); + /* Add local bindings */ + if (def->symbolmap) { + JanetTable *local_bindings = janet_table(0); + for (int32_t i = def->symbolmap_length - 1; i >= 0; i--) { + JanetSymbolMap jsm = def->symbolmap[i]; + uint32_t pc = (uint32_t) (frame->pc - def->bytecode); + if (pc >= jsm.birth_pc && pc < jsm.death_pc) { + janet_table_put(local_bindings, janet_wrap_symbol(jsm.symbol), stack[jsm.slot_index]); + } + } + janet_table_put(t, janet_ckeywordv("locals"), janet_wrap_table(local_bindings)); + } } return janet_wrap_table(t); } diff --git a/src/core/gc.c b/src/core/gc.c index 9eb1fb8f..f0ecdd9a 100644 --- a/src/core/gc.c +++ b/src/core/gc.c @@ -209,6 +209,12 @@ static void janet_mark_funcdef(JanetFuncDef *def) { janet_mark_string(def->source); if (def->name) janet_mark_string(def->name); + if (def->symbolmap) { + for (int i = 0; i < def->symbolmap_length; i++) { + janet_mark_string(def->symbolmap[i].symbol); + } + } + } static void janet_mark_function(JanetFunction *func) { @@ -314,7 +320,7 @@ static void janet_deinit_block(JanetGCObject *mem) { janet_free(def->bytecode); janet_free(def->sourcemap); janet_free(def->closure_bitset); - janet_free(def->symbolslots); + janet_free(def->symbolmap); } break; } diff --git a/src/core/marsh.c b/src/core/marsh.c index 969f3ac3..a203dcaf 100644 --- a/src/core/marsh.c +++ b/src/core/marsh.c @@ -824,8 +824,8 @@ static const uint8_t *unmarshal_one_def( def->constants = NULL; def->bytecode = NULL; def->sourcemap = NULL; - def->symbolslots = NULL; - def->symbolslots_length = 0; + def->symbolmap = NULL; + def->symbolmap_length = 0; janet_v_push(st->lookup_defs, def); /* Set default lengths to zero */ diff --git a/src/core/specials.c b/src/core/specials.c index 17ae7f96..4b81ea37 100644 --- a/src/core/specials.c +++ b/src/core/specials.c @@ -753,7 +753,6 @@ static JanetSlot janetc_while(JanetFopts opts, int32_t argn, const Janet *argv) if (c->buffer) janet_v__cnt(c->buffer) = labelwt; if (c->mapbuffer) janet_v__cnt(c->mapbuffer) = labelwt; - janet_v_push(c->local_symbols, NULL); janetc_scope(&tempscope, c, JANET_SCOPE_FUNCTION, "while-iife"); /* Recompile in the function scope */ @@ -830,7 +829,6 @@ static JanetSlot janetc_fn(JanetFopts opts, int32_t argn, const Janet *argv) { /* Begin function */ c->scope->flags |= JANET_SCOPE_CLOSURE; - janet_v_push(c->local_symbols, NULL); janetc_scope(&fnscope, c, JANET_SCOPE_FUNCTION, "function"); if (argn == 0) { diff --git a/src/include/janet.h b/src/include/janet.h index f3eaba96..78992667 100644 --- a/src/include/janet.h +++ b/src/include/janet.h @@ -356,7 +356,7 @@ typedef struct JanetOSRWLock JanetOSRWLock; /* What to do when out of memory */ #ifndef JANET_OUT_OF_MEMORY -#define JANET_OUT_OF_MEMORY do { fprintf(stderr, "janet out of memory\n"); exit(1); } while (0) +#define JANET_OUT_OF_MEMORY do { fprintf(stderr, "%s:%d - janet out of memory\n", __FILE__, __LINE__); exit(1); } while (0) #endif #ifdef JANET_BSD @@ -448,7 +448,7 @@ typedef struct JanetReg JanetReg; typedef struct JanetRegExt JanetRegExt; typedef struct JanetMethod JanetMethod; typedef struct JanetSourceMapping JanetSourceMapping; -typedef struct JanetSymbolSlot JanetSymbolSlot; +typedef struct JanetSymbolMap JanetSymbolMap; typedef struct JanetView JanetView; typedef struct JanetByteView JanetByteView; typedef struct JanetDictView JanetDictView; @@ -1020,7 +1020,7 @@ struct JanetSourceMapping { }; /* Symbol to slot mapping & lifetime structure. */ -struct JanetSymbolSlot { +struct JanetSymbolMap { uint32_t birth_pc; uint32_t death_pc; uint32_t slot_index; @@ -1040,7 +1040,7 @@ struct JanetFuncDef { JanetSourceMapping *sourcemap; JanetString source; JanetString name; - JanetSymbolSlot *symbolslots; + JanetSymbolMap *symbolmap; int32_t flags; int32_t slotcount; /* The amount of stack space required for the function */ @@ -1051,7 +1051,7 @@ struct JanetFuncDef { int32_t bytecode_length; int32_t environments_length; int32_t defs_length; - int32_t symbolslots_length; + int32_t symbolmap_length; }; /* A function environment */