delete lstk&fstk, store local address and function on stack and in vm registers
This commit is contained in:
parent
99f595e16f
commit
61666d275d
1
makefile
1
makefile
|
@ -27,6 +27,7 @@ test:nasal
|
||||||
@ ./nasal -op -e test/nasal_test.nas
|
@ ./nasal -op -e test/nasal_test.nas
|
||||||
@ ./nasal -op -t -d test/pi.nas
|
@ ./nasal -op -t -d test/pi.nas
|
||||||
@ ./nasal -op -t -d test/prime.nas
|
@ ./nasal -op -t -d test/prime.nas
|
||||||
|
@ ./nasal -op -t -d test/props_sim.nas
|
||||||
@ ./nasal -op -t -d test/quick_sort.nas
|
@ ./nasal -op -t -d test/quick_sort.nas
|
||||||
@ ./nasal -op -e test/scalar.nas
|
@ ./nasal -op -e test/scalar.nas
|
||||||
@ ./nasal -op -e test/trait.nas
|
@ ./nasal -op -e test/trait.nas
|
||||||
|
|
|
@ -96,7 +96,7 @@ nas_native(builtin_gc);
|
||||||
nasal_ref builtin_err(const char* func_name,std::string info)
|
nasal_ref builtin_err(const char* func_name,std::string info)
|
||||||
{
|
{
|
||||||
std::cerr<<"[vm] "<<func_name<<": "<<info<<".\n";
|
std::cerr<<"[vm] "<<func_name<<": "<<info<<".\n";
|
||||||
return {vm_none,nullptr};
|
return {vm_none};
|
||||||
}
|
}
|
||||||
|
|
||||||
// register builtin function's name and it's address here in this table below
|
// register builtin function's name and it's address here in this table below
|
||||||
|
|
|
@ -68,6 +68,7 @@ void nasal_dbg::help()
|
||||||
<<"\th, help | get help\n"
|
<<"\th, help | get help\n"
|
||||||
<<"\tbt, backtrace | get function call trace\n"
|
<<"\tbt, backtrace | get function call trace\n"
|
||||||
<<"\tc, continue | run program until break point or exit\n"
|
<<"\tc, continue | run program until break point or exit\n"
|
||||||
|
<<"\tf, file | see all the compiled files\n"
|
||||||
<<"\tg, global | see global values\n"
|
<<"\tg, global | see global values\n"
|
||||||
<<"\tl, local | see local values\n"
|
<<"\tl, local | see local values\n"
|
||||||
<<"\tu, upval | see upvalue\n"
|
<<"\tu, upval | see upvalue\n"
|
||||||
|
@ -129,6 +130,9 @@ void nasal_dbg::interact()
|
||||||
traceback();
|
traceback();
|
||||||
else if(res[0]=="c" || res[0]=="continue")
|
else if(res[0]=="c" || res[0]=="continue")
|
||||||
return;
|
return;
|
||||||
|
else if(res[0]=="f" || res[0]=="file")
|
||||||
|
for(size_t i=0;i<files_size;++i)
|
||||||
|
printf("[%zu] %s\n",i,files[i].c_str());
|
||||||
else if(res[0]=="g" || res[0]=="global")
|
else if(res[0]=="g" || res[0]=="global")
|
||||||
global_state();
|
global_state();
|
||||||
else if(res[0]=="l" || res[0]=="local")
|
else if(res[0]=="l" || res[0]=="local")
|
||||||
|
|
26
nasal_gc.h
26
nasal_gc.h
|
@ -6,6 +6,7 @@ enum nasal_type
|
||||||
/* none-gc object */
|
/* none-gc object */
|
||||||
vm_none=0,
|
vm_none=0,
|
||||||
vm_cnt,
|
vm_cnt,
|
||||||
|
vm_addr,
|
||||||
vm_ret,
|
vm_ret,
|
||||||
vm_nil,
|
vm_nil,
|
||||||
vm_num,
|
vm_num,
|
||||||
|
@ -26,6 +27,7 @@ const uint32_t increment[vm_type_size]=
|
||||||
/* none-gc object */
|
/* none-gc object */
|
||||||
0, // vm_none, error type
|
0, // vm_none, error type
|
||||||
0, // vm_count, used in foreach/forindex
|
0, // vm_count, used in foreach/forindex
|
||||||
|
0, // vm_addr, used to store local address pointers
|
||||||
0, // vm_ret, used to store call-return address
|
0, // vm_ret, used to store call-return address
|
||||||
0, // vm_nil
|
0, // vm_nil
|
||||||
0, // vm_num
|
0, // vm_num
|
||||||
|
@ -53,14 +55,22 @@ struct nasal_ref
|
||||||
uint32_t ret;
|
uint32_t ret;
|
||||||
int64_t cnt;
|
int64_t cnt;
|
||||||
double num;
|
double num;
|
||||||
|
nasal_ref* addr;
|
||||||
nasal_val* gcobj;
|
nasal_val* gcobj;
|
||||||
}value;
|
}value;
|
||||||
|
|
||||||
|
// vm_none/vm_nil
|
||||||
nasal_ref(const uint8_t t=vm_none):type(t){}
|
nasal_ref(const uint8_t t=vm_none):type(t){}
|
||||||
|
// vm_ret
|
||||||
nasal_ref(const uint8_t t,const uint32_t n):type(t){value.ret=n;}
|
nasal_ref(const uint8_t t,const uint32_t n):type(t){value.ret=n;}
|
||||||
|
// vm_cnt
|
||||||
nasal_ref(const uint8_t t,const int64_t n):type(t){value.cnt=n;}
|
nasal_ref(const uint8_t t,const int64_t n):type(t){value.cnt=n;}
|
||||||
|
// vm_num
|
||||||
nasal_ref(const uint8_t t,const double n):type(t){value.num=n;}
|
nasal_ref(const uint8_t t,const double n):type(t){value.num=n;}
|
||||||
|
// vm_str/vm_func/vm_vec/vm_hash/vm_upval/vm_obj
|
||||||
nasal_ref(const uint8_t t,nasal_val* n):type(t){value.gcobj=n;}
|
nasal_ref(const uint8_t t,nasal_val* n):type(t){value.gcobj=n;}
|
||||||
|
// vm_addr
|
||||||
|
nasal_ref(const uint8_t t,nasal_ref* n):type(t){value.addr=n;}
|
||||||
nasal_ref(const nasal_ref& nr):type(nr.type),value(nr.value){}
|
nasal_ref(const nasal_ref& nr):type(nr.type),value(nr.value){}
|
||||||
nasal_ref& operator=(const nasal_ref& nr)
|
nasal_ref& operator=(const nasal_ref& nr)
|
||||||
{
|
{
|
||||||
|
@ -74,6 +84,7 @@ struct nasal_ref
|
||||||
double to_number();
|
double to_number();
|
||||||
std::string to_string();
|
std::string to_string();
|
||||||
void print();
|
void print();
|
||||||
|
inline nasal_ref* addr();
|
||||||
inline uint32_t ret ();
|
inline uint32_t ret ();
|
||||||
inline int64_t& cnt ();
|
inline int64_t& cnt ();
|
||||||
inline double& num ();
|
inline double& num ();
|
||||||
|
@ -334,6 +345,7 @@ void nasal_ref::print()
|
||||||
case vm_obj: std::cout<<"<object>"; break;
|
case vm_obj: std::cout<<"<object>"; break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
inline nasal_ref* nasal_ref::addr (){return value.addr; }
|
||||||
inline uint32_t nasal_ref::ret (){return value.ret; }
|
inline uint32_t nasal_ref::ret (){return value.ret; }
|
||||||
inline int64_t& nasal_ref::cnt (){return value.cnt; }
|
inline int64_t& nasal_ref::cnt (){return value.cnt; }
|
||||||
inline double& nasal_ref::num (){return value.num; }
|
inline double& nasal_ref::num (){return value.num; }
|
||||||
|
@ -347,9 +359,10 @@ inline nasal_obj* nasal_ref::obj (){return value.gcobj->ptr.obj; }
|
||||||
const uint32_t STACK_MAX_DEPTH=8191;
|
const uint32_t STACK_MAX_DEPTH=8191;
|
||||||
const nasal_ref zero={vm_num,(double)0};
|
const nasal_ref zero={vm_num,(double)0};
|
||||||
const nasal_ref one ={vm_num,(double)1};
|
const nasal_ref one ={vm_num,(double)1};
|
||||||
const nasal_ref nil ={vm_nil,nullptr};
|
const nasal_ref nil ={vm_nil,(double)0};
|
||||||
struct nasal_gc
|
struct nasal_gc
|
||||||
{
|
{
|
||||||
|
nasal_ref funcr; // function register
|
||||||
nasal_ref stack[STACK_MAX_DEPTH+1];// 1 reserved to avoid stack overflow
|
nasal_ref stack[STACK_MAX_DEPTH+1];// 1 reserved to avoid stack overflow
|
||||||
nasal_ref* top; // stack top
|
nasal_ref* top; // stack top
|
||||||
std::vector<nasal_ref> strs; // reserved address for const vm_str
|
std::vector<nasal_ref> strs; // reserved address for const vm_str
|
||||||
|
@ -376,6 +389,7 @@ struct nasal_gc
|
||||||
void nasal_gc::mark()
|
void nasal_gc::mark()
|
||||||
{
|
{
|
||||||
std::queue<nasal_ref> bfs;
|
std::queue<nasal_ref> bfs;
|
||||||
|
bfs.push(funcr);
|
||||||
for(auto& i:upvalue)
|
for(auto& i:upvalue)
|
||||||
bfs.push(i);
|
bfs.push(i);
|
||||||
for(nasal_ref* i=stack;i<=top;++i)
|
for(nasal_ref* i=stack;i<=top;++i)
|
||||||
|
@ -432,6 +446,8 @@ void nasal_gc::sweep()
|
||||||
}
|
}
|
||||||
void nasal_gc::init(const std::vector<std::string>& s)
|
void nasal_gc::init(const std::vector<std::string>& s)
|
||||||
{
|
{
|
||||||
|
funcr=nil;
|
||||||
|
|
||||||
for(uint8_t i=0;i<vm_type_size;++i)
|
for(uint8_t i=0;i<vm_type_size;++i)
|
||||||
size[i]=count[i]=0;
|
size[i]=count[i]=0;
|
||||||
for(uint8_t i=vm_str;i<vm_type_size;++i)
|
for(uint8_t i=vm_str;i<vm_type_size;++i)
|
||||||
|
@ -467,10 +483,10 @@ void nasal_gc::clear()
|
||||||
void nasal_gc::info()
|
void nasal_gc::info()
|
||||||
{
|
{
|
||||||
const char* name[]={
|
const char* name[]={
|
||||||
"null ","cnt ","ret ",
|
"null ","cnt ","addr ",
|
||||||
"nil ","num ","str ",
|
"ret ","nil ","num ",
|
||||||
"func ","vec ","hash ",
|
"str ","func ","vec ",
|
||||||
"upval","obj "
|
"hash ","upval","obj "
|
||||||
};
|
};
|
||||||
std::cout<<"\ngarbage collector info:\n";
|
std::cout<<"\ngarbage collector info:\n";
|
||||||
for(uint8_t i=vm_str;i<vm_type_size;++i)
|
for(uint8_t i=vm_str;i<vm_type_size;++i)
|
||||||
|
|
111
nasal_vm.h
111
nasal_vm.h
|
@ -6,10 +6,9 @@ class nasal_vm
|
||||||
protected:
|
protected:
|
||||||
/* values of nasal_vm */
|
/* values of nasal_vm */
|
||||||
uint32_t pc; // program counter
|
uint32_t pc; // program counter
|
||||||
|
nasal_ref* localr; // local scope register
|
||||||
const double* num_table;// const numbers, ref from nasal_codegen
|
const double* num_table;// const numbers, ref from nasal_codegen
|
||||||
const std::string* str_table;// const symbols, ref from nasal_codegen
|
const std::string* str_table;// const symbols, ref from nasal_codegen
|
||||||
std::stack<nasal_func*> fstk; // stack to store function, used to get upvalues
|
|
||||||
std::stack<nasal_ref*> lstk; // stack to store local scopes' begin address
|
|
||||||
std::vector<uint32_t> imm; // immediate number
|
std::vector<uint32_t> imm; // immediate number
|
||||||
nasal_ref* mem_addr; // used for mem_call
|
nasal_ref* mem_addr; // used for mem_call
|
||||||
/* garbage collector */
|
/* garbage collector */
|
||||||
|
@ -139,6 +138,7 @@ void nasal_vm::init(
|
||||||
canary=gc.stack+STACK_MAX_DEPTH-1;
|
canary=gc.stack+STACK_MAX_DEPTH-1;
|
||||||
mem_addr=nullptr;
|
mem_addr=nullptr;
|
||||||
pc=0;
|
pc=0;
|
||||||
|
localr=nullptr;
|
||||||
}
|
}
|
||||||
void nasal_vm::valinfo(nasal_ref& val)
|
void nasal_vm::valinfo(nasal_ref& val)
|
||||||
{
|
{
|
||||||
|
@ -147,7 +147,8 @@ void nasal_vm::valinfo(nasal_ref& val)
|
||||||
switch(val.type)
|
switch(val.type)
|
||||||
{
|
{
|
||||||
case vm_none: printf("| null |\n");break;
|
case vm_none: printf("| null |\n");break;
|
||||||
case vm_ret: printf("| addr | pc:0x%x\n",val.ret());break;
|
case vm_ret: printf("| pc | 0x%x\n",val.ret());break;
|
||||||
|
case vm_addr: printf("| addr | 0x%lx\n",(uint64_t)val.addr());break;
|
||||||
case vm_cnt: printf("| cnt | %ld\n",val.cnt());break;
|
case vm_cnt: printf("| cnt | %ld\n",val.cnt());break;
|
||||||
case vm_nil: printf("| nil |\n");break;
|
case vm_nil: printf("| nil |\n");break;
|
||||||
case vm_num: printf("| num | ");std::cout<<val.num()<<'\n';break;
|
case vm_num: printf("| num | ");std::cout<<val.num()<<'\n';break;
|
||||||
|
@ -242,21 +243,22 @@ void nasal_vm::global_state()
|
||||||
}
|
}
|
||||||
void nasal_vm::local_state()
|
void nasal_vm::local_state()
|
||||||
{
|
{
|
||||||
if(lstk.empty() || !fstk.top()->lsize)
|
if(!localr || !gc.funcr.func()->lsize)
|
||||||
return;
|
return;
|
||||||
printf("local(0x%lx<sp+%ld>):\n",(uint64_t)lstk.top(),lstk.top()-gc.stack);
|
uint32_t lsize=gc.funcr.func()->lsize;
|
||||||
for(uint32_t i=0;i<fstk.top()->lsize;++i)
|
printf("local(0x%lx<sp+%ld>):\n",(uint64_t)localr,localr-gc.stack);
|
||||||
|
for(uint32_t i=0;i<lsize;++i)
|
||||||
{
|
{
|
||||||
printf("0x%.8x",i);
|
printf("0x%.8x",i);
|
||||||
valinfo(lstk.top()[i]);
|
valinfo(localr[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void nasal_vm::upval_state()
|
void nasal_vm::upval_state()
|
||||||
{
|
{
|
||||||
if(fstk.empty() || fstk.top()->upvalue.empty())
|
if(gc.funcr.type==vm_nil || gc.funcr.func()->upvalue.empty())
|
||||||
return;
|
return;
|
||||||
printf("upvalue:\n");
|
printf("upvalue:\n");
|
||||||
auto& upval=fstk.top()->upvalue;
|
auto& upval=gc.funcr.func()->upvalue;
|
||||||
for(uint32_t i=0;i<upval.size();++i)
|
for(uint32_t i=0;i<upval.size();++i)
|
||||||
{
|
{
|
||||||
printf("-> upval[%u]:\n",i);
|
printf("-> upval[%u]:\n",i);
|
||||||
|
@ -271,6 +273,13 @@ void nasal_vm::upval_state()
|
||||||
void nasal_vm::detail()
|
void nasal_vm::detail()
|
||||||
{
|
{
|
||||||
printf("maddr(0x%lx)\n",(uint64_t)mem_addr);
|
printf("maddr(0x%lx)\n",(uint64_t)mem_addr);
|
||||||
|
printf("localr(0x%lx)\n",(uint64_t)localr);
|
||||||
|
if(gc.funcr.type==vm_nil)
|
||||||
|
printf("funcr(nil)\n");
|
||||||
|
else
|
||||||
|
printf("funcr(<0x%lx> entry:0x%x)\n",
|
||||||
|
(uint64_t)gc.funcr.value.gcobj,
|
||||||
|
gc.funcr.func()->entry);
|
||||||
global_state();
|
global_state();
|
||||||
local_state();
|
local_state();
|
||||||
upval_state();
|
upval_state();
|
||||||
|
@ -336,11 +345,11 @@ inline void nasal_vm::opr_loadg()
|
||||||
}
|
}
|
||||||
inline void nasal_vm::opr_loadl()
|
inline void nasal_vm::opr_loadl()
|
||||||
{
|
{
|
||||||
lstk.top()[imm[pc]]=(gc.top--)[0];
|
localr[imm[pc]]=(gc.top--)[0];
|
||||||
}
|
}
|
||||||
inline void nasal_vm::opr_loadu()
|
inline void nasal_vm::opr_loadu()
|
||||||
{
|
{
|
||||||
fstk.top()->upvalue[(imm[pc]>>16)&0xffff].upval()[imm[pc]&0xffff]=(gc.top--)[0];
|
gc.funcr.func()->upvalue[(imm[pc]>>16)&0xffff].upval()[imm[pc]&0xffff]=(gc.top--)[0];
|
||||||
}
|
}
|
||||||
inline void nasal_vm::opr_pnum()
|
inline void nasal_vm::opr_pnum()
|
||||||
{
|
{
|
||||||
|
@ -348,7 +357,7 @@ inline void nasal_vm::opr_pnum()
|
||||||
}
|
}
|
||||||
inline void nasal_vm::opr_pnil()
|
inline void nasal_vm::opr_pnil()
|
||||||
{
|
{
|
||||||
(++gc.top)[0]={vm_nil,(double)0};
|
(++gc.top)[0]=nil;
|
||||||
}
|
}
|
||||||
inline void nasal_vm::opr_pstr()
|
inline void nasal_vm::opr_pstr()
|
||||||
{
|
{
|
||||||
|
@ -377,12 +386,12 @@ inline void nasal_vm::opr_newf()
|
||||||
func->psize=1;
|
func->psize=1;
|
||||||
|
|
||||||
/* this means you create a new function in local scope */
|
/* this means you create a new function in local scope */
|
||||||
if(!lstk.empty())
|
if(localr)
|
||||||
{
|
{
|
||||||
func->upvalue=fstk.top()->upvalue;
|
func->upvalue=gc.funcr.func()->upvalue;
|
||||||
nasal_ref upval=(gc.upvalue.back().type==vm_nil)?gc.alloc(vm_upval):gc.upvalue.back();
|
nasal_ref upval=(gc.upvalue.back().type==vm_nil)?gc.alloc(vm_upval):gc.upvalue.back();
|
||||||
upval.upval().size=fstk.top()->lsize;
|
upval.upval().size=gc.funcr.func()->lsize;
|
||||||
upval.upval().stk=lstk.top();
|
upval.upval().stk=localr;
|
||||||
func->upvalue.push_back(upval);
|
func->upvalue.push_back(upval);
|
||||||
gc.upvalue.back()=upval;
|
gc.upvalue.back()=upval;
|
||||||
}
|
}
|
||||||
|
@ -598,11 +607,11 @@ inline void nasal_vm::opr_callg()
|
||||||
}
|
}
|
||||||
inline void nasal_vm::opr_calll()
|
inline void nasal_vm::opr_calll()
|
||||||
{
|
{
|
||||||
(++gc.top)[0]=lstk.top()[imm[pc]];
|
(++gc.top)[0]=localr[imm[pc]];
|
||||||
}
|
}
|
||||||
inline void nasal_vm::opr_upval()
|
inline void nasal_vm::opr_upval()
|
||||||
{
|
{
|
||||||
(++gc.top)[0]=fstk.top()->upvalue[(imm[pc]>>16)&0xffff].upval()[imm[pc]&0xffff];
|
(++gc.top)[0]=gc.funcr.func()->upvalue[(imm[pc]>>16)&0xffff].upval()[imm[pc]&0xffff];
|
||||||
}
|
}
|
||||||
inline void nasal_vm::opr_callv()
|
inline void nasal_vm::opr_callv()
|
||||||
{
|
{
|
||||||
|
@ -663,28 +672,28 @@ inline void nasal_vm::opr_callh()
|
||||||
inline void nasal_vm::opr_callfv()
|
inline void nasal_vm::opr_callfv()
|
||||||
{
|
{
|
||||||
uint32_t argc=imm[pc]; // arguments counter
|
uint32_t argc=imm[pc]; // arguments counter
|
||||||
nasal_ref* args=gc.top-argc+1;// arguments begin address
|
nasal_ref* local=gc.top-argc+1;// arguments begin address
|
||||||
if(args[-1].type!=vm_func)
|
if(local[-1].type!=vm_func)
|
||||||
die("callfv: must call a function");
|
die("callfv: must call a function");
|
||||||
|
|
||||||
nasal_func* func=args[-1].func();
|
nasal_func* func=local[-1].func();
|
||||||
if(gc.top-argc+func->lsize+1>=canary) // gc.top-argc+lsize(local) +1(pc)
|
nasal_ref tmp=local[-1];
|
||||||
|
local[-1]=gc.funcr;
|
||||||
|
gc.funcr=tmp;
|
||||||
|
if(gc.top-argc+func->lsize+2>=canary) // gc.top-argc+lsize(local) +1(old pc) +1(old localr)
|
||||||
die("stack overflow");
|
die("stack overflow");
|
||||||
fstk.push(func); // push called function into stack to provide upvalue
|
|
||||||
lstk.push(gc.top-argc+1); // store begin of local scope
|
|
||||||
|
|
||||||
uint32_t psize=func->psize-1; // parameter size is func->psize-1, 1 is reserved for "me"
|
uint32_t psize=func->psize-1; // parameter size is func->psize-1, 1 is reserved for "me"
|
||||||
if(argc<psize && func->local[argc+1].type==vm_none)
|
if(argc<psize && func->local[argc+1].type==vm_none)
|
||||||
die("callfv: lack argument(s)");
|
die("callfv: lack argument(s)");
|
||||||
|
|
||||||
nasal_ref* local=args;
|
|
||||||
nasal_ref dynamic=nil;
|
nasal_ref dynamic=nil;
|
||||||
gc.top=local+func->lsize;
|
gc.top=local+func->lsize;
|
||||||
if(func->dynpara>=0)// load dynamic arguments
|
if(func->dynpara>=0)// load dynamic arguments
|
||||||
{
|
{
|
||||||
dynamic=gc.alloc(vm_vec);
|
dynamic=gc.alloc(vm_vec);
|
||||||
for(uint32_t i=psize;i<argc;++i)
|
for(uint32_t i=psize;i<argc;++i)
|
||||||
dynamic.vec()->elems.push_back(args[i]);
|
dynamic.vec()->elems.push_back(local[i]);
|
||||||
}
|
}
|
||||||
uint32_t min_size=std::min(psize,argc);
|
uint32_t min_size=std::min(psize,argc);
|
||||||
for(uint32_t i=min_size;i>=1;--i)// load arguments
|
for(uint32_t i=min_size;i>=1;--i)// load arguments
|
||||||
|
@ -695,8 +704,10 @@ inline void nasal_vm::opr_callfv()
|
||||||
if(func->dynpara>=0)
|
if(func->dynpara>=0)
|
||||||
local[psize+1]=dynamic;
|
local[psize+1]=dynamic;
|
||||||
|
|
||||||
gc.top[0]={vm_ret,pc};
|
gc.top[0]={vm_addr,localr};
|
||||||
|
(++gc.top)[0]={vm_ret,pc};
|
||||||
pc=func->entry-1;
|
pc=func->entry-1;
|
||||||
|
localr=local;
|
||||||
gc.upvalue.push_back(nil);
|
gc.upvalue.push_back(nil);
|
||||||
}
|
}
|
||||||
inline void nasal_vm::opr_callfh()
|
inline void nasal_vm::opr_callfh()
|
||||||
|
@ -706,12 +717,13 @@ inline void nasal_vm::opr_callfh()
|
||||||
die("callfh: must call a function");
|
die("callfh: must call a function");
|
||||||
|
|
||||||
nasal_func* func=gc.top[-1].func();
|
nasal_func* func=gc.top[-1].func();
|
||||||
if(gc.top+func->lsize>=canary) // gc.top -1(hash) +lsize(local) +1(pc)
|
nasal_ref tmp=gc.top[-1];
|
||||||
|
gc.top[-1]=gc.funcr;
|
||||||
|
gc.funcr=tmp;
|
||||||
|
if(gc.top+func->lsize+1>=canary) // gc.top -1(hash) +lsize(local) +1(old pc) +1(old localr)
|
||||||
die("stack overflow");
|
die("stack overflow");
|
||||||
if(func->dynpara>=0)
|
if(func->dynpara>=0)
|
||||||
die("callfh: special call cannot use dynamic argument");
|
die("callfh: special call cannot use dynamic argument");
|
||||||
fstk.push(func); // push called function into stack to provide upvalue
|
|
||||||
lstk.push(gc.top); // store begin of local scope
|
|
||||||
|
|
||||||
nasal_ref* local=gc.top;
|
nasal_ref* local=gc.top;
|
||||||
gc.top+=func->lsize;
|
gc.top+=func->lsize;
|
||||||
|
@ -726,18 +738,21 @@ inline void nasal_vm::opr_callfh()
|
||||||
die("callfh: lack argument(s): \""+i.first+"\"");
|
die("callfh: lack argument(s): \""+i.first+"\"");
|
||||||
}
|
}
|
||||||
|
|
||||||
gc.top[0]={vm_ret,(uint32_t)pc}; // rewrite top with vm_ret
|
gc.top[0]={vm_addr,localr};
|
||||||
|
(++gc.top)[0]={vm_ret,pc}; // rewrite top with vm_ret
|
||||||
pc=func->entry-1;
|
pc=func->entry-1;
|
||||||
|
localr=local;
|
||||||
gc.upvalue.push_back(nil);
|
gc.upvalue.push_back(nil);
|
||||||
}
|
}
|
||||||
inline void nasal_vm::opr_callb()
|
inline void nasal_vm::opr_callb()
|
||||||
{
|
{
|
||||||
(++gc.top)[0]=(*builtin[imm[pc]].func)(lstk.top(),gc);
|
(++gc.top)[0]=(*builtin[imm[pc]].func)(localr,gc);
|
||||||
if(gc.top[0].type==vm_none)
|
if(gc.top[0].type==vm_none)
|
||||||
die("native function error.");
|
die("native function error.");
|
||||||
}
|
}
|
||||||
inline void nasal_vm::opr_slcbegin()
|
inline void nasal_vm::opr_slcbegin()
|
||||||
{
|
{
|
||||||
|
// +--------------+
|
||||||
// | slice_vector | <-- gc.top[0]
|
// | slice_vector | <-- gc.top[0]
|
||||||
// +--------------+
|
// +--------------+
|
||||||
// | resource_vec | <-- gc.top[-1]
|
// | resource_vec | <-- gc.top[-1]
|
||||||
|
@ -797,12 +812,12 @@ inline void nasal_vm::opr_mcallg()
|
||||||
}
|
}
|
||||||
inline void nasal_vm::opr_mcalll()
|
inline void nasal_vm::opr_mcalll()
|
||||||
{
|
{
|
||||||
mem_addr=lstk.top()+imm[pc];
|
mem_addr=localr+imm[pc];
|
||||||
(++gc.top)[0]=mem_addr[0];
|
(++gc.top)[0]=mem_addr[0];
|
||||||
}
|
}
|
||||||
inline void nasal_vm::opr_mupval()
|
inline void nasal_vm::opr_mupval()
|
||||||
{
|
{
|
||||||
mem_addr=&(fstk.top()->upvalue[(imm[pc]>>16)&0xffff].upval()[imm[pc]&0xffff]);
|
mem_addr=&(gc.funcr.func()->upvalue[(imm[pc]>>16)&0xffff].upval()[imm[pc]&0xffff]);
|
||||||
(++gc.top)[0]=mem_addr[0];
|
(++gc.top)[0]=mem_addr[0];
|
||||||
}
|
}
|
||||||
inline void nasal_vm::opr_mcallv()
|
inline void nasal_vm::opr_mcallv()
|
||||||
|
@ -824,7 +839,7 @@ inline void nasal_vm::opr_mcallv()
|
||||||
mem_addr=ref.get_mem(str);
|
mem_addr=ref.get_mem(str);
|
||||||
if(!mem_addr)
|
if(!mem_addr)
|
||||||
{
|
{
|
||||||
ref.elems[str]={vm_nil};
|
ref.elems[str]=nil;
|
||||||
mem_addr=ref.get_mem(str);
|
mem_addr=ref.get_mem(str);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -841,39 +856,45 @@ inline void nasal_vm::opr_mcallh()
|
||||||
mem_addr=ref.get_mem(str);
|
mem_addr=ref.get_mem(str);
|
||||||
if(!mem_addr) // create a new key
|
if(!mem_addr) // create a new key
|
||||||
{
|
{
|
||||||
ref.elems[str]={vm_nil};
|
ref.elems[str]=nil;
|
||||||
mem_addr=ref.get_mem(str);
|
mem_addr=ref.get_mem(str);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
inline void nasal_vm::opr_ret()
|
inline void nasal_vm::opr_ret()
|
||||||
{
|
{
|
||||||
|
// +-----------------+
|
||||||
// | return value | <- gc.top[0]
|
// | return value | <- gc.top[0]
|
||||||
// +-----------------+
|
// +-----------------+
|
||||||
// | return address | <- gc.top[-1]
|
// | old pc | <- gc.top[-1]
|
||||||
|
// +-----------------+
|
||||||
|
// | old localr | <- gc.top[-2]
|
||||||
// +-----------------+
|
// +-----------------+
|
||||||
// | local scope |
|
// | local scope |
|
||||||
// +-----------------+ <- local pointer stored in lstk
|
// | ... |
|
||||||
// | called function | <- func is stored on stack because gc may mark it
|
// +-----------------+ <- local pointer stored in localr
|
||||||
|
// | old funcr | <- old function stored in gc.funcr
|
||||||
// +-----------------+
|
// +-----------------+
|
||||||
nasal_ref ret=gc.top[0];
|
nasal_ref ret=gc.top[0];
|
||||||
|
nasal_ref* local=localr;
|
||||||
|
nasal_ref func=gc.funcr;
|
||||||
|
|
||||||
pc=gc.top[-1].ret();
|
pc=gc.top[-1].ret();
|
||||||
|
localr=gc.top[-2].addr();
|
||||||
|
|
||||||
gc.top=lstk.top()-1;
|
gc.top=local-1;
|
||||||
|
func.func()->local[0]=nil;// get func and set 'me' to nil
|
||||||
|
gc.funcr=gc.top[0];
|
||||||
|
|
||||||
gc.top[0].func()->local[0]={vm_nil,nullptr}; // get func and set 'me' to nil
|
|
||||||
gc.top[0]=ret; // rewrite func with returned value
|
gc.top[0]=ret; // rewrite func with returned value
|
||||||
|
|
||||||
if(gc.upvalue.back().type==vm_upval) // synchronize upvalue
|
if(gc.upvalue.back().type==vm_upval) // synchronize upvalue
|
||||||
{
|
{
|
||||||
auto& upval=gc.upvalue.back().upval();
|
auto& upval=gc.upvalue.back().upval();
|
||||||
auto local=lstk.top();
|
auto size=func.func()->lsize;
|
||||||
auto size=fstk.top()->lsize;
|
|
||||||
upval.onstk=false;
|
upval.onstk=false;
|
||||||
for(uint32_t i=0;i<size;++i)
|
for(uint32_t i=0;i<size;++i)
|
||||||
upval.elems.push_back(local[i]);
|
upval.elems.push_back(local[i]);
|
||||||
}
|
}
|
||||||
lstk.pop();
|
|
||||||
fstk.pop();
|
|
||||||
gc.upvalue.pop_back();
|
gc.upvalue.pop_back();
|
||||||
}
|
}
|
||||||
void nasal_vm::run(
|
void nasal_vm::run(
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# Road check and auto pilot by ValKmjolnir
|
# Road check and auto pilot by ValKmjolnir
|
||||||
import("lib.nas");
|
import("lib.nas");
|
||||||
import("props.nas");
|
import("test/props_sim.nas");
|
||||||
var dt=0.01;
|
var dt=0.01;
|
||||||
var intergral=0;
|
var intergral=0;
|
||||||
var derivative=0;
|
var derivative=0;
|
||||||
|
|
|
@ -53,6 +53,7 @@ var testfile=[
|
||||||
"test/nasal_test.nas ",
|
"test/nasal_test.nas ",
|
||||||
"test/pi.nas ",
|
"test/pi.nas ",
|
||||||
"test/prime.nas ",
|
"test/prime.nas ",
|
||||||
|
"test/props_sim.nas ",
|
||||||
"test/props.nas ",
|
"test/props.nas ",
|
||||||
"test/quick_sort.nas ",
|
"test/quick_sort.nas ",
|
||||||
"test/scalar.nas ",
|
"test/scalar.nas ",
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
import("lib.nas");
|
import("lib.nas");
|
||||||
|
|
||||||
|
var geodinfo=func(lat,lon){}
|
||||||
|
var maketimer=func(t,f){}
|
||||||
|
|
||||||
var props=
|
var props=
|
||||||
{
|
{
|
||||||
globals:nil,
|
globals:nil,
|
Loading…
Reference in New Issue