vm: factor out code that visits object slots and code heap blocks into slot_visitor and code_block_visitor
parent
9abe29bebc
commit
fd1e992e7d
|
@ -0,0 +1,79 @@
|
|||
namespace factor
|
||||
{
|
||||
|
||||
template<typename Visitor> struct call_frame_code_block_visitor {
|
||||
Visitor visitor;
|
||||
|
||||
explicit call_frame_code_block_visitor(Visitor visitor_) : visitor(visitor_) {}
|
||||
|
||||
void operator()(stack_frame *frame)
|
||||
{
|
||||
cell offset = (cell)FRAME_RETURN_ADDRESS(frame,parent) - (cell)frame->xt;
|
||||
|
||||
code_block *new_block = visitor.visit_code_block(parent->frame_code(frame));
|
||||
frame->xt = new_block->xt();
|
||||
|
||||
FRAME_RETURN_ADDRESS(frame,parent) = (void *)((cell)frame->xt + offset);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Visitor> void factor_vm::visit_object_code_block(object *obj, Visitor visitor)
|
||||
{
|
||||
switch(obj->h.hi_tag())
|
||||
{
|
||||
case WORD_TYPE:
|
||||
{
|
||||
word *w = (word *)obj;
|
||||
if(w->code)
|
||||
w->code = visitor.visit_code_block(w->code);
|
||||
if(w->profiling)
|
||||
w->code = visitor.visit_code_block(w->profiling);
|
||||
|
||||
update_word_xt(obj);
|
||||
break;
|
||||
}
|
||||
case QUOTATION_TYPE:
|
||||
{
|
||||
quotation *q = (quotation *)obj;
|
||||
if(q->code)
|
||||
set_quot_xt(visitor.visit_code_block(q->code));
|
||||
break;
|
||||
}
|
||||
case CALLSTACK_TYPE:
|
||||
{
|
||||
callstack *stack = (callstack *)obj;
|
||||
call_frame_code_block_visitor<Visitor> call_frame_visitor(visitor);
|
||||
iterate_callstack_object(stack,call_frame_visitor);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Visitor> void factor_vm::visit_context_code_blocks(Visitor visitor)
|
||||
{
|
||||
callstack *stack = (callstack *)obj;
|
||||
call_frame_code_block_visitor<Visitor> call_frame_visitor(visitor);
|
||||
iterate_active_frames(call_frame_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)
|
||||
{
|
||||
stub->compiled = visitor.visit_code_block(stub->compiled);
|
||||
callbacks->update(stub);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Visitor> void factor_vm::visit_callback_code_blocks(Visitor visitor)
|
||||
{
|
||||
callback_code_block_visitor callback_visitor(callbacks,visitor);
|
||||
callbacks->iterate(callback_visitor);
|
||||
}
|
||||
|
||||
}
|
|
@ -188,7 +188,7 @@ void factor_vm::primitive_modify_code_heap()
|
|||
break;
|
||||
}
|
||||
|
||||
update_word_xt(word.value());
|
||||
update_word_xt(word.untagged());
|
||||
}
|
||||
|
||||
update_code_heap_words();
|
||||
|
@ -205,99 +205,42 @@ void factor_vm::primitive_code_room()
|
|||
dpush(tag_fixnum(max_free / 1024));
|
||||
}
|
||||
|
||||
code_block *code_heap::forward_code_block(code_block *compiled)
|
||||
{
|
||||
return (code_block *)allocator->state.forward_block(compiled);
|
||||
}
|
||||
struct code_block_forwarder {
|
||||
mark_bits<heap_block> *forwarding_map;
|
||||
|
||||
struct callframe_forwarder {
|
||||
factor_vm *parent;
|
||||
explicit code_block_forwarder(mark_bits<heap_block> *forwarding_map_) :
|
||||
forwarding_map(forwarding_map_) {}
|
||||
|
||||
explicit callframe_forwarder(factor_vm *parent_) : parent(parent_) {}
|
||||
|
||||
void operator()(stack_frame *frame)
|
||||
code_block *operator()(code_block *compiled)
|
||||
{
|
||||
cell offset = (cell)FRAME_RETURN_ADDRESS(frame,parent) - (cell)frame->xt;
|
||||
|
||||
code_block *forwarded = parent->code->forward_code_block(parent->frame_code(frame));
|
||||
frame->xt = forwarded->xt();
|
||||
|
||||
FRAME_RETURN_ADDRESS(frame,parent) = (void *)((cell)frame->xt + offset);
|
||||
return (code_block *)forwarding_map->forward_block(compiled);
|
||||
}
|
||||
};
|
||||
|
||||
void factor_vm::forward_object_xts()
|
||||
{
|
||||
code_block_forwarder forwarder(&code->allocator->state);
|
||||
|
||||
begin_scan();
|
||||
|
||||
cell obj;
|
||||
|
||||
while(to_boolean(obj = next_object()))
|
||||
{
|
||||
switch(tagged<object>(obj).type())
|
||||
{
|
||||
case WORD_TYPE:
|
||||
{
|
||||
word *w = untag<word>(obj);
|
||||
|
||||
if(w->code)
|
||||
w->code = code->forward_code_block(w->code);
|
||||
if(w->profiling)
|
||||
w->profiling = code->forward_code_block(w->profiling);
|
||||
|
||||
update_word_xt(obj);
|
||||
}
|
||||
break;
|
||||
case QUOTATION_TYPE:
|
||||
{
|
||||
quotation *quot = untag<quotation>(obj);
|
||||
|
||||
if(quot->code)
|
||||
{
|
||||
quot->code = code->forward_code_block(quot->code);
|
||||
set_quot_xt(quot,quot->code);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CALLSTACK_TYPE:
|
||||
{
|
||||
callstack *stack = untag<callstack>(obj);
|
||||
callframe_forwarder forwarder(this);
|
||||
iterate_callstack_object(stack,forwarder);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
visit_object_code_block(untag<object>(obj),forwarder);
|
||||
|
||||
end_scan();
|
||||
}
|
||||
|
||||
void factor_vm::forward_context_xts()
|
||||
{
|
||||
callframe_forwarder forwarder(this);
|
||||
iterate_active_frames(forwarder);
|
||||
code_block_forwarder forwarder(&code->allocator->state);
|
||||
visit_context_code_blocks(forwarder);
|
||||
}
|
||||
|
||||
struct callback_forwarder {
|
||||
code_heap *code;
|
||||
callback_heap *callbacks;
|
||||
|
||||
callback_forwarder(code_heap *code_, callback_heap *callbacks_) :
|
||||
code(code_), callbacks(callbacks_) {}
|
||||
|
||||
void operator()(callback *stub)
|
||||
{
|
||||
stub->compiled = code->forward_code_block(stub->compiled);
|
||||
callbacks->update(stub);
|
||||
}
|
||||
};
|
||||
|
||||
void factor_vm::forward_callback_xts()
|
||||
{
|
||||
callback_forwarder forwarder(code,callbacks);
|
||||
callbacks->iterate(forwarder);
|
||||
code_block_forwarder forwarder(&code->allocator->state);
|
||||
visit_callback_code_blocks(forwarder);
|
||||
}
|
||||
|
||||
/* Move all free space to the end of the code heap. Live blocks must be marked
|
||||
|
|
|
@ -26,7 +26,6 @@ struct code_heap {
|
|||
void set_marked_p(code_block *compiled);
|
||||
void clear_mark_bits();
|
||||
void code_heap_free(code_block *compiled);
|
||||
code_block *forward_code_block(code_block *compiled);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
213
vm/collector.hpp
213
vm/collector.hpp
|
@ -1,20 +1,14 @@
|
|||
namespace factor
|
||||
{
|
||||
|
||||
template<typename TargetGeneration, typename Policy> struct collector {
|
||||
template<typename TargetGeneration, typename Policy> struct collector_workhorse {
|
||||
factor_vm *parent;
|
||||
data_heap *data;
|
||||
code_heap *code;
|
||||
gc_state *current_gc;
|
||||
generation_statistics *stats;
|
||||
TargetGeneration *target;
|
||||
Policy policy;
|
||||
|
||||
explicit collector(factor_vm *parent_, generation_statistics *stats_, TargetGeneration *target_, Policy policy_) :
|
||||
explicit collector_workhorse(factor_vm *parent_, generation_statistics *stats_, TargetGeneration *target_, Policy policy_) :
|
||||
parent(parent_),
|
||||
data(parent_->data),
|
||||
code(parent_->code),
|
||||
current_gc(parent_->current_gc),
|
||||
stats(stats_),
|
||||
target(target_),
|
||||
policy(policy_) {}
|
||||
|
@ -32,52 +26,12 @@ template<typename TargetGeneration, typename Policy> struct collector {
|
|||
return untagged;
|
||||
}
|
||||
|
||||
void trace_handle(cell *handle)
|
||||
{
|
||||
cell pointer = *handle;
|
||||
|
||||
if(immediate_p(pointer)) return;
|
||||
|
||||
object *untagged = untag<object>(pointer);
|
||||
if(!policy.should_copy_p(untagged))
|
||||
{
|
||||
policy.visited_object(untagged);
|
||||
return;
|
||||
}
|
||||
|
||||
object *forwarding = resolve_forwarding(untagged);
|
||||
|
||||
if(forwarding == untagged)
|
||||
untagged = promote_object(untagged);
|
||||
else if(policy.should_copy_p(forwarding))
|
||||
untagged = promote_object(forwarding);
|
||||
else
|
||||
{
|
||||
untagged = forwarding;
|
||||
policy.visited_object(untagged);
|
||||
}
|
||||
|
||||
*handle = RETAG(untagged,TAG(pointer));
|
||||
}
|
||||
|
||||
void trace_slots(object *ptr)
|
||||
{
|
||||
cell *slot = (cell *)ptr;
|
||||
cell *end = (cell *)((cell)ptr + parent->binary_payload_start(ptr));
|
||||
|
||||
if(slot != end)
|
||||
{
|
||||
slot++;
|
||||
for(; slot < end; slot++) trace_handle(slot);
|
||||
}
|
||||
}
|
||||
|
||||
object *promote_object(object *untagged)
|
||||
{
|
||||
cell size = untagged->size();
|
||||
object *newpointer = target->allot(size);
|
||||
/* XXX not exception-safe */
|
||||
if(!newpointer) longjmp(current_gc->gc_unwind,1);
|
||||
if(!newpointer) longjmp(parent->current_gc->gc_unwind,1);
|
||||
|
||||
memcpy(newpointer,untagged,size);
|
||||
untagged->h.forward_to(newpointer);
|
||||
|
@ -90,68 +44,90 @@ template<typename TargetGeneration, typename Policy> struct collector {
|
|||
return newpointer;
|
||||
}
|
||||
|
||||
void trace_stack_elements(segment *region, cell *top)
|
||||
object *visit_handle(object *obj)
|
||||
{
|
||||
for(cell *ptr = (cell *)region->start; ptr <= top; ptr++)
|
||||
trace_handle(ptr);
|
||||
}
|
||||
|
||||
void trace_registered_locals()
|
||||
{
|
||||
std::vector<cell>::const_iterator iter = parent->gc_locals.begin();
|
||||
std::vector<cell>::const_iterator end = parent->gc_locals.end();
|
||||
|
||||
for(; iter < end; iter++)
|
||||
trace_handle((cell *)(*iter));
|
||||
}
|
||||
|
||||
void trace_registered_bignums()
|
||||
{
|
||||
std::vector<cell>::const_iterator iter = parent->gc_bignums.begin();
|
||||
std::vector<cell>::const_iterator end = parent->gc_bignums.end();
|
||||
|
||||
for(; iter < end; iter++)
|
||||
if(!policy.should_copy_p(obj))
|
||||
{
|
||||
cell *handle = (cell *)(*iter);
|
||||
policy.visited_object(obj);
|
||||
return obj;
|
||||
}
|
||||
|
||||
if(*handle)
|
||||
{
|
||||
*handle |= BIGNUM_TYPE;
|
||||
trace_handle(handle);
|
||||
*handle &= ~BIGNUM_TYPE;
|
||||
}
|
||||
object *forwarding = resolve_forwarding(obj);
|
||||
|
||||
if(forwarding == obj)
|
||||
return promote_object(obj);
|
||||
else if(policy.should_copy_p(forwarding))
|
||||
return promote_object(forwarding);
|
||||
else
|
||||
{
|
||||
policy.visited_object(forwarding);
|
||||
return forwarding;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<typename TargetGeneration, typename Policy>
|
||||
inline static slot_visitor<collector_workhorse<TargetGeneration,Policy> > make_collector_workhorse(
|
||||
factor_vm *parent,
|
||||
generation_statistics *stats,
|
||||
TargetGeneration *target,
|
||||
Policy policy)
|
||||
{
|
||||
return slot_visitor<collector_workhorse<TargetGeneration,Policy> >(parent,
|
||||
collector_workhorse<TargetGeneration,Policy>(parent,stats,target,policy));
|
||||
}
|
||||
|
||||
template<typename TargetGeneration, typename Policy> struct collector {
|
||||
factor_vm *parent;
|
||||
data_heap *data;
|
||||
code_heap *code;
|
||||
generation_statistics *stats;
|
||||
TargetGeneration *target;
|
||||
slot_visitor<collector_workhorse<TargetGeneration,Policy> > workhorse;
|
||||
|
||||
explicit collector(factor_vm *parent_, generation_statistics *stats_, TargetGeneration *target_, Policy policy_) :
|
||||
parent(parent_),
|
||||
data(parent_->data),
|
||||
code(parent_->code),
|
||||
stats(stats_),
|
||||
target(target_),
|
||||
workhorse(make_collector_workhorse(parent_,stats_,target_,policy_)) {}
|
||||
|
||||
void trace_handle(cell *handle)
|
||||
{
|
||||
workhorse.visit_handle(handle);
|
||||
}
|
||||
|
||||
void trace_slots(object *ptr)
|
||||
{
|
||||
workhorse.visit_slots(ptr);
|
||||
}
|
||||
|
||||
/* Copy roots over at the start of GC, namely various constants, stacks,
|
||||
the user environment and extra roots registered by local_roots.hpp */
|
||||
void trace_roots()
|
||||
{
|
||||
trace_handle(&parent->true_object);
|
||||
trace_handle(&parent->bignum_zero);
|
||||
trace_handle(&parent->bignum_pos_one);
|
||||
trace_handle(&parent->bignum_neg_one);
|
||||
|
||||
trace_registered_locals();
|
||||
trace_registered_bignums();
|
||||
|
||||
for(cell i = 0; i < special_object_count; i++)
|
||||
trace_handle(&parent->special_objects[i]);
|
||||
workhorse.visit_roots();
|
||||
}
|
||||
|
||||
void trace_contexts()
|
||||
{
|
||||
context *ctx = parent->ctx;
|
||||
workhorse.visit_contexts();
|
||||
}
|
||||
|
||||
while(ctx)
|
||||
/* Trace all literals referenced from a code block. Only for aging and nursery collections */
|
||||
void trace_literal_references(code_block *compiled)
|
||||
{
|
||||
workhorse.visit_literal_references(compiled);
|
||||
}
|
||||
|
||||
void trace_code_heap_roots(std::set<code_block *> *remembered_set)
|
||||
{
|
||||
std::set<code_block *>::const_iterator iter = remembered_set->begin();
|
||||
std::set<code_block *>::const_iterator end = remembered_set->end();
|
||||
|
||||
for(; iter != end; iter++)
|
||||
{
|
||||
trace_stack_elements(ctx->datastack_region,(cell *)ctx->datastack);
|
||||
trace_stack_elements(ctx->retainstack_region,(cell *)ctx->retainstack);
|
||||
|
||||
trace_handle(&ctx->catchstack_save);
|
||||
trace_handle(&ctx->current_callback_save);
|
||||
|
||||
ctx = ctx->next;
|
||||
trace_literal_references(*iter);
|
||||
parent->gc_stats.code_blocks_scanned++;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -167,17 +143,17 @@ template<typename TargetGeneration, typename Policy> struct collector {
|
|||
|
||||
inline cell card_deck_for_address(cell a)
|
||||
{
|
||||
return addr_to_deck(a - this->data->start);
|
||||
return addr_to_deck(a - data->start);
|
||||
}
|
||||
|
||||
inline cell card_start_address(cell card)
|
||||
{
|
||||
return (card << card_bits) + this->data->start;
|
||||
return (card << card_bits) + data->start;
|
||||
}
|
||||
|
||||
inline cell card_end_address(cell card)
|
||||
{
|
||||
return ((card + 1) << card_bits) + this->data->start;
|
||||
return ((card + 1) << card_bits) + data->start;
|
||||
}
|
||||
|
||||
void trace_partial_objects(cell start, cell end, cell card_start, cell card_end)
|
||||
|
@ -195,7 +171,7 @@ template<typename TargetGeneration, typename Policy> struct collector {
|
|||
if(slot_ptr != end_ptr)
|
||||
{
|
||||
for(; slot_ptr < end_ptr; slot_ptr++)
|
||||
this->trace_handle(slot_ptr);
|
||||
workhorse.visit_handle(slot_ptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -205,10 +181,10 @@ template<typename TargetGeneration, typename Policy> struct collector {
|
|||
{
|
||||
u64 start_time = current_micros();
|
||||
|
||||
card_deck *decks = this->data->decks;
|
||||
card_deck *cards = this->data->cards;
|
||||
card_deck *decks = data->decks;
|
||||
card_deck *cards = data->cards;
|
||||
|
||||
cell gen_start_card = addr_to_card(gen->start - this->data->start);
|
||||
cell gen_start_card = addr_to_card(gen->start - data->start);
|
||||
|
||||
cell first_deck = card_deck_for_address(gen->start);
|
||||
cell last_deck = card_deck_for_address(gen->end);
|
||||
|
@ -219,7 +195,7 @@ template<typename TargetGeneration, typename Policy> struct collector {
|
|||
{
|
||||
if(decks[deck_index] & mask)
|
||||
{
|
||||
this->parent->gc_stats.decks_scanned++;
|
||||
parent->gc_stats.decks_scanned++;
|
||||
|
||||
cell first_card = first_card_in_deck(deck_index);
|
||||
cell last_card = last_card_in_deck(deck_index);
|
||||
|
@ -228,17 +204,17 @@ template<typename TargetGeneration, typename Policy> struct collector {
|
|||
{
|
||||
if(cards[card_index] & mask)
|
||||
{
|
||||
this->parent->gc_stats.cards_scanned++;
|
||||
parent->gc_stats.cards_scanned++;
|
||||
|
||||
if(end < card_start_address(card_index))
|
||||
{
|
||||
start = gen->starts.find_object_containing_card(card_index - gen_start_card);
|
||||
binary_start = start + this->parent->binary_payload_start((object *)start);
|
||||
binary_start = start + parent->binary_payload_start((object *)start);
|
||||
end = start + ((object *)start)->size();
|
||||
}
|
||||
|
||||
#ifdef FACTOR_DEBUG
|
||||
assert(addr_to_card(start - this->data->start) <= card_index);
|
||||
assert(addr_to_card(start - data->start) <= card_index);
|
||||
assert(start < card_end_address(card_index));
|
||||
#endif
|
||||
|
||||
|
@ -253,7 +229,7 @@ scan_next_object: {
|
|||
start = gen->next_object_after(start);
|
||||
if(start)
|
||||
{
|
||||
binary_start = start + this->parent->binary_payload_start((object *)start);
|
||||
binary_start = start + parent->binary_payload_start((object *)start);
|
||||
end = start + ((object *)start)->size();
|
||||
goto scan_next_object;
|
||||
}
|
||||
|
@ -270,24 +246,7 @@ scan_next_object: {
|
|||
}
|
||||
}
|
||||
|
||||
end: this->parent->gc_stats.card_scan_time += (current_micros() - start_time);
|
||||
}
|
||||
|
||||
/* Trace all literals referenced from a code block. Only for aging and nursery collections */
|
||||
void trace_literal_references(code_block *compiled)
|
||||
{
|
||||
this->trace_handle(&compiled->owner);
|
||||
this->trace_handle(&compiled->literals);
|
||||
this->trace_handle(&compiled->relocation);
|
||||
this->parent->gc_stats.code_blocks_scanned++;
|
||||
}
|
||||
|
||||
void trace_code_heap_roots(std::set<code_block *> *remembered_set)
|
||||
{
|
||||
std::set<code_block *>::const_iterator iter = remembered_set->begin();
|
||||
std::set<code_block *>::const_iterator end = remembered_set->end();
|
||||
|
||||
for(; iter != end; iter++) trace_literal_references(*iter);
|
||||
end: parent->gc_stats.card_scan_time += (current_micros() - start_time);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -10,101 +10,36 @@ full_collector::full_collector(factor_vm *parent_) :
|
|||
parent_->data->tenured,
|
||||
full_policy(parent_)) {}
|
||||
|
||||
struct stack_frame_marker {
|
||||
factor_vm *parent;
|
||||
struct code_block_marker {
|
||||
code_heap *code;
|
||||
full_collector *collector;
|
||||
|
||||
explicit stack_frame_marker(full_collector *collector_) :
|
||||
parent(collector_->parent), collector(collector_) {}
|
||||
explicit code_block_marker(code_heap *code_, full_collector *collector_) :
|
||||
code(code_), collector(collector_) {}
|
||||
|
||||
void operator()(stack_frame *frame)
|
||||
code_block *operator()(code_block *compiled)
|
||||
{
|
||||
collector->mark_code_block(parent->frame_code(frame));
|
||||
if(!code->marked_p(compiled))
|
||||
{
|
||||
code->set_marked_p(compiled);
|
||||
collector->trace_literal_references(compiled);
|
||||
}
|
||||
|
||||
return compiled;
|
||||
}
|
||||
};
|
||||
|
||||
/* Mark code blocks executing in currently active stack frames. */
|
||||
void full_collector::mark_active_blocks()
|
||||
{
|
||||
stack_frame_marker marker(this);
|
||||
parent->iterate_active_frames(marker);
|
||||
}
|
||||
|
||||
void full_collector::mark_object_code_block(object *obj)
|
||||
{
|
||||
switch(obj->h.hi_tag())
|
||||
{
|
||||
case WORD_TYPE:
|
||||
{
|
||||
word *w = (word *)obj;
|
||||
if(w->code)
|
||||
mark_code_block(w->code);
|
||||
if(w->profiling)
|
||||
mark_code_block(w->profiling);
|
||||
break;
|
||||
}
|
||||
case QUOTATION_TYPE:
|
||||
{
|
||||
quotation *q = (quotation *)obj;
|
||||
if(q->code)
|
||||
mark_code_block(q->code);
|
||||
break;
|
||||
}
|
||||
case CALLSTACK_TYPE:
|
||||
{
|
||||
callstack *stack = (callstack *)obj;
|
||||
stack_frame_marker marker(this);
|
||||
parent->iterate_callstack_object(stack,marker);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct callback_tracer {
|
||||
full_collector *collector;
|
||||
|
||||
callback_tracer(full_collector *collector_) : collector(collector_) {}
|
||||
|
||||
void operator()(callback *stub)
|
||||
{
|
||||
collector->mark_code_block(stub->compiled);
|
||||
}
|
||||
};
|
||||
|
||||
void full_collector::trace_callbacks()
|
||||
{
|
||||
callback_tracer tracer(this);
|
||||
parent->callbacks->iterate(tracer);
|
||||
}
|
||||
|
||||
/* Trace all literals referenced from a code block. Only for aging and nursery collections */
|
||||
void full_collector::trace_literal_references(code_block *compiled)
|
||||
{
|
||||
this->trace_handle(&compiled->owner);
|
||||
this->trace_handle(&compiled->literals);
|
||||
this->trace_handle(&compiled->relocation);
|
||||
}
|
||||
|
||||
/* Mark all literals referenced from a word XT. Only for tenured
|
||||
collections */
|
||||
void full_collector::mark_code_block(code_block *compiled)
|
||||
{
|
||||
if(!this->code->marked_p(compiled))
|
||||
{
|
||||
this->code->set_marked_p(compiled);
|
||||
trace_literal_references(compiled);
|
||||
}
|
||||
}
|
||||
|
||||
void full_collector::mark_reachable_objects()
|
||||
{
|
||||
code_block_marker marker(code,this);
|
||||
std::vector<object *> *mark_stack = &this->target->mark_stack;
|
||||
|
||||
while(!mark_stack->empty())
|
||||
{
|
||||
object *obj = mark_stack->back();
|
||||
mark_stack->pop_back();
|
||||
this->trace_slots(obj);
|
||||
this->mark_object_code_block(obj);
|
||||
parent->visit_object_code_block(obj,marker);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -131,8 +66,9 @@ void factor_vm::collect_full_impl(bool trace_contexts_p)
|
|||
if(trace_contexts_p)
|
||||
{
|
||||
collector.trace_contexts();
|
||||
collector.mark_active_blocks();
|
||||
collector.trace_callbacks();
|
||||
code_block_marker marker(code,&collector);
|
||||
visit_context_code_blocks(marker);
|
||||
visit_callback_code_blocks(marker);
|
||||
}
|
||||
|
||||
collector.mark_reachable_objects();
|
||||
|
|
|
@ -28,11 +28,6 @@ struct full_collector : collector<tenured_space,full_policy> {
|
|||
bool trace_contexts_p;
|
||||
|
||||
full_collector(factor_vm *parent_);
|
||||
void mark_active_blocks();
|
||||
void mark_object_code_block(object *object);
|
||||
void trace_callbacks();
|
||||
void trace_literal_references(code_block *compiled);
|
||||
void mark_code_block(code_block *compiled);
|
||||
void mark_reachable_objects();
|
||||
};
|
||||
|
||||
|
|
|
@ -72,11 +72,13 @@ namespace factor
|
|||
#include "vm.hpp"
|
||||
#include "tagged.hpp"
|
||||
#include "local_roots.hpp"
|
||||
#include "slot_visitor.hpp"
|
||||
#include "collector.hpp"
|
||||
#include "copying_collector.hpp"
|
||||
#include "nursery_collector.hpp"
|
||||
#include "aging_collector.hpp"
|
||||
#include "to_tenured_collector.hpp"
|
||||
#include "code_block_visitor.hpp"
|
||||
#include "full_collector.hpp"
|
||||
#include "callstack.hpp"
|
||||
#include "generic_arrays.hpp"
|
||||
|
|
|
@ -40,7 +40,7 @@ void factor_vm::set_profiling(bool profiling)
|
|||
tagged<word> word(array_nth(words.untagged(),i));
|
||||
if(profiling)
|
||||
word->counter = tag_fixnum(0);
|
||||
update_word_xt(word.value());
|
||||
update_word_xt(word.untagged());
|
||||
}
|
||||
|
||||
update_code_heap_words();
|
||||
|
|
|
@ -338,7 +338,7 @@ void factor_vm::compile_all_words()
|
|||
if(!word->code || !word->code->optimized_p())
|
||||
jit_compile_word(word.value(),word->def,false);
|
||||
|
||||
update_word_xt(word.value());
|
||||
update_word_xt(word.untagged());
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,101 @@
|
|||
namespace factor
|
||||
{
|
||||
|
||||
template<typename Visitor> struct slot_visitor {
|
||||
factor_vm *parent;
|
||||
Visitor visitor;
|
||||
|
||||
slot_visitor<Visitor>(factor_vm *parent_, Visitor visitor_) :
|
||||
parent(parent_), visitor(visitor_) {}
|
||||
|
||||
void visit_handle(cell *handle)
|
||||
{
|
||||
cell pointer = *handle;
|
||||
|
||||
if(immediate_p(pointer)) return;
|
||||
|
||||
object *untagged = untag<object>(pointer);
|
||||
untagged = visitor.visit_handle(untagged);
|
||||
*handle = RETAG(untagged,TAG(pointer));
|
||||
}
|
||||
|
||||
void visit_slots(object *ptr)
|
||||
{
|
||||
cell *slot = (cell *)ptr;
|
||||
cell *end = (cell *)((cell)ptr + parent->binary_payload_start(ptr));
|
||||
|
||||
if(slot != end)
|
||||
{
|
||||
slot++;
|
||||
for(; slot < end; slot++) visit_handle(slot);
|
||||
}
|
||||
}
|
||||
|
||||
void visit_stack_elements(segment *region, cell *top)
|
||||
{
|
||||
for(cell *ptr = (cell *)region->start; ptr <= top; ptr++)
|
||||
visit_handle(ptr);
|
||||
}
|
||||
|
||||
void visit_registered_locals()
|
||||
{
|
||||
std::vector<cell>::const_iterator iter = parent->gc_locals.begin();
|
||||
std::vector<cell>::const_iterator end = parent->gc_locals.end();
|
||||
|
||||
for(; iter < end; iter++)
|
||||
visit_handle((cell *)(*iter));
|
||||
}
|
||||
|
||||
void visit_registered_bignums()
|
||||
{
|
||||
std::vector<cell>::const_iterator iter = parent->gc_bignums.begin();
|
||||
std::vector<cell>::const_iterator end = parent->gc_bignums.end();
|
||||
|
||||
for(; iter < end; iter++)
|
||||
{
|
||||
cell *handle = (cell *)(*iter);
|
||||
|
||||
if(*handle)
|
||||
*handle = (cell)visitor.visit_handle(*(object **)handle);
|
||||
}
|
||||
}
|
||||
|
||||
void visit_roots()
|
||||
{
|
||||
visit_handle(&parent->true_object);
|
||||
visit_handle(&parent->bignum_zero);
|
||||
visit_handle(&parent->bignum_pos_one);
|
||||
visit_handle(&parent->bignum_neg_one);
|
||||
|
||||
visit_registered_locals();
|
||||
visit_registered_bignums();
|
||||
|
||||
for(cell i = 0; i < special_object_count; i++)
|
||||
visit_handle(&parent->special_objects[i]);
|
||||
}
|
||||
|
||||
void visit_contexts()
|
||||
{
|
||||
context *ctx = parent->ctx;
|
||||
|
||||
while(ctx)
|
||||
{
|
||||
visit_stack_elements(ctx->datastack_region,(cell *)ctx->datastack);
|
||||
visit_stack_elements(ctx->retainstack_region,(cell *)ctx->retainstack);
|
||||
|
||||
visit_handle(&ctx->catchstack_save);
|
||||
visit_handle(&ctx->current_callback_save);
|
||||
|
||||
ctx = ctx->next;
|
||||
}
|
||||
}
|
||||
|
||||
void visit_literal_references(code_block *compiled)
|
||||
{
|
||||
visit_handle(&compiled->owner);
|
||||
visit_handle(&compiled->literals);
|
||||
visit_handle(&compiled->relocation);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
|
@ -353,7 +353,7 @@ struct factor_vm
|
|||
word *allot_word(cell name_, cell vocab_, cell hashcode_);
|
||||
void primitive_word();
|
||||
void primitive_word_xt();
|
||||
void update_word_xt(cell w_);
|
||||
void update_word_xt(word *w_);
|
||||
void primitive_optimized_p();
|
||||
void primitive_wrapper();
|
||||
|
||||
|
@ -485,6 +485,11 @@ struct factor_vm
|
|||
code_block *allot_code_block(cell size, code_block_type type);
|
||||
code_block *add_code_block(code_block_type type, cell code_, cell labels_, cell owner_, cell relocation_, cell literals_);
|
||||
|
||||
//code_block_visitor
|
||||
template<typename Visitor> void visit_object_code_block(object *obj, Visitor visitor);
|
||||
template<typename Visitor> void visit_context_code_blocks(Visitor visitor);
|
||||
template<typename Visitor> void visit_callback_code_blocks(Visitor visitor);
|
||||
|
||||
//code heap
|
||||
inline void check_code_pointer(cell ptr)
|
||||
{
|
||||
|
|
|
@ -23,7 +23,7 @@ word *factor_vm::allot_word(cell name_, cell vocab_, cell hashcode_)
|
|||
new_word->code = NULL;
|
||||
|
||||
jit_compile_word(new_word.value(),new_word->def,true);
|
||||
update_word_xt(new_word.value());
|
||||
update_word_xt(new_word.untagged());
|
||||
|
||||
if(profiling_p)
|
||||
relocate_code_block(new_word->profiling);
|
||||
|
@ -59,7 +59,7 @@ void factor_vm::primitive_word_xt()
|
|||
}
|
||||
|
||||
/* Allocates memory */
|
||||
void factor_vm::update_word_xt(cell w_)
|
||||
void factor_vm::update_word_xt(word *w_)
|
||||
{
|
||||
gc_root<word> w(w_,this);
|
||||
|
||||
|
|
Loading…
Reference in New Issue