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

This commit is contained in:
ValKmjolnir 2022-04-17 17:20:18 +08:00
parent fc25dd69e1
commit 4f5fd3de33
2 changed files with 100 additions and 43 deletions

View File

@ -676,10 +676,7 @@ void nasal_codegen::multi_assign_gen(const nasal_ast& ast)
else if(code.back().op==op_mcallg) else if(code.back().op==op_mcallg)
code.back().op=op_loadg; code.back().op=op_loadg;
else else
{ gen(op_meq,1,ast[0][i].line());
gen(op_meq,0,ast[0][i].line());
gen(op_pop,0,ast[0][i].line());
}
} }
} }
else else
@ -698,10 +695,7 @@ void nasal_codegen::multi_assign_gen(const nasal_ast& ast)
else if(code.back().op==op_mcallg) else if(code.back().op==op_mcallg)
code.back().op=op_loadg; code.back().op=op_loadg;
else else
{ gen(op_meq,1,ast[0][i].line());
gen(op_meq,0,ast[0][i].line());
gen(op_pop,0,ast[0][i].line());
}
} }
gen(op_pop,0,ast.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_null:break;
case ast_def:def_gen(ast[0]);break; case ast_def:def_gen(ast[0]);break;
case ast_multi_assign:multi_assign_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_nil:case ast_num:case ast_str:break;
case ast_vec:case ast_hash:case ast_func: case ast_vec:case ast_hash:case ast_func:
case ast_call: 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_neg:case ast_not:
case ast_add:case ast_sub: case ast_add:case ast_sub:
case ast_mult:case ast_div: case ast_mult:case ast_div:
@ -793,6 +795,9 @@ void nasal_codegen::for_gen(const nasal_ast& ast)
case ast_geq:case ast_grt: case ast_geq:case ast_grt:
case ast_trino: case ast_trino:
calc_gen(ast[0]); calc_gen(ast[0]);
if(code.back().op==op_meq)
code.back().num=1;
else
gen(op_pop,0,ast[0].line()); gen(op_pop,0,ast[0].line());
break; break;
case ast_equal: case ast_equal:
@ -811,6 +816,9 @@ void nasal_codegen::for_gen(const nasal_ast& ast)
else else
{ {
calc_gen(ast[0]); calc_gen(ast[0]);
if(code.back().op==op_meq)
code.back().num=1;
else
gen(op_pop,0,ast[0].line()); gen(op_pop,0,ast[0].line());
} }
break; break;
@ -830,12 +838,19 @@ void nasal_codegen::for_gen(const nasal_ast& ast)
case ast_null:break; case ast_null:break;
case ast_def:def_gen(ast[2]);break; case ast_def:def_gen(ast[2]);break;
case ast_multi_assign:multi_assign_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_nil:case ast_num:case ast_str:break;
case ast_vec:case ast_hash:case ast_func: case ast_vec:case ast_hash:case ast_func:
case ast_call: 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_neg:case ast_not:
case ast_add:case ast_sub:case ast_mult: case ast_add:case ast_sub:case ast_mult:
case ast_div:case ast_link: case ast_div:case ast_link:
@ -843,6 +858,9 @@ void nasal_codegen::for_gen(const nasal_ast& ast)
case ast_less:case ast_geq:case ast_grt: case ast_less:case ast_geq:case ast_grt:
case ast_trino: case ast_trino:
calc_gen(ast[2]); calc_gen(ast[2]);
if(code.back().op==op_meq)
code.back().num=1;
else
gen(op_pop,0,ast[2].line()); gen(op_pop,0,ast[2].line());
break; break;
case ast_equal: case ast_equal:
@ -861,6 +879,9 @@ void nasal_codegen::for_gen(const nasal_ast& ast)
else else
{ {
calc_gen(ast[2]); calc_gen(ast[2]);
if(code.back().op==op_meq)
code.back().num=1;
else
gen(op_pop,0,ast[2].line()); gen(op_pop,0,ast[2].line());
} }
break; break;
@ -893,10 +914,7 @@ void nasal_codegen::forindex_gen(const nasal_ast& ast)
else if(code.back().op==op_mupval) else if(code.back().op==op_mupval)
code.back().op=op_loadu; code.back().op=op_loadu;
else else
{ gen(op_meq,1,ast[0].line());
gen(op_meq,0,ast[0].line());
gen(op_pop,0,ast[0].line());
}
} }
++in_iterloop.top(); ++in_iterloop.top();
block_gen(ast[2]); block_gen(ast[2]);
@ -930,10 +948,7 @@ void nasal_codegen::foreach_gen(const nasal_ast& ast)
else if(code.back().op==op_mupval) else if(code.back().op==op_mupval)
code.back().op=op_loadu; code.back().op=op_loadu;
else else
{ gen(op_meq,1,ast[0].line());
gen(op_meq,0,ast[0].line());
gen(op_pop,0,ast[0].line());
}
} }
++in_iterloop.top(); ++in_iterloop.top();
block_gen(ast[2]); block_gen(ast[2]);
@ -1136,19 +1151,27 @@ void nasal_codegen::block_gen(const nasal_ast& ast)
else else
{ {
calc_gen(tmp); calc_gen(tmp);
if(code.back().op==op_meq)
code.back().num=1;
else
gen(op_pop,0,tmp.line()); gen(op_pop,0,tmp.line());
} }
break; 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_id:
case ast_vec: case ast_vec:
case ast_hash: case ast_hash:
case ast_func: case ast_func:
case ast_call: case ast_call:
case ast_addeq:
case ast_subeq:
case ast_multeq:
case ast_diveq:
case ast_lnkeq:
case ast_neg: case ast_neg:
case ast_not: case ast_not:
case ast_add: case ast_add:
@ -1164,7 +1187,13 @@ void nasal_codegen::block_gen(const nasal_ast& ast)
case ast_grt: case ast_grt:
case ast_or: case ast_or:
case ast_and: 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; case ast_ret:ret_gen(tmp);break;
} }
} }
@ -1236,8 +1265,15 @@ void nasal_codegen::print_op(uint32_t index)
// print detail info // print detail info
switch(c.op) 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: case op_addeqc:case op_subeqc: case op_muleqc:case op_diveqc:
printf("0x%x (",c.num&0x7fffffff);
std::cout<<num_res[c.num&0x7fffffff]<<") sp-"<<(c.num>>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_lessc: case op_leqc: case op_grtc: case op_geqc:
case op_pnum: case op_pnum:
printf("0x%x (",c.num);std::cout<<num_res[c.num]<<")\n";break; printf("0x%x (",c.num);std::cout<<num_res[c.num]<<")\n";break;
@ -1253,10 +1289,12 @@ void nasal_codegen::print_op(uint32_t index)
case op_upval:case op_mupval: case op_loadu: case op_upval:case op_mupval: case op_loadu:
printf("0x%x[0x%x]\n",(c.num>>16)&0xffff,c.num&0xffff);break; printf("0x%x[0x%x]\n",(c.num>>16)&0xffff,c.num&0xffff);break;
case op_happ: case op_pstr: case op_happ: case op_pstr:
case op_lnkc: case op_lnkeqc: case op_lnkc:
case op_callh: case op_mcallh: case op_callh: case op_mcallh:
case op_para: case op_defpara:case op_dynpara: case op_para: case op_defpara:case op_dynpara:
printf("0x%x (\"%s\")\n",c.num,rawstr(str_res[c.num]).c_str());break; 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; default:printf("\n");break;
} }
} }

