change instruction dispatch to computed-goto
bug fixed prepare for version 7.0
This commit is contained in:
parent
3c9a10d710
commit
706659ba3d
31
README.md
31
README.md
|
@ -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.
|
||||
|
||||
|
|
12
main.cpp
12
main.cpp
|
@ -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]!='-')
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
332
nasal_vm.h
332
nasal_vm.h
|
@ -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, &¶,
|
||||
&&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
|
10
stl/list.nas
10
stl/list.nas
|
@ -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()
|
||||
|
|
13
stl/sort.nas
13
stl/sort.nas
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue