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 \
vm/gc.o \
vm/image.o \
vm/inline_cache.o \
+ vm/instruction_operands.o \
vm/io.o \
vm/jit.o \
vm/math.o \
to_tenured_collector collector(this);
- current_gc->event->started_code_scan();
+ current_gc->event->started_card_scan();
collector.trace_cards(data->tenured,
card_points_to_aging,
full_unmarker());
cell rel_class = untag_fixnum(array_nth(code_template.untagged(),1));
cell offset = untag_fixnum(array_nth(code_template.untagged(),3));
- embedded_pointer ptr(rel_class,offset + (cell)(stub + 1));
- ptr.store_address((cell)(stub->compiled + 1));
+ instruction_operand op(rel_class,offset + (cell)(stub + 1));
+ op.store_value((cell)(stub->compiled + 1));
flush_icache((cell)stub,stub->size);
}
namespace factor
{
-template<typename Visitor> struct call_frame_code_block_visitor {
+template<typename Visitor> struct code_block_visitor {
+ factor_vm *parent;
+ Visitor visitor;
+
+ explicit code_block_visitor(factor_vm *parent_, Visitor visitor_) :
+ parent(parent_), visitor(visitor_) {}
+
+ void visit_object_code_block(object *obj);
+ void visit_referenced_code_blocks(code_block *compiled);
+ void visit_context_code_blocks();
+ void visit_callback_code_blocks();
+};
+
+template<typename Visitor>
+struct call_frame_code_block_visitor {
factor_vm *parent;
Visitor visitor;
}
};
-template<typename Visitor> struct callback_code_block_visitor {
- callback_heap *callbacks;
- Visitor visitor;
-
- explicit callback_code_block_visitor(callback_heap *callbacks_, Visitor visitor_) :
- callbacks(callbacks_), visitor(visitor_) {}
-
- void operator()(callback *stub)
+template<typename Visitor>
+void code_block_visitor<Visitor>::visit_object_code_block(object *obj)
+{
+ switch(obj->type())
{
- stub->compiled = visitor(stub->compiled);
- callbacks->update(stub);
+ case WORD_TYPE:
+ {
+ word *w = (word *)obj;
+ if(w->code)
+ w->code = visitor(w->code);
+ if(w->profiling)
+ w->profiling = visitor(w->profiling);
+
+ parent->update_word_xt(w);
+ break;
+ }
+ case QUOTATION_TYPE:
+ {
+ quotation *q = (quotation *)obj;
+ if(q->code)
+ parent->set_quot_xt(q,visitor(q->code));
+ break;
+ }
+ case CALLSTACK_TYPE:
+ {
+ callstack *stack = (callstack *)obj;
+ call_frame_code_block_visitor<Visitor> call_frame_visitor(parent,visitor);
+ parent->iterate_callstack_object(stack,call_frame_visitor);
+ break;
+ }
}
-};
+}
-template<typename Visitor> struct code_block_visitor {
- factor_vm *parent;
+template<typename Visitor>
+struct referenced_code_blocks_visitor {
Visitor visitor;
- explicit code_block_visitor(factor_vm *parent_, Visitor visitor_) :
- parent(parent_), visitor(visitor_) {}
+ explicit referenced_code_blocks_visitor(Visitor visitor_) : visitor(visitor_) {}
- void visit_object_code_block(object *obj)
+ void operator()(relocation_entry rel, cell index, code_block *compiled)
{
- switch(obj->type())
+ relocation_type type = rel.rel_type();
+ if(type == RT_XT || type == RT_XT_PIC || type == RT_XT_PIC_TAIL)
{
- case WORD_TYPE:
- {
- word *w = (word *)obj;
- if(w->code)
- w->code = visitor(w->code);
- if(w->profiling)
- w->profiling = visitor(w->profiling);
-
- parent->update_word_xt(w);
- break;
- }
- case QUOTATION_TYPE:
- {
- quotation *q = (quotation *)obj;
- if(q->code)
- parent->set_quot_xt(q,visitor(q->code));
- break;
- }
- case CALLSTACK_TYPE:
- {
- callstack *stack = (callstack *)obj;
- call_frame_code_block_visitor<Visitor> call_frame_visitor(parent,visitor);
- parent->iterate_callstack_object(stack,call_frame_visitor);
- break;
- }
+ instruction_operand op(rel.rel_class(),rel.rel_offset() + (cell)(compiled + 1));
+ cell literal = op.load_value();
+ code_block *compiled = ((code_block *)literal - 1);
+ compiled = visitor(compiled);
+ literal = (cell)compiled->xt();
+ op.store_value(literal);
}
}
+};
- void visit_context_code_blocks()
+template<typename Visitor>
+void code_block_visitor<Visitor>::visit_referenced_code_blocks(code_block *compiled)
+{
+ if(!parent->code->needs_fixup_p(compiled))
{
- call_frame_code_block_visitor<Visitor> call_frame_visitor(parent,visitor);
- parent->iterate_active_frames(call_frame_visitor);
+ referenced_code_blocks_visitor<Visitor> visitor(this->visitor);
+ parent->iterate_relocations(compiled,visitor);
}
+}
+
+template<typename Visitor>
+void code_block_visitor<Visitor>::visit_context_code_blocks()
+{
+ call_frame_code_block_visitor<Visitor> call_frame_visitor(parent,visitor);
+ parent->iterate_active_frames(call_frame_visitor);
+}
- void visit_callback_code_blocks()
+template<typename Visitor>
+struct callback_code_block_visitor {
+ callback_heap *callbacks;
+ Visitor visitor;
+
+ explicit callback_code_block_visitor(callback_heap *callbacks_, Visitor visitor_) :
+ callbacks(callbacks_), visitor(visitor_) {}
+
+ void operator()(callback *stub)
{
- callback_code_block_visitor<Visitor> callback_visitor(parent->callbacks,visitor);
- parent->callbacks->iterate(callback_visitor);
+ stub->compiled = visitor(stub->compiled);
+ callbacks->update(stub);
}
-
};
+template<typename Visitor>
+void code_block_visitor<Visitor>::visit_callback_code_blocks()
+{
+ callback_code_block_visitor<Visitor> callback_visitor(parent->callbacks,visitor);
+ parent->callbacks->iterate(callback_visitor);
+}
+
}
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));
+ instruction_operand op(rel.rel_class(),rel.rel_offset() + (cell)compiled->xt());
+ op.store_value(compute_relocation(rel,index,compiled));
}
struct word_references_updater {
}
}
-/* 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
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));
+ instruction_operand op(rel_class,offset + (cell)(compiled + 1));
+ op.store_value(target + (cell)(compiled + 1));
}
}
iterate_code_heap(updater);
}
-/* After a full GC that did not grow the heap, we have to update references
-to literals and other words. */
-struct word_and_literal_code_heap_updater {
- factor_vm *parent;
-
- explicit word_and_literal_code_heap_updater(factor_vm *parent_) : parent(parent_) {}
-
- void operator()(code_block *block, cell size)
- {
- parent->update_code_block_words_and_literals(block);
- }
-};
-
-void factor_vm::update_code_heap_words_and_literals()
-{
- word_and_literal_code_heap_updater updater(this);
- iterate_code_heap(updater);
-}
-
/* After growing the heap, we have to perform a full relocation to update
references to card and deck arrays. */
struct code_heap_relocator {
namespace factor
{
-template<typename TargetGeneration, typename Policy> struct collector_workhorse {
+template<typename TargetGeneration, typename Policy> struct data_workhorse {
factor_vm *parent;
TargetGeneration *target;
Policy policy;
- explicit collector_workhorse(factor_vm *parent_, TargetGeneration *target_, Policy policy_) :
+ explicit data_workhorse(factor_vm *parent_, TargetGeneration *target_, Policy policy_) :
parent(parent_),
target(target_),
policy(policy_) {}
};
template<typename TargetGeneration, typename Policy>
-inline static slot_visitor<collector_workhorse<TargetGeneration,Policy> > make_collector_workhorse(
+inline static slot_visitor<data_workhorse<TargetGeneration,Policy> > make_data_visitor(
factor_vm *parent,
TargetGeneration *target,
Policy policy)
{
- return slot_visitor<collector_workhorse<TargetGeneration,Policy> >(parent,
- collector_workhorse<TargetGeneration,Policy>(parent,target,policy));
+ return slot_visitor<data_workhorse<TargetGeneration,Policy> >(parent,
+ data_workhorse<TargetGeneration,Policy>(parent,target,policy));
}
struct dummy_unmarker {
void operator()(card *ptr) { *ptr = 0; }
};
-template<typename TargetGeneration, typename Policy> struct collector {
+template<typename TargetGeneration, typename Policy>
+struct collector {
factor_vm *parent;
data_heap *data;
code_heap *code;
TargetGeneration *target;
- slot_visitor<collector_workhorse<TargetGeneration,Policy> > workhorse;
+ slot_visitor<data_workhorse<TargetGeneration,Policy> > data_visitor;
cell cards_scanned;
cell decks_scanned;
cell code_blocks_scanned;
data(parent_->data),
code(parent_->code),
target(target_),
- workhorse(make_collector_workhorse(parent_,target_,policy_)),
+ data_visitor(make_data_visitor(parent_,target_,policy_)),
cards_scanned(0),
decks_scanned(0),
code_blocks_scanned(0) {}
void trace_handle(cell *handle)
{
- workhorse.visit_handle(handle);
+ data_visitor.visit_handle(handle);
}
void trace_object(object *ptr)
{
- workhorse.visit_slots(ptr);
+ data_visitor.visit_slots(ptr);
if(ptr->type() == ALIEN_TYPE)
((alien *)ptr)->update_address();
}
void trace_roots()
{
- workhorse.visit_roots();
+ data_visitor.visit_roots();
}
void trace_contexts()
{
- workhorse.visit_contexts();
+ data_visitor.visit_contexts();
}
/* Trace all literals referenced from a code block. Only for aging and nursery collections */
- void trace_literal_references(code_block *compiled)
+ void trace_referenced_literals(code_block *compiled)
{
- workhorse.visit_literal_references(compiled);
+ data_visitor.visit_referenced_literals(compiled);
}
void trace_code_heap_roots(std::set<code_block *> *remembered_set)
for(; iter != end; iter++)
{
- trace_literal_references(*iter);
+ trace_referenced_literals(*iter);
code_blocks_scanned++;
}
}
cell *end_ptr = (cell *)end;
for(; slot_ptr < end_ptr; slot_ptr++)
- workhorse.visit_handle(slot_ptr);
+ data_visitor.visit_handle(slot_ptr);
}
}
void operator()(code_block *old_address, code_block *new_address, cell size)
{
memmove(new_address,old_address,size);
- slot_forwarder.visit_literal_references(new_address);
+ slot_forwarder.visit_referenced_literals(new_address);
parent->relocate_code_block(new_address);
}
};
};
struct dummy_slot_forwarder {
- void visit_literal_references(code_block *compiled) {}
+ void visit_referenced_literals(code_block *compiled) {}
};
/* Compact just the code heap */
room.tenured_free_block_count = data->tenured->free_block_count();
room.cards = data->cards_end - data->cards;
room.decks = data->decks_end - data->decks;
- room.mark_stack = data->tenured->mark_stack.capacity() * sizeof(cell);
+ room.mark_stack = mark_stack.capacity() * sizeof(cell);
return room;
}
+++ /dev/null
-#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;
- }
-}
-
-}
+++ /dev/null
-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);
-};
-
-}
namespace factor
{
+inline static code_block_visitor<code_workhorse> make_code_visitor(factor_vm *parent)
+{
+ return code_block_visitor<code_workhorse>(parent,code_workhorse(parent));
+}
+
full_collector::full_collector(factor_vm *parent_) :
collector<tenured_space,full_policy>(
parent_,
parent_->data->tenured,
- full_policy(parent_)) {}
+ full_policy(parent_)),
+ code_visitor(make_code_visitor(parent_)) {}
+
+void full_collector::trace_code_block(code_block *compiled)
+{
+ data_visitor.visit_referenced_literals(compiled);
+ code_visitor.visit_referenced_code_blocks(compiled);
+}
+
+void full_collector::trace_context_code_blocks()
+{
+ code_visitor.visit_context_code_blocks();
+}
+
+void full_collector::trace_callback_code_blocks()
+{
+ code_visitor.visit_callback_code_blocks();
+}
+
+void full_collector::trace_object_code_block(object *obj)
+{
+ code_visitor.visit_object_code_block(obj);
+}
/* After a sweep, invalidate any code heap roots which are not marked,
so that if a block makes a tail call to a generic word, and the PIC
}
}
-struct code_block_marker {
- code_heap *code;
- full_collector *collector;
-
- explicit code_block_marker(code_heap *code_, full_collector *collector_) :
- code(code_), collector(collector_) {}
-
- code_block *operator()(code_block *compiled)
- {
- if(!code->marked_p(compiled))
- {
- code->set_marked_p(compiled);
- collector->trace_literal_references(compiled);
- }
-
- return compiled;
- }
-};
-
void factor_vm::collect_mark_impl(bool trace_contexts_p)
{
full_collector collector(this);
+ mark_stack.clear();
+
code->clear_mark_bits();
data->tenured->clear_mark_bits();
- data->tenured->clear_mark_stack();
-
- code_block_visitor<code_block_marker> code_marker(this,code_block_marker(code,&collector));
collector.trace_roots();
if(trace_contexts_p)
{
collector.trace_contexts();
- code_marker.visit_context_code_blocks();
- code_marker.visit_callback_code_blocks();
+ collector.trace_context_code_blocks();
+ collector.trace_callback_code_blocks();
}
- std::vector<object *> *mark_stack = &data->tenured->mark_stack;
-
- while(!mark_stack->empty())
+ while(!mark_stack.empty())
{
- object *obj = mark_stack->back();
- mark_stack->pop_back();
- collector.trace_object(obj);
- code_marker.visit_object_code_block(obj);
+ cell ptr = mark_stack.back();
+ mark_stack.pop_back();
+
+ if(ptr & 1)
+ {
+ code_block *compiled = (code_block *)(ptr - 1);
+ collector.trace_code_block(compiled);
+ }
+ else
+ {
+ object *obj = (object *)ptr;
+ collector.trace_object(obj);
+ collector.trace_object_code_block(obj);
+ }
}
data->reset_generation(data->tenured);
current_gc->event->op = collect_compact_op;
collect_compact_impl(trace_contexts_p);
}
- else
- update_code_heap_words_and_literals();
}
void factor_vm::collect_compact(bool trace_contexts_p)
void promoted_object(object *obj)
{
- tenured->mark_and_push(obj);
+ tenured->set_marked_p(obj);
+ parent->mark_stack.push_back((cell)obj);
}
void visited_object(object *obj)
{
if(!tenured->marked_p(obj))
- tenured->mark_and_push(obj);
+ promoted_object(obj);
+ }
+};
+
+struct code_workhorse {
+ factor_vm *parent;
+ code_heap *code;
+
+ explicit code_workhorse(factor_vm *parent_) : parent(parent_), code(parent->code) {}
+
+ code_block *operator()(code_block *compiled)
+ {
+ if(!code->marked_p(compiled))
+ {
+ code->set_marked_p(compiled);
+ parent->mark_stack.push_back((cell)compiled + 1);
+ }
+
+ return compiled;
}
};
struct full_collector : collector<tenured_space,full_policy> {
- bool trace_contexts_p;
+ code_block_visitor<code_workhorse> code_visitor;
explicit full_collector(factor_vm *parent_);
+ void trace_code_block(code_block *compiled);
+ void trace_context_code_blocks();
+ void trace_callback_code_blocks();
+ void trace_object_code_block(object *obj);
};
}
--- /dev/null
+#include "master.hpp"
+
+namespace factor
+{
+
+/* Load a 32-bit value from a PowerPC LIS/ORI sequence */
+fixnum instruction_operand::load_value_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 instruction_operand::load_value_masked(cell mask, fixnum shift)
+{
+ cell *ptr = (cell *)pointer;
+
+ return (*ptr & mask) << shift;
+}
+
+fixnum instruction_operand::load_value()
+{
+ switch(rel_class)
+ {
+ case RC_ABSOLUTE_CELL:
+ return *(cell *)pointer;
+ case RC_ABSOLUTE:
+ return *(u32*)pointer;
+ case RC_RELATIVE:
+ return *(s32*)pointer + pointer + sizeof(u32);
+ case RC_ABSOLUTE_PPC_2_2:
+ return load_value_2_2();
+ case RC_ABSOLUTE_PPC_2:
+ return load_value_masked(rel_absolute_ppc_2_mask,0);
+ case RC_RELATIVE_PPC_2:
+ return load_value_masked(rel_relative_ppc_2_mask,0) + pointer;
+ case RC_RELATIVE_PPC_3:
+ return load_value_masked(rel_relative_ppc_3_mask,0) + pointer;
+ case RC_RELATIVE_ARM_3:
+ return load_value_masked(rel_relative_arm_3_mask,2) + pointer + sizeof(cell) * 2;
+ case RC_INDIRECT_ARM:
+ return load_value_masked(rel_indirect_arm_mask,0) + pointer + sizeof(cell);
+ case RC_INDIRECT_ARM_PC:
+ return load_value_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 instruction_operand::store_value_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 instruction_operand::store_value_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 instruction_operand::store_value(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:
+ *(s32*)pointer = relative_value - sizeof(u32);
+ break;
+ case RC_ABSOLUTE_PPC_2_2:
+ store_value_2_2(absolute_value);
+ break;
+ case RC_ABSOLUTE_PPC_2:
+ store_value_masked(absolute_value,rel_absolute_ppc_2_mask,0);
+ break;
+ case RC_RELATIVE_PPC_2:
+ store_value_masked(relative_value,rel_relative_ppc_2_mask,0);
+ break;
+ case RC_RELATIVE_PPC_3:
+ store_value_masked(relative_value,rel_relative_ppc_3_mask,0);
+ break;
+ case RC_RELATIVE_ARM_3:
+ store_value_masked(relative_value - sizeof(cell) * 2,rel_relative_arm_3_mask,2);
+ break;
+ case RC_INDIRECT_ARM:
+ store_value_masked(relative_value - sizeof(cell),rel_indirect_arm_mask,0);
+ break;
+ case RC_INDIRECT_ARM_PC:
+ store_value_masked(relative_value - sizeof(cell) * 2,rel_indirect_arm_mask,0);
+ break;
+ default:
+ critical_error("Bad rel class",rel_class);
+ break;
+ }
+}
+
+}
--- /dev/null
+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 instruction_operand {
+ cell rel_class;
+ cell pointer;
+
+ instruction_operand(cell rel_class_, cell pointer_) :
+ rel_class(rel_class_), pointer(pointer_) {}
+
+ fixnum load_value_2_2();
+ fixnum load_value_masked(cell mask, fixnum shift);
+ fixnum load_value();
+
+ void store_value_2_2(fixnum value);
+ void store_value_masked(fixnum value, cell mask, fixnum shift);
+ void store_value(fixnum value);
+};
+
+}
#include "errors.hpp"
#include "bignumint.hpp"
#include "bignum.hpp"
-#include "embedded_pointers.hpp"
+#include "instruction_operands.hpp"
#include "code_blocks.hpp"
#include "bump_allocator.hpp"
#include "bitwise_hacks.hpp"
by referencing the old quotation unless we recompile all
unoptimized words. */
compile_all_words();
-
- /* Update references to old objects in the code heap */
- update_code_heap_words_and_literals();
+ update_code_heap_words();
}
}
void visit_bignum_roots();
void visit_roots();
void visit_contexts();
- void visit_literal_references(code_block *compiled);
+ void visit_referenced_literals(code_block *compiled);
};
template<typename Visitor>
template<typename Visitor>
struct literal_references_visitor {
- factor_vm *parent;
slot_visitor<Visitor> *visitor;
- explicit literal_references_visitor(factor_vm *parent_, slot_visitor<Visitor> *visitor_)
- : parent(parent_), visitor(visitor_) {}
+ explicit literal_references_visitor(slot_visitor<Visitor> *visitor_) : visitor(visitor_) {}
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));
- cell literal = ptr.load_address();
+ instruction_operand op(rel.rel_class(),rel.rel_offset() + (cell)(compiled + 1));
+ cell literal = op.load_address();
literal = visitor->visit_pointer(literal);
- ptr.store_address(literal);
+ op.store_address(literal);
}
}
};
template<typename Visitor>
-void slot_visitor<Visitor>::visit_literal_references(code_block *compiled)
+void slot_visitor<Visitor>::visit_referenced_literals(code_block *compiled)
{
visit_handle(&compiled->owner);
visit_handle(&compiled->literals);
visit_handle(&compiled->relocation);
- literal_references_visitor<Visitor> visitor(parent,this);
- parent->iterate_relocations(compiled,visitor);
+ if(!parent->code->needs_fixup_p(compiled))
+ {
+ literal_references_visitor<Visitor> visitor(this);
+ parent->iterate_relocations(compiled,visitor);
+ }
}
}
struct tenured_space : free_list_allocator<object> {
object_start_map starts;
- std::vector<object *> mark_stack;
explicit tenured_space(cell size, cell start) :
free_list_allocator<object>(size,start), starts(size,start) {}
state.clear_mark_bits();
}
- void clear_mark_stack()
- {
- mark_stack.clear();
- }
-
bool marked_p(object *obj)
{
return this->state.marked_p(obj);
}
- void mark_and_push(object *obj)
+ void set_marked_p(object *obj)
{
this->state.set_marked_p(obj);
- this->mark_stack.push_back(obj);
}
void sweep()
namespace factor
{
-to_tenured_collector::to_tenured_collector(factor_vm *myvm_) :
+to_tenured_collector::to_tenured_collector(factor_vm *parent_) :
collector<tenured_space,to_tenured_policy>(
- myvm_,
- myvm_->data->tenured,
- to_tenured_policy(myvm_)) {}
+ parent_,
+ parent_->data->tenured,
+ to_tenured_policy(parent_)) {}
void to_tenured_collector::tenure_reachable_objects()
{
- std::vector<object *> *mark_stack = &this->target->mark_stack;
+ std::vector<cell> *mark_stack = &parent->mark_stack;
while(!mark_stack->empty())
{
- object *obj = mark_stack->back();
+ cell ptr = mark_stack->back();
mark_stack->pop_back();
- this->trace_object(obj);
+ this->trace_object((object *)ptr);
}
}
/* Copy live objects from aging space to tenured space. */
to_tenured_collector collector(this);
- data->tenured->clear_mark_stack();
+ mark_stack.clear();
collector.trace_roots();
collector.trace_contexts();
{
struct to_tenured_policy {
- factor_vm *myvm;
+ factor_vm *parent;
tenured_space *tenured;
- explicit to_tenured_policy(factor_vm *myvm_) : myvm(myvm_), tenured(myvm->data->tenured) {}
+ explicit to_tenured_policy(factor_vm *parent_) : parent(parent_), tenured(parent->data->tenured) {}
bool should_copy_p(object *untagged)
{
void promoted_object(object *obj)
{
- tenured->mark_stack.push_back(obj);
+ parent->mark_stack.push_back((cell)obj);
}
void visited_object(object *obj) {}
};
struct to_tenured_collector : collector<tenured_space,to_tenured_policy> {
- explicit to_tenured_collector(factor_vm *myvm_);
+ explicit to_tenured_collector(factor_vm *parent_);
void tenure_reachable_objects();
};
/* Only set if we're performing a GC */
gc_state *current_gc;
+ /* Mark stack */
+ std::vector<cell> mark_stack;
+
/* If not NULL, we push GC events here */
std::vector<gc_event> *gc_events;
void relocate_code_block_step(relocation_entry rel, cell index, code_block *compiled);
void update_word_references(code_block *compiled);
- void update_code_block_words_and_literals(code_block *compiled);
void check_code_address(cell address);
void relocate_code_block(code_block *compiled);
void fixup_labels(array *labels, code_block *compiled);
bool in_code_heap_p(cell ptr);
void jit_compile_word(cell word_, cell def_, bool relocate);
void update_code_heap_words();
- void update_code_heap_words_and_literals();
void primitive_modify_code_heap();
code_heap_room code_room();
void primitive_code_room();