diff --git a/vm/data_gc.hpp b/vm/data_gc.hpp index 995d539d5d..47d2657587 100755 --- a/vm/data_gc.hpp +++ b/vm/data_gc.hpp @@ -22,19 +22,6 @@ void init_data_gc(); void gc(); -inline bool factorvm::collecting_accumulation_gen_p() -{ - return ((data->have_aging_p() - && collecting_gen == data->aging() - && !collecting_aging_again) - || collecting_gen == data->tenured()); -} - -inline bool collecting_accumulation_gen_p() -{ - return vm->collecting_accumulation_gen_p(); -} - void copy_handle(cell *handle); void garbage_collection(volatile cell gen, @@ -46,90 +33,6 @@ allocation (which does not call GC because of possible roots in volatile registers) does not run out of memory */ static const cell allot_buffer_zone = 1024; -inline object *factorvm::allot_zone(zone *z, cell a) -{ - cell h = z->here; - z->here = h + align8(a); - object *obj = (object *)h; - allot_barrier(obj); - return obj; -} - -inline object *allot_zone(zone *z, cell a) -{ - return vm->allot_zone(z,a); -} - -/* - * It is up to the caller to fill in the object's fields in a meaningful - * fashion! - */ -inline object *factorvm::allot_object(header header, cell size) -{ -#ifdef GC_DEBUG - if(!gc_off) - gc(); -#endif - - object *obj; - - if(nursery.size - allot_buffer_zone > size) - { - /* If there is insufficient room, collect the nursery */ - if(nursery.here + allot_buffer_zone + size > nursery.end) - garbage_collection(data->nursery(),false,0); - - cell h = nursery.here; - nursery.here = h + align8(size); - obj = (object *)h; - } - /* If the object is bigger than the nursery, allocate it in - tenured space */ - else - { - zone *tenured = &data->generations[data->tenured()]; - - /* If tenured space does not have enough room, collect */ - if(tenured->here + size > tenured->end) - { - gc(); - tenured = &data->generations[data->tenured()]; - } - - /* If it still won't fit, grow the heap */ - if(tenured->here + size > tenured->end) - { - garbage_collection(data->tenured(),true,size); - tenured = &data->generations[data->tenured()]; - } - - obj = allot_zone(tenured,size); - - /* Allows initialization code to store old->new pointers - without hitting the write barrier in the common case of - a nursery allocation */ - write_barrier(obj); - } - - obj->h = header; - return obj; -} - -inline object *allot_object(header header, cell size) -{ - return vm->allot_object(header,size); -} - -template TYPE *factorvm::allot(cell size) -{ - return (TYPE *)allot_object(header(TYPE::type_number),size); -} - -template TYPE *allot(cell size) -{ - return vm->allot(size); -} - void copy_reachable_objects(cell scan, cell *end); PRIMITIVE(gc); @@ -140,38 +43,6 @@ PRIMITIVE(become); extern bool growing_data_heap; -inline void factorvm::check_data_pointer(object *pointer) -{ -#ifdef FACTOR_DEBUG - if(!growing_data_heap) - { - assert((cell)pointer >= data->seg->start - && (cell)pointer < data->seg->end); - } -#endif -} - -inline void check_data_pointer(object *pointer) -{ - return vm->check_data_pointer(pointer); -} - -inline void factorvm::check_tagged_pointer(cell tagged) -{ -#ifdef FACTOR_DEBUG - if(!immediate_p(tagged)) - { - object *obj = untag(tagged); - check_data_pointer(obj); - obj->h.hi_tag(); - } -#endif -} - -inline void check_tagged_pointer(cell tagged) -{ - return vm->check_tagged_pointer(tagged); -} VM_ASM_API void inline_gc(cell *gc_roots_base, cell gc_roots_size); diff --git a/vm/local_roots.hpp b/vm/local_roots.hpp index 26d083be40..412ef35bb4 100644 --- a/vm/local_roots.hpp +++ b/vm/local_roots.hpp @@ -1,49 +1,4 @@ namespace factor { -struct factorvm; - -template -struct gc_root : public tagged -{ - factorvm *myvm; - - void push() { check_tagged_pointer(tagged::value()); myvm->gc_locals.push_back((cell)this); } - - //explicit gc_root(cell value_, factorvm *vm) : myvm(vm),tagged(value_) { push(); } - explicit gc_root(cell value_,factorvm *vm) : tagged(value_),myvm(vm) { push(); } - explicit gc_root(TYPE *value_, factorvm *vm) : tagged(value_),myvm(vm) { push(); } - - const gc_root& operator=(const TYPE *x) { tagged::operator=(x); return *this; } - const gc_root& operator=(const cell &x) { tagged::operator=(x); return *this; } - - ~gc_root() { -#ifdef FACTOR_DEBUG - assert(myvm->gc_locals.back() == (cell)this); -#endif - myvm->gc_locals.pop_back(); - } -}; - -/* A similar hack for the bignum implementation */ -struct gc_bignum -{ - bignum **addr; - factorvm *myvm; - gc_bignum(bignum **addr_, factorvm *vm) : addr(addr_), myvm(vm) { - if(*addr_) - check_data_pointer(*addr_); - myvm->gc_bignums.push_back((cell)addr); - } - - ~gc_bignum() { -#ifdef FACTOR_DEBUG - assert(myvm->gc_bignums.back() == (cell)addr); -#endif - myvm->gc_bignums.pop_back(); - } -}; - -#define GC_BIGNUM(x,vm) gc_bignum x##__gc_root(&x,vm) - } diff --git a/vm/master.hpp b/vm/master.hpp index 0b3bf7b474..7b3d6c5c73 100755 --- a/vm/master.hpp +++ b/vm/master.hpp @@ -49,9 +49,9 @@ #include "code_block.hpp" #include "data_heap.hpp" #include "write_barrier.hpp" -#include "vm.hpp" #include "data_gc.hpp" #include "local_roots.hpp" +#include "vm.hpp" #include "generic_arrays.hpp" #include "debug.hpp" #include "arrays.hpp" diff --git a/vm/vm.hpp b/vm/vm.hpp index cfb18d2036..f44c1ca0eb 100644 --- a/vm/vm.hpp +++ b/vm/vm.hpp @@ -678,6 +678,181 @@ inline void allot_barrier(object *address) return vm->allot_barrier(address); } + +//data_gc.hpp +inline bool factorvm::collecting_accumulation_gen_p() +{ + return ((data->have_aging_p() + && collecting_gen == data->aging() + && !collecting_aging_again) + || collecting_gen == data->tenured()); +} + +inline bool collecting_accumulation_gen_p() +{ + return vm->collecting_accumulation_gen_p(); +} + +inline object *factorvm::allot_zone(zone *z, cell a) +{ + cell h = z->here; + z->here = h + align8(a); + object *obj = (object *)h; + allot_barrier(obj); + return obj; +} + +inline object *allot_zone(zone *z, cell a) +{ + return vm->allot_zone(z,a); +} + +/* + * It is up to the caller to fill in the object's fields in a meaningful + * fashion! + */ +inline object *factorvm::allot_object(header header, cell size) +{ +#ifdef GC_DEBUG + if(!gc_off) + gc(); +#endif + + object *obj; + + if(nursery.size - allot_buffer_zone > size) + { + /* If there is insufficient room, collect the nursery */ + if(nursery.here + allot_buffer_zone + size > nursery.end) + garbage_collection(data->nursery(),false,0); + + cell h = nursery.here; + nursery.here = h + align8(size); + obj = (object *)h; + } + /* If the object is bigger than the nursery, allocate it in + tenured space */ + else + { + zone *tenured = &data->generations[data->tenured()]; + + /* If tenured space does not have enough room, collect */ + if(tenured->here + size > tenured->end) + { + gc(); + tenured = &data->generations[data->tenured()]; + } + + /* If it still won't fit, grow the heap */ + if(tenured->here + size > tenured->end) + { + garbage_collection(data->tenured(),true,size); + tenured = &data->generations[data->tenured()]; + } + + obj = allot_zone(tenured,size); + + /* Allows initialization code to store old->new pointers + without hitting the write barrier in the common case of + a nursery allocation */ + write_barrier(obj); + } + + obj->h = header; + return obj; +} + +inline object *allot_object(header header, cell size) +{ + return vm->allot_object(header,size); +} + +template TYPE *factorvm::allot(cell size) +{ + return (TYPE *)allot_object(header(TYPE::type_number),size); +} + +template TYPE *allot(cell size) +{ + return vm->allot(size); +} + +inline void factorvm::check_data_pointer(object *pointer) +{ +#ifdef FACTOR_DEBUG + if(!growing_data_heap) + { + assert((cell)pointer >= data->seg->start + && (cell)pointer < data->seg->end); + } +#endif +} + +inline void check_data_pointer(object *pointer) +{ + return vm->check_data_pointer(pointer); +} + +inline void factorvm::check_tagged_pointer(cell tagged) +{ +#ifdef FACTOR_DEBUG + if(!immediate_p(tagged)) + { + object *obj = untag(tagged); + check_data_pointer(obj); + obj->h.hi_tag(); + } +#endif +} + +inline void check_tagged_pointer(cell tagged) +{ + return vm->check_tagged_pointer(tagged); +} + +//local_roots.hpp +template +struct gc_root : public tagged +{ + factorvm *myvm; + + void push() { check_tagged_pointer(tagged::value()); myvm->gc_locals.push_back((cell)this); } + + //explicit gc_root(cell value_, factorvm *vm) : myvm(vm),tagged(value_) { push(); } + explicit gc_root(cell value_,factorvm *vm) : tagged(value_),myvm(vm) { push(); } + explicit gc_root(TYPE *value_, factorvm *vm) : tagged(value_),myvm(vm) { push(); } + + const gc_root& operator=(const TYPE *x) { tagged::operator=(x); return *this; } + const gc_root& operator=(const cell &x) { tagged::operator=(x); return *this; } + + ~gc_root() { +#ifdef FACTOR_DEBUG + assert(myvm->gc_locals.back() == (cell)this); +#endif + myvm->gc_locals.pop_back(); + } +}; + +/* A similar hack for the bignum implementation */ +struct gc_bignum +{ + bignum **addr; + factorvm *myvm; + gc_bignum(bignum **addr_, factorvm *vm) : addr(addr_), myvm(vm) { + if(*addr_) + check_data_pointer(*addr_); + myvm->gc_bignums.push_back((cell)addr); + } + + ~gc_bignum() { +#ifdef FACTOR_DEBUG + assert(myvm->gc_bignums.back() == (cell)addr); +#endif + myvm->gc_bignums.pop_back(); + } +}; + +#define GC_BIGNUM(x,vm) gc_bignum x##__gc_root(&x,vm) // next method here: