// test iterating objects in slabs void MemoryManager::checkHeap(const char* phase) { size_t bytes=0; std::vector<Header*> hdrs; std::unordered_set<FreeNode*> free_blocks; std::unordered_set<APCLocalArray*> apc_arrays; std::unordered_set<StringData*> apc_strings; size_t counts[NumHeaderKinds]; for (unsigned i=0; i < NumHeaderKinds; i++) counts[i] = 0; forEachHeader([&](Header* h) { hdrs.push_back(&*h); bytes += h->size(); counts[(int)h->kind()]++; switch (h->kind()) { case HeaderKind::Free: free_blocks.insert(&h->free_); break; case HeaderKind::Apc: if (h->apc_.m_sweep_index != kInvalidSweepIndex) { apc_arrays.insert(&h->apc_); } break; case HeaderKind::String: if (h->str_.isProxy()) apc_strings.insert(&h->str_); break; case HeaderKind::Packed: case HeaderKind::Struct: case HeaderKind::Mixed: case HeaderKind::Empty: case HeaderKind::Globals: case HeaderKind::Proxy: case HeaderKind::Object: case HeaderKind::WaitHandle: case HeaderKind::ResumableObj: case HeaderKind::AwaitAllWH: case HeaderKind::Vector: case HeaderKind::Map: case HeaderKind::Set: case HeaderKind::Pair: case HeaderKind::ImmVector: case HeaderKind::ImmMap: case HeaderKind::ImmSet: case HeaderKind::Resource: case HeaderKind::Ref: case HeaderKind::ResumableFrame: case HeaderKind::NativeData: case HeaderKind::SmallMalloc: case HeaderKind::BigMalloc: break; case HeaderKind::BigObj: case HeaderKind::Hole: assert(false && "forEachHeader skips these kinds"); break; } }); // check the free lists for (auto i = 0; i < kNumSmallSizes; i++) { for (auto n = m_freelists[i].head; n; n = n->next) { assert(free_blocks.find(n) != free_blocks.end()); free_blocks.erase(n); } } assert(free_blocks.empty()); // check the apc array list assert(apc_arrays.size() == m_apc_arrays.size()); for (auto a : m_apc_arrays) { assert(apc_arrays.find(a) != apc_arrays.end()); apc_arrays.erase(a); } assert(apc_arrays.empty()); // check the apc string list for (StringDataNode *next, *n = m_strings.next; n != &m_strings; n = next) { next = n->next; auto const s = StringData::node2str(n); assert(s->isProxy()); assert(apc_strings.find(s) != apc_strings.end()); apc_strings.erase(s); } assert(apc_strings.empty()); // heap check is done. If we are not exiting, check pointers using HeapGraph if (Trace::moduleEnabled(Trace::heapreport)) { auto g = makeHeapGraph(); if (!exiting()) checkPointers(g, phase); if (Trace::moduleEnabled(Trace::heapreport, 2)) { printHeapReport(g, phase); } } }
bool Heap::checkPointers() { bool chk=checkPointers(root); return chk; }