]> gitweb.factorcode.org Git - factor.git/blob - vm/code_block_visitor.hpp
vm: remove VM_ASM_API
[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 Visitor> struct code_block_visitor {
16         factor_vm *parent;
17         Visitor visitor;
18
19         explicit code_block_visitor(factor_vm *parent_, Visitor visitor_) :
20                 parent(parent_), visitor(visitor_) {}
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
29 template<typename Visitor>
30 code_block *code_block_visitor<Visitor>::visit_code_block(code_block *compiled)
31 {
32         return visitor(compiled);
33 }
34
35 template<typename Visitor>
36 struct call_frame_code_block_visitor {
37         factor_vm *parent;
38         Visitor visitor;
39
40         explicit call_frame_code_block_visitor(factor_vm *parent_, Visitor visitor_) :
41                 parent(parent_), visitor(visitor_) {}
42
43         void operator()(stack_frame *frame)
44         {
45                 cell offset = (cell)FRAME_RETURN_ADDRESS(frame,parent) - (cell)frame->xt;
46
47                 code_block *new_block = visitor(parent->frame_code(frame));
48                 frame->xt = new_block->xt();
49
50                 FRAME_RETURN_ADDRESS(frame,parent) = (void *)((cell)frame->xt + offset);
51         }
52 };
53
54 template<typename Visitor>
55 void code_block_visitor<Visitor>::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->code)
63                                 w->code = visitor(w->code);
64                         if(w->profiling)
65                                 w->profiling = visitor(w->profiling);
66
67                         parent->update_word_xt(w);
68                         break;
69                 }
70         case QUOTATION_TYPE:
71                 {
72                         quotation *q = (quotation *)obj;
73                         if(q->code)
74                                 parent->set_quot_xt(q,visitor(q->code));
75                         else
76                                 q->xt = (void *)lazy_jit_compile_impl;
77                         break;
78                 }
79         case CALLSTACK_TYPE:
80                 {
81                         callstack *stack = (callstack *)obj;
82                         call_frame_code_block_visitor<Visitor> call_frame_visitor(parent,visitor);
83                         parent->iterate_callstack_object(stack,call_frame_visitor);
84                         break;
85                 }
86         }
87 }
88
89 template<typename Visitor>
90 struct embedded_code_pointers_visitor {
91         Visitor visitor;
92
93         explicit embedded_code_pointers_visitor(Visitor visitor_) : visitor(visitor_) {}
94
95         void operator()(instruction_operand op)
96         {
97                 relocation_type type = op.rel_type();
98                 if(type == RT_XT || type == RT_XT_PIC || type == RT_XT_PIC_TAIL)
99                         op.store_code_block(visitor(op.load_code_block()));
100         }
101 };
102
103 template<typename Visitor>
104 void code_block_visitor<Visitor>::visit_embedded_code_pointers(code_block *compiled)
105 {
106         if(!parent->code->uninitialized_p(compiled))
107         {
108                 embedded_code_pointers_visitor<Visitor> visitor(this->visitor);
109                 compiled->each_instruction_operand(visitor);
110         }
111 }
112
113 template<typename Visitor>
114 void code_block_visitor<Visitor>::visit_context_code_blocks()
115 {
116         call_frame_code_block_visitor<Visitor> call_frame_visitor(parent,visitor);
117         parent->iterate_active_frames(call_frame_visitor);
118 }
119
120 template<typename Visitor>
121 void code_block_visitor<Visitor>::visit_uninitialized_code_blocks()
122 {
123         std::map<code_block *, cell> *uninitialized_blocks = &parent->code->uninitialized_blocks;
124         std::map<code_block *, cell>::const_iterator iter = uninitialized_blocks->begin();
125         std::map<code_block *, cell>::const_iterator end = uninitialized_blocks->end();
126
127         std::map<code_block *, cell> new_uninitialized_blocks;
128         for(; iter != end; iter++)
129         {
130                 new_uninitialized_blocks.insert(std::make_pair(
131                         visitor(iter->first),
132                         iter->second));
133         }
134
135         parent->code->uninitialized_blocks = new_uninitialized_blocks;
136 }
137
138 }