bug fixed & more efficient function call

fixed a bug when different hash calling the same function,'me' will be set to the latest called hash's address.
changed the way of pushing the scope to the stack by copying a new scope from the function's scope address.
use map as the nasal_scop instead of list<map>,it'll be more efficient.
This commit is contained in:
Valk Richard Li 2021-02-17 19:31:44 +08:00
parent 767711c93a
commit 02148f4766
2 changed files with 54 additions and 90 deletions

View File

@ -82,12 +82,10 @@ class nasal_scop
{ {
private: private:
nasal_gc& gc; nasal_gc& gc;
std::list<std::map<int,nasal_val*> > elems; std::map<int,nasal_val*> elems;
public: public:
nasal_scop(nasal_gc&); nasal_scop(nasal_gc&);
~nasal_scop(); ~nasal_scop();
void add_scope();
void del_scope();
void set_closure(nasal_scop&); void set_closure(nasal_scop&);
void add_new_value(int,nasal_val*); void add_new_value(int,nasal_val*);
nasal_val* get_value_address(int); nasal_val* get_value_address(int);
@ -435,76 +433,44 @@ nasal_val* nasal_func::get_closure_addr()
/*functions of nasal_scop*/ /*functions of nasal_scop*/
nasal_scop::nasal_scop(nasal_gc& ngc):gc(ngc) nasal_scop::nasal_scop(nasal_gc& ngc):gc(ngc)
{ {
std::map<int,nasal_val*> new_scope;
elems.push_back(new_scope);
return; return;
} }
nasal_scop::~nasal_scop() nasal_scop::~nasal_scop()
{ {
for(std::list<std::map<int,nasal_val*> >::iterator i=elems.begin();i!=elems.end();++i) for(std::map<int,nasal_val*>::iterator i=elems.begin();i!=elems.end();++i)
for(std::map<int,nasal_val*>::iterator j=i->begin();j!=i->end();++j)
gc.del_reference(j->second);
elems.clear();
return;
}
void nasal_scop::add_scope()
{
std::map<int,nasal_val*> new_scope;
elems.push_front(new_scope);
return;
}
void nasal_scop::del_scope()
{
std::map<int,nasal_val*>& last_scope=elems.front();
for(std::map<int,nasal_val*>::iterator i=last_scope.begin();i!=last_scope.end();++i)
gc.del_reference(i->second); gc.del_reference(i->second);
elems.pop_front(); elems.clear();
return; return;
} }
void nasal_scop::add_new_value(int key,nasal_val* value_address) void nasal_scop::add_new_value(int key,nasal_val* value_address)
{ {
if(elems.front().find(key)!=elems.front().end()) if(elems.find(key)!=elems.end())
{ {
// if this value already exists,delete the old value and update a new value // if this value already exists,delete the old value and update a new value
nasal_val* old_val_address=elems.front()[key]; gc.del_reference(elems[key]);
gc.del_reference(old_val_address);
} }
elems.front()[key]=value_address; elems[key]=value_address;
return; return;
} }
nasal_val* nasal_scop::get_value_address(int key) nasal_val* nasal_scop::get_value_address(int key)
{ {
nasal_val* ret_address=NULL; if(elems.find(key)!=elems.end())
for(std::list<std::map<int,nasal_val*> >::iterator i=elems.begin();i!=elems.end();++i) return elems[key];
if(i->find(key)!=i->end()) return NULL;
return (*i)[key];
return ret_address;
} }
nasal_val** nasal_scop::get_mem_address(int key) nasal_val** nasal_scop::get_mem_address(int key)
{ {
nasal_val** ret_address=NULL; if(elems.find(key)!=elems.end())
for(std::list<std::map<int,nasal_val*> >::iterator i=elems.begin();i!=elems.end();++i) return &(elems[key]);
if(i->find(key)!=i->end()) return NULL;
return &((*i)[key]);
return ret_address;
} }
void nasal_scop::set_closure(nasal_scop& tmp) void nasal_scop::set_closure(nasal_scop& tmp)
{ {
for(std::list<std::map<int,nasal_val*> >::iterator i=elems.begin();i!=elems.end();++i) for(std::map<int,nasal_val*>::iterator i=elems.begin();i!=elems.end();++i)
for(std::map<int,nasal_val*>::iterator j=i->begin();j!=i->end();++j) gc.del_reference(i->second);
gc.del_reference(j->second); elems=tmp.elems;
elems.clear(); for(std::map<int,nasal_val*>::iterator i=elems.begin();i!=elems.end();++i)
for(std::list<std::map<int,nasal_val*> >::iterator i=tmp.elems.begin();i!=tmp.elems.end();++i) gc.add_reference(i->second);
{
std::map<int,nasal_val*> new_scope;
elems.push_back(new_scope);
for(std::map<int,nasal_val*>::iterator j=i->begin();j!=i->end();++j)
{
nasal_val* value_addr=j->second;
gc.add_reference(value_addr);
elems.back()[j->first]=value_addr;
}
}
return; return;
} }

View File

@ -825,17 +825,16 @@ void nasal_vm::opr_callf()
die("callf: called a value that is not a function"); die("callf: called a value that is not a function");
return; return;
} }
nasal_func& ref=func_addr->get_func(); nasal_func& ref_func=func_addr->get_func();
nasal_val* closure=ref.get_closure_addr(); nasal_val* closure=gc.gc_alloc(vm_scop);
nasal_scop& ref_closure=closure->get_closure(); nasal_scop& ref_closure=closure->get_closure();
ref_closure.add_scope(); ref_closure.set_closure(ref_func.get_closure_addr()->get_closure());
local_scope_stack.push(closure); local_scope_stack.push(closure);
gc.add_reference(closure);
if(para_addr->get_type()==vm_vec) if(para_addr->get_type()==vm_vec)
{ {
nasal_vec& ref_vec=para_addr->get_vector(); nasal_vec& ref_vec=para_addr->get_vector();
std::vector<int>& ref_para=ref.get_para(); std::vector<int>& ref_para=ref_func.get_para();
std::vector<nasal_val*>& ref_default=ref.get_default(); std::vector<nasal_val*>& ref_default=ref_func.get_default();
int i=0; int i=0;
for(;i<ref_para.size();++i) for(;i<ref_para.size();++i)
{ {
@ -856,7 +855,7 @@ void nasal_vm::opr_callf()
gc.add_reference(tmp); gc.add_reference(tmp);
} }
} }
if(ref.get_dynamic_para()>=0) if(ref_func.get_dynamic_para()>=0)
{ {
nasal_val* vec_addr=gc.gc_alloc(vm_vec); nasal_val* vec_addr=gc.gc_alloc(vm_vec);
for(;i<ref_vec.size();++i) for(;i<ref_vec.size();++i)
@ -865,15 +864,15 @@ void nasal_vm::opr_callf()
vec_addr->get_vector().add_elem(tmp); vec_addr->get_vector().add_elem(tmp);
gc.add_reference(tmp); gc.add_reference(tmp);
} }
ref_closure.add_new_value(ref.get_dynamic_para(),vec_addr); ref_closure.add_new_value(ref_func.get_dynamic_para(),vec_addr);
} }
} }
else else
{ {
nasal_hash& ref_hash=para_addr->get_hash(); nasal_hash& ref_hash=para_addr->get_hash();
std::vector<int>& ref_para=ref.get_para(); std::vector<int>& ref_para=ref_func.get_para();
std::vector<nasal_val*>& ref_default=ref.get_default(); std::vector<nasal_val*>& ref_default=ref_func.get_default();
if(ref.get_dynamic_para()>=0) if(ref_func.get_dynamic_para()>=0)
{ {
die("callf: special call cannot use dynamic parameter"); die("callf: special call cannot use dynamic parameter");
return; return;
@ -894,7 +893,7 @@ void nasal_vm::opr_callf()
} }
gc.del_reference(para_addr); gc.del_reference(para_addr);
call_stack.push(ptr); call_stack.push(ptr);
ptr=ref.get_entry()-1; ptr=ref_func.get_entry()-1;
return; return;
} }
void nasal_vm::opr_builtincall() void nasal_vm::opr_builtincall()
@ -1086,7 +1085,6 @@ void nasal_vm::opr_return()
{ {
nasal_val* closure_addr=local_scope_stack.top(); nasal_val* closure_addr=local_scope_stack.top();
local_scope_stack.pop(); local_scope_stack.pop();
closure_addr->get_closure().del_scope();
gc.del_reference(closure_addr); gc.del_reference(closure_addr);
ptr=call_stack.top(); ptr=call_stack.top();
call_stack.pop(); call_stack.pop();