factor/vm/collector.hpp

151 lines
3.4 KiB
C++

namespace factor
{
template<typename TargetGeneration, typename Policy> struct collector {
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_) :
parent(parent_),
data(parent_->data),
code(parent_->code),
current_gc(parent_->current_gc),
stats(stats_),
target(target_),
policy(policy_) {}
object *resolve_forwarding(object *untagged)
{
parent->check_data_pointer(untagged);
/* is there another forwarding pointer? */
while(untagged->h.forwarding_pointer_p())
untagged = untagged->h.forwarding_pointer();
/* we've found the destination */
untagged->h.check_header();
return untagged;
}
void trace_handle(cell *handle)
{
cell pointer = *handle;
if(immediate_p(pointer)) return;
object *untagged = parent->untag<object>(pointer);
if(!policy.should_copy_p(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;
*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 = parent->untagged_object_size(untagged);
object *newpointer = target->allot(size);
/* XXX not exception-safe */
if(!newpointer) longjmp(current_gc->gc_unwind,1);
memcpy(newpointer,untagged,size);
untagged->h.forward_to(newpointer);
stats->object_count++;
stats->bytes_copied += size;
return newpointer;
}
void trace_stack_elements(segment *region, cell *top)
{
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++)
{
cell *handle = (cell *)(*iter);
if(*handle)
{
*handle |= BIGNUM_TYPE;
trace_handle(handle);
*handle &= ~BIGNUM_TYPE;
}
}
}
/* 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(int i = 0; i < USER_ENV; i++) trace_handle(&parent->userenv[i]);
}
void trace_contexts()
{
context *ctx = parent->ctx;
while(ctx)
{
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;
}
}
};
}