From 885b57cd52b6ae7b38cf1c41a965013b44bdf1c1 Mon Sep 17 00:00:00 2001 From: ValKmjolnir Date: Mon, 18 Oct 2021 19:59:41 +0800 Subject: [PATCH] add upvalue info into detail crash info --- nasal_gc.h | 59 +++---- nasal_vm.h | 477 +++++++++++++++++++++++++++-------------------------- 2 files changed, 273 insertions(+), 263 deletions(-) diff --git a/nasal_gc.h b/nasal_gc.h index 696c1b9..cae2b12 100644 --- a/nasal_gc.h +++ b/nasal_gc.h @@ -106,13 +106,13 @@ struct nasal_hash// 56 bytes struct nasal_func// 112 bytes { - int32_t dynpara; // dynamic parameter name index in hash - uint32_t entry; // pc will set to entry-1 to call this function - std::vector local; // local scope with default value(nasal_ref) - std::vector upvalue; // closure - std::unordered_map key_table; // parameter name table + uint32_t dynpara; // dynamic parameter index in hash. index 0 is reserved for 'me'. + uint32_t entry; // pc will set to entry-1 to call this function + std::vector local; // local scope with default value(nasal_ref) + std::vector upvalue; // closure + std::unordered_map keys; // parameter name table - nasal_func():dynpara(-1){} + nasal_func():dynpara(0){} void clear(); }; @@ -139,17 +139,17 @@ struct nasal_val// 16 bytes /*functions of nasal_vec*/ nasal_ref nasal_vec::get_val(const int index) { - int vec_size=elems.size(); - if(index<-vec_size || index>=vec_size) + int size=elems.size(); + if(index<-size || index>=size) return {vm_none}; - return elems[index>=0?index:index+vec_size]; + return elems[index>=0?index:index+size]; } nasal_ref* nasal_vec::get_mem(const int index) { - int vec_size=elems.size(); - if(index<-vec_size || index>=vec_size) + int size=elems.size(); + if(index<-size || index>=size) return nullptr; - return &elems[index>=0?index:index+vec_size]; + return &elems[index>=0?index:index+size]; } void nasal_vec::print() { @@ -212,15 +212,15 @@ nasal_ref* nasal_hash::get_mem(const std::string& key) return &elems[key]; else if(elems.count("parents")) { - nasal_ref* mem_addr=nullptr; + nasal_ref* addr=nullptr; nasal_ref val=elems["parents"]; if(val.type==vm_vec) for(auto& i:val.vec()->elems) { if(i.type==vm_hash) - mem_addr=i.hash()->get_mem(key); - if(mem_addr) - return mem_addr; + addr=i.hash()->get_mem(key); + if(addr) + return addr; } } return nullptr; @@ -265,9 +265,10 @@ void nasal_hash::print() /*functions of nasal_func*/ void nasal_func::clear() { - dynpara=-1; + dynpara=0; local.clear(); - key_table.clear(); + upvalue.clear(); + keys.clear(); return; } @@ -332,9 +333,9 @@ struct nasal_gc nasal_ref zero; // reserved address of nasal_val,type vm_num, 0 nasal_ref one; // reserved address of nasal_val,type vm_num, 1 nasal_ref nil; // reserved address of nasal_val,type vm_nil - nasal_ref val_stack[STACK_MAX_DEPTH+1];// 1 reserved to avoid stack overflow - nasal_ref* stack_top; // stack top - std::vector str_addrs; // reserved address for const vm_str + nasal_ref stack[STACK_MAX_DEPTH+1];// 1 reserved to avoid stack overflow + nasal_ref* top; // stack top + std::vector strs; // reserved address for const vm_str std::vector memory; // gc memory std::queue free_list[vm_type_size]; // gc free list std::vector local; @@ -352,7 +353,7 @@ void nasal_gc::mark() std::queue bfs; for(auto& i:local) bfs.push(i); - for(nasal_ref* i=val_stack;i<=stack_top;++i) + for(nasal_ref* i=stack;i<=top;++i) bfs.push(*i); while(!bfs.empty()) { @@ -406,7 +407,7 @@ void nasal_gc::sweep() } return; } -void nasal_gc::init(const std::vector& strs) +void nasal_gc::init(const std::vector& s) { for(uint8_t i=vm_str;i& strs) free_list[i].push(tmp); } - stack_top=val_stack; // set stack_top to val_stack + top=stack; // set top to stack zero={vm_num,(double)0}; // init constant 0 one ={vm_num,(double)1}; // init constant 1 nil ={vm_nil,(double)0}; // init constant nil // init constant strings - str_addrs.resize(strs.size()); + strs.resize(s.size()); for(uint32_t i=0;i ret; // ptr stack stores address for function to return std::stack func_stk; // stack to store function,this is used when getting upvalues std::stack counter; // iterator stack for forindex/foreach @@ -61,25 +61,25 @@ private: void opr_sub(); void opr_mul(); void opr_div(); - void opr_lnk();// + void opr_lnk(); void opr_addc(); void opr_subc(); void opr_mulc(); void opr_divc(); - void opr_lnkc();// + void opr_lnkc(); void opr_addeq(); void opr_subeq(); void opr_muleq(); void opr_diveq(); - void opr_lnkeq();// + void opr_lnkeq(); void opr_addeqc(); void opr_subeqc(); void opr_muleqc(); void opr_diveqc(); - void opr_lnkeqc();// + void opr_lnkeqc(); void opr_meq(); - void opr_eq();// - void opr_neq();// + void opr_eq(); + void opr_neq(); void opr_less(); void opr_leq(); void opr_grt(); @@ -99,24 +99,24 @@ private: void opr_callg(); void opr_calll(); void opr_upval(); - void opr_callv();// - void opr_callvi();// - void opr_callh();// - void opr_callfv();// - void opr_callfh();// + void opr_callv(); + void opr_callvi(); + void opr_callh(); + void opr_callfv(); + void opr_callfh(); void opr_callb(); void opr_slcbegin(); void opr_slcend(); - void opr_slc();// - void opr_slc2();// + void opr_slc(); + void opr_slc2(); void opr_mcallg(); void opr_mcalll(); void opr_mupval(); - void opr_mcallv();// + void opr_mcallv(); void opr_mcallh(); void opr_ret(); public: - nasal_vm():stack_top(gc.stack_top){} + nasal_vm():top(gc.top){} ~nasal_vm(){clear();} void run( const nasal_codegen&, @@ -147,17 +147,17 @@ void nasal_vm::clear() } void nasal_vm::valinfo(nasal_ref& val) { - const nasal_val* ptr=val.value.gcobj; + const nasal_val* p=val.value.gcobj; switch(val.type) { case vm_none: printf("\tnull |\n");break; case vm_nil: printf("\tnil |\n");break; case vm_num: printf("\tnum | %lf\n",val.num());break; - case vm_str: printf("\tstr | <%p> %s\n",ptr,raw_string(*val.str()).c_str());break; - case vm_func: printf("\tfunc | <%p> func{entry=0x%x}\n",ptr,val.func()->entry);break; - case vm_vec: printf("\tvec | <%p> [%lu val]\n",ptr,val.vec()->elems.size());break; - case vm_hash: printf("\thash | <%p> {%lu member}\n",ptr,val.hash()->elems.size());break; - case vm_obj: printf("\tobj | <%p>\n",ptr);break; + case vm_str: printf("\tstr | <%p> %s\n",p,raw_string(*val.str()).c_str());break; + case vm_func: printf("\tfunc | <%p> func{entry=0x%x}\n",p,val.func()->entry);break; + case vm_vec: printf("\tvec | <%p> [%lu val]\n",p,val.vec()->elems.size());break; + case vm_hash: printf("\thash | <%p> {%lu member}\n",p,val.hash()->elems.size());break; + case vm_obj: printf("\tobj | <%p>\n",p);break; } } void nasal_vm::bytecodeinfo(const uint32_t p) @@ -173,61 +173,63 @@ void nasal_vm::traceback() // push pc to ret stack to store the position program crashed ret.push(pc); printf("trace back:\n"); - uint32_t same_cnt=0,last_point=0xffffffff; - for(uint32_t point=0;!ret.empty();last_point=point,ret.pop()) + uint32_t same=0,last=0xffffffff; + for(uint32_t point=0;!ret.empty();last=point,ret.pop()) { point=ret.top(); - if(point==last_point) + if(point==last) { - ++same_cnt; + ++same; continue; } - if(same_cnt) + if(same) { - printf("\t0x%.8x: %d same call(s) ...\n",last_point,same_cnt); - same_cnt=0; + printf("\t0x%.8x: %d same call(s) ...\n",last,same); + same=0; } bytecodeinfo(point); } - if(same_cnt) - printf("\t0x%.8x: %d same call(s) ...\n",last_point,same_cnt); + if(same) + printf("\t0x%.8x: %d same call(s) ...\n",last,same); } -void nasal_vm::stackinfo(const uint32_t limit) +void nasal_vm::stackinfo(const uint32_t limit=10) { printf("vm stack(limit %d):\n",limit); - uint32_t same_cnt=0; - nasal_ref last_ptr={vm_none,0xffffffff}; - for(uint32_t i=0;i=gc.val_stack;++i,--stack_top) + uint32_t same=0,global_size=bytecode[0].num; + nasal_ref last={vm_none,0xffffffff}; + for(uint32_t i=0;i=gc.stack+global_size;++i,--top) { - if(stack_top[0]==last_ptr) + if(top[0]==last) { - ++same_cnt; + ++same; continue; } - if(same_cnt) + if(same) { - printf("\t... | %d same value(s)\n",same_cnt); - same_cnt=0; + printf("\t... | %d same value(s)\n",same); + same=0; } - last_ptr=stack_top[0]; - valinfo(stack_top[0]); + last=top[0]; + valinfo(top[0]); } - if(same_cnt) - printf("\t... | %d same value(s)\n",same_cnt); + if(same) + printf("\t... | %d same value(s)\n",same); } void nasal_vm::detail() { printf("mcall address: %p\n",mem_addr); - printf("global value:\n"); - // bytecode[0] is op_intg - for(uint32_t i=0;ielems; for(uint32_t i=0;iupvalue.empty()) + { + printf("upvalue:\n"); + auto& upval=func_stk.top()->upvalue; + for(uint32_t i=0;ielems; + for(uint32_t j=0;jlocal.resize(imm[pc],gc.nil); + top[0].func()->local.resize(imm[pc],gc.nil); } inline void nasal_vm::opr_loadg() { - gc.val_stack[imm[pc]]=(stack_top--)[0]; + gc.stack[imm[pc]]=(top--)[0]; } inline void nasal_vm::opr_loadl() { - gc.local.back().vec()->elems[imm[pc]]=(stack_top--)[0]; + gc.local.back().vec()->elems[imm[pc]]=(top--)[0]; } inline void nasal_vm::opr_loadu() { - func_stk.top()->upvalue[(imm[pc]>>16)&0xffff].vec()->elems[imm[pc]&0xffff]=(stack_top--)[0]; + func_stk.top()->upvalue[(imm[pc]>>16)&0xffff].vec()->elems[imm[pc]&0xffff]=(top--)[0]; } inline void nasal_vm::opr_pnum() { - (++stack_top)[0]={vm_num,num_table[imm[pc]]}; + (++top)[0]={vm_num,num_table[imm[pc]]}; } inline void nasal_vm::opr_pone() { - (++stack_top)[0]={vm_num,(double)1}; + (++top)[0]={vm_num,(double)1}; } inline void nasal_vm::opr_pzero() { - (++stack_top)[0]={vm_num,(double)0}; + (++top)[0]={vm_num,(double)0}; } inline void nasal_vm::opr_pnil() { - (++stack_top)[0].type=vm_nil; + (++top)[0].type=vm_nil; } inline void nasal_vm::opr_pstr() { - (++stack_top)[0]=gc.str_addrs[imm[pc]]; + (++top)[0]=gc.strs[imm[pc]]; } inline void nasal_vm::opr_newv() { - nasal_ref vec_addr=gc.alloc(vm_vec); - nasal_ref* begin=stack_top-imm[pc]+1; - auto& vec=vec_addr.vec()->elems;// stack_top-imm[pc] stores the vector + nasal_ref newv=gc.alloc(vm_vec); + auto& vec=newv.vec()->elems;// top-imm[pc] stores the vector vec.resize(imm[pc]); + top-=imm[pc]-1; for(uint32_t i=0;ientry=imm[pc]; + offset=1; + (++top)[0]=gc.alloc(vm_func); + top[0].func()->entry=imm[pc]; if(!gc.local.empty()) { - stack_top[0].func()->upvalue=func_stk.top()->upvalue; - stack_top[0].func()->upvalue.push_back(gc.local.back()); + top[0].func()->upvalue=func_stk.top()->upvalue; + top[0].func()->upvalue.push_back(gc.local.back()); } } inline void nasal_vm::opr_happ() { - stack_top[-1].hash()->elems[str_table[imm[pc]]]=stack_top[0]; - --stack_top; + top[-1].hash()->elems[str_table[imm[pc]]]=top[0]; + --top; } inline void nasal_vm::opr_para() { - nasal_func* func=stack_top[0].func(); - size_t size=func->key_table.size(); - func->key_table[str_table[imm[pc]]]=size; - func->local[newf_off]={vm_none}; - ++newf_off; + nasal_func* func=top[0].func(); + size_t size=func->keys.size(); + func->keys[str_table[imm[pc]]]=size; + func->local[offset++]={vm_none}; } inline void nasal_vm::opr_defpara() { - nasal_ref def_val=stack_top[0]; - nasal_func* func=(--stack_top)[0].func(); - size_t size=func->key_table.size(); - func->key_table[str_table[imm[pc]]]=size; - func->local[newf_off]=def_val; - ++newf_off; + nasal_ref val=top[0]; + nasal_func* func=(--top)[0].func(); + size_t size=func->keys.size(); + func->keys[str_table[imm[pc]]]=size; + func->local[offset++]=val; } inline void nasal_vm::opr_dynpara() { - stack_top[0].func()->dynpara=imm[pc]; + top[0].func()->dynpara=imm[pc]; } inline void nasal_vm::opr_unot() { - nasal_ref val=stack_top[0]; + nasal_ref val=top[0]; switch(val.type) { - case vm_nil:stack_top[0]=gc.zero;break; - case vm_num:stack_top[0]=val.num()?gc.zero:gc.one;break; + case vm_nil:top[0]=gc.zero;break; + case vm_num:top[0]=val.num()?gc.zero:gc.one;break; case vm_str: { double num=str2num(val.str()->c_str()); if(std::isnan(num)) - stack_top[0]=val.str()->empty()?gc.one:gc.zero; + top[0]=val.str()->empty()?gc.one:gc.zero; else - stack_top[0]=num?gc.zero:gc.one; + top[0]=num?gc.zero:gc.one; } break; default:die("unot: incorrect value type");break; @@ -395,12 +408,12 @@ inline void nasal_vm::opr_unot() } inline void nasal_vm::opr_usub() { - stack_top[0]={vm_num,-stack_top[0].to_number()}; + top[0]={vm_num,-top[0].to_number()}; } #define op_calc(type)\ - nasal_ref new_val(vm_num,stack_top[-1].to_number() type stack_top[0].to_number());\ - (--stack_top)[0]=new_val; + nasal_ref val(vm_num,top[-1].to_number() type top[0].to_number());\ + (--top)[0]=val; inline void nasal_vm::opr_add(){op_calc(+);} inline void nasal_vm::opr_sub(){op_calc(-);} @@ -408,14 +421,14 @@ inline void nasal_vm::opr_mul(){op_calc(*);} inline void nasal_vm::opr_div(){op_calc(/);} inline void nasal_vm::opr_lnk() { - nasal_ref new_val=gc.alloc(vm_str); - *new_val.str()=stack_top[-1].to_string()+stack_top[0].to_string(); - (--stack_top)[0]=new_val; + nasal_ref val=gc.alloc(vm_str); + *val.str()=top[-1].to_string()+top[0].to_string(); + (--top)[0]=val; } #define op_calc_const(type)\ - nasal_ref new_val(vm_num,stack_top[0].to_number() type num_table[imm[pc]]);\ - stack_top[0]=new_val; + nasal_ref val(vm_num,top[0].to_number() type num_table[imm[pc]]);\ + top[0]=val; inline void nasal_vm::opr_addc(){op_calc_const(+);} inline void nasal_vm::opr_subc(){op_calc_const(-);} @@ -423,14 +436,14 @@ inline void nasal_vm::opr_mulc(){op_calc_const(*);} inline void nasal_vm::opr_divc(){op_calc_const(/);} inline void nasal_vm::opr_lnkc() { - nasal_ref new_val=gc.alloc(vm_str); - *new_val.str()=stack_top[0].to_string()+str_table[imm[pc]]; - stack_top[0]=new_val; + nasal_ref val=gc.alloc(vm_str); + *val.str()=top[0].to_string()+str_table[imm[pc]]; + top[0]=val; } #define op_calc_eq(type)\ - nasal_ref new_val(vm_num,mem_addr[0].to_number() type stack_top[-1].to_number());\ - (--stack_top)[0]=mem_addr[0]=new_val; + nasal_ref val(vm_num,mem_addr[0].to_number() type top[-1].to_number());\ + (--top)[0]=mem_addr[0]=val; inline void nasal_vm::opr_addeq(){op_calc_eq(+);} inline void nasal_vm::opr_subeq(){op_calc_eq(-);} @@ -438,14 +451,14 @@ inline void nasal_vm::opr_muleq(){op_calc_eq(*);} inline void nasal_vm::opr_diveq(){op_calc_eq(/);} inline void nasal_vm::opr_lnkeq() { - nasal_ref new_val=gc.alloc(vm_str); - *new_val.str()=mem_addr[0].to_string()+stack_top[-1].to_string(); - (--stack_top)[0]=mem_addr[0]=new_val; + nasal_ref val=gc.alloc(vm_str); + *val.str()=mem_addr[0].to_string()+top[-1].to_string(); + (--top)[0]=mem_addr[0]=val; } #define op_calc_eq_const(type)\ - nasal_ref new_val(vm_num,mem_addr[0].to_number() type num_table[imm[pc]]);\ - stack_top[0]=mem_addr[0]=new_val; + nasal_ref val(vm_num,mem_addr[0].to_number() type num_table[imm[pc]]);\ + top[0]=mem_addr[0]=val; inline void nasal_vm::opr_addeqc(){op_calc_eq_const(+);} inline void nasal_vm::opr_subeqc(){op_calc_eq_const(-);} @@ -453,49 +466,49 @@ inline void nasal_vm::opr_muleqc(){op_calc_eq_const(*);} inline void nasal_vm::opr_diveqc(){op_calc_eq_const(/);} inline void nasal_vm::opr_lnkeqc() { - nasal_ref new_val=gc.alloc(vm_str); - *new_val.str()=mem_addr[0].to_string()+str_table[imm[pc]]; - stack_top[0]=mem_addr[0]=new_val; + nasal_ref val=gc.alloc(vm_str); + *val.str()=mem_addr[0].to_string()+str_table[imm[pc]]; + top[0]=mem_addr[0]=val; } inline void nasal_vm::opr_meq() { - mem_addr[0]=(--stack_top)[0]; + mem_addr[0]=(--top)[0]; } inline void nasal_vm::opr_eq() { - nasal_ref val2=stack_top[0]; - nasal_ref val1=(--stack_top)[0]; + nasal_ref val2=top[0]; + nasal_ref val1=(--top)[0]; uint8_t a_type=val1.type; uint8_t b_type=val2.type; if(a_type==vm_nil && b_type==vm_nil) - stack_top[0]=gc.one; + top[0]=gc.one; else if(a_type==vm_str && b_type==vm_str) - stack_top[0]=(*val1.str()==*val2.str())?gc.one:gc.zero; + top[0]=(*val1.str()==*val2.str())?gc.one:gc.zero; else if(a_type==vm_num || b_type==vm_num) - stack_top[0]=(val1.to_number()==val2.to_number())?gc.one:gc.zero; + top[0]=(val1.to_number()==val2.to_number())?gc.one:gc.zero; else - stack_top[0]=(val1==val2)?gc.one:gc.zero; + top[0]=(val1==val2)?gc.one:gc.zero; } inline void nasal_vm::opr_neq() { - nasal_ref val2=stack_top[0]; - nasal_ref val1=(--stack_top)[0]; + nasal_ref val2=top[0]; + nasal_ref val1=(--top)[0]; uint8_t a_type=val1.type; uint8_t b_type=val2.type; if(a_type==vm_nil && b_type==vm_nil) - stack_top[0]=gc.zero; + top[0]=gc.zero; else if(a_type==vm_str && b_type==vm_str) - stack_top[0]=(*val1.str()!=*val2.str())?gc.one:gc.zero; + top[0]=(*val1.str()!=*val2.str())?gc.one:gc.zero; else if(a_type==vm_num || b_type==vm_num) - stack_top[0]=(val1.to_number()!=val2.to_number())?gc.one:gc.zero; + top[0]=(val1.to_number()!=val2.to_number())?gc.one:gc.zero; else - stack_top[0]=(val1!=val2)?gc.one:gc.zero; + top[0]=(val1!=val2)?gc.one:gc.zero; } #define op_cmp(type)\ - --stack_top;\ - stack_top[0]=(stack_top[0].to_number() type stack_top[1].to_number())?gc.one:gc.zero; + --top;\ + top[0]=(top[0].to_number() type top[1].to_number())?gc.one:gc.zero; inline void nasal_vm::opr_less(){op_cmp(<);} inline void nasal_vm::opr_leq(){op_cmp(<=);} @@ -503,7 +516,7 @@ inline void nasal_vm::opr_grt(){op_cmp(>);} inline void nasal_vm::opr_geq(){op_cmp(>=);} #define op_cmp_const(type)\ - stack_top[0]=(stack_top[0].to_number() type num_table[imm[pc]])?gc.one:gc.zero; + top[0]=(top[0].to_number() type num_table[imm[pc]])?gc.one:gc.zero; inline void nasal_vm::opr_lessc(){op_cmp_const(<);} inline void nasal_vm::opr_leqc(){op_cmp_const(<=);} @@ -512,7 +525,7 @@ inline void nasal_vm::opr_geqc(){op_cmp_const(>=);} inline void nasal_vm::opr_pop() { - --stack_top; + --top; } inline void nasal_vm::opr_jmp() { @@ -520,19 +533,19 @@ inline void nasal_vm::opr_jmp() } inline void nasal_vm::opr_jt() { - if(condition(stack_top[0])) + if(condition(top[0])) pc=imm[pc]-1; } inline void nasal_vm::opr_jf() { - if(!condition(stack_top[0])) + if(!condition(top[0])) pc=imm[pc]-1; - --stack_top; + --top; } inline void nasal_vm::opr_counter() { counter.push(-1); - if(stack_top[0].type!=vm_vec) + if(top[0].type!=vm_vec) die("cnt: must use vector in forindex/foreach"); } inline void nasal_vm::opr_cntpop() @@ -541,54 +554,54 @@ inline void nasal_vm::opr_cntpop() } inline void nasal_vm::opr_findex() { - if(++counter.top()>=stack_top[0].vec()->elems.size()) + if(++counter.top()>=top[0].vec()->elems.size()) { pc=imm[pc]-1; return; } - (++stack_top)[0]={vm_num,static_cast(counter.top())}; + (++top)[0]={vm_num,static_cast(counter.top())}; } inline void nasal_vm::opr_feach() { - std::vector& ref=stack_top[0].vec()->elems; + std::vector& ref=top[0].vec()->elems; if(++counter.top()>=ref.size()) { pc=imm[pc]-1; return; } - (++stack_top)[0]=ref[counter.top()]; + (++top)[0]=ref[counter.top()]; } inline void nasal_vm::opr_callg() { - (++stack_top)[0]=gc.val_stack[imm[pc]]; + (++top)[0]=gc.stack[imm[pc]]; } inline void nasal_vm::opr_calll() { - (++stack_top)[0]=gc.local.back().vec()->elems[imm[pc]]; + (++top)[0]=gc.local.back().vec()->elems[imm[pc]]; } inline void nasal_vm::opr_upval() { - (++stack_top)[0]=func_stk.top()->upvalue[(imm[pc]>>16)&0xffff].vec()->elems[imm[pc]&0xffff]; + (++top)[0]=func_stk.top()->upvalue[(imm[pc]>>16)&0xffff].vec()->elems[imm[pc]&0xffff]; } inline void nasal_vm::opr_callv() { - nasal_ref val=stack_top[0]; - nasal_ref vec=(--stack_top)[0]; + nasal_ref val=top[0]; + nasal_ref vec=(--top)[0]; if(vec.type==vm_vec) { - stack_top[0]=vec.vec()->get_val(val.to_number()); - if(stack_top[0].type==vm_none) + top[0]=vec.vec()->get_val(val.to_number()); + if(top[0].type==vm_none) die("callv: index out of range:"+std::to_string(val.to_number())); } else if(vec.type==vm_hash) { if(val.type!=vm_str) die("callv: must use string as the key"); - stack_top[0]=vec.hash()->get_val(*val.value.gcobj->ptr.str); - if(stack_top[0].type==vm_none) + top[0]=vec.hash()->get_val(*val.value.gcobj->ptr.str); + if(top[0].type==vm_none) die("callv: cannot find member \""+*val.str()+"\" of this hash"); - if(stack_top[0].type==vm_func) - stack_top[0].func()->local[0]=val;// me + if(top[0].type==vm_func) + top[0].func()->local[0]=val;// me } else if(vec.type==vm_str) { @@ -597,194 +610,190 @@ inline void nasal_vm::opr_callv() int str_size=str.length(); if(num<-str_size || num>=str_size) die("callv: index out of range:"+std::to_string(val.to_number())); - stack_top[0]={vm_num,static_cast(str[num>=0? num:num+str_size])}; + top[0]={vm_num,static_cast(str[num>=0? num:num+str_size])}; } else die("callv: must call a vector/hash/string"); } inline void nasal_vm::opr_callvi() { - nasal_ref val=stack_top[0]; + nasal_ref val=top[0]; if(val.type!=vm_vec) die("callvi: must use a vector"); // cannot use operator[],because this may cause overflow - (++stack_top)[0]=val.vec()->get_val(imm[pc]); - if(stack_top[0].type==vm_none) + (++top)[0]=val.vec()->get_val(imm[pc]); + if(top[0].type==vm_none) die("callvi: index out of range:"+std::to_string(imm[pc])); } inline void nasal_vm::opr_callh() { - nasal_ref val=stack_top[0]; + nasal_ref val=top[0]; if(val.type!=vm_hash) die("callh: must call a hash"); - stack_top[0]=val.hash()->get_val(str_table[imm[pc]]); - if(stack_top[0].type==vm_none) + top[0]=val.hash()->get_val(str_table[imm[pc]]); + if(top[0].type==vm_none) die("callh: member \""+str_table[imm[pc]]+"\" does not exist"); - if(stack_top[0].type==vm_func) - stack_top[0].func()->local[0]=val;// me + if(top[0].type==vm_func) + top[0].func()->local[0]=val;// me } inline void nasal_vm::opr_callfv() { - // get parameter list and function value - uint32_t args_size=imm[pc]; - nasal_ref* vec=stack_top-args_size+1; - nasal_ref func_addr=vec[-1]; - if(func_addr.type!=vm_func) + size_t args_size=imm[pc]; + nasal_ref* args=top-args_size+1; + if(args[-1].type!=vm_func) die("callfv: must call a function"); // push new local scope - func_stk.push(func_addr.func()); - auto& ref_func=*func_addr.func(); + func_stk.push(args[-1].func()); + auto& func=*args[-1].func(); gc.local.push_back(gc.alloc(vm_vec)); - gc.local.back().vec()->elems=ref_func.local; + gc.local.back().vec()->elems=func.local; // load parameters - auto& ref_closure=gc.local.back().vec()->elems; + auto& closure=gc.local.back().vec()->elems; - uint32_t para_size=ref_func.key_table.size(); + size_t para_size=func.keys.size(); // load arguments // if the first default value is not vm_none,then values after it are not nullptr - if(args_sizepara_size,for 0 to args_size will cause corruption - uint32_t min_size=std::min(para_size,args_size); + size_t min_size=std::min(para_size,args_size); for(uint32_t i=0;i=para_size - if(ref_func.dynpara>=0) + if(func.dynpara) { - nasal_ref vec_addr=gc.alloc(vm_vec); + nasal_ref vec=gc.alloc(vm_vec); for(uint32_t i=para_size;ielems.push_back(vec[i]); - ref_closure.back()=vec_addr; + vec.vec()->elems.push_back(args[i]); + closure.back()=vec; } - stack_top-=args_size;// pop arguments + top-=args_size;// pop arguments ret.push(pc); - pc=ref_func.entry-1; + pc=func.entry-1; } inline void nasal_vm::opr_callfh() { // get parameter list and function value - auto& ref_hash=stack_top[0].hash()->elems; - nasal_ref func_addr=stack_top[-1]; - if(func_addr.type!=vm_func) + auto& hash=top[0].hash()->elems; + if(top[-1].type!=vm_func) die("callfh: must call a function"); // push new local scope - func_stk.push(func_addr.func()); - auto& ref_func=*func_addr.func(); + func_stk.push(top[-1].func()); + auto& func=*top[-1].func(); gc.local.push_back(gc.alloc(vm_vec)); - gc.local.back().vec()->elems=ref_func.local; + gc.local.back().vec()->elems=func.local; // load parameters - - auto& ref_closure=gc.local.back().vec()->elems; - if(ref_func.dynpara>=0) + auto& closure=gc.local.back().vec()->elems; + if(func.dynpara) die("callfh: special call cannot use dynamic argument"); - for(auto& i:ref_func.key_table) + for(auto& i:func.keys) { - if(ref_hash.count(i.first)) - ref_closure[i.second+1]=ref_hash[i.first]; - else if(ref_func.local[i.second+1/*1 is reserved for 'me'*/].type==vm_none) + if(hash.count(i.first)) + closure[i.second+1]=hash[i.first]; + else if(func.local[i.second+1/*1 is reserved for 'me'*/].type==vm_none) die("callfh: lack argument(s): \""+i.first+"\""); } - --stack_top;// pop hash + --top;// pop hash ret.push(pc); - pc=ref_func.entry-1; + pc=func.entry-1; } inline void nasal_vm::opr_callb() { - (++stack_top)[0]=(*builtin_func[imm[pc]].func)(gc.local.back().vec()->elems,gc); - if(stack_top[0].type==vm_none) + (++top)[0]=(*builtin_func[imm[pc]].func)(gc.local.back().vec()->elems,gc); + if(top[0].type==vm_none) die("native function error."); } inline void nasal_vm::opr_slcbegin() { - // | slice_vector | <-- stack_top[0] + // | slice_vector | <-- top[0] // ---------------- - // | resource_vec | <-- stack_top[-1] + // | resource_vec | <-- top[-1] // ---------------- - (++stack_top)[0]=gc.alloc(vm_vec); - if(stack_top[-1].type!=vm_vec) + (++top)[0]=gc.alloc(vm_vec); + if(top[-1].type!=vm_vec) die("slcbegin: must slice a vector"); } inline void nasal_vm::opr_slcend() { - stack_top[-1]=stack_top[0]; - --stack_top; + top[-1]=top[0]; + --top; } inline void nasal_vm::opr_slc() { - nasal_ref val=(stack_top--)[0]; - nasal_ref res=stack_top[-1].vec()->get_val(val.to_number()); + nasal_ref val=(top--)[0]; + nasal_ref res=top[-1].vec()->get_val(val.to_number()); if(res.type==vm_none) die("slc: index out of range:"+std::to_string(val.to_number())); - stack_top[0].vec()->elems.push_back(res); + top[0].vec()->elems.push_back(res); } inline void nasal_vm::opr_slc2() { - nasal_ref val2=(stack_top--)[0]; - nasal_ref val1=(stack_top--)[0]; - std::vector& ref=stack_top[-1].vec()->elems; - std::vector& aim=stack_top[0].vec()->elems; + nasal_ref val2=(top--)[0]; + nasal_ref val1=(top--)[0]; + std::vector& ref=top[-1].vec()->elems; + std::vector& aim=top[0].vec()->elems; uint8_t type1=val1.type,type2=val2.type; int num1=val1.to_number(); int num2=val2.to_number(); - int ref_size=ref.size(); + size_t size=ref.size(); if(type1==vm_nil && type2==vm_nil) { num1=0; - num2=ref_size-1; + num2=size-1; } else if(type1==vm_nil && type2!=vm_nil) - num1=num2<0? -ref_size:0; + num1=num2<0? -size:0; else if(type1!=vm_nil && type2==vm_nil) - num2=num1<0? -1:ref_size-1; + num2=num1<0? -1:size-1; if(num1>=num2) die("slc2: begin index must be less than end index"); - else if(num1<-ref_size || num1>=ref_size) + else if(num1<-size || num1>=size) die("slc2: begin index out of range: "+std::to_string(num1)); - else if(num2<-ref_size || num2>=ref_size) + else if(num2<-size || num2>=size) die("slc2: end index out of range: "+std::to_string(num2)); else for(int i=num1;i<=num2;++i) - aim.push_back(i>=0?ref[i]:ref[i+ref_size]); + aim.push_back(i>=0?ref[i]:ref[i+size]); } inline void nasal_vm::opr_mcallg() { - mem_addr=gc.val_stack+imm[pc]; - (++stack_top)[0]=mem_addr[0]; + mem_addr=gc.stack+imm[pc]; + (++top)[0]=mem_addr[0]; } inline void nasal_vm::opr_mcalll() { mem_addr=&(gc.local.back().vec()->elems[imm[pc]]); - (++stack_top)[0]=mem_addr[0]; + (++top)[0]=mem_addr[0]; } inline void nasal_vm::opr_mupval() { mem_addr=&func_stk.top()->upvalue[(imm[pc]>>16)&0xffff].vec()->elems[imm[pc]&0xffff]; - (++stack_top)[0]=mem_addr[0]; + (++top)[0]=mem_addr[0]; } inline void nasal_vm::opr_mcallv() { - nasal_ref val=stack_top[0]; - nasal_ref vec_addr=(--stack_top)[0]; - if(vec_addr.type==vm_vec) + nasal_ref val=top[0]; + nasal_ref vec=(--top)[0]; + if(vec.type==vm_vec) { - mem_addr=vec_addr.vec()->get_mem(val.to_number()); + mem_addr=vec.vec()->get_mem(val.to_number()); if(!mem_addr) die("mcallv: index out of range:"+std::to_string(val.to_number())); } - else if(vec_addr.type==vm_hash) + else if(vec.type==vm_hash) { if(val.type!=vm_str) die("mcallv: must use string as the key"); - nasal_hash& ref=*vec_addr.hash(); + nasal_hash& ref=*vec.hash(); std::string& str=*val.str(); mem_addr=ref.get_mem(str); if(!mem_addr) @@ -798,10 +807,10 @@ inline void nasal_vm::opr_mcallv() } inline void nasal_vm::opr_mcallh() { - nasal_ref hash_addr=stack_top[0]; - if(hash_addr.type!=vm_hash) + nasal_ref hash=top[0]; + if(hash.type!=vm_hash) die("mcallh: must call a hash"); - nasal_hash& ref=*hash_addr.hash(); + nasal_hash& ref=*hash.hash(); std::string& str=str_table[imm[pc]]; mem_addr=ref.get_mem(str); if(!mem_addr) // create a new key @@ -814,9 +823,9 @@ inline void nasal_vm::opr_ret() { // get nasal_func and set 'me' to nil // and rewrite nasal_func with returned value - stack_top[-1].func()->local[0]={vm_nil}; - --stack_top; - stack_top[0]=stack_top[1]; + top[-1].func()->local[0]={vm_nil}; + --top; + top[0]=top[1]; func_stk.pop(); // pop function stack gc.local.pop_back(); // pop local scope @@ -826,7 +835,7 @@ void nasal_vm::run( const nasal_codegen& gen, const nasal_import& linker, const bool opcnt, - const bool debug=false) + const bool debug) { detail_info=debug; init(gen.get_strs(),gen.get_nums(),linker.get_file()); @@ -863,7 +872,7 @@ void nasal_vm::run( } // set canary and program counter - auto& canary=gc.val_stack[STACK_MAX_DEPTH-1]; + auto& canary=gc.stack[STACK_MAX_DEPTH-1]; canary.value.gcobj=nullptr; pc=0; // goto the first operand