add new gc type vm_upval

This commit is contained in:
ValKmjolnir 2022-02-13 22:40:54 +08:00
parent 9139e34c0b
commit 5fba784d05
4 changed files with 97 additions and 61 deletions

View File

@ -175,8 +175,6 @@ If your system is __`Windows`__ and you want to output unicode,please use this c
> chcp 65001 > chcp 65001
The interpreter's interactive mode will do this automatically,so you don't need to run this command if you use the interactive interpreter.
## __Release Notes__ ## __Release Notes__
### __version 8.0 release__ ### __version 8.0 release__
@ -735,7 +733,7 @@ running time:
|:----|:----|:----| |:----|:----|:----|
|bf.nas|1100.19s|| |bf.nas|1100.19s||
|mandel.nas|28.98s|| |mandel.nas|28.98s||
|life.nas|0.857s(windows) 0.56(ubuntu WSL)|| |life.nas|0.56s|0.857s(windows)|
|ycombinator.nas|0.64s|| |ycombinator.nas|0.64s||
|fib.nas|0.28s|| |fib.nas|0.28s||
|bfs.nas|0.156s|random result| |bfs.nas|0.156s|random result|
@ -754,8 +752,8 @@ running time:
|:----|:----|:----| |:----|:----|:----|
|bf.nas|276.55s|great improvement| |bf.nas|276.55s|great improvement|
|mandel.nas|28.16s|| |mandel.nas|28.16s||
|ycombinator.nas|0.578s|| |ycombinator.nas|0.59s||
|life.nas|0.649s(windows) 0.2(ubuntu WSL)|| |life.nas|0.2s|0.649s(windows)|
|fib.nas|0.234s|little improvement| |fib.nas|0.234s|little improvement|
|bfs.nas|0.14s|random result| |bfs.nas|0.14s|random result|
|pi.nas|0.0625s|| |pi.nas|0.0625s||

View File

