From aa191a9feb768e21a214e70c717c3a67a2880b56 Mon Sep 17 00:00:00 2001 From: ValKmjolnir Date: Thu, 2 Dec 2021 22:23:22 +0800 Subject: [PATCH] delete ret stack/ add math.lg now return address is stored on value stack --- lib.nas | 3 +- nasal_builtin.h | 11 ++++- nasal_codegen.h | 2 +- nasal_gc.h | 10 ++++- nasal_vm.h | 117 +++++++++++++++++++++--------------------------- stl/lib.nas | 3 +- 6 files changed, 75 insertions(+), 71 deletions(-) diff --git a/lib.nas b/lib.nas index 77fa6a1..5e5d5ff 100644 --- a/lib.nas +++ b/lib.nas @@ -68,7 +68,8 @@ var math= sin: func(x) {return __builtin_sin(x); }, cos: func(x) {return __builtin_cos(x); }, tan: func(x) {return __builtin_tan(x); }, - exp: func(x) {return __builtin_exp(x); }, + exp: func(x) {return __builtin_exp(x); }, + lg: func(x) {return __builtin_lg(x); }, ln: func(x) {return __builtin_ln(x); }, sqrt: func(x) {return __builtin_sqrt(x); }, atan2: func(x,y){return __builtin_atan2(x,y);}, diff --git a/nasal_builtin.h b/nasal_builtin.h index b5b3ce4..4e9862f 100644 --- a/nasal_builtin.h +++ b/nasal_builtin.h @@ -39,6 +39,7 @@ nas_native(builtin_sin); nas_native(builtin_cos); nas_native(builtin_tan); nas_native(builtin_exp); +nas_native(builtin_lg); nas_native(builtin_ln); nas_native(builtin_sqrt); nas_native(builtin_atan2); @@ -115,6 +116,7 @@ struct {"__builtin_cos", builtin_cos }, {"__builtin_tan", builtin_tan }, {"__builtin_exp", builtin_exp }, + {"__builtin_lg", builtin_lg }, {"__builtin_ln", builtin_ln }, {"__builtin_sqrt", builtin_sqrt }, {"__builtin_atan2", builtin_atan2 }, @@ -467,12 +469,19 @@ nasal_ref builtin_exp(std::vector& local,nasal_gc& gc) return builtin_err("exp","\"x\" must be number"); return {vm_num,exp(val.num())}; } +nasal_ref builtin_lg(std::vector& local,nasal_gc& gc) +{ + nasal_ref val=local[1]; + if(val.type!=vm_num) + return builtin_err("ln","\"x\" must be number"); + return {vm_num,log(val.num())/log(10.0)}; +} nasal_ref builtin_ln(std::vector& local,nasal_gc& gc) { nasal_ref val=local[1]; if(val.type!=vm_num) return builtin_err("ln","\"x\" must be number"); - return {vm_num,log(val.num())/log(2.7182818284590452354)}; + return {vm_num,log(val.num())}; } nasal_ref builtin_sqrt(std::vector& local,nasal_gc& gc) { diff --git a/nasal_codegen.h b/nasal_codegen.h index 19bae0a..811faf4 100644 --- a/nasal_codegen.h +++ b/nasal_codegen.h @@ -1237,7 +1237,7 @@ void nasal_codegen::print_op(uint32_t index) case op_newf: case op_jmp: case op_jt: case op_jf: printf("0x%x\n",c.num);break; case op_callb: - printf("0x%x <%s>\n",c.num,builtin[c.num].name);break; + printf("0x%x <%s@0x%lx>\n",c.num,builtin[c.num].name,(uint64_t)builtin[c.num].func);break; case op_callg: case op_mcallg: case op_loadg: case op_calll: case op_mcalll: case op_loadl: printf("0x%x\n",c.num);break; diff --git a/nasal_gc.h b/nasal_gc.h index e060cff..a87b068 100644 --- a/nasal_gc.h +++ b/nasal_gc.h @@ -6,6 +6,7 @@ enum nasal_type /* none-gc object */ vm_none=0, vm_cnt, + vm_ret, vm_nil, vm_num, /* gc object */ @@ -24,6 +25,7 @@ const uint32_t increment[vm_type_size]= /* none-gc object */ 0, // vm_none, error type 0, // vm_count, used in foreach/forindex + 0, // vm_ret, used to store call-return address 0, // vm_nil 0, // vm_num /* gc object */ @@ -45,12 +47,14 @@ struct nasal_ref uint8_t type; union { - int64_t cnt; - double num; + uint32_t ret; + int64_t cnt; + double num; nasal_val* gcobj; }value; nasal_ref(const uint8_t t=vm_none):type(t){} + nasal_ref(const uint8_t t,const uint32_t n):type(t){value.ret=n;} nasal_ref(const uint8_t t,const int64_t n):type(t){value.cnt=n;} nasal_ref(const uint8_t t,const double n):type(t){value.num=n;} nasal_ref(const uint8_t t,nasal_val* n):type(t){value.gcobj=n;} @@ -66,6 +70,7 @@ struct nasal_ref // number and string can be translated to each other double to_number(); std::string to_string(); + inline uint32_t ret (); inline int64_t& cnt (); inline double& num (); inline std::string* str (); @@ -305,6 +310,7 @@ std::string nasal_ref::to_string() return std::to_string(num()); return ""; } +inline uint32_t nasal_ref::ret (){return value.ret; } inline int64_t& nasal_ref::cnt (){return value.cnt; } inline double& nasal_ref::num (){return value.num; } inline std::string* nasal_ref::str (){return value.gcobj->ptr.str; } diff --git a/nasal_vm.h b/nasal_vm.h index 7cce511..34875ea 100644 --- a/nasal_vm.h +++ b/nasal_vm.h @@ -9,7 +9,6 @@ private: uint32_t offset; // used to load default parameters to a new function const double* num_table;// const numbers, ref from nasal_codegen const std::string* str_table;// const symbols, ref from nasal_codegen - std::stack ret; // stack to store return pc std::stack func_stk; // stack to store function, used to get upvalues std::vector imm; // immediate number nasal_ref* mem_addr; // used for mem_call @@ -23,7 +22,6 @@ private: const std::vector&, const std::vector&, const std::vector&); - void clear(); /* debug functions */ bool detail_info; void valinfo(nasal_ref&); @@ -113,7 +111,6 @@ private: void opr_mcallh(); void opr_ret(); public: - ~nasal_vm(){clear();} void run( const nasal_codegen&, const nasal_import&, @@ -131,27 +128,21 @@ void nasal_vm::init( str_table=strs.data(); files=filenames.data(); } -void nasal_vm::clear() -{ - gc.clear(); - while(!ret.empty()) - ret.pop(); - imm.clear(); -} void nasal_vm::valinfo(nasal_ref& val) { const nasal_val* p=val.value.gcobj; switch(val.type) { - case vm_none: printf("\t|null |\n");break; - case vm_cnt: printf("\t|counter| %ld\n",val.cnt());break; - case vm_nil: printf("\t|nil |\n");break; - case vm_num: printf("\t|number | %lf\n",val.num());break; - case vm_str: printf("\t|string | <%p> %s\n",p,rawstr(*val.str()).c_str());break; - case vm_func: printf("\t|func | <%p> func{entry=0x%x}\n",p,val.func()->entry);break; - case vm_vec: printf("\t|vector | <%p> [%lu val]\n",p,val.vec()->elems.size());break; - case vm_hash: printf("\t|hash | <%p> {%lu member}\n",p,val.hash()->elems.size());break; - case vm_obj: printf("\t|object | <%p>\n",p);break; + case vm_none: printf("\t| null |\n");break; + case vm_ret: printf("\t| addr | 0x%x\n",val.ret());break; + case vm_cnt: printf("\t| cnt | %ld\n",val.cnt());break; + case vm_nil: printf("\t| nil |\n");break; + case vm_num: printf("\t| num | %lf\n",val.num());break; + case vm_str: printf("\t| str | <0x%lx> %s\n",(uint64_t)p,rawstr(*val.str()).c_str());break; + case vm_func: printf("\t| func | <0x%lx> func{entry=0x%x}\n",(uint64_t)p,val.func()->entry);break; + case vm_vec: printf("\t| vec | <0x%lx> [%lu val]\n",(uint64_t)p,val.vec()->elems.size());break; + case vm_hash: printf("\t| hash | <0x%lx> {%lu member}\n",(uint64_t)p,val.hash()->elems.size());break; + case vm_obj: printf("\t| obj | <0x%lx>\n",(uint64_t)p);break; } } void nasal_vm::bytecodeinfo(const uint32_t p) @@ -159,11 +150,18 @@ void nasal_vm::bytecodeinfo(const uint32_t p) const opcode& code=bytecode[p]; printf("\t0x%.8x: %s 0x%x",p,code_table[code.op].name,code.num); if(code.op==op_callb) - printf(" <%s>",builtin[code.num].name); + printf(" <%s@0x%lx>",builtin[code.num].name,(uint64_t)builtin[code.num].func); printf(" (<%s> line %d)\n",files[code.fidx].c_str(),code.line); } void nasal_vm::traceback() { + uint32_t global_size=bytecode[0].num; // bytecode[0] is op_intg + nasal_ref* top=gc.top; + nasal_ref* bottom=gc.stack+global_size; + std::stack ret; + for(nasal_ref* i=bottom;i<=top;++i) + if(i->type==vm_ret) + ret.push(i->ret()); // push pc to ret stack to store the position program crashed ret.push(pc); printf("trace back:\n"); @@ -177,46 +175,32 @@ void nasal_vm::traceback() } if(same) { - printf("\t0x%.8x: %d same call(s) ...\n",last,same); + printf("\t0x%.8x: %d same call(s)\n",last,same); same=0; } bytecodeinfo(point); } if(same) - printf("\t0x%.8x: %d same call(s) ...\n",last,same); + printf("\t0x%.8x: %d same call(s)\n",last,same); } -void nasal_vm::stackinfo(const uint32_t limit=20) +void nasal_vm::stackinfo(const uint32_t limit=10) { - printf("vm stack(limit %d):\n",limit); - uint32_t same=0,global_size=bytecode[0].num; - nasal_ref last={vm_none,(nasal_val*)0xffffffff}; - for(uint32_t i=0;i=gc.stack+global_size;++i,--gc.top) - { - if(gc.top[0]==last) - { - ++same; - continue; - } - if(same) - { - printf("\t... | %d same value(s)\n",same); - same=0; - } - last=gc.top[0]; - valinfo(gc.top[0]); - } - if(same) - printf("\t... | %d same value(s)\n",same); + uint32_t global_size=bytecode[0].num; // bytecode[0] is op_intg + nasal_ref* top=gc.top; + nasal_ref* bottom=gc.stack+global_size; + printf("vm stack(limit %d, total %ld):\n",limit,top-bottom+1); + for(uint32_t i=0;i=bottom;++i,--top) + valinfo(top[0]); } void nasal_vm::detail() { - printf("mcall address: %p\n",mem_addr); - if(bytecode[0].num)// bytecode[0] is op_intg + printf("mcall address: 0x%lx\n",(uint64_t)mem_addr); + if(bytecode[0].num) // bytecode[0] is op_intg { printf("global:\n"); for(uint32_t i=0;ielems; for(uint32_t i=0;ielems; for(uint32_t j=0;jlocal[0]={vm_nil}; - --gc.top; - gc.top[0]=gc.top[1]; + // | return value | <- gc.top[0] + // +-----------------+ + // | return address | <- gc.top[-1] + // +-----------------+ + // | called function | <- gc.top[-2] funct is set on stack because gc may mark it + // +-----------------+ + pc=gc.top[-1].ret(); + gc.top[-2].func()->local[0]={vm_nil,nullptr}; // get func and set 'me' to nil + gc.top[-2]=gc.top[0]; // rewrite func with returned value + gc.top-=2; func_stk.pop(); gc.local.pop_back(); - pc=ret.top();ret.pop(); } void nasal_vm::run( const nasal_codegen& gen, @@ -855,21 +842,21 @@ void nasal_vm::run( } // set canary and program counter - auto& canary=gc.stack[STACK_MAX_DEPTH-1]; - canary.value.gcobj=nullptr; + auto canary=gc.stack+STACK_MAX_DEPTH-1; pc=0; // goto the first operand goto *code[pc]; vmexit: - if(canary.value.gcobj) + if(gc.top>=canary) die("stack overflow"); if(opcnt) opcallsort(count); - clear(); + gc.clear(); + imm.clear(); return; // may cause stackoverflow -#define exec_operand(op,num) {op();++count[num];if(!canary.value.gcobj)goto *code[++pc];goto vmexit;} +#define exec_operand(op,num) {op();++count[num];if(gc.top=0 arguments +callfh: exec_opnodie(opr_callfh ,op_callfh ); // -0 call this will push one hash callb: exec_opnodie(opr_callb ,op_callb ); // -0 slcbegin:exec_operand(opr_slcbegin,op_slcbegin); // +1 slcend: exec_opnodie(opr_slcend ,op_slcend ); // -1 diff --git a/stl/lib.nas b/stl/lib.nas index 77fa6a1..5e5d5ff 100644 --- a/stl/lib.nas +++ b/stl/lib.nas @@ -68,7 +68,8 @@ var math= sin: func(x) {return __builtin_sin(x); }, cos: func(x) {return __builtin_cos(x); }, tan: func(x) {return __builtin_tan(x); }, - exp: func(x) {return __builtin_exp(x); }, + exp: func(x) {return __builtin_exp(x); }, + lg: func(x) {return __builtin_lg(x); }, ln: func(x) {return __builtin_ln(x); }, sqrt: func(x) {return __builtin_sqrt(x); }, atan2: func(x,y){return __builtin_atan2(x,y);},