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);
        }
    }
示例#2
0
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;
}
示例#3
0
 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);
         }
     }
 }
示例#4
0
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);
 }