5 void factor_vm::update_fixup_set_for_compaction(mark_bits<code_block> *forwarding_map)
7 std::set<code_block *>::const_iterator iter = code->needs_fixup.begin();
8 std::set<code_block *>::const_iterator end = code->needs_fixup.end();
10 std::set<code_block *> new_needs_fixup;
11 for(; iter != end; iter++)
13 printf("a block needs fixup\n");
14 new_needs_fixup.insert(forwarding_map->forward_block(*iter));
17 code->needs_fixup = new_needs_fixup;
20 template<typename Block> struct forwarder {
21 mark_bits<Block> *forwarding_map;
23 explicit forwarder(mark_bits<Block> *forwarding_map_) :
24 forwarding_map(forwarding_map_) {}
26 Block *operator()(Block *block)
28 return forwarding_map->forward_block(block);
32 static inline cell tuple_size_with_forwarding(mark_bits<object> *forwarding_map, object *obj)
34 /* The tuple layout may or may not have been forwarded already. Tricky. */
35 object *layout_obj = (object *)UNTAG(((tuple *)obj)->layout);
40 /* It's already been moved up; dereference through forwarding
41 map to get the size */
42 layout = (tuple_layout *)forwarding_map->forward_block(layout_obj);
46 /* It hasn't been moved up yet; dereference directly */
47 layout = (tuple_layout *)layout_obj;
50 return tuple_size(layout);
53 struct compaction_sizer {
54 mark_bits<object> *forwarding_map;
56 explicit compaction_sizer(mark_bits<object> *forwarding_map_) :
57 forwarding_map(forwarding_map_) {}
59 cell operator()(object *obj)
61 if(!forwarding_map->marked_p(obj))
62 return forwarding_map->unmarked_block_size(obj);
63 else if(obj->type() == TUPLE_TYPE)
64 return align(tuple_size_with_forwarding(forwarding_map,obj),data_alignment);
70 struct object_compaction_updater {
72 slot_visitor<forwarder<object> > slot_forwarder;
73 code_block_visitor<forwarder<code_block> > code_forwarder;
74 mark_bits<object> *data_forwarding_map;
75 object_start_map *starts;
77 explicit object_compaction_updater(factor_vm *parent_,
78 slot_visitor<forwarder<object> > slot_forwarder_,
79 code_block_visitor<forwarder<code_block> > code_forwarder_,
80 mark_bits<object> *data_forwarding_map_) :
82 slot_forwarder(slot_forwarder_),
83 code_forwarder(code_forwarder_),
84 data_forwarding_map(data_forwarding_map_),
85 starts(&parent->data->tenured->starts) {}
87 void operator()(object *old_address, object *new_address, cell size)
90 if(old_address->type() == TUPLE_TYPE)
91 payload_start = tuple_size_with_forwarding(data_forwarding_map,old_address);
93 payload_start = old_address->binary_payload_start();
95 memmove(new_address,old_address,size);
97 slot_forwarder.visit_slots(new_address,payload_start);
98 code_forwarder.visit_object_code_block(new_address);
99 starts->record_object_start_offset(new_address);
103 struct relative_address_updater {
105 code_block *old_address;
107 explicit relative_address_updater(factor_vm *parent_, code_block *old_address_) :
108 parent(parent_), old_address(old_address_) {}
110 void operator()(relocation_entry rel, cell index, code_block *compiled)
112 instruction_operand op(rel.rel_class(),rel.rel_offset() + (cell)compiled->xt());
114 relocation_type type = rel.rel_type();
116 if(type == RT_HERE || type == RT_THIS)
117 value = parent->compute_relocation(rel,index,compiled);
119 value = op.load_value(rel.rel_offset() + (cell)old_address->xt());
121 op.store_value(value);
125 template<typename SlotForwarder, typename CodeBlockForwarder>
126 struct code_block_compaction_updater {
128 slot_visitor<forwarder<object> > slot_forwarder;
129 code_block_visitor<forwarder<code_block> > code_forwarder;
131 explicit code_block_compaction_updater(factor_vm *parent_,
132 slot_visitor<forwarder<object> > slot_forwarder_,
133 code_block_visitor<forwarder<code_block> > code_forwarder_) :
134 parent(parent_), slot_forwarder(slot_forwarder_), code_forwarder(code_forwarder_) {}
136 void operator()(code_block *old_address, code_block *new_address, cell size)
138 memmove(new_address,old_address,size);
140 slot_forwarder.visit_code_block_objects(new_address);
142 relative_address_updater updater(parent,old_address);
143 parent->iterate_relocations(new_address,updater);
145 slot_forwarder.visit_embedded_literals(new_address);
146 code_forwarder.visit_embedded_code_pointers(new_address);
150 /* Compact data and code heaps */
151 void factor_vm::collect_compact_impl(bool trace_contexts_p)
153 current_gc->event->started_compaction();
155 tenured_space *tenured = data->tenured;
156 mark_bits<object> *data_forwarding_map = &tenured->state;
157 mark_bits<code_block> *code_forwarding_map = &code->allocator->state;
159 /* Figure out where blocks are going to go */
160 data_forwarding_map->compute_forwarding();
161 code_forwarding_map->compute_forwarding();
163 update_fixup_set_for_compaction(code_forwarding_map);
165 slot_visitor<forwarder<object> > slot_forwarder(this,forwarder<object>(data_forwarding_map));
166 code_block_visitor<forwarder<code_block> > code_forwarder(this,forwarder<code_block>(code_forwarding_map));
168 /* Object start offsets get recomputed by the object_compaction_updater */
169 data->tenured->starts.clear_object_start_offsets();
171 /* Slide everything in tenured space up, and update data and code heap
172 pointers inside objects. */
173 object_compaction_updater object_updater(this,slot_forwarder,code_forwarder,data_forwarding_map);
174 compaction_sizer object_sizer(data_forwarding_map);
175 tenured->compact(object_updater,object_sizer);
177 /* Slide everything in the code heap up, and update data and code heap
178 pointers inside code blocks. */
179 code_block_compaction_updater<slot_visitor<forwarder<object> >, code_block_visitor<forwarder<code_block> > > code_block_updater(this,slot_forwarder,code_forwarder);
180 standard_sizer<code_block> code_block_sizer;
181 code->allocator->compact(code_block_updater,code_block_sizer);
183 slot_forwarder.visit_roots();
186 slot_forwarder.visit_contexts();
187 code_forwarder.visit_context_code_blocks();
188 code_forwarder.visit_callback_code_blocks();
191 update_code_roots_for_compaction();
193 current_gc->event->ended_compaction();
196 struct object_code_block_updater {
197 code_block_visitor<forwarder<code_block> > code_forwarder;
199 explicit object_code_block_updater(code_block_visitor<forwarder<code_block> > code_forwarder_) :
200 code_forwarder(code_forwarder_) {}
202 void operator()(object *obj)
204 code_forwarder.visit_object_code_block(obj);
208 struct code_block_grow_heap_updater {
211 explicit code_block_grow_heap_updater(factor_vm *parent_) : parent(parent_) {}
213 void operator()(code_block *old_address, code_block *new_address, cell size)
215 memmove(new_address,old_address,size);
216 parent->relocate_code_block(new_address);
220 /* Compact just the code heap, after growing the data heap */
221 void factor_vm::collect_compact_code_impl(bool trace_contexts_p)
223 /* Figure out where blocks are going to go */
224 mark_bits<code_block> *code_forwarding_map = &code->allocator->state;
225 code_forwarding_map->compute_forwarding();
227 update_fixup_set_for_compaction(code_forwarding_map);
229 code_block_visitor<forwarder<code_block> > code_forwarder(this,forwarder<code_block>(code_forwarding_map));
233 code_forwarder.visit_context_code_blocks();
234 code_forwarder.visit_callback_code_blocks();
237 /* Update code heap references in data heap */
238 object_code_block_updater updater(code_forwarder);
239 each_object(updater);
241 /* Slide everything in the code heap up, and update code heap
242 pointers inside code blocks. */
243 code_block_grow_heap_updater code_block_updater(this);
244 standard_sizer<code_block> code_block_sizer;
245 code->allocator->compact(code_block_updater,code_block_sizer);
247 update_code_roots_for_compaction();