vm: eliminating literal table work in progress

db4
Slava Pestov 2009-11-07 16:16:09 -06:00
parent 43e08c76fb
commit 57c541ea46
11 changed files with 268 additions and 187 deletions

View File

@ -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 \

View 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);
}

View File

@ -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<object>(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<array>(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<typename Iterator> void factor_vm::iterate_relocations(code_block *comp
{
relocation_entry rel = relocation->data<relocation_entry>()[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<array>(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<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));
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));
}
}

48
vm/code_blocks.hpp Normal file
View File

@ -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);
}
};
}

116
vm/embedded_pointers.cpp Normal file
View File

@ -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;
}
}
}

View File

@ -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);
};
}

View 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));
}
}

View File

@ -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 {

View File

@ -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"

View 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)

View File

@ -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<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);