]> gitweb.factorcode.org Git - factor.git/blob - vm/slot_visitor.hpp
d4dd44bed1a59b81cc78b5bdc50b04dedfb8ed75
[factor.git] / vm / slot_visitor.hpp
1 namespace factor
2 {
3
4 /* Slot visitors iterate over the slots of an object, applying a functor to
5 each one that is a non-immediate slot. The pointer is untagged first. The
6 functor returns a new untagged object pointer. The return value may or may not equal the old one,
7 however the new pointer receives the same tag before being stored back to the
8 original location.
9
10 Slots storing immediate values are left unchanged and the visitor does inspect
11 them.
12
13 This is used by GC's copying, sweep and compact phases, and the implementation
14 of the become primitive.
15
16 Iteration is driven by visit_*() methods. Some of them define GC roots:
17 - visit_roots()
18 - visit_contexts() */
19
20 template<typename Visitor> struct slot_visitor {
21         factor_vm *parent;
22         Visitor visitor;
23
24         explicit slot_visitor<Visitor>(factor_vm *parent_, Visitor visitor_) :
25                 parent(parent_), visitor(visitor_) {}
26
27         cell visit_pointer(cell pointer);
28         void visit_handle(cell *handle);
29         void visit_object_array(cell *start, cell *end);
30         void visit_slots(object *ptr, cell payload_start);
31         void visit_slots(object *ptr);
32         void visit_stack_elements(segment *region, cell *top);
33         void visit_data_roots();
34         void visit_bignum_roots();
35         void visit_callback_roots();
36         void visit_literal_table_roots();
37         void visit_roots();
38         void visit_contexts();
39         void visit_code_block_objects(code_block *compiled);
40         void visit_embedded_literals(code_block *compiled);
41 };
42
43 template<typename Visitor>
44 cell slot_visitor<Visitor>::visit_pointer(cell pointer)
45 {
46         if(immediate_p(pointer)) return pointer;
47
48         object *untagged = untag<object>(pointer);
49         untagged = visitor(untagged);
50         return RETAG(untagged,TAG(pointer));
51 }
52
53 template<typename Visitor>
54 void slot_visitor<Visitor>::visit_handle(cell *handle)
55 {
56         *handle = visit_pointer(*handle);
57 }
58
59 template<typename Visitor>
60 void slot_visitor<Visitor>::visit_object_array(cell *start, cell *end)
61 {
62         while(start < end) visit_handle(start++);
63 }
64
65 template<typename Visitor>
66 void slot_visitor<Visitor>::visit_slots(object *ptr, cell payload_start)
67 {
68         cell *slot = (cell *)ptr;
69         cell *end = (cell *)((cell)ptr + payload_start);
70
71         if(slot != end)
72         {
73                 slot++;
74                 visit_object_array(slot,end);
75         }
76 }
77
78 template<typename Visitor>
79 void slot_visitor<Visitor>::visit_slots(object *ptr)
80 {
81         visit_slots(ptr,ptr->binary_payload_start());
82 }
83
84 template<typename Visitor>
85 void slot_visitor<Visitor>::visit_stack_elements(segment *region, cell *top)
86 {
87         visit_object_array((cell *)region->start,top + 1);
88 }
89
90 template<typename Visitor>
91 void slot_visitor<Visitor>::visit_data_roots()
92 {
93         std::vector<data_root_range>::const_iterator iter = parent->data_roots.begin();
94         std::vector<data_root_range>::const_iterator end = parent->data_roots.end();
95
96         for(; iter < end; iter++)
97                 visit_object_array(iter->start,iter->start + iter->len);
98 }
99
100 template<typename Visitor>
101 void slot_visitor<Visitor>::visit_bignum_roots()
102 {
103         std::vector<cell>::const_iterator iter = parent->bignum_roots.begin();
104         std::vector<cell>::const_iterator end = parent->bignum_roots.end();
105
106         for(; iter < end; iter++)
107         {
108                 cell *handle = (cell *)(*iter);
109
110                 if(*handle)
111                         *handle = (cell)visitor(*(object **)handle);
112         }
113 }
114
115 template<typename Visitor>
116 struct callback_slot_visitor {
117         callback_heap *callbacks;
118         slot_visitor<Visitor> *visitor;
119
120         explicit callback_slot_visitor(callback_heap *callbacks_, slot_visitor<Visitor> *visitor_) :
121                 callbacks(callbacks_), visitor(visitor_) {}
122
123         void operator()(code_block *stub)
124         {
125                 visitor->visit_handle(&stub->owner);
126         }
127 };
128
129 template<typename Visitor>
130 void slot_visitor<Visitor>::visit_callback_roots()
131 {
132         callback_slot_visitor<Visitor> callback_visitor(parent->callbacks,this);
133         parent->callbacks->each_callback(callback_visitor);
134 }
135
136 template<typename Visitor>
137 void slot_visitor<Visitor>::visit_literal_table_roots()
138 {
139         std::map<code_block *, cell> *uninitialized_blocks = &parent->code->uninitialized_blocks;
140         std::map<code_block *, cell>::const_iterator iter = uninitialized_blocks->begin();
141         std::map<code_block *, cell>::const_iterator end = uninitialized_blocks->end();
142
143         std::map<code_block *, cell> new_uninitialized_blocks;
144         for(; iter != end; iter++)
145         {
146                 new_uninitialized_blocks.insert(std::make_pair(
147                         iter->first,
148                         visit_pointer(iter->second)));
149         }
150
151         parent->code->uninitialized_blocks = new_uninitialized_blocks;
152 }
153
154 template<typename Visitor>
155 void slot_visitor<Visitor>::visit_roots()
156 {
157         visit_handle(&parent->true_object);
158         visit_handle(&parent->bignum_zero);
159         visit_handle(&parent->bignum_pos_one);
160         visit_handle(&parent->bignum_neg_one);
161
162         visit_data_roots();
163         visit_bignum_roots();
164         visit_callback_roots();
165         visit_literal_table_roots();
166
167         visit_object_array(parent->special_objects,parent->special_objects + special_object_count);
168 }
169
170 template<typename Visitor>
171 void slot_visitor<Visitor>::visit_contexts()
172 {
173         std::set<context *>::const_iterator begin = parent->active_contexts.begin();
174         std::set<context *>::const_iterator end = parent->active_contexts.end();
175         while(begin != end)
176         {
177                 context *ctx = *begin;
178
179                 visit_stack_elements(ctx->datastack_seg,(cell *)ctx->datastack);
180                 visit_stack_elements(ctx->retainstack_seg,(cell *)ctx->retainstack);
181                 visit_object_array(ctx->context_objects,ctx->context_objects + context_object_count);
182
183                 begin++;
184         }
185 }
186
187 template<typename Visitor>
188 struct literal_references_visitor {
189         slot_visitor<Visitor> *visitor;
190
191         explicit literal_references_visitor(slot_visitor<Visitor> *visitor_) : visitor(visitor_) {}
192
193         void operator()(instruction_operand op)
194         {
195                 if(op.rel_type() == RT_LITERAL)
196                         op.store_value(visitor->visit_pointer(op.load_value()));
197         }
198 };
199
200 template<typename Visitor>
201 void slot_visitor<Visitor>::visit_code_block_objects(code_block *compiled)
202 {
203         visit_handle(&compiled->owner);
204         visit_handle(&compiled->parameters);
205         visit_handle(&compiled->relocation);
206 }
207
208 template<typename Visitor>
209 void slot_visitor<Visitor>::visit_embedded_literals(code_block *compiled)
210 {
211         if(!parent->code->uninitialized_p(compiled))
212         {
213                 literal_references_visitor<Visitor> visitor(this);
214                 compiled->each_instruction_operand(visitor);
215         }
216 }
217
218 }