| 
									
										
										
										
											2013-05-11 22:13:01 -04:00
										 |  |  | namespace factor { | 
					
						
							| 
									
										
										
										
											2009-10-16 15:41:40 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-05 20:29:27 -05:00
										 |  |  | const int mark_bits_granularity = sizeof(cell) * 8; | 
					
						
							|  |  |  | const int mark_bits_mask = sizeof(cell) * 8 - 1; | 
					
						
							| 
									
										
										
										
											2009-10-16 15:41:40 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-06 11:58:24 -05:00
										 |  |  | struct mark_bits { | 
					
						
							| 
									
										
										
										
											2013-05-11 22:13:01 -04:00
										 |  |  |   cell size; | 
					
						
							|  |  |  |   cell start; | 
					
						
							|  |  |  |   cell bits_size; | 
					
						
							|  |  |  |   cell* marked; | 
					
						
							|  |  |  |   cell* forwarding; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   void clear_mark_bits() { memset(marked, 0, bits_size * sizeof(cell)); } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   void clear_forwarding() { memset(forwarding, 0, bits_size * sizeof(cell)); } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-12 23:20:43 -04:00
										 |  |  |   mark_bits(cell size, cell start) | 
					
						
							|  |  |  |       : size(size), | 
					
						
							|  |  |  |         start(start), | 
					
						
							| 
									
										
										
										
											2013-05-11 22:13:01 -04:00
										 |  |  |         bits_size(size / data_alignment / mark_bits_granularity), | 
					
						
							|  |  |  |         marked(new cell[bits_size]), | 
					
						
							|  |  |  |         forwarding(new cell[bits_size]) { | 
					
						
							|  |  |  |     clear_mark_bits(); | 
					
						
							|  |  |  |     clear_forwarding(); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   ~mark_bits() { | 
					
						
							|  |  |  |     delete[] marked; | 
					
						
							|  |  |  |     marked = NULL; | 
					
						
							|  |  |  |     delete[] forwarding; | 
					
						
							|  |  |  |     forwarding = NULL; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-06 11:58:24 -05:00
										 |  |  |   cell block_line(cell address) { | 
					
						
							|  |  |  |     return (address - start) / data_alignment; | 
					
						
							| 
									
										
										
										
											2013-05-11 22:13:01 -04:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-06 11:58:24 -05:00
										 |  |  |   cell line_block(cell line) { | 
					
						
							|  |  |  |     return line * data_alignment + start; | 
					
						
							| 
									
										
										
										
											2013-05-11 22:13:01 -04:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-06 11:58:24 -05:00
										 |  |  |   std::pair<cell, cell> bitmap_deref(const cell address) { | 
					
						
							| 
									
										
										
										
											2013-05-11 22:13:01 -04:00
										 |  |  |     cell line_number = block_line(address); | 
					
						
							|  |  |  |     cell word_index = (line_number / mark_bits_granularity); | 
					
						
							|  |  |  |     cell word_shift = (line_number & mark_bits_mask); | 
					
						
							|  |  |  |     return std::make_pair(word_index, word_shift); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-06 11:58:24 -05:00
										 |  |  |   bool bitmap_elt(cell* bits, const cell address) { | 
					
						
							| 
									
										
										
										
											2013-05-11 22:13:01 -04:00
										 |  |  |     std::pair<cell, cell> position = bitmap_deref(address); | 
					
						
							| 
									
										
										
										
											2013-05-13 00:53:47 -04:00
										 |  |  |     return (bits[position.first] & ((cell)1 << position.second)) != 0; | 
					
						
							| 
									
										
										
										
											2013-05-11 22:13:01 -04:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-06 11:58:24 -05:00
										 |  |  |   void set_bitmap_range(cell* bits, const cell address, const cell size) { | 
					
						
							| 
									
										
										
										
											2013-05-11 22:13:01 -04:00
										 |  |  |     std::pair<cell, cell> start = bitmap_deref(address); | 
					
						
							| 
									
										
										
										
											2016-11-14 16:56:33 -05:00
										 |  |  |     std::pair<cell, cell> end = bitmap_deref(address + size); | 
					
						
							| 
									
										
										
										
											2013-05-11 22:13:01 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-13 00:53:47 -04:00
										 |  |  |     cell start_mask = ((cell)1 << start.second) - 1; | 
					
						
							|  |  |  |     cell end_mask = ((cell)1 << end.second) - 1; | 
					
						
							| 
									
										
										
										
											2013-05-11 22:13:01 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (start.first == end.first) | 
					
						
							|  |  |  |       bits[start.first] |= start_mask ^ end_mask; | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |       FACTOR_ASSERT(start.first < bits_size); | 
					
						
							|  |  |  |       bits[start.first] |= ~start_mask; | 
					
						
							| 
									
										
										
										
											2009-10-19 01:07:43 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-11 22:13:01 -04:00
										 |  |  |       for (cell index = start.first + 1; index < end.first; index++) | 
					
						
							| 
									
										
										
										
											2013-05-13 00:53:47 -04:00
										 |  |  |         bits[index] = (cell)-1; | 
					
						
							| 
									
										
										
										
											2009-10-19 01:07:43 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-11 22:13:01 -04:00
										 |  |  |       if (end_mask != 0) { | 
					
						
							|  |  |  |         FACTOR_ASSERT(end.first < bits_size); | 
					
						
							|  |  |  |         bits[end.first] |= end_mask; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-06 11:58:24 -05:00
										 |  |  |   bool marked_p(const cell address) { return bitmap_elt(marked, address); } | 
					
						
							| 
									
										
										
										
											2013-05-11 22:13:01 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-06 11:58:24 -05:00
										 |  |  |   void set_marked_p(const cell address, const cell size) { | 
					
						
							|  |  |  |     set_bitmap_range(marked, address, size); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2013-05-11 22:13:01 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-21 10:26:04 -04:00
										 |  |  |   // The eventual destination of a block after compaction is just the number
 | 
					
						
							|  |  |  |   // of marked blocks before it. Live blocks must be marked on entry.
 | 
					
						
							| 
									
										
										
										
											2013-05-11 22:13:01 -04:00
										 |  |  |   void compute_forwarding() { | 
					
						
							|  |  |  |     cell accum = 0; | 
					
						
							|  |  |  |     for (cell index = 0; index < bits_size; index++) { | 
					
						
							|  |  |  |       forwarding[index] = accum; | 
					
						
							|  |  |  |       accum += popcount(marked[index]); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-21 10:26:04 -04:00
										 |  |  |   // We have the popcount for every mark_bits_granularity entries; look
 | 
					
						
							|  |  |  |   // up and compute the rest
 | 
					
						
							| 
									
										
										
										
											2015-01-06 11:58:24 -05:00
										 |  |  |   cell forward_block(const cell original) { | 
					
						
							| 
									
										
										
										
											2013-05-11 22:13:01 -04:00
										 |  |  |     FACTOR_ASSERT(marked_p(original)); | 
					
						
							|  |  |  |     std::pair<cell, cell> position = bitmap_deref(original); | 
					
						
							| 
									
										
										
										
											2015-01-06 11:58:24 -05:00
										 |  |  |     cell offset = original & (data_alignment - 1); | 
					
						
							| 
									
										
										
										
											2009-10-19 01:07:43 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-11 22:13:01 -04:00
										 |  |  |     cell approx_popcount = forwarding[position.first]; | 
					
						
							| 
									
										
										
										
											2013-05-13 00:53:47 -04:00
										 |  |  |     cell mask = ((cell)1 << position.second) - 1; | 
					
						
							| 
									
										
										
										
											2009-10-19 01:07:43 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-11 22:13:01 -04:00
										 |  |  |     cell new_line_number = | 
					
						
							|  |  |  |         approx_popcount + popcount(marked[position.first] & mask); | 
					
						
							| 
									
										
										
										
											2015-01-06 11:58:24 -05:00
										 |  |  |     cell new_block = line_block(new_line_number) + offset; | 
					
						
							| 
									
										
										
										
											2013-05-11 22:13:01 -04:00
										 |  |  |     FACTOR_ASSERT(new_block <= original); | 
					
						
							|  |  |  |     return new_block; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-06 11:58:24 -05:00
										 |  |  |   cell next_unmarked_block_after(const cell original) { | 
					
						
							| 
									
										
										
										
											2013-05-11 22:13:01 -04:00
										 |  |  |     std::pair<cell, cell> position = bitmap_deref(original); | 
					
						
							|  |  |  |     cell bit_index = position.second; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (cell index = position.first; index < bits_size; index++) { | 
					
						
							| 
									
										
										
										
											2016-11-15 23:23:54 -05:00
										 |  |  |       cell mask = ((fixnum)marked[index] >> bit_index); | 
					
						
							| 
									
										
										
										
											2013-05-11 22:13:01 -04:00
										 |  |  |       if (~mask) { | 
					
						
							| 
									
										
										
										
											2016-08-21 10:26:04 -04:00
										 |  |  |         // Found an unmarked block on this page. Stop, it's hammer time
 | 
					
						
							| 
									
										
										
										
											2013-05-11 22:13:01 -04:00
										 |  |  |         cell clear_bit = rightmost_clear_bit(mask); | 
					
						
							|  |  |  |         return line_block(index * mark_bits_granularity + bit_index + | 
					
						
							|  |  |  |                           clear_bit); | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2016-11-14 23:57:40 -05:00
										 |  |  |       // No unmarked blocks on this page. Keep looking
 | 
					
						
							|  |  |  |       bit_index = 0; | 
					
						
							| 
									
										
										
										
											2013-05-11 22:13:01 -04:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-21 10:26:04 -04:00
										 |  |  |     // No unmarked blocks were found
 | 
					
						
							| 
									
										
										
										
											2015-01-06 11:58:24 -05:00
										 |  |  |     return this->start + this->size; | 
					
						
							| 
									
										
										
										
											2013-05-11 22:13:01 -04:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-06 11:58:24 -05:00
										 |  |  |   cell next_marked_block_after(const cell original) { | 
					
						
							| 
									
										
										
										
											2013-05-11 22:13:01 -04:00
										 |  |  |     std::pair<cell, cell> position = bitmap_deref(original); | 
					
						
							|  |  |  |     cell bit_index = position.second; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (cell index = position.first; index < bits_size; index++) { | 
					
						
							| 
									
										
										
										
											2016-11-15 23:23:54 -05:00
										 |  |  |       cell mask = (marked[index] >> bit_index); | 
					
						
							| 
									
										
										
										
											2013-05-11 22:13:01 -04:00
										 |  |  |       if (mask) { | 
					
						
							| 
									
										
										
										
											2016-08-21 10:26:04 -04:00
										 |  |  |         // Found an marked block on this page. Stop, it's hammer time
 | 
					
						
							| 
									
										
										
										
											2013-05-11 22:13:01 -04:00
										 |  |  |         cell set_bit = rightmost_set_bit(mask); | 
					
						
							|  |  |  |         return line_block(index * mark_bits_granularity + bit_index + set_bit); | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2016-11-14 23:57:40 -05:00
										 |  |  |       // No marked blocks on this page. Keep looking
 | 
					
						
							|  |  |  |       bit_index = 0; | 
					
						
							| 
									
										
										
										
											2013-05-11 22:13:01 -04:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-21 10:26:04 -04:00
										 |  |  |     // No marked blocks were found
 | 
					
						
							| 
									
										
										
										
											2015-01-06 11:58:24 -05:00
										 |  |  |     return this->start + this->size; | 
					
						
							| 
									
										
										
										
											2013-05-11 22:13:01 -04:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-06 11:58:24 -05:00
										 |  |  |   cell unmarked_block_size(cell original) { | 
					
						
							|  |  |  |     cell next_marked = next_marked_block_after(original); | 
					
						
							|  |  |  |     return next_marked - original; | 
					
						
							| 
									
										
										
										
											2013-05-11 22:13:01 -04:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2009-10-19 04:05:20 -04:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-16 15:41:40 -04:00
										 |  |  | } |