Merge branch 'no_literal_table' of git://factorcode.org/git/factor into no_literal_table

db4
Slava Pestov 2009-11-27 18:33:34 -06:00
commit 333c7654ae
10 changed files with 295 additions and 244 deletions

View File

@ -40,7 +40,7 @@ SYMBOL: labels
V{ } clone calls set ;
: generate-insns ( asm -- code )
dup word>> [
dup label>> [
init-generator
instructions>> [
[ class insn-counts get inc-at ]

View File

@ -4,7 +4,7 @@ USING: arrays byte-arrays byte-vectors generic assocs hashtables
io.binary kernel kernel.private math namespaces make sequences
words quotations strings alien.accessors alien.strings layouts
system combinators math.bitwise math.order
accessors growable fry generalizations compiler.constants ;
accessors growable fry compiler.constants ;
IN: compiler.codegen.fixup
! Owner
@ -114,8 +114,7 @@ SYMBOL: relocation-table
init-fixup
@
label-table [ resolve-labels ] change
compiling-word get
literal-table get >array
relocation-table get >byte-array
label-table get
] B{ } make 5 narray ; inline
] B{ } make 4array ; inline

View File

@ -54,6 +54,8 @@ void code_block_visitor<Visitor>::visit_object_code_block(object *obj)
quotation *q = (quotation *)obj;
if(q->code)
parent->set_quot_xt(q,visitor(q->code));
else
q->xt = (void *)lazy_jit_compile;
break;
}
case CALLSTACK_TYPE:

View File

