⚡ optimize framework of vm
This commit is contained in:
parent
ba629e57d7
commit
93528babdb
12
src/main.cpp
12
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<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";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue