]> gitweb.factorcode.org Git - factor.git/blob - vm/slot_visitor.hpp
0ab9cc171d703f36e0e4dee65f09c892f87bc822
[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_slots(object *ptr, cell payload_start);
30         void visit_slots(object *ptr);
31         void visit_stack_elements(segment *region, cell *top);
32         void visit_data_roots();
33         void visit_bignum_roots();
34         void visit_callback_roots();
35         void visit_literal_table_roots();
36         void visit_roots();
37         void visit_contexts();
38         void visit_code_block_objects(code_block *compiled);
39         void visit_embedded_literals(code_block *compiled);
40 };
41
42 template<typename Visitor>
43 cell slot_visitor<Visitor>::visit_pointer(cell pointer)
44 {
45         if(immediate_p(pointer)) return pointer;
46
47         object *untagged = untag<object>(pointer);
48         untagged = visitor(untagged);
49         return RETAG(untagged,TAG(pointer));
50 }
51
52 template<typename Visitor>
53 void slot_visitor<Visitor>::visit_handle(cell *handle)
54 {
55         *handle = visit_pointer(*handle);
56 }
57
58 template<typename Visitor>
59 void slot_visitor<Visitor>::visit_slots(object *ptr, cell payload_start)
60 {
61         cell *slot = (cell *)ptr;
62         cell *end = (cell *)((cell)ptr + payload_start);
63
64         if(slot != end)
65         {
66                 slot++;
67                 for(; slot < end; slot++) visit_handle(slot);
68         }
69 }
70
71 template<typename Visitor>
72 void slot_visitor<Visitor>::visit_slots(object *ptr)
73 {
74         visit_slots(ptr,ptr->binary_payload_start());
75 }
76
77 template<typename Visitor>
78 void slot_visitor<Visitor>::visit_stack_elements(segment *region, cell *top)
79 {
80         for(cell *ptr = (cell *)region->start; ptr <= top; ptr++)
81                 visit_handle(ptr);
82 }
83
84 template<typename Visitor>
85 void slot_visitor<Visitor>::visit_data_roots()
86 {
87         std::vector<data_root_range>::const_iterator iter = parent->data_roots.begin();
88         std::vector<data_root_range>::const_iterator end = parent->data_roots.end();
89
90         for(; iter < end; iter++)
91         {
92                 data_root_range r = *iter;
93                 for(cell index = 0; index < r.len; index++)
94                         visit_handle(r.start + index);
95         }
96 }
97
98 template<typename Visitor>
99 void slot_visitor<Visitor>::visit_bignum_roots()
100 {
101         std::vector<cell>::const_iterator iter = parent->bignum_roots.begin();
102         std::vector<cell>::const_iterator end = parent->bignum_roots.end();
103
104         for(; iter < end; iter++)
105         {
106                 cell *handle = (cell *)(*iter);
107
108                 if(*handle)
109                         *handle = (cell)visitor(*(object **)handle);
110         }
111 }
112
113 template<typename Visitor>
114 struct callback_slot_visitor {
115         callback_heap *callbacks;
116         slot_visitor<Visitor> *visitor;
117
118         explicit callback_slot_visitor(callback_heap *callbacks_, slot_visitor<Visitor> *visitor_) :
119                 callbacks(callbacks_), visitor(visitor_) {}
120
121         void operator()(code_block *stub)
122         {
123                 visitor->visit_handle(&stub->owner);
124         }
125 };
126
127 template<typename Visitor>
128 void slot_visitor<Visitor>::visit_callback_roots()
129 {
130         callback_slot_visitor<Visitor> callback_visitor(parent->callbacks,this);
131         parent->callbacks->each_callback(callback_visitor);
132 }
133
134 template<typename Visitor>
135 void slot_visitor<Visitor>::visit_literal_table_roots()
136 {
137         std::map<code_block *, cell> *uninitialized_blocks = &parent->code->uninitialized_blocks;
138         std::map<code_block *, cell>::const_iterator iter = uninitialized_blocks->begin();
139         std::map<code_block *, cell>::const_iterator end = uninitialized_blocks->end();
140
141         std::map<code_block *, cell> new_uninitialized_blocks;
142         for(; iter != end; iter++)
143         {
144                 new_uninitialized_blocks.insert(std::make_pair(
145                         iter->first,
146                         visit_pointer(iter->second)));
147         }
148
149         parent->code->uninitialized_blocks = new_uninitialized_blocks;
150 }
151
152 template<typename Visitor>
153 void slot_visitor<Visitor>::visit_roots()
154 {
155         visit_handle(&parent->true_object);
156         visit_handle(&parent->bignum_zero);
157         visit_handle(&parent->bignum_pos_one);
158         visit_handle(&parent->bignum_neg_one);
159
160         visit_data_roots();
161         visit_bignum_roots();
162         visit_callback_roots();
163         visit_literal_table_roots();
164
165         for(cell i = 0; i < special_object_count; i++)
166                 visit_handle(&parent->special_objects[i]);
167 }
168
169 template<typename Visitor>
170 void slot_visitor<Visitor>::visit_contexts()
171 {
172         context *ctx = parent->ctx;
173
174         while(ctx)
175         {
176                 visit_stack_elements(ctx->datastack_region,(cell *)ctx->datastack);
177                 visit_stack_elements(ctx->retainstack_region,(cell *)ctx->retainstack);
178
179                 visit_handle(&ctx->catchstack_save);
180                 visit_handle(&ctx->current_callback_save);
181
182                 ctx = ctx->next;
183         }
184 }
185
186 template<typename Visitor>
187 struct literal_references_visitor {
188         slot_visitor<Visitor> *visitor;
189
190         explicit literal_references_visitor(slot_visitor<Visitor> *visitor_) : visitor(visitor_) {}
191
192         void operator()(instruction_operand op)
193         {
194                 if(op.rel_type() == RT_LITERAL)
195                         op.store_value(visitor->visit_pointer(op.load_value()));
196         }
197 };
198
199 template<typename Visitor>
200 void slot_visitor<Visitor>::visit_code_block_objects(code_block *compiled)
201 {
202         visit_handle(&compiled->owner);
203         visit_handle(&compiled->parameters);
204         visit_handle(&compiled->relocation);
205 }
206
207 template<typename Visitor>
208 void slot_visitor<Visitor>::visit_embedded_literals(code_block *compiled)
209 {
210         if(!parent->code->uninitialized_p(compiled))
211         {
212                 literal_references_visitor<Visitor> visitor(this);
213                 compiled->each_instruction_operand(visitor);
214         }
215 }
216
217 }