PageRenderTime 33ms CodeModel.GetById 9ms app.highlight 21ms RepoModel.GetById 1ms app.codeStats 0ms

/vm/mark_bits.hpp

http://github.com/abeaumont/factor
C++ Header | 206 lines | 162 code | 30 blank | 14 comment | 11 complexity | 4bbaf404f4471f4d28473b76e6b94dca MD5 | raw file
  1namespace factor
  2{
  3
  4const int mark_bits_granularity = sizeof(cell) * 8;
  5const int mark_bits_mask = sizeof(cell) * 8 - 1;
  6
  7template<typename Block> struct mark_bits {
  8	cell size;
  9	cell start;
 10	cell bits_size;
 11	cell *marked;
 12	cell *forwarding;
 13
 14	void clear_mark_bits()
 15	{
 16		memset(marked,0,bits_size * sizeof(cell));
 17	}
 18
 19	void clear_forwarding()
 20	{
 21		memset(forwarding,0,bits_size * sizeof(cell));
 22	}
 23
 24	explicit mark_bits(cell size_, cell start_) :
 25		size(size_),
 26		start(start_),
 27		bits_size(size / data_alignment / mark_bits_granularity),
 28		marked(new cell[bits_size]),
 29		forwarding(new cell[bits_size])
 30	{
 31		clear_mark_bits();
 32		clear_forwarding();
 33	}
 34
 35	~mark_bits()
 36	{
 37		delete[] marked;
 38		marked = NULL;
 39		delete[] forwarding;
 40		forwarding = NULL;
 41	}
 42
 43	cell block_line(const Block *address)
 44	{
 45		return (((cell)address - start) / data_alignment);
 46	}
 47
 48	Block *line_block(cell line)
 49	{
 50		return (Block *)(line * data_alignment + start);
 51	}
 52
 53	std::pair<cell,cell> bitmap_deref(const Block *address)
 54	{
 55		cell line_number = block_line(address);
 56		cell word_index = (line_number / mark_bits_granularity);
 57		cell word_shift = (line_number & mark_bits_mask);
 58		return std::make_pair(word_index,word_shift);
 59	}
 60
 61	bool bitmap_elt(cell *bits, const Block *address)
 62	{
 63		std::pair<cell,cell> position = bitmap_deref(address);
 64		return (bits[position.first] & ((cell)1 << position.second)) != 0;
 65	}
 66
 67	Block *next_block_after(const Block *block)
 68	{
 69		return (Block *)((cell)block + block->size());
 70	}
 71
 72	void set_bitmap_range(cell *bits, const Block *address)
 73	{
 74		std::pair<cell,cell> start = bitmap_deref(address);
 75		std::pair<cell,cell> end = bitmap_deref(next_block_after(address));
 76
 77		cell start_mask = ((cell)1 << start.second) - 1;
 78		cell end_mask = ((cell)1 << end.second) - 1;
 79
 80		if(start.first == end.first)
 81			bits[start.first] |= start_mask ^ end_mask;
 82		else
 83		{
 84#ifdef FACTOR_DEBUG
 85			FACTOR_ASSERT(start.first < bits_size);
 86#endif
 87			bits[start.first] |= ~start_mask;
 88
 89			for(cell index = start.first + 1; index < end.first; index++)
 90				bits[index] = (cell)-1;
 91
 92			if(end_mask != 0)
 93			{
 94#ifdef FACTOR_DEBUG
 95				FACTOR_ASSERT(end.first < bits_size);
 96#endif
 97				bits[end.first] |= end_mask;
 98			}
 99		}
100	}
101
102	bool marked_p(const Block *address)
103	{
104		return bitmap_elt(marked,address);
105	}
106
107	void set_marked_p(const Block *address)
108	{
109		set_bitmap_range(marked,address);
110	}
111
112	/* The eventual destination of a block after compaction is just the number
113	of marked blocks before it. Live blocks must be marked on entry. */
114	void compute_forwarding()
115	{
116		cell accum = 0;
117		for(cell index = 0; index < bits_size; index++)
118		{
119			forwarding[index] = accum;
120			accum += popcount(marked[index]);
121		}
122	}
123
124	/* We have the popcount for every mark_bits_granularity entries; look
125	up and compute the rest */
126	Block *forward_block(const Block *original)
127	{
128#ifdef FACTOR_DEBUG
129		FACTOR_ASSERT(marked_p(original));
130#endif
131		std::pair<cell,cell> position = bitmap_deref(original);
132		cell offset = (cell)original & (data_alignment - 1);
133
134		cell approx_popcount = forwarding[position.first];
135		cell mask = ((cell)1 << position.second) - 1;
136
137		cell new_line_number = approx_popcount + popcount(marked[position.first] & mask);
138		Block *new_block = (Block*)((char*)line_block(new_line_number) + offset);
139#ifdef FACTOR_DEBUG
140		FACTOR_ASSERT(new_block <= original);
141#endif
142		return new_block;
143	}
144
145	Block *next_unmarked_block_after(const Block *original)
146	{
147		std::pair<cell,cell> position = bitmap_deref(original);
148		cell bit_index = position.second;
149
150		for(cell index = position.first; index < bits_size; index++)
151		{
152			cell mask = ((fixnum)marked[index] >> bit_index);
153			if(~mask)
154			{
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);
159			}
160			else
161			{
162				/* No unmarked blocks on this page.
163				Keep looking */
164				bit_index = 0;
165			}
166		}
167
168		/* No unmarked blocks were found */
169		return (Block *)(this->start + this->size);
170	}
171
172	Block *next_marked_block_after(const Block *original)
173	{
174		std::pair<cell,cell> position = bitmap_deref(original);
175		cell bit_index = position.second;
176
177		for(cell index = position.first; index < bits_size; index++)
178		{
179			cell mask = (marked[index] >> bit_index);
180			if(mask)
181			{
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);
186			}
187			else
188			{
189				/* No marked blocks on this page.
190				Keep looking */
191				bit_index = 0;
192			}
193		}
194
195		/* No marked blocks were found */
196		return (Block *)(this->start + this->size);
197	}
198
199	cell unmarked_block_size(Block *original)
200	{
201		Block *next_marked = next_marked_block_after(original);
202		return ((char *)next_marked - (char *)original);
203	}
204};
205
206}