]> gitweb.factorcode.org Git - factor.git/blob - vm/code_block_visitor.hpp
VM: Remove unnecessary explicit keywords
[factor.git] / vm / code_block_visitor.hpp
1 namespace factor {
2
3 /* Code block visitors iterate over sets of code blocks, applying a functor to
4 each one. The functor returns a new code_block pointer, which may or may not
5 equal the old one. This is stored back to the original location.
6
7 This is used by GC's sweep and compact phases, and the implementation of the
8 modify-code-heap primitive.
9
10 Iteration is driven by visit_*() methods. Some of them define GC roots:
11 - visit_context_code_blocks()
12 - visit_callback_code_blocks() */
13
14 template <typename Fixup> struct code_block_visitor {
15   factor_vm* parent;
16   Fixup fixup;
17
18   code_block_visitor(factor_vm* parent_, Fixup fixup_)
19       : parent(parent_), fixup(fixup_) {}
20
21   code_block* visit_code_block(code_block* compiled);
22   void visit_object_code_block(object* obj);
23   void visit_embedded_code_pointers(code_block* compiled);
24   void visit_context_code_blocks();
25   void visit_uninitialized_code_blocks();
26
27   void visit_code_roots();
28 };
29
30 template <typename Fixup>
31 code_block* code_block_visitor<Fixup>::visit_code_block(code_block* compiled) {
32   return fixup.fixup_code(compiled);
33 }
34
35 template <typename Fixup> struct call_frame_code_block_visitor {
36   factor_vm* parent;
37   Fixup fixup;
38
39   call_frame_code_block_visitor(factor_vm* parent_, Fixup fixup_)
40       : parent(parent_), fixup(fixup_) {}
41
42   void operator()(void* frame_top, cell frame_size, code_block* owner,
43                   void* addr) {
44     code_block* compiled =
45         Fixup::translated_code_block_map ? owner : fixup.fixup_code(owner);
46     void* fixed_addr = compiled->address_for_offset(owner->offset(addr));
47     set_frame_return_address(frame_top, fixed_addr);
48   }
49 };
50
51 template <typename Fixup>
52 void code_block_visitor<Fixup>::visit_object_code_block(object* obj) {
53   switch (obj->type()) {
54     case WORD_TYPE: {
55       word* w = (word*)obj;
56       if (w->entry_point)
57         w->entry_point = visit_code_block(w->code())->entry_point();
58       break;
59     }
60     case QUOTATION_TYPE: {
61       quotation* q = (quotation*)obj;
62       if (q->entry_point)
63         q->entry_point = visit_code_block(q->code())->entry_point();
64       break;
65     }
66     case CALLSTACK_TYPE: {
67       callstack* stack = (callstack*)obj;
68       call_frame_code_block_visitor<Fixup> call_frame_visitor(parent, fixup);
69       parent->iterate_callstack_object(stack, call_frame_visitor, fixup);
70       break;
71     }
72   }
73 }
74
75 template <typename Fixup> struct embedded_code_pointers_visitor {
76   Fixup fixup;
77
78   explicit embedded_code_pointers_visitor(Fixup fixup_) : fixup(fixup_) {}
79
80   void operator()(instruction_operand op) {
81     relocation_type type = op.rel_type();
82     if (type == RT_ENTRY_POINT || type == RT_ENTRY_POINT_PIC ||
83         type == RT_ENTRY_POINT_PIC_TAIL)
84       op.store_code_block(fixup.fixup_code(op.load_code_block()));
85   }
86 };
87
88 template <typename Fixup>
89 void code_block_visitor<Fixup>::visit_embedded_code_pointers(
90     code_block* compiled) {
91   if (!parent->code->uninitialized_p(compiled)) {
92     embedded_code_pointers_visitor<Fixup> operand_visitor(fixup);
93     compiled->each_instruction_operand(operand_visitor);
94   }
95 }
96
97 template <typename Fixup>
98 void code_block_visitor<Fixup>::visit_context_code_blocks() {
99   call_frame_code_block_visitor<Fixup> call_frame_visitor(parent, fixup);
100   parent->iterate_active_callstacks(call_frame_visitor, fixup);
101 }
102
103 template <typename Fixup>
104 void code_block_visitor<Fixup>::visit_uninitialized_code_blocks() {
105   std::map<code_block*, cell>* uninitialized_blocks =
106       &parent->code->uninitialized_blocks;
107   std::map<code_block*, cell>::const_iterator iter =
108       uninitialized_blocks->begin();
109   std::map<code_block*, cell>::const_iterator end = uninitialized_blocks->end();
110
111   std::map<code_block*, cell> new_uninitialized_blocks;
112   for (; iter != end; iter++) {
113     new_uninitialized_blocks.insert(
114         std::make_pair(fixup.fixup_code(iter->first), iter->second));
115   }
116
117   parent->code->uninitialized_blocks = new_uninitialized_blocks;
118 }
119
120 template <typename Fixup> void code_block_visitor<Fixup>::visit_code_roots() {
121   visit_uninitialized_code_blocks();
122 }
123
124 }