diff --git a/vm/alien.cpp b/vm/alien.cpp index 4171c99d62..d07b6e353b 100755 --- a/vm/alien.cpp +++ b/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 delegate(delegate_,this); - gc_root new_alien(allot(sizeof(alien)),this); + data_root delegate(delegate_,this); + data_root new_alien(allot(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 path(dpop(),this); + data_root path(dpop(),this); path.untag_check(this); - gc_root library(allot(sizeof(dll)),this); + data_root library(allot(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 library(dpop(),this); - gc_root name(dpop(),this); + data_root library(dpop(),this); + data_root name(dpop(),this); name.untag_check(this); symbol_char *sym = name->data(); diff --git a/vm/arrays.cpp b/vm/arrays.cpp index 3c69368f29..3060ac70a3 100644 --- a/vm/arrays.cpp +++ b/vm/arrays.cpp @@ -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 fill(fill_,this); - gc_root new_array(allot_uninitialized_array(capacity),this); + data_root fill(fill_,this); + data_root new_array(allot_uninitialized_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 obj(obj_,this); - gc_root a(allot_uninitialized_array(1),this); + data_root obj(obj_,this); + data_root a(allot_uninitialized_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 v1(v1_,this); - gc_root v2(v2_,this); - gc_root a(allot_uninitialized_array(2),this); + data_root v1(v1_,this); + data_root v2(v2_,this); + data_root a(allot_uninitialized_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 v1(v1_,this); - gc_root v2(v2_,this); - gc_root v3(v3_,this); - gc_root v4(v4_,this); - gc_root a(allot_uninitialized_array(4),this); + data_root v1(v1_,this); + data_root v2(v2_,this); + data_root v3(v3_,this); + data_root v4(v4_,this); + data_root a(allot_uninitialized_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 elt(elt_,parent); + data_root 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 elts(elts_,parent); + data_root elts(elts_,parent); cell capacity = array_capacity(elts.untagged()); if(count + capacity > array_capacity(elements.untagged())) { diff --git a/vm/arrays.hpp b/vm/arrays.hpp index 6063269e7f..8eb2b530b0 100755 --- a/vm/arrays.hpp +++ b/vm/arrays.hpp @@ -23,7 +23,7 @@ inline void factor_vm::set_array_nth(array *array, cell slot, cell value) struct growable_array { cell count; - gc_root elements; + data_root elements; explicit growable_array(factor_vm *parent, cell capacity = 10) : count(0), elements(parent->allot_array(capacity,false_object),parent) {} diff --git a/vm/byte_arrays.cpp b/vm/byte_arrays.cpp index fa02ede6c3..b317c39f62 100644 --- a/vm/byte_arrays.cpp +++ b/vm/byte_arrays.cpp @@ -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_,elements.parent); + data_root byte_array(byte_array_,elements.parent); cell len = array_capacity(byte_array.untagged()); cell new_size = count + len; diff --git a/vm/byte_arrays.hpp b/vm/byte_arrays.hpp index 0817f7dcdc..a3d6fcf941 100755 --- a/vm/byte_arrays.hpp +++ b/vm/byte_arrays.hpp @@ -3,7 +3,7 @@ namespace factor struct growable_byte_array { cell count; - gc_root elements; + data_root elements; explicit growable_byte_array(factor_vm *parent,cell capacity = 40) : count(0), elements(parent->allot_byte_array(capacity),parent) { } diff --git a/vm/callstack.cpp b/vm/callstack.cpp index 623db8a3fe..85f392af0e 100755 --- a/vm/callstack.cpp +++ b/vm/callstack.cpp @@ -130,8 +130,8 @@ struct stack_frame_accumulator { void operator()(stack_frame *frame) { - gc_root executing(parent->frame_executing(frame),parent); - gc_root scan(parent->frame_scan(frame),parent); + data_root executing(parent->frame_executing(frame),parent); + data_root 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(dpop(),this); + data_root 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(dpop(),this); - gc_root quot(dpop(),this); + data_root callstack(dpop(),this); + data_root quot(dpop(),this); callstack.untag_check(this); quot.untag_check(this); diff --git a/vm/callstack.hpp b/vm/callstack.hpp index 4d44904281..76bf3ecea4 100755 --- a/vm/callstack.hpp +++ b/vm/callstack.hpp @@ -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 void factor_vm::iterate_callstack_object(callstack *stack_, Iterator &iterator) { - gc_root stack(stack_,this); + data_root stack(stack_,this); fixnum frame_offset = untag_fixnum(stack->length) - sizeof(stack_frame); while(frame_offset >= 0) diff --git a/vm/code_block.cpp b/vm/code_block.cpp index d3670af3c0..9869630732 100755 --- a/vm/code_block.cpp +++ b/vm/code_block.cpp @@ -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 code(code_,this); - gc_root labels(labels_,this); - gc_root owner(owner_,this); - gc_root relocation(relocation_,this); - gc_root literals(literals_,this); + data_root code(code_,this); + data_root labels(labels_,this); + data_root owner(owner_,this); + data_root relocation(relocation_,this); + data_root literals(literals_,this); cell code_length = array_capacity(code.untagged()); code_block *compiled = allot_code_block(code_length,type); diff --git a/vm/code_heap.cpp b/vm/code_heap.cpp index f3d36527b5..b4e071d644 100755 --- a/vm/code_heap.cpp +++ b/vm/code_heap.cpp @@ -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_,this); - gc_root def(def_,this); + data_root word(word_,this); + data_root 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 alist(dpop(),this); + data_root 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 pair(array_nth(alist.untagged(),i),this); + data_root pair(array_nth(alist.untagged(),i),this); - gc_root word(array_nth(pair.untagged(),0),this); - gc_root data(array_nth(pair.untagged(),1),this); + data_root word(array_nth(pair.untagged(),0),this); + data_root data(array_nth(pair.untagged(),1),this); switch(data.type()) { diff --git a/vm/compaction.cpp b/vm/compaction.cpp index 86d3efd3d6..10e37db263 100644 --- a/vm/compaction.cpp +++ b/vm/compaction.cpp @@ -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 code_block_updater(this,slot_forwarder); standard_sizer code_block_sizer; code->allocator->compact(code_block_updater,code_block_sizer); + + update_code_roots_for_compaction(); } } diff --git a/vm/dispatch.cpp b/vm/dispatch.cpp index 30c4617cf0..6bef970944 100755 --- a/vm/dispatch.cpp +++ b/vm/dispatch.cpp @@ -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 methods(methods_,parent); - gc_root cache(cache_,parent); + data_root methods(methods_,parent); + data_root cache(cache_,parent); /* Generate machine code to determine the object's class. */ emit_class_lookup(index,PIC_TUPLE); diff --git a/vm/errors.cpp b/vm/errors.cpp index 3161f625cd..2bbe3e5328 100755 --- a/vm/errors.cpp +++ b/vm/errors.cpp @@ -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 */ diff --git a/vm/full_collector.cpp b/vm/full_collector.cpp index 369fc38f09..acce777301 100644 --- a/vm/full_collector.cpp +++ b/vm/full_collector.cpp @@ -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::const_iterator iter = code_roots.begin(); + std::vector::const_iterator end = code_roots.end(); + + mark_bits *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::const_iterator iter = code_roots.begin(); + std::vector::const_iterator end = code_roots.end(); + + mark_bits *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(); } diff --git a/vm/gc.cpp b/vm/gc.cpp index afc1798911..06e9d78ce2 100755 --- a/vm/gc.cpp +++ b/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); } /* diff --git a/vm/gc.hpp b/vm/gc.hpp index 7ad7e71524..a9250eddb2 100755 --- a/vm/gc.hpp +++ b/vm/gc.hpp @@ -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); } diff --git a/vm/generic_arrays.hpp b/vm/generic_arrays.hpp index 89eb56a70d..f45785f9ef 100755 --- a/vm/generic_arrays.hpp +++ b/vm/generic_arrays.hpp @@ -33,7 +33,7 @@ template bool factor_vm::reallot_array_in_place_p(Array *array, template Array *factor_vm::reallot_array(Array *array_, cell capacity) { - gc_root array(array_,this); + data_root array(array_,this); if(reallot_array_in_place_p(array.untagged(),capacity)) { diff --git a/vm/image.cpp b/vm/image.cpp index 0524a145a8..b3a9eae7a5 100755 --- a/vm/image.cpp +++ b/vm/image.cpp @@ -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 path(dpop(),this); + data_root 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 path(dpop(),this); + data_root path(dpop(),this); path.untag_check(this); /* strip out special_objects data which is set on startup anyway */ diff --git a/vm/inline_cache.cpp b/vm/inline_cache.cpp index 3542a92b78..fd5e93560b 100755 --- a/vm/inline_cache.cpp +++ b/vm/inline_cache.cpp @@ -83,9 +83,9 @@ void inline_cache_jit::compile_inline_cache(fixnum index, cell cache_entries_, bool tail_call_p) { - gc_root generic_word(generic_word_,parent); - gc_root methods(methods_,parent); - gc_root cache_entries(cache_entries_,parent); + data_root generic_word(generic_word_,parent); + data_root methods(methods_,parent); + data_root 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 generic_word(generic_word_,this); - gc_root methods(methods_,this); - gc_root cache_entries(cache_entries_,this); + data_root generic_word(generic_word_,this); + data_root methods(methods_,this); + data_root 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 cache_entries(cache_entries_,this); - gc_root klass(klass_,this); - gc_root method(method_,this); + data_root cache_entries(cache_entries_,this); + data_root klass(klass_,this); + data_root method(method_,this); cell pic_size = array_capacity(cache_entries.untagged()); - gc_root new_cache_entries(reallot_array(cache_entries.untagged(),pic_size + 2),this); + data_root 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 cache_entries(dpop(),this); + data_root cache_entries(dpop(),this); fixnum index = untag_fixnum(dpop()); - gc_root methods(dpop(),this); - gc_root generic_word(dpop(),this); - gc_root object(((cell *)ds)[-index],this); + data_root methods(dpop(),this); + data_root generic_word(dpop(),this); + data_root 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 new_cache_entries(add_inline_cache_entry( + data_root new_cache_entries(add_inline_cache_entry( cache_entries.value(), klass, method),this); @@ -208,18 +217,21 @@ 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 " - << (tail_call_site_p(return_address) ? "tail" : "non-tail") - << " call site 0x" << std::hex << return_address << std::dec - << " with " << std::hex << (cell)xt << std::dec; + std::cout << "Updated " + << (tail_call_site_p(return_address) ? "tail" : "non-tail") + << " call site 0x" << std::hex << return_address << std::dec + << " with " << std::hex << (cell)xt << std::dec; #endif + } return xt; } diff --git a/vm/io.cpp b/vm/io.cpp index bbcac0b849..a8f9cb6897 100755 --- a/vm/io.cpp +++ b/vm/io.cpp @@ -33,8 +33,8 @@ void factor_vm::io_error() void factor_vm::primitive_fopen() { - gc_root mode(dpop(),this); - gc_root path(dpop(),this); + data_root mode(dpop(),this); + data_root path(dpop(),this); mode.untag_check(this); path.untag_check(this); @@ -88,7 +88,7 @@ void factor_vm::primitive_fread() return; } - gc_root buf(allot_uninitialized_array(size),this); + data_root buf(allot_uninitialized_array(size),this); for(;;) { diff --git a/vm/jit.cpp b/vm/jit.cpp index 2fa948e4d6..e72e88bfdf 100644 --- a/vm/jit.cpp +++ b/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 code_template(code_template_,parent); + data_root 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 code_template(code_template_,parent); + data_root code_template(code_template_,parent); emit_relocation(code_template.value()); - gc_root insns(array_nth(code_template.untagged(),0),parent); + data_root 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 code_template(code_template_,parent); - gc_root argument(argument_,parent); + data_root code_template(code_template_,parent); + data_root argument(argument_,parent); literal(argument.value()); emit(code_template.value()); } diff --git a/vm/jit.hpp b/vm/jit.hpp index 9feade4cc1..b5a2457d57 100644 --- a/vm/jit.hpp +++ b/vm/jit.hpp @@ -3,7 +3,7 @@ namespace factor struct jit { code_block_type type; - gc_root owner; + data_root 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_,parent); + data_root 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_,parent); - gc_root code_pair(word->subprimitive,parent); + data_root word(word_,parent); + data_root code_pair(word->subprimitive,parent); literals.append(untag(array_nth(code_pair.untagged(),0))); emit(array_nth(code_pair.untagged(),1)); } diff --git a/vm/layouts.hpp b/vm/layouts.hpp index 2e4a90cc0e..6b96ade8f5 100644 --- a/vm/layouts.hpp +++ b/vm/layouts.hpp @@ -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; diff --git a/vm/local_roots.hpp b/vm/local_roots.hpp deleted file mode 100644 index 442a91f350..0000000000 --- a/vm/local_roots.hpp +++ /dev/null @@ -1,46 +0,0 @@ -namespace factor -{ - -template -struct gc_root : public tagged -{ - factor_vm *parent; - - void push() { parent->gc_locals.push_back((cell)this); } - - explicit gc_root(cell value_,factor_vm *vm) : tagged(value_),parent(vm) { push(); } - explicit gc_root(Type *value_, factor_vm *vm) : tagged(value_),parent(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(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) - -} diff --git a/vm/master.hpp b/vm/master.hpp index 0f8276cf66..0654e63bcb 100755 --- a/vm/master.hpp +++ b/vm/master.hpp @@ -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" diff --git a/vm/profiler.cpp b/vm/profiler.cpp index 2f5fc6fcf4..50e88cc57a 100755 --- a/vm/profiler.cpp +++ b/vm/profiler.cpp @@ -11,7 +11,7 @@ void factor_vm::init_profiler() /* Allocates memory */ code_block *factor_vm::compile_profiling_stub(cell word_) { - gc_root word(word_,this); + data_root 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 words(find_all_words(),this); + data_root words(find_all_words(),this); cell i; cell length = array_capacity(words.untagged()); diff --git a/vm/quotations.cpp b/vm/quotations.cpp index 17b7c4328b..2c5e401ad9 100755 --- a/vm/quotations.cpp +++ b/vm/quotations.cpp @@ -110,7 +110,7 @@ bool quotation_jit::trivial_quotation_p(array *elements) void quotation_jit::emit_quot(cell quot_) { - gc_root quot(quot_,parent); + data_root quot(quot_,parent); array *elements = untag(quot->array); @@ -143,7 +143,7 @@ void quotation_jit::iterate_quotation() { set_position(i); - gc_root obj(array_nth(elements.untagged(),i),parent); + data_root 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 quot(quot_,this); + data_root 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 words(find_all_words(),this); + data_root words(find_all_words(),this); cell i; cell length = array_capacity(words.untagged()); for(i = 0; i < length; i++) { - gc_root word(array_nth(words.untagged(),i),this); + data_root 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 quot(quot_,this); - gc_root array(quot->array,this); + data_root quot(quot_,this); + data_root 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 quot(quot_,this); + data_root quot(quot_,this); ctx->callstack_top = stack; jit_compile(quot.value(),true); return quot.value(); diff --git a/vm/quotations.hpp b/vm/quotations.hpp index e6e6afcd0b..6d04d80de3 100755 --- a/vm/quotations.hpp +++ b/vm/quotations.hpp @@ -2,7 +2,7 @@ namespace factor { struct quotation_jit : public jit { - gc_root elements; + data_root elements; bool compiling, relocate; explicit quotation_jit(cell quot, bool compiling_, bool relocate_, factor_vm *vm) diff --git a/vm/run.cpp b/vm/run.cpp index b6e3324502..6d3e9f7374 100755 --- a/vm/run.cpp +++ b/vm/run.cpp @@ -52,7 +52,7 @@ void factor_vm::primitive_load_locals() cell factor_vm::clone_object(cell obj_) { - gc_root obj(obj_,this); + data_root obj(obj_,this); if(immediate_p(obj.value())) return obj.value(); diff --git a/vm/slot_visitor.hpp b/vm/slot_visitor.hpp index 38d0081c0a..e777347622 100644 --- a/vm/slot_visitor.hpp +++ b/vm/slot_visitor.hpp @@ -42,19 +42,19 @@ template struct slot_visitor { visit_handle(ptr); } - void visit_registered_locals() + void visit_data_roots() { - std::vector::const_iterator iter = parent->gc_locals.begin(); - std::vector::const_iterator end = parent->gc_locals.end(); + std::vector::const_iterator iter = parent->data_roots.begin(); + std::vector::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::const_iterator iter = parent->gc_bignums.begin(); - std::vector::const_iterator end = parent->gc_bignums.end(); + std::vector::const_iterator iter = parent->bignum_roots.begin(); + std::vector::const_iterator end = parent->bignum_roots.end(); for(; iter < end; iter++) { @@ -72,8 +72,8 @@ template 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]); diff --git a/vm/strings.cpp b/vm/strings.cpp index 3022611319..9e135e6779 100644 --- a/vm/strings.cpp +++ b/vm/strings.cpp @@ -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 str(str_,this); + data_root 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 str(str_,this); + data_root 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 str(allot_string_internal(capacity),this); + data_root 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 str(str_,this); + data_root 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 new_str(allot_string_internal(capacity),this); + data_root new_str(allot_string_internal(capacity),this); memcpy(new_str->data(),str->data(),to_copy); diff --git a/vm/tagged.hpp b/vm/tagged.hpp index 77cb6e5287..e520e326fa 100755 --- a/vm/tagged.hpp +++ b/vm/tagged.hpp @@ -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(); diff --git a/vm/tuples.cpp b/vm/tuples.cpp index 8c759b4884..eaac437753 100755 --- a/vm/tuples.cpp +++ b/vm/tuples.cpp @@ -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 layout(dpop(),this); + data_root layout(dpop(),this); tagged t(allot(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 layout(dpop(),this); + data_root layout(dpop(),this); tagged t(allot(tuple_size(layout.untagged()))); t->layout = layout.value(); diff --git a/vm/vm.hpp b/vm/vm.hpp index d58ce37742..0789590c49 100755 --- a/vm/vm.hpp +++ b/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_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 gc_locals; - std::vector 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 data_roots; + std::vector bignum_roots; + std::vector 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); diff --git a/vm/words.cpp b/vm/words.cpp index 4248c14b7d..c375ec2174 100644 --- a/vm/words.cpp +++ b/vm/words.cpp @@ -5,10 +5,10 @@ namespace factor word *factor_vm::allot_word(cell name_, cell vocab_, cell hashcode_) { - gc_root vocab(vocab_,this); - gc_root name(name_,this); + data_root vocab(vocab_,this); + data_root name(name_,this); - gc_root new_word(allot(sizeof(word)),this); + data_root new_word(allot(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 w(dpop(),this); + data_root 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 w(w_,this); + data_root w(w_,this); if(profiling_p) {