// 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) { if (h->kind() != HeaderKind::Free || include_free) { blocks.insert(h); // adds interval [h, h+h->size[ } }); blocks.prepare(); // initialize nodes by iterating over PtrMap's regions g.nodes.reserve(blocks.size()); blocks.iterate([&](const Header* h, size_t size) { g.nodes.push_back(HeapGraph::Node{h, -1, -1}); }); // find roots PtrFilter<RootMarker> rmark(g, blocks); scanRoots(rmark); // find heap->heap pointers for (size_t i = 0, n = g.nodes.size(); i < n; i++) { auto h = g.nodes[i].h; PtrFilter<ObjMarker> omark(g, blocks, h); scanHeader(h, omark); } g.nodes.shrink_to_fit(); g.ptrs.shrink_to_fit(); g.roots.shrink_to_fit(); return g; }
static void RunAnnotate(char *fname, int side) { FILE *fin = fopen(fname, "r"); struct Position *p; if(fin) { struct PGNHeader header; char move[16]; while(!scanHeader(fin, &header)) { p = InitialPosition(); while(!scanMove(fin, move)) { int themove = ParseSAN(p, move); if(themove != M_NONE) { ShowPosition(p); Print(0, "%s(%d): ", p->turn == White ? "White":"Black", (p->ply/2)+1); Print(0, "%s\n", SAN(p, themove)); if(side == -1 || (side == p->turn)) { Iterate(p); } DoMove(p, themove); } } FreePosition(p); } } else Print(0, "Couldn't open %s\n", fname); }
NEVER_INLINE void Marker::trace() { scanRoots(*this); while (!work_.empty()) { auto h = work_.back(); work_.pop_back(); scanHeader(h, *this); } }
// 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; }