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
parent
a3b5c07e80
commit
6c2c87758a
12
vm/alien.cpp
12
vm/alien.cpp
|
@ -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>();
|
||||
|
|
|
@ -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()))
|
||||
{
|
||||
|
|
|
@ -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) {}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) { }
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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())
|
||||
{
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
14
vm/gc.cpp
14
vm/gc.cpp
|
@ -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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -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);
|
||||
|
||||
}
|
||||
|
|
|
@ -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))
|
||||
{
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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(;;)
|
||||
{
|
||||
|
|
10
vm/jit.cpp
10
vm/jit.cpp
|
@ -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());
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
||||
}
|
|
@ -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"
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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]);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
15
vm/vm.hpp
15
vm/vm.hpp
|
@ -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);
|
||||
|
|
10
vm/words.cpp
10
vm/words.cpp
|
@ -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)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue