]> gitweb.factorcode.org Git - factor.git/commitdiff
Fix conflict
authorSlava Pestov <slava@slava-pestovs-macbook-pro.local>
Sun, 22 Nov 2009 08:12:44 +0000 (02:12 -0600)
committerSlava Pestov <slava@slava-pestovs-macbook-pro.local>
Sun, 22 Nov 2009 08:12:44 +0000 (02:12 -0600)
13 files changed:
Makefile
vm/callbacks.cpp
vm/code_block.cpp [deleted file]
vm/code_block.hpp [deleted file]
vm/code_blocks.cpp [new file with mode: 0755]
vm/code_blocks.hpp [new file with mode: 0644]
vm/embedded_pointers.cpp [new file with mode: 0644]
vm/embedded_pointers.hpp [new file with mode: 0644]
vm/jit.cpp
vm/layouts.hpp
vm/master.hpp
vm/slot_visitor.hpp
vm/vm.hpp

index 6aee3e329df38352f8084559496d16260c086863..e5229ef7dfb562cfeb4a676b7718f40a1926ef0c 100755 (executable)
--- a/Makefile
+++ b/Makefile
@@ -39,7 +39,7 @@ 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 \
@@ -47,6 +47,7 @@ DLL_OBJS = $(PLAF_DLL_OBJS) \
        vm/data_heap_checker.o \
        vm/debug.o \
        vm/dispatch.o \
+       vm/embedded_pointers.o \
        vm/errors.o \
        vm/factor.o \
        vm/free_list.o \
