change instruction dispatch to computed-goto

bug fixed
prepare for version 7.0
This commit is contained in:
ValKmjolnir 2021-06-26 14:53:10 +08:00
parent 3c9a10d710
commit 706659ba3d
7 changed files with 212 additions and 194 deletions

View File

@ -199,7 +199,7 @@ for(var i=0;i<4000000;i+=1);
0x0000000c: nop 0x00000000
```
### Version 6.5(latest)
### Version 6.5(last update 2021/6/24)
2021/5/31 update: Now gc can collect garbage correctly without re-collecting,which will cause fatal error.
@ -329,6 +329,16 @@ As you could see from the bytecode above,mcall/mcallv/mcallh operands' using fre
And because of the new structure of mcall, addr_stack, a stack used to store the memory address, is deleted from nasal_vm, and now nasal_vm use nasal_val** mem_addr to store the memory address. This will not cause fatal errors because the memory address is used __immediately__ after getting it.
### version 7.0(latest)
2021/6/26 update:
Instruction dispatch is changed from call-threading to computed-goto(with inline function).After changing the way of instruction dispatch,there is a great improvement in nasal_vm.Now vm can run test/bigloop and test/pi in 0.2s!And vm runs test/fib in 0.8s on linux.You could see the time use data below,in Test data section.
This version uses gcc extension "labels as values", which is also supported by clang.(But i don't know if MSVC supports this)
There is also a change in nasal_gc: std::vector global is deleted,now the global values are all stored on stack(from val_stack+0 to val_stack+intg-1).
## Test data
### version 6.5(i5-8250U windows10 2021/6/19)
@ -378,6 +388,23 @@ operands calling total times:
|quick_sort.nas|16226|5561|4144|3524|2833|
|bfs.nas|24707|16297|14606|14269|8672|
### version 7.0(i5-8250U ubuntu-WSL on windows10 2021/6/26)
running time:
|file|total time|info|
|:----|:----|:----|
|pi.nas|0.17s|great improvement|
|fib.nas|0.75s|great improvement|
|bp.nas|0.32s(5467 epoch)|good improvement|
|bigloop.nas|0.11s|great improvement|
|mandelbrot.nas|0.04s|great improvment|
|life.nas|8.80s(windows) 1.34(ubuntu WSL)|little improvement|
|ascii-art.nas|0.015s|little improvement|
|calc.nas|0.0625s|little improvement|
|quick_sort.nas|0s|great improvement|
|bfs.nas|0.0156s|great improvement|
## How to Use Nasal to Program
### basic value type
@ -660,7 +687,7 @@ Use import("") to get the nasal file including your built-in functions,then you
version 6.5 update:
Use nasal_gc::builtin_alloc in builtin function if this function uses alloc more then one time.
Use nasal_gc::builtin_alloc in builtin function if this function uses alloc more than one time.
When running a builtin function,alloc will run more than one time,this may cause mark-sweep in gc_alloc.

View File

@ -29,7 +29,6 @@ void help_cmd()
void info()
{
std::cout
<<">> Nasal interpreter ver 6.5.\n"
<<">> Thanks to https://github.com/andyross/nasal\n"
<<">> Code: https://github.com/ValKmjolnir/Nasal-Interpreter\n"
<<">> Code: https://gitee.com/valkmjolnir/Nasal-Interpreter\n"
@ -44,7 +43,8 @@ void logo()
<<" /\\ \\ \\__ _ ___ __ _| | \n"
<<" / \\/ / _` / __|/ _` | | \n"
<<" / /\\ / (_| \\__ \\ (_| | | \n"
<<" \\_\\ \\/ \\__,_|___/\\__,_|_|\n";
<<" \\_\\ \\/ \\__,_|___/\\__,_|_|\n"
<<">> Nasal interpreter ver 7.0 \n";
return;
}
void die(const char* stage,std::string& filename)
@ -104,10 +104,9 @@ void execute(std::string& file,std::string& command)
}
vm.init(
codegen.get_str_table(),
codegen.get_num_table(),
codegen.get_exec_code()
codegen.get_num_table()
);
vm.run();
vm.run(codegen.get_exec_code());
vm.clear();
return;
}
@ -150,10 +149,7 @@ int main(int argc,const char* argv[])
if(argc==1)
interact();
else if(argc==2 && (!strcmp(argv[1],"-v") || !strcmp(argv[1],"-version")))
{
logo();
std::cout<<"Nasal interpreter ver 6.5\n";
}
else if(argc==2 && (!strcmp(argv[1],"-h") || !strcmp(argv[1],"-help")))
help_cmd();
else if(argc==2 && argv[1][0]!='-')

View File

@ -722,7 +722,7 @@ nasal_val* builtin_substr(std::vector<nasal_val*>& local_scope,nasal_gc& gc)
std::string& str=*str_addr->ptr.str;
int beg=(int)beg_addr->ptr.num;
int len=(int)len_addr->ptr.num;
if(beg>=str.length() || beg+len>=str.length())
if(beg>=str.length() || beg+len-1>=str.length())
{
builtin_err("susbtr","index out of range");
return nullptr;

View File

@ -245,7 +245,6 @@ struct nasal_gc
std::vector<nasal_val*> slice_stack; // slice stack for vec[val,val,val:val]
std::vector<nasal_val*> memory; // gc memory
std::queue <nasal_val*> free_list[vm_type_size]; // gc free list
std::vector<nasal_val*> global;
std::list<std::vector<nasal_val*>> local;
void mark();
void sweep();
@ -259,8 +258,6 @@ struct nasal_gc
void nasal_gc::mark()
{
std::queue<nasal_val*> bfs;
for(auto i:global)
bfs.push(i);
for(auto& i:local)
for(auto j:i)
bfs.push(j);
@ -332,7 +329,6 @@ void nasal_gc::gc_init(std::vector<double>& nums,std::vector<std::string>& strs)
nil_addr=new nasal_val(vm_nil); // init nil
*val_stack=nil_addr; // the first space will not store any values,but gc checks
// init constant numbers
num_addrs.resize(nums.size());
for(int i=0;i<nums.size();++i)
@ -357,7 +353,7 @@ void nasal_gc::gc_clear()
for(int i=0;i<vm_type_size;++i)
while(!free_list[i].empty())
free_list[i].pop();
global.clear();
//global.clear();
local.clear();
slice_stack.clear();

View File

@ -8,19 +8,15 @@ private:
nasal_val**& stack_top;// stack top
/* values of nasal_vm */
uint32_t pc; // program counter
bool loop_mark;// when mark is false,break the main loop
std::stack<int> ret; // ptr stack stores address for function to return
std::stack<int> counter; // iterator stack for forindex/foreach
std::vector<std::string> str_table;// symbols used in process
std::vector<void (nasal_vm::*)()>
exec_code;//function pointer
std::vector<uint32_t> imm; // immediate number
nasal_val** mem_addr; // used for mem_call
nasal_gc gc; // garbage collector
void die(std::string);
bool condition(nasal_val*);
void opr_nop();
void opr_intg();
void opr_intl();
void opr_offset();
@ -86,91 +82,18 @@ public:
nasal_vm():stack_top(gc.stack_top){};
void init(
std::vector<std::string>&,
std::vector<double>&,
std::vector<opcode>&);
std::vector<double>&);
void clear();
void run();
void run(std::vector<opcode>&);
};
void nasal_vm::init(
std::vector<std::string>& strs,
std::vector<double>& nums,
std::vector<opcode>& exec)
std::vector<double>& nums)
{
gc.gc_init(nums,strs);
gc.val_stack[STACK_MAX_DEPTH-1]=nullptr;
str_table=strs; // get constant strings & symbols
void (nasal_vm::*opr_table[])()=
{
&nasal_vm::opr_nop,
&nasal_vm::opr_intg,
&nasal_vm::opr_intl,
&nasal_vm::opr_offset,
&nasal_vm::opr_loadg,
&nasal_vm::opr_loadl,
&nasal_vm::opr_pnum,
&nasal_vm::opr_pone,
&nasal_vm::opr_pzero,
&nasal_vm::opr_pnil,
&nasal_vm::opr_pstr,
&nasal_vm::opr_newv,
&nasal_vm::opr_newh,
&nasal_vm::opr_newf,
&nasal_vm::opr_happ,
&nasal_vm::opr_para,
&nasal_vm::opr_defpara,
&nasal_vm::opr_dynpara,
&nasal_vm::opr_unot,
&nasal_vm::opr_usub,
&nasal_vm::opr_add,
&nasal_vm::opr_sub,
&nasal_vm::opr_mul,
&nasal_vm::opr_div,
&nasal_vm::opr_lnk,
&nasal_vm::opr_addeq,
&nasal_vm::opr_subeq,
&nasal_vm::opr_muleq,
&nasal_vm::opr_diveq,
&nasal_vm::opr_lnkeq,
&nasal_vm::opr_meq,
&nasal_vm::opr_eq,
&nasal_vm::opr_neq,
&nasal_vm::opr_less,
&nasal_vm::opr_leq,
&nasal_vm::opr_grt,
&nasal_vm::opr_geq,
&nasal_vm::opr_pop,
&nasal_vm::opr_jmp,
&nasal_vm::opr_jt,
&nasal_vm::opr_jf,
&nasal_vm::opr_counter,
&nasal_vm::opr_cntpop,
&nasal_vm::opr_findex,
&nasal_vm::opr_feach,
&nasal_vm::opr_callg,
&nasal_vm::opr_calll,
&nasal_vm::opr_callv,
&nasal_vm::opr_callvi,
&nasal_vm::opr_callh,
&nasal_vm::opr_callfv,
&nasal_vm::opr_callfh,
&nasal_vm::opr_callb,
&nasal_vm::opr_slcbegin,
&nasal_vm::opr_slcend,
&nasal_vm::opr_slc,
&nasal_vm::opr_slc2,
&nasal_vm::opr_mcallg,
&nasal_vm::opr_mcalll,
&nasal_vm::opr_mcallv,
&nasal_vm::opr_mcallh,
&nasal_vm::opr_ret
};
for(auto& i:exec)
{
exec_code.push_back(opr_table[i.op]);
imm.push_back(i.num);
}
loop_mark=true; // set loop mark to true
return;
}
void nasal_vm::clear()
@ -181,13 +104,13 @@ void nasal_vm::clear()
while(!counter.empty())
counter.pop();
str_table.clear();
exec_code.clear();
imm.clear();
return;
}
void nasal_vm::die(std::string str)
{
printf(">> [vm] 0x%.8x: %s\n",pc,str.c_str());
loop_mark=false;
gc.val_stack[STACK_MAX_DEPTH-1]=(nasal_val*)0xffff;
return;
}
bool nasal_vm::condition(nasal_val* val_addr)
@ -204,62 +127,60 @@ bool nasal_vm::condition(nasal_val* val_addr)
}
return false;
}
void nasal_vm::opr_nop()
inline void nasal_vm::opr_intg()
{
loop_mark=false;
// global values store on stack
for(int i=0;i<imm[pc];++i)
(stack_top++)[0]=gc.nil_addr;
--stack_top;// point to the top
return;
}
void nasal_vm::opr_intg()
{
gc.global.resize(imm[pc],gc.nil_addr);
return;
}
void nasal_vm::opr_intl()
inline void nasal_vm::opr_intl()
{
stack_top[0]->ptr.func->closure.resize(imm[pc],gc.nil_addr);
return;
}
void nasal_vm::opr_offset()
inline void nasal_vm::opr_offset()
{
stack_top[0]->ptr.func->offset=imm[pc];
return;
}
void nasal_vm::opr_loadg()
inline void nasal_vm::opr_loadg()
{
gc.global[imm[pc]]=(stack_top--)[0];
gc.val_stack[imm[pc]]=(stack_top--)[0];
return;
}
void nasal_vm::opr_loadl()
inline void nasal_vm::opr_loadl()
{
gc.local.back()[imm[pc]]=(stack_top--)[0];
return;
}
void nasal_vm::opr_pnum()
inline void nasal_vm::opr_pnum()
{
(++stack_top)[0]=gc.num_addrs[imm[pc]];
return;
}
void nasal_vm::opr_pone()
inline void nasal_vm::opr_pone()
{
(++stack_top)[0]=gc.one_addr;
return;
}
void nasal_vm::opr_pzero()
inline void nasal_vm::opr_pzero()
{
(++stack_top)[0]=gc.zero_addr;
return;
}
void nasal_vm::opr_pnil()
inline void nasal_vm::opr_pnil()
{
(++stack_top)[0]=gc.nil_addr;
return;
}
void nasal_vm::opr_pstr()
inline void nasal_vm::opr_pstr()
{
(++stack_top)[0]=gc.str_addrs[imm[pc]];
return;
}
void nasal_vm::opr_newv()
inline void nasal_vm::opr_newv()
{
nasal_val* vec_addr=gc.gc_alloc(vm_vec);
nasal_val** begin=stack_top-imm[pc]+1;
@ -271,12 +192,12 @@ void nasal_vm::opr_newv()
stack_top=begin;
return;
}
void nasal_vm::opr_newh()
inline void nasal_vm::opr_newh()
{
(++stack_top)[0]=gc.gc_alloc(vm_hash);
return;
}
void nasal_vm::opr_newf()
inline void nasal_vm::opr_newf()
{
nasal_val* val=gc.gc_alloc(vm_func);
val->ptr.func->entry=imm[pc];
@ -287,13 +208,13 @@ void nasal_vm::opr_newf()
(++stack_top)[0]=val;
return;
}
void nasal_vm::opr_happ()
inline void nasal_vm::opr_happ()
{
nasal_val* val=stack_top[0];
(--stack_top)[0]->ptr.hash->elems[str_table[imm[pc]]]=val;
return;
}
void nasal_vm::opr_para()
inline void nasal_vm::opr_para()
{
nasal_func* func=stack_top[0]->ptr.func;
int size=func->key_table.size();
@ -301,7 +222,7 @@ void nasal_vm::opr_para()
func->default_para.push_back(nullptr);
return;
}
void nasal_vm::opr_defpara()
inline void nasal_vm::opr_defpara()
{
nasal_val* def_val=stack_top[0];
nasal_func* func=(--stack_top)[0]->ptr.func;
@ -310,12 +231,12 @@ void nasal_vm::opr_defpara()
func->default_para.push_back(def_val);
return;
}
void nasal_vm::opr_dynpara()
inline void nasal_vm::opr_dynpara()
{
stack_top[0]->ptr.func->dynpara=imm[pc];
return;
}
void nasal_vm::opr_unot()
inline void nasal_vm::opr_unot()
{
nasal_val* val=stack_top[0];
int type=val->type;
@ -335,89 +256,89 @@ void nasal_vm::opr_unot()
die("unot: incorrect value type");
return;
}
void nasal_vm::opr_usub()
inline void nasal_vm::opr_usub()
{
nasal_val* new_val=gc.gc_alloc(vm_num);
new_val->ptr.num=-stack_top[0]->to_number();
stack_top[0]=new_val;
return;
}
void nasal_vm::opr_add()
inline void nasal_vm::opr_add()
{
nasal_val* new_val=gc.gc_alloc(vm_num);
new_val->ptr.num=stack_top[-1]->to_number()+stack_top[0]->to_number();
(--stack_top)[0]=new_val;
return;
}
void nasal_vm::opr_sub()
inline void nasal_vm::opr_sub()
{
nasal_val* new_val=gc.gc_alloc(vm_num);
new_val->ptr.num=stack_top[-1]->to_number()-stack_top[0]->to_number();
(--stack_top)[0]=new_val;
return;
}
void nasal_vm::opr_mul()
inline void nasal_vm::opr_mul()
{
nasal_val* new_val=gc.gc_alloc(vm_num);
new_val->ptr.num=stack_top[-1]->to_number()*stack_top[0]->to_number();
(--stack_top)[0]=new_val;
return;
}
void nasal_vm::opr_div()
inline void nasal_vm::opr_div()
{
nasal_val* new_val=gc.gc_alloc(vm_num);
new_val->ptr.num=stack_top[-1]->to_number()/stack_top[0]->to_number();
(--stack_top)[0]=new_val;
return;
}
void nasal_vm::opr_lnk()
inline void nasal_vm::opr_lnk()
{
nasal_val* new_val=gc.gc_alloc(vm_str);
*new_val->ptr.str=stack_top[-1]->to_string()+stack_top[0]->to_string();
(--stack_top)[0]=new_val;
return;
}
void nasal_vm::opr_addeq()
inline void nasal_vm::opr_addeq()
{
nasal_val* new_val=gc.gc_alloc(vm_num);
new_val->ptr.num=mem_addr[0]->to_number()+stack_top[-1]->to_number();
(--stack_top)[0]=mem_addr[0]=new_val;
return;
}
void nasal_vm::opr_subeq()
inline void nasal_vm::opr_subeq()
{
nasal_val* new_val=gc.gc_alloc(vm_num);
new_val->ptr.num=mem_addr[0]->to_number()-stack_top[-1]->to_number();
(--stack_top)[0]=mem_addr[0]=new_val;
return;
}
void nasal_vm::opr_muleq()
inline void nasal_vm::opr_muleq()
{
nasal_val* new_val=gc.gc_alloc(vm_num);
new_val->ptr.num=mem_addr[0]->to_number()*stack_top[-1]->to_number();
(--stack_top)[0]=mem_addr[0]=new_val;
return;
}
void nasal_vm::opr_diveq()
inline void nasal_vm::opr_diveq()
{
nasal_val* new_val=gc.gc_alloc(vm_num);
new_val->ptr.num=mem_addr[0]->to_number()/stack_top[-1]->to_number();
(--stack_top)[0]=mem_addr[0]=new_val;
return;
}
void nasal_vm::opr_lnkeq()
inline void nasal_vm::opr_lnkeq()
{
nasal_val* new_val=gc.gc_alloc(vm_str);
*new_val->ptr.str=mem_addr[0]->to_string()+stack_top[-1]->to_string();
(--stack_top)[0]=mem_addr[0]=new_val;
return;
}
void nasal_vm::opr_meq()
inline void nasal_vm::opr_meq()
{
mem_addr[0]=(--stack_top)[0];
return;
}
void nasal_vm::opr_eq()
inline void nasal_vm::opr_eq()
{
nasal_val* val2=stack_top[0];
nasal_val* val1=(--stack_top)[0];
@ -433,7 +354,7 @@ void nasal_vm::opr_eq()
stack_top[0]=(val1==val2)?gc.one_addr:gc.zero_addr;
return;
}
void nasal_vm::opr_neq()
inline void nasal_vm::opr_neq()
{
nasal_val* val2=stack_top[0];
nasal_val* val1=(--stack_top)[0];
@ -449,66 +370,66 @@ void nasal_vm::opr_neq()
stack_top[0]=(val1!=val2)?gc.one_addr:gc.zero_addr;
return;
}
void nasal_vm::opr_less()
inline void nasal_vm::opr_less()
{
--stack_top;
stack_top[0]=(stack_top[0]->to_number()<stack_top[1]->to_number())?gc.one_addr:gc.zero_addr;
return;
}
void nasal_vm::opr_leq()
inline void nasal_vm::opr_leq()
{
--stack_top;
stack_top[0]=(stack_top[0]->to_number()<=stack_top[1]->to_number())?gc.one_addr:gc.zero_addr;
return;
}
void nasal_vm::opr_grt()
inline void nasal_vm::opr_grt()
{
--stack_top;
stack_top[0]=(stack_top[0]->to_number()>stack_top[1]->to_number())?gc.one_addr:gc.zero_addr;
return;
}
void nasal_vm::opr_geq()
inline void nasal_vm::opr_geq()
{
--stack_top;
stack_top[0]=(stack_top[0]->to_number()>=stack_top[1]->to_number())?gc.one_addr:gc.zero_addr;
return;
}
void nasal_vm::opr_pop()
inline void nasal_vm::opr_pop()
{
--stack_top;
return;
}
void nasal_vm::opr_jmp()
inline void nasal_vm::opr_jmp()
{
pc=imm[pc]-1;
return;
}
void nasal_vm::opr_jt()
inline void nasal_vm::opr_jt()
{
if(condition(stack_top[0]))
pc=imm[pc]-1;
return;
}
void nasal_vm::opr_jf()
inline void nasal_vm::opr_jf()
{
if(!condition(stack_top[0]))
pc=imm[pc]-1;
--stack_top;
return;
}
void nasal_vm::opr_counter()
inline void nasal_vm::opr_counter()
{
counter.push(-1);
if(stack_top[0]->type!=vm_vec)
die("cnt: must use vector in forindex/foreach");
return;
}
void nasal_vm::opr_cntpop()
inline void nasal_vm::opr_cntpop()
{
counter.pop();
return;
}
void nasal_vm::opr_findex()
inline void nasal_vm::opr_findex()
{
if(++counter.top()>=stack_top[0]->ptr.vec->elems.size())
{
@ -519,7 +440,7 @@ void nasal_vm::opr_findex()
stack_top[0]->ptr.num=counter.top();
return;
}
void nasal_vm::opr_feach()
inline void nasal_vm::opr_feach()
{
std::vector<nasal_val*>& ref=stack_top[0]->ptr.vec->elems;
if(++counter.top()>=ref.size())
@ -530,17 +451,17 @@ void nasal_vm::opr_feach()
(++stack_top)[0]=ref[counter.top()];
return;
}
void nasal_vm::opr_callg()
inline void nasal_vm::opr_callg()
{
(++stack_top)[0]=gc.global[imm[pc]];
(++stack_top)[0]=gc.val_stack[imm[pc]];
return;
}
void nasal_vm::opr_calll()
inline void nasal_vm::opr_calll()
{
(++stack_top)[0]=gc.local.back()[imm[pc]];
return;
}
void nasal_vm::opr_callv()
inline void nasal_vm::opr_callv()
{
nasal_val* val=stack_top[0];
nasal_val* vec_addr=(--stack_top)[0];
@ -584,7 +505,7 @@ void nasal_vm::opr_callv()
die("callv: must call a vector/hash/string");
return;
}
void nasal_vm::opr_callvi()
inline void nasal_vm::opr_callvi()
{
nasal_val* val=stack_top[0];
if(val->type!=vm_vec)
@ -598,7 +519,7 @@ void nasal_vm::opr_callvi()
die("callvi: index out of range:"+num2str(imm[pc]));
return;
}
void nasal_vm::opr_callh()
inline void nasal_vm::opr_callh()
{
nasal_val* val=stack_top[0];
if(val->type!=vm_hash)
@ -616,7 +537,7 @@ void nasal_vm::opr_callh()
stack_top[0]->ptr.func->closure[0]=val;// me
return;
}
void nasal_vm::opr_callfv()
inline void nasal_vm::opr_callfv()
{
// get parameter list and function value
int args_size=imm[pc];
@ -660,7 +581,7 @@ void nasal_vm::opr_callfv()
pc=ref_func.entry-1;
return;
}
void nasal_vm::opr_callfh()
inline void nasal_vm::opr_callfh()
{
// get parameter list and function value
auto& ref_hash=stack_top[0]->ptr.hash->elems;
@ -701,25 +622,26 @@ void nasal_vm::opr_callfh()
pc=ref_func.entry-1;
return;
}
void nasal_vm::opr_callb()
inline void nasal_vm::opr_callb()
{
loop_mark=(++stack_top)[0]=(*builtin_func[imm[pc]].func)(gc.local.back(),gc);
(++stack_top)[0]=(*builtin_func[imm[pc]].func)(gc.local.back(),gc);
gc.val_stack[STACK_MAX_DEPTH-1]=(stack_top[0]?nullptr:(nasal_val*)0xffff);
return;
}
void nasal_vm::opr_slcbegin()
inline void nasal_vm::opr_slcbegin()
{
gc.slice_stack.push_back(gc.gc_alloc(vm_vec));
if(stack_top[0]->type!=vm_vec)
die("slcbegin: must slice a vector");
return;
}
void nasal_vm::opr_slcend()
inline void nasal_vm::opr_slcend()
{
stack_top[0]=gc.slice_stack.back();
gc.slice_stack.pop_back();
return;
}
void nasal_vm::opr_slc()
inline void nasal_vm::opr_slc()
{
nasal_val* val=(stack_top--)[0];
nasal_val* res=stack_top[0]->ptr.vec->get_val(val->to_number());
@ -728,7 +650,7 @@ void nasal_vm::opr_slc()
gc.slice_stack.back()->ptr.vec->elems.push_back(res);
return;
}
void nasal_vm::opr_slc2()
inline void nasal_vm::opr_slc2()
{
nasal_val* val2=(stack_top--)[0];
nasal_val* val1=(stack_top--)[0];
@ -768,19 +690,19 @@ void nasal_vm::opr_slc2()
aim.push_back(i>=0?ref[i]:ref[i+ref_size]);
return;
}
void nasal_vm::opr_mcallg()
inline void nasal_vm::opr_mcallg()
{
mem_addr=&gc.global[imm[pc]];
mem_addr=gc.val_stack+imm[pc];
(++stack_top)[0]=mem_addr[0];
return;
}
void nasal_vm::opr_mcalll()
inline void nasal_vm::opr_mcalll()
{
mem_addr=&gc.local.back()[imm[pc]];
(++stack_top)[0]=mem_addr[0];
return;
}
void nasal_vm::opr_mcallv()
inline void nasal_vm::opr_mcallv()
{
nasal_val* val=stack_top[0];
nasal_val* vec_addr=(--stack_top)[0];
@ -811,7 +733,7 @@ void nasal_vm::opr_mcallv()
die("mcallv: cannot get memory space in other types");
return;
}
void nasal_vm::opr_mcallh()
inline void nasal_vm::opr_mcallh()
{
nasal_val* hash_addr=stack_top[0];
if(hash_addr->type!=vm_hash)
@ -829,7 +751,7 @@ void nasal_vm::opr_mcallh()
}
return;
}
void nasal_vm::opr_ret()
inline void nasal_vm::opr_ret()
{
gc.local.pop_back();// delete local scope
pc=ret.top();ret.pop();// fetch pc
@ -837,14 +759,104 @@ void nasal_vm::opr_ret()
stack_top[0]=stack_top[1];// rewrite nasal_func with returned value
return;
}
void nasal_vm::run()
void nasal_vm::run(std::vector<opcode>& exec)
{
clock_t begin_time=clock();
for(pc=0;loop_mark&&!gc.val_stack[STACK_MAX_DEPTH-1];++pc)
(this->*exec_code[pc])();
if(gc.val_stack[STACK_MAX_DEPTH-1])
die("stack overflow");
std::cout<<">> [vm] process exited after "<<((double)(clock()-begin_time))/CLOCKS_PER_SEC<<"s.\n";
void* opr_table[]=
{
&&nop, &&intg, &&intl, &&offset,
&&loadg, &&loadl, &&pnum, &&pone,
&&pzero, &&pnil, &&pstr, &&newv,
&&newh, &&newf, &&happ, &&para,
&&defpara, &&dynpara, &&unot, &&usub,
&&add, &&sub, &&mul, &&div,
&&lnk, &&addeq, &&subeq, &&muleq,
&&diveq, &&lnkeq, &&meq, &&eq,
&&neq, &&less, &&leq, &&grt,
&&geq, &&pop, &&jmp, &&jt,
&&jf, &&counter, &&cntpop, &&findex,
&&feach, &&callg, &&calll, &&callv,
&&callvi, &&callh, &&callfv, &&callfh,
&&callb, &&slcbegin, &&slcend, &&slc,
&&slc2, &&mcallg, &&mcalll, &&mcallv,
&&mcallh, &&ret
};
std::vector<void*> code;
for(auto& i:exec)
{
code.push_back(opr_table[i.op]);
imm.push_back(i.num);
}
clock_t begin=clock();
pc=0;
goto *code[pc];
nop:
if(gc.val_stack[STACK_MAX_DEPTH-1]&&gc.val_stack[STACK_MAX_DEPTH-1]!=(nasal_val*)0xffff)
std::cout<<">> [vm] stack overflow.\n";
std::cout<<">> [vm] process exited after "<<((double)(clock()-begin))/CLOCKS_PER_SEC<<"s.\n";
return;
#define exec_operand(op) {op();if(!gc.val_stack[STACK_MAX_DEPTH-1])goto *code[++pc];goto nop;}
intg: exec_operand(opr_intg );
intl: exec_operand(opr_intl );
offset: exec_operand(opr_offset );
loadg: exec_operand(opr_loadg );
loadl: exec_operand(opr_loadl );
pnum: exec_operand(opr_pnum );
pone: exec_operand(opr_pone );
pzero: exec_operand(opr_pzero );
pnil: exec_operand(opr_pnil );
pstr: exec_operand(opr_pstr );
newv: exec_operand(opr_newv );
newh: exec_operand(opr_newh );
newf: exec_operand(opr_newf );
happ: exec_operand(opr_happ );
para: exec_operand(opr_para );
defpara: exec_operand(opr_defpara );
dynpara: exec_operand(opr_dynpara );
unot: exec_operand(opr_unot );
usub: exec_operand(opr_usub );
add: exec_operand(opr_add );
sub: exec_operand(opr_sub );
mul: exec_operand(opr_mul );
div: exec_operand(opr_div );
lnk: exec_operand(opr_lnk );
addeq: exec_operand(opr_addeq );
subeq: exec_operand(opr_subeq );
muleq: exec_operand(opr_muleq );
diveq: exec_operand(opr_diveq );
lnkeq: exec_operand(opr_lnkeq );
meq: exec_operand(opr_meq );
eq: exec_operand(opr_eq );
neq: exec_operand(opr_neq );
less: exec_operand(opr_less );
leq: exec_operand(opr_leq );
grt: exec_operand(opr_grt );
geq: exec_operand(opr_geq );
pop: exec_operand(opr_pop );
jmp: exec_operand(opr_jmp );
jt: exec_operand(opr_jt );
jf: exec_operand(opr_jf );
counter: exec_operand(opr_counter );
cntpop: exec_operand(opr_cntpop );
findex: exec_operand(opr_findex );
feach: exec_operand(opr_feach );
callg: exec_operand(opr_callg );
calll: exec_operand(opr_calll );
callv: exec_operand(opr_callv );
callvi: exec_operand(opr_callvi );
callh: exec_operand(opr_callh );
callfv: exec_operand(opr_callfv );
callfh: exec_operand(opr_callfh );
callb: exec_operand(opr_callb );
slcbegin:exec_operand(opr_slcbegin);
slcend: exec_operand(opr_slcend );
slc: exec_operand(opr_slc );
slc2: exec_operand(opr_slc2 );
mcallg: exec_operand(opr_mcallg );
mcalll: exec_operand(opr_mcalll );
mcallv: exec_operand(opr_mcallv );
mcallh: exec_operand(opr_mcallh );
ret: exec_operand(opr_ret );
}
#endif

View File

@ -15,10 +15,7 @@ var list=func()
_.end=tmp;
}
else
{
_.begin=tmp;
_.end=tmp;
}
_.begin=_.end=tmp;
return;
},
push_front:func(elem)
@ -31,10 +28,7 @@ var list=func()
_.begin=tmp;
}
else
{
_.begin=tmp;
_.end=tmp;
}
_.begin=_.end=tmp;
return;
},
pop_back:func()

View File

@ -3,9 +3,7 @@
var sort=func(vec,left,right,cmp=func(a,b){return a<=b;})
{
if(left>=right) return nil;
var L=left;
var R=right;
var tmp=vec[L];
var (L,R,tmp)=(left,right,vec[left]);
while(left<right)
{
while(left<right and cmp(tmp,vec[right]))
@ -13,14 +11,9 @@ var sort=func(vec,left,right,cmp=func(a,b){return a<=b;})
while(left<right and cmp(vec[left],tmp))
left+=1;
if(left!=right)
{
var t=vec[left];
vec[left]=vec[right];
vec[right]=t;
}
(vec[left],vec[right])=(vec[right],vec[left]);
}
vec[L]=vec[left];
vec[left]=tmp;
(vec[L],vec[left])=(vec[left],tmp);
sort(vec,L,left-1,cmp);
sort(vec,left+1,R,cmp);
return nil;