delete ret stack/ add math.lg
now return address is stored on value stack
This commit is contained in:
parent
b8ef3cf6b6
commit
aa191a9feb
3
lib.nas
3
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);},
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
10
nasal_gc.h
10
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; }
|
||||
|
|
117
nasal_vm.h
117
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<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
|
||||
|
|
|
@ -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);},
|
||||
|
|
Loading…
Reference in New Issue