#ifndef __NASAL_GC_H__ #define __NASAL_GC_H__ // all identifiers in nasal points to a memory space in nasal_gc. // memory space uses std::vector. // gc_unit is a struct which has nasal_scalar and refcnt in it.(more details please see the definition of gc_unit bellow) // when an identifier needs to be assigned,but the type of value is not the same as the identifier's value // the identifier will get a new memory space in nasal_gc and do deep_copy() // and the memory space that is not used ,its ref_cnt-=1. class nasal_closure { private: std::list > closure; public: void set_clear(); void set_local_scope(std::list >&); std::list >& get_local_scope(); void print_closure_ids(); }; class nasal_function { private: // closure_updated flag is used to mark if this function's closure is updated. // to avoid some unexpected errors,closure of each function must be updated before blocks popping back the last scope bool closure_updated; int closure_addr; abstract_syntax_tree parameter_list; abstract_syntax_tree function_root; public: nasal_function(); void set_clear(); void set_local_scope(int); bool get_closure_update_state(); void set_closure_update_state(bool); void set_paramemter_list(abstract_syntax_tree&); void set_statement_block(abstract_syntax_tree&); int get_local_scope(); abstract_syntax_tree& get_parameter_list(); abstract_syntax_tree& get_statement_block(); void deep_copy(nasal_function&); }; class nasal_number { private: double nas_number; public: void set_clear(); void set_number(double); double get_number(); void deep_copy(nasal_number&); }; class nasal_string { private: std::string nas_string; public: void set_clear(); void set_string(std::string); std::string get_string(); void deep_copy(nasal_string&); }; class nasal_vector { private: std::vector nas_array; public: void set_clear(); void vec_push(int); int* get_elem_addr(int); int get_elem(int); int vec_pop(); int get_size(); int* get_parent_hash_member_addr(std::string); int get_parent_hash_member(std::string); void generate_new_hash(); void deep_copy(nasal_vector&); }; class nasal_hash { private: std::map nas_hash; public: void set_clear(); int* get_hash_member_addr(std::string); int get_hash_member(std::string); std::vector get_elem(); void hash_push(std::string,int); void hash_pop(std::string); void deep_copy(nasal_hash&); }; class nasal_scalar { private: int type; nasal_string var_string; nasal_number var_number; nasal_vector var_vector; nasal_hash var_hash; nasal_function var_func; nasal_closure var_cls; public: nasal_scalar(); void set_type(int); int get_type(); nasal_number& get_number(); nasal_string& get_string(); nasal_vector& get_vector(); nasal_hash& get_hash(); nasal_function& get_function(); nasal_closure& get_closure(); }; struct gc_unit { // collected: If gc collected this item,it'll be set to true.Otherwise it is false. // elem: Item that this unit stores // refcnt: Reference counter bool collected; bool is_const; nasal_scalar elem; int refcnt; gc_unit() { collected=true; refcnt=0; return; } }; #ifndef NAS_POOL_SIZE #define NAS_POOL_SIZE 128 struct memory_block { gc_unit space[NAS_POOL_SIZE]; }; class memory_block_base { private: std::vector mem_page; int mem_size; public: memory_block_base() { mem_size=0; memory_block* tmp=new memory_block; mem_page.push_back(tmp); return; } ~memory_block_base() { mem_size=0; int page_size=mem_page.size(); for(int i=0;ispace[block_plc]; } void push_back() { ++mem_size; if(mem_size>mem_page.size()*NAS_POOL_SIZE) { memory_block* tmp=new memory_block; mem_page.push_back(tmp); } return; } int size() { return mem_size; } int capacity() { return NAS_POOL_SIZE*mem_page.size(); } }; #endif class gc_manager { private: // free_space list is used to store space that is not in use. std::list free_space; /* cannot use std::vector to simulate memory because if vector memory is not enough,vector will use another larger memory as it's main memory then all the things will be moved to a new space, at this time if you reference a member in it,this will cause segmentation error. */ memory_block_base memory; bool error_occurred; public: void gc_init() { // this function must be called in class nasal_runtime before running any codes memory.clear(); free_space.clear(); error_occurred=false; return; } int gc_alloc() { // add a new space for a new value // if list free_space is not empty,it will get the address at the front and give it to the new value // if list free_space is empty,it will add new space in memory vector and give it to the new value // by this way it can manage memory efficiently. if(free_space.empty()) { memory.push_back(); free_space.push_back(memory.size()-1); } int alloc_plc=free_space.front(); free_space.pop_front(); memory[alloc_plc].collected=false; memory[alloc_plc].refcnt=1; return alloc_plc; } int get_reference(int addr) { // get the reference counts of the scalar if(addr>=memory.size()) return -1; return memory[addr].refcnt; } nasal_scalar& get_scalar(int addr) { // get the reference of the scalar return memory[addr].elem; } bool place_check(const int addr) { // check if this place is in memory // and this place is uncollected // this function is often used when an identifier is calling a space in memory return (0<=addr) && (addr> [Gc] fatal error: reference unexpected memory place "; prt_hex(addr); std::cout<<" ."<> [Gc] collected ";prt_hex(addr);std::cout<> [Gc] fatal error: delete unexpected memory address: "; prt_hex(addr); std::cout<<" ."<> [Gc] memory size:"<> [Gc] memory capacity:"<> [Gc] memory usage: "< >::iterator iter=closure.begin();iter!=closure.end();++iter) for(std::map::iterator i=iter->begin();i!=iter->end();++i) nasal_gc.reference_delete(i->second); closure.clear(); return; } void nasal_closure::set_local_scope(std::list >& tmp_scope) { if(closure.size()) for(std::list >::iterator iter=closure.begin();iter!=closure.end();++iter) for(std::map::iterator i=iter->begin();i!=iter->end();++i) nasal_gc.reference_delete(i->second); closure.clear(); closure=tmp_scope; for(std::list >::iterator iter=closure.begin();iter!=closure.end();++iter) for(std::map::iterator i=iter->begin();i!=iter->end();++i) nasal_gc.reference_add(i->second); return; } std::list >& nasal_closure::get_local_scope() { return closure; } void nasal_closure::print_closure_ids() { for(std::list >::iterator iter=closure.begin();iter!=closure.end();++iter) for(std::map::iterator i=iter->begin();i!=iter->end();++i) { std::cout<first<<": "; prt_hex(i->second); std::cout<=0) nasal_gc.reference_delete(closure_addr); closure_addr=-1; function_root.set_clear(); return; } void nasal_function::set_local_scope(int tmp_addr) { if(closure_addr>=0) nasal_gc.reference_delete(closure_addr); closure_addr=tmp_addr; return; } bool nasal_function::get_closure_update_state() { return closure_updated; } void nasal_function::set_closure_update_state(bool _state) { closure_updated=_state; return; } void nasal_function::set_paramemter_list(abstract_syntax_tree& para_list) { parameter_list=para_list; return; } void nasal_function::set_statement_block(abstract_syntax_tree& func_block) { function_root=func_block; return; } int nasal_function::get_local_scope() { return closure_addr; } abstract_syntax_tree& nasal_function::get_parameter_list() { return parameter_list; } abstract_syntax_tree& nasal_function::get_statement_block() { return function_root; } void nasal_function::deep_copy(nasal_function& tmp) { if(closure_addr>=0) nasal_gc.reference_delete(closure_addr); closure_addr=tmp.closure_addr; nasal_gc.reference_add(closure_addr); // copy abstract_syntax_tree parameter_list=tmp.parameter_list; function_root=tmp.function_root; return; } void nasal_number::set_clear() { nas_number=0; return; } void nasal_number::set_number(double num) { nas_number=num; return; } double nasal_number::get_number() { return nas_number; } void nasal_number::deep_copy(nasal_number& tmp) { nas_number=tmp.nas_number; return; } void nasal_string::set_clear() { nas_string=""; return; } void nasal_string::set_string(std::string str) { nas_string=str; return; } std::string nasal_string::get_string() { return nas_string; } void nasal_string::deep_copy(nasal_string& tmp) { nas_string=tmp.nas_string; return; } void nasal_vector::set_clear() { for(int i=0;i vec_for_swap; nas_array.swap(vec_for_swap); return; } void nasal_vector::vec_push(int addr) { nas_array.push_back(addr); return; } int* nasal_vector::get_elem_addr(int addr) { // 0 ~ size-1 -size ~ -1 int bound=nas_array.size(); if(-bound<=addr && addr<0) return &nas_array[bound+addr]; else if(0<=addr && addr=0) break; } return ret_addr; } void nasal_vector::generate_new_hash() { for(int i=0;i=0 && nasal_gc.get_scalar(nas_array[i]).get_type()==scalar_hash) { int tmp_addr=nas_array[i]; nas_array[i]=nasal_gc.gc_alloc(); nasal_gc.get_scalar(nas_array[i]).set_type(scalar_hash); nasal_gc.get_scalar(nas_array[i]).get_hash().deep_copy(nasal_gc.get_scalar(tmp_addr).get_hash()); nasal_gc.reference_delete(tmp_addr);; } return; } void nasal_vector::deep_copy(nasal_vector& tmp) { // before deep copy,nasal_vector needs to delete all values in it. for(int i=0;i::iterator i=nas_hash.begin();i!=nas_hash.end();++i) nasal_gc.reference_delete(i->second); return; } int* nasal_hash::get_hash_member_addr(std::string member_name) { if(nas_hash.find(member_name)!=nas_hash.end()) return &nas_hash[member_name]; else if(nas_hash.find("parents")!=nas_hash.end()) return nasal_gc.get_scalar(nas_hash["parents"]).get_vector().get_parent_hash_member_addr(member_name); return NULL; } int nasal_hash::get_hash_member(std::string member_name) { if(nas_hash.find(member_name)!=nas_hash.end()) return nas_hash[member_name]; else if(nas_hash.find("parents")!=nas_hash.end()) return nasal_gc.get_scalar(nas_hash["parents"]).get_vector().get_parent_hash_member(member_name); return -1; } std::vector nasal_hash::get_elem() { std::vector vec; for(std::map::iterator i=nas_hash.begin();i!=nas_hash.end();++i) vec.push_back(i->second); return vec; } void nasal_hash::hash_push(std::string member_name,int addr) { nas_hash[member_name]=addr; return; } void nasal_hash::hash_pop(std::string member_name) { if(nas_hash.find(member_name)!=nas_hash.end()) { nasal_gc.reference_delete(nas_hash[member_name]); nas_hash.erase(member_name); } return; } void nasal_hash::deep_copy(nasal_hash& tmp) { // defore deep copy,nasal_hash needs to delete all members in it for(std::map::iterator i=nas_hash.begin();i!=nas_hash.end();++i) nasal_gc.reference_delete(i->second); // copy process for(std::map::iterator i=tmp.nas_hash.begin();i!=tmp.nas_hash.end();++i) { int tmp_type=nasal_gc.get_scalar(i->second).get_type(); int new_addr=nasal_gc.gc_alloc(); nasal_gc.get_scalar(new_addr).set_type(tmp_type); switch(tmp_type) { case scalar_nil :break; case scalar_number :nasal_gc.get_scalar(new_addr).get_number().deep_copy(nasal_gc.get_scalar(i->second).get_number());break; case scalar_string :nasal_gc.get_scalar(new_addr).get_string().deep_copy(nasal_gc.get_scalar(i->second).get_string());break; case scalar_vector :nasal_gc.get_scalar(new_addr).get_vector().deep_copy(nasal_gc.get_scalar(i->second).get_vector());break; case scalar_hash :nasal_gc.get_scalar(new_addr).get_hash().deep_copy(nasal_gc.get_scalar(i->second).get_hash());break; case scalar_function:nasal_gc.get_scalar(new_addr).get_function().deep_copy(nasal_gc.get_scalar(i->second).get_function());break; } nas_hash[i->first]=new_addr; } return; } nasal_scalar::nasal_scalar() { type=scalar_nil; return; } void nasal_scalar::set_type(int tmp_type) { // scalar_function is the last enum in enum::scalar_type type=tmp_type>scalar_closure? scalar_nil:tmp_type; return; } int nasal_scalar::get_type() { // get scalar type return type; } nasal_number& nasal_scalar::get_number() { // get nasal_number return var_number; } nasal_string& nasal_scalar::get_string() { // get nasal_string return var_string; } nasal_vector& nasal_scalar::get_vector() { // get nasal_vector return var_vector; } nasal_hash& nasal_scalar::get_hash() { // get nasal_hash return var_hash; } nasal_function& nasal_scalar::get_function() { // get nasal_function return var_func; } nasal_closure& nasal_scalar::get_closure() { // get nasal_closure return var_cls; } #endif /* code: var i=1; int addr=nasal_gc.gc_alloc(); nasal_gc.get_scalar(addr).set_type(scalar_number); nasal_gc.get_scalar(addr).set_number(1); code: var i='hello'; int addr=nasal_gc.gc_alloc(); nasal_gc.get_scalar(addr).set_type(scalar_string); nasal_gc.get_scalar(addr).set_string("hello"); code: var i=[]; int addr=vector_generation(); nasal_gc.get_scalar(addr).set_type(scalar_vector); code: var i={}; int addr=hash_generation(); nasal_gc.get_scalar(addr).set_type(scalar_hash); nasal_gc.get_scalar(addr).get_hash().set_self_addr(addr); code: var i=func{return 0;} // copy local_scope if needed // copy abstract_syntax_tree */