diff --git a/Makefile b/Makefile index 52914d128a..f85dbb9bee 100755 --- a/Makefile +++ b/Makefile @@ -39,13 +39,14 @@ DLL_OBJS = $(PLAF_DLL_OBJS) \ vm/byte_arrays.o \ vm/callbacks.o \ vm/callstack.o \ - vm/code_block.o \ + vm/code_blocks.o \ vm/code_heap.o \ vm/compaction.o \ vm/contexts.o \ vm/data_heap.o \ vm/debug.o \ vm/dispatch.o \ + vm/embedded_pointers.o \ vm/errors.o \ vm/factor.o \ vm/free_list.o \ diff --git a/vm/callbacks.cpp b/vm/callbacks.cpp index 4fe19c0bc0..d6b941b93b 100644 --- a/vm/callbacks.cpp +++ b/vm/callbacks.cpp @@ -26,9 +26,8 @@ void callback_heap::update(callback *stub) cell rel_class = untag_fixnum(array_nth(code_template.untagged(),1)); cell offset = untag_fixnum(array_nth(code_template.untagged(),3)); - parent->store_address_in_code_block(rel_class, - (cell)(stub + 1) + offset, - (cell)(stub->compiled + 1)); + embedded_pointer ptr(rel_class,offset + (cell)(stub + 1)); + ptr.store_address((cell)(stub->compiled + 1)); flush_icache((cell)stub,stub->size); } diff --git a/vm/code_block.cpp b/vm/code_blocks.cpp similarity index 73% rename from vm/code_block.cpp rename to vm/code_blocks.cpp index dc6a488e26..d33d468d20 100755 --- a/vm/code_block.cpp +++ b/vm/code_blocks.cpp @@ -3,53 +3,11 @@ namespace factor { -relocation_type factor_vm::relocation_type_of(relocation_entry r) -{ - return (relocation_type)((r & 0xf0000000) >> 28); -} - -relocation_class factor_vm::relocation_class_of(relocation_entry r) -{ - return (relocation_class)((r & 0x0f000000) >> 24); -} - -cell factor_vm::relocation_offset_of(relocation_entry r) -{ - return (r & 0x00ffffff); -} - void factor_vm::flush_icache_for(code_block *block) { flush_icache((cell)block,block->size()); } -int factor_vm::number_of_parameters(relocation_type type) -{ - switch(type) - { - case RT_PRIMITIVE: - case RT_XT: - case RT_XT_PIC: - case RT_XT_PIC_TAIL: - case RT_IMMEDIATE: - case RT_HERE: - case RT_UNTAGGED: - case RT_VM: - return 1; - case RT_DLSYM: - return 2; - case RT_THIS: - case RT_CONTEXT: - case RT_MEGAMORPHIC_CACHE_HITS: - case RT_CARDS_OFFSET: - case RT_DECKS_OFFSET: - return 0; - default: - critical_error("Bad rel type",type); - return -1; /* Can't happen */ - } -} - void *factor_vm::object_xt(cell obj) { switch(tagged(obj).type()) @@ -148,11 +106,11 @@ cell factor_vm::compute_relocation(relocation_entry rel, cell index, code_block { array *literals = (to_boolean(compiled->literals) ? untag(compiled->literals) : NULL); - cell offset = relocation_offset_of(rel) + (cell)compiled->xt(); + cell offset = rel.rel_offset() + (cell)compiled->xt(); #define ARG array_nth(literals,index) - switch(relocation_type_of(rel)) + switch(rel.rel_type()) { case RT_PRIMITIVE: return (cell)primitives[untag_fixnum(ARG)]; @@ -186,7 +144,7 @@ cell factor_vm::compute_relocation(relocation_entry rel, cell index, code_block case RT_DECKS_OFFSET: return decks_offset; default: - critical_error("Bad rel type",rel); + critical_error("Bad rel type",rel.rel_type()); return 0; /* Can't happen */ } @@ -206,75 +164,11 @@ template void factor_vm::iterate_relocations(code_block *comp { relocation_entry rel = relocation->data()[i]; iter(rel,index,compiled); - index += number_of_parameters(relocation_type_of(rel)); + index += rel.number_of_parameters(); } } } -/* Store a 32-bit value into a PowerPC LIS/ORI sequence */ -void factor_vm::store_address_2_2(cell *ptr, cell value) -{ - ptr[-1] = ((ptr[-1] & ~0xffff) | ((value >> 16) & 0xffff)); - ptr[ 0] = ((ptr[ 0] & ~0xffff) | (value & 0xffff)); -} - -/* Store a value into a bitfield of a PowerPC instruction */ -void factor_vm::store_address_masked(cell *ptr, fixnum value, cell mask, fixnum shift) -{ - /* This is unaccurate but good enough */ - fixnum test = (fixnum)mask >> 1; - if(value <= -test || value >= test) - critical_error("Value does not fit inside relocation",0); - - *ptr = ((*ptr & ~mask) | ((value >> shift) & mask)); -} - -/* Perform a fixup on a code block */ -void factor_vm::store_address_in_code_block(cell klass, cell offset, fixnum absolute_value) -{ - fixnum relative_value = absolute_value - offset; - - switch(klass) - { - case RC_ABSOLUTE_CELL: - *(cell *)offset = absolute_value; - break; - case RC_ABSOLUTE: - *(u32*)offset = absolute_value; - break; - case RC_RELATIVE: - *(u32*)offset = relative_value - sizeof(u32); - break; - case RC_ABSOLUTE_PPC_2_2: - store_address_2_2((cell *)offset,absolute_value); - break; - case RC_ABSOLUTE_PPC_2: - store_address_masked((cell *)offset,absolute_value,rel_absolute_ppc_2_mask,0); - break; - case RC_RELATIVE_PPC_2: - store_address_masked((cell *)offset,relative_value,rel_relative_ppc_2_mask,0); - break; - case RC_RELATIVE_PPC_3: - store_address_masked((cell *)offset,relative_value,rel_relative_ppc_3_mask,0); - break; - case RC_RELATIVE_ARM_3: - store_address_masked((cell *)offset,relative_value - sizeof(cell) * 2, - rel_relative_arm_3_mask,2); - break; - case RC_INDIRECT_ARM: - store_address_masked((cell *)offset,relative_value - sizeof(cell), - rel_indirect_arm_mask,0); - break; - case RC_INDIRECT_ARM_PC: - store_address_masked((cell *)offset,relative_value - sizeof(cell) * 2, - rel_indirect_arm_mask,0); - break; - default: - critical_error("Bad rel class",klass); - break; - } -} - struct literal_references_updater { factor_vm *parent; @@ -282,12 +176,11 @@ struct literal_references_updater { void operator()(relocation_entry rel, cell index, code_block *compiled) { - if(parent->relocation_type_of(rel) == RT_IMMEDIATE) + if(rel.rel_type() == RT_IMMEDIATE) { - cell offset = parent->relocation_offset_of(rel) + (cell)(compiled + 1); + embedded_pointer ptr(rel.rel_class(),rel.rel_offset() + (cell)(compiled + 1)); array *literals = untag(compiled->literals); - fixnum absolute_value = array_nth(literals,index); - parent->store_address_in_code_block(parent->relocation_class_of(rel),offset,absolute_value); + ptr.store_address(array_nth(literals,index)); } } }; @@ -313,9 +206,8 @@ void factor_vm::relocate_code_block_step(relocation_entry rel, cell index, code_ tagged(compiled->relocation).untag_check(this); #endif - store_address_in_code_block(relocation_class_of(rel), - relocation_offset_of(rel) + (cell)compiled->xt(), - compute_relocation(rel,index,compiled)); + embedded_pointer ptr(rel.rel_class(),rel.rel_offset() + (cell)compiled->xt()); + ptr.store_address(compute_relocation(rel,index,compiled)); } struct word_references_updater { @@ -324,7 +216,7 @@ struct word_references_updater { explicit word_references_updater(factor_vm *parent_) : parent(parent_) {} void operator()(relocation_entry rel, cell index, code_block *compiled) { - relocation_type type = parent->relocation_type_of(rel); + relocation_type type = rel.rel_type(); if(type == RT_XT || type == RT_XT_PIC || type == RT_XT_PIC_TAIL) parent->relocate_code_block_step(rel,index,compiled); } @@ -363,7 +255,8 @@ struct literal_and_word_references_updater { void operator()(relocation_entry rel, cell index, code_block *compiled) { - relocation_type type = parent->relocation_type_of(rel); + relocation_type type = rel.rel_type(); + switch(type) { case RT_IMMEDIATE: @@ -425,13 +318,12 @@ void factor_vm::fixup_labels(array *labels, code_block *compiled) for(i = 0; i < size; i += 3) { - cell klass = untag_fixnum(array_nth(labels,i)); + cell rel_class = untag_fixnum(array_nth(labels,i)); cell offset = untag_fixnum(array_nth(labels,i + 1)); cell target = untag_fixnum(array_nth(labels,i + 2)); - store_address_in_code_block(klass, - offset + (cell)(compiled + 1), - target + (cell)(compiled + 1)); + embedded_pointer ptr(rel_class,offset + (cell)(compiled + 1)); + ptr.store_address(target + (cell)(compiled + 1)); } } diff --git a/vm/code_blocks.hpp b/vm/code_blocks.hpp new file mode 100644 index 0000000000..dad71786dc --- /dev/null +++ b/vm/code_blocks.hpp @@ -0,0 +1,48 @@ +namespace factor +{ + +/* The compiled code heap is structured into blocks. */ +struct code_block +{ + cell header; + cell owner; /* tagged pointer to word, quotation or f */ + cell literals; /* tagged pointer to array or f */ + cell relocation; /* tagged pointer to byte-array or f */ + + bool free_p() const + { + return header & 1 == 1; + } + + code_block_type type() const + { + return (code_block_type)((header >> 1) & 0x3); + } + + void set_type(code_block_type type) + { + header = ((header & ~0x7) | (type << 1)); + } + + bool pic_p() const + { + return type() == code_block_pic; + } + + bool optimized_p() const + { + return type() == code_block_optimized; + } + + cell size() const + { + return header & ~7; + } + + void *xt() const + { + return (void *)(this + 1); + } +}; + +} diff --git a/vm/embedded_pointers.cpp b/vm/embedded_pointers.cpp new file mode 100644 index 0000000000..8d368e5f32 --- /dev/null +++ b/vm/embedded_pointers.cpp @@ -0,0 +1,116 @@ +#include "master.hpp" + +namespace factor +{ + +/* Load a 32-bit value from a PowerPC LIS/ORI sequence */ +fixnum embedded_pointer::load_address_2_2() +{ + cell *ptr = (cell *)pointer; + cell hi = (ptr[-1] & 0xffff); + cell lo = (ptr[ 0] & 0xffff); + return hi << 16 | lo; +} + +/* Load a value from a bitfield of a PowerPC instruction */ +fixnum embedded_pointer::load_address_masked(cell mask, fixnum shift) +{ + cell *ptr = (cell *)pointer; + + return (*ptr & mask) << shift; +} + +fixnum embedded_pointer::load_address() +{ + switch(rel_class) + { + case RC_ABSOLUTE_CELL: + return *(cell *)pointer; + case RC_ABSOLUTE: + return *(u32*)pointer; + case RC_RELATIVE: + return *(u32*)pointer + pointer + sizeof(u32); + case RC_ABSOLUTE_PPC_2_2: + return load_address_2_2(); + case RC_ABSOLUTE_PPC_2: + return load_address_masked(rel_absolute_ppc_2_mask,0); + case RC_RELATIVE_PPC_2: + return load_address_masked(rel_relative_ppc_2_mask,0) + pointer; + case RC_RELATIVE_PPC_3: + return load_address_masked(rel_relative_ppc_3_mask,0) + pointer; + case RC_RELATIVE_ARM_3: + return load_address_masked(rel_relative_arm_3_mask,2) + pointer + sizeof(cell) * 2; + case RC_INDIRECT_ARM: + return load_address_masked(rel_indirect_arm_mask,0) + pointer + sizeof(cell); + case RC_INDIRECT_ARM_PC: + return load_address_masked(rel_indirect_arm_mask,0) + pointer + sizeof(cell) * 2; + default: + critical_error("Bad rel class",rel_class); + return 0; + } +} + +/* Store a 32-bit value into a PowerPC LIS/ORI sequence */ +void embedded_pointer::store_address_2_2(fixnum value) +{ + cell *ptr = (cell *)pointer; + ptr[-1] = ((ptr[-1] & ~0xffff) | ((value >> 16) & 0xffff)); + ptr[ 0] = ((ptr[ 0] & ~0xffff) | (value & 0xffff)); +} + +/* Store a value into a bitfield of a PowerPC instruction */ +void embedded_pointer::store_address_masked(fixnum value, cell mask, fixnum shift) +{ + cell *ptr = (cell *)pointer; + + /* This is unaccurate but good enough */ + fixnum test = (fixnum)mask >> 1; + if(value <= -test || value >= test) + critical_error("Value does not fit inside relocation",0); + + *ptr = ((*ptr & ~mask) | ((value >> shift) & mask)); +} + +void embedded_pointer::store_address(fixnum absolute_value) +{ + fixnum relative_value = absolute_value - pointer; + + switch(rel_class) + { + case RC_ABSOLUTE_CELL: + *(cell *)pointer = absolute_value; + break; + case RC_ABSOLUTE: + *(u32*)pointer = absolute_value; + break; + case RC_RELATIVE: + *(u32*)pointer = relative_value - sizeof(u32); + break; + case RC_ABSOLUTE_PPC_2_2: + store_address_2_2(absolute_value); + break; + case RC_ABSOLUTE_PPC_2: + store_address_masked(absolute_value,rel_absolute_ppc_2_mask,0); + break; + case RC_RELATIVE_PPC_2: + store_address_masked(relative_value,rel_relative_ppc_2_mask,0); + break; + case RC_RELATIVE_PPC_3: + store_address_masked(relative_value,rel_relative_ppc_3_mask,0); + break; + case RC_RELATIVE_ARM_3: + store_address_masked(relative_value - sizeof(cell) * 2,rel_relative_arm_3_mask,2); + break; + case RC_INDIRECT_ARM: + store_address_masked(relative_value - sizeof(cell),rel_indirect_arm_mask,0); + break; + case RC_INDIRECT_ARM_PC: + store_address_masked(relative_value - sizeof(cell) * 2,rel_indirect_arm_mask,0); + break; + default: + critical_error("Bad rel class",rel_class); + break; + } +} + +} diff --git a/vm/code_block.hpp b/vm/embedded_pointers.hpp similarity index 58% rename from vm/code_block.hpp rename to vm/embedded_pointers.hpp index d31a776c0e..69435899ef 100644 --- a/vm/code_block.hpp +++ b/vm/embedded_pointers.hpp @@ -64,6 +64,75 @@ static const cell rel_indirect_arm_mask = 0xfff; static const cell rel_relative_arm_3_mask = 0xffffff; /* code relocation table consists of a table of entries for each fixup */ -typedef u32 relocation_entry; +struct relocation_entry { + u32 value; + + relocation_entry(u32 value_) : value(value_) {} + + relocation_entry(relocation_type rel_type, + relocation_class rel_class, + cell offset) + { + value = (rel_type << 28) | (rel_class << 24) | offset; + } + + relocation_type rel_type() + { + return (relocation_type)((value & 0xf0000000) >> 28); + } + + relocation_class rel_class() + { + return (relocation_class)((value & 0x0f000000) >> 24); + } + + cell rel_offset() + { + return (value & 0x00ffffff); + } + + int number_of_parameters() + { + switch(rel_type()) + { + case RT_PRIMITIVE: + case RT_XT: + case RT_XT_PIC: + case RT_XT_PIC_TAIL: + case RT_IMMEDIATE: + case RT_HERE: + case RT_UNTAGGED: + case RT_VM: + return 1; + case RT_DLSYM: + return 2; + case RT_THIS: + case RT_CONTEXT: + case RT_MEGAMORPHIC_CACHE_HITS: + case RT_CARDS_OFFSET: + case RT_DECKS_OFFSET: + return 0; + default: + critical_error("Bad rel type",rel_type()); + return -1; /* Can't happen */ + } + } +}; + +struct embedded_pointer { + cell rel_class; + cell pointer; + + embedded_pointer(cell rel_class_, cell pointer_) : + rel_class(rel_class_), pointer(pointer_) {} + + fixnum load_address_2_2(); + fixnum load_address_masked(cell mask, fixnum shift); + fixnum load_address(); + + void store_address_2_2(fixnum value); + void store_address_masked(fixnum value, cell mask, fixnum shift); + void store_address(fixnum value); +}; } diff --git a/vm/jit.cpp b/vm/jit.cpp index e72e88bfdf..2fe9384630 100644 --- a/vm/jit.cpp +++ b/vm/jit.cpp @@ -32,10 +32,10 @@ void jit::emit_relocation(cell code_template_) cell rel_type = array_nth(code_template.untagged(),i + 1); cell offset = array_nth(code_template.untagged(),i + 2); - relocation_entry new_entry - = (untag_fixnum(rel_type) << 28) - | (untag_fixnum(rel_class) << 24) - | ((code.count + untag_fixnum(offset))); + relocation_entry new_entry( + (relocation_type)untag_fixnum(rel_type), + (relocation_class)untag_fixnum(rel_class), + code.count + untag_fixnum(offset)); relocation.append_bytes(&new_entry,sizeof(relocation_entry)); } } diff --git a/vm/layouts.hpp b/vm/layouts.hpp index ff7ccbf3c0..541ee227ee 100644 --- a/vm/layouts.hpp +++ b/vm/layouts.hpp @@ -211,49 +211,7 @@ struct string : public object { cell nth(cell i) const; }; -/* The compiled code heap is structured into blocks. */ -struct code_block -{ - cell header; - cell owner; /* tagged pointer to word, quotation or f */ - cell literals; /* tagged pointer to array or f */ - cell relocation; /* tagged pointer to byte-array or f */ - - bool free_p() const - { - return header & 1 == 1; - } - - code_block_type type() const - { - return (code_block_type)((header >> 1) & 0x3); - } - - void set_type(code_block_type type) - { - header = ((header & ~0x7) | (type << 1)); - } - - bool pic_p() const - { - return type() == code_block_pic; - } - - bool optimized_p() const - { - return type() == code_block_optimized; - } - - cell size() const - { - return header & ~7; - } - - void *xt() const - { - return (void *)(this + 1); - } -}; +struct code_block; /* Assembly code makes assumptions about the layout of this struct */ struct word : public object { diff --git a/vm/master.hpp b/vm/master.hpp index 23c70782df..cfb71a4715 100755 --- a/vm/master.hpp +++ b/vm/master.hpp @@ -49,7 +49,8 @@ namespace factor #include "errors.hpp" #include "bignumint.hpp" #include "bignum.hpp" -#include "code_block.hpp" +#include "embedded_pointers.hpp" +#include "code_blocks.hpp" #include "bump_allocator.hpp" #include "bitwise_hacks.hpp" #include "mark_bits.hpp" diff --git a/vm/slot_visitor.hpp b/vm/slot_visitor.hpp index af920fc6e2..908e0f3152 100644 --- a/vm/slot_visitor.hpp +++ b/vm/slot_visitor.hpp @@ -8,14 +8,18 @@ template struct slot_visitor { explicit slot_visitor(factor_vm *parent_, Visitor visitor_) : parent(parent_), visitor(visitor_) {} - void visit_handle(cell *handle) + cell visit_pointer(cell pointer) { - cell pointer = *handle; - if(immediate_p(pointer)) return; + if(immediate_p(pointer)) return pointer; object *untagged = untag(pointer); untagged = visitor(untagged); - *handle = RETAG(untagged,TAG(pointer)); + return RETAG(untagged,TAG(pointer)); + } + + void visit_handle(cell *handle) + { + *handle = visit_pointer(*handle); } void visit_slots(object *ptr, cell payload_start) diff --git a/vm/vm.hpp b/vm/vm.hpp index 05f15af560..022ddfa603 100755 --- a/vm/vm.hpp +++ b/vm/vm.hpp @@ -485,11 +485,7 @@ struct factor_vm void primitive_fclose(); //code_block - relocation_type relocation_type_of(relocation_entry r); - relocation_class relocation_class_of(relocation_entry r); - cell relocation_offset_of(relocation_entry r); void flush_icache_for(code_block *block); - int number_of_parameters(relocation_type type); void *object_xt(cell obj); void *xt_pic(word *w, cell tagged_quot); void *word_xt_pic(word *w); @@ -498,9 +494,6 @@ struct factor_vm void *get_rel_symbol(array *literals, cell index); cell compute_relocation(relocation_entry rel, cell index, code_block *compiled); template void iterate_relocations(code_block *compiled, Iterator &iter); - void store_address_2_2(cell *ptr, cell value); - void store_address_masked(cell *ptr, fixnum value, cell mask, fixnum shift); - void store_address_in_code_block(cell klass, cell offset, fixnum absolute_value); void update_literal_references(code_block *compiled); void relocate_code_block_step(relocation_entry rel, cell index, code_block *compiled); void update_word_references(code_block *compiled);