diff --git a/src/core/asm.c b/src/core/asm.c index f3626ce6..0f3f0fed 100644 --- a/src/core/asm.c +++ b/src/core/asm.c @@ -721,11 +721,10 @@ static JanetAssembleResult janet_asm1(JanetAssembler *parent, Janet source, int } } - /* Set symbolslots */ + /* Set symbolmap */ def->symbolmap = NULL; def->symbolmap_length = 0; - - x = janet_get1(s, janet_ckeywordv("symbolslots")); + x = janet_get1(s, janet_ckeywordv("symbolmap")); if (janet_indexed_view(x, &arr, &count)) { def->symbolmap_length = count; def->symbolmap = janet_malloc(sizeof(JanetSymbolMap) * (size_t)count); @@ -749,16 +748,17 @@ static JanetAssembleResult janet_asm1(JanetAssembler *parent, Janet source, int if (!janet_checkint(tup[2])) { janet_asm_error(&a, "expected integer"); } - if (!janet_checktype(tup[3], JANET_STRING)) { - janet_asm_error(&a, "expected string"); + if (!janet_checktype(tup[3], JANET_SYMBOL)) { + janet_asm_error(&a, "expected symbol"); } ss.birth_pc = janet_unwrap_integer(tup[0]); ss.death_pc = janet_unwrap_integer(tup[1]); ss.slot_index = janet_unwrap_integer(tup[2]); - ss.symbol = janet_unwrap_string(tup[3]); + ss.symbol = janet_unwrap_symbol(tup[3]); def->symbolmap[i] = ss; } } + if (def->symbolmap_length) def->flags |= JANET_FUNCDEF_FLAG_HASSYMBOLMAP; /* Set environments */ x = janet_get1(s, janet_ckeywordv("environments")); @@ -934,7 +934,7 @@ static Janet janet_disasm_symbolslots(JanetFuncDef *def) { t[0] = janet_wrap_integer(ss.birth_pc); t[1] = janet_wrap_integer(ss.death_pc); t[2] = janet_wrap_integer(ss.slot_index); - t[3] = janet_cstringv((const char *) ss.symbol); + t[3] = janet_wrap_symbol(ss.symbol); symbolslots->data[i] = janet_wrap_tuple(janet_tuple_end(t)); } symbolslots->count = def->symbolmap_length; @@ -1021,7 +1021,7 @@ Janet janet_disasm(JanetFuncDef *def) { janet_table_put(ret, janet_ckeywordv("structarg"), janet_disasm_structarg(def)); janet_table_put(ret, janet_ckeywordv("name"), janet_disasm_name(def)); janet_table_put(ret, janet_ckeywordv("slotcount"), janet_disasm_slotcount(def)); - janet_table_put(ret, janet_ckeywordv("symbolslots"), janet_disasm_symbolslots(def)); + janet_table_put(ret, janet_ckeywordv("symbolmap"), janet_disasm_symbolslots(def)); janet_table_put(ret, janet_ckeywordv("constants"), janet_disasm_constants(def)); janet_table_put(ret, janet_ckeywordv("sourcemap"), janet_disasm_sourcemap(def)); janet_table_put(ret, janet_ckeywordv("environments"), janet_disasm_environments(def)); @@ -1058,7 +1058,7 @@ JANET_CORE_FN(cfun_disasm, "* :source - name of source file that this function was compiled from.\n" "* :name - name of function.\n" "* :slotcount - how many virtual registers, or slots, this function uses. Corresponds to stack space used by function.\n" - "* :symbolslots - all symbols and their slots.\n" + "* :symbolmap - all symbols and their slots.\n" "* :constants - an array of constants referenced by this function.\n" "* :sourcemap - a mapping of each bytecode instruction to a line and column in the source file.\n" "* :environments - an internal mapping of which enclosing functions are referenced for bindings.\n" diff --git a/src/core/compile.c b/src/core/compile.c index f0dc99f4..1eb32e6f 100644 --- a/src/core/compile.c +++ b/src/core/compile.c @@ -93,12 +93,13 @@ void janetc_freeslot(JanetCompiler *c, JanetSlot s) { /* Add a slot to a scope with a symbol associated with it (def or var). */ void janetc_nameslot(JanetCompiler *c, const uint8_t *sym, JanetSlot s) { SymPair sp; + int32_t cnt = janet_v_count(c->buffer); sp.sym = sym; sp.sym2 = sym; sp.slot = s; sp.keep = 0; sp.slot.flags |= JANET_SLOT_NAMED; - sp.birth_pc = janet_v_count(c->buffer); + sp.birth_pc = cnt ? cnt - 1 : 0; sp.death_pc = UINT32_MAX; janet_v_push(c->scope->syms, sp); } @@ -950,6 +951,7 @@ JanetFuncDef *janetc_pop_funcdef(JanetCompiler *c) { } def->symbolmap_length = janet_v_count(locals); def->symbolmap = janet_v_flatten(locals); + if (def->symbolmap_length) def->flags |= JANET_FUNCDEF_FLAG_HASSYMBOLMAP; /* Pop the scope */ janetc_popscope(c); diff --git a/src/core/debug.c b/src/core/debug.c index 81965beb..0faf68b9 100644 --- a/src/core/debug.c +++ b/src/core/debug.c @@ -334,7 +334,7 @@ static Janet doframe(JanetStackFrame *frame) { 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); + 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]); } diff --git a/src/core/marsh.c b/src/core/marsh.c index a203dcaf..078fb797 100644 --- a/src/core/marsh.c +++ b/src/core/marsh.c @@ -252,6 +252,8 @@ static void marshal_one_def(MarshalState *st, JanetFuncDef *def, int flags) { pushint(st, def->environments_length); if (def->flags & JANET_FUNCDEF_FLAG_HASDEFS) pushint(st, def->defs_length); + if (def->flags & JANET_FUNCDEF_FLAG_HASSYMBOLMAP) + pushint(st, def->symbolmap_length); if (def->flags & JANET_FUNCDEF_FLAG_HASNAME) marshal_one(st, janet_wrap_string(def->name), flags); if (def->flags & JANET_FUNCDEF_FLAG_HASSOURCE) @@ -261,6 +263,14 @@ static void marshal_one_def(MarshalState *st, JanetFuncDef *def, int flags) { for (int32_t i = 0; i < def->constants_length; i++) marshal_one(st, def->constants[i], flags); + /* Marshal symbol map, if needed */ + for (int32_t i = 0; i < def->symbolmap_length; i++) { + pushint(st, (int32_t) def->symbolmap[i].birth_pc); + pushint(st, (int32_t) def->symbolmap[i].death_pc); + pushint(st, (int32_t) def->symbolmap[i].slot_index); + marshal_one(st, janet_wrap_symbol(def->symbolmap[i].symbol), flags); + } + /* marshal the bytecode */ janet_marshal_u32s(st, def->bytecode, def->bytecode_length); @@ -270,7 +280,7 @@ static void marshal_one_def(MarshalState *st, JanetFuncDef *def, int flags) { /* marshal the sub funcdefs if needed */ for (int32_t i = 0; i < def->defs_length; i++) - marshal_one_def(st, def->defs[i], flags); + marshal_one_def(st, def->defs[i], flags + 1); /* marshal source maps if needed */ if (def->flags & JANET_FUNCDEF_FLAG_HASSOURCEMAP) { @@ -833,6 +843,7 @@ static const uint8_t *unmarshal_one_def( int32_t constants_length = 0; int32_t environments_length = 0; int32_t defs_length = 0; + int32_t symbolmap_length = 0; /* Read flags and other fixed values */ def->flags = readint(st, &data); @@ -848,6 +859,8 @@ static const uint8_t *unmarshal_one_def( environments_length = readnat(st, &data); if (def->flags & JANET_FUNCDEF_FLAG_HASDEFS) defs_length = readnat(st, &data); + if (def->flags & JANET_FUNCDEF_FLAG_HASSYMBOLMAP) + symbolmap_length = readnat(st, &data); /* Check name and source (optional) */ if (def->flags & JANET_FUNCDEF_FLAG_HASNAME) { @@ -876,6 +889,26 @@ static const uint8_t *unmarshal_one_def( } def->constants_length = constants_length; + /* Unmarshal symbol map, if needed */ + if (def->flags & JANET_FUNCDEF_FLAG_HASSYMBOLMAP) { + size_t size = sizeof(JanetSymbolMap) * symbolmap_length; + def->symbolmap = janet_malloc(size); + if (def->symbolmap == NULL) { + JANET_OUT_OF_MEMORY; + } + for (int32_t i = 0; i < symbolmap_length; i++) { + def->symbolmap[i].birth_pc = (uint32_t) readint(st, &data); + def->symbolmap[i].death_pc = (uint32_t) readint(st, &data); + def->symbolmap[i].slot_index = (uint32_t) readint(st, &data); + Janet value; + data = unmarshal_one(st, data, &value, flags + 1); + if (!janet_checktype(value, JANET_SYMBOL)) + janet_panic("expected symbol in symbol map"); + def->symbolmap[i].symbol = janet_unwrap_symbol(value); + } + def->symbolmap_length = (uint32_t) symbolmap_length; + } + /* Unmarshal bytecode */ def->bytecode = janet_malloc(sizeof(uint32_t) * bytecode_length); if (!def->bytecode) { diff --git a/src/include/janet.h b/src/include/janet.h index 78992667..5c2a26ce 100644 --- a/src/include/janet.h +++ b/src/include/janet.h @@ -1004,6 +1004,7 @@ struct JanetAbstractHead { /* Some function definition flags */ #define JANET_FUNCDEF_FLAG_VARARG 0x10000 #define JANET_FUNCDEF_FLAG_NEEDSENV 0x20000 +#define JANET_FUNCDEF_FLAG_HASSYMBOLMAP 0x40000 #define JANET_FUNCDEF_FLAG_HASNAME 0x80000 #define JANET_FUNCDEF_FLAG_HASSOURCE 0x100000 #define JANET_FUNCDEF_FLAG_HASDEFS 0x200000 diff --git a/test/suite0015.janet b/test/suite0015.janet index 9902ad4e..6eabf4ed 100644 --- a/test/suite0015.janet +++ b/test/suite0015.janet @@ -3,53 +3,42 @@ (import ./helper :prefix "" :exit true) (start-suite 15) -(assert (deep= (in (disasm (defn a [] (def x 10) x)) :symbolslots) nil) - "no symbolslots when *debug* is false") +(assert (deep= (in (disasm (defn a [] (def x 10) x)) :symbolmap) + @[[0 3 0 'a] [1 3 1 'x]]) + "symbolslots when *debug* is true") -(setdyn *debug* true) -(assert (deep= (in (disasm (defn a [] (def x 10) x)) :symbolslots) - @[[0 2147483647 0 "a"] [1 2147483647 1 "x"]]) - "symbolslots when *debug* is true") -(setdyn *debug* false) - -(setdyn *debug* true) (defn a [arg] - (def x 10) - (do - (def y 20) - (def z 30) - (+ x y z))) + (def x 10) + (do + (def y 20) + (def z 30) + (+ x y z))) (def symbolslots (in (disasm a) :symbolslots)) (def f (asm (disasm a))) (assert (deep= (in (disasm f) :symbolslots) - symbolslots) - "symbolslots survive disasm/asm") -(setdyn *debug* false) + symbolslots) + "symbolslots survive disasm/asm") # need to fix upvalues (comment (setdyn *debug* true) (setdyn :pretty-format "%.40M") - (def f (fn [x] (fn [y] (+ x y)))) - (assert (deep= (map last (in (disasm (f 10)) :symbolslots)) - @["x" "y"]) - "symbolslots upvalues") - (setdyn *debug* false) - ) + (def f (fn [x] (fn [y] (+ x y)))) + (assert (deep= (map last (in (disasm (f 10)) :symbolmap)) + @['x 'y]) + "symbolslots upvalues")) -(setdyn *debug* true) (assert (deep= (in (disasm (defn a [arg] - (def x 10) - (do - (def y 20) - (def z 30) - (+ x y z)))) :symbolslots) - @[[-1 2147483647 0 "arg"] - [0 2147483647 1 "a"] - [1 2147483647 2 "x"] - [2 7 3 "y"] - [3 7 4 "z"]]) - "arg & inner symbolslots") -(setdyn *debug* false) + (def x 10) + (do + (def y 20) + (def z 30) + (+ x y z)))) :symbolmap) + @[[0 7 0 'arg] + [0 7 1 'a] + [1 7 2 'x] + [2 7 3 'y] + [3 7 4 'z]]) + "arg & inner symbolslots") (end-suite)