]> gitweb.factorcode.org Git - factor.git/blob - vm/code_block_visitor.hpp
vm: new implementation of modify-code-heap that doesn't use literal tables
[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                         break;
58                 }
59         case CALLSTACK_TYPE:
60                 {
61                         callstack *stack = (callstack *)obj;
62                         call_frame_code_block_visitor<Visitor> call_frame_visitor(parent,visitor);
63                         parent->iterate_callstack_object(stack,call_frame_visitor);
64                         break;
65                 }
66         }
67 }
68
69 template<typename Visitor>
70 struct embedded_code_pointers_visitor {
71         Visitor visitor;
72
73         explicit embedded_code_pointers_visitor(Visitor visitor_) : visitor(visitor_) {}
74
75         void operator()(relocation_entry rel, cell index, code_block *compiled)
76         {
77                 relocation_type type = rel.rel_type();
78                 if(type == RT_XT || type == RT_XT_PIC || type == RT_XT_PIC_TAIL)
79                 {
80                         instruction_operand op(rel.rel_class(),rel.rel_offset() + (cell)compiled->xt());
81                         op.store_code_block(visitor(op.load_code_block()));
82                 }
83         }
84 };
85
86 template<typename Visitor>
87 void code_block_visitor<Visitor>::visit_embedded_code_pointers(code_block *compiled)
88 {
89         if(!parent->code->needs_fixup_p(compiled))
90         {
91                 embedded_code_pointers_visitor<Visitor> visitor(this->visitor);
92                 parent->iterate_relocations(compiled,visitor);
93         }
94 }
95
96 template<typename Visitor>
97 void code_block_visitor<Visitor>::visit_context_code_blocks()
98 {
99         call_frame_code_block_visitor<Visitor> call_frame_visitor(parent,visitor);
100         parent->iterate_active_frames(call_frame_visitor);
101 }
102
103 template<typename Visitor>
104 struct callback_code_block_visitor {
105         callback_heap *callbacks;
106         Visitor visitor;
107
108         explicit callback_code_block_visitor(callback_heap *callbacks_, Visitor visitor_) :
109                 callbacks(callbacks_), visitor(visitor_) {}
110
111         void operator()(callback *stub)
112         {
113                 stub->compiled = visitor(stub->compiled);
114                 callbacks->update(stub);
115         }
116 };
117
118 template<typename Visitor>
119 void code_block_visitor<Visitor>::visit_callback_code_blocks()
120 {
121         callback_code_block_visitor<Visitor> callback_visitor(parent->callbacks,visitor);
122         parent->callbacks->iterate(callback_visitor);
123 }
124
125 }