4 /* Code block visitors iterate over sets of code blocks, applying a functor to
5 each one. The functor returns a new code_block pointer, which may or may not
6 equal the old one. This is stored back to the original location.
8 This is used by GC's sweep and compact phases, and the implementation of the
9 modify-code-heap primitive.
11 Iteration is driven by visit_*() methods. Some of them define GC roots:
12 - visit_context_code_blocks()
13 - visit_callback_code_blocks() */
15 template<typename Fixup> struct code_block_visitor {
19 explicit code_block_visitor(factor_vm *parent_, Fixup fixup_) :
20 parent(parent_), fixup(fixup_) {}
22 code_block *visit_code_block(code_block *compiled);
23 void visit_object_code_block(object *obj);
24 void visit_embedded_code_pointers(code_block *compiled);
25 void visit_context_code_blocks();
26 void visit_uninitialized_code_blocks();
29 template<typename Fixup>
30 code_block *code_block_visitor<Fixup>::visit_code_block(code_block *compiled)
32 return fixup.fixup_code(compiled);
35 template<typename Fixup>
36 struct call_frame_code_block_visitor {
40 explicit call_frame_code_block_visitor(factor_vm *parent_, Fixup fixup_) :
41 parent(parent_), fixup(fixup_) {}
43 void operator()(stack_frame *frame)
45 cell offset = parent->frame_offset(frame);
46 code_block *compiled = fixup.fixup_code(parent->frame_code(frame));
47 frame->entry_point = compiled->entry_point();
48 parent->set_frame_offset(frame,offset);
52 template<typename Fixup>
53 void code_block_visitor<Fixup>::visit_object_code_block(object *obj)
59 word *w = (word *)obj;
61 w->code = visit_code_block(w->code);
63 w->profiling = visit_code_block(w->profiling);
65 parent->update_word_entry_point(w);
70 quotation *q = (quotation *)obj;
72 parent->set_quot_entry_point(q,visit_code_block(q->code));
77 callstack *stack = (callstack *)obj;
78 call_frame_code_block_visitor<Fixup> call_frame_visitor(parent,fixup);
79 parent->iterate_callstack_object(stack,call_frame_visitor);
85 template<typename Fixup>
86 struct embedded_code_pointers_visitor {
89 explicit embedded_code_pointers_visitor(Fixup fixup_) : fixup(fixup_) {}
91 void operator()(instruction_operand op)
93 relocation_type type = op.rel_type();
94 if(type == RT_ENTRY_POINT
95 || type == RT_ENTRY_POINT_PIC
96 || type == RT_ENTRY_POINT_PIC_TAIL)
97 op.store_code_block(fixup.fixup_code(op.load_code_block()));
101 template<typename Fixup>
102 void code_block_visitor<Fixup>::visit_embedded_code_pointers(code_block *compiled)
104 if(!parent->code->uninitialized_p(compiled))
106 embedded_code_pointers_visitor<Fixup> operand_visitor(fixup);
107 compiled->each_instruction_operand(operand_visitor);
111 template<typename Fixup>
112 void code_block_visitor<Fixup>::visit_context_code_blocks()
114 call_frame_code_block_visitor<Fixup> call_frame_visitor(parent,fixup);
115 parent->iterate_active_callstacks(call_frame_visitor);
118 template<typename Fixup>
119 void code_block_visitor<Fixup>::visit_uninitialized_code_blocks()
121 std::map<code_block *, cell> *uninitialized_blocks = &parent->code->uninitialized_blocks;
122 std::map<code_block *, cell>::const_iterator iter = uninitialized_blocks->begin();
123 std::map<code_block *, cell>::const_iterator end = uninitialized_blocks->end();
125 std::map<code_block *, cell> new_uninitialized_blocks;
126 for(; iter != end; iter++)
128 new_uninitialized_blocks.insert(std::make_pair(
129 fixup.fixup_code(iter->first),
133 parent->code->uninitialized_blocks = new_uninitialized_blocks;