⚡ merge runtime regs into struct context
This commit is contained in:
parent
3852ce23a3
commit
5519dc7a29
2
LICENSE
2
LICENSE
|
@ -1,6 +1,6 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2021 ValKmjolnir
|
||||
Copyright (c) 2019-2023 ValKmjolnir
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
|
12
main.cpp
12
main.cpp
|
@ -13,8 +13,6 @@
|
|||
|
||||
#include <unordered_map>
|
||||
|
||||
using ch_clk=std::chrono::high_resolution_clock;
|
||||
|
||||
const u32 VM_AST =0x01;
|
||||
const u32 VM_CODE =0x02;
|
||||
const u32 VM_TIME =0x04;
|
||||
|
@ -73,6 +71,8 @@ void err() {
|
|||
}
|
||||
|
||||
void execute(const string& file,const std::vector<string>& argv,const u32 cmd) {
|
||||
using clk=std::chrono::high_resolution_clock;
|
||||
|
||||
error err;
|
||||
lexer lex(err);
|
||||
parse parse(err);
|
||||
|
@ -103,12 +103,12 @@ void execute(const string& file,const std::vector<string>& argv,const u32 cmd) {
|
|||
|
||||
// run
|
||||
if (cmd&VM_DEBUG) {
|
||||
debugger(err).run(gen,ld,argv);
|
||||
dbg(err).run(gen,ld,argv);
|
||||
} else if (cmd&VM_TIME) {
|
||||
auto start=ch_clk::now();
|
||||
auto start=clk::now();
|
||||
ctx.run(gen,ld,argv,cmd&VM_DETAIL);
|
||||
auto end=ch_clk::now();
|
||||
std::clog<<"process exited after "<<(end-start).count()*1.0/ch_clk::duration::period::den<<"s.\n\n";
|
||||
auto end=clk::now();
|
||||
std::clog<<"process exited after "<<(end-start).count()*1.0/clk::duration::period::den<<"s.\n\n";
|
||||
} else if (cmd&VM_EXEC) {
|
||||
ctx.run(gen,ld,argv,cmd&VM_DETAIL);
|
||||
}
|
||||
|
|
2
makefile
2
makefile
|
@ -58,7 +58,7 @@ test:nasal
|
|||
@ ./nasal -t test/mandelbrot.nas
|
||||
@ ./nasal -t test/md5.nas
|
||||
@ ./nasal -t -d test/md5compare.nas
|
||||
-@ ./nasal -d test/module_test.nas
|
||||
@ ./nasal -d test/module_test.nas
|
||||
@ ./nasal -e test/nasal_test.nas
|
||||
@ ./nasal -t -d test/occupation.nas 2
|
||||
@ ./nasal -t -d test/pi.nas
|
||||
|
|
|
@ -981,7 +981,7 @@ var builtin_dlcall(var* local,gc& ngc) {
|
|||
return nas_err("dlcall","\"ptr\" is not a valid function pointer");
|
||||
}
|
||||
// arguments' stored place begins at local +2
|
||||
return ((mod)fp.obj().ptr)(local+2,ngc.top-local-2,&ngc);
|
||||
return ((mod)fp.obj().ptr)(local+2,ngc.rctx->top-local-2,&ngc);
|
||||
}
|
||||
|
||||
var builtin_platform(var* local,gc& ngc) {
|
||||
|
@ -1108,19 +1108,19 @@ var builtin_cocreate(var* local,gc& ngc) {
|
|||
}
|
||||
var co=ngc.alloc(vm_co);
|
||||
nas_co& cort=co.co();
|
||||
cort.pc=func.func().entry-1;
|
||||
cort.ctx.pc=func.func().entry-1;
|
||||
|
||||
cort.top[0]=nil;
|
||||
cort.localr=cort.top+1;
|
||||
cort.top=cort.localr+func.func().lsize;
|
||||
cort.localr[0]=func.func().local[0];
|
||||
cort.top[0]=nil; // old upvalr
|
||||
cort.top++;
|
||||
cort.top[0]=var::addr((var*)nullptr); // old localr
|
||||
cort.top++;
|
||||
cort.top[0]=var::ret(0); // old pc, set to zero to make op_ret recognizing this as coroutine function
|
||||
cort.ctx.top[0]=nil;
|
||||
cort.ctx.localr=cort.ctx.top+1;
|
||||
cort.ctx.top=cort.ctx.localr+func.func().lsize;
|
||||
cort.ctx.localr[0]=func.func().local[0];
|
||||
cort.ctx.top[0]=nil; // old upvalr
|
||||
cort.ctx.top++;
|
||||
cort.ctx.top[0]=var::addr((var*)nullptr); // old localr
|
||||
cort.ctx.top++;
|
||||
cort.ctx.top[0]=var::ret(0); // old pc, set to zero to make op_ret recognizing this as coroutine function
|
||||
|
||||
cort.funcr=func; // make sure the coroutine function can use correct upvalues
|
||||
cort.ctx.funcr=func; // make sure the coroutine function can use correct upvalues
|
||||
cort.status=nas_co::suspended;
|
||||
|
||||
return co;
|
||||
|
@ -1145,9 +1145,9 @@ var builtin_coresume(var* local,gc& ngc) {
|
|||
|
||||
// fetch coroutine's stack top and return
|
||||
// so the coroutine's stack top in fact is not changed
|
||||
if (ngc.top[0].type==vm_ret) {
|
||||
if (ngc.rctx->top[0].type==vm_ret) {
|
||||
// when first calling this coroutine, the stack top must be vm_ret
|
||||
return ngc.top[0];
|
||||
return ngc.rctx->top[0];
|
||||
}
|
||||
|
||||
// after first calling the coroutine, each time coroutine.yield triggered
|
||||
|
|
276
nasal_dbg.h
276
nasal_dbg.h
|
@ -6,7 +6,7 @@
|
|||
#include "nasal_vm.h"
|
||||
#include <algorithm>
|
||||
|
||||
class debugger:public vm {
|
||||
class dbg:public vm {
|
||||
private:
|
||||
bool next;
|
||||
usize fsize;
|
||||
|
@ -22,7 +22,7 @@ private:
|
|||
void stepinfo();
|
||||
void interact();
|
||||
public:
|
||||
debugger(error& err):
|
||||
dbg(error& err):
|
||||
next(false),fsize(0),
|
||||
bk_fidx(0),bk_line(0),
|
||||
src(err) {}
|
||||
|
@ -33,7 +33,7 @@ public:
|
|||
);
|
||||
};
|
||||
|
||||
std::vector<string> debugger::parse(const string& cmd) {
|
||||
std::vector<string> dbg::parse(const string& cmd) {
|
||||
std::vector<string> res;
|
||||
usize last=0,pos=cmd.find(" ",0);
|
||||
while(pos!=string::npos) {
|
||||
|
@ -49,7 +49,7 @@ std::vector<string> debugger::parse(const string& cmd) {
|
|||
return res;
|
||||
}
|
||||
|
||||
u16 debugger::fileindex(const string& filename) {
|
||||
u16 dbg::fileindex(const string& filename) {
|
||||
for(u16 i=0;i<fsize;++i) {
|
||||
if (filename==files[i]) {
|
||||
return i;
|
||||
|
@ -58,13 +58,13 @@ u16 debugger::fileindex(const string& filename) {
|
|||
return 65535;
|
||||
}
|
||||
|
||||
void debugger::err() {
|
||||
void dbg::err() {
|
||||
std::cerr
|
||||
<<"incorrect command\n"
|
||||
<<"input \'h\' to get help\n";
|
||||
}
|
||||
|
||||
void debugger::help() {
|
||||
void dbg::help() {
|
||||
std::cout
|
||||
<<"<option>\n"
|
||||
<<"\th, help | get help\n"
|
||||
|
@ -82,7 +82,7 @@ void debugger::help() {
|
|||
<<"\tbk, break | set break point\n";
|
||||
}
|
||||
|
||||
void debugger::callsort(const u64* arr) {
|
||||
void dbg::callsort(const u64* arr) {
|
||||
typedef std::pair<u32,u64> op;
|
||||
std::vector<op> opcall;
|
||||
u64 total=0;
|
||||
|
@ -104,36 +104,38 @@ void debugger::callsort(const u64* arr) {
|
|||
std::clog<<" total : "<<total<<'\n';
|
||||
}
|
||||
|
||||
void debugger::stepinfo() {
|
||||
u32 line=bytecode[pc].line==0?0:bytecode[pc].line-1;
|
||||
void dbg::stepinfo() {
|
||||
u32 line=bytecode[ctx.pc].line==0?0:bytecode[ctx.pc].line-1;
|
||||
u32 begin=(line>>3)==0?0:((line>>3)<<3);
|
||||
u32 end=(1+(line>>3))<<3;
|
||||
src.load(files[bytecode[pc].fidx]);
|
||||
src.load(files[bytecode[ctx.pc].fidx]);
|
||||
std::cout<<"\nsource code:\n";
|
||||
for(u32 i=begin;i<end && i<src.size();++i) {
|
||||
std::cout<<(i==line?back_white:reset)<<(i==line?"--> ":" ")<<src[i]<<reset<<"\n";
|
||||
}
|
||||
std::cout<<"next bytecode:\n";
|
||||
begin=(pc>>3)==0?0:((pc>>3)<<3);
|
||||
end=(1+(pc>>3))<<3;
|
||||
|
||||
begin=(ctx.pc>>3)==0?0:((ctx.pc>>3)<<3);
|
||||
end=(1+(ctx.pc>>3))<<3;
|
||||
codestream::set(cnum,cstr,files);
|
||||
std::cout<<"next bytecode:\n";
|
||||
for(u32 i=begin;i<end && bytecode[i].op!=op_exit;++i) {
|
||||
std::cout
|
||||
<<(i==pc?back_white:reset)<<(i==pc?"--> ":" ")
|
||||
<<(i==ctx.pc?back_white:reset)
|
||||
<<(i==ctx.pc?"--> ":" ")
|
||||
<<codestream(bytecode[i],i)
|
||||
<<reset<<"\n";
|
||||
}
|
||||
stackinfo(10);
|
||||
}
|
||||
|
||||
void debugger::interact() {
|
||||
void dbg::interact() {
|
||||
// special operand
|
||||
if (bytecode[pc].op==op_exit) {
|
||||
if (bytecode[ctx.pc].op==op_exit) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
(bytecode[pc].fidx!=bk_fidx || bytecode[pc].line!=bk_line) && // break point
|
||||
(bytecode[ctx.pc].fidx!=bk_fidx || bytecode[ctx.pc].line!=bk_line) && // break point
|
||||
!next // next step
|
||||
) {
|
||||
return;
|
||||
|
@ -146,7 +148,9 @@ void debugger::interact() {
|
|||
std::cout<<">> ";
|
||||
std::getline(std::cin,cmd);
|
||||
auto res=parse(cmd);
|
||||
if (res.size()==1) {
|
||||
if (res.size()==0) {
|
||||
stepinfo();
|
||||
} else if (res.size()==1) {
|
||||
if (res[0]=="h" || res[0]=="help") {
|
||||
help();
|
||||
} else if (res[0]=="bt" || res[0]=="backtrace") {
|
||||
|
@ -193,7 +197,7 @@ void debugger::interact() {
|
|||
}
|
||||
}
|
||||
|
||||
void debugger::run(
|
||||
void dbg::run(
|
||||
const codegen& gen,
|
||||
const linker& linker,
|
||||
const std::vector<string>& argv)
|
||||
|
@ -202,205 +206,71 @@ void debugger::run(
|
|||
fsize=linker.filelist().size();
|
||||
init(gen.strs(),gen.nums(),gen.codes(),linker.filelist(),argv);
|
||||
u64 count[op_ret+1]={0};
|
||||
#ifndef _MSC_VER
|
||||
const void* oprs[]={
|
||||
&&vmexit, &&intg, &&intl, &&loadg,
|
||||
&&loadl, &&loadu, &&pnum, &&pnil,
|
||||
&&pstr, &&newv, &&newh, &&newf,
|
||||
&&happ, &¶, &&deft, &&dyn,
|
||||
&&lnot, &&usub, &&bnot, &&btor,
|
||||
&&btxor, &&btand, &&add, &&sub,
|
||||
&&mul, &&div, &&lnk, &&addc,
|
||||
&&subc, &&mulc, &&divc, &&lnkc,
|
||||
&&addeq, &&subeq, &&muleq, &&diveq,
|
||||
&&lnkeq, &&bandeq, &&boreq, &&bxoreq,
|
||||
&&addeqc, &&subeqc, &&muleqc, &&diveqc,
|
||||
&&lnkeqc, &&addecp, &&subecp, &&mulecp,
|
||||
&&divecp, &&lnkecp, &&meq, &&eq,
|
||||
&&neq, &&less, &&leq, &&grt,
|
||||
&&geq, &&lessc, &&leqc, &&grtc,
|
||||
&&geqc, &&pop, &&jmp, &&jt,
|
||||
&&jf, &&cnt, &&findex, &&feach,
|
||||
&&callg, &&calll, &&upval, &&callv,
|
||||
&&callvi, &&callh, &&callfv, &&callfh,
|
||||
&&callb, &&slcbeg, &&slcend, &&slc,
|
||||
&&slc2, &&mcallg, &&mcalll, &&mupval,
|
||||
&&mcallv, &&mcallh, &&ret
|
||||
};
|
||||
std::vector<const void*> code;
|
||||
for(auto& i:gen.codes()) {
|
||||
code.push_back(oprs[i.op]);
|
||||
imm.push_back(i.num);
|
||||
}
|
||||
// goto the first operand
|
||||
goto *code[pc];
|
||||
#else
|
||||
typedef void (debugger::*nafunc)();
|
||||
typedef void (dbg::*nafunc)();
|
||||
const nafunc oprs[]={
|
||||
nullptr, &debugger::o_intg,
|
||||
&debugger::o_intl, &debugger::o_loadg,
|
||||
&debugger::o_loadl, &debugger::o_loadu,
|
||||
&debugger::o_pnum, &debugger::o_pnil,
|
||||
&debugger::o_pstr, &debugger::o_newv,
|
||||
&debugger::o_newh, &debugger::o_newf,
|
||||
&debugger::o_happ, &debugger::o_para,
|
||||
&debugger::o_deft, &debugger::o_dyn,
|
||||
&debugger::o_lnot, &debugger::o_usub,
|
||||
&debugger::o_bnot, &debugger::o_btor,
|
||||
&debugger::o_btxor, &debugger::o_btand,
|
||||
&debugger::o_add, &debugger::o_sub,
|
||||
&debugger::o_mul, &debugger::o_div,
|
||||
&debugger::o_lnk, &debugger::o_addc,
|
||||
&debugger::o_subc, &debugger::o_mulc,
|
||||
&debugger::o_divc, &debugger::o_lnkc,
|
||||
&debugger::o_addeq, &debugger::o_subeq,
|
||||
&debugger::o_muleq, &debugger::o_diveq,
|
||||
&debugger::o_lnkeq, &debugger::o_bandeq,
|
||||
&debugger::o_boreq, &debugger::o_bxoreq,
|
||||
&debugger::o_addeqc, &debugger::o_subeqc,
|
||||
&debugger::o_muleqc, &debugger::o_diveqc,
|
||||
&debugger::o_lnkeqc, &debugger::o_addecp,
|
||||
&debugger::o_subecp, &debugger::o_mulecp,
|
||||
&debugger::o_divecp, &debugger::o_lnkecp,
|
||||
&debugger::o_meq, &debugger::o_eq,
|
||||
&debugger::o_neq, &debugger::o_less,
|
||||
&debugger::o_leq, &debugger::o_grt,
|
||||
&debugger::o_geq, &debugger::o_lessc,
|
||||
&debugger::o_leqc, &debugger::o_grtc,
|
||||
&debugger::o_geqc, &debugger::o_pop,
|
||||
&debugger::o_jmp, &debugger::o_jt,
|
||||
&debugger::o_jf, &debugger::o_cnt,
|
||||
&debugger::o_findex, &debugger::o_feach,
|
||||
&debugger::o_callg, &debugger::o_calll,
|
||||
&debugger::o_upval, &debugger::o_callv,
|
||||
&debugger::o_callvi, &debugger::o_callh,
|
||||
&debugger::o_callfv, &debugger::o_callfh,
|
||||
&debugger::o_callb, &debugger::o_slcbeg,
|
||||
&debugger::o_slcend, &debugger::o_slc,
|
||||
&debugger::o_slc2, &debugger::o_mcallg,
|
||||
&debugger::o_mcalll, &debugger::o_mupval,
|
||||
&debugger::o_mcallv, &debugger::o_mcallh,
|
||||
&debugger::o_ret
|
||||
nullptr, &dbg::o_intg,
|
||||
&dbg::o_intl, &dbg::o_loadg,
|
||||
&dbg::o_loadl, &dbg::o_loadu,
|
||||
&dbg::o_pnum, &dbg::o_pnil,
|
||||
&dbg::o_pstr, &dbg::o_newv,
|
||||
&dbg::o_newh, &dbg::o_newf,
|
||||
&dbg::o_happ, &dbg::o_para,
|
||||
&dbg::o_deft, &dbg::o_dyn,
|
||||
&dbg::o_lnot, &dbg::o_usub,
|
||||
&dbg::o_bnot, &dbg::o_btor,
|
||||
&dbg::o_btxor, &dbg::o_btand,
|
||||
&dbg::o_add, &dbg::o_sub,
|
||||
&dbg::o_mul, &dbg::o_div,
|
||||
&dbg::o_lnk, &dbg::o_addc,
|
||||
&dbg::o_subc, &dbg::o_mulc,
|
||||
&dbg::o_divc, &dbg::o_lnkc,
|
||||
&dbg::o_addeq, &dbg::o_subeq,
|
||||
&dbg::o_muleq, &dbg::o_diveq,
|
||||
&dbg::o_lnkeq, &dbg::o_bandeq,
|
||||
&dbg::o_boreq, &dbg::o_bxoreq,
|
||||
&dbg::o_addeqc, &dbg::o_subeqc,
|
||||
&dbg::o_muleqc, &dbg::o_diveqc,
|
||||
&dbg::o_lnkeqc, &dbg::o_addecp,
|
||||
&dbg::o_subecp, &dbg::o_mulecp,
|
||||
&dbg::o_divecp, &dbg::o_lnkecp,
|
||||
&dbg::o_meq, &dbg::o_eq,
|
||||
&dbg::o_neq, &dbg::o_less,
|
||||
&dbg::o_leq, &dbg::o_grt,
|
||||
&dbg::o_geq, &dbg::o_lessc,
|
||||
&dbg::o_leqc, &dbg::o_grtc,
|
||||
&dbg::o_geqc, &dbg::o_pop,
|
||||
&dbg::o_jmp, &dbg::o_jt,
|
||||
&dbg::o_jf, &dbg::o_cnt,
|
||||
&dbg::o_findex, &dbg::o_feach,
|
||||
&dbg::o_callg, &dbg::o_calll,
|
||||
&dbg::o_upval, &dbg::o_callv,
|
||||
&dbg::o_callvi, &dbg::o_callh,
|
||||
&dbg::o_callfv, &dbg::o_callfh,
|
||||
&dbg::o_callb, &dbg::o_slcbeg,
|
||||
&dbg::o_slcend, &dbg::o_slc,
|
||||
&dbg::o_slc2, &dbg::o_mcallg,
|
||||
&dbg::o_mcalll, &dbg::o_mupval,
|
||||
&dbg::o_mcallv, &dbg::o_mcallh,
|
||||
&dbg::o_ret
|
||||
};
|
||||
std::vector<u32> code;
|
||||
for(auto& i:gen.codes()) {
|
||||
code.push_back(i.op);
|
||||
imm.push_back(i.num);
|
||||
}
|
||||
while(oprs[code[pc]]) {
|
||||
while(oprs[code[ctx.pc]]) {
|
||||
interact();
|
||||
++count[code[pc]];
|
||||
(this->*oprs[code[pc]])();
|
||||
if (top>=canary) {
|
||||
++count[code[ctx.pc]];
|
||||
(this->*oprs[code[ctx.pc]])();
|
||||
if (ctx.top>=ctx.canary) {
|
||||
die("stack overflow");
|
||||
}
|
||||
++pc;
|
||||
++ctx.pc;
|
||||
}
|
||||
#endif
|
||||
|
||||
vmexit:
|
||||
callsort(count);
|
||||
ngc.info();
|
||||
ngc.clear();
|
||||
imm.clear();
|
||||
return;
|
||||
#ifndef _MSC_VER
|
||||
#define dbg(op,num) {\
|
||||
interact();\
|
||||
op();\
|
||||
++count[num];\
|
||||
if (top<canary) {\
|
||||
goto *code[++pc];\
|
||||
}\
|
||||
die("stack overflow");\
|
||||
goto *code[++pc];\
|
||||
}
|
||||
|
||||
intg: dbg(o_intg ,op_intg );
|
||||
intl: dbg(o_intl ,op_intl );
|
||||
loadg: dbg(o_loadg ,op_loadg );
|
||||
loadl: dbg(o_loadl ,op_loadl );
|
||||
loadu: dbg(o_loadu ,op_loadu );
|
||||
pnum: dbg(o_pnum ,op_pnum );
|
||||
pnil: dbg(o_pnil ,op_pnil );
|
||||
pstr: dbg(o_pstr ,op_pstr );
|
||||
newv: dbg(o_newv ,op_newv );
|
||||
newh: dbg(o_newh ,op_newh );
|
||||
newf: dbg(o_newf ,op_newf );
|
||||
happ: dbg(o_happ ,op_happ );
|
||||
para: dbg(o_para ,op_para );
|
||||
deft: dbg(o_deft ,op_deft );
|
||||
dyn: dbg(o_dyn ,op_dyn );
|
||||
lnot: dbg(o_lnot ,op_lnot );
|
||||
usub: dbg(o_usub ,op_usub );
|
||||
bnot: dbg(o_bnot ,op_bnot );
|
||||
btor: dbg(o_btor ,op_btor );
|
||||
btxor: dbg(o_btxor ,op_btxor );
|
||||
btand: dbg(o_btand ,op_btand );
|
||||
add: dbg(o_add ,op_add );
|
||||
sub: dbg(o_sub ,op_sub );
|
||||
mul: dbg(o_mul ,op_mul );
|
||||
div: dbg(o_div ,op_div );
|
||||
lnk: dbg(o_lnk ,op_lnk );
|
||||
addc: dbg(o_addc ,op_addc );
|
||||
subc: dbg(o_subc ,op_subc );
|
||||
mulc: dbg(o_mulc ,op_mulc );
|
||||
divc: dbg(o_divc ,op_divc );
|
||||
lnkc: dbg(o_lnkc ,op_lnkc );
|
||||
addeq: dbg(o_addeq ,op_addeq );
|
||||
subeq: dbg(o_subeq ,op_subeq );
|
||||
muleq: dbg(o_muleq ,op_muleq );
|
||||
diveq: dbg(o_diveq ,op_diveq );
|
||||
lnkeq: dbg(o_lnkeq ,op_lnkeq );
|
||||
bandeq: dbg(o_bandeq,op_btandeq);
|
||||
boreq: dbg(o_boreq, op_btoreq);
|
||||
bxoreq: dbg(o_bxoreq,op_btxoreq);
|
||||
addeqc: dbg(o_addeqc,op_addeqc);
|
||||
subeqc: dbg(o_subeqc,op_subeqc);
|
||||
muleqc: dbg(o_muleqc,op_muleqc);
|
||||
diveqc: dbg(o_diveqc,op_diveqc);
|
||||
lnkeqc: dbg(o_lnkeqc,op_lnkeqc);
|
||||
addecp: dbg(o_addecp,op_addecp);
|
||||
subecp: dbg(o_subecp,op_subecp);
|
||||
mulecp: dbg(o_mulecp,op_mulecp);
|
||||
divecp: dbg(o_divecp,op_divecp);
|
||||
lnkecp: dbg(o_lnkecp,op_lnkecp);
|
||||
meq: dbg(o_meq ,op_meq );
|
||||
eq: dbg(o_eq ,op_eq );
|
||||
neq: dbg(o_neq ,op_neq );
|
||||
less: dbg(o_less ,op_less );
|
||||
leq: dbg(o_leq ,op_leq );
|
||||
grt: dbg(o_grt ,op_grt );
|
||||
geq: dbg(o_geq ,op_geq );
|
||||
lessc: dbg(o_lessc ,op_lessc );
|
||||
leqc: dbg(o_leqc ,op_leqc );
|
||||
grtc: dbg(o_grtc ,op_grtc );
|
||||
geqc: dbg(o_geqc ,op_geqc );
|
||||
pop: dbg(o_pop ,op_pop );
|
||||
jmp: dbg(o_jmp ,op_jmp );
|
||||
jt: dbg(o_jt ,op_jt );
|
||||
jf: dbg(o_jf ,op_jf );
|
||||
cnt: dbg(o_cnt ,op_cnt );
|
||||
findex: dbg(o_findex,op_findex);
|
||||
feach: dbg(o_feach ,op_feach );
|
||||
callg: dbg(o_callg ,op_callg );
|
||||
calll: dbg(o_calll ,op_calll );
|
||||
upval: dbg(o_upval ,op_upval );
|
||||
callv: dbg(o_callv ,op_callv );
|
||||
callvi: dbg(o_callvi,op_callvi);
|
||||
callh: dbg(o_callh ,op_callh );
|
||||
callfv: dbg(o_callfv,op_callfv);
|
||||
callfh: dbg(o_callfh,op_callfh);
|
||||
callb: dbg(o_callb ,op_callb );
|
||||
slcbeg: dbg(o_slcbeg,op_slcbeg);
|
||||
slcend: dbg(o_slcend,op_slcend);
|
||||
slc: dbg(o_slc ,op_slc );
|
||||
slc2: dbg(o_slc2 ,op_slc2 );
|
||||
mcallg: dbg(o_mcallg,op_mcallg);
|
||||
mcalll: dbg(o_mcalll,op_mcalll);
|
||||
mupval: dbg(o_mupval,op_mupval);
|
||||
mcallv: dbg(o_mcallv,op_mcallv);
|
||||
mcallh: dbg(o_mcallh,op_mcallh);
|
||||
ret: dbg(o_ret ,op_ret );
|
||||
#endif
|
||||
}
|
||||
|
|
124
nasal_gc.h
124
nasal_gc.h
|
@ -196,6 +196,17 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
struct context {
|
||||
u32 pc;
|
||||
var* localr;
|
||||
var* memr;
|
||||
var funcr;
|
||||
var upvalr;
|
||||
var* canary;
|
||||
var* stack;
|
||||
var* top;
|
||||
};
|
||||
|
||||
struct nas_co {
|
||||
enum costat:u32{
|
||||
suspended,
|
||||
|
@ -204,15 +215,8 @@ struct nas_co {
|
|||
};
|
||||
|
||||
// calculation stack
|
||||
var stack[STACK_DEPTH];
|
||||
|
||||
u32 pc;
|
||||
var* top;
|
||||
var* canary=stack+STACK_DEPTH-1;
|
||||
var* localr;
|
||||
var* memr;
|
||||
var funcr;
|
||||
var upvalr;
|
||||
var stack[STACK_DEPTH];
|
||||
context ctx;
|
||||
|
||||
u32 status;
|
||||
nas_co() {clear();}
|
||||
|
@ -220,13 +224,16 @@ struct nas_co {
|
|||
for(u32 i=0;i<STACK_DEPTH;++i) {
|
||||
stack[i]=var::nil();
|
||||
}
|
||||
pc=0;
|
||||
localr=nullptr;
|
||||
memr=nullptr;
|
||||
top=stack;
|
||||
ctx.pc=0;
|
||||
ctx.localr=nullptr;
|
||||
ctx.memr=nullptr;
|
||||
ctx.canary=stack+STACK_DEPTH-1;
|
||||
ctx.top=stack;
|
||||
ctx.funcr=var::nil();
|
||||
ctx.upvalr=var::nil();
|
||||
ctx.stack=stack;
|
||||
|
||||
status=nas_co::suspended;
|
||||
funcr=var::nil();
|
||||
upvalr=var::nil();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -489,30 +496,14 @@ const var nil =var::nil();
|
|||
|
||||
struct gc {
|
||||
/* main context */
|
||||
struct {
|
||||
u32 pc;
|
||||
var* top;
|
||||
var* localr;
|
||||
var* memr;
|
||||
var funcr;
|
||||
var upvalr;
|
||||
var* canary;
|
||||
var* stack;
|
||||
} mctx;
|
||||
context mctx;
|
||||
|
||||
/* runtime context */
|
||||
u32& pc; // program counter
|
||||
var*& localr; // local scope register
|
||||
var*& memr; // used for mem_call
|
||||
var& funcr; // function register
|
||||
var& upvalr; // upvalue register
|
||||
var*& canary; // avoid stackoverflow
|
||||
var*& top; // stack top
|
||||
var* stack; // stack pointer
|
||||
nas_co* cort; // running coroutine
|
||||
context* rctx;
|
||||
nas_co* cort=nullptr; // running coroutine
|
||||
|
||||
/* native function used */
|
||||
var temp; // temporary place used in builtin/module functions
|
||||
var temp=nil; // temporary place used in builtin/module functions
|
||||
|
||||
/* constants and memory pool */
|
||||
std::vector<var> strs; // reserved address for const vm_str
|
||||
|
@ -535,13 +526,9 @@ struct gc {
|
|||
u64 size[gc_tsize];
|
||||
u64 gcnt[gc_tsize];
|
||||
u64 acnt[gc_tsize];
|
||||
i64 worktime;
|
||||
i64 worktime=0;
|
||||
|
||||
gc(u32& _pc, var*& _localr, var*& _memr, var& _funcr,
|
||||
var& _upvalr, var*& _canary, var*& _top, var* _stk):
|
||||
pc(_pc),localr(_localr),memr(_memr),funcr(_funcr),upvalr(_upvalr),
|
||||
canary(_canary),top(_top),stack(_stk),cort(nullptr),temp(nil),
|
||||
worktime(0) {}
|
||||
gc(context* _ctx): rctx(_ctx) {}
|
||||
void mark();
|
||||
void sweep();
|
||||
void extend(u8);
|
||||
|
@ -563,11 +550,11 @@ void gc::mark() {
|
|||
// scan main process stack when coroutine ptr is null
|
||||
// this scan process must execute because when running coroutine,
|
||||
// the nas_co related to it will not update it's context(like `top`) until the coroutine suspends or exits.
|
||||
for(var* i=stack;i<=top;++i) {
|
||||
for(var* i=rctx->stack;i<=rctx->top;++i) {
|
||||
bfs.push_back(*i);
|
||||
}
|
||||
bfs.push_back(funcr);
|
||||
bfs.push_back(upvalr);
|
||||
bfs.push_back(rctx->funcr);
|
||||
bfs.push_back(rctx->upvalr);
|
||||
bfs.push_back(temp);
|
||||
|
||||
// if coroutine is running, scan main process stack from mctx
|
||||
|
@ -611,9 +598,9 @@ void gc::mark() {
|
|||
}
|
||||
break;
|
||||
case vm_co:
|
||||
bfs.push_back(tmp.co().funcr);
|
||||
bfs.push_back(tmp.co().upvalr);
|
||||
for(var* i=tmp.co().stack;i<=tmp.co().top;++i) {
|
||||
bfs.push_back(tmp.co().ctx.funcr);
|
||||
bfs.push_back(tmp.co().ctx.upvalr);
|
||||
for(var* i=tmp.co().stack;i<=tmp.co().ctx.top;++i) {
|
||||
bfs.push_back(*i);
|
||||
}
|
||||
break;
|
||||
|
@ -653,7 +640,7 @@ void gc::extend(u8 type) {
|
|||
|
||||
void gc::init(const std::vector<string>& s,const std::vector<string>& argv) {
|
||||
// initialize function register
|
||||
funcr=nil;
|
||||
rctx->funcr=nil;
|
||||
worktime=0;
|
||||
|
||||
// initialize counters
|
||||
|
@ -762,29 +749,15 @@ var gc::newstr(const string& buff) {
|
|||
return s;
|
||||
}
|
||||
|
||||
void gc::ctxchg(nas_co& ctx) {
|
||||
void gc::ctxchg(nas_co& co) {
|
||||
// store running state to main context
|
||||
mctx.pc=pc;
|
||||
mctx.top=top;
|
||||
mctx.localr=localr;
|
||||
mctx.memr=memr;
|
||||
mctx.funcr=funcr;
|
||||
mctx.upvalr=upvalr;
|
||||
mctx.canary=canary;
|
||||
mctx.stack=stack;
|
||||
mctx=*rctx;
|
||||
|
||||
// restore coroutine context state
|
||||
pc=ctx.pc;
|
||||
top=ctx.top;
|
||||
localr=ctx.localr;
|
||||
memr=ctx.memr;
|
||||
funcr=ctx.funcr;
|
||||
upvalr=ctx.upvalr;
|
||||
canary=ctx.canary;
|
||||
stack=ctx.stack;
|
||||
*rctx=co.ctx;
|
||||
|
||||
// set coroutine pointer
|
||||
cort=&ctx;
|
||||
cort=&co;
|
||||
|
||||
// set coroutine state to running
|
||||
cort->status=nas_co::running;
|
||||
|
@ -792,26 +765,13 @@ void gc::ctxchg(nas_co& ctx) {
|
|||
|
||||
void gc::ctxreserve() {
|
||||
// pc=0 means this coroutine is finished
|
||||
cort->status=pc? nas_co::suspended:nas_co::dead;
|
||||
cort->status=rctx->pc? nas_co::suspended:nas_co::dead;
|
||||
|
||||
// store running state to coroutine
|
||||
cort->pc=pc;
|
||||
cort->localr=localr;
|
||||
cort->memr=memr;
|
||||
cort->funcr=funcr;
|
||||
cort->upvalr=upvalr;
|
||||
cort->canary=canary;
|
||||
cort->top=top;
|
||||
cort->ctx=*rctx;
|
||||
|
||||
// restore main context state
|
||||
pc=mctx.pc;
|
||||
localr=mctx.localr;
|
||||
memr=mctx.memr;
|
||||
funcr=mctx.funcr;
|
||||
upvalr=mctx.upvalr;
|
||||
canary=mctx.canary;
|
||||
top=mctx.top;
|
||||
stack=mctx.stack;
|
||||
*rctx=mctx;
|
||||
|
||||
// set coroutine pointer to nullptr
|
||||
cort=nullptr;
|
||||
|
|
|
@ -141,11 +141,6 @@ public:
|
|||
codestream(const opcode& c,const u32 i):code(c),index(i) {}
|
||||
static void set(const f64*,const string*,const string*);
|
||||
void dump(std::ostream&) const;
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& out,const codestream& ins) {
|
||||
ins.dump(out);
|
||||
return out;
|
||||
}
|
||||
};
|
||||
|
||||
const f64* codestream::nums=nullptr;
|
||||
|
@ -172,25 +167,19 @@ void codestream::dump(std::ostream& out) const {
|
|||
case op_addeq: case op_subeq: case op_muleq: case op_diveq:
|
||||
case op_lnkeq: case op_meq: case op_btandeq: case op_btoreq:
|
||||
case op_btxoreq:
|
||||
out<<std::hex<<"0x"<<num<<std::dec
|
||||
<<" sp-"<<num;break;
|
||||
out<<std::hex<<"0x"<<num<<std::dec<<" sp-"<<num;break;
|
||||
case op_addeqc:case op_subeqc: case op_muleqc:case op_diveqc:
|
||||
out<<std::hex<<"0x"<<num<<std::dec
|
||||
<<" ("<<nums[num]<<")";break;
|
||||
out<<std::hex<<"0x"<<num<<std::dec<<" ("<<nums[num]<<")";break;
|
||||
case op_lnkeqc:
|
||||
out<<std::hex<<"0x"<<num<<std::dec<<" (\""
|
||||
<<rawstr(strs[num],16)<<"\")";break;
|
||||
out<<std::hex<<"0x"<<num<<std::dec<<" ("<<rawstr(strs[num],16)<<")";break;
|
||||
case op_addecp:case op_subecp:case op_mulecp:case op_divecp:
|
||||
out<<std::hex<<"0x"<<num<<std::dec
|
||||
<<" ("<<nums[num]<<") sp-1";break;
|
||||
out<<std::hex<<"0x"<<num<<std::dec<<" ("<<nums[num]<<") sp-1";break;
|
||||
case op_lnkecp:
|
||||
out<<std::hex<<"0x"<<num<<std::dec<<" (\""
|
||||
<<rawstr(strs[num],16)<<"\") sp-1";break;
|
||||
out<<std::hex<<"0x"<<num<<std::dec<<" ("<<rawstr(strs[num],16)<<") sp-1";break;
|
||||
case op_addc: case op_subc: case op_mulc: case op_divc:
|
||||
case op_lessc: case op_leqc: case op_grtc: case op_geqc:
|
||||
case op_pnum:
|
||||
out<<std::hex<<"0x"<<num<<std::dec<<" ("
|
||||
<<nums[num]<<")";break;
|
||||
out<<std::hex<<"0x"<<num<<std::dec<<" ("<<nums[num]<<")";break;
|
||||
case op_callvi:case op_newv: case op_callfv:
|
||||
case op_intg: case op_intl:
|
||||
case op_findex:case op_feach:
|
||||
|
@ -208,8 +197,7 @@ void codestream::dump(std::ostream& out) const {
|
|||
case op_lnkc:
|
||||
case op_callh: case op_mcallh:
|
||||
case op_para: case op_deft: case op_dyn:
|
||||
out<<std::hex<<"0x"<<num<<std::dec
|
||||
<<" (\""<<rawstr(strs[num],16)<<"\")";break;
|
||||
out<<std::hex<<"0x"<<num<<std::dec<<" ("<<rawstr(strs[num],16)<<")";break;
|
||||
default:
|
||||
if (files) {
|
||||
out<<std::hex<<"0x"<<num<<std::dec;
|
||||
|
@ -217,6 +205,11 @@ void codestream::dump(std::ostream& out) const {
|
|||
break;
|
||||
}
|
||||
if (files) {
|
||||
out<<" ("<<files[code.fidx]<<":"<<code.line<<")";
|
||||
out<<"("<<files[code.fidx]<<":"<<code.line<<")";
|
||||
}
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& out,const codestream& ins) {
|
||||
ins.dump(out);
|
||||
return out;
|
||||
}
|
|
@ -52,7 +52,7 @@ private:
|
|||
const token* toks;
|
||||
ast root;
|
||||
error& err;
|
||||
std::unordered_map<tok,string> tokname {
|
||||
const std::unordered_map<tok,string> tokname {
|
||||
{tok::rfor ,"for" },
|
||||
{tok::forindex,"forindex"},
|
||||
{tok::foreach ,"foreach" },
|
||||
|
@ -204,7 +204,7 @@ void parse::match(tok type,const char* info) {
|
|||
case tok::num:die(thisspan,"expected number"); break;
|
||||
case tok::str:die(thisspan,"expected string"); break;
|
||||
case tok::id: die(thisspan,"expected identifier");break;
|
||||
default: die(thisspan,"expected '"+tokname[type]+"'"); break;
|
||||
default: die(thisspan,"expected '"+tokname.at(type)+"'"); break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
|
538
nasal_vm.h
538
nasal_vm.h
File diff suppressed because it is too large
Load Diff
|
@ -41,7 +41,7 @@ var run=func(width,height){
|
|||
forindex(var j;map[i])
|
||||
map[i][j]=rand()<0.45?'O':'.';
|
||||
|
||||
for(var r=0;r<200;r+=1){
|
||||
for(var r=0;r<100;r+=1){
|
||||
prt(map);
|
||||
for(var i=0;i<height;i+=1)
|
||||
for(var j=0;j<width;j+=1){
|
||||
|
|
Loading…
Reference in New Issue