@ -180,7 +180,7 @@ void nasal_dbg::run(
const nasal_import& linker) const nasal_import& linker)
{ {
detail_info=true; detail_info=true;
init(gen.get_strs(),gen.get_nums(),linker.get_file()); init(gen.get_strs(),gen.get_nums(),gen.get_code(),linker.get_file());
const void* opr_table[]= const void* opr_table[]=
{ {
&&nop, &&intg, &&intl, &&loadg, &&nop, &&intg, &&intl, &&loadg,
@ -203,7 +203,6 @@ void nasal_dbg::run(
&&slc2, &&mcallg, &&mcalll, &&mupval, &&slc2, &&mcallg, &&mcalll, &&mupval,
&&mcallv, &&mcallh, &&ret, &&vmexit &&mcallv, &&mcallh, &&ret, &&vmexit
}; };
bytecode=gen.get_code().data();
std::vector<const void*> code; std::vector<const void*> code;
for(auto& i:gen.get_code()) for(auto& i:gen.get_code())
{ {

View File

@ -14,6 +14,7 @@ enum nasal_type
vm_func, vm_func,
vm_vec, vm_vec,
vm_hash, vm_hash,
vm_upval,
vm_obj, vm_obj,
vm_type_size vm_type_size
}; };
@ -29,18 +30,20 @@ const uint32_t increment[vm_type_size]=
0, // vm_nil 0, // vm_nil
0, // vm_num 0, // vm_num
/* gc object */ /* gc object */
256, // vm_str 128, // vm_str
512, // vm_func 512, // vm_func
512, // vm_vec 128, // vm_vec
128, // vm_hash 64, // vm_hash
512, // vm_upval
16 // vm_obj 16 // vm_obj
}; };
struct nasal_vec; // vector struct nasal_vec; // vector
struct nasal_hash;// hashmap(dict) struct nasal_hash; // hashmap(dict)
struct nasal_func;// function(lambda) struct nasal_func; // function(lambda)
struct nasal_obj; // special objects struct nasal_upval;// upvalue
struct nasal_val; // nasal_val includes gc-managed types struct nasal_obj; // special objects
struct nasal_val; // nasal_val includes gc-managed types
struct nasal_ref struct nasal_ref
{ {
@ -78,6 +81,7 @@ struct nasal_ref
inline nasal_vec* vec (); inline nasal_vec* vec ();
inline nasal_hash* hash(); inline nasal_hash* hash();
inline nasal_func* func(); inline nasal_func* func();
inline nasal_upval& upval();
inline nasal_obj* obj (); inline nasal_obj* obj ();
}; };
@ -113,6 +117,17 @@ struct nasal_func
void clear(); void clear();
}; };
struct nasal_upval
{
bool onstk;
nasal_ref* stk;
std::vector<nasal_ref> elems;
nasal_upval(){onstk=true;stk=nullptr;}
nasal_ref& operator[](const int);
void clear(){onstk=true;elems.clear();}
};
struct nasal_obj struct nasal_obj
{ {
uint32_t type; uint32_t type;
@ -135,6 +150,7 @@ struct nasal_val
nasal_vec* vec; nasal_vec* vec;
nasal_hash* hash; nasal_hash* hash;
nasal_func* func; nasal_func* func;
nasal_upval* upval;
nasal_obj* obj; nasal_obj* obj;
}ptr; }ptr;
@ -241,6 +257,13 @@ void nasal_func::clear()
keys.clear(); keys.clear();
} }
nasal_ref& nasal_upval::operator[](const int index)
{
if(onstk)
return stk[index];
return elems[index];
}
nasal_val::nasal_val(uint8_t val_type) nasal_val::nasal_val(uint8_t val_type)
{ {
mark=GC_COLLECTED; mark=GC_COLLECTED;
@ -248,11 +271,12 @@ nasal_val::nasal_val(uint8_t val_type)
unmut=0; unmut=0;
switch(val_type) switch(val_type)
{ {
case vm_str: ptr.str=new std::string; break; case vm_str: ptr.str=new std::string; break;
case vm_vec: ptr.vec=new nasal_vec; break; case vm_vec: ptr.vec=new nasal_vec; break;
case vm_hash: ptr.hash=new nasal_hash; break; case vm_hash: ptr.hash=new nasal_hash; break;
case vm_func: ptr.func=new nasal_func; break; case vm_func: ptr.func=new nasal_func; break;
case vm_obj: ptr.obj=new nasal_obj; break; case vm_upval:ptr.upval=new nasal_upval;break;
case vm_obj: ptr.obj=new nasal_obj; break;
} }
} }
nasal_val::~nasal_val() nasal_val::~nasal_val()
@ -263,6 +287,7 @@ nasal_val::~nasal_val()
case vm_vec: delete ptr.vec; break; case vm_vec: delete ptr.vec; break;
case vm_hash: delete ptr.hash; break; case vm_hash: delete ptr.hash; break;
case vm_func: delete ptr.func; break; case vm_func: delete ptr.func; break;
case vm_upval:delete ptr.upval;break;
case vm_obj: delete ptr.obj; break; case vm_obj: delete ptr.obj; break;
} }
type=vm_nil; type=vm_nil;
@ -293,14 +318,15 @@ void nasal_ref::print()
case vm_obj: std::cout<<"<object>"; break; case vm_obj: std::cout<<"<object>"; break;
} }
} }
inline uint32_t nasal_ref::ret (){return value.ret; } inline uint32_t nasal_ref::ret (){return value.ret; }
inline int64_t& nasal_ref::cnt (){return value.cnt; } inline int64_t& nasal_ref::cnt (){return value.cnt; }
inline double& nasal_ref::num (){return value.num; } inline double& nasal_ref::num (){return value.num; }
inline std::string* nasal_ref::str (){return value.gcobj->ptr.str; } inline std::string* nasal_ref::str (){return value.gcobj->ptr.str; }
inline nasal_vec* nasal_ref::vec (){return value.gcobj->ptr.vec; } inline nasal_vec* nasal_ref::vec (){return value.gcobj->ptr.vec; }
inline nasal_hash* nasal_ref::hash(){return value.gcobj->ptr.hash;} inline nasal_hash* nasal_ref::hash (){return value.gcobj->ptr.hash; }
inline nasal_func* nasal_ref::func(){return value.gcobj->ptr.func;} inline nasal_func* nasal_ref::func (){return value.gcobj->ptr.func; }
inline nasal_obj* nasal_ref::obj (){return value.gcobj->ptr.obj; } inline nasal_upval& nasal_ref::upval(){return *value.gcobj->ptr.upval;}
inline nasal_obj* nasal_ref::obj (){return value.gcobj->ptr.obj; }
const uint32_t STACK_MAX_DEPTH=8191; const uint32_t STACK_MAX_DEPTH=8191;
const nasal_ref zero={vm_num,(double)0}; const nasal_ref zero={vm_num,(double)0};
@ -355,6 +381,9 @@ void nasal_gc::mark()
for(auto& i:tmp.func()->upvalue) for(auto& i:tmp.func()->upvalue)
bfs.push(i); bfs.push(i);
break; break;
case vm_upval:
for(auto& i:tmp.upval().elems)
bfs.push(i);
} }
} }
} }
@ -366,11 +395,12 @@ void nasal_gc::sweep()
{ {
switch(i->type) switch(i->type)
{ {
case vm_str: i->ptr.str->clear(); break; case vm_str: i->ptr.str->clear(); break;
case vm_vec: i->ptr.vec->elems.clear(); break; case vm_vec: i->ptr.vec->elems.clear(); break;
case vm_hash:i->ptr.hash->elems.clear();break; case vm_hash: i->ptr.hash->elems.clear();break;
case vm_func:i->ptr.func->clear(); break; case vm_func: i->ptr.func->clear(); break;
case vm_obj: i->ptr.obj->clear(); break; case vm_upval:i->ptr.upval->clear(); break;
case vm_obj: i->ptr.obj->clear(); break;
} }
free_list[i->type].push(i); free_list[i->type].push(i);
i->mark=GC_COLLECTED; i->mark=GC_COLLECTED;
@ -416,9 +446,10 @@ void nasal_gc::clear()
void nasal_gc::info() void nasal_gc::info()
{ {
const char* name[]={ const char* name[]={
"null","cnt ","ret ", "null ","cnt ","ret ",
"nil ","num ","str ", "nil ","num ","str ",
"func","vec ","hash","obj " "func ","vec ","hash ",
"upval","obj "
}; };
std::cout<<"\ngarbage collector info:\n"; std::cout<<"\ngarbage collector info:\n";
for(uint8_t i=vm_str;i<vm_type_size;++i) for(uint8_t i=vm_str;i<vm_type_size;++i)

View File

@ -24,6 +24,7 @@ protected:
void init( void init(
const std::vector<std::string>&, const std::vector<std::string>&,
const std::vector<double>&, const std::vector<double>&,
const std::vector<opcode>&,
const std::vector<std::string>&); const std::vector<std::string>&);
/* debug functions */ /* debug functions */
bool detail_info; bool detail_info;
@ -126,11 +127,13 @@ public:
void nasal_vm::init( void nasal_vm::init(
const std::vector<std::string>& strs, const std::vector<std::string>& strs,
const std::vector<double>& nums, const std::vector<double>& nums,
const std::vector<opcode>& code,
const std::vector<std::string>& filenames) const std::vector<std::string>& filenames)
{ {
gc.init(strs); gc.init(strs);
num_table=nums.data(); num_table=nums.data();
str_table=strs.data(); str_table=strs.data();
bytecode=code.data();
files=filenames.data(); files=filenames.data();
files_size=filenames.size(); files_size=filenames.size();
/* set canary and program counter */ /* set canary and program counter */
@ -339,11 +342,10 @@ inline void nasal_vm::opr_loadg()
inline void nasal_vm::opr_loadl() inline void nasal_vm::opr_loadl()
{ {
lstk.top()[imm[pc]]=(gc.top--)[0]; lstk.top()[imm[pc]]=(gc.top--)[0];
//gc.local.back().vec()->elems[imm[pc]]=(gc.top--)[0];
} }
inline void nasal_vm::opr_loadu() inline void nasal_vm::opr_loadu()
{ {
fstk.top()->upvalue[(imm[pc]>>16)&0xffff].vec()->elems[imm[pc]&0xffff]=(gc.top--)[0]; fstk.top()->upvalue[(imm[pc]>>16)&0xffff].upval()[imm[pc]&0xffff]=(gc.top--)[0];
} }
inline void nasal_vm::opr_pnum() inline void nasal_vm::opr_pnum()
{ {
@ -383,12 +385,10 @@ inline void nasal_vm::opr_newf()
if(!lstk.empty()) if(!lstk.empty())
{ {
func->upvalue=fstk.top()->upvalue; func->upvalue=fstk.top()->upvalue;
nasal_ref upval=(gc.upvalue.back().type==vm_nil)?gc.alloc(vm_vec):gc.upvalue.back(); nasal_ref upval=(gc.upvalue.back().type==vm_nil)?gc.alloc(vm_upval):gc.upvalue.back();
upval.upval().stk=lstk.top();
func->upvalue.push_back(upval); func->upvalue.push_back(upval);
gc.upvalue.back()=upval; gc.upvalue.back()=upval;
auto& vec=upval.vec()->elems;
for(uint32_t i=0;i<fstk.top()->lsize;++i)
vec.push_back(lstk.top()[i]);
} }
} }
inline void nasal_vm::opr_happ() inline void nasal_vm::opr_happ()
@ -601,7 +601,7 @@ inline void nasal_vm::opr_calll()
} }
inline void nasal_vm::opr_upval() inline void nasal_vm::opr_upval()
{ {
(++gc.top)[0]=fstk.top()->upvalue[(imm[pc]>>16)&0xffff].vec()->elems[imm[pc]&0xffff]; (++gc.top)[0]=fstk.top()->upvalue[(imm[pc]>>16)&0xffff].upval()[imm[pc]&0xffff];
} }
inline void nasal_vm::opr_callv() inline void nasal_vm::opr_callv()
{ {
@ -801,7 +801,7 @@ inline void nasal_vm::opr_mcalll()
} }
inline void nasal_vm::opr_mupval() inline void nasal_vm::opr_mupval()
{ {
mem_addr=&fstk.top()->upvalue[(imm[pc]>>16)&0xffff].vec()->elems[imm[pc]&0xffff]; mem_addr=&(fstk.top()->upvalue[(imm[pc]>>16)&0xffff].upval()[imm[pc]&0xffff]);
(++gc.top)[0]=mem_addr[0]; (++gc.top)[0]=mem_addr[0];
} }
inline void nasal_vm::opr_mcallv() inline void nasal_vm::opr_mcallv()
@ -852,17 +852,26 @@ inline void nasal_vm::opr_ret()
// +-----------------+ // +-----------------+
// | local scope | // | local scope |
// +-----------------+ <- local pointer stored in lstk // +-----------------+ <- local pointer stored in lstk
// | called function | <- funct is set on stack because gc may mark it // | called function | <- func is stored on stack because gc may mark it
// +-----------------+ // +-----------------+
nasal_ref ret=gc.top[0]; nasal_ref ret=gc.top[0];
pc=gc.top[-1].ret(); pc=gc.top[-1].ret();
gc.top=lstk.top()-1; gc.top=lstk.top()-1;
lstk.pop();
gc.top[0].func()->local[0]={vm_nil,nullptr}; // get func and set 'me' to nil gc.top[0].func()->local[0]={vm_nil,nullptr}; // get func and set 'me' to nil
gc.top[0]=ret; // rewrite func with returned value gc.top[0]=ret; // rewrite func with returned value
if(gc.upvalue.back().type==vm_upval) // synchronize upvalue
{
auto& upval=gc.upvalue.back().upval();
auto local=lstk.top();
auto size=fstk.top()->lsize;
upval.onstk=false;
for(uint32_t i=0;i<size;++i)
upval.elems.push_back(local[i]);
}
lstk.pop();
fstk.pop(); fstk.pop();
gc.upvalue.pop_back(); gc.upvalue.pop_back();
} }
@ -873,7 +882,7 @@ void nasal_vm::run(
const bool detail) const bool detail)
{ {
detail_info=detail; detail_info=detail;
init(gen.get_strs(),gen.get_nums(),linker.get_file()); init(gen.get_strs(),gen.get_nums(),gen.get_code(),linker.get_file());
uint64_t count[op_exit+1]={0}; uint64_t count[op_exit+1]={0};
const void* opr_table[]= const void* opr_table[]=
{ {
@ -897,7 +906,6 @@ void nasal_vm::run(
&&slc2, &&mcallg, &&mcalll, &&mupval, &&slc2, &&mcallg, &&mcalll, &&mupval,
&&mcallv, &&mcallh, &&ret, &&vmexit &&mcallv, &&mcallh, &&ret, &&vmexit
}; };
bytecode=gen.get_code().data();
std::vector<const void*> code; std::vector<const void*> code;
for(auto& i:gen.get_code()) for(auto& i:gen.get_code())
{ {
@ -985,7 +993,7 @@ callv: exec_opnodie(opr_callv ,op_callv ); // -0
callvi: exec_opnodie(opr_callvi ,op_callvi ); // -0 callvi: exec_opnodie(opr_callvi ,op_callvi ); // -0
callh: exec_opnodie(opr_callh ,op_callh ); // -0 callh: exec_opnodie(opr_callh ,op_callh ); // -0
callfv: exec_opnodie(opr_callfv ,op_callfv ); // check in the function callfv: exec_opnodie(opr_callfv ,op_callfv ); // check in the function
callfh: exec_opnodie(opr_callfh ,op_callfh ); // -0 call this will push one hash callfh: exec_opnodie(opr_callfh ,op_callfh ); // check in the function
callb: exec_opnodie(opr_callb ,op_callb ); // -0 callb: exec_opnodie(opr_callb ,op_callb ); // -0
slcbegin:exec_operand(opr_slcbegin,op_slcbegin); // +1 slcbegin:exec_operand(opr_slcbegin,op_slcbegin); // +1
slcend: exec_opnodie(opr_slcend ,op_slcend ); // -1 slcend: exec_opnodie(opr_slcend ,op_slcend ); // -1