From 93528babdb8b2d85f3424a15a673065c2782fd09 Mon Sep 17 00:00:00 2001 From: ValKmjolnir Date: Thu, 24 Aug 2023 23:24:04 +0800 Subject: [PATCH] :zap: optimize framework of vm --- src/main.cpp | 12 ++++++---- src/nasal_gc.cpp | 23 +++++++++++++------ src/nasal_gc.h | 35 +++++++++++++++++++--------- src/nasal_vm.cpp | 60 ++++++++++++++++++++++++------------------------ src/nasal_vm.h | 19 ++++++++++----- 5 files changed, 90 insertions(+), 59 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 29c8864..6867690 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -114,7 +114,6 @@ void execute( parse parse; linker ld; codegen gen; - vm ctx; // lexer scans file to get tokens lex.scan(file).chkerr(); @@ -150,15 +149,18 @@ void execute( // run auto start = clk::now(); if (cmd&VM_DEBUG) { - dbg().run(gen, ld, argv, cmd&VM_PROFILE, cmd&VM_PROF_ALL); + auto debugger = std::unique_ptr(new dbg); + debugger->run(gen, ld, argv, cmd&VM_PROFILE, cmd&VM_PROF_ALL); } else if (cmd&VM_TIME || cmd&VM_EXEC) { - ctx.run(gen, ld, argv, cmd&VM_DETAIL); + auto runtime = std::unique_ptr(new vm); + runtime->run(gen, ld, argv, cmd&VM_DETAIL); } // get running time + auto end = clk::now(); if (cmd&VM_TIME) { - f64 tm = (clk::now()-start).count()*1.0/den; - std::clog << "process exited after " << tm << "s.\n\n"; + std::clog << "process exited after "; + std::clog << (end-start).count()*1.0/den << "s.\n\n"; } } diff --git a/src/nasal_gc.cpp b/src/nasal_gc.cpp index ee6b1e2..31fa605 100644 --- a/src/nasal_gc.cpp +++ b/src/nasal_gc.cpp @@ -133,17 +133,20 @@ std::ostream& operator<<(std::ostream& out, const nas_ghost& ghost) { } void nas_co::clear() { - for(u32 i = 0; i& vec, usize begin, usize end) { } void gc::mark_context_root(std::vector& bfs_queue) { - + // scan global + for(usize i = 0; ivm_num) { + bfs_queue.push_back(val); + } + } // scan now running context, this context maybe related to coroutine or main for(var* i = rctx->stack; i<=rctx->top; ++i) { if (i->type>vm_num) { @@ -479,7 +488,7 @@ void gc::mark_upval(std::vector& bfs_queue, nas_upval& upval) { void gc::mark_co(std::vector& bfs_queue, nas_co& co) { bfs_queue.push_back(co.ctx.funcr); bfs_queue.push_back(co.ctx.upvalr); - for(var* i = co.stack; i<=co.ctx.top; ++i) { + for(var* i = co.ctx.stack; i<=co.ctx.top; ++i) { if (i->type>vm_num) { bfs_queue.push_back(*i); } diff --git a/src/nasal_gc.h b/src/nasal_gc.h index 901db8e..51909ca 100644 --- a/src/nasal_gc.h +++ b/src/nasal_gc.h @@ -202,14 +202,14 @@ public: }; struct context { - u32 pc; - var* localr; - var* memr; - var funcr; - var upvalr; - var* canary; - var* stack; - var* top; + u32 pc = 0; + var* localr = nullptr; + var* memr = nullptr; + var funcr = var::nil(); + var upvalr = var::nil(); + var* canary = nullptr; + var* stack = nullptr; + var* top = nullptr; }; struct nas_co { @@ -219,11 +219,16 @@ struct nas_co { dead }; - var stack[STACK_DEPTH]; context ctx; status status; - nas_co() {clear();} + nas_co() { + ctx.stack = new var[STACK_DEPTH]; + clear(); + } + ~nas_co() { + delete[] ctx.stack; + } void clear(); }; @@ -281,6 +286,10 @@ struct gc { /* main context temporary storage */ context mctx; + /* global storage */ + var* main_context_global = nullptr; + usize main_context_global_size = 0; + /* runtime context */ context* rctx = nullptr; nas_co* cort = nullptr; // running coroutine @@ -315,7 +324,11 @@ struct gc { i64 max_mark_time = 0; i64 max_sweep_time = 0; - gc(context* _ctx): rctx(_ctx) {} + void set(context* _ctx, var* _global, usize _size) { + rctx = _ctx; + main_context_global = _global; + main_context_global_size = _size; + } private: /* gc functions */ diff --git a/src/nasal_vm.cpp b/src/nasal_vm.cpp index 6249aec..0bb57c0 100644 --- a/src/nasal_vm.cpp +++ b/src/nasal_vm.cpp @@ -5,7 +5,7 @@ void vm::init( const std::vector& nums, const std::vector& natives, const std::vector& code, - const std::unordered_map& global, + const std::unordered_map& global_symbol, const std::vector& filenames, const std::vector& argv ) { @@ -23,28 +23,29 @@ void vm::init( ctx.memr = nullptr; ctx.funcr = nil; ctx.upvalr = nil; - ctx.canary = stack+STACK_DEPTH-1; // stack[STACK_DEPTH-1] - ctx.top = stack; - ctx.stack = stack; + ctx.canary = ctx.stack+STACK_DEPTH-1; // stack[STACK_DEPTH-1] + ctx.top = ctx.stack; - /* clear main stack */ + /* clear main stack and global */ for(u32 i = 0; istack==stack? stack+bytecode[0].num:ngc.rctx->stack; - var* ctx_top = ngc.rctx->stack==stack? ctx.top:ngc.rctx->top; + var* bottom = ctx.stack; + var* top = ctx.top; + std::stack ret; - for(var* i = bottom; i<=ctx_top; ++i) { + for(var* i = bottom; i<=top; ++i) { if (i->type==vm_ret && i->ret()!=0) { ret.push(i->ret()); } } ret.push(ctx.pc); // store the position program crashed + std::clog << "trace back (" - << (ngc.rctx->stack==stack? "main":"coroutine") + << (ngc.cort? "coroutine":"main") << ")\n"; codestream::set(cnum, cstr, native.data(), files); for(u32 p = 0, same = 0, prev = 0xffffffff; !ret.empty(); prev = p, ret.pop()) { @@ -121,19 +123,17 @@ void vm::traceback() { } void vm::stackinfo(const u32 limit = 10) { - /* bytecode[0].num is the global size */ - const u32 gsize = ngc.rctx->stack==stack? bytecode[0].num:0; - var* t = ctx.top; - var* bottom = ngc.rctx->stack+gsize; + var* top = ctx.top; + var* bottom = ctx.stack; std::clog << "stack (0x" << std::hex << (u64)bottom << std::dec; - std::clog << " <+" << gsize << ">, limit " << limit << ", total "; - std::clog << (t=bottom; ++i, --t) { + std::clog << ", limit " << limit << ", total "; + std::clog << (top=bottom; ++i, --top) { std::clog << " 0x" << std::hex << std::setw(6) << std::setfill('0') - << (u64)(t-ngc.rctx->stack) << std::dec + << (u64)(top-ngc.rctx->stack) << std::dec << " "; - valinfo(t[0]); + valinfo(top[0]); } } @@ -141,7 +141,7 @@ void vm::reginfo() { std::clog << "registers (" << (ngc.cort? "coroutine":"main") << ")\n" << std::hex << " [pc ] | pc | 0x" << ctx.pc << "\n" - << " [global] | addr | 0x" << (u64)stack << "\n" + << " [global] | addr | 0x" << (u64)global << "\n" << " [local ] | addr | 0x" << (u64)ctx.localr << "\n" << " [memr ] | addr | 0x" << (u64)ctx.memr << "\n" << " [canary] | addr | 0x" << (u64)ctx.canary << "\n" @@ -153,16 +153,16 @@ void vm::reginfo() { void vm::gstate() { // bytecode[0].op is op_intg - if (!bytecode[0].num || stack[0].type==vm_none) { + if (!bytecode[0].num || global[0].type==vm_none) { return; } std::clog << "global (0x" << std::hex - << (u64)stack << " <+0>)\n" << std::dec; + << (u64)global << ")\n" << std::dec; for(u32 i = 0; istack) + << " <+" << (u64)(ctx.localr-ctx.stack) << ">)\n" << std::dec; for(u32 i = 0; istack==stack) { + if (!ngc.cort) { // in main context, exit directly std::exit(1); } else { diff --git a/src/nasal_vm.h b/src/nasal_vm.h index 3b54cf7..93d352a 100644 --- a/src/nasal_vm.h +++ b/src/nasal_vm.h @@ -29,7 +29,7 @@ protected: gc ngc; /* main stack */ - var stack[STACK_DEPTH]; + var* global = nullptr; /* values used for debugger */ const std::string* files = nullptr; // file name list @@ -46,7 +46,7 @@ protected: const std::vector&); /* debug functions */ - bool verbose; + bool verbose = false; void valinfo(var&); void traceback(); void stackinfo(const u32); @@ -151,7 +151,14 @@ protected: public: /* constructor of vm instance */ - vm(): ngc(&ctx), verbose(false) {} + vm() { + ctx.stack = new var[STACK_DEPTH]; + global = new var[STACK_DEPTH]; + } + ~vm() { + delete[] ctx.stack; + delete[] global; + } /* execution entry */ void run( @@ -184,7 +191,7 @@ inline void vm::o_intl() { } inline void vm::o_loadg() { - stack[imm[ctx.pc]] = (ctx.top--)[0]; + global[imm[ctx.pc]] = (ctx.top--)[0]; } inline void vm::o_loadl() { @@ -534,7 +541,7 @@ inline void vm::o_feach() { inline void vm::o_callg() { // get main stack directly - (++ctx.top)[0] = stack[imm[ctx.pc]]; + (++ctx.top)[0] = global[imm[ctx.pc]]; } inline void vm::o_calll() { @@ -819,7 +826,7 @@ inline void vm::o_slc2() { } inline void vm::o_mcallg() { - ctx.memr = stack+imm[ctx.pc]; + ctx.memr = global+imm[ctx.pc]; (++ctx.top)[0] = ctx.memr[0]; // push value in this memory space on stack // to avoid being garbage collected