moved data_gc and local_roots inline functions to vm.hpp
parent
31905b68a7
commit
4dabd186c9
129
vm/data_gc.hpp
129
vm/data_gc.hpp
|
@ -22,19 +22,6 @@ void init_data_gc();
|
||||||
|
|
||||||
void 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 copy_handle(cell *handle);
|
||||||
|
|
||||||
void garbage_collection(volatile cell gen,
|
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 */
|
registers) does not run out of memory */
|
||||||
static const cell allot_buffer_zone = 1024;
|
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<typename TYPE> TYPE *factorvm::allot(cell size)
|
|
||||||
{
|
|
||||||
return (TYPE *)allot_object(header(TYPE::type_number),size);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename TYPE> TYPE *allot(cell size)
|
|
||||||
{
|
|
||||||
return vm->allot<TYPE>(size);
|
|
||||||
}
|
|
||||||
|
|
||||||
void copy_reachable_objects(cell scan, cell *end);
|
void copy_reachable_objects(cell scan, cell *end);
|
||||||
|
|
||||||
PRIMITIVE(gc);
|
PRIMITIVE(gc);
|
||||||
|
@ -140,38 +43,6 @@ PRIMITIVE(become);
|
||||||
|
|
||||||
extern bool growing_data_heap;
|
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<object>(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);
|
VM_ASM_API void inline_gc(cell *gc_roots_base, cell gc_roots_size);
|
||||||
|
|
||||||
|
|
|
@ -1,49 +1,4 @@
|
||||||
namespace factor
|
namespace factor
|
||||||
{
|
{
|
||||||
|
|
||||||
struct factorvm;
|
|
||||||
|
|
||||||
template <typename TYPE>
|
|
||||||
struct gc_root : public tagged<TYPE>
|
|
||||||
{
|
|
||||||
factorvm *myvm;
|
|
||||||
|
|
||||||
void push() { check_tagged_pointer(tagged<TYPE>::value()); myvm->gc_locals.push_back((cell)this); }
|
|
||||||
|
|
||||||
//explicit gc_root(cell value_, factorvm *vm) : myvm(vm),tagged<TYPE>(value_) { push(); }
|
|
||||||
explicit gc_root(cell value_,factorvm *vm) : tagged<TYPE>(value_),myvm(vm) { push(); }
|
|
||||||
explicit gc_root(TYPE *value_, factorvm *vm) : tagged<TYPE>(value_),myvm(vm) { push(); }
|
|
||||||
|
|
||||||
const gc_root<TYPE>& operator=(const TYPE *x) { tagged<TYPE>::operator=(x); return *this; }
|
|
||||||
const gc_root<TYPE>& operator=(const cell &x) { tagged<TYPE>::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)
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,9 +49,9 @@
|
||||||
#include "code_block.hpp"
|
#include "code_block.hpp"
|
||||||
#include "data_heap.hpp"
|
#include "data_heap.hpp"
|
||||||
#include "write_barrier.hpp"
|
#include "write_barrier.hpp"
|
||||||
#include "vm.hpp"
|
|
||||||
#include "data_gc.hpp"
|
#include "data_gc.hpp"
|
||||||
#include "local_roots.hpp"
|
#include "local_roots.hpp"
|
||||||
|
#include "vm.hpp"
|
||||||
#include "generic_arrays.hpp"
|
#include "generic_arrays.hpp"
|
||||||
#include "debug.hpp"
|
#include "debug.hpp"
|
||||||
#include "arrays.hpp"
|
#include "arrays.hpp"
|
||||||
|
|
175
vm/vm.hpp
175
vm/vm.hpp
|
@ -678,6 +678,181 @@ inline void allot_barrier(object *address)
|
||||||
return vm->allot_barrier(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<typename TYPE> TYPE *factorvm::allot(cell size)
|
||||||
|
{
|
||||||
|
return (TYPE *)allot_object(header(TYPE::type_number),size);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename TYPE> TYPE *allot(cell size)
|
||||||
|
{
|
||||||
|
return vm->allot<TYPE>(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<object>(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 <typename TYPE>
|
||||||
|
struct gc_root : public tagged<TYPE>
|
||||||
|
{
|
||||||
|
factorvm *myvm;
|
||||||
|
|
||||||
|
void push() { check_tagged_pointer(tagged<TYPE>::value()); myvm->gc_locals.push_back((cell)this); }
|
||||||
|
|
||||||
|
//explicit gc_root(cell value_, factorvm *vm) : myvm(vm),tagged<TYPE>(value_) { push(); }
|
||||||
|
explicit gc_root(cell value_,factorvm *vm) : tagged<TYPE>(value_),myvm(vm) { push(); }
|
||||||
|
explicit gc_root(TYPE *value_, factorvm *vm) : tagged<TYPE>(value_),myvm(vm) { push(); }
|
||||||
|
|
||||||
|
const gc_root<TYPE>& operator=(const TYPE *x) { tagged<TYPE>::operator=(x); return *this; }
|
||||||
|
const gc_root<TYPE>& operator=(const cell &x) { tagged<TYPE>::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:
|
// next method here:
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue