From f1fb58ead3e1d05dadb63ae9d9d56d45b6f40f61 Mon Sep 17 00:00:00 2001 From: ValKmjolnir Date: Sun, 16 Jun 2024 00:05:21 +0800 Subject: [PATCH] :bug: fix render bug in gc info --- src/nasal_dbg.cpp | 2 +- src/nasal_dbg.h | 2 +- src/nasal_gc.cpp | 22 +++--- src/nasal_opcode.cpp | 18 +++-- src/nasal_opcode.h | 180 +++++++++++++++++++++---------------------- src/nasal_type.cpp | 16 +++- src/nasal_type.h | 6 +- src/nasal_vm.cpp | 105 +++++++++++++++++-------- src/nasal_vm.h | 6 +- 9 files changed, 210 insertions(+), 147 deletions(-) diff --git a/src/nasal_dbg.cpp b/src/nasal_dbg.cpp index 4f6c4cb..edc99b2 100644 --- a/src/nasal_dbg.cpp +++ b/src/nasal_dbg.cpp @@ -47,7 +47,7 @@ void operand_line_counter::dump_operand_count() const { break; } std::clog << " "; - std::clog << operand_name_table.at(static_cast(i.first)); + std::clog << operand_name_table.at(static_cast(i.first)); std::clog << " : " << i.second << " (" << rate << "%)\n"; } std::clog << " total : " << total << '\n'; diff --git a/src/nasal_dbg.h b/src/nasal_dbg.h index c554941..02f0b91 100644 --- a/src/nasal_dbg.h +++ b/src/nasal_dbg.h @@ -15,7 +15,7 @@ namespace nasal { // and show them before each line of the source file class operand_line_counter { private: - static const usize operand_size = op_code_type::op_ret + 1; + static const usize operand_size = opcode_type::op_ret + 1; u64 operand_counter[operand_size]; std::vector file_name_list; std::vector> file_line_counter; diff --git a/src/nasal_gc.cpp b/src/nasal_gc.cpp index 6f2a999..6192849 100644 --- a/src/nasal_gc.cpp +++ b/src/nasal_gc.cpp @@ -315,16 +315,20 @@ void gc::info() const { indent_string += "─"; } const auto first_line = "╭" + indent_string + "┬" + - indent_string + "─" + - indent_string + "─" + + indent_string + "┬" + + indent_string + "┬" + indent_string + "╮"; + const auto second_line = "├" + indent_string + "┼" + + indent_string + "┼" + + indent_string + "┼" + + indent_string + "┤"; const auto mid_line = "├" + indent_string + "┼" + - indent_string + "┼" + - indent_string + "┼" + + indent_string + "┴" + + indent_string + "┴" + indent_string + "┤"; const auto another_mid_line = "├" + indent_string + "┼" + - indent_string + "┴" + - indent_string + "┴" + + indent_string + "─" + + indent_string + "─" + indent_string + "┤"; const auto last_line = "╰" + indent_string + "┴" + indent_string + "─" + @@ -336,7 +340,7 @@ void gc::info() const { std::clog << " │ " << left << setw(indent) << setfill(' ') << "gc count"; std::clog << " │ " << left << setw(indent) << setfill(' ') << "alloc count"; std::clog << " │ " << left << setw(indent) << setfill(' ') << "memory size"; - std::clog << " │\n" << mid_line << "\n"; + std::clog << " │\n" << second_line << "\n"; double total = 0; for(u8 i = 0; i=0; i -= 8) { - out << hex << setw(2) << setfill('0') << ((num>>i)&0xff) << dec << " "; + auto this_byte = ((num>>i)&0xff); + out << hex << setw(2) << setfill('0') << this_byte << dec << " "; } // dump operand name - out << " " << operand_name_table.at(static_cast(op)) << " "; + out << " " << operand_name_table.at(static_cast(op)) << " "; switch(op) { case op_addeq: @@ -56,7 +57,7 @@ void codestream::dump(std::ostream& out) const { break; case op_lnkeqc: out << hex << "0x" << num << dec; - out << " (" << util::rawstr(const_string[num], 16) << ")"; + out << " (\"" << util::rawstr(const_string[num], 32) << "\")"; break; case op_addecp: case op_subecp: @@ -67,7 +68,7 @@ void codestream::dump(std::ostream& out) const { break; case op_lnkecp: out << hex << "0x" << num << dec; - out << " (" << util::rawstr(const_string[num], 16) << ") sp-1"; + out << " (\"" << util::rawstr(const_string[num], 32) << "\") sp-1"; break; case op_addc: case op_subc: @@ -100,8 +101,11 @@ void codestream::dump(std::ostream& out) const { case op_loadl: out << hex << "0x" << num << dec; break; case op_callb: - out << hex << "0x" << num << dec << " [" - << natives[num].name << "]"; break; + out << hex << "0x" << num << dec; + out << " [" << natives[num].name << "@0x"; + out << hex << reinterpret_cast(natives[num].func) << dec; + out << "]"; + break; case op_upval: case op_mupval: case op_loadu: @@ -116,7 +120,7 @@ void codestream::dump(std::ostream& out) const { case op_deft: case op_dyn: out << hex << "0x" << num << dec; - out << " (" << util::rawstr(const_string[num], 16) << ")"; + out << " (\"" << util::rawstr(const_string[num], 32) << "\")"; break; default: if (files) { diff --git a/src/nasal_opcode.h b/src/nasal_opcode.h index e64ade5..0b9fa1a 100644 --- a/src/nasal_opcode.h +++ b/src/nasal_opcode.h @@ -7,7 +7,7 @@ namespace nasal { -enum op_code_type: u8 { +enum opcode_type: u8 { op_exit, // stop the virtual machine op_repl, // in repl mode: print value on stack top op_intl, // local scope size @@ -98,95 +98,95 @@ enum op_code_type: u8 { op_ret // return }; -static std::unordered_map operand_name_table = { - {op_code_type::op_exit, "exit "}, - {op_code_type::op_repl, "repl "}, - {op_code_type::op_intl, "intl "}, - {op_code_type::op_loadg, "loadg "}, - {op_code_type::op_loadl, "loadl "}, - {op_code_type::op_loadu, "loadu "}, - {op_code_type::op_dup, "dup "}, - {op_code_type::op_pnum, "pnum "}, - {op_code_type::op_pnil, "pnil "}, - {op_code_type::op_pstr, "pstr "}, - {op_code_type::op_newv, "newv "}, - {op_code_type::op_newh, "newh "}, - {op_code_type::op_newf, "newf "}, - {op_code_type::op_happ, "happ "}, - {op_code_type::op_para, "para "}, - {op_code_type::op_deft, "def "}, - {op_code_type::op_dyn, "dyn "}, - {op_code_type::op_lnot, "lnot "}, - {op_code_type::op_usub, "usub "}, - {op_code_type::op_bnot, "bitnot"}, - {op_code_type::op_btor, "bitor "}, - {op_code_type::op_btxor, "bitxor"}, - {op_code_type::op_btand, "bitand"}, - {op_code_type::op_add, "add "}, - {op_code_type::op_sub, "sub "}, - {op_code_type::op_mul, "mult "}, - {op_code_type::op_div, "div "}, - {op_code_type::op_lnk, "lnk "}, - {op_code_type::op_addc, "addc "}, - {op_code_type::op_subc, "subc "}, - {op_code_type::op_mulc, "multc "}, - {op_code_type::op_divc, "divc "}, - {op_code_type::op_lnkc, "lnkc "}, - {op_code_type::op_addeq, "addeq "}, - {op_code_type::op_subeq, "subeq "}, - {op_code_type::op_muleq, "muleq "}, - {op_code_type::op_diveq, "diveq "}, - {op_code_type::op_lnkeq, "lnkeq "}, - {op_code_type::op_btandeq, "bandeq"}, - {op_code_type::op_btoreq, "boreq "}, - {op_code_type::op_btxoreq, "bxoreq"}, - {op_code_type::op_addeqc, "addeqc"}, - {op_code_type::op_subeqc, "subeqc"}, - {op_code_type::op_muleqc, "muleqc"}, - {op_code_type::op_diveqc, "diveqc"}, - {op_code_type::op_lnkeqc, "lnkeqc"}, - {op_code_type::op_addecp, "addecp"}, - {op_code_type::op_subecp, "subecp"}, - {op_code_type::op_mulecp, "mulecp"}, - {op_code_type::op_divecp, "divecp"}, - {op_code_type::op_lnkecp, "lnkecp"}, - {op_code_type::op_meq, "meq "}, - {op_code_type::op_eq, "eq "}, - {op_code_type::op_neq, "neq "}, - {op_code_type::op_less, "less "}, - {op_code_type::op_leq, "leq "}, - {op_code_type::op_grt, "grt "}, - {op_code_type::op_geq, "geq "}, - {op_code_type::op_lessc, "lessc "}, - {op_code_type::op_leqc, "leqc "}, - {op_code_type::op_grtc, "grtc "}, - {op_code_type::op_geqc, "geqc "}, - {op_code_type::op_pop, "pop "}, - {op_code_type::op_jmp, "jmp "}, - {op_code_type::op_jt, "jt "}, - {op_code_type::op_jf, "jf "}, - {op_code_type::op_cnt, "cnt "}, - {op_code_type::op_findex, "findx "}, - {op_code_type::op_feach, "feach "}, - {op_code_type::op_callg, "callg "}, - {op_code_type::op_calll, "calll "}, - {op_code_type::op_upval, "upval "}, - {op_code_type::op_callv, "callv "}, - {op_code_type::op_callvi, "callvi"}, - {op_code_type::op_callh, "callh "}, - {op_code_type::op_callfv, "callfv"}, - {op_code_type::op_callfh, "callfh"}, - {op_code_type::op_callb, "callb "}, - {op_code_type::op_slcbeg, "slcbeg"}, - {op_code_type::op_slcend, "slcend"}, - {op_code_type::op_slc, "slice "}, - {op_code_type::op_slc2, "slice2"}, - {op_code_type::op_mcallg, "mcallg"}, - {op_code_type::op_mcalll, "mcalll"}, - {op_code_type::op_mupval, "mupval"}, - {op_code_type::op_mcallv, "mcallv"}, - {op_code_type::op_mcallh, "mcallh"}, - {op_code_type::op_ret, "ret "} +static std::unordered_map operand_name_table = { + {opcode_type::op_exit, "exit "}, + {opcode_type::op_repl, "repl "}, + {opcode_type::op_intl, "intl "}, + {opcode_type::op_loadg, "loadg "}, + {opcode_type::op_loadl, "loadl "}, + {opcode_type::op_loadu, "loadu "}, + {opcode_type::op_dup, "dup "}, + {opcode_type::op_pnum, "pnum "}, + {opcode_type::op_pnil, "pnil "}, + {opcode_type::op_pstr, "pstr "}, + {opcode_type::op_newv, "newv "}, + {opcode_type::op_newh, "newh "}, + {opcode_type::op_newf, "newf "}, + {opcode_type::op_happ, "happ "}, + {opcode_type::op_para, "para "}, + {opcode_type::op_deft, "def "}, + {opcode_type::op_dyn, "dyn "}, + {opcode_type::op_lnot, "lnot "}, + {opcode_type::op_usub, "usub "}, + {opcode_type::op_bnot, "bitnot"}, + {opcode_type::op_btor, "bitor "}, + {opcode_type::op_btxor, "bitxor"}, + {opcode_type::op_btand, "bitand"}, + {opcode_type::op_add, "add "}, + {opcode_type::op_sub, "sub "}, + {opcode_type::op_mul, "mult "}, + {opcode_type::op_div, "div "}, + {opcode_type::op_lnk, "lnk "}, + {opcode_type::op_addc, "addc "}, + {opcode_type::op_subc, "subc "}, + {opcode_type::op_mulc, "multc "}, + {opcode_type::op_divc, "divc "}, + {opcode_type::op_lnkc, "lnkc "}, + {opcode_type::op_addeq, "addeq "}, + {opcode_type::op_subeq, "subeq "}, + {opcode_type::op_muleq, "muleq "}, + {opcode_type::op_diveq, "diveq "}, + {opcode_type::op_lnkeq, "lnkeq "}, + {opcode_type::op_btandeq, "bandeq"}, + {opcode_type::op_btoreq, "boreq "}, + {opcode_type::op_btxoreq, "bxoreq"}, + {opcode_type::op_addeqc, "addeqc"}, + {opcode_type::op_subeqc, "subeqc"}, + {opcode_type::op_muleqc, "muleqc"}, + {opcode_type::op_diveqc, "diveqc"}, + {opcode_type::op_lnkeqc, "lnkeqc"}, + {opcode_type::op_addecp, "addecp"}, + {opcode_type::op_subecp, "subecp"}, + {opcode_type::op_mulecp, "mulecp"}, + {opcode_type::op_divecp, "divecp"}, + {opcode_type::op_lnkecp, "lnkecp"}, + {opcode_type::op_meq, "meq "}, + {opcode_type::op_eq, "eq "}, + {opcode_type::op_neq, "neq "}, + {opcode_type::op_less, "less "}, + {opcode_type::op_leq, "leq "}, + {opcode_type::op_grt, "grt "}, + {opcode_type::op_geq, "geq "}, + {opcode_type::op_lessc, "lessc "}, + {opcode_type::op_leqc, "leqc "}, + {opcode_type::op_grtc, "grtc "}, + {opcode_type::op_geqc, "geqc "}, + {opcode_type::op_pop, "pop "}, + {opcode_type::op_jmp, "jmp "}, + {opcode_type::op_jt, "jt "}, + {opcode_type::op_jf, "jf "}, + {opcode_type::op_cnt, "cnt "}, + {opcode_type::op_findex, "findx "}, + {opcode_type::op_feach, "feach "}, + {opcode_type::op_callg, "callg "}, + {opcode_type::op_calll, "calll "}, + {opcode_type::op_upval, "upval "}, + {opcode_type::op_callv, "callv "}, + {opcode_type::op_callvi, "callvi"}, + {opcode_type::op_callh, "callh "}, + {opcode_type::op_callfv, "callfv"}, + {opcode_type::op_callfh, "callfh"}, + {opcode_type::op_callb, "callb "}, + {opcode_type::op_slcbeg, "slcbeg"}, + {opcode_type::op_slcend, "slcend"}, + {opcode_type::op_slc, "slice "}, + {opcode_type::op_slc2, "slice2"}, + {opcode_type::op_mcallg, "mcallg"}, + {opcode_type::op_mcalll, "mcalll"}, + {opcode_type::op_mupval, "mupval"}, + {opcode_type::op_mcallv, "mcallv"}, + {opcode_type::op_mcallh, "mcallh"}, + {opcode_type::op_ret, "ret "} }; struct opcode { diff --git a/src/nasal_type.cpp b/src/nasal_type.cpp index 4d6b2a2..93d3485 100644 --- a/src/nasal_type.cpp +++ b/src/nasal_type.cpp @@ -89,12 +89,18 @@ std::ostream& operator<<(std::ostream& out, nas_hash& hash) { out << (hash.elems.size()? "{..}":"{}"); return out; } + + // mark print, to avoid infinite recursion hash.printed = true; + + static const char* sep[] = {", ", "}"}; usize iter = 0, size = hash.elems.size(); out << "{"; for(auto& i : hash.elems) { - out << i.first << ":" << i.second << ",}"[(++iter)==size]; + out << i.first << ": " << i.second << sep[(++iter)==size]; } + + // restore flag hash.printed = false; return out; } @@ -212,12 +218,18 @@ std::ostream& operator<<(std::ostream& out, nas_map& mp) { out << (mp.mapper.size()? "{..}":"{}"); return out; } + + // mark print, to avoid infinite recursion mp.printed = true; + + static const char* sep[] = {", ", "}"}; usize iter = 0, size = mp.mapper.size(); out << "{"; for(auto& i : mp.mapper) { - out << i.first << ":" << *i.second << ",}"[(++iter)==size]; + out << i.first << ": " << *i.second << sep[(++iter)==size]; } + + // restore flag mp.printed = false; return out; } diff --git a/src/nasal_type.h b/src/nasal_type.h index 5a759e5..d8302f7 100644 --- a/src/nasal_type.h +++ b/src/nasal_type.h @@ -131,7 +131,7 @@ struct nas_vec { // mark if this is printed, avoid stack overflow bool printed = false; - usize size() const {return elems.size();} + auto size() const { return elems.size(); } var get_value(const i32); var* get_memory(const i32); }; @@ -142,7 +142,7 @@ struct nas_hash { // mark if this is printed, avoid stack overflow bool printed = false; - usize size() const {return elems.size();} + auto size() const { return elems.size(); } var get_value(const std::string&); var* get_memory(const std::string&); }; @@ -256,9 +256,11 @@ struct nas_map { bool printed = false; std::unordered_map mapper; +public: void clear() { mapper.clear(); } + auto size() const { return mapper.size(); } var get_value(const std::string&); var* get_memory(const std::string&); diff --git a/src/nasal_vm.cpp b/src/nasal_vm.cpp index 0cda417..1d7460e 100644 --- a/src/nasal_vm.cpp +++ b/src/nasal_vm.cpp @@ -63,12 +63,12 @@ void vm::context_and_global_init() { } } -void vm::hash_value_info(var& val) { +void vm::hash_value_info(var& val, const usize max_show_elems) { std::clog << "{"; usize count = 0; for(const auto& i : val.hash().elems) { ++count; - if (count>3) { + if (count>max_show_elems) { break; } @@ -77,55 +77,92 @@ void vm::hash_value_info(var& val) { std::clog << ", "; } } - if (val.hash().size()>3) { + if (val.hash().size()>max_show_elems) { std::clog << "..."; } std::clog << "}"; } +void vm::namespace_value_info(var& val, const usize max_show_elems) { + std::clog << "{"; + usize count = 0; + for(const auto& i : val.map().mapper) { + ++count; + if (count>max_show_elems) { + break; + } + + std::clog << i.first; + if (count!=val.map().size()) { + std::clog << ", "; + } + } + if (val.map().size()>max_show_elems) { + std::clog << "..."; + } + std::clog << "}"; +} + +void vm::value_name_form(const var& val) { + std::clog << "| "; + switch(val.type) { + case vm_type::vm_none: std::clog << "null "; break; + case vm_type::vm_ret: std::clog << "return "; break; + case vm_type::vm_addr: std::clog << "address "; break; + case vm_type::vm_cnt: std::clog << "counter "; break; + case vm_type::vm_nil: std::clog << "nil "; break; + case vm_type::vm_num: std::clog << "number "; break; + case vm_type::vm_str: std::clog << "string "; break; + case vm_type::vm_func: std::clog << "function "; break; + case vm_type::vm_upval: std::clog << "upvalue "; break; + case vm_type::vm_vec: std::clog << "vector "; break; + case vm_type::vm_hash: std::clog << "hash "; break; + case vm_type::vm_ghost: std::clog << "ghost "; break; + case vm_type::vm_co: std::clog << "coroutine"; break; + case vm_type::vm_map: std::clog << "namespace"; break; + default: std::clog << "error "; break; + } + std::clog << " | "; +} + void vm::value_info(var& val) { const auto p = reinterpret_cast(val.val.gcobj); + + value_name_form(val); + switch(val.type) { - case vm_type::vm_none: std::clog << "| null |"; break; + case vm_type::vm_none: std::clog << "null"; break; case vm_type::vm_ret: - std::clog << "| pc | 0x" << std::hex << val.ret() << std::dec; + std::clog << "0x" << std::hex << val.ret() << std::dec; break; case vm_type::vm_addr: - std::clog << "| addr | 0x"; + std::clog << "0x"; std::clog << std::hex << reinterpret_cast(val.addr()) << std::dec; break; - case vm_type::vm_cnt: std::clog << "| cnt | " << val.cnt(); break; - case vm_type::vm_nil: std::clog << "| nil |"; break; - case vm_type::vm_num: std::clog << "| num | " << val.num(); break; + case vm_type::vm_cnt: std::clog << val.cnt(); break; + case vm_type::vm_nil: std::clog << "nil"; break; + case vm_type::vm_num: std::clog << val.num(); break; case vm_type::vm_str: - std::clog << "| str | \"" << util::rawstr(val.str(), 16) << "\""; - break; - case vm_type::vm_func: - std::clog << "| func | " << val.func(); + std::clog << "\"" << util::rawstr(val.str(), 16) << "\""; break; + case vm_type::vm_func: std::clog << val.func(); break; case vm_type::vm_upval: - std::clog << "| upval| <0x" << std::hex << p << std::dec; - std::clog << "> [" << val.upval().size << " val]"; break; - case vm_type::vm_vec: - std::clog << "| vec | [" << val.vec().size() << " val]"; break; - case vm_type::vm_hash: - std::clog << "| hash | "; - hash_value_info(val); + std::clog << "<0x" << std::hex << p << std::dec; + std::clog << "> [" << val.upval().size << " val]"; break; + case vm_type::vm_vec: + std::clog << "[" << val.vec().size() << " val]"; break; + case vm_type::vm_hash: hash_value_info(val, 4); break; case vm_type::vm_ghost: - std::clog << "| obj | <0x" << std::hex << p << "> " << std::dec; + std::clog << "<0x" << std::hex << p << "> " << std::dec; std::clog << "object:" << val.ghost().type_name; break; case vm_type::vm_co: - std::clog << "| co | coroutine@0x" << std::hex << p << std::dec; - break; - case vm_type::vm_map: - std::clog << "| nmspc| ["; - std::clog << val.map().mapper.size() << " val]"; + std::clog << "coroutine@0x" << std::hex << p << std::dec; break; + case vm_type::vm_map: namespace_value_info(val, 4); break; default: - std::clog << "| err | <0x" << std::hex << p << std::dec; - std::clog << "> unknown object"; + std::clog << "<0x" << std::hex << p << std::dec << "> unknown"; break; } std::clog << "\n"; @@ -247,16 +284,16 @@ void vm::stack_info(const u64 limit = 16) { void vm::register_info() { std::clog << "\nregister (" << (ngc.cort? "coroutine":"main") << ")\n"; std::clog << std::hex - << " [ pc ] | pc | 0x" << ctx.pc << "\n" - << " [ global ] | addr | 0x" + << " [ pc ] | pc | 0x" << ctx.pc << "\n" + << " [ global ] | address | 0x" << reinterpret_cast(global) << "\n" - << " [ local ] | addr | 0x" + << " [ local ] | address | 0x" << reinterpret_cast(ctx.localr) << "\n" - << " [ memr ] | addr | 0x" + << " [ memr ] | address | 0x" << reinterpret_cast(ctx.memr) << "\n" - << " [ canary ] | addr | 0x" + << " [ canary ] | address | 0x" << reinterpret_cast(ctx.canary) << "\n" - << " [ top ] | addr | 0x" + << " [ top ] | address | 0x" << reinterpret_cast(ctx.top) << "\n" << std::dec; std::clog << " [ funcr ] "; value_info(ctx.funcr); diff --git a/src/nasal_vm.h b/src/nasal_vm.h index 89b9cf3..ec00167 100644 --- a/src/nasal_vm.h +++ b/src/nasal_vm.h @@ -65,7 +65,9 @@ protected: protected: /* debug functions */ bool verbose = false; - void hash_value_info(var&); + void hash_value_info(var&, const usize); + void namespace_value_info(var&, const usize); + void value_name_form(const var&); void value_info(var&); void function_detail_info(const nas_func&); void function_call_trace(); @@ -76,6 +78,8 @@ protected: void local_state(); void upvalue_state(); void all_state_detail(); + +protected: std::string report_lack_arguments(u32, const nas_func&) const; std::string report_special_call_lack_arguments(var*, const nas_func&) const; std::string report_key_not_found(const std::string&, const nas_hash&) const;