struct compaction_sizer { mark_bits *forwarding_map; compaction_sizer(mark_bits *forwarding_map_) : forwarding_map(forwarding_map_) {} cell size(object *obj) { if(obj->h.hi_tag() == TUPLE_TYPE) { /* The tuple layout may or may not have been forwarded already. Tricky. */ object *layout_obj = (object *)UNTAG(((tuple *)this)->layout); tuple_layout *layout; if(layout_obj < obj) { /* It's already been moved up; dereference through forwarding map to get the size */ layout = (tuple_layout *)forwarding_map->forward_block(layout_obj); } else { /* It hasn't been moved up yet; dereference directly */ layout = (tuple_layout *)layout_obj; } return layout->size; } else return obj->size(); } }; /* During compaction we have to be careful and measure object sizes differently */ template template void free_list_allocator::iterate(Iterator &iter, Sizer &sizer) { Block *scan = first_block(); Block *end = last_block(); while(scan != end) { cell size = sizer(scan); Block *next = (Block *)((cell)scan + size); if(!scan->free_p()) iter(scan,size); scan = next; } } template struct standard_sizer { cell operator()(Block *block) { return block->size(); } }; template template void free_list_allocator::iterate(Iterator &iter) { standard_sizer sizer; iterate(iter,sizer); }