void operator()(instruction_operand op) { code_block *compiled = op.parent_code_block(); cell old_offset = op.rel_offset() + (cell)compiled->entry_point() - code_offset; switch(op.rel_type()) { case RT_LITERAL: op.store_value(data_visitor.visit_pointer(op.load_value(old_offset))); break; case RT_ENTRY_POINT: case RT_ENTRY_POINT_PIC: case RT_ENTRY_POINT_PIC_TAIL: op.store_code_block(code_visitor(op.load_code_block(old_offset))); break; case RT_HERE: op.store_value(op.load_value(old_offset) + code_offset); break; case RT_UNTAGGED: break; default: parent->store_external_address(op); break; } }
void operator()(code_block *old_address, code_block *new_address, cell size) { data_forwarder.visit_code_block_objects(new_address); code_block_compaction_relocation_visitor<Fixup> visitor(parent,old_address,fixup); new_address->each_instruction_operand(visitor); }
/* next -> [entry_point] [size] [return address] -- x86 only, backend adds 1 to each spill location [spill area] ... frame -> [entry_point] [size] */ void operator()(stack_frame *frame) { cell return_address = parent->frame_offset(frame); if(return_address == (cell)-1) return; code_block *compiled = visitor->fixup.translate_code(parent->frame_code(frame)); gc_info *info = compiled->block_gc_info(); 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; #endif cell *stack_pointer = (cell *)(parent->frame_successor(frame) + 1); 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; #endif stack_pointer[spill_slot] -= stack_pointer[base_pointer]; } } /* 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)) { #ifdef DEBUG_GC_MAPS 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]; } }
void operator()(object *obj, cell size) { parent->data->tenured->starts.record_object_start_offset(obj); switch(obj->type()) { case ALIEN_TYPE: { cell payload_start = obj->binary_payload_start(); data_visitor.visit_slots(obj,payload_start); alien *ptr = (alien *)obj; if(to_boolean(ptr->base)) ptr->update_address(); else ptr->expired = parent->true_object; break; } case DLL_TYPE: { cell payload_start = obj->binary_payload_start(); data_visitor.visit_slots(obj,payload_start); parent->ffi_dlopen((dll *)obj); break; } case TUPLE_TYPE: { cell payload_start = tuple_size_with_fixup(data_offset,obj); data_visitor.visit_slots(obj,payload_start); break; } default: { cell payload_start = obj->binary_payload_start(); data_visitor.visit_slots(obj,payload_start); code_visitor.visit_object_code_block(obj); break; } } }
/* 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); 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; #ifdef DEBUG_GC_MAPS std::cout << "call frame code block " << compiled << " with offset " << return_address << std::endl; #endif cell* stack_pointer = (cell*)frame_top; uint8_t* 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++) { uint32_t base_pointer = info->lookup_base_pointer(callsite, spill_slot); if (base_pointer != (uint32_t)-1) { #ifdef DEBUG_GC_MAPS std::cout << "visiting derived root " << spill_slot << " with base pointer " << base_pointer << std::endl; #endif stack_pointer[spill_slot] -= stack_pointer[base_pointer]; } } /* 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)) { #ifdef DEBUG_GC_MAPS 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++) { uint32_t base_pointer = info->lookup_base_pointer(callsite, spill_slot); if (base_pointer != (uint32_t)-1) stack_pointer[spill_slot] += stack_pointer[base_pointer]; } }
void trace_partial_objects(cell start, cell end, cell card_start, cell card_end) { if(card_start < end) { start += sizeof(cell); if(start < card_start) start = card_start; if(end > card_end) end = card_end; cell *slot_ptr = (cell *)start; cell *end_ptr = (cell *)end; for(; slot_ptr < end_ptr; slot_ptr++) data_visitor.visit_handle(slot_ptr); } }
/* next -> [entry_point] [size] [return address] -- x86 only, backend adds 1 to each spill location [spill area] ... frame -> [entry_point] [size] */ void operator()(stack_frame *frame) { cell return_address = parent->frame_offset(frame); if(return_address == (cell)-1) return; code_block *compiled = visitor->fixup.translate_code(parent->frame_code(frame)); gc_info *info = compiled->block_gc_info(); assert(return_address < compiled->size()); int index = info->return_address_index(return_address); if(index == -1) return; u8 *bitmap = info->gc_info_bitmap(); cell base = info->spill_slot_base(index); cell *stack_pointer = (cell *)(parent->frame_successor(frame) + 1); for(cell spill_slot = 0; spill_slot < info->gc_root_count; spill_slot++) { if(bitmap_p(bitmap,base + spill_slot)) visitor->visit_handle(&stack_pointer[spill_slot]); } }
void operator()(object *obj) { workhorse->visit_slots(obj); }
void trace_embedded_literals(code_block *compiled) { data_visitor.visit_embedded_literals(compiled); }
void trace_code_block_objects(code_block *compiled) { data_visitor.visit_code_block_objects(compiled); }
void trace_contexts() { data_visitor.visit_contexts(); }
void trace_roots() { data_visitor.visit_roots(); }
void trace_object(object *ptr) { data_visitor.visit_slots(ptr); if(ptr->type() == ALIEN_TYPE) ((alien *)ptr)->update_address(); }
void trace_handle(cell *handle) { data_visitor.visit_handle(handle); }
void operator()(code_block *compiled, cell size) { workhorse->visit_code_block_objects(compiled); workhorse->visit_embedded_literals(compiled); }
void operator()(code_block* stub) { visitor->visit_handle(&stub->owner); }
void operator()(instruction_operand op) { if (op.rel_type() == RT_LITERAL) op.store_value(visitor->visit_pointer(op.load_value())); }