2009-10-24 04:54:53 -04:00
|
|
|
namespace factor
|
|
|
|
{
|
|
|
|
|
2009-12-02 01:48:41 -05:00
|
|
|
/* Slot visitors iterate over the slots of an object, applying a functor to
|
|
|
|
each one that is a non-immediate slot. The pointer is untagged first. The
|
|
|
|
functor returns a new untagged object pointer. The return value may or may not equal the old one,
|
|
|
|
however the new pointer receives the same tag before being stored back to the
|
|
|
|
original location.
|
|
|
|
|
|
|
|
Slots storing immediate values are left unchanged and the visitor does inspect
|
|
|
|
them.
|
|
|
|
|
|
|
|
This is used by GC's copying, sweep and compact phases, and the implementation
|
|
|
|
of the become primitive.
|
|
|
|
|
|
|
|
Iteration is driven by visit_*() methods. Some of them define GC roots:
|
|
|
|
- visit_roots()
|
|
|
|
- visit_contexts() */
|
|
|
|
|
2009-10-24 04:54:53 -04:00
|
|
|
template<typename Visitor> struct slot_visitor {
|
|
|
|
factor_vm *parent;
|
|
|
|
Visitor visitor;
|
|
|
|
|
2009-10-25 00:02:58 -04:00
|
|
|
explicit slot_visitor<Visitor>(factor_vm *parent_, Visitor visitor_) :
|
2009-10-24 04:54:53 -04:00
|
|
|
parent(parent_), visitor(visitor_) {}
|
|
|
|
|
2009-11-22 14:37:39 -05:00
|
|
|
cell visit_pointer(cell pointer);
|
|
|
|
void visit_handle(cell *handle);
|
|
|
|
void visit_slots(object *ptr, cell payload_start);
|
|
|
|
void visit_slots(object *ptr);
|
|
|
|
void visit_stack_elements(segment *region, cell *top);
|
|
|
|
void visit_data_roots();
|
|
|
|
void visit_bignum_roots();
|
2009-12-02 01:48:41 -05:00
|
|
|
void visit_callback_roots();
|
2009-12-02 05:28:15 -05:00
|
|
|
void visit_literal_table_roots();
|
2009-11-22 14:37:39 -05:00
|
|
|
void visit_roots();
|
|
|
|
void visit_contexts();
|
2009-11-24 20:29:59 -05:00
|
|
|
void visit_code_block_objects(code_block *compiled);
|
|
|
|
void visit_embedded_literals(code_block *compiled);
|
2009-11-22 14:37:39 -05:00
|
|
|
};
|
2009-11-06 02:22:53 -05:00
|
|
|
|
2009-11-22 14:37:39 -05:00
|
|
|
template<typename Visitor>
|
|
|
|
cell slot_visitor<Visitor>::visit_pointer(cell pointer)
|
|
|
|
{
|
|
|
|
if(immediate_p(pointer)) return pointer;
|
2009-11-07 17:16:09 -05:00
|
|
|
|
2009-11-22 14:37:39 -05:00
|
|
|
object *untagged = untag<object>(pointer);
|
|
|
|
untagged = visitor(untagged);
|
|
|
|
return RETAG(untagged,TAG(pointer));
|
|
|
|
}
|
2009-10-24 04:54:53 -04:00
|
|
|
|
2009-11-22 14:37:39 -05:00
|
|
|
template<typename Visitor>
|
|
|
|
void slot_visitor<Visitor>::visit_handle(cell *handle)
|
|
|
|
{
|
|
|
|
*handle = visit_pointer(*handle);
|
|
|
|
}
|
2009-10-24 04:54:53 -04:00
|
|
|
|
2009-11-22 14:37:39 -05:00
|
|
|
template<typename Visitor>
|
|
|
|
void slot_visitor<Visitor>::visit_slots(object *ptr, cell payload_start)
|
|
|
|
{
|
|
|
|
cell *slot = (cell *)ptr;
|
|
|
|
cell *end = (cell *)((cell)ptr + payload_start);
|
2009-10-24 04:54:53 -04:00
|
|
|
|
2009-11-22 14:37:39 -05:00
|
|
|
if(slot != end)
|
2009-10-25 00:51:14 -04:00
|
|
|
{
|
2009-11-22 14:37:39 -05:00
|
|
|
slot++;
|
|
|
|
for(; slot < end; slot++) visit_handle(slot);
|
2009-10-25 00:51:14 -04:00
|
|
|
}
|
2009-11-22 14:37:39 -05:00
|
|
|
}
|
2009-10-25 00:51:14 -04:00
|
|
|
|
2009-11-22 14:37:39 -05:00
|
|
|
template<typename Visitor>
|
|
|
|
void slot_visitor<Visitor>::visit_slots(object *ptr)
|
|
|
|
{
|
|
|
|
visit_slots(ptr,ptr->binary_payload_start());
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename Visitor>
|
|
|
|
void slot_visitor<Visitor>::visit_stack_elements(segment *region, cell *top)
|
|
|
|
{
|
|
|
|
for(cell *ptr = (cell *)region->start; ptr <= top; ptr++)
|
|
|
|
visit_handle(ptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename Visitor>
|
|
|
|
void slot_visitor<Visitor>::visit_data_roots()
|
|
|
|
{
|
|
|
|
std::vector<data_root_range>::const_iterator iter = parent->data_roots.begin();
|
|
|
|
std::vector<data_root_range>::const_iterator end = parent->data_roots.end();
|
|
|
|
|
|
|
|
for(; iter < end; iter++)
|
2009-10-24 04:54:53 -04:00
|
|
|
{
|
2009-11-22 14:37:39 -05:00
|
|
|
data_root_range r = *iter;
|
|
|
|
for(cell index = 0; index < r.len; index++)
|
|
|
|
visit_handle(r.start + index);
|
2009-10-24 04:54:53 -04:00
|
|
|
}
|
2009-11-22 14:37:39 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
template<typename Visitor>
|
|
|
|
void slot_visitor<Visitor>::visit_bignum_roots()
|
|
|
|
{
|
|
|
|
std::vector<cell>::const_iterator iter = parent->bignum_roots.begin();
|
|
|
|
std::vector<cell>::const_iterator end = parent->bignum_roots.end();
|
2009-10-24 04:54:53 -04:00
|
|
|
|
2009-11-22 14:37:39 -05:00
|
|
|
for(; iter < end; iter++)
|
2009-10-24 04:54:53 -04:00
|
|
|
{
|
2009-11-22 14:37:39 -05:00
|
|
|
cell *handle = (cell *)(*iter);
|
2009-10-24 04:54:53 -04:00
|
|
|
|
2009-11-22 14:37:39 -05:00
|
|
|
if(*handle)
|
|
|
|
*handle = (cell)visitor(*(object **)handle);
|
2009-10-24 04:54:53 -04:00
|
|
|
}
|
2009-11-22 14:37:39 -05:00
|
|
|
}
|
2009-10-24 04:54:53 -04:00
|
|
|
|
2009-12-02 01:48:41 -05:00
|
|
|
template<typename Visitor>
|
|
|
|
struct callback_slot_visitor {
|
|
|
|
callback_heap *callbacks;
|
|
|
|
slot_visitor<Visitor> *visitor;
|
|
|
|
|
|
|
|
explicit callback_slot_visitor(callback_heap *callbacks_, slot_visitor<Visitor> *visitor_) :
|
|
|
|
callbacks(callbacks_), visitor(visitor_) {}
|
|
|
|
|
|
|
|
void operator()(code_block *stub)
|
|
|
|
{
|
|
|
|
visitor->visit_handle(&stub->owner);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template<typename Visitor>
|
|
|
|
void slot_visitor<Visitor>::visit_callback_roots()
|
|
|
|
{
|
|
|
|
callback_slot_visitor<Visitor> callback_visitor(parent->callbacks,this);
|
|
|
|
parent->callbacks->each_callback(callback_visitor);
|
|
|
|
}
|
|
|
|
|
2009-12-02 05:28:15 -05:00
|
|
|
template<typename Visitor>
|
|
|
|
void slot_visitor<Visitor>::visit_literal_table_roots()
|
|
|
|
{
|
|
|
|
std::map<code_block *, cell> *uninitialized_blocks = &parent->code->uninitialized_blocks;
|
|
|
|
std::map<code_block *, cell>::const_iterator iter = uninitialized_blocks->begin();
|
|
|
|
std::map<code_block *, cell>::const_iterator end = uninitialized_blocks->end();
|
|
|
|
|
|
|
|
std::map<code_block *, cell> new_uninitialized_blocks;
|
|
|
|
for(; iter != end; iter++)
|
|
|
|
{
|
|
|
|
new_uninitialized_blocks.insert(std::make_pair(
|
|
|
|
iter->first,
|
|
|
|
visit_pointer(iter->second)));
|
|
|
|
}
|
|
|
|
|
|
|
|
parent->code->uninitialized_blocks = new_uninitialized_blocks;
|
|
|
|
}
|
|
|
|
|
2009-11-22 14:37:39 -05:00
|
|
|
template<typename Visitor>
|
|
|
|
void slot_visitor<Visitor>::visit_roots()
|
|
|
|
{
|
|
|
|
visit_handle(&parent->true_object);
|
|
|
|
visit_handle(&parent->bignum_zero);
|
|
|
|
visit_handle(&parent->bignum_pos_one);
|
|
|
|
visit_handle(&parent->bignum_neg_one);
|
2009-10-24 04:54:53 -04:00
|
|
|
|
2009-11-22 14:37:39 -05:00
|
|
|
visit_data_roots();
|
|
|
|
visit_bignum_roots();
|
2009-12-02 01:48:41 -05:00
|
|
|
visit_callback_roots();
|
2009-12-02 05:28:15 -05:00
|
|
|
visit_literal_table_roots();
|
2009-10-24 04:54:53 -04:00
|
|
|
|
2009-11-22 14:37:39 -05:00
|
|
|
for(cell i = 0; i < special_object_count; i++)
|
|
|
|
visit_handle(&parent->special_objects[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename Visitor>
|
|
|
|
void slot_visitor<Visitor>::visit_contexts()
|
|
|
|
{
|
|
|
|
context *ctx = parent->ctx;
|
2009-10-24 04:54:53 -04:00
|
|
|
|
2009-11-22 14:37:39 -05:00
|
|
|
while(ctx)
|
2009-10-24 04:54:53 -04:00
|
|
|
{
|
2009-11-22 14:37:39 -05:00
|
|
|
visit_stack_elements(ctx->datastack_region,(cell *)ctx->datastack);
|
|
|
|
visit_stack_elements(ctx->retainstack_region,(cell *)ctx->retainstack);
|
2009-10-24 04:54:53 -04:00
|
|
|
|
2009-11-22 14:37:39 -05:00
|
|
|
visit_handle(&ctx->catchstack_save);
|
|
|
|
visit_handle(&ctx->current_callback_save);
|
2009-10-24 04:54:53 -04:00
|
|
|
|
2009-11-22 14:37:39 -05:00
|
|
|
ctx = ctx->next;
|
2009-10-24 04:54:53 -04:00
|
|
|
}
|
2009-11-22 14:37:39 -05:00
|
|
|
}
|
2009-10-24 04:54:53 -04:00
|
|
|
|
2009-11-22 14:37:39 -05:00
|
|
|
template<typename Visitor>
|
|
|
|
struct literal_references_visitor {
|
|
|
|
slot_visitor<Visitor> *visitor;
|
2009-10-24 04:54:53 -04:00
|
|
|
|
2009-11-23 19:51:08 -05:00
|
|
|
explicit literal_references_visitor(slot_visitor<Visitor> *visitor_) : visitor(visitor_) {}
|
2009-10-24 04:54:53 -04:00
|
|
|
|
2009-12-02 01:48:41 -05:00
|
|
|
void operator()(instruction_operand op)
|
2009-10-24 04:54:53 -04:00
|
|
|
{
|
2009-12-15 07:20:09 -05:00
|
|
|
if(op.rel_type() == RT_LITERAL)
|
2009-11-27 18:05:08 -05:00
|
|
|
op.store_value(visitor->visit_pointer(op.load_value()));
|
2009-10-24 04:54:53 -04:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2009-11-22 14:37:39 -05:00
|
|
|
template<typename Visitor>
|
2009-11-24 20:29:59 -05:00
|
|
|
void slot_visitor<Visitor>::visit_code_block_objects(code_block *compiled)
|
2009-11-22 14:37:39 -05:00
|
|
|
{
|
|
|
|
visit_handle(&compiled->owner);
|
2009-12-02 05:28:15 -05:00
|
|
|
visit_handle(&compiled->parameters);
|
2009-11-22 14:37:39 -05:00
|
|
|
visit_handle(&compiled->relocation);
|
2009-11-24 20:29:59 -05:00
|
|
|
}
|
2009-11-22 14:37:39 -05:00
|
|
|
|
2009-11-24 20:29:59 -05:00
|
|
|
template<typename Visitor>
|
|
|
|
void slot_visitor<Visitor>::visit_embedded_literals(code_block *compiled)
|
|
|
|
{
|
2009-12-02 05:28:15 -05:00
|
|
|
if(!parent->code->uninitialized_p(compiled))
|
2009-11-23 19:51:08 -05:00
|
|
|
{
|
|
|
|
literal_references_visitor<Visitor> visitor(this);
|
2009-12-02 01:48:41 -05:00
|
|
|
compiled->each_instruction_operand(visitor);
|
2009-11-23 19:51:08 -05:00
|
|
|
}
|
2009-11-22 14:37:39 -05:00
|
|
|
}
|
|
|
|
|
2009-10-24 04:54:53 -04:00
|
|
|
}
|