diff --git a/vm/code_heap.cpp b/vm/code_heap.cpp index 6cb952cd36..f07639d9bb 100755 --- a/vm/code_heap.cpp +++ b/vm/code_heap.cpp @@ -3,12 +3,12 @@ namespace factor { -code_heap::code_heap(factor_vm *myvm, cell size) : heap(myvm,size) {} +code_heap::code_heap(bool secure_gc, cell size) : heap(secure_gc,size) {} void code_heap::write_barrier(code_block *compiled) { - remembered_set[compiled] = myvm->data->nursery(); - youngest_referenced_generation = myvm->data->nursery(); + remembered_set[compiled] = nursery_gen; + youngest_referenced_generation = nursery_gen; } bool code_heap::needs_fixup_p(code_block *compiled) @@ -26,7 +26,7 @@ void code_heap::code_heap_free(code_block *compiled) /* Allocate a code heap during startup */ void factor_vm::init_code_heap(cell size) { - code = new code_heap(this,size); + code = new code_heap(secure_gc,size); } bool factor_vm::in_code_heap_p(cell ptr) @@ -228,7 +228,7 @@ critical here */ void factor_vm::compact_code_heap() { /* Free all unreachable code blocks, don't trace contexts */ - garbage_collection(data->tenured(),false,false,0); + garbage_collection(tenured_gen,false,false,0); /* Figure out where the code heap blocks are going to end up */ cell size = code->compute_heap_forwarding(); diff --git a/vm/code_heap.hpp b/vm/code_heap.hpp index 1ac72e8218..feea7da307 100755 --- a/vm/code_heap.hpp +++ b/vm/code_heap.hpp @@ -13,7 +13,7 @@ struct code_heap : heap { /* Minimum value in the above map. */ cell youngest_referenced_generation; - explicit code_heap(factor_vm *myvm, cell size); + explicit code_heap(bool secure_gc, cell size); void write_barrier(code_block *compiled); bool needs_fixup_p(code_block *compiled); void code_heap_free(code_block *compiled); diff --git a/vm/contexts.cpp b/vm/contexts.cpp index 2b7a55d491..78dc2ccd3f 100644 --- a/vm/contexts.cpp +++ b/vm/contexts.cpp @@ -44,8 +44,8 @@ context *factor_vm::alloc_context() else { new_context = new context; - new_context->datastack_region = new segment(this,ds_size); - new_context->retainstack_region = new segment(this,rs_size); + new_context->datastack_region = new segment(ds_size); + new_context->retainstack_region = new segment(rs_size); } return new_context; diff --git a/vm/data_gc.cpp b/vm/data_gc.cpp index 1b12bddaf3..0fa5e1b07f 100755 --- a/vm/data_gc.cpp +++ b/vm/data_gc.cpp @@ -5,7 +5,7 @@ namespace factor void factor_vm::init_data_gc() { - code->youngest_referenced_generation = data->nursery(); + code->youngest_referenced_generation = nursery_gen; } gc_state::gc_state(data_heap *data_, bool growing_data_heap_, cell collecting_gen_) : @@ -71,7 +71,7 @@ template object *factor_vm::promote_object(object *untagged, object *newpointer = strategy.allot(size); if(!newpointer) longjmp(current_gc->gc_unwind,1); - gc_stats *s = &stats[current_gc->collecting_gen]; + generation_stats *s = &stats.generations[current_gc->collecting_gen]; s->object_count++; s->bytes_copied += size; @@ -91,7 +91,7 @@ template void factor_vm::trace_card(card *ptr, cell gen, cell strategy.copy_reachable_objects(card_scan,&card_end); - cards_scanned++; + stats.cards_scanned++; } template void factor_vm::trace_card_deck(card_deck *deck, cell gen, card mask, card unmask, Strategy &strategy) @@ -122,7 +122,7 @@ template void factor_vm::trace_card_deck(card_deck *deck, cel } } - decks_scanned++; + stats.decks_scanned++; } /* Trace all objects referenced from marked cards */ @@ -142,11 +142,11 @@ template void factor_vm::trace_generation_cards(cell gen, Str /* after the collection, no old->nursery pointers remain anywhere, but old->aging pointers might remain in tenured space */ - if(gen == data->tenured()) + if(gen == tenured_gen) unmask = card_points_to_nursery; /* after the collection, all cards in aging space can be cleared */ - else if(gen == data->aging()) + else if(gen == aging_gen) unmask = card_mark_mask; else { @@ -201,7 +201,7 @@ template void factor_vm::trace_cards(Strategy &strategy) for(i = current_gc->collecting_gen + 1; i < gen_count; i++) trace_generation_cards(i,strategy); - card_scan_time += (current_micros() - start); + stats.card_scan_time += (current_micros() - start); } /* Copy all tagged pointers in a range of memory */ @@ -353,7 +353,7 @@ template void factor_vm::trace_code_heap_roots(Strategy &stra trace_literal_references(iter->first,strategy); } - code_heap_scans++; + stats.code_heap_scans++; } } @@ -385,7 +385,7 @@ void factor_vm::free_unmarked_code_blocks() literal_and_word_reference_updater updater(this); code->free_unmarked(updater); code->remembered_set.clear(); - code->youngest_referenced_generation = data->tenured(); + code->youngest_referenced_generation = tenured_gen; } void factor_vm::update_dirty_code_blocks() @@ -429,7 +429,11 @@ template Strategy ©ing_collector::strategy() template object *copying_collector::allot(cell size) { if(newspace->here + size <= newspace->end) - return myvm->allot_zone(newspace,size); + { + object *obj = newspace->allot(size); + myvm->allot_barrier(obj); + return obj; + } else return NULL; } @@ -478,7 +482,7 @@ struct aging_collector : copying_collector explicit aging_collector(factor_vm *myvm_, zone *newspace_) : copying_collector(myvm_,newspace_), - tenured(&myvm->data->generations[myvm->data->tenured()]) {} + tenured(&myvm->data->generations[tenured_gen]) {} bool should_copy_p(object *untagged) { @@ -532,7 +536,7 @@ struct tenured_collector : copying_collector void factor_vm::collect_nursery() { - nursery_collector collector(this,&data->generations[data->aging()]); + nursery_collector collector(this,&data->generations[aging_gen]); trace_roots(collector); trace_contexts(collector); @@ -546,10 +550,10 @@ void factor_vm::collect_nursery() void factor_vm::collect_aging() { - std::swap(data->generations[data->aging()],data->semispaces[data->aging()]); - reset_generation(data->aging()); + std::swap(data->generations[aging_gen],data->semispaces[aging_gen]); + reset_generation(aging_gen); - aging_collector collector(this,&data->generations[data->aging()]); + aging_collector collector(this,&data->generations[aging_gen]); trace_roots(collector); trace_contexts(collector); @@ -563,7 +567,7 @@ void factor_vm::collect_aging() void factor_vm::collect_aging_again() { - aging_again_collector collector(this,&data->generations[data->tenured()]); + aging_again_collector collector(this,&data->generations[tenured_gen]); trace_roots(collector); trace_contexts(collector); @@ -572,7 +576,7 @@ void factor_vm::collect_aging_again() collector.go(); update_dirty_code_blocks(); - reset_generation(data->aging()); + reset_generation(aging_gen); nursery.here = nursery.start; } @@ -585,18 +589,18 @@ void factor_vm::collect_tenured(cell requested_bytes, bool trace_contexts_) } else { - std::swap(data->generations[data->tenured()],data->semispaces[data->tenured()]); - reset_generation(data->tenured()); + std::swap(data->generations[tenured_gen],data->semispaces[tenured_gen]); + reset_generation(tenured_gen); } - tenured_collector collector(this,&data->generations[data->tenured()]); + tenured_collector collector(this,&data->generations[tenured_gen]); trace_roots(collector); if(trace_contexts_) trace_contexts(collector); collector.go(); free_unmarked_code_blocks(); - reset_generation(data->aging()); + reset_generation(aging_gen); nursery.here = nursery.start; if(current_gc->growing_data_heap) @@ -605,7 +609,7 @@ void factor_vm::collect_tenured(cell requested_bytes, bool trace_contexts_) void factor_vm::record_gc_stats() { - gc_stats *s = &stats[current_gc->collecting_gen]; + generation_stats *s = &stats.generations[current_gc->collecting_gen]; cell gc_elapsed = (current_micros() - current_gc->start_time); s->collections++; @@ -673,7 +677,7 @@ void factor_vm::garbage_collection(cell collecting_gen_, bool growing_data_heap_ void factor_vm::gc() { - garbage_collection(data->tenured(),false,true,0); + garbage_collection(tenured_gen,false,true,0); } void factor_vm::primitive_gc() @@ -690,7 +694,7 @@ void factor_vm::primitive_gc_stats() for(i = 0; i < gen_count; i++) { - gc_stats *s = &stats[i]; + generation_stats *s = &stats.generations[i]; result.add(allot_cell(s->collections)); result.add(tag(long_long_to_bignum(s->gc_time))); result.add(tag(long_long_to_bignum(s->max_gc_time))); @@ -702,10 +706,10 @@ void factor_vm::primitive_gc_stats() } result.add(tag(ulong_long_to_bignum(total_gc_time))); - result.add(tag(ulong_long_to_bignum(cards_scanned))); - result.add(tag(ulong_long_to_bignum(decks_scanned))); - result.add(tag(ulong_long_to_bignum(card_scan_time))); - result.add(allot_cell(code_heap_scans)); + result.add(tag(ulong_long_to_bignum(stats.cards_scanned))); + result.add(tag(ulong_long_to_bignum(stats.decks_scanned))); + result.add(tag(ulong_long_to_bignum(stats.card_scan_time))); + result.add(allot_cell(stats.code_heap_scans)); result.trim(); dpush(result.elements.value()); @@ -713,13 +717,7 @@ void factor_vm::primitive_gc_stats() void factor_vm::clear_gc_stats() { - for(cell i = 0; i < gen_count; i++) - memset(&stats[i],0,sizeof(gc_stats)); - - cards_scanned = 0; - decks_scanned = 0; - card_scan_time = 0; - code_heap_scans = 0; + memset(&stats,0,sizeof(gc_stats)); } void factor_vm::primitive_clear_gc_stats() @@ -763,7 +761,7 @@ void factor_vm::inline_gc(cell *gc_roots_base, cell gc_roots_size) for(cell i = 0; i < gc_roots_size; i++) gc_locals.push_back((cell)&gc_roots_base[i]); - garbage_collection(data->nursery(),false,true,0); + garbage_collection(nursery_gen,false,true,0); for(cell i = 0; i < gc_roots_size; i++) gc_locals.pop_back(); @@ -775,15 +773,6 @@ VM_C_API void inline_gc(cell *gc_roots_base, cell gc_roots_size, factor_vm *myvm VM_PTR->inline_gc(gc_roots_base,gc_roots_size); } -inline object *factor_vm::allot_zone(zone *z, cell a) -{ - cell h = z->here; - z->here = h + align8(a); - object *obj = (object *)h; - allot_barrier(obj); - return obj; -} - /* * It is up to the caller to fill in the object's fields in a meaningful * fashion! @@ -801,33 +790,32 @@ object *factor_vm::allot_object(header header, cell size) { /* If there is insufficient room, collect the nursery */ if(nursery.here + size > nursery.end) - garbage_collection(data->nursery(),false,true,0); + garbage_collection(nursery_gen,false,true,0); - cell h = nursery.here; - nursery.here = h + align8(size); - obj = (object *)h; + obj = nursery.allot(size); } /* If the object is bigger than the nursery, allocate it in tenured space */ else { - zone *tenured = &data->generations[data->tenured()]; + zone *tenured = &data->generations[tenured_gen]; /* If tenured space does not have enough room, collect */ if(tenured->here + size > tenured->end) { gc(); - tenured = &data->generations[data->tenured()]; + tenured = &data->generations[tenured_gen]; } /* If it still won't fit, grow the heap */ if(tenured->here + size > tenured->end) { - garbage_collection(data->tenured(),true,true,size); - tenured = &data->generations[data->tenured()]; + garbage_collection(tenured_gen,true,true,size); + tenured = &data->generations[tenured_gen]; } - obj = allot_zone(tenured,size); + obj = tenured->allot(size); + allot_barrier(obj); /* Allows initialization code to store old->new pointers without hitting the write barrier in the common case of diff --git a/vm/data_gc.hpp b/vm/data_gc.hpp index c8b7b479c2..04a9682ae5 100755 --- a/vm/data_gc.hpp +++ b/vm/data_gc.hpp @@ -2,7 +2,7 @@ namespace factor { /* statistics */ -struct gc_stats { +struct generation_stats { cell collections; u64 gc_time; u64 max_gc_time; @@ -10,6 +10,14 @@ struct gc_stats { u64 bytes_copied; }; +struct gc_stats { + generation_stats generations[gen_count]; + u64 cards_scanned; + u64 decks_scanned; + u64 card_scan_time; + cell code_heap_scans; +}; + struct gc_state { /* The data heap we're collecting */ data_heap *data; @@ -35,17 +43,17 @@ struct gc_state { inline bool collecting_nursery_p() { - return collecting_gen == data->nursery(); + return collecting_gen == nursery_gen; } inline bool collecting_aging_p() { - return collecting_gen == data->aging(); + return collecting_gen == aging_gen; } inline bool collecting_tenured_p() { - return collecting_gen == data->tenured(); + return collecting_gen == tenured_gen; } inline bool collecting_accumulation_gen_p() diff --git a/vm/data_heap.cpp b/vm/data_heap.cpp index d5cfbb449d..5ccde31f37 100755 --- a/vm/data_heap.cpp +++ b/vm/data_heap.cpp @@ -25,7 +25,7 @@ data_heap::data_heap(factor_vm *myvm, cell young_size_, cell aging_size_, cell t total_size += deck_size; - seg = new segment(myvm,total_size); + seg = new segment(total_size); generations = new zone[gen_count]; semispaces = new zone[gen_count]; @@ -43,17 +43,17 @@ data_heap::data_heap(factor_vm *myvm, cell young_size_, cell aging_size_, cell t cell alloter = align(seg->start,deck_size); - alloter = generations[tenured()].init_zone(tenured_size,alloter); - alloter = semispaces[tenured()].init_zone(tenured_size,alloter); + alloter = generations[tenured_gen].init_zone(tenured_size,alloter); + alloter = semispaces[tenured_gen].init_zone(tenured_size,alloter); - alloter = generations[aging()].init_zone(aging_size,alloter); - alloter = semispaces[aging()].init_zone(aging_size,alloter); + alloter = generations[aging_gen].init_zone(aging_size,alloter); + alloter = semispaces[aging_gen].init_zone(aging_size,alloter); - alloter = generations[nursery()].init_zone(young_size,alloter); - alloter = semispaces[nursery()].init_zone(0,alloter); + alloter = generations[nursery_gen].init_zone(young_size,alloter); + alloter = semispaces[nursery_gen].init_zone(0,alloter); if(seg->end - alloter > deck_size) - myvm->critical_error("Bug in alloc_data_heap",alloter); + critical_error("Bug in alloc_data_heap",alloter); } data_heap *factor_vm::grow_data_heap(data_heap *data, cell requested_bytes) @@ -103,7 +103,7 @@ void factor_vm::clear_allot_markers(cell gen) their allocation pointers and cards reset. */ void factor_vm::reset_generation(cell gen) { - assert(gen != data->nursery()); + assert(gen != nursery_gen); zone *z = &data->generations[gen]; z->here = z->start; @@ -117,11 +117,11 @@ void factor_vm::reset_generation(cell gen) void factor_vm::set_data_heap(data_heap *data_) { data = data_; - nursery = data->generations[data->nursery()]; + nursery = data->generations[nursery_gen]; nursery.here = nursery.start; init_card_decks(); - reset_generation(data->aging()); - reset_generation(data->tenured()); + reset_generation(aging_gen); + reset_generation(tenured_gen); } void factor_vm::init_data_heap(cell young_size, cell aging_size, cell tenured_size, bool secure_gc_) @@ -234,7 +234,7 @@ void factor_vm::primitive_data_room() cell gen; for(gen = 0; gen < gen_count; gen++) { - zone *z = (gen == data->nursery() ? &nursery : &data->generations[gen]); + zone *z = (gen == nursery_gen ? &nursery : &data->generations[gen]); a.add(tag_fixnum((z->end - z->here) >> 10)); a.add(tag_fixnum((z->size) >> 10)); } @@ -246,7 +246,7 @@ void factor_vm::primitive_data_room() /* Disables GC and activates next-object ( -- obj ) primitive */ void factor_vm::begin_scan() { - heap_scan_ptr = data->generations[data->tenured()].start; + heap_scan_ptr = data->generations[tenured_gen].start; gc_off = true; } @@ -265,7 +265,7 @@ cell factor_vm::next_object() if(!gc_off) general_error(ERROR_HEAP_SCAN,F,F,NULL); - if(heap_scan_ptr >= data->generations[data->tenured()].here) + if(heap_scan_ptr >= data->generations[tenured_gen].here) return F; object *obj = (object *)heap_scan_ptr; diff --git a/vm/data_heap.hpp b/vm/data_heap.hpp index c4e8fe0d7b..cd53d66768 100755 --- a/vm/data_heap.hpp +++ b/vm/data_heap.hpp @@ -9,7 +9,7 @@ struct zone { cell here; cell size; cell end; - + cell init_zone(cell size_, cell start_) { size = size_; @@ -17,11 +17,18 @@ struct zone { end = start_ + size_; return end; } - + inline bool contains_p(object *pointer) { return ((cell)pointer - start) < size; } + + inline object *allot(cell size) + { + cell h = here; + here = h + align8(size); + return (object *)h; + } }; struct data_heap { @@ -43,19 +50,13 @@ struct data_heap { char *decks; char *decks_end; - /* the 0th generation is where new objects are allocated. */ - cell nursery() { return 0; } - - /* where objects hang around */ - cell aging() { return 1; } - - /* the oldest generation */ - cell tenured() { return 2; } - explicit data_heap(factor_vm *myvm, cell young_size, cell aging_size, cell tenured_size); ~data_heap(); }; +static const cell nursery_gen = 0; +static const cell aging_gen = 1; +static const cell tenured_gen = 2; static const cell gen_count = 3; } diff --git a/vm/errors.cpp b/vm/errors.cpp index 2435ac1c33..fc79603e67 100755 --- a/vm/errors.cpp +++ b/vm/errors.cpp @@ -3,26 +3,26 @@ namespace factor { -void factor_vm::out_of_memory() -{ - print_string("Out of memory\n\n"); - dump_generations(); - exit(1); -} - -void fatal_error(const char* msg, cell tagged) +void fatal_error(const char *msg, cell tagged) { print_string("fatal_error: "); print_string(msg); print_string(": "); print_cell_hex(tagged); nl(); exit(1); } -void factor_vm::critical_error(const char* msg, cell tagged) +void critical_error(const char *msg, cell tagged) { print_string("You have triggered a bug in Factor. Please report.\n"); print_string("critical_error: "); print_string(msg); print_string(": "); print_cell_hex(tagged); nl(); - factorbug(); + SIGNAL_VM_PTR()->factorbug(); +} + +void out_of_memory() +{ + print_string("Out of memory\n\n"); + SIGNAL_VM_PTR()->dump_generations(); + exit(1); } void factor_vm::throw_error(cell error, stack_frame *callstack_top) diff --git a/vm/errors.hpp b/vm/errors.hpp index b837381005..c1ea2e1907 100755 --- a/vm/errors.hpp +++ b/vm/errors.hpp @@ -23,7 +23,9 @@ enum vm_error_type ERROR_FP_TRAP, }; -void fatal_error(const char* msg, cell tagged); +void fatal_error(const char *msg, cell tagged); +void critical_error(const char *msg, cell tagged); +void out_of_memory(); void memory_signal_handler_impl(); void fp_signal_handler_impl(); void misc_signal_handler_impl(); diff --git a/vm/heap.cpp b/vm/heap.cpp index 0f2f2fda1f..8c2d7d9ef5 100644 --- a/vm/heap.cpp +++ b/vm/heap.cpp @@ -11,10 +11,9 @@ void heap::clear_free_list() memset(&free,0,sizeof(heap_free_list)); } -heap::heap(factor_vm *myvm_, cell size) +heap::heap(bool secure_gc_, cell size) : secure_gc(secure_gc_) { - myvm = myvm_; - seg = new segment(myvm,align_page(size)); + seg = new segment(align_page(size)); if(!seg) fatal_error("Out of memory in new_heap",size); clear_free_list(); } @@ -85,7 +84,7 @@ void heap::build_free_list(cell size) void heap::assert_free_block(free_heap_block *block) { if(block->type() != FREE_BLOCK_TYPE) - myvm->critical_error("Invalid block in free list",(cell)block); + critical_error("Invalid block in free list",(cell)block); } free_heap_block *heap::find_free_block(cell size) @@ -263,7 +262,7 @@ void heap::compact_heap() heap_block *heap::free_allocated(heap_block *prev, heap_block *scan) { - if(myvm->secure_gc) + if(secure_gc) memset(scan + 1,0,scan->size() - sizeof(heap_block)); if(prev && prev->type() == FREE_BLOCK_TYPE) diff --git a/vm/heap.hpp b/vm/heap.hpp index 07ed6bc291..52d3f98ba5 100644 --- a/vm/heap.hpp +++ b/vm/heap.hpp @@ -10,12 +10,12 @@ struct heap_free_list { }; struct heap { - factor_vm *myvm; + bool secure_gc; segment *seg; heap_free_list free; unordered_map forwarding; - explicit heap(factor_vm *myvm, cell size); + explicit heap(bool secure_gc_, cell size); inline heap_block *next_block(heap_block *block) { diff --git a/vm/image.cpp b/vm/image.cpp index 90afaa82f2..5af8790506 100755 --- a/vm/image.cpp +++ b/vm/image.cpp @@ -28,7 +28,7 @@ void factor_vm::load_data_heap(FILE *file, image_header *h, vm_parameters *p) clear_gc_stats(); - zone *tenured = &data->generations[data->tenured()]; + zone *tenured = &data->generations[tenured_gen]; fixnum bytes_read = fread((void*)tenured->start,1,h->data_size,file); @@ -85,7 +85,7 @@ bool factor_vm::save_image(const vm_char *filename) return false; } - zone *tenured = &data->generations[data->tenured()]; + zone *tenured = &data->generations[tenured_gen]; h.magic = image_magic; h.version = image_version; @@ -156,7 +156,7 @@ void factor_vm::data_fixup(cell *cell) if(immediate_p(*cell)) return; - zone *tenured = &data->generations[data->tenured()]; + zone *tenured = &data->generations[tenured_gen]; *cell += (tenured->start - data_relocation_base); } @@ -280,7 +280,7 @@ void factor_vm::relocate_data() data_fixup(&bignum_pos_one); data_fixup(&bignum_neg_one); - zone *tenured = &data->generations[data->tenured()]; + zone *tenured = &data->generations[tenured_gen]; for(relocating = tenured->start; relocating < tenured->here; diff --git a/vm/os-unix.cpp b/vm/os-unix.cpp index d17dedf299..e792483e0d 100644 --- a/vm/os-unix.cpp +++ b/vm/os-unix.cpp @@ -83,9 +83,8 @@ void factor_vm::primitive_existsp() box_boolean(stat(path,&sb) >= 0); } -segment::segment(factor_vm *myvm_, cell size_) +segment::segment(cell size_) { - myvm = myvm_; size = size_; int pagesize = getpagesize(); @@ -94,8 +93,7 @@ segment::segment(factor_vm *myvm_, cell size_) PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANON | MAP_PRIVATE,-1,0); - if(array == (char*)-1) - myvm->out_of_memory(); + if(array == (char*)-1) out_of_memory(); if(mprotect(array,pagesize,PROT_NONE) == -1) fatal_error("Cannot protect low guard page",(cell)array); diff --git a/vm/os-windows.cpp b/vm/os-windows.cpp index 0dfaecab69..48ddeffcb6 100755 --- a/vm/os-windows.cpp +++ b/vm/os-windows.cpp @@ -96,9 +96,8 @@ void factor_vm::primitive_existsp() box_boolean(windows_stat(path)); } -segment::segment(factor_vm *myvm_, cell size_) +segment::segment(cell size_) { - myvm = myvm_; size = size_; char *mem; @@ -106,7 +105,7 @@ segment::segment(factor_vm *myvm_, cell size_) if((mem = (char *)VirtualAlloc(NULL, getpagesize() * 2 + size, MEM_COMMIT, PAGE_EXECUTE_READWRITE)) == 0) - myvm->out_of_memory(); + out_of_memory(); if (!VirtualProtect(mem, getpagesize(), PAGE_NOACCESS, &ignore)) fatal_error("Cannot allocate low guard page", (cell)mem); diff --git a/vm/segments.hpp b/vm/segments.hpp index 6b2e6c69d4..6ff2170974 100644 --- a/vm/segments.hpp +++ b/vm/segments.hpp @@ -9,12 +9,11 @@ inline cell align_page(cell a) /* segments set up guard pages to check for under/overflow. size must be a multiple of the page size */ struct segment { - factor_vm *myvm; cell start; cell size; cell end; - explicit segment(factor_vm *myvm, cell size); + explicit segment(cell size); ~segment(); }; diff --git a/vm/vm.hpp b/vm/vm.hpp index 2ddb991b29..772f8bcfdb 100755 --- a/vm/vm.hpp +++ b/vm/vm.hpp @@ -4,16 +4,97 @@ namespace factor struct factor_vm { // First five fields accessed directly by assembler. See vm.factor + + /* Current stacks */ context *stack_chain; - zone nursery; /* new objects are allocated here */ + + /* New objects are allocated here */ + zone nursery; + + /* Add this to a shifted address to compute write barrier offsets */ cell cards_offset; cell decks_offset; - cell userenv[USER_ENV]; /* TAGGED user environment data; see getenv/setenv prims */ - // contexts + /* TAGGED user environment data; see getenv/setenv prims */ + cell userenv[USER_ENV]; + + /* Data stack and retain stack sizes */ cell ds_size, rs_size; + + /* Pooling unused contexts to make callbacks cheaper */ context *unused_contexts; + /* Canonical T object. It's just a word */ + cell T; + + /* Is call counting enabled? */ + bool profiling_p; + + /* Global variables used to pass fault handler state from signal handler to + user-space */ + cell signal_number; + cell signal_fault_addr; + unsigned int signal_fpu_status; + stack_frame *signal_callstack_top; + + /* Zeroes out deallocated memory; set by the -securegc command line argument */ + bool secure_gc; + + /* A heap walk allows useful things to be done, like finding all + references to an object for debugging purposes. */ + cell heap_scan_ptr; + + /* GC is off during heap walking */ + bool gc_off; + + /* Data heap */ + data_heap *data; + + /* Where we store object start offsets in cards */ + cell allot_markers_offset; + + /* Only set if we're performing a GC */ + gc_state *current_gc; + + /* Statistics */ + gc_stats stats; + + /* Code heap */ + code_heap *code; + + /* 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; + + /* Debugger */ + bool fep_disabled; + bool full_output; + + /* Canonical bignums */ + cell bignum_zero; + cell bignum_pos_one; + cell bignum_neg_one; + + /* Only used during image loading */ + cell code_relocation_base; + cell data_relocation_base; + + /* Method dispatch statistics */ + cell megamorphic_cache_hits; + cell megamorphic_cache_misses; + + cell cold_call_to_ic_transitions; + cell ic_to_pic_transitions; + cell pic_to_mega_transitions; + /* Indexed by PIC_TAG, PIC_HI_TAG, PIC_TUPLE, PIC_HI_TAG_TUPLE */ + cell pic_counts[4]; + + /* Number of entries in a polymorphic inline cache */ + cell max_pic_size; + + // contexts void reset_datastack(); void reset_retainstack(); void fix_stacks(); @@ -32,9 +113,6 @@ struct factor_vm void primitive_check_datastack(); // run - /* Canonical T object. It's just a word */ - cell T; - void primitive_getenv(); void primitive_setenv(); void primitive_exit(); @@ -46,23 +124,12 @@ struct factor_vm void primitive_clone(); // profiler - bool profiling_p; - void init_profiler(); code_block *compile_profiling_stub(cell word_); void set_profiling(bool profiling); void primitive_profiling(); // errors - /* Global variables used to pass fault handler state from signal handler to - user-space */ - cell signal_number; - cell signal_fault_addr; - unsigned int signal_fpu_status; - stack_frame *signal_callstack_top; - - void out_of_memory(); - void critical_error(const char* msg, cell tagged); void throw_error(cell error, stack_frame *callstack_top); void not_implemented_error(); bool in_page(cell fault, cell area, cell area_size, int offset); @@ -142,13 +209,6 @@ struct factor_vm bignum *digit_stream_to_bignum(unsigned int n_digits, unsigned int (*producer)(unsigned int, factor_vm *), unsigned int radix, int negative_p); //data_heap - bool secure_gc; /* Set by the -securegc command line argument */ - bool gc_off; /* GC is off during heap walking */ - data_heap *data; - /* A heap walk allows useful things to be done, like finding all - references to an object for debugging purposes. */ - cell heap_scan_ptr; - void init_card_decks(); data_heap *grow_data_heap(data_heap *data, cell requested_bytes); void clear_cards(cell gen); @@ -173,8 +233,6 @@ struct factor_vm cell object_size(cell tagged); //write barrier - cell allot_markers_offset; - inline card *addr_to_card(cell a) { return (card*)(((cell)(a) >> card_bits) + cards_offset); @@ -227,15 +285,6 @@ struct factor_vm } // data_gc - /* used during garbage collection only */ - gc_state *current_gc; - /* statistics */ - gc_stats stats[gen_count]; - u64 cards_scanned; - u64 decks_scanned; - u64 card_scan_time; - cell code_heap_scans; - void init_data_gc(); template object *resolve_forwarding(object *untagged, Strategy &strategy); template void trace_handle(cell *handle, Strategy &strategy); @@ -269,7 +318,6 @@ struct factor_vm void clear_gc_stats(); void primitive_become(); void inline_gc(cell *gc_roots_base, cell gc_roots_size); - inline object *allot_zone(zone *z, cell a); object *allot_object(header header, cell size); void primitive_clear_gc_stats(); @@ -301,22 +349,12 @@ struct factor_vm #endif } - // local roots - /* 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; - // generic arrays template Array *allot_array_internal(cell capacity); template bool reallot_array_in_place_p(Array *array, cell capacity); template Array *reallot_array(Array *array_, cell capacity); //debug - bool fep_disabled; - bool full_output; - void print_chars(string* str); void print_word(word* word, cell nesting); void print_factor_string(string* str); @@ -389,10 +427,6 @@ struct factor_vm void primitive_wrapper(); //math - cell bignum_zero; - cell bignum_pos_one; - cell bignum_neg_one; - void primitive_bignum_to_fixnum(); void primitive_float_to_fixnum(); void primitive_fixnum_divint(); @@ -519,8 +553,6 @@ struct factor_vm code_block *add_code_block(cell type, cell code_, cell labels_, cell owner_, cell relocation_, cell literals_); //code_heap - code_heap *code; - inline void check_code_pointer(cell ptr) { #ifdef FACTOR_DEBUG @@ -554,9 +586,6 @@ struct factor_vm } //image - cell code_relocation_base; - cell data_relocation_base; - void init_objects(image_header *h); void load_data_heap(FILE *file, image_header *h, vm_parameters *p); void load_code_heap(FILE *file, image_header *h, vm_parameters *p); @@ -646,9 +675,6 @@ struct factor_vm void primitive_quot_compiled_p(); //dispatch - cell megamorphic_cache_hits; - cell megamorphic_cache_misses; - cell search_lookup_alist(cell table, cell klass); cell search_lookup_hash(cell table, cell klass, cell hashcode); cell nth_superclass(tuple_layout *layout, fixnum echelon); @@ -666,12 +692,6 @@ struct factor_vm void primitive_dispatch_stats(); //inline cache - cell max_pic_size; - cell cold_call_to_ic_transitions; - cell ic_to_pic_transitions; - cell pic_to_mega_transitions; - cell pic_counts[4]; /* PIC_TAG, PIC_HI_TAG, PIC_TUPLE, PIC_HI_TAG_TUPLE */ - void init_inline_caching(int max_size); void deallocate_inline_cache(cell return_address); cell determine_inline_cache_type(array *cache_entries);