@ -3,42 +3,119 @@
namespace factor
{
void *factor_vm::object_xt(cell obj)
cell factor_vm::compute_primitive_relocation(cell arg)
{
return (cell)primitives[untag_fixnum(arg)];
}
/* 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 */
cell factor_vm::compute_dlsym_relocation(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 (cell)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 (cell)sym;
else
return (cell)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 (cell)sym;
}
return (cell)factor::undefined_symbol;
}
default:
critical_error("Bad symbol specifier",symbol);
return (cell)factor::undefined_symbol;
}
}
cell factor_vm::compute_xt_relocation(cell obj)
{
switch(tagged<object>(obj).type())
{
case WORD_TYPE:
return untag<word>(obj)->xt;
return (cell)untag<word>(obj)->xt;
case QUOTATION_TYPE:
return untag<quotation>(obj)->xt;
return (cell)untag<quotation>(obj)->xt;
default:
critical_error("Expected word or quotation",obj);
return NULL;
return 0;
}
}
void *factor_vm::xt_pic(word *w, cell tagged_quot)
cell factor_vm::compute_xt_pic_relocation(word *w, cell tagged_quot)
{
if(!to_boolean(tagged_quot) || max_pic_size == 0)
return w->xt;
return (cell)w->xt;
else
{
quotation *quot = untag<quotation>(tagged_quot);
if(quot->code)
return quot->xt;
return (cell)quot->xt;
else
return w->xt;
return (cell)w->xt;
}
}
void *factor_vm::word_xt_pic(word *w)
cell factor_vm::compute_xt_pic_relocation(cell w_)
{
return xt_pic(w,w->pic_def);
tagged<word> w(w_);
return compute_xt_pic_relocation(w.untagged(),w->pic_def);
}
void *factor_vm::word_xt_pic_tail(word *w)
cell factor_vm::compute_xt_pic_tail_relocation(cell w_)
{
return xt_pic(w,w->pic_tail_def);
tagged<word> w(w_);
return compute_xt_pic_relocation(w.untagged(),w->pic_tail_def);
}
cell factor_vm::compute_here_relocation(cell arg, cell offset, code_block *compiled)
{
fixnum n = untag_fixnum(arg);
return n >= 0 ? ((cell)compiled->xt() + offset + n) : ((cell)compiled->xt() - n);
}
cell factor_vm::compute_context_relocation()
{
return (cell)&ctx;
}
cell factor_vm::compute_vm_relocation(cell arg)
{
return (cell)this + untag_fixnum(arg);
}
cell factor_vm::code_block_owner(code_block *compiled)
@ -83,19 +160,19 @@ struct word_references_updater {
case RT_XT:
{
code_block *compiled = op.load_code_block();
op.store_value((cell)parent->object_xt(compiled->owner));
op.store_value(parent->compute_xt_relocation(compiled->owner));
break;
}
case RT_XT_PIC:
{
code_block *compiled = op.load_code_block();
op.store_value((cell)parent->word_xt_pic(untag<word>(parent->code_block_owner(compiled))));
op.store_value(parent->compute_xt_pic_relocation(parent->code_block_owner(compiled)));
break;
}
case RT_XT_PIC_TAIL:
{
code_block *compiled = op.load_code_block();
op.store_value((cell)parent->word_xt_pic_tail(untag<word>(parent->code_block_owner(compiled))));
op.store_value(parent->compute_xt_pic_tail_relocation(parent->code_block_owner(compiled)));
break;
}
default:
@ -129,97 +206,39 @@ void factor_vm::update_word_references(code_block *compiled)
}
}
/* 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)];
return compute_primitive_relocation(ARG);
case RT_DLSYM:
return (cell)get_rel_symbol(literals,index);
return compute_dlsym_relocation(literals,index);
case RT_IMMEDIATE:
return ARG;
case RT_XT:
return (cell)object_xt(ARG);
return compute_xt_relocation(ARG);
case RT_XT_PIC:
return (cell)word_xt_pic(untag<word>(ARG));
return compute_xt_pic_relocation(ARG);
case RT_XT_PIC_TAIL:
return (cell)word_xt_pic_tail(untag<word>(ARG));
return compute_xt_pic_tail_relocation(ARG);
case RT_HERE:
{
fixnum arg = untag_fixnum(ARG);
return (arg >= 0 ? offset + arg : (cell)compiled->xt() - arg);
}
return compute_here_relocation(ARG,rel.rel_offset(),compiled);
case RT_THIS:
return (cell)compiled->xt();
case RT_CONTEXT:
return (cell)&ctx;
return compute_context_relocation();
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);
return compute_vm_relocation(ARG);
case RT_CARDS_OFFSET:
return cards_offset;
case RT_DECKS_OFFSET:

View File

@ -113,17 +113,16 @@ void factor_vm::primitive_modify_code_heap()
case ARRAY_TYPE:
{
array *compiled_data = data.as<array>().untagged();
cell owner = array_nth(compiled_data,0);
cell literals = array_nth(compiled_data,1);
cell relocation = array_nth(compiled_data,2);
cell labels = array_nth(compiled_data,3);
cell code = array_nth(compiled_data,4);
cell literals = array_nth(compiled_data,0);
cell relocation = array_nth(compiled_data,1);
cell labels = array_nth(compiled_data,2);
cell code = array_nth(compiled_data,3);
code_block *compiled = add_code_block(
code_block_optimized,
code,
labels,
owner,
word.value(),
relocation,
literals);

View File

@ -55,177 +55,206 @@ void factor_vm::load_code_heap(FILE *file, image_header *h, vm_parameters *p)
code->allocator->initial_free_list(h->code_size);
}
void factor_vm::data_fixup(cell *handle, cell data_relocation_base)
{
if(immediate_p(*handle))
return;
struct data_fixupper {
cell offset;
*handle += (data->tenured->start - data_relocation_base);
}
explicit data_fixupper(cell offset_) : offset(offset_) {}
template<typename Type> void factor_vm::code_fixup(Type **handle, cell code_relocation_base)
{
Type *ptr = *handle;
Type *new_ptr = (Type *)(((cell)ptr) + (code->seg->start - code_relocation_base));
*handle = new_ptr;
}
void factor_vm::fixup_word(word *word, cell code_relocation_base)
{
if(word->code)
code_fixup(&word->code,code_relocation_base);
if(word->profiling)
code_fixup(&word->profiling,code_relocation_base);
code_fixup(&word->xt,code_relocation_base);
}
void factor_vm::fixup_quotation(quotation *quot, cell code_relocation_base)
{
if(quot->code)
object *operator()(object *obj)
{
code_fixup(&quot->xt,code_relocation_base);
code_fixup(&quot->code,code_relocation_base);
}
else
quot->xt = (void *)lazy_jit_compile;
}
void factor_vm::fixup_alien(alien *ptr)
{
if(!to_boolean(ptr->base))
ptr->expired = true_object;
else
ptr->update_address();
}
struct stack_frame_fixupper {
factor_vm *parent;
cell code_relocation_base;
explicit stack_frame_fixupper(factor_vm *parent_, cell code_relocation_base_) :
parent(parent_), code_relocation_base(code_relocation_base_) {}
void operator()(stack_frame *frame)
{
parent->code_fixup(&frame->xt,code_relocation_base);
parent->code_fixup(&FRAME_RETURN_ADDRESS(frame,parent),code_relocation_base);
return (object *)((char *)obj + offset);
}
};
void factor_vm::fixup_callstack_object(callstack *stack, cell code_relocation_base)
struct code_fixupper {
cell offset;
explicit code_fixupper(cell offset_) : offset(offset_) {}
code_block *operator()(code_block *compiled)
{
return (code_block *)((char *)compiled + offset);
}
};
static inline cell tuple_size_with_fixup(cell offset, object *obj)
{
stack_frame_fixupper fixupper(this,code_relocation_base);
iterate_callstack_object(stack,fixupper);
tuple_layout *layout = (tuple_layout *)((char *)UNTAG(((tuple *)obj)->layout) + offset);
return tuple_size(layout);
}
struct fixup_sizer {
cell offset;
explicit fixup_sizer(cell offset_) : offset(offset_) {}
cell operator()(object *obj)
{
if(obj->type() == TUPLE_TYPE)
return align(tuple_size_with_fixup(offset,obj),data_alignment);
else
return obj->size();
}
};
struct object_fixupper {
factor_vm *parent;
cell data_relocation_base;
cell data_offset;
slot_visitor<data_fixupper> data_visitor;
code_block_visitor<code_fixupper> code_visitor;
explicit object_fixupper(factor_vm *parent_, cell data_relocation_base_) :
parent(parent_), data_relocation_base(data_relocation_base_) { }
object_fixupper(factor_vm *parent_, cell data_offset_, cell code_offset_) :
parent(parent_),
data_offset(data_offset_),
data_visitor(slot_visitor<data_fixupper>(parent_,data_fixupper(data_offset_))),
code_visitor(code_block_visitor<code_fixupper>(parent_,code_fixupper(code_offset_))) {}
void operator()(cell *scan)
void operator()(object *obj, cell size)
{
parent->data_fixup(scan,data_relocation_base);
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(!parent->to_boolean(ptr->base))
ptr->expired = parent->true_object;
else
ptr->update_address();
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;
}
}
}
};
/* Initialize an object in a newly-loaded image */
void factor_vm::relocate_object(object *object,
cell data_relocation_base,
cell code_relocation_base)
void factor_vm::fixup_data(cell data_offset, cell code_offset)
{
cell type = object->type();
slot_visitor<data_fixupper> data_workhorse(this,data_fixupper(data_offset));
data_workhorse.visit_roots();
object_fixupper fixupper(this,data_offset,code_offset);
fixup_sizer sizer(data_offset);
data->tenured->iterate(fixupper,sizer);
}
struct code_block_updater {
factor_vm *parent;
cell code_offset;
slot_visitor<data_fixupper> data_visitor;
code_fixupper code_visitor;
code_block_updater(factor_vm *parent_, cell data_offset_, cell code_offset_) :
parent(parent_),
code_offset(code_offset_),
data_visitor(slot_visitor<data_fixupper>(parent_,data_fixupper(data_offset_))),
code_visitor(code_fixupper(code_offset_)) {}
void operator()(relocation_entry rel, cell index, code_block *compiled)
{
relocation_type type = rel.rel_type();
instruction_operand op(rel.rel_class(),rel.rel_offset() + (cell)compiled->xt());
/* Tuple relocation is a bit trickier; we have to fix up the
layout object before we can get the tuple size, so each_slot is
out of the question */
if(type == TUPLE_TYPE)
{
tuple *t = (tuple *)object;
data_fixup(&t->layout,data_relocation_base);
array *literals = (parent->to_boolean(compiled->literals)
? untag<array>(compiled->literals) : NULL);
cell *scan = t->data();
cell *end = (cell *)((cell)object + object->size());
for(; scan < end; scan++)
data_fixup(scan,data_relocation_base);
}
else
{
object_fixupper fixupper(this,data_relocation_base);
object->each_slot(fixupper);
cell old_offset = (cell)compiled - code_offset;
switch(type)
{
case WORD_TYPE:
fixup_word((word *)object,code_relocation_base);
case RT_IMMEDIATE:
op.store_value(data_visitor.visit_pointer(op.load_value(old_offset)));
break;
case QUOTATION_TYPE:
fixup_quotation((quotation *)object,code_relocation_base);
case RT_XT:
case RT_XT_PIC:
case RT_XT_PIC_TAIL:
op.store_code_block(code_visitor(op.load_code_block(old_offset)));
break;
case DLL_TYPE:
ffi_dlopen((dll *)object);
case RT_PRIMITIVE:
op.store_value(parent->compute_primitive_relocation(array_nth(literals,index)));
break;
case ALIEN_TYPE:
fixup_alien((alien *)object);
case RT_DLSYM:
op.store_value(parent->compute_dlsym_relocation(literals,index));
break;
case CALLSTACK_TYPE:
fixup_callstack_object((callstack *)object,code_relocation_base);
case RT_HERE:
op.store_value(parent->compute_here_relocation(array_nth(literals,index),rel.rel_offset(),compiled));
break;
case RT_THIS:
op.store_value((cell)compiled->xt());
break;
case RT_CONTEXT:
op.store_value(parent->compute_context_relocation());
break;
case RT_UNTAGGED:
op.store_value(untag_fixnum(array_nth(literals,index)));
case RT_MEGAMORPHIC_CACHE_HITS:
op.store_value((cell)&parent->dispatch_stats.megamorphic_cache_hits);
break;
case RT_VM:
op.store_value(parent->compute_vm_relocation(array_nth(literals,index)));
break;
case RT_CARDS_OFFSET:
op.store_value(parent->cards_offset);
break;
case RT_DECKS_OFFSET:
op.store_value(parent->decks_offset);
break;
default:
critical_error("Bad rel type",rel.rel_type());
break;
}
}
}
/* Since the image might have been saved with a different base address than
where it is loaded, we need to fix up pointers in the image. */
void factor_vm::relocate_data(cell data_relocation_base, cell code_relocation_base)
{
for(cell i = 0; i < special_object_count; i++)
data_fixup(&special_objects[i],data_relocation_base);
data_fixup(&true_object,data_relocation_base);
data_fixup(&bignum_zero,data_relocation_base);
data_fixup(&bignum_pos_one,data_relocation_base);
data_fixup(&bignum_neg_one,data_relocation_base);
cell obj = data->tenured->start;
while(obj)
{
relocate_object((object *)obj,data_relocation_base,code_relocation_base);
data->tenured->starts.record_object_start_offset((object *)obj);
obj = data->tenured->next_object_after(obj);
}
}
void factor_vm::fixup_code_block(code_block *compiled, cell data_relocation_base)
{
/* relocate literal table data */
data_fixup(&compiled->owner,data_relocation_base);
data_fixup(&compiled->literals,data_relocation_base);
data_fixup(&compiled->relocation,data_relocation_base);
relocate_code_block(compiled);
}
};
struct code_block_fixupper {
factor_vm *parent;
cell data_relocation_base;
cell data_offset;
cell code_offset;
explicit code_block_fixupper(factor_vm *parent_, cell data_relocation_base_) :
parent(parent_), data_relocation_base(data_relocation_base_) { }
code_block_fixupper(factor_vm *parent_, cell data_offset_, cell code_offset_) :
parent(parent_),
data_offset(data_offset_),
code_offset(code_offset_) {}
void operator()(code_block *compiled, cell size)
{
parent->fixup_code_block(compiled,data_relocation_base);
slot_visitor<data_fixupper> data_visitor(parent,data_fixupper(data_offset));
data_visitor.visit_code_block_objects(compiled);
code_block_updater updater(parent,data_offset,code_offset);
parent->iterate_relocations(compiled,updater);
}
};
void factor_vm::relocate_code(cell data_relocation_base)
void factor_vm::fixup_code(cell data_offset, cell code_offset)
{
code_block_fixupper fixupper(this,data_relocation_base);
iterate_code_heap(fixupper);
code_block_fixupper fixupper(this,data_offset,code_offset);
code->allocator->iterate(fixupper);
}
/* Read an image file from disk, only done once during startup */
@ -257,8 +286,11 @@ void factor_vm::load_image(vm_parameters *p)
init_objects(&h);
relocate_data(h.data_relocation_base,h.code_relocation_base);
relocate_code(h.data_relocation_base);
cell data_offset = data->tenured->start - h.data_relocation_base;
cell code_offset = code->seg->start - h.code_relocation_base;
fixup_data(data_offset,code_offset);
fixup_code(data_offset,code_offset);
/* Store image path name */
special_objects[OBJ_IMAGE] = allot_alien(false_object,(cell)p->image_path);

