Exemple #1
0
// parse the heap to find valid objects and initialize metadata, then
// add edges for every known root pointer and every known obj->obj ptr.
HeapGraph makeHeapGraph(bool include_free) {
  HeapGraph g;
  PtrMap blocks;

  // parse the heap once to create a PtrMap for pointer filtering. Create
  // one node for every parsed block, including NativeData and AsyncFuncFrame
  // blocks. Only include free blocks if requested.
  MM().forEachHeader([&](Header* h, size_t alloc_size) {
    if (h->kind() != HeaderKind::Free || include_free) {
      blocks.insert(h, alloc_size); // adds interval [h, h+alloc_size[
    }
  });
  blocks.prepare();

  // initialize nodes by iterating over PtrMap's regions
  g.nodes.reserve(blocks.size());
  blocks.iterate([&](const Header* h, size_t size) {
    type_scan::Index ty;
    switch (h->kind()) {
      case HeaderKind::NativeData:
        ty = h->native_.typeIndex();
        break;
      case HeaderKind::Resource:
        ty = h->res_.typeIndex();
        break;
      case HeaderKind::SmallMalloc:
      case HeaderKind::BigMalloc:
        ty = h->malloc_.typeIndex();
        break;
      default:
        ty = type_scan::kIndexUnknown;
        break;
    }
    g.nodes.push_back(
      HeapGraph::Node{h, size, false, ty, -1, -1}
    );
  });

  // find root nodes
  type_scan::Scanner scanner;
  iterateRoots([&](const void* h, size_t size, type_scan::Index tyindex) {
    // it's important that we actually scan each root node before
    // returning, since at least one will be the C++ stack, and some
    // nodes will only exist for the duration of the call to this lambda,
    // for example EphemeralPtrWrapper<T>.
    addRootNode(g, blocks, scanner, h, size, tyindex);
  });

  // find heap->heap pointers
  for (size_t i = 0, n = g.nodes.size(); i < n; i++) {
    if (g.nodes[i].is_root) continue;
    auto h = g.nodes[i].h;
    scanHeader(h, scanner);
    auto from = blocks.index(h);
    assert(from == i);
    scanner.finish(
      [&](const void* p) {
        // definitely a ptr, but maybe interior, and maybe not counted
        if (auto r = blocks.region(p)) {
          addPtr(g, from, blocks.index(r), HeapGraph::Implicit, UnknownOffset);
        }
      },
      [&](const void* p, std::size_t size) {
        conservativeScan(p, size, [&](const void** addr, const void* ptr) {
          if (auto r = blocks.region(ptr)) {
            auto to = blocks.index(r);
            auto offset = uintptr_t(addr) - uintptr_t(h);
            addPtr(g, from, to, HeapGraph::Ambiguous, offset);
          }
        });
      },
      [&](const void** addr) {
        if (auto r = blocks.region(*addr)) {
          auto to = blocks.index(r);
          auto offset = uintptr_t(addr) - uintptr_t(h);
          addPtr(g, from, to, HeapGraph::Counted, offset);
        }
      }
    );
  }
  g.nodes.shrink_to_fit();
  g.ptrs.shrink_to_fit();
  g.root_ptrs.shrink_to_fit();
  g.root_nodes.shrink_to_fit();
  return g;
}