]> gitweb.factorcode.org Git - factor.git/blob - vm/mark_bits.hpp
Merge branch 'master' into new_gc
[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> pair = bitmap_deref(address);
64                 return (bits[pair.first] & ((u64)1 << pair.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         /* From http://chessprogramming.wikispaces.com/Population+Count */
113         cell popcount(u64 x)
114         {
115                 u64 k1 = 0x5555555555555555ll;
116                 u64 k2 = 0x3333333333333333ll;
117                 u64 k4 = 0x0f0f0f0f0f0f0f0fll;
118                 u64 kf = 0x0101010101010101ll;
119                 x =  x       - ((x >> 1)  & k1); // put count of each 2 bits into those 2 bits
120                 x = (x & k2) + ((x >> 2)  & k2); // put count of each 4 bits into those 4 bits
121                 x = (x       +  (x >> 4)) & k4 ; // put count of each 8 bits into those 8 bits
122                 x = (x * kf) >> 56; // returns 8 most significant bits of x + (x<<8) + (x<<16) + (x<<24) + ...
123
124                 return (cell)x;
125         }
126
127         /* The eventual destination of a block after compaction is just the number
128         of marked blocks before it. Live blocks must be marked on entry. */
129         void compute_forwarding()
130         {
131                 cell accum = 0;
132                 for(cell index = 0; index < bits_size; index++)
133                 {
134                         forwarding[index] = accum;
135                         accum += popcount(marked[index]);
136                 }
137         }
138
139         /* We have the popcount for every 64 entries; look up and compute the rest */
140         Block *forward_block(Block *original)
141         {
142                 std::pair<cell,cell> pair = bitmap_deref(original);
143
144                 cell approx_popcount = forwarding[pair.first];
145                 u64 mask = ((u64)1 << pair.second) - 1;
146
147                 cell new_line_number = approx_popcount + popcount(marked[pair.first] & mask);
148                 return line_block(new_line_number);
149         }
150 };
151
152 template<typename Block, typename Iterator> struct heap_compactor {
153         mark_bits<Block> *state;
154         char *address;
155         Iterator &iter;
156
157         explicit heap_compactor(mark_bits<Block> *state_, Block *address_, Iterator &iter_) :
158                 state(state_), address((char *)address_), iter(iter_) {}
159
160         void operator()(Block *block, cell size)
161         {
162                 if(this->state->marked_p(block))
163                 {
164                         memmove(address,block,size);
165                         iter((Block *)address,size);
166                         address += size;
167                 }
168         }
169 };
170
171 }