index 4fe19c0bc0c481fb23e47cdc08ae2751113036ba..d6b941b93ba5922636dae5fbd9f3d2e49a601994 100644 (file)
@@ -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_block.cpp
deleted file mode 100755 (executable)
index dc6a488..0000000
+++ /dev/null
@@ -1,506 +0,0 @@
-#include "master.hpp"
-
-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<object>(obj).type())
-       {
-       case WORD_TYPE:
-               return untag<word>(obj)->xt;
-       case QUOTATION_TYPE:
-               return untag<quotation>(obj)->xt;
-       default:
-               critical_error("Expected word or quotation",obj);
-               return NULL;
-       }
-}
-
-void *factor_vm::xt_pic(word *w, cell tagged_quot)
-{
-       if(!to_boolean(tagged_quot) || max_pic_size == 0)
-               return w->xt;
-       else
-       {
-               quotation *quot = untag<quotation>(tagged_quot);
-               if(quot->code)
-                       return quot->xt;
-               else
-                       return w->xt;
-       }
-}
-
-void *factor_vm::word_xt_pic(word *w)
-{
-       return xt_pic(w,w->pic_def);
-}
-
-void *factor_vm::word_xt_pic_tail(word *w)
-{
-       return xt_pic(w,w->pic_tail_def);
-}
-
-/* References to undefined symbols are patched up to call this function on
-image load */
-void factor_vm::undefined_symbol()
-{
-       general_error(ERROR_UNDEFINED_SYMBOL,false_object,false_object,NULL);
-}
-
-void undefined_symbol()
-{
-       return tls_vm()->undefined_symbol();
-}
-
-/* Look up an external library symbol referenced by a compiled code block */
-void *factor_vm::get_rel_symbol(array *literals, cell index)
-{
-       cell symbol = array_nth(literals,index);
-       cell library = array_nth(literals,index + 1);
-
-       dll *d = (to_boolean(library) ? untag<dll>(library) : NULL);
-
-       if(d != NULL && !d->dll)
-               return (void *)factor::undefined_symbol;
-
-       switch(tagged<object>(symbol).type())
-       {
-       case BYTE_ARRAY_TYPE:
-               {
-                       symbol_char *name = alien_offset(symbol);
-                       void *sym = ffi_dlsym(d,name);
-
-                       if(sym)
-                               return sym;
-                       else
-                       {
-                               return (void *)factor::undefined_symbol;
-                       }
-               }
-       case ARRAY_TYPE:
-               {
-                       array *names = untag<array>(symbol);
-                       for(cell i = 0; i < array_capacity(names); i++)
-                       {
-                               symbol_char *name = alien_offset(array_nth(names,i));
-                               void *sym = ffi_dlsym(d,name);
-
-                               if(sym)
-                                       return sym;
-                       }
-                       return (void *)factor::undefined_symbol;
-               }
-       default:
-               critical_error("Bad symbol specifier",symbol);
-               return (void *)factor::undefined_symbol;
-       }
-}
-
-cell factor_vm::compute_relocation(relocation_entry rel, cell index, code_block *compiled)
-{
-       array *literals = (to_boolean(compiled->literals)
-               ? untag<array>(compiled->literals) : NULL);
-       cell offset = relocation_offset_of(rel) + (cell)compiled->xt();
-
-#define ARG array_nth(literals,index)
-
-       switch(relocation_type_of(rel))
-       {
-       case RT_PRIMITIVE:
-               return (cell)primitives[untag_fixnum(ARG)];
-       case RT_DLSYM:
-               return (cell)get_rel_symbol(literals,index);
-       case RT_IMMEDIATE:
-               return ARG;
-       case RT_XT:
-               return (cell)object_xt(ARG);
-       case RT_XT_PIC:
-               return (cell)word_xt_pic(untag<word>(ARG));
-       case RT_XT_PIC_TAIL:
-               return (cell)word_xt_pic_tail(untag<word>(ARG));
-       case RT_HERE:
-       {
-               fixnum arg = untag_fixnum(ARG);
-               return (arg >= 0 ? offset + arg : (cell)(compiled + 1) - arg);
-       }
-       case RT_THIS:
-               return (cell)(compiled + 1);
-       case RT_CONTEXT:
-               return (cell)&ctx;
-       case RT_UNTAGGED:
-               return untag_fixnum(ARG);
-       case RT_MEGAMORPHIC_CACHE_HITS:
-               return (cell)&dispatch_stats.megamorphic_cache_hits;
-       case RT_VM:
-               return (cell)this + untag_fixnum(ARG);
-       case RT_CARDS_OFFSET:
-               return cards_offset;
-       case RT_DECKS_OFFSET:
-               return decks_offset;
-       default:
-               critical_error("Bad rel type",rel);
-               return 0; /* Can't happen */
-       }
-
-#undef ARG
-}
-
-template<typename Iterator> void factor_vm::iterate_relocations(code_block *compiled, Iterator &iter)
-{
-       if(to_boolean(compiled->relocation))
-       {
-               byte_array *relocation = untag<byte_array>(compiled->relocation);
-
-               cell index = 0;
-               cell length = array_capacity(relocation) / sizeof(relocation_entry);
-
-               for(cell i = 0; i < length; i++)
-               {
-                       relocation_entry rel = relocation->data<relocation_entry>()[i];
-                       iter(rel,index,compiled);
-                       index += number_of_parameters(relocation_type_of(rel));                 
-               }
-       }
-}
-
-/* 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;
-
-       explicit literal_references_updater(factor_vm *parent_) : parent(parent_) {}
-
-       void operator()(relocation_entry rel, cell index, code_block *compiled)
-       {
-               if(parent->relocation_type_of(rel) == RT_IMMEDIATE)
-               {
-                       cell offset = parent->relocation_offset_of(rel) + (cell)(compiled + 1);
-                       array *literals = untag<array>(compiled->literals);
-                       fixnum absolute_value = array_nth(literals,index);
-                       parent->store_address_in_code_block(parent->relocation_class_of(rel),offset,absolute_value);
-               }
-       }
-};
-
-/* Update pointers to literals from compiled code. */
-void factor_vm::update_literal_references(code_block *compiled)
-{
-       if(!code->needs_fixup_p(compiled))
-       {
-               literal_references_updater updater(this);
-               iterate_relocations(compiled,updater);
-               flush_icache_for(compiled);
-       }
-}
-
-/* Compute an address to store at a relocation */
-void factor_vm::relocate_code_block_step(relocation_entry rel, cell index, code_block *compiled)
-{
-#ifdef FACTOR_DEBUG
-       if(to_boolean(compiled->literals))
-               tagged<array>(compiled->literals).untag_check(this);
-       if(to_boolean(compiled->relocation))
-               tagged<byte_array>(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));
-}
-
-struct word_references_updater {
-       factor_vm *parent;
-
-       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);
-               if(type == RT_XT || type == RT_XT_PIC || type == RT_XT_PIC_TAIL)
-                       parent->relocate_code_block_step(rel,index,compiled);
-       }
-};
-
-/* Relocate new code blocks completely; updating references to literals,
-dlsyms, and words. For all other words in the code heap, we only need
-to update references to other words, without worrying about literals
-or dlsyms. */
-void factor_vm::update_word_references(code_block *compiled)
-{
-       if(code->needs_fixup_p(compiled))
-               relocate_code_block(compiled);
-       /* update_word_references() is always applied to every block in
-          the code heap. Since it resets all call sites to point to
-          their canonical XT (cold entry point for non-tail calls,
-          standard entry point for tail calls), it means that no PICs
-          are referenced after this is done. So instead of polluting
-          the code heap with dead PICs that will be freed on the next
-          GC, we add them to the free list immediately. */
-       else if(compiled->pic_p())
-               code->code_heap_free(compiled);
-       else
-       {
-               word_references_updater updater(this);
-               iterate_relocations(compiled,updater);
-               flush_icache_for(compiled);
-       }
-}
-
-/* This runs after a full collection */
-struct literal_and_word_references_updater {
-       factor_vm *parent;
-
-       explicit literal_and_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);
-               switch(type)
-               {
-               case RT_IMMEDIATE:
-               case RT_XT:
-               case RT_XT_PIC:
-               case RT_XT_PIC_TAIL:
-                       parent->relocate_code_block_step(rel,index,compiled);
-                       break;
-               default:
-                       break;
-               }
-       }
-};
-
-void factor_vm::update_code_block_words_and_literals(code_block *compiled)
-{
-       if(code->needs_fixup_p(compiled))
-               relocate_code_block(compiled);
-       else
-       {
-               literal_and_word_references_updater updater(this);
-               iterate_relocations(compiled,updater);
-               flush_icache_for(compiled);
-       }
-}
-
-void factor_vm::check_code_address(cell address)
-{
-#ifdef FACTOR_DEBUG
-       assert(address >= code->seg->start && address < code->seg->end);
-#endif
-}
-
-struct code_block_relocator {
-       factor_vm *parent;
-
-       explicit code_block_relocator(factor_vm *parent_) : parent(parent_) {}
-
-       void operator()(relocation_entry rel, cell index, code_block *compiled)
-       {
-               parent->relocate_code_block_step(rel,index,compiled);
-       }
-};
-
-/* Perform all fixups on a code block */
-void factor_vm::relocate_code_block(code_block *compiled)
-{
-       code->needs_fixup.erase(compiled);
-       code_block_relocator relocator(this);
-       iterate_relocations(compiled,relocator);
-       flush_icache_for(compiled);
-}
-
-/* Fixup labels. This is done at compile time, not image load time */
-void factor_vm::fixup_labels(array *labels, code_block *compiled)
-{
-       cell i;
-       cell size = array_capacity(labels);
-
-       for(i = 0; i < size; i += 3)
-       {
-               cell klass = 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));
-       }
-}
-
-/* Might GC */
-code_block *factor_vm::allot_code_block(cell size, code_block_type type)
-{
-       code_block *block = code->allocator->allot(size + sizeof(code_block));
-
-       /* If allocation failed, do a full GC and compact the code heap.
-       A full GC that occurs as a result of the data heap filling up does not
-       trigger a compaction. This setup ensures that most GCs do not compact
-       the code heap, but if the code fills up, it probably means it will be
-       fragmented after GC anyway, so its best to compact. */
-       if(block == NULL)
-       {
-               primitive_compact_gc();
-               block = code->allocator->allot(size + sizeof(code_block));
-
-               /* Insufficient room even after code GC, give up */
-               if(block == NULL)
-               {
-                       std::cout << "Code heap used: " << code->allocator->occupied_space() << "\n";
-                       std::cout << "Code heap free: " << code->allocator->free_space() << "\n";
-                       fatal_error("Out of memory in add-compiled-block",0);
-               }
-       }
-
-       block->set_type(type);
-       return block;
-}
-
-/* Might GC */
-code_block *factor_vm::add_code_block(code_block_type type, cell code_, cell labels_, cell owner_, cell relocation_, cell literals_)
-{
-       data_root<byte_array> code(code_,this);
-       data_root<object> labels(labels_,this);
-       data_root<object> owner(owner_,this);
-       data_root<byte_array> relocation(relocation_,this);
-       data_root<array> literals(literals_,this);
-
-       cell code_length = array_capacity(code.untagged());
-       code_block *compiled = allot_code_block(code_length,type);
-
-       compiled->owner = owner.value();
-
-       /* slight space optimization */
-       if(relocation.type() == BYTE_ARRAY_TYPE && array_capacity(relocation.untagged()) == 0)
-               compiled->relocation = false_object;
-       else
-               compiled->relocation = relocation.value();
-
-       if(literals.type() == ARRAY_TYPE && array_capacity(literals.untagged()) == 0)
-               compiled->literals = false_object;
-       else
-               compiled->literals = literals.value();
-
-       /* code */
-       memcpy(compiled + 1,code.untagged() + 1,code_length);
-
-       /* fixup labels */
-       if(to_boolean(labels.value()))
-               fixup_labels(labels.as<array>().untagged(),compiled);
-
-       /* next time we do a minor GC, we have to scan the code heap for
-       literals */
-       this->code->write_barrier(compiled);
-       this->code->needs_fixup.insert(compiled);
-
-       return compiled;
-}
-
-}
diff --git a/vm/code_block.hpp b/vm/code_block.hpp
deleted file mode 100644 (file)
index d31a776..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-namespace factor
-{
-
-enum relocation_type {
-       /* arg is a primitive number */
-       RT_PRIMITIVE,
-       /* arg is a literal table index, holding an array pair (symbol/dll) */
-       RT_DLSYM,
-       /* a pointer to a compiled word reference */
-       RT_DISPATCH,
-       /* a word or quotation's general entry point */
-       RT_XT,
-       /* a word's PIC entry point */
-       RT_XT_PIC,
-       /* a word's tail-call PIC entry point */
-       RT_XT_PIC_TAIL,
-       /* current offset */
-       RT_HERE,
-       /* current code block */
-       RT_THIS,
-       /* immediate literal */
-       RT_IMMEDIATE,
-       /* address of ctx var */
-       RT_CONTEXT,
-       /* untagged fixnum literal */
-       RT_UNTAGGED,
-       /* address of megamorphic_cache_hits var */
-       RT_MEGAMORPHIC_CACHE_HITS,
-       /* address of vm object */
-       RT_VM,
-       /* value of vm->cards_offset */
-       RT_CARDS_OFFSET,
-       /* value of vm->decks_offset */
-       RT_DECKS_OFFSET,
-};
-
-enum relocation_class {
-       /* absolute address in a 64-bit location */
-       RC_ABSOLUTE_CELL,
-       /* absolute address in a 32-bit location */
-       RC_ABSOLUTE,
-       /* relative address in a 32-bit location */
-       RC_RELATIVE,
-       /* absolute address in a PowerPC LIS/ORI sequence */
-       RC_ABSOLUTE_PPC_2_2,
-       /* absolute address in a PowerPC LWZ instruction */
-       RC_ABSOLUTE_PPC_2,
-       /* relative address in a PowerPC LWZ/STW/BC instruction */
-       RC_RELATIVE_PPC_2,
-       /* relative address in a PowerPC B/BL instruction */
-       RC_RELATIVE_PPC_3,
-       /* relative address in an ARM B/BL instruction */
-       RC_RELATIVE_ARM_3,
-       /* pointer to address in an ARM LDR/STR instruction */
-       RC_INDIRECT_ARM,
-       /* pointer to address in an ARM LDR/STR instruction offset by 8 bytes */
-       RC_INDIRECT_ARM_PC
-};
-
-static const cell rel_absolute_ppc_2_mask = 0xffff;
-static const cell rel_relative_ppc_2_mask = 0xfffc;
-static const cell rel_relative_ppc_3_mask = 0x3fffffc;
-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;
-
-}
diff --git a/vm/code_blocks.cpp b/vm/code_blocks.cpp
new file mode 100755 (executable)
index 0000000..d33d468
--- /dev/null
@@ -0,0 +1,398 @@
+#include "master.hpp"
+
+namespace factor
+{
+
+void factor_vm::flush_icache_for(code_block *block)
+{
+       flush_icache((cell)block,block->size());
+}
+
+void *factor_vm::object_xt(cell obj)
+{
+       switch(tagged<object>(obj).type())
+       {
+       case WORD_TYPE:
+               return untag<word>(obj)->xt;
+       case QUOTATION_TYPE:
+               return untag<quotation>(obj)->xt;
+       default:
+               critical_error("Expected word or quotation",obj);
+               return NULL;
+       }
+}
+
+void *factor_vm::xt_pic(word *w, cell tagged_quot)
+{
+       if(!to_boolean(tagged_quot) || max_pic_size == 0)
+               return w->xt;
+       else
+       {
+               quotation *quot = untag<quotation>(tagged_quot);
+               if(quot->code)
+                       return quot->xt;
+               else
+                       return w->xt;
+       }
+}
+
+void *factor_vm::word_xt_pic(word *w)
+{
+       return xt_pic(w,w->pic_def);
+}
+
+void *factor_vm::word_xt_pic_tail(word *w)
+{
+       return xt_pic(w,w->pic_tail_def);
+}
+
+/* References to undefined symbols are patched up to call this function on
+image load */
+void factor_vm::undefined_symbol()
+{
+       general_error(ERROR_UNDEFINED_SYMBOL,false_object,false_object,NULL);
+}
+
+void undefined_symbol()
+{
+       return tls_vm()->undefined_symbol();
+}
+
+/* Look up an external library symbol referenced by a compiled code block */
+void *factor_vm::get_rel_symbol(array *literals, cell index)
+{
+       cell symbol = array_nth(literals,index);
+       cell library = array_nth(literals,index + 1);
+
+       dll *d = (to_boolean(library) ? untag<dll>(library) : NULL);
+
+       if(d != NULL && !d->dll)
+               return (void *)factor::undefined_symbol;
+
+       switch(tagged<object>(symbol).type())
+       {
+       case BYTE_ARRAY_TYPE:
+               {
+                       symbol_char *name = alien_offset(symbol);
+                       void *sym = ffi_dlsym(d,name);
+
+                       if(sym)
+                               return sym;
+                       else
+                       {
+                               return (void *)factor::undefined_symbol;
+                       }
+               }
+       case ARRAY_TYPE:
+               {
+                       array *names = untag<array>(symbol);
+                       for(cell i = 0; i < array_capacity(names); i++)
+                       {
+                               symbol_char *name = alien_offset(array_nth(names,i));
+                               void *sym = ffi_dlsym(d,name);
+
+                               if(sym)
+                                       return sym;
+                       }
+                       return (void *)factor::undefined_symbol;
+               }
+       default:
+               critical_error("Bad symbol specifier",symbol);
+               return (void *)factor::undefined_symbol;
+       }
+}
+
+cell factor_vm::compute_relocation(relocation_entry rel, cell index, code_block *compiled)
+{
+       array *literals = (to_boolean(compiled->literals)
+               ? untag<array>(compiled->literals) : NULL);
+       cell offset = rel.rel_offset() + (cell)compiled->xt();
+
+#define ARG array_nth(literals,index)
+
+       switch(rel.rel_type())
+       {
+       case RT_PRIMITIVE:
+               return (cell)primitives[untag_fixnum(ARG)];
+       case RT_DLSYM:
+               return (cell)get_rel_symbol(literals,index);
+       case RT_IMMEDIATE:
+               return ARG;
+       case RT_XT:
+               return (cell)object_xt(ARG);
+       case RT_XT_PIC:
+               return (cell)word_xt_pic(untag<word>(ARG));
+       case RT_XT_PIC_TAIL:
+               return (cell)word_xt_pic_tail(untag<word>(ARG));
+       case RT_HERE:
+       {
+               fixnum arg = untag_fixnum(ARG);
+               return (arg >= 0 ? offset + arg : (cell)(compiled + 1) - arg);
+       }
+       case RT_THIS:
+               return (cell)(compiled + 1);
+       case RT_CONTEXT:
+               return (cell)&ctx;
+       case RT_UNTAGGED:
+               return untag_fixnum(ARG);
+       case RT_MEGAMORPHIC_CACHE_HITS:
+               return (cell)&dispatch_stats.megamorphic_cache_hits;
+       case RT_VM:
+               return (cell)this + untag_fixnum(ARG);
+       case RT_CARDS_OFFSET:
+               return cards_offset;
+       case RT_DECKS_OFFSET:
+               return decks_offset;
+       default:
+               critical_error("Bad rel type",rel.rel_type());
+               return 0; /* Can't happen */
+       }
+
+#undef ARG
+}
+
+template<typename Iterator> void factor_vm::iterate_relocations(code_block *compiled, Iterator &iter)
+{
+       if(to_boolean(compiled->relocation))
+       {
+               byte_array *relocation = untag<byte_array>(compiled->relocation);
+
+               cell index = 0;
+               cell length = array_capacity(relocation) / sizeof(relocation_entry);
+
+               for(cell i = 0; i < length; i++)
+               {
+                       relocation_entry rel = relocation->data<relocation_entry>()[i];
+                       iter(rel,index,compiled);
+                       index += rel.number_of_parameters();
+               }
+       }
+}
+
+struct literal_references_updater {
+       factor_vm *parent;
+
+       explicit literal_references_updater(factor_vm *parent_) : parent(parent_) {}
+
+       void operator()(relocation_entry rel, cell index, code_block *compiled)
+       {
+               if(rel.rel_type() == RT_IMMEDIATE)
+               {
+                       embedded_pointer ptr(rel.rel_class(),rel.rel_offset() + (cell)(compiled + 1));
+                       array *literals = untag<array>(compiled->literals);
+                       ptr.store_address(array_nth(literals,index));
+               }
+       }
+};
+
+/* Update pointers to literals from compiled code. */
+void factor_vm::update_literal_references(code_block *compiled)
+{
+       if(!code->needs_fixup_p(compiled))
+       {
+               literal_references_updater updater(this);
+               iterate_relocations(compiled,updater);
+               flush_icache_for(compiled);
+       }
+}
+
+/* Compute an address to store at a relocation */
+void factor_vm::relocate_code_block_step(relocation_entry rel, cell index, code_block *compiled)
+{
+#ifdef FACTOR_DEBUG
+       if(to_boolean(compiled->literals))
+               tagged<array>(compiled->literals).untag_check(this);
+       if(to_boolean(compiled->relocation))
+               tagged<byte_array>(compiled->relocation).untag_check(this);
+#endif
+
+       embedded_pointer ptr(rel.rel_class(),rel.rel_offset() + (cell)compiled->xt());
+       ptr.store_address(compute_relocation(rel,index,compiled));
+}
+
+struct word_references_updater {
+       factor_vm *parent;
+
+       explicit word_references_updater(factor_vm *parent_) : parent(parent_) {}
+       void operator()(relocation_entry rel, cell index, code_block *compiled)
+       {
+               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);
+       }
+};
+
+/* Relocate new code blocks completely; updating references to literals,
+dlsyms, and words. For all other words in the code heap, we only need
+to update references to other words, without worrying about literals
+or dlsyms. */
+void factor_vm::update_word_references(code_block *compiled)
+{
+       if(code->needs_fixup_p(compiled))
+               relocate_code_block(compiled);
+       /* update_word_references() is always applied to every block in
+          the code heap. Since it resets all call sites to point to
+          their canonical XT (cold entry point for non-tail calls,
+          standard entry point for tail calls), it means that no PICs
+          are referenced after this is done. So instead of polluting
+          the code heap with dead PICs that will be freed on the next
+          GC, we add them to the free list immediately. */
+       else if(compiled->pic_p())
+               code->code_heap_free(compiled);
+       else
+       {
+               word_references_updater updater(this);
+               iterate_relocations(compiled,updater);
+               flush_icache_for(compiled);
+       }
+}
+
+/* This runs after a full collection */
+struct literal_and_word_references_updater {
+       factor_vm *parent;
+
+       explicit literal_and_word_references_updater(factor_vm *parent_) : parent(parent_) {}
+
+       void operator()(relocation_entry rel, cell index, code_block *compiled)
+       {
+               relocation_type type = rel.rel_type();
+
+               switch(type)
+               {
+               case RT_IMMEDIATE:
+               case RT_XT:
+               case RT_XT_PIC:
+               case RT_XT_PIC_TAIL:
+                       parent->relocate_code_block_step(rel,index,compiled);
+                       break;
+               default:
+                       break;
+               }
+       }
+};
+
+void factor_vm::update_code_block_words_and_literals(code_block *compiled)
+{
+       if(code->needs_fixup_p(compiled))
+               relocate_code_block(compiled);
+       else
+       {
+               literal_and_word_references_updater updater(this);
+               iterate_relocations(compiled,updater);
+               flush_icache_for(compiled);
+       }
+}
+
+void factor_vm::check_code_address(cell address)
+{
+#ifdef FACTOR_DEBUG
+       assert(address >= code->seg->start && address < code->seg->end);
+#endif
+}
+
+struct code_block_relocator {
+       factor_vm *parent;
+
+       explicit code_block_relocator(factor_vm *parent_) : parent(parent_) {}
+
+       void operator()(relocation_entry rel, cell index, code_block *compiled)
+       {
+               parent->relocate_code_block_step(rel,index,compiled);
+       }
+};
+
+/* Perform all fixups on a code block */
+void factor_vm::relocate_code_block(code_block *compiled)
+{
+       code->needs_fixup.erase(compiled);
+       code_block_relocator relocator(this);
+       iterate_relocations(compiled,relocator);
+       flush_icache_for(compiled);
+}
+
+/* Fixup labels. This is done at compile time, not image load time */
+void factor_vm::fixup_labels(array *labels, code_block *compiled)
+{
+       cell i;
+       cell size = array_capacity(labels);
+
+       for(i = 0; i < size; i += 3)
+       {
+               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));
+
+               embedded_pointer ptr(rel_class,offset + (cell)(compiled + 1));
+               ptr.store_address(target + (cell)(compiled + 1));
+       }
+}
+
+/* Might GC */
+code_block *factor_vm::allot_code_block(cell size, code_block_type type)
+{
+       code_block *block = code->allocator->allot(size + sizeof(code_block));
+
+       /* If allocation failed, do a full GC and compact the code heap.
+       A full GC that occurs as a result of the data heap filling up does not
+       trigger a compaction. This setup ensures that most GCs do not compact
+       the code heap, but if the code fills up, it probably means it will be
+       fragmented after GC anyway, so its best to compact. */
+       if(block == NULL)
+       {
+               primitive_compact_gc();
+               block = code->allocator->allot(size + sizeof(code_block));
+
+               /* Insufficient room even after code GC, give up */
+               if(block == NULL)
+               {
+                       std::cout << "Code heap used: " << code->allocator->occupied_space() << "\n";
+                       std::cout << "Code heap free: " << code->allocator->free_space() << "\n";
+                       fatal_error("Out of memory in add-compiled-block",0);
+               }
+       }
+
+       block->set_type(type);
+       return block;
+}
+
+/* Might GC */
+code_block *factor_vm::add_code_block(code_block_type type, cell code_, cell labels_, cell owner_, cell relocation_, cell literals_)
+{
+       data_root<byte_array> code(code_,this);
+       data_root<object> labels(labels_,this);
+       data_root<object> owner(owner_,this);
+       data_root<byte_array> relocation(relocation_,this);
+       data_root<array> literals(literals_,this);
+
+       cell code_length = array_capacity(code.untagged());
+       code_block *compiled = allot_code_block(code_length,type);
+
+       compiled->owner = owner.value();
+
+       /* slight space optimization */
+       if(relocation.type() == BYTE_ARRAY_TYPE && array_capacity(relocation.untagged()) == 0)
+               compiled->relocation = false_object;
+       else
+               compiled->relocation = relocation.value();
+
+       if(literals.type() == ARRAY_TYPE && array_capacity(literals.untagged()) == 0)
+               compiled->literals = false_object;
+       else
+               compiled->literals = literals.value();
+
+       /* code */
+       memcpy(compiled + 1,code.untagged() + 1,code_length);
+
+       /* fixup labels */
+       if(to_boolean(labels.value()))
+               fixup_labels(labels.as<array>().untagged(),compiled);
+
+       /* next time we do a minor GC, we have to scan the code heap for
+       literals */
+       this->code->write_barrier(compiled);
+       this->code->needs_fixup.insert(compiled);
+
+       return compiled;
+}
+
+}
diff --git a/vm/code_blocks.hpp b/vm/code_blocks.hpp
new file mode 100644 (file)
index 0000000..dad7178
--- /dev/null
@@ -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 (file)
index 0000000..8d368e5
--- /dev/null
@@ -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/embedded_pointers.hpp b/vm/embedded_pointers.hpp
new file mode 100644 (file)
index 0000000..6943589
--- /dev/null
@@ -0,0 +1,138 @@
+namespace factor
+{
+
+enum relocation_type {
+       /* arg is a primitive number */
+       RT_PRIMITIVE,
+       /* arg is a literal table index, holding an array pair (symbol/dll) */
+       RT_DLSYM,
+       /* a pointer to a compiled word reference */
+       RT_DISPATCH,
+       /* a word or quotation's general entry point */
+       RT_XT,
+       /* a word's PIC entry point */
+       RT_XT_PIC,
+       /* a word's tail-call PIC entry point */
+       RT_XT_PIC_TAIL,
+       /* current offset */
+       RT_HERE,
+       /* current code block */
+       RT_THIS,
+       /* immediate literal */
+       RT_IMMEDIATE,
+       /* address of ctx var */
+       RT_CONTEXT,
+       /* untagged fixnum literal */
+       RT_UNTAGGED,
+       /* address of megamorphic_cache_hits var */
+       RT_MEGAMORPHIC_CACHE_HITS,
+       /* address of vm object */
+       RT_VM,
+       /* value of vm->cards_offset */
+       RT_CARDS_OFFSET,
+       /* value of vm->decks_offset */
+       RT_DECKS_OFFSET,
+};
+
+enum relocation_class {
+       /* absolute address in a 64-bit location */
+       RC_ABSOLUTE_CELL,
+       /* absolute address in a 32-bit location */
+       RC_ABSOLUTE,
+       /* relative address in a 32-bit location */
+       RC_RELATIVE,
+       /* absolute address in a PowerPC LIS/ORI sequence */
+       RC_ABSOLUTE_PPC_2_2,
+       /* absolute address in a PowerPC LWZ instruction */
+       RC_ABSOLUTE_PPC_2,
+       /* relative address in a PowerPC LWZ/STW/BC instruction */
+       RC_RELATIVE_PPC_2,
+       /* relative address in a PowerPC B/BL instruction */
+       RC_RELATIVE_PPC_3,
+       /* relative address in an ARM B/BL instruction */
+       RC_RELATIVE_ARM_3,
+       /* pointer to address in an ARM LDR/STR instruction */
+       RC_INDIRECT_ARM,
+       /* pointer to address in an ARM LDR/STR instruction offset by 8 bytes */
+       RC_INDIRECT_ARM_PC
+};
+
+static const cell rel_absolute_ppc_2_mask = 0xffff;
+static const cell rel_relative_ppc_2_mask = 0xfffc;
+static const cell rel_relative_ppc_3_mask = 0x3fffffc;
+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 */
+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);
+};
+
+}
index e72e88bfdff70c6c45945cdbfc34bbfec1b32c49..2fe9384630958725f8d83663a2977849db9ff930 100644 (file)
@@ -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));
        }
 }
index 048c9c460f072e42d89a60b354772f246d0fc76c..b03a0d22444b7518090b04c63a295f94d954d2e2 100644 (file)
@@ -209,49 +209,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 {
index 23c70782dfe8a30557b5d86b2fc8d82683c39ac5..cfb71a47157e5390d3b1637c1c95a87a236992cc 100755 (executable)
@@ -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"
index af920fc6e2401b7bc4d4fb1b6de92f360fa6befc..908e0f3152ff77f6351876f6b361dd87e1bef006 100644 (file)
@@ -8,14 +8,18 @@ template<typename Visitor> struct slot_visitor {
        explicit slot_visitor<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<object>(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)
index 4f82e595989096b757657c28349a013663ece088..67997e859021b1686232aa0b984a46f1d0e00f3b 100755 (executable)
--- a/vm/vm.hpp
+++ b/vm/vm.hpp
@@ -496,11 +496,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);
@@ -509,9 +505,6 @@ struct factor_vm
        void *get_rel_symbol(array *literals, cell index);
        cell compute_relocation(relocation_entry rel, cell index, code_block *compiled);
        template<typename Iterator> 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);