/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

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