merge runtime regs into struct context

This commit is contained in:
ValKmjolnir 2023-04-08 00:18:58 +08:00
parent 3852ce23a3
commit 5519dc7a29
10 changed files with 419 additions and 602 deletions

View File

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

View File

@ -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);
}

View File

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

View File

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

View File

@ -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, &&para, &&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
}

View File

@ -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;

View File

@ -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;
}

View File

@ -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;
}

File diff suppressed because it is too large Load Diff

View File

@ -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){