View File

@ -55,9 +55,14 @@ fixnum instruction_operand::load_value()
return load_value(pointer);
}
code_block *instruction_operand::load_code_block(cell relative_to)
{
return ((code_block *)load_value(relative_to) - 1);
}
code_block *instruction_operand::load_code_block()
{
return ((code_block *)load_value() - 1);
return load_code_block(pointer);
}
/* Store a 32-bit value into a PowerPC LIS/ORI sequence */

View File

@ -130,6 +130,7 @@ struct instruction_operand {
fixnum load_value_masked(cell mask, fixnum shift);
fixnum load_value(cell relative_to);
fixnum load_value();
code_block *load_code_block(cell relative_to);
code_block *load_code_block();
void store_value_2_2(fixnum value);

View File

@ -135,9 +135,7 @@ struct literal_references_visitor {
if(rel.rel_type() == RT_IMMEDIATE)
{
instruction_operand op(rel.rel_class(),rel.rel_offset() + (cell)compiled->xt());
cell literal = op.load_value();
literal = visitor->visit_pointer(literal);
op.store_value(literal);
op.store_value(visitor->visit_pointer(op.load_value()));
}
}
};

View File

@ -500,14 +500,17 @@ struct factor_vm
void primitive_fclose();
//code_block
void *object_xt(cell obj);
void *xt_pic(word *w, cell tagged_quot);
void *word_xt_pic(word *w);
void *word_xt_pic_tail(word *w);
cell code_block_owner(code_block *compiled);
cell compute_primitive_relocation(cell arg);
void undefined_symbol();
void *get_rel_symbol(array *literals, cell index);
cell compute_relocation(relocation_entry rel, cell index, code_block *compiled);
cell compute_dlsym_relocation(array *literals, cell index);
cell compute_xt_relocation(cell obj);
cell compute_xt_pic_relocation(word *w, cell tagged_quot);
cell compute_xt_pic_relocation(cell w_);
cell compute_xt_pic_tail_relocation(cell w_);
cell compute_here_relocation(cell arg, cell offset, code_block *compiled);
cell compute_context_relocation();
cell compute_vm_relocation(cell arg);
cell code_block_owner(code_block *compiled);
template<typename Iterator> void iterate_relocations(code_block *compiled, Iterator &iter)
{
@ -528,6 +531,7 @@ struct factor_vm
}
void update_word_references(code_block *compiled);
cell compute_relocation(relocation_entry rel, cell index, code_block *compiled);
void check_code_address(cell address);
void relocate_code_block(code_block *compiled);
void fixup_labels(array *labels, code_block *compiled);
@ -567,16 +571,8 @@ struct factor_vm
bool save_image(const vm_char *filename);
void primitive_save_image();
void primitive_save_image_and_exit();
void data_fixup(cell *handle, cell data_relocation_base);
template<typename Type> void code_fixup(Type **handle, cell code_relocation_base);
void fixup_word(word *word, cell code_relocation_base);
void fixup_quotation(quotation *quot, cell code_relocation_base);
void fixup_alien(alien *d);
void fixup_callstack_object(callstack *stack, cell code_relocation_base);
void relocate_object(object *object, cell data_relocation_base, cell code_relocation_base);
void relocate_data(cell data_relocation_base, cell code_relocation_base);
void fixup_code_block(code_block *compiled, cell data_relocation_base);
void relocate_code(cell data_relocation_base);
void fixup_data(cell data_offset, cell code_offset);
void fixup_code(cell data_offset, cell code_offset);
void load_image(vm_parameters *p);
//callstack