void HeapVerifier::reportObject(LiveObjectData& objData, int cycleIndex, HeapVerifier::GCCycle& cycle, LiveObjectList& list) { JSObject* obj = objData.obj; if (objData.isConfirmedDead) { dataLogF("FOUND dead obj %p in GC[%d] %s list '%s'\n", obj, cycleIndex, cycle.collectionTypeName(), list.name); return; } Structure* structure = obj->structure(); Butterfly* butterfly = obj->butterfly(); void* butterflyBase; size_t butterflyCapacityInBytes; CopiedBlock* butterflyBlock; getButterflyDetails(obj, butterflyBase, butterflyCapacityInBytes, butterflyBlock); dataLogF("FOUND obj %p type '%s' butterfly %p (base %p size %zu block %p) in GC[%d] %s list '%s'\n", obj, structure->classInfo()->className, butterfly, butterflyBase, butterflyCapacityInBytes, butterflyBlock, cycleIndex, cycle.collectionTypeName(), list.name); }
bool HeapVerifier::verifyButterflyIsInStorageSpace(Phase phase, LiveObjectList& list) { auto& liveObjects = list.liveObjects; CopiedSpace& storageSpace = m_heap->m_storageSpace; bool listNamePrinted = false; bool success = true; for (size_t i = 0; i < liveObjects.size(); i++) { LiveObjectData& objectData = liveObjects[i]; if (objectData.isConfirmedDead) continue; JSObject* obj = objectData.obj; Butterfly* butterfly = obj->butterfly(); if (butterfly) { void* butterflyBase; size_t butterflyCapacityInBytes; CopiedBlock* butterflyBlock; getButterflyDetails(obj, butterflyBase, butterflyCapacityInBytes, butterflyBlock); if (!storageSpace.contains(butterflyBlock)) { if (!listNamePrinted) { dataLogF("Verification @ phase %s FAILED in object list '%s' (size %zu)\n", phaseName(phase), list.name, liveObjects.size()); listNamePrinted = true; } Structure* structure = obj->structure(); const char* structureClassName = structure->classInfo()->className; dataLogF(" butterfly %p (base %p size %zu block %p) NOT in StorageSpace | obj %p type '%s'\n", butterfly, butterflyBase, butterflyCapacityInBytes, butterflyBlock, obj, structureClassName); success = false; } } } return success; }