From 03d861976cd13b610b7effcd4366e7e38cd08d5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Lindqvist?= Date: Sat, 1 Aug 2015 16:47:04 +0200 Subject: [PATCH] VM: new method visit_instruction_operands(), it replaces the instruction operand iteration code in compaction.cpp and image.cpp --- vm/compaction.cpp | 43 +++------------------------------------- vm/image.cpp | 48 ++------------------------------------------- vm/slot_visitor.hpp | 37 ++++++++++++++++++++++++++++++++++ 3 files changed, 42 insertions(+), 86 deletions(-) diff --git a/vm/compaction.cpp b/vm/compaction.cpp index 48b45ab9d6..3e606ca52b 100644 --- a/vm/compaction.cpp +++ b/vm/compaction.cpp @@ -52,37 +52,6 @@ struct compaction_fixup { } }; -template -fixnum compute_operand_value(factor_vm* parent, - cell old_entry_point, - Fixup fixup, - instruction_operand op) { - cell old_offset = op.rel_offset() + old_entry_point; - switch (op.rel_type()) { - case RT_LITERAL: { - cell value = op.load_value(old_offset); - if (immediate_p(value)) - return value; - return RETAG(fixup.fixup_data(untag(value)), TAG(value)); - } - case RT_ENTRY_POINT: - case RT_ENTRY_POINT_PIC: - case RT_ENTRY_POINT_PIC_TAIL: - case RT_HERE: { - cell value = op.load_value(old_offset); - cell offset = TAG(value); - code_block* compiled = (code_block*)UNTAG(value); - return (cell)fixup.fixup_code(compiled) + offset; - } - case RT_THIS: - case RT_CARDS_OFFSET: - case RT_DECKS_OFFSET: - return parent->compute_external_address(op); - default: - return op.load_value(old_offset); - } -} - /* After a compaction, invalidate any code heap roots which are not marked, and also slide the valid roots up so that call sites can be updated correctly in case an inline cache compilation triggered compaction. */ @@ -148,20 +117,14 @@ void factor_vm::collect_compact_impl() { /* Slide everything in the code heap up, and update data and code heap pointers inside code blocks. */ - auto compact_data_func = [&](code_block* old_addr, + auto compact_code_func = [&](code_block* old_addr, code_block* new_addr, cell size) { forwarder.visit_code_block_objects(new_addr); cell old_entry_point = old_addr->entry_point(); - auto update_func = [&](instruction_operand op) { - op.store_value(compute_operand_value(this, - old_entry_point, - forwarder.fixup, - op)); - }; - new_addr->each_instruction_operand(update_func); + forwarder.visit_instruction_operands(new_addr, old_entry_point); }; - code->allocator->compact(compact_data_func, fixup, &code_finger); + code->allocator->compact(compact_code_func, fixup, &code_finger); forwarder.visit_all_roots(); forwarder.visit_context_code_blocks(); diff --git a/vm/image.cpp b/vm/image.cpp index d4d6a8e4c5..2c59dc27ca 100644 --- a/vm/image.cpp +++ b/vm/image.cpp @@ -109,57 +109,13 @@ void factor_vm::fixup_data(cell data_offset, cell code_offset) { data->tenured->iterate(start_object_updater, fixup); } -struct startup_code_block_relocation_visitor { - factor_vm* parent; - startup_fixup fixup; - slot_visitor visitor; - - startup_code_block_relocation_visitor(factor_vm* parent, - startup_fixup fixup) - : parent(parent), - fixup(fixup), - visitor(slot_visitor(parent, fixup)) {} - - fixnum compute_operand_value(instruction_operand op) { - code_block* compiled = op.compiled; - cell old_offset = - op.rel_offset() + compiled->entry_point() - fixup.code_offset; - switch (op.rel_type()) { - case RT_LITERAL: { - cell value = op.load_value(old_offset); - if (immediate_p(value)) - return value; - return RETAG(fixup.fixup_data(untag(value)), TAG(value)); - } - case RT_ENTRY_POINT: - case RT_ENTRY_POINT_PIC: - case RT_ENTRY_POINT_PIC_TAIL: - case RT_HERE: { - cell value = op.load_value(old_offset); - cell offset = TAG(value); - code_block* compiled = (code_block*)UNTAG(value); - return (cell)fixup.fixup_code(compiled) + offset; - } - case RT_UNTAGGED: - return op.load_value(old_offset); - default: - return parent->compute_external_address(op); - } - } - - void operator()(instruction_operand op) { - op.store_value(compute_operand_value(op)); - } -}; - void factor_vm::fixup_code(cell data_offset, cell code_offset) { startup_fixup fixup(data_offset, code_offset); auto updater = [&](code_block* compiled, cell size) { slot_visitor visitor(this, fixup); visitor.visit_code_block_objects(compiled); - - startup_code_block_relocation_visitor code_visitor(this, fixup); - compiled->each_instruction_operand(code_visitor); + cell rel_base = compiled->entry_point() - fixup.code_offset; + visitor.visit_instruction_operands(compiled, rel_base); }; code->allocator->iterate(updater, fixup); } diff --git a/vm/slot_visitor.hpp b/vm/slot_visitor.hpp index 7552b21c94..5128c39e2c 100644 --- a/vm/slot_visitor.hpp +++ b/vm/slot_visitor.hpp @@ -141,6 +141,7 @@ template struct slot_visitor { void visit_embedded_code_pointers(code_block* compiled); void visit_object(object* obj); void visit_mark_stack(std::vector* mark_stack); + void visit_instruction_operands(code_block* block, cell rel_base); }; template @@ -466,4 +467,40 @@ void slot_visitor::visit_mark_stack(std::vector* mark_stack) { } } +/* Visits the instruction operands in a code block. If the operand is + a pointer to a code block or data object, then the fixup is applied + to it. Otherwise, if it is an external addess, that address is + recomputed. If it is an untagged number literal (RT_UNTAGGED) or an + immediate value, then nothing is done with it. */ +template +void slot_visitor::visit_instruction_operands(code_block* block, + cell rel_base) { + auto visit_func = [&](instruction_operand op){ + cell old_offset = rel_base + op.rel_offset(); + cell value = op.load_value(old_offset); + switch (op.rel_type()) { + case RT_LITERAL: { + value = visit_pointer(value); + break; + } + case RT_ENTRY_POINT: + case RT_ENTRY_POINT_PIC: + case RT_ENTRY_POINT_PIC_TAIL: + case RT_HERE: { + cell offset = TAG(value); + code_block* compiled = (code_block*)UNTAG(value); + value = RETAG(fixup.fixup_code(compiled), offset); + break; + } + case RT_UNTAGGED: + break; + default: + value = parent->compute_external_address(op); + break; + } + op.store_value(value); + }; + block->each_instruction_operand(visit_func); +} + }