Heap Queries
For any Heap Object, we can efficiently query which Heap contains that object. Typically, this is implemented in the code as follows: first we get the chunk containing the object, and then we use the union-find acceleration structure to get to the “level head”, i.e., the representative HM_HierarchicalHeap structure for this region of memory.
objptr op; // given a pointer to some object
HM_HierarchicalHeap h; // result is a pointer to a heap
h = HM_getLevelHead(HM_getChunkOf(op));
Below is an illustration of a full heap query. ① We start with an objptr pointing to some object. ② The function call HM_getChunkOf(...) returns the chunk descriptor (see Chunks) for the chunk that contains that object. ③ Next, with the chunk descriptor in hand, we call HM_getLevelHead to traverse the union-find structure. ④ Finally, out of the union-find structure, we arrive at the appropriate HM_HierarchicalHeap.

Throughout the run-time system you will also see the following.
h = HM_getLevelHeadPathCompress(HM_getChunkOf(op));This is similar to the approach described above, except that it also performs path compression within the union-find structure to help accelerate future queries. Some care is needed to avoid concurrency issues, because
HM_getLevelHeadPathCompressmodifies the union-find structure.
It might at first seem like heap queries are expensive. In practice, a typical heap query requires only a bitmask, two pointer dereferences, and a couple conditionals. Path compression ensures that the number of links traversed within the union-find structure is almost constant.