]> gitweb.factorcode.org Git - factor.git/blob - vm/mark_bits.hpp
Merge branch 'master' into simd-cleanup
[factor.git] / vm / mark_bits.hpp
1 namespace factor
2 {
3
4 const int block_granularity = 16;
5 const int forwarding_granularity = 64;
6
7 template<typename Block> struct mark_bits {
8         cell size;
9         cell start;
10         cell bits_size;
11         u64 *marked;
12         cell *forwarding;
13
14         void clear_mark_bits()
15         {
16                 memset(marked,0,bits_size * sizeof(u64));
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 / block_granularity / forwarding_granularity),
28                 marked(new u64[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(Block *address)
44         {
45                 return (((cell)address - start) / block_granularity);
46         }
47
48         Block *line_block(cell line)
49         {
50                 return (Block *)(line * block_granularity + start);
51         }
52
53         std::pair<cell,cell> bitmap_deref(Block *address)
54         {
55                 cell line_number = block_line(address);
56                 cell word_index = (line_number >> 6);
57                 cell word_shift = (line_number & 63);
58                 return std::make_pair(word_index,word_shift);
59         }
60
61         bool bitmap_elt(u64 *bits, Block *address)
62         {
63                 std::pair<cell,cell> position = bitmap_deref(address);
64                 return (bits[position.first] & ((u64)1 << position.second)) != 0;
65         }
66
67         Block *next_block_after(Block *block)
68         {
69                 return (Block *)((cell)block + block->size());
70         }
71
72         void set_bitmap_range(u64 *bits, 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                 u64 start_mask = ((u64)1 << start.second) - 1;
78                 u64 end_mask = ((u64)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                         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] = (u64)-1;
91
92                         if(end_mask != 0)
93                         {
94 #ifdef FACTOR_DEBUG
95                                 assert(end.first < bits_size);
96 #endif
97                                 bits[end.first] |= end_mask;
98                         }
99                 }
100         }
101
102         bool marked_p(Block *address)
103         {
104                 return bitmap_elt(marked,address);
105         }
106
107         void set_marked_p(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 64 entries; look up and compute the rest */
125         Block *forward_block(Block *original)
126         {
127 #ifdef FACTOR_DEBUG
128                 assert(marked_p(original));
129 #endif
130                 std::pair<cell,cell> position = bitmap_deref(original);
131
132                 cell approx_popcount = forwarding[position.first];
133                 u64 mask = ((u64)1 << position.second) - 1;
134
135                 cell new_line_number = approx_popcount + popcount(marked[position.first] & mask);
136                 Block *new_block = line_block(new_line_number);
137 #ifdef FACTOR_DEBUG
138                 assert(new_block <= original);
139 #endif
140                 return new_block;
141         }
142
143         Block *next_unmarked_block_after(Block *original)
144         {
145                 std::pair<cell,cell> position = bitmap_deref(original);
146                 cell bit_index = position.second;
147
148                 for(cell index = position.first; index < bits_size; index++)
149                 {
150                         u64 mask = ((s64)marked[index] >> bit_index);
151                         if(~mask)
152                         {
153                                 /* Found an unmarked block on this page.
154                                 Stop, it's hammer time */
155                                 cell clear_bit = rightmost_clear_bit(mask);
156                                 return line_block(index * 64 + bit_index + clear_bit);
157                         }
158                         else
159                         {
160                                 /* No unmarked blocks on this page.
161                                 Keep looking */
162                                 bit_index = 0;
163                         }
164                 }
165
166                 /* No unmarked blocks were found */
167                 return (Block *)(this->start + this->size);
168         }
169
170         Block *next_marked_block_after(Block *original)
171         {
172                 std::pair<cell,cell> position = bitmap_deref(original);
173                 cell bit_index = position.second;
174
175                 for(cell index = position.first; index < bits_size; index++)
176                 {
177                         u64 mask = (marked[index] >> bit_index);
178                         if(mask)
179                         {
180                                 /* Found an marked block on this page.
181                                 Stop, it's hammer time */
182                                 cell set_bit = rightmost_set_bit(mask);
183                                 return line_block(index * 64 + bit_index + set_bit);
184                         }
185                         else
186                         {
187                                 /* No marked blocks on this page.
188                                 Keep looking */
189                                 bit_index = 0;
190                         }
191                 }
192
193                 /* No marked blocks were found */
194                 return (Block *)(this->start + this->size);
195         }
196
197         cell unmarked_block_size(Block *original)
198         {
199                 Block *next_marked = next_marked_block_after(original);
200                 return ((char *)next_marked - (char *)original);
201         }
202 };
203
204 }