]> gitweb.factorcode.org Git - factor.git/blob - vm/code_block_visitor.hpp
vm: strip out call-counting profiler
[factor.git] / vm / code_block_visitor.hpp
1 namespace factor
2 {
3
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.
7
8 This is used by GC's sweep and compact phases, and the implementation of the
9 modify-code-heap primitive.
10
11 Iteration is driven by visit_*() methods. Some of them define GC roots:
12 - visit_context_code_blocks()
13 - visit_callback_code_blocks() */
14  
15 template<typename Fixup> struct code_block_visitor {
16         factor_vm *parent;
17         Fixup fixup;
18
19         explicit code_block_visitor(factor_vm *parent_, Fixup fixup_) :
20                 parent(parent_), fixup(fixup_) {}
21
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();
27
28         void visit_code_roots();
29 };
30
31 template<typename Fixup>
32 code_block *code_block_visitor<Fixup>::visit_code_block(code_block *compiled)
33 {
34         return fixup.fixup_code(compiled);
35 }
36
37 template<typename Fixup>
38 struct call_frame_code_block_visitor {
39         factor_vm *parent;
40         Fixup fixup;
41
42         explicit call_frame_code_block_visitor(factor_vm *parent_, Fixup fixup_) :
43                 parent(parent_), fixup(fixup_) {}
44
45         void operator()(stack_frame *frame)
46         {
47                 cell offset = parent->frame_offset(frame);
48                 code_block *compiled = fixup.fixup_code(parent->frame_code(frame));
49                 frame->entry_point = compiled->entry_point();
50                 parent->set_frame_offset(frame,offset);
51         }
52 };
53
54 template<typename Fixup>
55 void code_block_visitor<Fixup>::visit_object_code_block(object *obj)
56 {
57         switch(obj->type())
58         {
59         case WORD_TYPE:
60                 {
61                         word *w = (word *)obj;
62                         if(w->entry_point)
63                                 w->entry_point = visit_code_block(w->code())->entry_point();
64                         break;
65                 }
66         case QUOTATION_TYPE:
67                 {
68                         quotation *q = (quotation *)obj;
69                         if(q->entry_point)
70                                 q->entry_point = visit_code_block(q->code())->entry_point();
71                         break;
72                 }
73         case CALLSTACK_TYPE:
74                 {
75                         callstack *stack = (callstack *)obj;
76                         call_frame_code_block_visitor<Fixup> call_frame_visitor(parent,fixup);
77                         parent->iterate_callstack_object(stack,call_frame_visitor);
78                         break;
79                 }
80         }
81 }
82
83 template<typename Fixup>
84 struct embedded_code_pointers_visitor {
85         Fixup fixup;
86
87         explicit embedded_code_pointers_visitor(Fixup fixup_) : fixup(fixup_) {}
88
89         void operator()(instruction_operand op)
90         {
91                 relocation_type type = op.rel_type();
92                 if(type == RT_ENTRY_POINT
93                         || type == RT_ENTRY_POINT_PIC
94                         || type == RT_ENTRY_POINT_PIC_TAIL)
95                         op.store_code_block(fixup.fixup_code(op.load_code_block()));
96         }
97 };
98
99 template<typename Fixup>
100 void code_block_visitor<Fixup>::visit_embedded_code_pointers(code_block *compiled)
101 {
102         if(!parent->code->uninitialized_p(compiled))
103         {
104                 embedded_code_pointers_visitor<Fixup> operand_visitor(fixup);
105                 compiled->each_instruction_operand(operand_visitor);
106         }
107 }
108
109 template<typename Fixup>
110 void code_block_visitor<Fixup>::visit_context_code_blocks()
111 {
112         call_frame_code_block_visitor<Fixup> call_frame_visitor(parent,fixup);
113         parent->iterate_active_callstacks(call_frame_visitor);
114 }
115
116 template<typename Fixup>
117 void code_block_visitor<Fixup>::visit_uninitialized_code_blocks()
118 {
119         std::map<code_block *, cell> *uninitialized_blocks = &parent->code->uninitialized_blocks;
120         std::map<code_block *, cell>::const_iterator iter = uninitialized_blocks->begin();
121         std::map<code_block *, cell>::const_iterator end = uninitialized_blocks->end();
122
123         std::map<code_block *, cell> new_uninitialized_blocks;
124         for(; iter != end; iter++)
125         {
126                 new_uninitialized_blocks.insert(std::make_pair(
127                         fixup.fixup_code(iter->first),
128                         iter->second));
129         }
130
131         parent->code->uninitialized_blocks = new_uninitialized_blocks;
132 }
133
134 template<typename Fixup>
135 void code_block_visitor<Fixup>::visit_code_roots()
136 {
137         visit_uninitialized_code_blocks();
138 }
139
140 }