namespace factor
{
-template<typename Visitor> struct call_frame_code_block_visitor {
- factor_vm *parent;
- Visitor visitor;
+/* Code block visitors iterate over sets of code blocks, applying a functor to
+each one. The functor returns a new code_block pointer, which may or may not
+equal the old one. This is stored back to the original location.
- explicit call_frame_code_block_visitor(factor_vm *parent_, Visitor visitor_) :
- parent(parent_), visitor(visitor_) {}
+This is used by GC's sweep and compact phases, and the implementation of the
+modify-code-heap primitive.
- void operator()(stack_frame *frame)
- {
- cell offset = (cell)FRAME_RETURN_ADDRESS(frame,parent) - (cell)frame->xt;
+Iteration is driven by visit_*() methods. Some of them define GC roots:
+- visit_context_code_blocks()
+- visit_callback_code_blocks() */
+
+template<typename Fixup> struct code_block_visitor {
+ factor_vm *parent;
+ Fixup fixup;
- code_block *new_block = visitor(parent->frame_code(frame));
- frame->xt = new_block->xt();
+ explicit code_block_visitor(factor_vm *parent_, Fixup fixup_) :
+ parent(parent_), fixup(fixup_) {}
- FRAME_RETURN_ADDRESS(frame,parent) = (void *)((cell)frame->xt + offset);
- }
+ code_block *visit_code_block(code_block *compiled);
+ void visit_object_code_block(object *obj);
+ void visit_embedded_code_pointers(code_block *compiled);
+ void visit_context_code_blocks();
+ void visit_uninitialized_code_blocks();
+
+ void visit_code_roots();
};
-template<typename Visitor> struct callback_code_block_visitor {
- callback_heap *callbacks;
- Visitor visitor;
+template<typename Fixup>
+code_block *code_block_visitor<Fixup>::visit_code_block(code_block *compiled)
+{
+ return fixup.fixup_code(compiled);
+}
+
+template<typename Fixup>
+struct call_frame_code_block_visitor {
+ factor_vm *parent;
+ Fixup fixup;
- explicit callback_code_block_visitor(callback_heap *callbacks_, Visitor visitor_) :
- callbacks(callbacks_), visitor(visitor_) {}
+ explicit call_frame_code_block_visitor(factor_vm *parent_, Fixup fixup_) :
+ parent(parent_), fixup(fixup_) {}
- void operator()(callback *stub)
+ void operator()(stack_frame *frame)
{
- stub->compiled = visitor(stub->compiled);
- callbacks->update(stub);
+ cell offset = parent->frame_offset(frame);
+ code_block *compiled = fixup.fixup_code(parent->frame_code(frame));
+ frame->entry_point = compiled->entry_point();
+ parent->set_frame_offset(frame,offset);
}
};
-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)
+template<typename Fixup>
+void code_block_visitor<Fixup>::visit_object_code_block(object *obj)
+{
+ switch(obj->type())
{
- switch(obj->type())
+ case WORD_TYPE:
+ {
+ word *w = (word *)obj;
+ if(w->entry_point)
+ w->entry_point = visit_code_block(w->code())->entry_point();
+ break;
+ }
+ case QUOTATION_TYPE:
+ {
+ quotation *q = (quotation *)obj;
+ if(q->entry_point)
+ q->entry_point = visit_code_block(q->code())->entry_point();
+ break;
+ }
+ case CALLSTACK_TYPE:
{
- 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;
- }
+ callstack *stack = (callstack *)obj;
+ call_frame_code_block_visitor<Fixup> call_frame_visitor(parent,fixup);
+ parent->iterate_callstack_object(stack,call_frame_visitor);
+ break;
}
}
+}
+
+template<typename Fixup>
+struct embedded_code_pointers_visitor {
+ Fixup fixup;
+
+ explicit embedded_code_pointers_visitor(Fixup fixup_) : fixup(fixup_) {}
- void visit_context_code_blocks()
+ void operator()(instruction_operand op)
{
- call_frame_code_block_visitor<Visitor> call_frame_visitor(parent,visitor);
- parent->iterate_active_frames(call_frame_visitor);
+ relocation_type type = op.rel_type();
+ if(type == RT_ENTRY_POINT
+ || type == RT_ENTRY_POINT_PIC
+ || type == RT_ENTRY_POINT_PIC_TAIL)
+ op.store_code_block(fixup.fixup_code(op.load_code_block()));
}
+};
- void visit_callback_code_blocks()
+template<typename Fixup>
+void code_block_visitor<Fixup>::visit_embedded_code_pointers(code_block *compiled)
+{
+ if(!parent->code->uninitialized_p(compiled))
{
- callback_code_block_visitor<Visitor> callback_visitor(parent->callbacks,visitor);
- parent->callbacks->iterate(callback_visitor);
+ embedded_code_pointers_visitor<Fixup> operand_visitor(fixup);
+ compiled->each_instruction_operand(operand_visitor);
}
+}
-};
+template<typename Fixup>
+void code_block_visitor<Fixup>::visit_context_code_blocks()
+{
+ call_frame_code_block_visitor<Fixup> call_frame_visitor(parent,fixup);
+ parent->iterate_active_callstacks(call_frame_visitor);
+}
+
+template<typename Fixup>
+void code_block_visitor<Fixup>::visit_uninitialized_code_blocks()
+{
+ 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(
+ fixup.fixup_code(iter->first),
+ iter->second));
+ }
+
+ parent->code->uninitialized_blocks = new_uninitialized_blocks;
+}
+
+template<typename Fixup>
+void code_block_visitor<Fixup>::visit_code_roots()
+{
+ visit_uninitialized_code_blocks();
+}
}