]> gitweb.factorcode.org Git - factor.git/blob - vm/mark_bits.hpp
vm: stage code block map fixup properly for GC
[factor.git] / vm / mark_bits.hpp
1 namespace factor
2 {
3
4 const int mark_bits_granularity = sizeof(cell) * 8;
5 const int mark_bits_mask = sizeof(cell) * 8 - 1;
6
7 template<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 }