void ThreadLocalCollector::scan_with_layout(const Range &range, const unsigned char* map) { // convert to double indirect void **reference = (void **)range.address(); void ** const end = (void **)range.end(); Range subrange; // while not '\0' terminator while (unsigned data = *map++) { // extract the skip and run unsigned skip = data >> 4; unsigned run = data & 0xf; // advance the reference by the skip reference += skip; // scan runs as a range. subrange.set_range(reference, reference + run); if (subrange.address() < end && subrange.end() <= end) { // <rdar://problem/6516045>: make sure we only scan valid ranges. scan_range(subrange); } else { break; } reference += run; } if (reference < end) { // since objects can be allocated with extra data at end, scan the remainder conservatively. subrange.set_range((void *)reference, end); scan_range(subrange); } }
void ThreadLocalCollector::scan_range(const Range &range) { // set up the iteration for this range void ** reference = (void **)range.address(); void ** const end = (void **)range.end(); // local copies of valid address info const uintptr_t valid_lowest = (uintptr_t)_coverage.address(); const uintptr_t valid_size = (uintptr_t)_coverage.end() - valid_lowest; // iterate through all the potential references for (void *last_valid_pointer = end - 1; reference <= last_valid_pointer; ++reference) { // get referent void *referent = *reference; // if is a block then check this block out if (((intptr_t)referent - valid_lowest) < valid_size) { mark_push_block(referent); } } }