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); } }
const Airspaces::AirspaceVector Airspaces::scan_nearest(const GeoPoint &location, const AirspacePredicate &condition) const { Airspace bb_target(location, task_projection); std::pair<AirspaceTree::const_iterator, double> found = airspace_tree.find_nearest(bb_target); #ifdef INSTRUMENT_TASK n_queries++; #endif AirspaceVector res; if (found.first != airspace_tree.end()) { // also should do scan_range with range = 0 since there // could be more than one with zero dist if (found.second == 0) { return scan_range(location, fixed_zero, condition); } else { if (condition(*found.first->get_airspace())) res.push_back(*found.first); } } return res; }
void ThreadLocalCollector::evict_local_garbage(size_t count, vm_address_t garbage[]) { set_marked_blocks_buffer(NULL); // scan the garbage blocks first. _markedBlocksCounter = 0; for (size_t i = 0; i < count; ++i) { void *block = (void*)garbage[i]; Subzone *sz = Subzone::subzone(block); usword_t layout = sz->layout(block); if (!(layout & AUTO_UNSCANNED)) { Range range(block, sz->size(block)); const unsigned char *map = (layout & AUTO_OBJECT) ? _zone->layout_map_for_block(block) : NULL; if (map) scan_with_layout(range, map, NULL); // TLC doesn't need the write barrier. else scan_range(range, NULL); } } // if no blocks were marked, then no evicitions needed. if (_markedBlocksCounter == 0) return; // now, mark all blocks reachable from the garbage blocks themselves. scan_marked_blocks(); for (uint32_t i = _localBlocks.firstOccupiedSlot(); i <= _localBlocks.lastOccupiedSlot(); i++) { if (!_localBlocks.validPointerAtIndex(i)) continue; if (_localBlocks.wasMarked(i)) { void *block = _localBlocks[i]; Subzone *subzone = Subzone::subzone(block); // evict this block, since it is reachable from garbage, but not itself garbage. subzone->make_global(block); _localBlocks.remove(i); } } }
static int walk_mips32(struct elfc *pelf, const struct mips_walk_data *mwd, GElf_Addr pgdaddr, GElf_Addr begin_addr, GElf_Addr end_addr, handle_page_f handle_page, void *userdata) { uint32_t pgd[MAX_PGTAB_ENTRIES(sizeof(uint32_t))]; int pgd_count = ENTRIES_PER_PGTAB(mwd, pgd, sizeof(uint32_t)); int i; int rv; GElf_Addr maxaddr; uint32_t dir_offset = mwd->PAGE_OFFSET - mwd->PHYS_OFFSET; uint32_t start, end; /* * Add the direct mapping first. */ maxaddr = elfc_max_paddr(pelf); rv = scan_range(pelf, mwd, pgdaddr, dir_offset, &begin_addr, &end_addr, dir_offset, dir_offset + maxaddr - 1, handle_page, userdata, walk_mips32); if (rv == -1) return rv; if (rv == 1) return 0; rv = elfc_read_pmem(pelf, pgdaddr, pgd, pgd_count * sizeof(uint32_t)); if (rv == -1) { fprintf(stderr, "Unable to read page directory at" " %llx: %s\n", (unsigned long long) pgdaddr, strerror(elfc_get_errno(pelf))); return -1; } start = begin_addr >> mwd->pgd_shift; end = end_addr >> mwd->pgd_shift; begin_addr &= ADDR32_MASK(mwd->pgd_shift); end_addr &= ADDR32_MASK(mwd->pgd_shift); for (i = start; i <= end; i++) { uint32_t lpgd = mwd->conv32(&pgd[i]); if (mips_virt_to_phys32(mwd, pgdaddr, i, lpgd, &lpgd) == -1) continue; if (mwd->pmd_present) rv = handle_32pmd(pelf, mwd, i << mwd->pgd_shift, lpgd, begin_addr, end_addr, handle_page, userdata); else rv = handle_32pte(pelf, mwd, i << mwd->pgd_shift, lpgd, begin_addr, end_addr, handle_page, userdata); if (rv == -1) return -1; } return 0; }
inline void ThreadLocalCollector::scan_local_block(Subzone *subzone, usword_t q, void *block) { Range range(block, subzone->size(q)); const unsigned char *map = (subzone->layout(q) & AUTO_OBJECT) ? _zone->layout_map_for_block(block) : NULL; if (map) scan_with_layout(range, map); else scan_range(range); }