From 6d5197923c3b0cd1593a29e4d719878038b5f759 Mon Sep 17 00:00:00 2001 From: Erik Charlebois Date: Sat, 11 May 2013 22:28:42 -0400 Subject: [PATCH] VM: Refactor slot_visitor.hpp to Factor style --- vm/slot_visitor.hpp | 619 +++++++++++++++++++++----------------------- 1 file changed, 288 insertions(+), 331 deletions(-) diff --git a/vm/slot_visitor.hpp b/vm/slot_visitor.hpp index 88a12e0991..033a332d8c 100644 --- a/vm/slot_visitor.hpp +++ b/vm/slot_visitor.hpp @@ -1,103 +1,97 @@ -namespace factor -{ +namespace factor { /* Size of the object pointed to by an untagged pointer */ -template -cell object::size(Fixup fixup) const -{ - if(free_p()) return ((free_heap_block *)this)->size(); - - switch(type()) - { - case ARRAY_TYPE: - return align(array_size((array*)this),data_alignment); - case BIGNUM_TYPE: - return align(array_size((bignum*)this),data_alignment); - case BYTE_ARRAY_TYPE: - return align(array_size((byte_array*)this),data_alignment); - case STRING_TYPE: - return align(string_size(string_capacity((string*)this)),data_alignment); - case TUPLE_TYPE: - { - tuple_layout *layout = (tuple_layout *)fixup.translate_data(untag(((tuple *)this)->layout)); - return align(tuple_size(layout),data_alignment); - } - case QUOTATION_TYPE: - return align(sizeof(quotation),data_alignment); - case WORD_TYPE: - return align(sizeof(word),data_alignment); - case FLOAT_TYPE: - return align(sizeof(boxed_float),data_alignment); - case DLL_TYPE: - return align(sizeof(dll),data_alignment); - case ALIEN_TYPE: - return align(sizeof(alien),data_alignment); - case WRAPPER_TYPE: - return align(sizeof(wrapper),data_alignment); - case CALLSTACK_TYPE: - return align(callstack_object_size(untag_fixnum(((callstack *)this)->length)),data_alignment); - default: - critical_error("Invalid header in size",(cell)this); - return 0; /* can't happen */ - } +template cell object::size(Fixup fixup) const { + if (free_p()) + return ((free_heap_block*)this)->size(); + + switch (type()) { + case ARRAY_TYPE: + return align(array_size((array*)this), data_alignment); + case BIGNUM_TYPE: + return align(array_size((bignum*)this), data_alignment); + case BYTE_ARRAY_TYPE: + return align(array_size((byte_array*)this), data_alignment); + case STRING_TYPE: + return align(string_size(string_capacity((string*)this)), data_alignment); + case TUPLE_TYPE: { + tuple_layout* layout = (tuple_layout*)fixup.translate_data( + untag(((tuple*)this)->layout)); + return align(tuple_size(layout), data_alignment); + } + case QUOTATION_TYPE: + return align(sizeof(quotation), data_alignment); + case WORD_TYPE: + return align(sizeof(word), data_alignment); + case FLOAT_TYPE: + return align(sizeof(boxed_float), data_alignment); + case DLL_TYPE: + return align(sizeof(dll), data_alignment); + case ALIEN_TYPE: + return align(sizeof(alien), data_alignment); + case WRAPPER_TYPE: + return align(sizeof(wrapper), data_alignment); + case CALLSTACK_TYPE: + return align( + callstack_object_size(untag_fixnum(((callstack*)this)->length)), + data_alignment); + default: + critical_error("Invalid header in size", (cell) this); + return 0; /* can't happen */ + } } -inline cell object::size() const -{ - return size(no_fixup()); -} +inline cell object::size() const { return size(no_fixup()); } /* The number of cells from the start of the object which should be scanned by the GC. Some types have a binary payload at the end (string, word, DLL) which we ignore. */ -template -cell object::binary_payload_start(Fixup fixup) const -{ - if(free_p()) return 0; - - switch(type()) - { - /* these objects do not refer to other objects at all */ - case FLOAT_TYPE: - case BYTE_ARRAY_TYPE: - case BIGNUM_TYPE: - case CALLSTACK_TYPE: - return 0; - /* these objects have some binary data at the end */ - case WORD_TYPE: - return sizeof(word) - sizeof(cell); - case ALIEN_TYPE: - return sizeof(cell) * 3; - case DLL_TYPE: - return sizeof(cell) * 2; - case QUOTATION_TYPE: - return sizeof(quotation) - sizeof(cell); - case STRING_TYPE: - return sizeof(string); - /* everything else consists entirely of pointers */ - case ARRAY_TYPE: - return array_size(array_capacity((array*)this)); - case TUPLE_TYPE: - { - tuple_layout *layout = (tuple_layout *)fixup.translate_data(untag(((tuple *)this)->layout)); - return tuple_size(layout); - } - case WRAPPER_TYPE: - return sizeof(wrapper); - default: - critical_error("Invalid header in binary_payload_start",(cell)this); - return 0; /* can't happen */ - } +template cell object::binary_payload_start(Fixup fixup) const { + if (free_p()) + return 0; + + switch (type()) { + /* these objects do not refer to other objects at all */ + case FLOAT_TYPE: + case BYTE_ARRAY_TYPE: + case BIGNUM_TYPE: + case CALLSTACK_TYPE: + return 0; + /* these objects have some binary data at the end */ + case WORD_TYPE: + return sizeof(word) - sizeof(cell); + case ALIEN_TYPE: + return sizeof(cell) * 3; + case DLL_TYPE: + return sizeof(cell) * 2; + case QUOTATION_TYPE: + return sizeof(quotation) - sizeof(cell); + case STRING_TYPE: + return sizeof(string); + /* everything else consists entirely of pointers */ + case ARRAY_TYPE: + return array_size(array_capacity((array*)this)); + case TUPLE_TYPE: { + tuple_layout* layout = (tuple_layout*)fixup.translate_data( + untag(((tuple*)this)->layout)); + return tuple_size(layout); + } + case WRAPPER_TYPE: + return sizeof(wrapper); + default: + critical_error("Invalid header in binary_payload_start", (cell) this); + return 0; /* can't happen */ + } } -inline cell object::binary_payload_start() const -{ - return binary_payload_start(no_fixup()); +inline cell object::binary_payload_start() const { + return binary_payload_start(no_fixup()); } /* Slot visitors iterate over the slots of an object, applying a functor to each one that is a non-immediate slot. The pointer is untagged first. The -functor returns a new untagged object pointer. The return value may or may not equal the old one, +functor returns a new untagged object pointer. The return value may or may not +equal the old one, however the new pointer receives the same tag before being stored back to the original location. @@ -111,320 +105,283 @@ Iteration is driven by visit_*() methods. Some of them define GC roots: - visit_roots() - visit_contexts() */ -template struct slot_visitor { - factor_vm *parent; - Fixup fixup; - - explicit slot_visitor(factor_vm *parent_, Fixup fixup_) : - parent(parent_), fixup(fixup_) {} - - cell visit_pointer(cell pointer); - void visit_handle(cell *handle); - void visit_object_array(cell *start, cell *end); - void visit_slots(object *ptr, cell payload_start); - void visit_slots(object *ptr); - void visit_stack_elements(segment *region, cell *top); - void visit_data_roots(); - void visit_bignum_roots(); - void visit_callback_roots(); - void visit_literal_table_roots(); - void visit_roots(); - void visit_callstack_object(callstack *stack); - void visit_callstack(context *ctx); - void visit_contexts(); - void visit_code_block_objects(code_block *compiled); - void visit_embedded_literals(code_block *compiled); - void visit_sample_callstacks(); - void visit_sample_threads(); +template struct slot_visitor { + factor_vm* parent; + Fixup fixup; + + explicit slot_visitor(factor_vm* parent_, Fixup fixup_) + : parent(parent_), fixup(fixup_) {} + + cell visit_pointer(cell pointer); + void visit_handle(cell* handle); + void visit_object_array(cell* start, cell* end); + void visit_slots(object* ptr, cell payload_start); + void visit_slots(object* ptr); + void visit_stack_elements(segment* region, cell* top); + void visit_data_roots(); + void visit_bignum_roots(); + void visit_callback_roots(); + void visit_literal_table_roots(); + void visit_roots(); + void visit_callstack_object(callstack* stack); + void visit_callstack(context* ctx); + void visit_contexts(); + void visit_code_block_objects(code_block* compiled); + void visit_embedded_literals(code_block* compiled); + void visit_sample_callstacks(); + void visit_sample_threads(); }; -template -cell slot_visitor::visit_pointer(cell pointer) -{ - if(immediate_p(pointer)) return pointer; +template +cell slot_visitor::visit_pointer(cell pointer) { + if (immediate_p(pointer)) + return pointer; - object *untagged = fixup.fixup_data(untag(pointer)); - return RETAG(untagged,TAG(pointer)); + object* untagged = fixup.fixup_data(untag(pointer)); + return RETAG(untagged, TAG(pointer)); } -template -void slot_visitor::visit_handle(cell *handle) -{ - *handle = visit_pointer(*handle); +template void slot_visitor::visit_handle(cell* handle) { + *handle = visit_pointer(*handle); } -template -void slot_visitor::visit_object_array(cell *start, cell *end) -{ - while(start < end) visit_handle(start++); +template +void slot_visitor::visit_object_array(cell* start, cell* end) { + while (start < end) + visit_handle(start++); } -template -void slot_visitor::visit_slots(object *ptr, cell payload_start) -{ - cell *slot = (cell *)ptr; - cell *end = (cell *)((cell)ptr + payload_start); - - if(slot != end) - { - slot++; - visit_object_array(slot,end); - } +template +void slot_visitor::visit_slots(object* ptr, cell payload_start) { + cell* slot = (cell*)ptr; + cell* end = (cell*)((cell) ptr + payload_start); + + if (slot != end) { + slot++; + visit_object_array(slot, end); + } } -template -void slot_visitor::visit_slots(object *obj) -{ - if(obj->type() == CALLSTACK_TYPE) - visit_callstack_object((callstack *)obj); - else - visit_slots(obj,obj->binary_payload_start(fixup)); +template void slot_visitor::visit_slots(object* obj) { + if (obj->type() == CALLSTACK_TYPE) + visit_callstack_object((callstack*)obj); + else + visit_slots(obj, obj->binary_payload_start(fixup)); } -template -void slot_visitor::visit_stack_elements(segment *region, cell *top) -{ - visit_object_array((cell *)region->start,top + 1); +template +void slot_visitor::visit_stack_elements(segment* region, cell* top) { + visit_object_array((cell*)region->start, top + 1); } -template -void slot_visitor::visit_data_roots() -{ - std::vector::const_iterator iter = parent->data_roots.begin(); - std::vector::const_iterator end = parent->data_roots.end(); +template void slot_visitor::visit_data_roots() { + std::vector::const_iterator iter = + parent->data_roots.begin(); + std::vector::const_iterator end = parent->data_roots.end(); - for(; iter < end; iter++) - visit_object_array(iter->start,iter->start + iter->len); + for (; iter < end; iter++) + visit_object_array(iter->start, iter->start + iter->len); } -template -void slot_visitor::visit_bignum_roots() -{ - std::vector::const_iterator iter = parent->bignum_roots.begin(); - std::vector::const_iterator end = parent->bignum_roots.end(); +template void slot_visitor::visit_bignum_roots() { + std::vector::const_iterator iter = parent->bignum_roots.begin(); + std::vector::const_iterator end = parent->bignum_roots.end(); - for(; iter < end; iter++) - { - cell *handle = (cell *)(*iter); + for (; iter < end; iter++) { + cell* handle = (cell*)(*iter); - if(*handle) - *handle = (cell)fixup.fixup_data(*(object **)handle); - } + if (*handle) + *handle = (cell) fixup.fixup_data(*(object**)handle); + } } -template -struct callback_slot_visitor { - callback_heap *callbacks; - slot_visitor *visitor; +template struct callback_slot_visitor { + callback_heap* callbacks; + slot_visitor* visitor; - explicit callback_slot_visitor(callback_heap *callbacks_, slot_visitor *visitor_) : - callbacks(callbacks_), visitor(visitor_) {} + explicit callback_slot_visitor(callback_heap* callbacks_, + slot_visitor* visitor_) + : callbacks(callbacks_), visitor(visitor_) {} - void operator()(code_block *stub) - { - visitor->visit_handle(&stub->owner); - } + void operator()(code_block* stub) { visitor->visit_handle(&stub->owner); } }; -template -void slot_visitor::visit_callback_roots() -{ - callback_slot_visitor callback_visitor(parent->callbacks,this); - parent->callbacks->each_callback(callback_visitor); +template void slot_visitor::visit_callback_roots() { + callback_slot_visitor callback_visitor(parent->callbacks, this); + parent->callbacks->each_callback(callback_visitor); } -template -void slot_visitor::visit_literal_table_roots() -{ - std::map *uninitialized_blocks = &parent->code->uninitialized_blocks; - std::map::const_iterator iter = uninitialized_blocks->begin(); - std::map::const_iterator end = uninitialized_blocks->end(); - - std::map new_uninitialized_blocks; - for(; iter != end; iter++) - { - new_uninitialized_blocks.insert(std::make_pair( - iter->first, - visit_pointer(iter->second))); - } - - parent->code->uninitialized_blocks = new_uninitialized_blocks; +template +void slot_visitor::visit_literal_table_roots() { + std::map* uninitialized_blocks = + &parent->code->uninitialized_blocks; + std::map::const_iterator iter = + uninitialized_blocks->begin(); + std::map::const_iterator end = uninitialized_blocks->end(); + + std::map new_uninitialized_blocks; + for (; iter != end; iter++) { + new_uninitialized_blocks.insert( + std::make_pair(iter->first, visit_pointer(iter->second))); + } + + parent->code->uninitialized_blocks = new_uninitialized_blocks; } -template -void slot_visitor::visit_sample_callstacks() -{ - for (std::vector::iterator iter = parent->sample_callstacks.begin(); - iter != parent->sample_callstacks.end(); - ++iter) - { - visit_handle(&*iter); - } +template void slot_visitor::visit_sample_callstacks() { + for (std::vector::iterator iter = parent->sample_callstacks.begin(); + iter != parent->sample_callstacks.end(); ++iter) { + visit_handle(&*iter); + } } -template -void slot_visitor::visit_sample_threads() -{ - for (std::vector::iterator iter = parent->samples.begin(); - iter != parent->samples.end(); - ++iter) - { - visit_handle(&iter->thread); - } +template void slot_visitor::visit_sample_threads() { + for (std::vector::iterator iter = parent->samples.begin(); + iter != parent->samples.end(); ++iter) { + visit_handle(&iter->thread); + } } -template -void slot_visitor::visit_roots() -{ - visit_handle(&parent->true_object); - visit_handle(&parent->bignum_zero); - visit_handle(&parent->bignum_pos_one); - visit_handle(&parent->bignum_neg_one); - - visit_data_roots(); - visit_bignum_roots(); - visit_callback_roots(); - visit_literal_table_roots(); - visit_sample_callstacks(); - visit_sample_threads(); - - visit_object_array(parent->special_objects,parent->special_objects + special_object_count); +template void slot_visitor::visit_roots() { + visit_handle(&parent->true_object); + visit_handle(&parent->bignum_zero); + visit_handle(&parent->bignum_pos_one); + visit_handle(&parent->bignum_neg_one); + + visit_data_roots(); + visit_bignum_roots(); + visit_callback_roots(); + visit_literal_table_roots(); + visit_sample_callstacks(); + visit_sample_threads(); + + visit_object_array(parent->special_objects, + parent->special_objects + special_object_count); } -template -struct call_frame_slot_visitor { - factor_vm *parent; - slot_visitor *visitor; +template struct call_frame_slot_visitor { + factor_vm* parent; + slot_visitor* visitor; - explicit call_frame_slot_visitor(factor_vm *parent_, slot_visitor *visitor_) : - parent(parent_), visitor(visitor_) {} + explicit call_frame_slot_visitor(factor_vm* parent_, + slot_visitor* visitor_) + : parent(parent_), visitor(visitor_) {} - /* + /* frame top -> [return address] [spill area] ... [entry_point] [size] */ - void operator()(void *frame_top, cell frame_size, code_block *owner, void *addr) - { - cell return_address = owner->offset(addr); + void operator()(void* frame_top, cell frame_size, code_block* owner, + void* addr) { + cell return_address = owner->offset(addr); - code_block *compiled = Fixup::translated_code_block_map - ? owner - : visitor->fixup.translate_code(owner); - gc_info *info = compiled->block_gc_info(); + code_block* compiled = + Fixup::translated_code_block_map ? owner + : visitor->fixup.translate_code(owner); + gc_info* info = compiled->block_gc_info(); - FACTOR_ASSERT(return_address < compiled->size()); - cell callsite = info->return_address_index(return_address); - if(callsite == (cell)-1) - return; + FACTOR_ASSERT(return_address < compiled->size()); + cell callsite = info->return_address_index(return_address); + if (callsite == (cell) - 1) + return; #ifdef DEBUG_GC_MAPS - std::cout << "call frame code block " << compiled << " with offset " << return_address << std::endl; + std::cout << "call frame code block " << compiled << " with offset " + << return_address << std::endl; #endif - cell *stack_pointer = (cell *)frame_top; - u8 *bitmap = info->gc_info_bitmap(); - - /* Subtract old value of base pointer from every derived pointer. */ - for(cell spill_slot = 0; spill_slot < info->derived_root_count; spill_slot++) - { - u32 base_pointer = info->lookup_base_pointer(callsite, spill_slot); - if(base_pointer != (u32)-1) - { + cell* stack_pointer = (cell*)frame_top; + u8* bitmap = info->gc_info_bitmap(); + + /* Subtract old value of base pointer from every derived pointer. */ + for (cell spill_slot = 0; spill_slot < info->derived_root_count; + spill_slot++) { + u32 base_pointer = info->lookup_base_pointer(callsite, spill_slot); + if (base_pointer != (u32) - 1) { #ifdef DEBUG_GC_MAPS - std::cout << "visiting derived root " << spill_slot - << " with base pointer " << base_pointer - << std::endl; + std::cout << "visiting derived root " << spill_slot + << " with base pointer " << base_pointer << std::endl; #endif - stack_pointer[spill_slot] -= stack_pointer[base_pointer]; - } - } + stack_pointer[spill_slot] -= stack_pointer[base_pointer]; + } + } - /* Update all GC roots, including base pointers. */ - cell callsite_gc_roots = info->callsite_gc_roots(callsite); + /* Update all GC roots, including base pointers. */ + cell callsite_gc_roots = info->callsite_gc_roots(callsite); - for(cell spill_slot = 0; spill_slot < info->gc_root_count; spill_slot++) - { - if(bitmap_p(bitmap,callsite_gc_roots + spill_slot)) - { + for (cell spill_slot = 0; spill_slot < info->gc_root_count; spill_slot++) { + if (bitmap_p(bitmap, callsite_gc_roots + spill_slot)) { #ifdef DEBUG_GC_MAPS - std::cout << "visiting GC root " << spill_slot << std::endl; + std::cout << "visiting GC root " << spill_slot << std::endl; #endif - visitor->visit_handle(stack_pointer + spill_slot); - } - } - - /* Add the base pointers to obtain new derived pointer values. */ - for(cell spill_slot = 0; spill_slot < info->derived_root_count; spill_slot++) - { - u32 base_pointer = info->lookup_base_pointer(callsite, spill_slot); - if(base_pointer != (u32)-1) - stack_pointer[spill_slot] += stack_pointer[base_pointer]; - } - } + visitor->visit_handle(stack_pointer + spill_slot); + } + } + + /* Add the base pointers to obtain new derived pointer values. */ + for (cell spill_slot = 0; spill_slot < info->derived_root_count; + spill_slot++) { + u32 base_pointer = info->lookup_base_pointer(callsite, spill_slot); + if (base_pointer != (u32) - 1) + stack_pointer[spill_slot] += stack_pointer[base_pointer]; + } + } }; -template -void slot_visitor::visit_callstack_object(callstack *stack) -{ - call_frame_slot_visitor call_frame_visitor(parent,this); - parent->iterate_callstack_object(stack,call_frame_visitor,fixup); +template +void slot_visitor::visit_callstack_object(callstack* stack) { + call_frame_slot_visitor call_frame_visitor(parent, this); + parent->iterate_callstack_object(stack, call_frame_visitor, fixup); } -template -void slot_visitor::visit_callstack(context *ctx) -{ - call_frame_slot_visitor call_frame_visitor(parent,this); - parent->iterate_callstack(ctx,call_frame_visitor,fixup); +template +void slot_visitor::visit_callstack(context* ctx) { + call_frame_slot_visitor call_frame_visitor(parent, this); + parent->iterate_callstack(ctx, call_frame_visitor, fixup); } -template -void slot_visitor::visit_contexts() -{ - std::set::const_iterator begin = parent->active_contexts.begin(); - std::set::const_iterator end = parent->active_contexts.end(); - while(begin != end) - { - context *ctx = *begin; - - visit_stack_elements(ctx->datastack_seg,(cell *)ctx->datastack); - visit_stack_elements(ctx->retainstack_seg,(cell *)ctx->retainstack); - visit_object_array(ctx->context_objects,ctx->context_objects + context_object_count); - visit_callstack(ctx); - begin++; - } +template void slot_visitor::visit_contexts() { + std::set::const_iterator begin = parent->active_contexts.begin(); + std::set::const_iterator end = parent->active_contexts.end(); + while (begin != end) { + context* ctx = *begin; + + visit_stack_elements(ctx->datastack_seg, (cell*)ctx->datastack); + visit_stack_elements(ctx->retainstack_seg, (cell*)ctx->retainstack); + visit_object_array(ctx->context_objects, + ctx->context_objects + context_object_count); + visit_callstack(ctx); + begin++; + } } -template -struct literal_references_visitor { - slot_visitor *visitor; +template struct literal_references_visitor { + slot_visitor* visitor; - explicit literal_references_visitor(slot_visitor *visitor_) : visitor(visitor_) {} + explicit literal_references_visitor(slot_visitor* visitor_) + : visitor(visitor_) {} - void operator()(instruction_operand op) - { - if(op.rel_type() == RT_LITERAL) - op.store_value(visitor->visit_pointer(op.load_value())); - } + void operator()(instruction_operand op) { + if (op.rel_type() == RT_LITERAL) + op.store_value(visitor->visit_pointer(op.load_value())); + } }; -template -void slot_visitor::visit_code_block_objects(code_block *compiled) -{ - visit_handle(&compiled->owner); - visit_handle(&compiled->parameters); - visit_handle(&compiled->relocation); +template +void slot_visitor::visit_code_block_objects(code_block* compiled) { + visit_handle(&compiled->owner); + visit_handle(&compiled->parameters); + visit_handle(&compiled->relocation); } -template -void slot_visitor::visit_embedded_literals(code_block *compiled) -{ - if(!parent->code->uninitialized_p(compiled)) - { - literal_references_visitor visitor(this); - compiled->each_instruction_operand(visitor); - } +template +void slot_visitor::visit_embedded_literals(code_block* compiled) { + if (!parent->code->uninitialized_p(compiled)) { + literal_references_visitor visitor(this); + compiled->each_instruction_operand(visitor); + } } } -- 2.34.1