optimize framework of vm

This commit is contained in:
ValKmjolnir 2023-08-24 23:24:04 +08:00
parent ba629e57d7
commit 93528babdb
5 changed files with 90 additions and 59 deletions

View File

@ -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<dbg>(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<vm>(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";
}
}

View File

@ -133,17 +133,20 @@ std::ostream& operator<<(std::ostream& out, const nas_ghost& ghost) {
}
void nas_co::clear() {
for(u32 i = 0; i<STACK_DEPTH; ++i) {
stack[i] = var::nil();
if (!ctx.stack) {
return;
}
for(u32 i = 0; i<STACK_DEPTH; ++i) {
ctx.stack[i] = var::nil();
}
ctx.pc = 0;
ctx.localr = nullptr;
ctx.memr = nullptr;
ctx.canary = stack+STACK_DEPTH-1;
ctx.top = stack;
ctx.canary = ctx.stack+STACK_DEPTH-1;
ctx.top = ctx.stack;
ctx.funcr = var::nil();
ctx.upvalr = var::nil();
ctx.stack = stack;
status = status::suspended;
}
@ -403,7 +406,13 @@ void gc::concurrent_mark(std::vector<var>& vec, usize begin, usize end) {
}
void gc::mark_context_root(std::vector<var>& bfs_queue) {
// scan global
for(usize i = 0; i<main_context_global_size; ++i) {
auto& val = main_context_global[i];
if (val.type>vm_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<var>& bfs_queue, nas_upval& upval) {
void gc::mark_co(std::vector<var>& 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);
}

View File

@ -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 */

View File

@ -5,7 +5,7 @@ void vm::init(
const std::vector<f64>& nums,
const std::vector<nasal_builtin_table>& natives,
const std::vector<opcode>& code,
const std::unordered_map<std::string, i32>& global,
const std::unordered_map<std::string, i32>& global_symbol,
const std::vector<std::string>& filenames,
const std::vector<std::string>& 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; i<STACK_DEPTH; ++i) {
stack[i] = nil;
ctx.stack[i] = nil;
global[i] = nil;
}
/* init gc */
ngc.set(&ctx, global, global_symbol.size());
ngc.init(strs, argv);
/* init vm globals */
auto map_instance = ngc.alloc(vm_map);
stack[global.at("globals")] = map_instance;
for(const auto& i : global) {
map_instance.map().mapper[i.first] = stack+i.second;
global[global_symbol.at("globals")] = map_instance;
for(const auto& i : global_symbol) {
map_instance.map().mapper[i.first] = global+i.second;
}
/* init vm arg */
auto arg_instance = ngc.alloc(vm_vec);
stack[global.at("arg")] = arg_instance;
global[global_symbol.at("arg")] = arg_instance;
arg_instance.vec().elems = ngc.env_argv;
}
@ -89,18 +90,19 @@ void vm::valinfo(var& val) {
}
void vm::traceback() {
/* bytecode[0].num is the global size */
var* bottom = ngc.rctx->stack==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<u32> 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? 0:(i64)(t-bottom+1)) << ")\n";
for(u32 i = 0; i<limit && t>=bottom; ++i, --t) {
std::clog << ", limit " << limit << ", total ";
std::clog << (top<bottom? 0:(i64)(top-bottom+1)) << ")\n";
for(u32 i = 0; i<limit && 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; i<bytecode[0].num; ++i) {
std::clog << " 0x" << std::hex << std::setw(6)
<< std::setfill('0') << i << std::dec
<< " ";
valinfo(stack[i]);
valinfo(global[i]);
}
}
@ -172,7 +172,7 @@ void vm::lstate() {
}
const u32 lsize = ctx.funcr.func().lsize;
std::clog << "local (0x" << std::hex << (u64)ctx.localr
<< " <+" << (u64)(ctx.localr-ngc.rctx->stack)
<< " <+" << (u64)(ctx.localr-ctx.stack)
<< ">)\n" << std::dec;
for(u32 i = 0; i<lsize; ++i) {
std::clog << " 0x" << std::hex << std::setw(6)
@ -217,7 +217,7 @@ void vm::die(const std::string& str) {
detail();
}
if (ngc.rctx->stack==stack) {
if (!ngc.cort) {
// in main context, exit directly
std::exit(1);
} else {

View File

@ -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<std::string>&);
/* 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