vm: rename gc_root to data_root, add code_root to fix a problem where code blocks would move underneath the PIC compiler if PIC compiler allocated enough

db4
Slava Pestov 2009-11-02 18:10:34 -06:00
parent a3b5c07e80
commit 6c2c87758a
34 changed files with 218 additions and 187 deletions

View File

@ -30,8 +30,8 @@ char *factor_vm::pinned_alien_offset(cell obj)
/* make an alien */
cell factor_vm::allot_alien(cell delegate_, cell displacement)
{
gc_root<object> delegate(delegate_,this);
gc_root<alien> new_alien(allot<alien>(sizeof(alien)),this);
data_root<object> delegate(delegate_,this);
data_root<alien> new_alien(allot<alien>(sizeof(alien)),this);
if(delegate.type_p(ALIEN_TYPE))
{
@ -117,9 +117,9 @@ DEFINE_ALIEN_ACCESSOR(cell,void *,box_alien,pinned_alien_offset)
/* open a native library and push a handle */
void factor_vm::primitive_dlopen()
{
gc_root<byte_array> path(dpop(),this);
data_root<byte_array> path(dpop(),this);
path.untag_check(this);
gc_root<dll> library(allot<dll>(sizeof(dll)),this);
data_root<dll> library(allot<dll>(sizeof(dll)),this);
library->path = path.value();
ffi_dlopen(library.untagged());
dpush(library.value());
@ -128,8 +128,8 @@ void factor_vm::primitive_dlopen()
/* look up a symbol in a native library */
void factor_vm::primitive_dlsym()
{
gc_root<object> library(dpop(),this);
gc_root<byte_array> name(dpop(),this);
data_root<object> library(dpop(),this);
data_root<byte_array> name(dpop(),this);
name.untag_check(this);
symbol_char *sym = name->data<symbol_char>();

View File

@ -6,8 +6,8 @@ namespace factor
/* make a new array with an initial element */
array *factor_vm::allot_array(cell capacity, cell fill_)
{
gc_root<object> fill(fill_,this);
gc_root<array> new_array(allot_uninitialized_array<array>(capacity),this);
data_root<object> fill(fill_,this);
data_root<array> new_array(allot_uninitialized_array<array>(capacity),this);
memset_cell(new_array->data(),fill.value(),capacity * sizeof(cell));
return new_array.untagged();
}
@ -22,17 +22,17 @@ void factor_vm::primitive_array()
cell factor_vm::allot_array_1(cell obj_)
{
gc_root<object> obj(obj_,this);
gc_root<array> a(allot_uninitialized_array<array>(1),this);
data_root<object> obj(obj_,this);
data_root<array> a(allot_uninitialized_array<array>(1),this);
set_array_nth(a.untagged(),0,obj.value());
return a.value();
}
cell factor_vm::allot_array_2(cell v1_, cell v2_)
{
gc_root<object> v1(v1_,this);
gc_root<object> v2(v2_,this);
gc_root<array> a(allot_uninitialized_array<array>(2),this);
data_root<object> v1(v1_,this);
data_root<object> v2(v2_,this);
data_root<array> a(allot_uninitialized_array<array>(2),this);
set_array_nth(a.untagged(),0,v1.value());
set_array_nth(a.untagged(),1,v2.value());
return a.value();
@ -40,11 +40,11 @@ cell factor_vm::allot_array_2(cell v1_, cell v2_)
cell factor_vm::allot_array_4(cell v1_, cell v2_, cell v3_, cell v4_)
{
gc_root<object> v1(v1_,this);
gc_root<object> v2(v2_,this);
gc_root<object> v3(v3_,this);
gc_root<object> v4(v4_,this);
gc_root<array> a(allot_uninitialized_array<array>(4),this);
data_root<object> v1(v1_,this);
data_root<object> v2(v2_,this);
data_root<object> v3(v3_,this);
data_root<object> v4(v4_,this);
data_root<array> a(allot_uninitialized_array<array>(4),this);
set_array_nth(a.untagged(),0,v1.value());
set_array_nth(a.untagged(),1,v2.value());
set_array_nth(a.untagged(),2,v3.value());
@ -62,7 +62,7 @@ void factor_vm::primitive_resize_array()
void growable_array::add(cell elt_)
{
factor_vm *parent = elements.parent;
gc_root<object> elt(elt_,parent);
data_root<object> elt(elt_,parent);
if(count == array_capacity(elements.untagged()))
elements = parent->reallot_array(elements.untagged(),count * 2);
@ -72,7 +72,7 @@ void growable_array::add(cell elt_)
void growable_array::append(array *elts_)
{
factor_vm *parent = elements.parent;
gc_root<array> elts(elts_,parent);
data_root<array> elts(elts_,parent);
cell capacity = array_capacity(elts.untagged());
if(count + capacity > array_capacity(elements.untagged()))
{

View File

@ -23,7 +23,7 @@ inline void factor_vm::set_array_nth(array *array, cell slot, cell value)
struct growable_array {
cell count;
gc_root<array> elements;
data_root<array> elements;
explicit growable_array(factor_vm *parent, cell capacity = 10) :
count(0), elements(parent->allot_array(capacity,false_object),parent) {}

View File

@ -43,7 +43,7 @@ void growable_byte_array::append_bytes(void *elts, cell len)
void growable_byte_array::append_byte_array(cell byte_array_)
{
gc_root<byte_array> byte_array(byte_array_,elements.parent);
data_root<byte_array> byte_array(byte_array_,elements.parent);
cell len = array_capacity(byte_array.untagged());
cell new_size = count + len;

View File

@ -3,7 +3,7 @@ namespace factor
struct growable_byte_array {
cell count;
gc_root<byte_array> elements;
data_root<byte_array> elements;
explicit growable_byte_array(factor_vm *parent,cell capacity = 40) : count(0), elements(parent->allot_byte_array(capacity),parent) { }

View File

@ -130,8 +130,8 @@ struct stack_frame_accumulator {
void operator()(stack_frame *frame)
{
gc_root<object> executing(parent->frame_executing(frame),parent);
gc_root<object> scan(parent->frame_scan(frame),parent);
data_root<object> executing(parent->frame_executing(frame),parent);
data_root<object> scan(parent->frame_scan(frame),parent);
frames.add(executing.value());
frames.add(scan.value());
@ -142,7 +142,7 @@ struct stack_frame_accumulator {
void factor_vm::primitive_callstack_to_array()
{
gc_root<callstack> callstack(dpop(),this);
data_root<callstack> callstack(dpop(),this);
stack_frame_accumulator accum(this);
iterate_callstack_object(callstack.untagged(),accum);
@ -184,8 +184,8 @@ void factor_vm::primitive_innermost_stack_frame_scan()
void factor_vm::primitive_set_innermost_stack_frame_quot()
{
gc_root<callstack> callstack(dpop(),this);
gc_root<quotation> quot(dpop(),this);
data_root<callstack> callstack(dpop(),this);
data_root<quotation> quot(dpop(),this);
callstack.untag_check(this);
quot.untag_check(this);

View File

@ -12,7 +12,7 @@ VM_ASM_API void save_callstack_bottom(stack_frame *callstack_bottom, factor_vm *
keep the callstack in a GC root and use relative offsets */
template<typename Iterator> void factor_vm::iterate_callstack_object(callstack *stack_, Iterator &iterator)
{
gc_root<callstack> stack(stack_,this);
data_root<callstack> stack(stack_,this);
fixnum frame_offset = untag_fixnum(stack->length) - sizeof(stack_frame);
while(frame_offset >= 0)

View File

@ -467,11 +467,11 @@ code_block *factor_vm::allot_code_block(cell size, code_block_type type)
/* Might GC */
code_block *factor_vm::add_code_block(code_block_type type, cell code_, cell labels_, cell owner_, cell relocation_, cell literals_)
{
gc_root<byte_array> code(code_,this);
gc_root<object> labels(labels_,this);
gc_root<object> owner(owner_,this);
gc_root<byte_array> relocation(relocation_,this);
gc_root<array> literals(literals_,this);
data_root<byte_array> code(code_,this);
data_root<object> labels(labels_,this);
data_root<object> owner(owner_,this);
data_root<byte_array> relocation(relocation_,this);
data_root<array> literals(literals_,this);
cell code_length = array_capacity(code.untagged());
code_block *compiled = allot_code_block(code_length,type);

View File

@ -73,8 +73,8 @@ bool factor_vm::in_code_heap_p(cell ptr)
/* Compile a word definition with the non-optimizing compiler. Allocates memory */
void factor_vm::jit_compile_word(cell word_, cell def_, bool relocate)
{
gc_root<word> word(word_,this);
gc_root<quotation> def(def_,this);
data_root<word> word(word_,this);
data_root<quotation> def(def_,this);
jit_compile(def.value(),relocate);
@ -145,7 +145,7 @@ void factor_vm::relocate_code_heap()
void factor_vm::primitive_modify_code_heap()
{
gc_root<array> alist(dpop(),this);
data_root<array> alist(dpop(),this);
cell count = array_capacity(alist.untagged());
@ -155,10 +155,10 @@ void factor_vm::primitive_modify_code_heap()
cell i;
for(i = 0; i < count; i++)
{
gc_root<array> pair(array_nth(alist.untagged(),i),this);
data_root<array> pair(array_nth(alist.untagged(),i),this);
gc_root<word> word(array_nth(pair.untagged(),0),this);
gc_root<object> data(array_nth(pair.untagged(),1),this);
data_root<word> word(array_nth(pair.untagged(),0),this);
data_root<object> data(array_nth(pair.untagged(),1),this);
switch(data.type())
{

View File

@ -139,6 +139,8 @@ void factor_vm::collect_compact_impl(bool trace_contexts_p)
code_forwarder.visit_callback_code_blocks();
}
update_code_roots_for_compaction();
current_gc->event->ended_compaction();
}
@ -182,6 +184,8 @@ void factor_vm::collect_compact_code_impl(bool trace_contexts_p)
code_block_compaction_updater<dummy_slot_forwarder> code_block_updater(this,slot_forwarder);
standard_sizer<code_block> code_block_sizer;
code->allocator->compact(code_block_updater,code_block_sizer);
update_code_roots_for_compaction();
}
}

View File

@ -149,8 +149,8 @@ void factor_vm::primitive_dispatch_stats()
void quotation_jit::emit_mega_cache_lookup(cell methods_, fixnum index, cell cache_)
{
gc_root<array> methods(methods_,parent);
gc_root<array> cache(cache_,parent);
data_root<array> methods(methods_,parent);
data_root<array> cache(cache_,parent);
/* Generate machine code to determine the object's class. */
emit_class_lookup(index,PIC_TUPLE);

View File

@ -37,8 +37,8 @@ void factor_vm::throw_error(cell error, stack_frame *callstack_top)
gc_off = false;
/* Reset local roots */
gc_locals.clear();
gc_bignums.clear();
data_roots.clear();
bignum_roots.clear();
/* If we had an underflow or overflow, stack pointers might be
out of bounds */

View File

@ -9,6 +9,56 @@ full_collector::full_collector(factor_vm *parent_) :
parent_->data->tenured,
full_policy(parent_)) {}
/* After a sweep, invalidate any code heap roots which are not marked,
so that if a block makes a tail call to a generic word, and the PIC
compiler triggers a GC, and the caller block gets gets GCd as a result,
the PIC code won't try to overwrite the call site */
void factor_vm::update_code_roots_for_sweep()
{
std::vector<code_root *>::const_iterator iter = code_roots.begin();
std::vector<code_root *>::const_iterator end = code_roots.end();
mark_bits<code_block> *state = &code->allocator->state;
for(; iter < end; iter++)
{
printf("We have a code root!\n");
code_root *root = *iter;
code_block *block = (code_block *)(root->value & -block_granularity);
if(root->valid && !state->marked_p(block))
root->valid = false;
}
}
/* After a compaction, invalidate any code heap roots which are not
marked as above, and also slide the valid roots up so that call sites
can be updated correctly. */
void factor_vm::update_code_roots_for_compaction()
{
std::vector<code_root *>::const_iterator iter = code_roots.begin();
std::vector<code_root *>::const_iterator end = code_roots.end();
mark_bits<code_block> *state = &code->allocator->state;
for(; iter < end; iter++)
{
printf("We have a code root - compaction!\n");
code_root *root = *iter;
code_block *block = (code_block *)(root->value & -block_granularity);
/* Offset of return address within 16-byte allocation line */
cell offset = root->value - (cell)block;
if(root->valid && state->marked_p((code_block *)root->value))
{
block = state->forward_block(block);
root->value = (cell)block + offset;
}
else
root->valid = false;
}
}
struct code_block_marker {
code_heap *code;
full_collector *collector;
@ -66,6 +116,7 @@ void factor_vm::collect_sweep_impl()
{
current_gc->event->started_data_sweep();
data->tenured->sweep();
update_code_roots_for_sweep();
current_gc->event->ended_data_sweep();
}

View File

@ -249,20 +249,20 @@ void factor_vm::primitive_become()
compile_all_words();
}
void factor_vm::inline_gc(cell *gc_roots_base, cell gc_roots_size)
void factor_vm::inline_gc(cell *data_roots_base, cell data_roots_size)
{
for(cell i = 0; i < gc_roots_size; i++)
gc_locals.push_back((cell)&gc_roots_base[i]);
for(cell i = 0; i < data_roots_size; i++)
data_roots.push_back((cell)&data_roots_base[i]);
primitive_minor_gc();
for(cell i = 0; i < gc_roots_size; i++)
gc_locals.pop_back();
for(cell i = 0; i < data_roots_size; i++)
data_roots.pop_back();
}
VM_C_API void inline_gc(cell *gc_roots_base, cell gc_roots_size, factor_vm *parent)
VM_C_API void inline_gc(cell *data_roots_base, cell data_roots_size, factor_vm *parent)
{
parent->inline_gc(gc_roots_base,gc_roots_size);
parent->inline_gc(data_roots_base,data_roots_size);
}
/*

View File

@ -53,6 +53,6 @@ struct gc_state {
void start_again(gc_op op_, factor_vm *parent);
};
VM_C_API void inline_gc(cell *gc_roots_base, cell gc_roots_size, factor_vm *parent);
VM_C_API void inline_gc(cell *data_roots_base, cell data_roots_size, factor_vm *parent);
}

View File

@ -33,7 +33,7 @@ template<typename Array> bool factor_vm::reallot_array_in_place_p(Array *array,
template<typename Array> Array *factor_vm::reallot_array(Array *array_, cell capacity)
{
gc_root<Array> array(array_,this);
data_root<Array> array(array_,this);
if(reallot_array_in_place_p(array.untagged(),capacity))
{

View File

@ -311,7 +311,7 @@ void factor_vm::primitive_save_image()
/* do a full GC to push everything into tenured space */
primitive_compact_gc();
gc_root<byte_array> path(dpop(),this);
data_root<byte_array> path(dpop(),this);
path.untag_check(this);
save_image((vm_char *)(path.untagged() + 1));
}
@ -321,7 +321,7 @@ void factor_vm::primitive_save_image_and_exit()
/* We unbox this before doing anything else. This is the only point
where we might throw an error, so we have to throw an error here since
later steps destroy the current image. */
gc_root<byte_array> path(dpop(),this);
data_root<byte_array> path(dpop(),this);
path.untag_check(this);
/* strip out special_objects data which is set on startup anyway */

View File

@ -83,9 +83,9 @@ void inline_cache_jit::compile_inline_cache(fixnum index,
cell cache_entries_,
bool tail_call_p)
{
gc_root<word> generic_word(generic_word_,parent);
gc_root<array> methods(methods_,parent);
gc_root<array> cache_entries(cache_entries_,parent);
data_root<word> generic_word(generic_word_,parent);
data_root<array> methods(methods_,parent);
data_root<array> cache_entries(cache_entries_,parent);
cell inline_cache_type = parent->determine_inline_cache_type(cache_entries.untagged());
parent->update_pic_count(inline_cache_type);
@ -118,11 +118,15 @@ void inline_cache_jit::compile_inline_cache(fixnum index,
word_special(parent->special_objects[tail_call_p ? PIC_MISS_TAIL_WORD : PIC_MISS_WORD]);
}
code_block *factor_vm::compile_inline_cache(fixnum index,cell generic_word_,cell methods_,cell cache_entries_,bool tail_call_p)
code_block *factor_vm::compile_inline_cache(fixnum index,
cell generic_word_,
cell methods_,
cell cache_entries_,
bool tail_call_p)
{
gc_root<word> generic_word(generic_word_,this);
gc_root<array> methods(methods_,this);
gc_root<array> cache_entries(cache_entries_,this);
data_root<word> generic_word(generic_word_,this);
data_root<array> methods(methods_,this);
data_root<array> cache_entries(cache_entries_,this);
inline_cache_jit jit(generic_word.value(),this);
jit.compile_inline_cache(index,
@ -149,12 +153,12 @@ cell factor_vm::inline_cache_size(cell cache_entries)
/* Allocates memory */
cell factor_vm::add_inline_cache_entry(cell cache_entries_, cell klass_, cell method_)
{
gc_root<array> cache_entries(cache_entries_,this);
gc_root<object> klass(klass_,this);
gc_root<word> method(method_,this);
data_root<array> cache_entries(cache_entries_,this);
data_root<object> klass(klass_,this);
data_root<word> method(method_,this);
cell pic_size = array_capacity(cache_entries.untagged());
gc_root<array> new_cache_entries(reallot_array(cache_entries.untagged(),pic_size + 2),this);
data_root<array> new_cache_entries(reallot_array(cache_entries.untagged(),pic_size + 2),this);
set_array_nth(new_cache_entries.untagged(),pic_size,klass.value());
set_array_nth(new_cache_entries.untagged(),pic_size + 1,method.value());
return new_cache_entries.value();
@ -170,22 +174,27 @@ void factor_vm::update_pic_transitions(cell pic_size)
ic_to_pic_transitions++;
}
/* The cache_entries parameter is either f (on cold call site) or an array (on cache miss).
Called from assembly with the actual return address */
void *factor_vm::inline_cache_miss(cell return_address)
/* The cache_entries parameter is either f (on cold call site) or an array
(on cache miss). Called from assembly with the actual return address.
Compilation of the inline cache may trigger a GC, which may trigger a compaction;
also, the block containing the return address may now be dead. Use a code_root
to take care of the details. */
void *factor_vm::inline_cache_miss(cell return_address_)
{
check_code_pointer(return_address);
code_root return_address(return_address_,this);
check_code_pointer(return_address.value);
/* Since each PIC is only referenced from a single call site,
if the old call target was a PIC, we can deallocate it immediately,
instead of leaving dead PICs around until the next GC. */
deallocate_inline_cache(return_address);
deallocate_inline_cache(return_address.value);
gc_root<array> cache_entries(dpop(),this);
data_root<array> cache_entries(dpop(),this);
fixnum index = untag_fixnum(dpop());
gc_root<array> methods(dpop(),this);
gc_root<word> generic_word(dpop(),this);
gc_root<object> object(((cell *)ds)[-index],this);
data_root<array> methods(dpop(),this);
data_root<word> generic_word(dpop(),this);
data_root<object> object(((cell *)ds)[-index],this);
void *xt;
@ -200,7 +209,7 @@ void *factor_vm::inline_cache_miss(cell return_address)
cell klass = object_class(object.value());
cell method = lookup_method(object.value(),methods.value());
gc_root<array> new_cache_entries(add_inline_cache_entry(
data_root<array> new_cache_entries(add_inline_cache_entry(
cache_entries.value(),
klass,
method),this);
@ -208,11 +217,13 @@ void *factor_vm::inline_cache_miss(cell return_address)
generic_word.value(),
methods.value(),
new_cache_entries.value(),
tail_call_site_p(return_address))->xt();
tail_call_site_p(return_address.value))->xt();
}
/* Install the new stub. */
set_call_target(return_address,xt);
if(return_address.valid)
{
set_call_target(return_address.value,xt);
#ifdef PIC_DEBUG
std::cout << "Updated "
@ -220,6 +231,7 @@ void *factor_vm::inline_cache_miss(cell return_address)
<< " call site 0x" << std::hex << return_address << std::dec
<< " with " << std::hex << (cell)xt << std::dec;
#endif
}
return xt;
}

View File

@ -33,8 +33,8 @@ void factor_vm::io_error()
void factor_vm::primitive_fopen()
{
gc_root<byte_array> mode(dpop(),this);
gc_root<byte_array> path(dpop(),this);
data_root<byte_array> mode(dpop(),this);
data_root<byte_array> path(dpop(),this);
mode.untag_check(this);
path.untag_check(this);
@ -88,7 +88,7 @@ void factor_vm::primitive_fread()
return;
}
gc_root<byte_array> buf(allot_uninitialized_array<byte_array>(size),this);
data_root<byte_array> buf(allot_uninitialized_array<byte_array>(size),this);
for(;;)
{

View File

@ -24,7 +24,7 @@ jit::jit(code_block_type type_, cell owner_, factor_vm *vm)
void jit::emit_relocation(cell code_template_)
{
gc_root<array> code_template(code_template_,parent);
data_root<array> code_template(code_template_,parent);
cell capacity = array_capacity(code_template.untagged());
for(cell i = 1; i < capacity; i += 3)
{
@ -43,11 +43,11 @@ void jit::emit_relocation(cell code_template_)
/* Allocates memory */
void jit::emit(cell code_template_)
{
gc_root<array> code_template(code_template_,parent);
data_root<array> code_template(code_template_,parent);
emit_relocation(code_template.value());
gc_root<byte_array> insns(array_nth(code_template.untagged(),0),parent);
data_root<byte_array> insns(array_nth(code_template.untagged(),0),parent);
if(computing_offset_p)
{
@ -71,8 +71,8 @@ void jit::emit(cell code_template_)
}
void jit::emit_with(cell code_template_, cell argument_) {
gc_root<array> code_template(code_template_,parent);
gc_root<object> argument(argument_,parent);
data_root<array> code_template(code_template_,parent);
data_root<object> argument(argument_,parent);
literal(argument.value());
emit(code_template.value());
}

View File

@ -3,7 +3,7 @@ namespace factor
struct jit {
code_block_type type;
gc_root<object> owner;
data_root<object> owner;
growable_byte_array code;
growable_byte_array relocation;
growable_array literals;
@ -28,7 +28,7 @@ struct jit {
void word_jump(cell word_)
{
gc_root<word> word(word_,parent);
data_root<word> word(word_,parent);
literal(tag_fixnum(xt_tail_pic_offset));
literal(word.value());
emit(parent->special_objects[JIT_WORD_JUMP]);
@ -46,8 +46,8 @@ struct jit {
void emit_subprimitive(cell word_)
{
gc_root<word> word(word_,parent);
gc_root<array> code_pair(word->subprimitive,parent);
data_root<word> word(word_,parent);
data_root<array> code_pair(word->subprimitive,parent);
literals.append(untag<array>(array_nth(code_pair.untagged(),0)));
emit(array_nth(code_pair.untagged(),1));
}

View File

@ -51,7 +51,7 @@ static const cell data_alignment = 16;
#define TYPE_COUNT 14
#define GC_COLLECTED 5 /* can be anything other than FIXNUM_TYPE */
#define FORWARDING_POINTER 5 /* can be anything other than FIXNUM_TYPE */
enum code_block_type
{
@ -117,7 +117,7 @@ struct header {
bool forwarding_pointer_p() const
{
return TAG(value) == GC_COLLECTED;
return TAG(value) == FORWARDING_POINTER;
}
object *forwarding_pointer() const
@ -127,7 +127,7 @@ struct header {
void forward_to(object *pointer)
{
value = RETAG(pointer,GC_COLLECTED);
value = RETAG(pointer,FORWARDING_POINTER);
}
};
@ -344,8 +344,7 @@ struct dll : public object {
void *dll;
};
struct stack_frame
{
struct stack_frame {
void *xt;
/* Frame size in bytes */
cell size;

View File

@ -1,46 +0,0 @@
namespace factor
{
template<typename Type>
struct gc_root : public tagged<Type>
{
factor_vm *parent;
void push() { parent->gc_locals.push_back((cell)this); }
explicit gc_root(cell value_,factor_vm *vm) : tagged<Type>(value_),parent(vm) { push(); }
explicit gc_root(Type *value_, factor_vm *vm) : tagged<Type>(value_),parent(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(parent->gc_locals.back() == (cell)this);
#endif
parent->gc_locals.pop_back();
}
};
/* A similar hack for the bignum implementation */
struct gc_bignum
{
bignum **addr;
factor_vm *parent;
gc_bignum(bignum **addr_, factor_vm *vm) : addr(addr_), parent(vm) {
if(*addr_)
parent->check_data_pointer(*addr_);
parent->gc_bignums.push_back((cell)addr);
}
~gc_bignum() {
#ifdef FACTOR_DEBUG
assert(parent->gc_bignums.back() == (cell)addr);
#endif
parent->gc_bignums.pop_back();
}
};
#define GC_BIGNUM(x) gc_bignum x##__gc_root(&x,this)
}

View File

@ -74,7 +74,8 @@ namespace factor
#include "vm.hpp"
#include "allot.hpp"
#include "tagged.hpp"
#include "local_roots.hpp"
#include "data_roots.hpp"
#include "code_roots.hpp"
#include "slot_visitor.hpp"
#include "collector.hpp"
#include "copying_collector.hpp"

View File

@ -11,7 +11,7 @@ void factor_vm::init_profiler()
/* Allocates memory */
code_block *factor_vm::compile_profiling_stub(cell word_)
{
gc_root<word> word(word_,this);
data_root<word> word(word_,this);
jit jit(code_block_profiling,word.value(),this);
jit.emit_with(special_objects[JIT_PROFILING],word.value());
@ -31,7 +31,7 @@ void factor_vm::set_profiling(bool profiling)
and allocate profiling blocks if necessary */
primitive_full_gc();
gc_root<array> words(find_all_words(),this);
data_root<array> words(find_all_words(),this);
cell i;
cell length = array_capacity(words.untagged());

View File

@ -110,7 +110,7 @@ bool quotation_jit::trivial_quotation_p(array *elements)
void quotation_jit::emit_quot(cell quot_)
{
gc_root<quotation> quot(quot_,parent);
data_root<quotation> quot(quot_,parent);
array *elements = untag<array>(quot->array);
@ -143,7 +143,7 @@ void quotation_jit::iterate_quotation()
{
set_position(i);
gc_root<object> obj(array_nth(elements.untagged(),i),parent);
data_root<object> obj(array_nth(elements.untagged(),i),parent);
switch(obj.type())
{
@ -290,7 +290,7 @@ void factor_vm::set_quot_xt(quotation *quot, code_block *code)
/* Allocates memory */
void factor_vm::jit_compile(cell quot_, bool relocating)
{
gc_root<quotation> quot(quot_,this);
data_root<quotation> quot(quot_,this);
if(quot->code) return;
quotation_jit compiler(quot.value(),true,relocating,this);
@ -327,13 +327,13 @@ void factor_vm::primitive_quotation_xt()
void factor_vm::compile_all_words()
{
gc_root<array> words(find_all_words(),this);
data_root<array> words(find_all_words(),this);
cell i;
cell length = array_capacity(words.untagged());
for(i = 0; i < length; i++)
{
gc_root<word> word(array_nth(words.untagged(),i),this);
data_root<word> word(array_nth(words.untagged(),i),this);
if(!word->code || !word->code->optimized_p())
jit_compile_word(word.value(),word->def,false);
@ -348,8 +348,8 @@ void factor_vm::compile_all_words()
/* Allocates memory */
fixnum factor_vm::quot_code_offset_to_scan(cell quot_, cell offset)
{
gc_root<quotation> quot(quot_,this);
gc_root<array> array(quot->array,this);
data_root<quotation> quot(quot_,this);
data_root<array> array(quot->array,this);
quotation_jit compiler(quot.value(),false,false,this);
compiler.compute_position(offset);
@ -360,7 +360,7 @@ fixnum factor_vm::quot_code_offset_to_scan(cell quot_, cell offset)
cell factor_vm::lazy_jit_compile_impl(cell quot_, stack_frame *stack)
{
gc_root<quotation> quot(quot_,this);
data_root<quotation> quot(quot_,this);
ctx->callstack_top = stack;
jit_compile(quot.value(),true);
return quot.value();

View File

@ -2,7 +2,7 @@ namespace factor
{
struct quotation_jit : public jit {
gc_root<array> elements;
data_root<array> elements;
bool compiling, relocate;
explicit quotation_jit(cell quot, bool compiling_, bool relocate_, factor_vm *vm)

View File

@ -52,7 +52,7 @@ void factor_vm::primitive_load_locals()
cell factor_vm::clone_object(cell obj_)
{
gc_root<object> obj(obj_,this);
data_root<object> obj(obj_,this);
if(immediate_p(obj.value()))
return obj.value();

View File

@ -42,19 +42,19 @@ template<typename Visitor> struct slot_visitor {
visit_handle(ptr);
}
void visit_registered_locals()
void visit_data_roots()
{
std::vector<cell>::const_iterator iter = parent->gc_locals.begin();
std::vector<cell>::const_iterator end = parent->gc_locals.end();
std::vector<cell>::const_iterator iter = parent->data_roots.begin();
std::vector<cell>::const_iterator end = parent->data_roots.end();
for(; iter < end; iter++)
visit_handle((cell *)(*iter));
}
void visit_registered_bignums()
void visit_bignum_roots()
{
std::vector<cell>::const_iterator iter = parent->gc_bignums.begin();
std::vector<cell>::const_iterator end = parent->gc_bignums.end();
std::vector<cell>::const_iterator iter = parent->bignum_roots.begin();
std::vector<cell>::const_iterator end = parent->bignum_roots.end();
for(; iter < end; iter++)
{
@ -72,8 +72,8 @@ template<typename Visitor> struct slot_visitor {
visit_handle(&parent->bignum_pos_one);
visit_handle(&parent->bignum_neg_one);
visit_registered_locals();
visit_registered_bignums();
visit_data_roots();
visit_bignum_roots();
for(cell i = 0; i < special_object_count; i++)
visit_handle(&parent->special_objects[i]);

View File

@ -29,7 +29,7 @@ void factor_vm::set_string_nth_fast(string *str, cell index, cell ch)
void factor_vm::set_string_nth_slow(string *str_, cell index, cell ch)
{
gc_root<string> str(str_,this);
data_root<string> str(str_,this);
byte_array *aux;
@ -78,7 +78,7 @@ string *factor_vm::allot_string_internal(cell capacity)
/* Allocates memory */
void factor_vm::fill_string(string *str_, cell start, cell capacity, cell fill)
{
gc_root<string> str(str_,this);
data_root<string> str(str_,this);
if(fill <= 0x7f)
memset(&str->data()[start],fill,capacity - start);
@ -94,7 +94,7 @@ void factor_vm::fill_string(string *str_, cell start, cell capacity, cell fill)
/* Allocates memory */
string *factor_vm::allot_string(cell capacity, cell fill)
{
gc_root<string> str(allot_string_internal(capacity),this);
data_root<string> str(allot_string_internal(capacity),this);
fill_string(str.untagged(),0,capacity,fill);
return str.untagged();
}
@ -115,7 +115,7 @@ bool factor_vm::reallot_string_in_place_p(string *str, cell capacity)
string* factor_vm::reallot_string(string *str_, cell capacity)
{
gc_root<string> str(str_,this);
data_root<string> str(str_,this);
if(reallot_string_in_place_p(str.untagged(),capacity))
{
@ -135,7 +135,7 @@ string* factor_vm::reallot_string(string *str_, cell capacity)
if(capacity < to_copy)
to_copy = capacity;
gc_root<string> new_str(allot_string_internal(capacity),this);
data_root<string> new_str(allot_string_internal(capacity),this);
memcpy(new_str->data(),str->data(),to_copy);

View File

@ -16,7 +16,8 @@ struct tagged
{
cell value_;
cell type() const {
cell type() const
{
return TAG(value_);
}
@ -33,20 +34,24 @@ struct tagged
return type_p(Type::type_number);
}
cell value() const {
cell value() const
{
#ifdef FACTOR_DEBUG
assert(type_p());
#endif
return value_;
}
Type *untagged() const {
Type *untagged() const
{
#ifdef FACTOR_DEBUG
assert(type_p());
#endif
return (Type *)(UNTAG(value_));
}
Type *untag_check(factor_vm *parent) const {
Type *untag_check(factor_vm *parent) const
{
if(!type_p())
parent->type_error(Type::type_number,value_);
return untagged();

View File

@ -6,7 +6,7 @@ namespace factor
/* push a new tuple on the stack, filling its slots with f */
void factor_vm::primitive_tuple()
{
gc_root<tuple_layout> layout(dpop(),this);
data_root<tuple_layout> layout(dpop(),this);
tagged<tuple> t(allot<tuple>(tuple_size(layout.untagged())));
t->layout = layout.value();
@ -18,7 +18,7 @@ void factor_vm::primitive_tuple()
/* push a new tuple on the stack, filling its slots from the stack */
void factor_vm::primitive_tuple_boa()
{
gc_root<tuple_layout> layout(dpop(),this);
data_root<tuple_layout> layout(dpop(),this);
tagged<tuple> t(allot<tuple>(tuple_size(layout.untagged())));
t->layout = layout.value();

View File

@ -2,6 +2,7 @@ namespace factor
{
struct growable_array;
struct code_root;
struct factor_vm
{
@ -62,10 +63,12 @@ struct factor_vm
std::vector<gc_event> *gc_events;
/* If a runtime function needs to call another function which potentially
allocates memory, it must wrap any local variable references to Factor
objects in gc_root instances */
std::vector<cell> gc_locals;
std::vector<cell> gc_bignums;
allocates memory, it must wrap any references to the data and code
heaps with data_root and code_root smart pointers, which register
themselves here. See data_roots.hpp and code_roots.hpp */
std::vector<cell> data_roots;
std::vector<cell> bignum_roots;
std::vector<code_root *> code_roots;
/* Debugger */
bool fep_disabled;
@ -255,6 +258,8 @@ struct factor_vm
void collect_nursery();
void collect_aging();
void collect_to_tenured();
void update_code_roots_for_sweep();
void update_code_roots_for_compaction();
void collect_mark_impl(bool trace_contexts_p);
void collect_sweep_impl();
void collect_compact_impl(bool trace_contexts_p);
@ -265,7 +270,7 @@ struct factor_vm
void primitive_full_gc();
void primitive_compact_gc();
void primitive_become();
void inline_gc(cell *gc_roots_base, cell gc_roots_size);
void inline_gc(cell *data_roots_base, cell data_roots_size);
void primitive_enable_gc_events();
void primitive_disable_gc_events();
object *allot_object(header header, cell size);

View File

@ -5,10 +5,10 @@ namespace factor
word *factor_vm::allot_word(cell name_, cell vocab_, cell hashcode_)
{
gc_root<object> vocab(vocab_,this);
gc_root<object> name(name_,this);
data_root<object> vocab(vocab_,this);
data_root<object> name(name_,this);
gc_root<word> new_word(allot<word>(sizeof(word)),this);
data_root<word> new_word(allot<word>(sizeof(word)),this);
new_word->hashcode = hashcode_;
new_word->vocabulary = vocab.value();
@ -43,7 +43,7 @@ void factor_vm::primitive_word()
/* word-xt ( word -- start end ) */
void factor_vm::primitive_word_xt()
{
gc_root<word> w(dpop(),this);
data_root<word> w(dpop(),this);
w.untag_check(this);
if(profiling_p)
@ -61,7 +61,7 @@ void factor_vm::primitive_word_xt()
/* Allocates memory */
void factor_vm::update_word_xt(word *w_)
{
gc_root<word> w(w_,this);
data_root<word> w(w_,this);
if(profiling_p)
{