4 const int block_granularity = 16;
5 const int mark_bits_granularity = sizeof(cell) * 8;
6 const int mark_bits_mask = sizeof(cell) * 8 - 1;
8 template<typename Block> struct mark_bits {
15 void clear_mark_bits()
17 memset(marked,0,bits_size * sizeof(cell));
20 void clear_forwarding()
22 memset(forwarding,0,bits_size * sizeof(cell));
25 explicit mark_bits(cell size_, cell start_) :
28 bits_size(size / block_granularity / mark_bits_granularity),
29 marked(new cell[bits_size]),
30 forwarding(new cell[bits_size])
44 cell block_line(Block *address)
46 return (((cell)address - start) / block_granularity);
49 Block *line_block(cell line)
51 return (Block *)(line * block_granularity + start);
54 std::pair<cell,cell> bitmap_deref(Block *address)
56 cell line_number = block_line(address);
57 cell word_index = (line_number / mark_bits_granularity);
58 cell word_shift = (line_number & mark_bits_mask);
59 return std::make_pair(word_index,word_shift);
62 bool bitmap_elt(cell *bits, Block *address)
64 std::pair<cell,cell> position = bitmap_deref(address);
65 return (bits[position.first] & ((cell)1 << position.second)) != 0;
68 Block *next_block_after(Block *block)
70 return (Block *)((cell)block + block->size());
73 void set_bitmap_range(cell *bits, Block *address)
75 std::pair<cell,cell> start = bitmap_deref(address);
76 std::pair<cell,cell> end = bitmap_deref(next_block_after(address));
78 cell start_mask = ((cell)1 << start.second) - 1;
79 cell end_mask = ((cell)1 << end.second) - 1;
81 if(start.first == end.first)
82 bits[start.first] |= start_mask ^ end_mask;
86 assert(start.first < bits_size);
88 bits[start.first] |= ~start_mask;
90 for(cell index = start.first + 1; index < end.first; index++)
91 bits[index] = (cell)-1;
96 assert(end.first < bits_size);
98 bits[end.first] |= end_mask;
103 bool marked_p(Block *address)
105 return bitmap_elt(marked,address);
108 void set_marked_p(Block *address)
110 set_bitmap_range(marked,address);
113 /* The eventual destination of a block after compaction is just the number
114 of marked blocks before it. Live blocks must be marked on entry. */
115 void compute_forwarding()
118 for(cell index = 0; index < bits_size; index++)
120 forwarding[index] = accum;
121 accum += popcount(marked[index]);
125 /* We have the popcount for every mark_bits_granularity entries; look
126 up and compute the rest */
127 Block *forward_block(Block *original)
130 assert(marked_p(original));
132 std::pair<cell,cell> position = bitmap_deref(original);
134 cell approx_popcount = forwarding[position.first];
135 cell mask = ((cell)1 << position.second) - 1;
137 cell new_line_number = approx_popcount + popcount(marked[position.first] & mask);
138 Block *new_block = line_block(new_line_number);
140 assert(new_block <= original);
145 Block *next_unmarked_block_after(Block *original)
147 std::pair<cell,cell> position = bitmap_deref(original);
148 cell bit_index = position.second;
150 for(cell index = position.first; index < bits_size; index++)
152 cell mask = ((fixnum)marked[index] >> bit_index);
155 /* Found an unmarked block on this page.
156 Stop, it's hammer time */
157 cell clear_bit = rightmost_clear_bit(mask);
158 return line_block(index * mark_bits_granularity + bit_index + clear_bit);
162 /* No unmarked blocks on this page.
168 /* No unmarked blocks were found */
169 return (Block *)(this->start + this->size);
172 Block *next_marked_block_after(Block *original)
174 std::pair<cell,cell> position = bitmap_deref(original);
175 cell bit_index = position.second;
177 for(cell index = position.first; index < bits_size; index++)
179 cell mask = (marked[index] >> bit_index);
182 /* Found an marked block on this page.
183 Stop, it's hammer time */
184 cell set_bit = rightmost_set_bit(mask);
185 return line_block(index * mark_bits_granularity + bit_index + set_bit);
189 /* No marked blocks on this page.
195 /* No marked blocks were found */
196 return (Block *)(this->start + this->size);
199 cell unmarked_block_size(Block *original)
201 Block *next_marked = next_marked_block_after(original);
202 return ((char *)next_marked - (char *)original);