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
10 Slots storing immediate values are left unchanged and the visitor does inspect
13 This is used by GC's copying, sweep and compact phases, and the implementation
14 of the become primitive.
16 Iteration is driven by visit_*() methods. Some of them define GC roots:
20 template<typename Visitor> struct slot_visitor {
24 explicit slot_visitor<Visitor>(factor_vm *parent_, Visitor visitor_) :
25 parent(parent_), visitor(visitor_) {}
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();
38 void visit_contexts();
39 void visit_code_block_objects(code_block *compiled);
40 void visit_embedded_literals(code_block *compiled);
43 template<typename Visitor>
44 cell slot_visitor<Visitor>::visit_pointer(cell pointer)
46 if(immediate_p(pointer)) return pointer;
48 object *untagged = untag<object>(pointer);
49 untagged = visitor(untagged);
50 return RETAG(untagged,TAG(pointer));
53 template<typename Visitor>
54 void slot_visitor<Visitor>::visit_handle(cell *handle)
56 *handle = visit_pointer(*handle);
59 template<typename Visitor>
60 void slot_visitor<Visitor>::visit_object_array(cell *start, cell *end)
62 while(start < end) visit_handle(start++);
65 template<typename Visitor>
66 void slot_visitor<Visitor>::visit_slots(object *ptr, cell payload_start)
68 cell *slot = (cell *)ptr;
69 cell *end = (cell *)((cell)ptr + payload_start);
74 visit_object_array(slot,end);
78 template<typename Visitor>
79 void slot_visitor<Visitor>::visit_slots(object *ptr)
81 visit_slots(ptr,ptr->binary_payload_start());
84 template<typename Visitor>
85 void slot_visitor<Visitor>::visit_stack_elements(segment *region, cell *top)
87 visit_object_array((cell *)region->start,top + 1);
90 template<typename Visitor>
91 void slot_visitor<Visitor>::visit_data_roots()
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();
96 for(; iter < end; iter++)
97 visit_object_array(iter->start,iter->start + iter->len);
100 template<typename Visitor>
101 void slot_visitor<Visitor>::visit_bignum_roots()
103 std::vector<cell>::const_iterator iter = parent->bignum_roots.begin();
104 std::vector<cell>::const_iterator end = parent->bignum_roots.end();
106 for(; iter < end; iter++)
108 cell *handle = (cell *)(*iter);
111 *handle = (cell)visitor(*(object **)handle);
115 template<typename Visitor>
116 struct callback_slot_visitor {
117 callback_heap *callbacks;
118 slot_visitor<Visitor> *visitor;
120 explicit callback_slot_visitor(callback_heap *callbacks_, slot_visitor<Visitor> *visitor_) :
121 callbacks(callbacks_), visitor(visitor_) {}
123 void operator()(code_block *stub)
125 visitor->visit_handle(&stub->owner);
129 template<typename Visitor>
130 void slot_visitor<Visitor>::visit_callback_roots()
132 callback_slot_visitor<Visitor> callback_visitor(parent->callbacks,this);
133 parent->callbacks->each_callback(callback_visitor);
136 template<typename Visitor>
137 void slot_visitor<Visitor>::visit_literal_table_roots()
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();
143 std::map<code_block *, cell> new_uninitialized_blocks;
144 for(; iter != end; iter++)
146 new_uninitialized_blocks.insert(std::make_pair(
148 visit_pointer(iter->second)));
151 parent->code->uninitialized_blocks = new_uninitialized_blocks;
154 template<typename Visitor>
155 void slot_visitor<Visitor>::visit_roots()
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);
163 visit_bignum_roots();
164 visit_callback_roots();
165 visit_literal_table_roots();
167 visit_object_array(parent->special_objects,parent->special_objects + special_object_count);
170 template<typename Visitor>
171 void slot_visitor<Visitor>::visit_contexts()
173 std::set<context *>::const_iterator begin = parent->active_contexts.begin();
174 std::set<context *>::const_iterator end = parent->active_contexts.end();
177 context *ctx = *begin;
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);
187 template<typename Visitor>
188 struct literal_references_visitor {
189 slot_visitor<Visitor> *visitor;
191 explicit literal_references_visitor(slot_visitor<Visitor> *visitor_) : visitor(visitor_) {}
193 void operator()(instruction_operand op)
195 if(op.rel_type() == RT_LITERAL)
196 op.store_value(visitor->visit_pointer(op.load_value()));
200 template<typename Visitor>
201 void slot_visitor<Visitor>::visit_code_block_objects(code_block *compiled)
203 visit_handle(&compiled->owner);
204 visit_handle(&compiled->parameters);
205 visit_handle(&compiled->relocation);
208 template<typename Visitor>
209 void slot_visitor<Visitor>::visit_embedded_literals(code_block *compiled)
211 if(!parent->code->uninitialized_p(compiled))
213 literal_references_visitor<Visitor> visitor(this);
214 compiled->each_instruction_operand(visitor);