delete ret stack/ add math.lg

now return address is stored on value stack
This commit is contained in:
ValKmjolnir 2021-12-02 22:23:22 +08:00
parent b8ef3cf6b6
commit aa191a9feb
6 changed files with 75 additions and 71 deletions

View File

@ -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);},

View File

@ -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<nasal_ref>& local,nasal_gc& gc)
return builtin_err("exp","\"x\" must be number");
return {vm_num,exp(val.num())};
}
nasal_ref builtin_lg(std::vector<nasal_ref>& 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<nasal_ref>& 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<nasal_ref>& local,nasal_gc& gc)
{

View File

@ -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;

View File

@ -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; }

View File

@ -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<uint32_t> ret; // stack to store return pc
std::stack<nasal_func*> func_stk; // stack to store function, used to get upvalues
std::vector<uint32_t> imm; // immediate number
nasal_ref* mem_addr; // used for mem_call
@ -23,7 +22,6 @@ private:
const std::vector<std::string>&,
const std::vector<double>&,
const std::vector<std::string>&);
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<uint32_t> 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<limit && gc.top>=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<limit && top>=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;i<bytecode[0].num;++i)
{
printf("[%d]",i);
printf("[0x%.8x]",i);
valinfo(gc.stack[i]);
}
}
@ -226,7 +210,7 @@ void nasal_vm::detail()
auto& vec=gc.local.back().vec()->elems;
for(uint32_t i=0;i<vec.size();++i)
{
printf("[%d]",i);
printf("[0x%.8x]",i);
valinfo(vec[i]);
}
}
@ -239,7 +223,7 @@ void nasal_vm::detail()
auto& vec=upval[i].vec()->elems;
for(uint32_t j=0;j<vec.size();++j)
{
printf("[%d][%d]",i,j);
printf("[%.4x][%.4x]",i,j);
valinfo(vec[j]);
}
}
@ -657,8 +641,8 @@ inline void nasal_vm::opr_callfv()
local.back()=vec;
}
gc.top-=args_size;// pop arguments
ret.push(pc);
gc.top-=args_size; // pop arguments
(++gc.top)[0]={vm_ret,pc};
pc=func.entry-1;
}
inline void nasal_vm::opr_callfh()
@ -683,8 +667,7 @@ inline void nasal_vm::opr_callfh()
die("callfh: lack argument(s): \""+i.first+"\"");
}
--gc.top;// pop hash
ret.push(pc);
gc.top[0]={vm_ret,(uint32_t)pc}; // rewrite top with vm_ret
pc=func.entry-1;
}
inline void nasal_vm::opr_callb()
@ -804,15 +787,19 @@ inline void nasal_vm::opr_mcallh()
}
inline void nasal_vm::opr_ret()
{
// get nasal_func and set 'me' to nil
// and rewrite nasal_func with returned value
gc.top[-1].func()->local[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<canary)goto *code[++pc];goto vmexit;}
// do not cause stackoverflow
#define exec_opnodie(op,num) {op();++count[num];goto *code[++pc];}
@ -937,8 +924,8 @@ upval: exec_operand(opr_upval ,op_upval ); // +1
callv: exec_opnodie(opr_callv ,op_callv ); // -0
callvi: exec_opnodie(opr_callvi ,op_callvi ); // -0
callh: exec_opnodie(opr_callh ,op_callh ); // -0
callfv: exec_opnodie(opr_callfv ,op_callfv ); // -0
callfh: exec_opnodie(opr_callfh ,op_callfh ); // -0
callfv: exec_operand(opr_callfv ,op_callfv ); // +1-imm[pc] call this will push >=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

View File

@ -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);},