This commit is contained in:
Valk Richard Li 2020-09-10 08:34:02 -07:00 committed by GitHub
parent 17fa6a71b9
commit 54a80df127
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 107 additions and 71 deletions

View File

@ -77,7 +77,7 @@ public:
void add_new_value(std::string,int);
int get_value_address(std::string);
int get_mem_address(std::string);
void deepcopy(nasal_closure&);
void set_closure(nasal_closure&);
};
class nasal_scalar
@ -123,7 +123,7 @@ class nasal_virtual_machine
struct gc_unit
{
bool collected;
char ref_cnt;
int ref_cnt;
nasal_scalar elem;
gc_unit()
{
@ -141,10 +141,12 @@ private:
public:
~nasal_virtual_machine();
void clear();
void debug();
int gc_alloc(); // garbage collector gives a new space
nasal_scalar& gc_get(int); // get scalar that stored in gc
int add_reference(int);
int del_reference(int);
void add_reference(int);
void del_reference(int);
int get_refcnt(int);
int mem_alloc(); // memory gives a new space
int mem_free(int); // give space back to memory
int mem_change(int,int); // change value in memory space
@ -190,6 +192,8 @@ int nasal_vector::del_elem(int index)
return -1;
int ret=elems[index];
nasal_vm.mem_free(ret);
for(int i=index;i<elems.size()-1;++i)
elems[i]=elems[i+1];
elems.pop_back();
return ret;
}
@ -352,7 +356,10 @@ void nasal_function::set_closure_addr(int value_address)
{
if(closure_addr>=0)
nasal_vm.del_reference(closure_addr);
closure_addr=value_address;
int new_closure=nasal_vm.gc_alloc();
nasal_vm.gc_get(new_closure).set_type(vm_closure);
nasal_vm.gc_get(new_closure).get_closure().set_closure(nasal_vm.gc_get(value_address).get_closure());
closure_addr=new_closure;
return;
}
int nasal_function::get_closure_addr()
@ -415,39 +422,8 @@ void nasal_closure::del_scope()
{
if(this->elems.empty())
return;
// make closure here
// functions in different scope but the same closure will get different copies of closures
// functions in the same scope will get the same copy of closure,when running these functions,one closure will be changed,make sure you are using it correctly!
// please notice this,otherwise your programme may not work correctly
int closure=nasal_vm.gc_alloc();
nasal_vm.gc_get(closure).set_type(vm_closure);
nasal_closure& new_closure=nasal_vm.gc_get(closure).get_closure();
new_closure.deepcopy(*this);
std::vector<std::string> func_name;
for(std::map<std::string,int>::iterator i=new_closure.elems.back().begin();i!=new_closure.elems.back().end();++i)
{
int value_addr=nasal_vm.mem_get(i->second);
if(nasal_vm.gc_get(value_addr).get_type()==vm_function)
{
func_name.push_back(i->first);
nasal_vm.mem_free(i->second); // mem_free will delete the reference of mem_get(i->second)
}
}
for(int i=0;i<func_name.size();++i)
new_closure.elems.back().erase(func_name[i]);
for(std::map<std::string,int>::iterator i=this->elems.back().begin();i!=this->elems.back().end();++i)
{
int value_addr=nasal_vm.mem_get(i->second);
if(nasal_vm.gc_get(value_addr).get_type()==vm_function)
{
nasal_vm.gc_get(value_addr).get_func().set_closure_addr(closure);
nasal_vm.add_reference(closure);
}
for(std::map<std::string,int>::iterator i=elems.back().begin();i!=elems.back().end();++i)
nasal_vm.mem_free(i->second);
}
nasal_vm.del_reference(closure);
this->elems.pop_back();
return;
}
@ -484,19 +460,22 @@ int nasal_closure::get_mem_address(std::string key)
}
return ret_address;
}
void nasal_closure::deepcopy(nasal_closure& tmp)
void nasal_closure::set_closure(nasal_closure& tmp)
{
for(std::list<std::map<std::string,int> >::iterator i=elems.begin();i!=elems.end();++i)
for(std::map<std::string,int>::iterator j=i->begin();j!=i->end();++j)
nasal_vm.mem_free(j->second);
elems.clear();
for(std::list<std::map<std::string,int> >::iterator i=tmp.elems.begin();i!=tmp.elems.end();++i)
{
this->add_scope();
for(std::map<std::string,int>::iterator j=i->begin();j!=i->end();++j)
{
int new_mem_addr=nasal_vm.mem_alloc();
int new_value_addr=nasal_vm.gc_alloc();
nasal_vm.mem_init(new_mem_addr,new_value_addr);
int tmp_value_addr=nasal_vm.mem_get(j->second);
nasal_vm.gc_get(new_value_addr).deepcopy(nasal_vm.gc_get(tmp_value_addr));
this->elems.back()[j->first]=new_mem_addr;
int value_addr=nasal_vm.mem_get(j->second);
nasal_vm.mem_init(new_mem_addr,value_addr);
nasal_vm.add_reference(value_addr);
elems.back()[j->first]=new_mem_addr;
}
}
return;
@ -521,12 +500,12 @@ nasal_scalar::~nasal_scalar()
case vm_function: delete (nasal_function*)(this->scalar_ptr); break;
case vm_closure: delete (nasal_closure*)(this->scalar_ptr); break;
}
this->type=vm_nil;
this->scalar_ptr=NULL;
return;
}
void nasal_scalar::clear()
{
this->type=vm_nil;
switch(this->type)
{
case vm_nil: break;
@ -537,6 +516,7 @@ void nasal_scalar::clear()
case vm_function: delete (nasal_function*)(this->scalar_ptr); break;
case vm_closure: delete (nasal_closure*)(this->scalar_ptr); break;
}
this->type=vm_nil;
this->scalar_ptr=NULL;
return;
}
@ -630,7 +610,7 @@ void nasal_scalar::deepcopy(nasal_scalar& tmp)
case vm_vector: this->scalar_ptr=(void*)(new nasal_vector);(*(nasal_vector*)this->scalar_ptr).deepcopy(tmp.get_vector());break;
case vm_hash: this->scalar_ptr=(void*)(new nasal_hash);(*(nasal_hash*)this->scalar_ptr).deepcopy(tmp.get_hash());break;
case vm_function: this->scalar_ptr=(void*)(new nasal_function);(*(nasal_function*)this->scalar_ptr).deepcopy(tmp.get_func());break;
case vm_closure: this->scalar_ptr=(void*)(new nasal_closure);(*(nasal_closure*)this->scalar_ptr).deepcopy(tmp.get_closure());break;
case vm_closure: this->scalar_ptr=(void*)(new nasal_closure);(*(nasal_closure*)this->scalar_ptr).set_closure(tmp.get_closure());break;
}
return;
}
@ -1381,19 +1361,52 @@ nasal_virtual_machine::~nasal_virtual_machine()
int gc_mem_size=garbage_collector_memory.size();
int mm_mem_size=memory_manager_memory.size();
for(int i=0;i<gc_mem_size;++i)
{
for(int j=0;j<GC_BLK_SIZE;++j)
if(garbage_collector_memory[i][j].ref_cnt)
garbage_collector_memory[i][j].elem.clear();
delete []garbage_collector_memory[i];
}
for(int i=0;i<mm_mem_size;++i)
delete []memory_manager_memory[i];
garbage_collector_memory.clear();
memory_manager_memory.clear();
return;
}
void nasal_virtual_machine::debug()
{
int gc_mem_size=garbage_collector_memory.size();
int mm_mem_size=memory_manager_memory.size();
for(int i=0;i<gc_mem_size;++i)
for(int j=0;j<GC_BLK_SIZE;++j)
if(garbage_collector_memory[i][j].ref_cnt)
{
std::cout<<">> [debug] "<<((i<<8)+j)<<": "<<garbage_collector_memory[i][j].ref_cnt<<" ";
switch(garbage_collector_memory[i][j].elem.get_type())
{
case vm_nil:std::cout<<"nil";break;
case vm_number:std::cout<<"number "<<garbage_collector_memory[i][j].elem.get_number();break;
case vm_string:std::cout<<"string "<<garbage_collector_memory[i][j].elem.get_string();break;
case vm_vector:std::cout<<"vector";break;
case vm_hash:std::cout<<"hash";break;
case vm_function:std::cout<<"function";break;
case vm_closure:std::cout<<"closure";break;
}
std::cout<<"\n";
}
return;
}
void nasal_virtual_machine::clear()
{
int gc_mem_size=garbage_collector_memory.size();
int mm_mem_size=memory_manager_memory.size();
for(int i=0;i<gc_mem_size;++i)
{
for(int j=0;j<GC_BLK_SIZE;++j)
if(garbage_collector_memory[i][j].ref_cnt)
garbage_collector_memory[i][j].elem.clear();
delete []garbage_collector_memory[i];
}
for(int i=0;i<mm_mem_size;++i)
delete []memory_manager_memory[i];
while(!garbage_collector_free_space.empty())
@ -1432,20 +1445,17 @@ nasal_scalar& nasal_virtual_machine::gc_get(int value_address)
return error_returned_value;
}
}
int nasal_virtual_machine::add_reference(int value_address)
void nasal_virtual_machine::add_reference(int value_address)
{
int blk_num=(value_address>>8);
int blk_plc=(value_address&0xff);
if(0<=value_address && value_address<(garbage_collector_memory.size()<<8) && !garbage_collector_memory[blk_num][blk_plc].collected)
++garbage_collector_memory[blk_num][blk_plc].ref_cnt;
else
{
std::cout<<">> [vm] gc_add_ref:unexpected memory \'"<<value_address<<"\'."<<std::endl;
return 0;
}
return 1;
return;
}
int nasal_virtual_machine::del_reference(int value_address)
void nasal_virtual_machine::del_reference(int value_address)
{
int blk_num=(value_address>>8);
int blk_plc=(value_address&0xff);
@ -1454,7 +1464,7 @@ int nasal_virtual_machine::del_reference(int value_address)
else
{
std::cout<<">> [vm] gc_del_ref:unexpected memory \'"<<value_address<<"\'."<<std::endl;
return 0;
return;
}
if(!garbage_collector_memory[blk_num][blk_plc].ref_cnt)
{
@ -1462,7 +1472,17 @@ int nasal_virtual_machine::del_reference(int value_address)
garbage_collector_memory[blk_num][blk_plc].elem.clear();
garbage_collector_free_space.push(value_address);
}
return 1;
return;
}
int nasal_virtual_machine::get_refcnt(int value_address)
{
int blk_num=(value_address>>8);
int blk_plc=(value_address&0xff);
if(0<=value_address && value_address<(garbage_collector_memory.size()<<8) && !garbage_collector_memory[blk_num][blk_plc].collected)
return garbage_collector_memory[blk_num][blk_plc].ref_cnt;
else
std::cout<<">> [vm] get_refcnt:unexpected memory \'"<<value_address<<"\'."<<std::endl;
return -1;
}
int nasal_virtual_machine::mem_alloc()
{

View File

@ -40,7 +40,7 @@ private:
// generate hash and return gc place of this hash
int hash_generation(nasal_ast&,int);
// generate function and return gc place of this function
int function_generation(nasal_ast&);
int function_generation(nasal_ast&,int);
/*
functions after this note may have parameter named 'local_scope_addr'
@ -104,6 +104,7 @@ void nasal_runtime::set_root(nasal_ast& parse_result)
void nasal_runtime::run()
{
this->error=0;
this->function_returned_address=-1;
this->global_scope_address=nasal_vm.gc_alloc();
nasal_vm.gc_get(global_scope_address).set_type(vm_closure);
@ -168,7 +169,7 @@ int nasal_runtime::hash_generation(nasal_ast& node,int local_scope_addr)
}
return new_addr;
}
int nasal_runtime::function_generation(nasal_ast& node)
int nasal_runtime::function_generation(nasal_ast& node,int local_scope_addr)
{
int new_addr=nasal_vm.gc_alloc();
nasal_vm.gc_get(new_addr).set_type(vm_function);
@ -177,9 +178,15 @@ int nasal_runtime::function_generation(nasal_ast& node)
ref_of_this_function.set_arguments(node.get_children()[0]);
ref_of_this_function.set_run_block(node.get_children()[1]);
int new_closure=nasal_vm.gc_alloc();
nasal_vm.gc_get(new_closure).set_type(vm_closure);
ref_of_this_function.set_closure_addr(new_closure);
if(local_scope_addr>=0)
ref_of_this_function.set_closure_addr(local_scope_addr);
else
{
int new_closure=nasal_vm.gc_alloc();
nasal_vm.gc_get(new_closure).set_type(vm_closure);
ref_of_this_function.set_closure_addr(new_closure);
nasal_vm.del_reference(new_closure);
}
return new_addr;
}
int nasal_runtime::main_progress()
@ -353,12 +360,18 @@ int nasal_runtime::loop_progress(nasal_ast& node,int local_scope_addr,bool allow
nasal_vm.gc_get(while_local_scope_addr).get_closure().add_scope();
}
// check condition and begin loop
while(check_condition(calculation(condition_node,while_local_scope_addr)))
int condition_value_addr=calculation(condition_node,while_local_scope_addr);
bool result=check_condition(condition_value_addr);
nasal_vm.del_reference(condition_value_addr);
while(result)
{
// return expression will be checked in block_progress
ret_state=block_progress(run_block_node,local_scope_addr,allow_return);
if(ret_state==rt_break || ret_state==rt_error || ret_state==rt_return)
break;
condition_value_addr=calculation(condition_node,while_local_scope_addr);
result=check_condition(condition_value_addr);
nasal_vm.del_reference(condition_value_addr);
}
nasal_vm.gc_get(while_local_scope_addr).get_closure().del_scope();
nasal_vm.del_reference(while_local_scope_addr);
@ -429,6 +442,7 @@ int nasal_runtime::loop_progress(nasal_ast& node,int local_scope_addr,bool allow
if(ret_state==rt_break || ret_state==rt_return || ret_state==rt_error)
break;
}
nasal_vm.del_reference(vector_value_addr);
nasal_vm.gc_get(forei_local_scope_addr).get_closure().del_scope();
nasal_vm.del_reference(forei_local_scope_addr);
}
@ -453,9 +467,12 @@ int nasal_runtime::loop_progress(nasal_ast& node,int local_scope_addr,bool allow
nasal_vm.gc_get(for_local_scope_addr).get_closure().add_scope();
}
// for progress
int condition_value_addr=calculation(condition_node,for_local_scope_addr);
bool result=check_condition(condition_value_addr);
nasal_vm.del_reference(condition_value_addr);
for(
ret_state=before_for_loop(before_loop_node,for_local_scope_addr);
check_condition(calculation(condition_node,for_local_scope_addr));
result;
ret_state=after_each_for_loop(each_loop_do_node,for_local_scope_addr)
)
{
@ -464,6 +481,9 @@ int nasal_runtime::loop_progress(nasal_ast& node,int local_scope_addr,bool allow
ret_state=block_progress(run_block_node,for_local_scope_addr,allow_return);
if(ret_state==rt_error || ret_state==rt_return || ret_state==rt_break)
break;
condition_value_addr=calculation(condition_node,for_local_scope_addr);
result=check_condition(condition_value_addr);
nasal_vm.del_reference(condition_value_addr);
}
nasal_vm.gc_get(for_local_scope_addr).get_closure().del_scope();
nasal_vm.del_reference(for_local_scope_addr);
@ -513,7 +533,9 @@ int nasal_runtime::conditional_progress(nasal_ast& node,int local_scope_addr,boo
int condition_value_addr=calculation(tmp_node.get_children()[0],local_scope_addr);
if(condition_value_addr<0)
return rt_error;
if(check_condition(condition_value_addr))
bool result=check_condition(condition_value_addr);
nasal_vm.del_reference(condition_value_addr);
if(result)
{
ret_state=block_progress(tmp_node.get_children()[1],local_scope_addr,allow_return);
break;
@ -862,8 +884,8 @@ int nasal_runtime::call_function(nasal_ast& node,std::string func_name,int base_
// set self
if(func_name.length())
{
run_closure.add_new_value(func_name,base_value_addr);
nasal_vm.add_reference(base_value_addr);
run_closure.add_new_value(func_name,base_value_addr);
}
// set hash.me
if(last_call_hash_addr>=0)
@ -1041,6 +1063,8 @@ int nasal_runtime::call_function(nasal_ast& node,std::string func_name,int base_
}
}
int ret_state=block_progress(reference_of_func.get_run_block(),run_closure_addr,true);
run_closure.del_scope();
if(ret_state==rt_break || ret_state==rt_continue)
{
std::cout<<">> [runtime] call_function: break and continue are not allowed to be used here."<<std::endl;
@ -1050,7 +1074,6 @@ int nasal_runtime::call_function(nasal_ast& node,std::string func_name,int base_
else if(ret_state==rt_error)
return -1;
run_closure.del_scope();
if(function_returned_address>=0)
{
ret_value_addr=function_returned_address;
@ -1243,7 +1266,7 @@ int nasal_runtime::calculation(nasal_ast& node,int local_scope_addr)
else if(calculation_type==ast_hash)
ret_address=hash_generation(node,local_scope_addr);
else if(calculation_type==ast_function)
ret_address=function_generation(node);
ret_address=function_generation(node,local_scope_addr);
else if(calculation_type==ast_call)
ret_address=call_scalar(node,local_scope_addr);
else if(calculation_type==ast_add)
@ -1393,13 +1416,6 @@ int nasal_runtime::calculation(nasal_ast& node,int local_scope_addr)
int new_scalar_gc_addr=calculation(node.get_children()[1],local_scope_addr);
int type=nasal_vm.gc_get(new_scalar_gc_addr).get_type();
if(type!=vm_hash && type!=vm_vector)
{
int tmp_value_addr=nasal_vm.gc_alloc();
nasal_vm.gc_get(tmp_value_addr).deepcopy(nasal_vm.gc_get(new_scalar_gc_addr));
nasal_vm.del_reference(new_scalar_gc_addr);
new_scalar_gc_addr=tmp_value_addr;
}
nasal_vm.mem_change(scalar_mem_space,new_scalar_gc_addr);// this progress will delete the reference to old gc_addr in scalar_mem_space
nasal_vm.add_reference(new_scalar_gc_addr);// this reference is reserved for ret_address
ret_address=new_scalar_gc_addr;