View File

@ -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); printf("%s0x%.8x: %s 0x%x",header,p,code_table[c.op].name,c.num);
switch(c.op) 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: case op_addeqc:case op_subeqc: case op_muleqc:case op_diveqc:
std::cout<<" ("<<num_table[c.num&0x7fffffff]<<") sp-"<<(c.num>>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_lessc: case op_leqc: case op_grtc: case op_geqc:
case op_pnum: case op_pnum:
std::cout<<" ("<<num_table[c.num]<<")";break; std::cout<<" ("<<num_table[c.num]<<")";break;
case op_callb: case op_callb:
printf(" <%s@0x%lx>",builtin[c.num].name,(uint64_t)builtin[c.num].func);break; printf(" <%s@0x%lx>",builtin[c.num].name,(uint64_t)builtin[c.num].func);break;
case op_happ: case op_pstr: case op_happ: case op_pstr:
case op_lnkc: case op_lnkeqc: case op_lnkc:
case op_callh: case op_mcallh: case op_callh: case op_mcallh:
case op_para: case op_defpara:case op_dynpara: case op_para: case op_defpara:case op_dynpara:
printf(" (\"%s\")",rawstr(str_table[c.num]).c_str());break; 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)\ #define op_calc_eq(type)\
nasal_ref val(vm_num,mem_addr[0].to_number() type gc.top[-1].to_number());\ nasal_ref val(vm_num,mem_addr[0].to_number() type gc.top[-1].to_number());\
(--gc.top)[0]=mem_addr[0]=val;\ (--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_addeq(){op_calc_eq(+);}
inline void nasal_vm::opr_subeq(){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(); val.str()=mem_addr[0].to_string()+gc.top[-1].to_string();
(--gc.top)[0]=mem_addr[0]=val; (--gc.top)[0]=mem_addr[0]=val;
mem_addr=nullptr; mem_addr=nullptr;
gc.top-=imm[pc];
} }
#define op_calc_eq_const(type)\ #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;\ 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_addeqc(){op_calc_eq_const(+);}
inline void nasal_vm::opr_subeqc(){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() inline void nasal_vm::opr_lnkeqc()
{ {
nasal_ref val=gc.alloc(vm_str); 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; gc.top[0]=mem_addr[0]=val;
mem_addr=nullptr; mem_addr=nullptr;
gc.top-=(imm[pc]>>31);
} }
inline void nasal_vm::opr_meq() 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; mem_addr=nullptr;
if(imm[pc]) gc.top-=imm[pc];
--gc.top;
} }
inline void nasal_vm::opr_eq() inline void nasal_vm::opr_eq()
{ {
@ -815,16 +828,22 @@ inline void nasal_vm::opr_mcallg()
{ {
mem_addr=gc.stack+imm[pc]; mem_addr=gc.stack+imm[pc];
(++gc.top)[0]=mem_addr[0]; (++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() inline void nasal_vm::opr_mcalll()
{ {
mem_addr=localr+imm[pc]; mem_addr=localr+imm[pc];
(++gc.top)[0]=mem_addr[0]; (++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() inline void nasal_vm::opr_mupval()
{ {
mem_addr=&(gc.funcr.func().upvalue[(imm[pc]>>16)&0xffff].upval()[imm[pc]&0xffff]); mem_addr=&(gc.funcr.func().upvalue[(imm[pc]>>16)&0xffff].upval()[imm[pc]&0xffff]);
(++gc.top)[0]=mem_addr[0]; (++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() inline void nasal_vm::opr_mcallv()
{ {