tree.html 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. <HTML>
  2. <HEAD>
  3. <TITLE> Two-Level Tree Structure for Fast Pointer Lookup</TITLE>
  4. <AUTHOR> Hans-J. Boehm, Silicon Graphics (now at HP)</author>
  5. </HEAD>
  6. <BODY>
  7. <H1>Two-Level Tree Structure for Fast Pointer Lookup</h1>
  8. <P>
  9. The conservative garbage collector described
  10. <A HREF="http://www.hpl.hp.com/personal/Hans_Boehm/gc/">here</a>
  11. uses a 2-level tree
  12. data structure to aid in fast pointer identification.
  13. This data structure is described in a bit more detail here, since
  14. <OL>
  15. <LI> Variations of the data structure are more generally useful.
  16. <LI> It appears to be hard to understand by reading the code.
  17. <LI> Some other collectors appear to use inferior data structures to
  18. solve the same problem.
  19. <LI> It is central to fast collector operation.
  20. </ol>
  21. A candidate pointer is divided into three sections, the <I>high</i>,
  22. <I>middle</i>, and <I>low</i> bits. The exact division between these
  23. three groups of bits is dependent on the detailed collector configuration.
  24. <P>
  25. The high and middle bits are used to look up an entry in the table described
  26. here. The resulting table entry consists of either a block descriptor
  27. (<TT>struct hblkhdr *</tt> or <TT>hdr *</tt>)
  28. identifying the layout of objects in the block, or an indication that this
  29. address range corresponds to the middle of a large block, together with a
  30. hint for locating the actual block descriptor. Such a hint consist
  31. of a displacement that can be subtracted from the middle bits of the candidate
  32. pointer without leaving the object.
  33. <P>
  34. In either case, the block descriptor (<TT>struct hblkhdr</tt>)
  35. refers to a table of object starting addresses (the <TT>hb_map</tt> field).
  36. The starting address table is indexed by the low bits if the candidate pointer.
  37. The resulting entry contains a displacement to the beginning of the object,
  38. or an indication that this cannot be a valid object pointer.
  39. (If all interior pointer are recognized, pointers into large objects
  40. are handled specially, as appropriate.)
  41. <H2>The Tree</h2>
  42. <P>
  43. The rest of this discussion focuses on the two level data structure
  44. used to map the high and middle bits to the block descriptor.
  45. <P>
  46. The high bits are used as an index into the <TT>GC_top_index</tt> (really
  47. <TT>GC_arrays._top_index</tt>) array. Each entry points to a
  48. <TT>bottom_index</tt> data structure. This structure in turn consists
  49. mostly of an array <TT>index</tt> indexed by the middle bits of
  50. the candidate pointer. The <TT>index</tt> array contains the actual
  51. <TT>hdr</tt> pointers.
  52. <P>
  53. Thus a pointer lookup consists primarily of a handful of memory references,
  54. and can be quite fast:
  55. <OL>
  56. <LI> The appropriate <TT>bottom_index</tt> pointer is looked up in
  57. <TT>GC_top_index</tt>, based on the high bits of the candidate pointer.
  58. <LI> The appropriate <TT>hdr</tt> pointer is looked up in the
  59. <TT>bottom_index</tt> structure, based on the middle bits.
  60. <LI> The block layout map pointer is retrieved from the <TT>hdr</tt>
  61. structure. (This memory reference is necessary since we try to share
  62. block layout maps.)
  63. <LI> The displacement to the beginning of the object is retrieved from the
  64. above map.
  65. </ol>
  66. <P>
  67. In order to conserve space, not all <TT>GC_top_index</tt> entries in fact
  68. point to distinct <TT>bottom_index</tt> structures. If no address with
  69. the corresponding high bits is part of the heap, then the entry points
  70. to <TT>GC_all_nils</tt>, a single <TT>bottom_index</tt> structure consisting
  71. only of NULL <TT>hdr</tt> pointers.
  72. <P>
  73. <TT>Bottom_index</tt> structures contain slightly more information than
  74. just <TT>hdr</tt> pointers. The <TT>asc_link</tt> field is used to link
  75. all <TT>bottom_index</tt> structures in ascending order for fast traversal.
  76. This list is pointed to be <TT>GC_all_bottom_indices</tt>.
  77. It is maintained with the aid of <TT>key</tt> field that contains the
  78. high bits corresponding to the <TT>bottom_index</tt>.
  79. <H2>64 bit addresses</h2>
  80. <P>
  81. In the case of 64 bit addresses, this picture is complicated slightly
  82. by the fact that one of the index structures would have to be huge to
  83. cover the entire address space with a two level tree. We deal with this
  84. by turning <TT>GC_top_index</tt> into a chained hash table, instead of
  85. a simple array. This adds a <TT>hash_link</tt> field to the
  86. <TT>bottom_index</tt> structure.
  87. <P>
  88. The "hash function" consists of dropping the high bits. This is cheap to
  89. compute, and guarantees that there will be no collisions if the heap
  90. is contiguous and not excessively large.
  91. <H2>A picture</h2>
  92. <P>
  93. The following is an ASCII diagram of the data structure.
  94. This was contributed by Dave Barrett several years ago.
  95. <PRE>
  96. Data Structure used by GC_base in gc3.7:
  97. 21-Apr-94
  98. 63 LOG_TOP_SZ[11] LOG_BOTTOM_SZ[10] LOG_HBLKSIZE[13]
  99. +------------------+----------------+------------------+------------------+
  100. p:| | TL_HASH(hi) | | HBLKDISPL(p) |
  101. +------------------+----------------+------------------+------------------+
  102. \-----------------------HBLKPTR(p)-------------------/
  103. \------------hi-------------------/
  104. \______ ________/ \________ _______/ \________ _______/
  105. V V V
  106. | | |
  107. GC_top_index[] | | |
  108. --- +--------------+ | | |
  109. ^ | | | | |
  110. | | | | | |
  111. TOP +--------------+<--+ | |
  112. _SZ +-<| [] | * | |
  113. (items)| +--------------+ if 0 < bi< HBLKSIZE | |
  114. | | | | then large object | |
  115. | | | | starts at the bi'th | |
  116. v | | | HBLK before p. | i |
  117. --- | +--------------+ | (word- |
  118. v | aligned) |
  119. bi= |GET_BI(p){->hash_link}->key==hi | |
  120. v | |
  121. | (bottom_index) \ scratch_alloc'd | |
  122. | ( struct bi ) / by get_index() | |
  123. --- +->+--------------+ | |
  124. ^ | | | |
  125. ^ | | | |
  126. BOTTOM | | ha=GET_HDR_ADDR(p) | |
  127. _SZ(items)+--------------+<----------------------+ +-------+
  128. | +--<| index[] | |
  129. | | +--------------+ GC_obj_map: v
  130. | | | | from / +-+-+-----+-+-+-+-+ ---
  131. v | | | GC_add < 0| | | | | | | | ^
  132. --- | +--------------+ _map_entry \ +-+-+-----+-+-+-+-+ |
  133. | | asc_link | +-+-+-----+-+-+-+-+ MAXOBJSZ
  134. | +--------------+ +-->| | | j | | | | | +1
  135. | | key | | +-+-+-----+-+-+-+-+ |
  136. | +--------------+ | +-+-+-----+-+-+-+-+ |
  137. | | hash_link | | | | | | | | | | v
  138. | +--------------+ | +-+-+-----+-+-+-+-+ ---
  139. | | |<--MAX_OFFSET--->|
  140. | | (bytes)
  141. HDR(p)| GC_find_header(p) | |<--MAP_ENTRIES-->|
  142. | \ from | =HBLKSIZE/WORDSZ
  143. | (hdr) (struct hblkhdr) / alloc_hdr() | (1024 on Alpha)
  144. +-->+----------------------+ | (8/16 bits each)
  145. GET_HDR(p)| word hb_sz (words) | |
  146. +----------------------+ |
  147. | struct hblk *hb_next | |
  148. +----------------------+ |
  149. |mark_proc hb_mark_proc| |
  150. +----------------------+ |
  151. | char * hb_map |>-------------+
  152. +----------------------+
  153. | ushort hb_obj_kind |
  154. +----------------------+
  155. | hb_last_reclaimed |
  156. --- +----------------------+
  157. ^ | |
  158. MARK_BITS| hb_marks[] | *if hdr is free, hb_sz + DISCARD_WORDS
  159. _SZ(words)| | is the size of a heap chunk (struct hblk)
  160. v | | of at least MININCR*HBLKSIZE bytes (below),
  161. --- +----------------------+ otherwise, size of each object in chunk.
  162. Dynamic data structures above are interleaved throughout the heap in blocks of
  163. size MININCR * HBLKSIZE bytes as done by gc_scratch_alloc which cannot be
  164. freed; free lists are used (e.g. alloc_hdr). HBLK's below are collected.
  165. (struct hblk)
  166. --- +----------------------+ < HBLKSIZE --- --- DISCARD_
  167. ^ |garbage[DISCARD_WORDS]| aligned ^ ^ HDR_BYTES WORDS
  168. | | | | v (bytes) (words)
  169. | +-----hb_body----------+ < WORDSZ | --- ---
  170. | | | aligned | ^ ^
  171. | | Object 0 | | hb_sz |
  172. | | | i |(word- (words)|
  173. | | | (bytes)|aligned) v |
  174. | + - - - - - - - - - - -+ --- | --- |
  175. | | | ^ | ^ |
  176. n * | | j (words) | hb_sz BODY_SZ
  177. HBLKSIZE | Object 1 | v v | (words)
  178. (bytes) | |--------------- v MAX_OFFSET
  179. | + - - - - - - - - - - -+ --- (bytes)
  180. | | | !All_INTERIOR_PTRS ^ |
  181. | | | sets j only for hb_sz |
  182. | | Object N | valid object offsets. | |
  183. v | | All objects WORDSZ v v
  184. --- +----------------------+ aligned. --- ---
  185. DISCARD_WORDS is normally zero. Indeed the collector has not been tested
  186. with another value in ages.
  187. </pre>
  188. </body>