From 4f5fd3de3332e7059c69634537b0a4376da498de Mon Sep 17 00:00:00 2001 From: ValKmjolnir Date: Sun, 17 Apr 2022 17:20:18 +0800 Subject: [PATCH] op_addeq~op_lnkeq and op_addeqc~op_lnkeqc and op_meq operands now can do pop, this will decrease the frequency of calling op_pop --- nasal_codegen.h | 106 ++++++++++++++++++++++++++++++++---------------- nasal_vm.h | 37 +++++++++++++---- 2 files changed, 100 insertions(+), 43 deletions(-) diff --git a/nasal_codegen.h b/nasal_codegen.h index 9ee3ee4..a9de36d 100644 --- a/nasal_codegen.h +++ b/nasal_codegen.h @@ -676,10 +676,7 @@ void nasal_codegen::multi_assign_gen(const nasal_ast& ast) else if(code.back().op==op_mcallg) code.back().op=op_loadg; else - { - gen(op_meq,0,ast[0][i].line()); - gen(op_pop,0,ast[0][i].line()); - } + gen(op_meq,1,ast[0][i].line()); } } else @@ -698,10 +695,7 @@ void nasal_codegen::multi_assign_gen(const nasal_ast& ast) else if(code.back().op==op_mcallg) code.back().op=op_loadg; else - { - gen(op_meq,0,ast[0][i].line()); - gen(op_pop,0,ast[0][i].line()); - } + gen(op_meq,1,ast[0][i].line()); } gen(op_pop,0,ast.line()); } @@ -779,11 +773,19 @@ void nasal_codegen::for_gen(const nasal_ast& ast) case ast_null:break; case ast_def:def_gen(ast[0]);break; case ast_multi_assign:multi_assign_gen(ast[0]);break; + case ast_addeq:case ast_subeq: + case ast_multeq:case ast_diveq:case ast_lnkeq: + calc_gen(ast[0]); + if(op_addeq<=code.back().op && code.back().op<=op_lnkeq) + code.back().num=1; + else if(op_addeqc<=code.back().op && code.back().op<=op_lnkeqc) + code.back().num|=0x80000000; + else + gen(op_pop,0,ast[0].line()); + break; case ast_nil:case ast_num:case ast_str:break; case ast_vec:case ast_hash:case ast_func: case ast_call: - case ast_addeq:case ast_subeq: - case ast_multeq:case ast_diveq:case ast_lnkeq: case ast_neg:case ast_not: case ast_add:case ast_sub: case ast_mult:case ast_div: @@ -793,7 +795,10 @@ void nasal_codegen::for_gen(const nasal_ast& ast) case ast_geq:case ast_grt: case ast_trino: calc_gen(ast[0]); - gen(op_pop,0,ast[0].line()); + if(code.back().op==op_meq) + code.back().num=1; + else + gen(op_pop,0,ast[0].line()); break; case ast_equal: if(ast[0][0].type()==ast_id) @@ -811,7 +816,10 @@ void nasal_codegen::for_gen(const nasal_ast& ast) else { calc_gen(ast[0]); - gen(op_pop,0,ast[0].line()); + if(code.back().op==op_meq) + code.back().num=1; + else + gen(op_pop,0,ast[0].line()); } break; } @@ -830,12 +838,19 @@ void nasal_codegen::for_gen(const nasal_ast& ast) case ast_null:break; case ast_def:def_gen(ast[2]);break; case ast_multi_assign:multi_assign_gen(ast[2]);break; + case ast_addeq:case ast_subeq: + case ast_multeq:case ast_diveq:case ast_lnkeq: + calc_gen(ast[2]); + if(op_addeq<=code.back().op && code.back().op<=op_lnkeq) + code.back().num=1; + else if(op_addeqc<=code.back().op && code.back().op<=op_lnkeqc) + code.back().num|=0x80000000; + else + gen(op_pop,0,ast[2].line()); + break; case ast_nil:case ast_num:case ast_str:break; case ast_vec:case ast_hash:case ast_func: case ast_call: - case ast_addeq: - case ast_subeq:case ast_multeq: - case ast_diveq:case ast_lnkeq: case ast_neg:case ast_not: case ast_add:case ast_sub:case ast_mult: case ast_div:case ast_link: @@ -843,7 +858,10 @@ void nasal_codegen::for_gen(const nasal_ast& ast) case ast_less:case ast_geq:case ast_grt: case ast_trino: calc_gen(ast[2]); - gen(op_pop,0,ast[2].line()); + if(code.back().op==op_meq) + code.back().num=1; + else + gen(op_pop,0,ast[2].line()); break; case ast_equal: if(ast[2][0].type()==ast_id) @@ -861,7 +879,10 @@ void nasal_codegen::for_gen(const nasal_ast& ast) else { calc_gen(ast[2]); - gen(op_pop,0,ast[2].line()); + if(code.back().op==op_meq) + code.back().num=1; + else + gen(op_pop,0,ast[2].line()); } break; } @@ -893,10 +914,7 @@ void nasal_codegen::forindex_gen(const nasal_ast& ast) else if(code.back().op==op_mupval) code.back().op=op_loadu; else - { - gen(op_meq,0,ast[0].line()); - gen(op_pop,0,ast[0].line()); - } + gen(op_meq,1,ast[0].line()); } ++in_iterloop.top(); block_gen(ast[2]); @@ -930,10 +948,7 @@ void nasal_codegen::foreach_gen(const nasal_ast& ast) else if(code.back().op==op_mupval) code.back().op=op_loadu; else - { - gen(op_meq,0,ast[0].line()); - gen(op_pop,0,ast[0].line()); - } + gen(op_meq,1,ast[0].line()); } ++in_iterloop.top(); block_gen(ast[2]); @@ -1136,19 +1151,27 @@ void nasal_codegen::block_gen(const nasal_ast& ast) else { calc_gen(tmp); - gen(op_pop,0,tmp.line()); + if(code.back().op==op_meq) + code.back().num=1; + else + gen(op_pop,0,tmp.line()); } break; + case ast_addeq:case ast_subeq: + case ast_multeq:case ast_diveq:case ast_lnkeq: + calc_gen(tmp); + if(op_addeq<=code.back().op && code.back().op<=op_lnkeq) + code.back().num=1; + else if(op_addeqc<=code.back().op && code.back().op<=op_lnkeqc) + code.back().num|=0x80000000; + else + gen(op_pop,0,tmp.line()); + break; case ast_id: case ast_vec: case ast_hash: case ast_func: case ast_call: - case ast_addeq: - case ast_subeq: - case ast_multeq: - case ast_diveq: - case ast_lnkeq: case ast_neg: case ast_not: case ast_add: @@ -1164,7 +1187,13 @@ void nasal_codegen::block_gen(const nasal_ast& ast) case ast_grt: case ast_or: case ast_and: - case ast_trino:calc_gen(tmp);gen(op_pop,0,tmp.line());break; + case ast_trino: + calc_gen(tmp); + if(code.back().op==op_meq) + code.back().num=1; + else + gen(op_pop,0,tmp.line()); + break; case ast_ret:ret_gen(tmp);break; } } @@ -1236,8 +1265,15 @@ void nasal_codegen::print_op(uint32_t index) // print detail info switch(c.op) { - case op_addc: case op_subc: case op_mulc: case op_divc: + case op_addeq: case op_subeq: case op_muleq: case op_diveq: case op_lnkeq: + printf("0x%x sp-%u\n",c.num,c.num);break; case op_addeqc:case op_subeqc: case op_muleqc:case op_diveqc: + printf("0x%x (",c.num&0x7fffffff); + std::cout<>31)<<"\n"; + break; + case op_lnkeqc: + printf("0x%x (\"%s\") sp-%u\n",c.num&0x7fffffff,rawstr(str_res[c.num&0x7fffffff]).c_str(),c.num>>31);break; + case op_addc: case op_subc: case op_mulc: case op_divc: case op_lessc: case op_leqc: case op_grtc: case op_geqc: case op_pnum: printf("0x%x (",c.num);std::cout<>16)&0xffff,c.num&0xffff);break; case op_happ: case op_pstr: - case op_lnkc: case op_lnkeqc: + case op_lnkc: case op_callh: case op_mcallh: case op_para: case op_defpara:case op_dynpara: printf("0x%x (\"%s\")\n",c.num,rawstr(str_res[c.num]).c_str());break; + case op_meq: + printf("0x%x sp-%u\n",c.num,c.num);break; default:printf("\n");break; } } diff --git a/nasal_vm.h b/nasal_vm.h index 18a9b15..7755dda 100644 --- a/nasal_vm.h +++ b/nasal_vm.h @@ -166,15 +166,20 @@ void nasal_vm::bytecodeinfo(const char* header,const uint32_t p) printf("%s0x%.8x: %s 0x%x",header,p,code_table[c.op].name,c.num); switch(c.op) { - case op_addc: case op_subc: case op_mulc: case op_divc: + case op_addeq: case op_subeq: case op_muleq: case op_diveq: case op_lnkeq: + printf(" sp-%u",c.num);break; case op_addeqc:case op_subeqc: case op_muleqc:case op_diveqc: + std::cout<<" ("<>31);break; + case op_lnkeqc: + printf(" (\"%s\") sp-%u",rawstr(str_table[c.num&0x7fffffff]).c_str(),c.num>>31);break; + case op_addc: case op_subc: case op_mulc: case op_divc: case op_lessc: case op_leqc: case op_grtc: case op_geqc: case op_pnum: std::cout<<" ("<",builtin[c.num].name,(uint64_t)builtin[c.num].func);break; case op_happ: case op_pstr: - case op_lnkc: case op_lnkeqc: + case op_lnkc: case op_callh: case op_mcallh: case op_para: case op_defpara:case op_dynpara: printf(" (\"%s\")",rawstr(str_table[c.num]).c_str());break; @@ -477,7 +482,8 @@ inline void nasal_vm::opr_lnkc() #define op_calc_eq(type)\ nasal_ref val(vm_num,mem_addr[0].to_number() type gc.top[-1].to_number());\ (--gc.top)[0]=mem_addr[0]=val;\ - mem_addr=nullptr; + mem_addr=nullptr;\ + gc.top-=imm[pc]; inline void nasal_vm::opr_addeq(){op_calc_eq(+);} inline void nasal_vm::opr_subeq(){op_calc_eq(-);} @@ -489,12 +495,14 @@ inline void nasal_vm::opr_lnkeq() val.str()=mem_addr[0].to_string()+gc.top[-1].to_string(); (--gc.top)[0]=mem_addr[0]=val; mem_addr=nullptr; + gc.top-=imm[pc]; } #define op_calc_eq_const(type)\ - nasal_ref val(vm_num,mem_addr[0].to_number() type num_table[imm[pc]]);\ + nasal_ref val(vm_num,mem_addr[0].to_number() type num_table[imm[pc]&0x7fffffff]);\ gc.top[0]=mem_addr[0]=val;\ - mem_addr=nullptr; + mem_addr=nullptr;\ + gc.top-=(imm[pc]>>31); inline void nasal_vm::opr_addeqc(){op_calc_eq_const(+);} inline void nasal_vm::opr_subeqc(){op_calc_eq_const(-);} @@ -503,17 +511,22 @@ inline void nasal_vm::opr_diveqc(){op_calc_eq_const(/);} inline void nasal_vm::opr_lnkeqc() { nasal_ref val=gc.alloc(vm_str); - val.str()=mem_addr[0].to_string()+str_table[imm[pc]]; + val.str()=mem_addr[0].to_string()+str_table[imm[pc]&0x7fffffff]; gc.top[0]=mem_addr[0]=val; mem_addr=nullptr; + gc.top-=(imm[pc]>>31); } inline void nasal_vm::opr_meq() { - mem_addr[0]=(--gc.top)[0]; // pop old mem_addr[0] and replace it + // pop old mem_addr[0] and replace it + // the reason why we should get mem_addr and push the old value on stack + // is that when lnkeq/lnkeqc is called, there will be + // a new gc object vm_str which is returned by gc::alloc + // this may cause gc, so we should temporarily put it on stack + mem_addr[0]=(--gc.top)[0]; mem_addr=nullptr; - if(imm[pc]) - --gc.top; + gc.top-=imm[pc]; } inline void nasal_vm::opr_eq() { @@ -815,16 +828,22 @@ inline void nasal_vm::opr_mcallg() { mem_addr=gc.stack+imm[pc]; (++gc.top)[0]=mem_addr[0]; + // push value in this memory space on stack + // to avoid being garbage collected } inline void nasal_vm::opr_mcalll() { mem_addr=localr+imm[pc]; (++gc.top)[0]=mem_addr[0]; + // push value in this memory space on stack + // to avoid being garbage collected } inline void nasal_vm::opr_mupval() { mem_addr=&(gc.funcr.func().upvalue[(imm[pc]>>16)&0xffff].upval()[imm[pc]&0xffff]); (++gc.top)[0]=mem_addr[0]; + // push value in this memory space on stack + // to avoid being garbage collected } inline void nasal_vm::opr_mcallv() {