]> gitweb.factorcode.org Git - factor.git/blob - vm/code_block_visitor.hpp
Merge branch 'no_literal_table' of git://factorcode.org/git/factor into no_literal_table
[factor.git] / vm / code_block_visitor.hpp
1 namespace factor
2 {
3
4 template<typename Visitor> struct code_block_visitor {
5         factor_vm *parent;
6         Visitor visitor;
7
8         explicit code_block_visitor(factor_vm *parent_, Visitor visitor_) :
9                 parent(parent_), visitor(visitor_) {}
10
11         void visit_object_code_block(object *obj);
12         void visit_embedded_code_pointers(code_block *compiled);
13         void visit_context_code_blocks();
14         void visit_callback_code_blocks();
15 };
16
17 template<typename Visitor>
18 struct call_frame_code_block_visitor {
19         factor_vm *parent;
20         Visitor visitor;
21
22         explicit call_frame_code_block_visitor(factor_vm *parent_, Visitor visitor_) :
23                 parent(parent_), visitor(visitor_) {}
24
25         void operator()(stack_frame *frame)
26         {
27                 cell offset = (cell)FRAME_RETURN_ADDRESS(frame,parent) - (cell)frame->xt;
28
29                 code_block *new_block = visitor(parent->frame_code(frame));
30                 frame->xt = new_block->xt();
31
32                 FRAME_RETURN_ADDRESS(frame,parent) = (void *)((cell)frame->xt + offset);
33         }
34 };
35
36 template<typename Visitor>
37 void code_block_visitor<Visitor>::visit_object_code_block(object *obj)
38 {
39         switch(obj->type())
40         {
41         case WORD_TYPE:
42                 {
43                         word *w = (word *)obj;
44                         if(w->code)
45                                 w->code = visitor(w->code);
46                         if(w->profiling)
47                                 w->profiling = visitor(w->profiling);
48
49                         parent->update_word_xt(w);
50                         break;
51                 }
52         case QUOTATION_TYPE:
53                 {
54                         quotation *q = (quotation *)obj;
55                         if(q->code)
56                                 parent->set_quot_xt(q,visitor(q->code));
57                         else
58                                 q->xt = (void *)lazy_jit_compile;
59                         break;
60                 }
61         case CALLSTACK_TYPE:
62                 {
63                         callstack *stack = (callstack *)obj;
64                         call_frame_code_block_visitor<Visitor> call_frame_visitor(parent,visitor);
65                         parent->iterate_callstack_object(stack,call_frame_visitor);
66                         break;
67                 }
68         }
69 }
70
71 template<typename Visitor>
72 struct embedded_code_pointers_visitor {
73         Visitor visitor;
74
75         explicit embedded_code_pointers_visitor(Visitor visitor_) : visitor(visitor_) {}
76
77         void operator()(relocation_entry rel, cell index, code_block *compiled)
78         {
79                 relocation_type type = rel.rel_type();
80                 if(type == RT_XT || type == RT_XT_PIC || type == RT_XT_PIC_TAIL)
81                 {
82                         instruction_operand op(rel.rel_class(),rel.rel_offset() + (cell)compiled->xt());
83                         op.store_code_block(visitor(op.load_code_block()));
84                 }
85         }
86 };
87
88 template<typename Visitor>
89 void code_block_visitor<Visitor>::visit_embedded_code_pointers(code_block *compiled)
90 {
91         if(!parent->code->needs_fixup_p(compiled))
92         {
93                 embedded_code_pointers_visitor<Visitor> visitor(this->visitor);
94                 parent->iterate_relocations(compiled,visitor);
95         }
96 }
97
98 template<typename Visitor>
99 void code_block_visitor<Visitor>::visit_context_code_blocks()
100 {
101         call_frame_code_block_visitor<Visitor> call_frame_visitor(parent,visitor);
102         parent->iterate_active_frames(call_frame_visitor);
103 }
104
105 template<typename Visitor>
106 struct callback_code_block_visitor {
107         callback_heap *callbacks;
108         Visitor visitor;
109
110         explicit callback_code_block_visitor(callback_heap *callbacks_, Visitor visitor_) :
111                 callbacks(callbacks_), visitor(visitor_) {}
112
113         void operator()(callback *stub)
114         {
115                 stub->compiled = visitor(stub->compiled);
116                 callbacks->update(stub);
117         }
118 };
119
120 template<typename Visitor>
121 void code_block_visitor<Visitor>::visit_callback_code_blocks()
122 {
123         callback_code_block_visitor<Visitor> callback_visitor(parent->callbacks,visitor);
124         parent->callbacks->iterate(callback_visitor);
125 }
126
127 }