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_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();
37 void visit_contexts();
38 void visit_code_block_objects(code_block *compiled);
39 void visit_embedded_literals(code_block *compiled);
42 template<typename Visitor>
43 cell slot_visitor<Visitor>::visit_pointer(cell pointer)
45 if(immediate_p(pointer)) return pointer;
47 object *untagged = untag<object>(pointer);
48 untagged = visitor(untagged);
49 return RETAG(untagged,TAG(pointer));
52 template<typename Visitor>
53 void slot_visitor<Visitor>::visit_handle(cell *handle)
55 *handle = visit_pointer(*handle);
58 template<typename Visitor>
59 void slot_visitor<Visitor>::visit_slots(object *ptr, cell payload_start)
61 cell *slot = (cell *)ptr;
62 cell *end = (cell *)((cell)ptr + payload_start);
67 for(; slot < end; slot++) visit_handle(slot);
71 template<typename Visitor>
72 void slot_visitor<Visitor>::visit_slots(object *ptr)
74 visit_slots(ptr,ptr->binary_payload_start());
77 template<typename Visitor>
78 void slot_visitor<Visitor>::visit_stack_elements(segment *region, cell *top)
80 for(cell *ptr = (cell *)region->start; ptr <= top; ptr++)
84 template<typename Visitor>
85 void slot_visitor<Visitor>::visit_data_roots()
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();
90 for(; iter < end; iter++)
92 data_root_range r = *iter;
93 for(cell index = 0; index < r.len; index++)
94 visit_handle(r.start + index);
98 template<typename Visitor>
99 void slot_visitor<Visitor>::visit_bignum_roots()
101 std::vector<cell>::const_iterator iter = parent->bignum_roots.begin();
102 std::vector<cell>::const_iterator end = parent->bignum_roots.end();
104 for(; iter < end; iter++)
106 cell *handle = (cell *)(*iter);
109 *handle = (cell)visitor(*(object **)handle);
113 template<typename Visitor>
114 struct callback_slot_visitor {
115 callback_heap *callbacks;
116 slot_visitor<Visitor> *visitor;
118 explicit callback_slot_visitor(callback_heap *callbacks_, slot_visitor<Visitor> *visitor_) :
119 callbacks(callbacks_), visitor(visitor_) {}
121 void operator()(code_block *stub)
123 visitor->visit_handle(&stub->owner);
127 template<typename Visitor>
128 void slot_visitor<Visitor>::visit_callback_roots()
130 callback_slot_visitor<Visitor> callback_visitor(parent->callbacks,this);
131 parent->callbacks->each_callback(callback_visitor);
134 template<typename Visitor>
135 void slot_visitor<Visitor>::visit_literal_table_roots()
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();
141 std::map<code_block *, cell> new_uninitialized_blocks;
142 for(; iter != end; iter++)
144 new_uninitialized_blocks.insert(std::make_pair(
146 visit_pointer(iter->second)));
149 parent->code->uninitialized_blocks = new_uninitialized_blocks;
152 template<typename Visitor>
153 void slot_visitor<Visitor>::visit_roots()
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);
161 visit_bignum_roots();
162 visit_callback_roots();
163 visit_literal_table_roots();
165 for(cell i = 0; i < special_object_count; i++)
166 visit_handle(&parent->special_objects[i]);
169 template<typename Visitor>
170 void slot_visitor<Visitor>::visit_contexts()
172 context *ctx = parent->ctx;
176 visit_stack_elements(ctx->datastack_region,(cell *)ctx->datastack);
177 visit_stack_elements(ctx->retainstack_region,(cell *)ctx->retainstack);
179 visit_handle(&ctx->catchstack_save);
180 visit_handle(&ctx->current_callback_save);
186 template<typename Visitor>
187 struct literal_references_visitor {
188 slot_visitor<Visitor> *visitor;
190 explicit literal_references_visitor(slot_visitor<Visitor> *visitor_) : visitor(visitor_) {}
192 void operator()(instruction_operand op)
194 if(op.rel_type() == RT_LITERAL)
195 op.store_value(visitor->visit_pointer(op.load_value()));
199 template<typename Visitor>
200 void slot_visitor<Visitor>::visit_code_block_objects(code_block *compiled)
202 visit_handle(&compiled->owner);
203 visit_handle(&compiled->parameters);
204 visit_handle(&compiled->relocation);
207 template<typename Visitor>
208 void slot_visitor<Visitor>::visit_embedded_literals(code_block *compiled)
210 if(!parent->code->uninitialized_p(compiled))
212 literal_references_visitor<Visitor> visitor(this);
213 compiled->each_instruction_operand(visitor);