| 
									
										
										
										
											2009-10-16 15:41:40 -04:00
										 |  |  | namespace factor | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-20 15:01:46 -04:00
										 |  |  | template<typename Block> struct mark_bits { | 
					
						
							| 
									
										
										
										
											2009-10-16 15:41:40 -04:00
										 |  |  | 	cell size; | 
					
						
							| 
									
										
										
										
											2009-10-23 00:41:02 -04:00
										 |  |  | 	cell start; | 
					
						
							| 
									
										
										
										
											2009-10-16 15:41:40 -04:00
										 |  |  | 	cell bits_size; | 
					
						
							| 
									
										
										
										
											2009-11-05 20:29:27 -05:00
										 |  |  | 	cell *marked; | 
					
						
							| 
									
										
										
										
											2009-10-16 15:41:40 -04:00
										 |  |  | 	cell *forwarding; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	void clear_mark_bits() | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2009-11-05 20:29:27 -05:00
										 |  |  | 		memset(marked,0,bits_size * sizeof(cell)); | 
					
						
							| 
									
										
										
										
											2009-10-16 15:41:40 -04:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	void clear_forwarding() | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2009-10-19 01:07:43 -04:00
										 |  |  | 		memset(forwarding,0,bits_size * sizeof(cell)); | 
					
						
							| 
									
										
										
										
											2009-10-16 15:41:40 -04:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-23 00:41:02 -04:00
										 |  |  | 	explicit mark_bits(cell size_, cell start_) : | 
					
						
							| 
									
										
										
										
											2009-10-16 15:41:40 -04:00
										 |  |  | 		size(size_), | 
					
						
							| 
									
										
										
										
											2009-10-23 00:41:02 -04:00
										 |  |  | 		start(start_), | 
					
						
							| 
									
										
										
										
											2009-12-02 01:48:41 -05:00
										 |  |  | 		bits_size(size / data_alignment / mark_bits_granularity), | 
					
						
							| 
									
										
										
										
											2009-11-05 20:29:27 -05:00
										 |  |  | 		marked(new cell[bits_size]), | 
					
						
							| 
									
										
										
										
											2009-10-19 01:07:43 -04:00
										 |  |  | 		forwarding(new cell[bits_size]) | 
					
						
							| 
									
										
										
										
											2009-10-16 15:41:40 -04:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 		clear_mark_bits(); | 
					
						
							|  |  |  | 		clear_forwarding(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	~mark_bits() | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		delete[] marked; | 
					
						
							|  |  |  | 		marked = NULL; | 
					
						
							|  |  |  | 		delete[] forwarding; | 
					
						
							|  |  |  | 		forwarding = NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-11 20:06:00 -04:00
										 |  |  | 	cell block_line(const Block *address) | 
					
						
							| 
									
										
										
										
											2009-10-19 01:07:43 -04:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2009-12-02 01:48:41 -05:00
										 |  |  | 		return (((cell)address - start) / data_alignment); | 
					
						
							| 
									
										
										
										
											2009-10-19 01:07:43 -04:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	Block *line_block(cell line) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2009-12-02 01:48:41 -05:00
										 |  |  | 		return (Block *)(line * data_alignment + start); | 
					
						
							| 
									
										
										
										
											2009-10-19 01:07:43 -04:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-11 20:06:00 -04:00
										 |  |  | 	std::pair<cell,cell> bitmap_deref(const Block *address) | 
					
						
							| 
									
										
										
										
											2009-10-16 15:41:40 -04:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2009-10-19 01:07:43 -04:00
										 |  |  | 		cell line_number = block_line(address); | 
					
						
							| 
									
										
										
										
											2009-11-05 20:29:27 -05:00
										 |  |  | 		cell word_index = (line_number / mark_bits_granularity); | 
					
						
							|  |  |  | 		cell word_shift = (line_number & mark_bits_mask); | 
					
						
							| 
									
										
										
										
											2009-10-16 15:41:40 -04:00
										 |  |  | 		return std::make_pair(word_index,word_shift); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-11 20:06:00 -04:00
										 |  |  | 	bool bitmap_elt(cell *bits, const Block *address) | 
					
						
							| 
									
										
										
										
											2009-10-16 15:41:40 -04:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2009-11-01 04:47:09 -05:00
										 |  |  | 		std::pair<cell,cell> position = bitmap_deref(address); | 
					
						
							| 
									
										
										
										
											2009-11-05 20:29:27 -05:00
										 |  |  | 		return (bits[position.first] & ((cell)1 << position.second)) != 0; | 
					
						
							| 
									
										
										
										
											2009-10-16 15:41:40 -04:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-11 20:06:00 -04:00
										 |  |  | 	Block *next_block_after(const Block *block) | 
					
						
							| 
									
										
										
										
											2009-10-20 14:47:04 -04:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2009-10-20 15:01:46 -04:00
										 |  |  | 		return (Block *)((cell)block + block->size()); | 
					
						
							| 
									
										
										
										
											2009-10-20 14:47:04 -04:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-11 20:06:00 -04:00
										 |  |  | 	void set_bitmap_range(cell *bits, const Block *address) | 
					
						
							| 
									
										
										
										
											2009-10-16 15:41:40 -04:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2009-10-19 01:07:43 -04:00
										 |  |  | 		std::pair<cell,cell> start = bitmap_deref(address); | 
					
						
							| 
									
										
										
										
											2009-10-20 14:47:04 -04:00
										 |  |  | 		std::pair<cell,cell> end = bitmap_deref(next_block_after(address)); | 
					
						
							| 
									
										
										
										
											2009-10-19 01:07:43 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-05 20:29:27 -05:00
										 |  |  | 		cell start_mask = ((cell)1 << start.second) - 1; | 
					
						
							|  |  |  | 		cell end_mask = ((cell)1 << end.second) - 1; | 
					
						
							| 
									
										
										
										
											2009-10-19 01:07:43 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		if(start.first == end.first) | 
					
						
							|  |  |  | 			bits[start.first] |= start_mask ^ end_mask; | 
					
						
							| 
									
										
										
										
											2009-10-16 15:41:40 -04:00
										 |  |  | 		else | 
					
						
							| 
									
										
										
										
											2009-10-19 01:07:43 -04:00
										 |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2009-10-22 00:24:35 -04:00
										 |  |  | #ifdef FACTOR_DEBUG
 | 
					
						
							|  |  |  | 			assert(start.first < bits_size); | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2009-10-19 01:07:43 -04:00
										 |  |  | 			bits[start.first] |= ~start_mask; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-19 03:21:11 -04:00
										 |  |  | 			for(cell index = start.first + 1; index < end.first; index++) | 
					
						
							| 
									
										
										
										
											2009-11-05 20:29:27 -05:00
										 |  |  | 				bits[index] = (cell)-1; | 
					
						
							| 
									
										
										
										
											2009-10-19 01:07:43 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-22 00:24:35 -04:00
										 |  |  | 			if(end_mask != 0) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | #ifdef FACTOR_DEBUG
 | 
					
						
							|  |  |  | 				assert(end.first < bits_size); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 				bits[end.first] |= end_mask; | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2009-10-19 01:07:43 -04:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2009-10-16 15:41:40 -04:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-11 20:06:00 -04:00
										 |  |  | 	bool marked_p(const Block *address) | 
					
						
							| 
									
										
										
										
											2009-10-16 15:41:40 -04:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 		return bitmap_elt(marked,address); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-11 20:06:00 -04:00
										 |  |  | 	void set_marked_p(const Block *address) | 
					
						
							| 
									
										
										
										
											2009-10-16 15:41:40 -04:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2009-10-19 01:07:43 -04:00
										 |  |  | 		set_bitmap_range(marked,address); | 
					
						
							| 
									
										
										
										
											2009-10-16 15:41:40 -04:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-19 01:07:43 -04:00
										 |  |  | 	/* The eventual destination of a block after compaction is just the number
 | 
					
						
							| 
									
										
										
										
											2009-10-19 03:21:11 -04:00
										 |  |  | 	of marked blocks before it. Live blocks must be marked on entry. */ | 
					
						
							| 
									
										
										
										
											2009-10-19 01:07:43 -04:00
										 |  |  | 	void compute_forwarding() | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		cell accum = 0; | 
					
						
							|  |  |  | 		for(cell index = 0; index < bits_size; index++) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			forwarding[index] = accum; | 
					
						
							|  |  |  | 			accum += popcount(marked[index]); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-05 20:29:27 -05:00
										 |  |  | 	/* We have the popcount for every mark_bits_granularity entries; look
 | 
					
						
							|  |  |  | 	up and compute the rest */ | 
					
						
							| 
									
										
										
										
											2010-06-11 20:06:00 -04:00
										 |  |  | 	Block *forward_block(const Block *original) | 
					
						
							| 
									
										
										
										
											2009-10-19 01:07:43 -04:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2009-10-25 09:07:21 -04:00
										 |  |  | #ifdef FACTOR_DEBUG
 | 
					
						
							|  |  |  | 		assert(marked_p(original)); | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2009-11-01 04:47:09 -05:00
										 |  |  | 		std::pair<cell,cell> position = bitmap_deref(original); | 
					
						
							| 
									
										
										
										
											2009-10-19 01:07:43 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-01 04:47:09 -05:00
										 |  |  | 		cell approx_popcount = forwarding[position.first]; | 
					
						
							| 
									
										
										
										
											2009-11-05 20:29:27 -05:00
										 |  |  | 		cell mask = ((cell)1 << position.second) - 1; | 
					
						
							| 
									
										
										
										
											2009-10-19 01:07:43 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-01 04:47:09 -05:00
										 |  |  | 		cell new_line_number = approx_popcount + popcount(marked[position.first] & mask); | 
					
						
							| 
									
										
										
										
											2009-10-25 09:07:21 -04:00
										 |  |  | 		Block *new_block = line_block(new_line_number); | 
					
						
							|  |  |  | #ifdef FACTOR_DEBUG
 | 
					
						
							|  |  |  | 		assert(new_block <= original); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 		return new_block; | 
					
						
							| 
									
										
										
										
											2009-10-19 04:05:20 -04:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-10-27 22:31:28 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-11 20:06:00 -04:00
										 |  |  | 	Block *next_unmarked_block_after(const Block *original) | 
					
						
							| 
									
										
										
										
											2009-11-01 04:47:09 -05:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 		std::pair<cell,cell> position = bitmap_deref(original); | 
					
						
							|  |  |  | 		cell bit_index = position.second; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		for(cell index = position.first; index < bits_size; index++) | 
					
						
							|  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2009-11-05 20:29:27 -05:00
										 |  |  | 			cell mask = ((fixnum)marked[index] >> bit_index); | 
					
						
							| 
									
										
										
										
											2009-11-01 04:47:09 -05:00
										 |  |  | 			if(~mask) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				/* Found an unmarked block on this page.
 | 
					
						
							|  |  |  | 				Stop, it's hammer time */ | 
					
						
							|  |  |  | 				cell clear_bit = rightmost_clear_bit(mask); | 
					
						
							| 
									
										
										
										
											2009-11-05 20:29:27 -05:00
										 |  |  | 				return line_block(index * mark_bits_granularity + bit_index + clear_bit); | 
					
						
							| 
									
										
										
										
											2009-11-01 04:47:09 -05:00
										 |  |  | 			} | 
					
						
							|  |  |  | 			else | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				/* No unmarked blocks on this page.
 | 
					
						
							|  |  |  | 				Keep looking */ | 
					
						
							|  |  |  | 				bit_index = 0; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* No unmarked blocks were found */ | 
					
						
							|  |  |  | 		return (Block *)(this->start + this->size); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-11 20:06:00 -04:00
										 |  |  | 	Block *next_marked_block_after(const Block *original) | 
					
						
							| 
									
										
										
										
											2009-11-01 04:47:09 -05:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2009-11-01 05:40:15 -05:00
										 |  |  | 		std::pair<cell,cell> position = bitmap_deref(original); | 
					
						
							|  |  |  | 		cell bit_index = position.second; | 
					
						
							| 
									
										
										
										
											2009-10-27 22:31:28 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-01 05:40:15 -05:00
										 |  |  | 		for(cell index = position.first; index < bits_size; index++) | 
					
						
							|  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2009-11-05 20:29:27 -05:00
										 |  |  | 			cell mask = (marked[index] >> bit_index); | 
					
						
							| 
									
										
										
										
											2009-11-01 05:40:15 -05:00
										 |  |  | 			if(mask) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				/* Found an marked block on this page.
 | 
					
						
							|  |  |  | 				Stop, it's hammer time */ | 
					
						
							|  |  |  | 				cell set_bit = rightmost_set_bit(mask); | 
					
						
							| 
									
										
										
										
											2009-11-05 20:29:27 -05:00
										 |  |  | 				return line_block(index * mark_bits_granularity + bit_index + set_bit); | 
					
						
							| 
									
										
										
										
											2009-11-01 05:40:15 -05:00
										 |  |  | 			} | 
					
						
							|  |  |  | 			else | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				/* No marked blocks on this page.
 | 
					
						
							|  |  |  | 				Keep looking */ | 
					
						
							|  |  |  | 				bit_index = 0; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2009-10-27 22:31:28 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-01 05:40:15 -05:00
										 |  |  | 		/* No marked blocks were found */ | 
					
						
							|  |  |  | 		return (Block *)(this->start + this->size); | 
					
						
							| 
									
										
										
										
											2009-11-01 04:47:09 -05:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	cell unmarked_block_size(Block *original) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		Block *next_marked = next_marked_block_after(original); | 
					
						
							|  |  |  | 		return ((char *)next_marked - (char *)original); | 
					
						
							| 
									
										
										
										
											2009-10-27 22:31:28 -04:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-10-19 04:05:20 -04:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-16 15:41:40 -04:00
										 |  |  | } |