nsresult nsTraceRefcnt::DumpStatistics() { if (!gBloatLog || !gBloatView) { return NS_ERROR_FAILURE; } AutoTraceLogLock lock; MOZ_ASSERT(!gDumpedStatistics, "Calling DumpStatistics more than once may result in " "bogus positive or negative leaks being reported"); gDumpedStatistics = true; // Don't try to log while we hold the lock, we'd deadlock. AutoRestore<LoggingType> saveLogging(gLogging); gLogging = NoLogging; BloatEntry total("TOTAL", 0); PL_HashTableEnumerateEntries(gBloatView, BloatEntry::TotalEntries, &total); const char* msg; if (gLogLeaksOnly) { msg = "ALL (cumulative) LEAK STATISTICS"; } else { msg = "ALL (cumulative) LEAK AND BLOAT STATISTICS"; } const bool leaked = total.PrintDumpHeader(gBloatLog, msg); nsTArray<BloatEntry*> entries; PL_HashTableEnumerateEntries(gBloatView, BloatEntry::DumpEntry, &entries); const uint32_t count = entries.Length(); if (!gLogLeaksOnly || leaked) { // Sort the entries alphabetically by classname. entries.Sort(); for (uint32_t i = 0; i < count; ++i) { BloatEntry* entry = entries[i]; entry->Dump(i, gBloatLog); } fprintf(gBloatLog, "\n"); } fprintf(gBloatLog, "nsTraceRefcnt::DumpStatistics: %d entries\n", count); if (gSerialNumbers) { fprintf(gBloatLog, "\nSerial Numbers of Leaked Objects:\n"); PL_HashTableEnumerateEntries(gSerialNumbers, DumpSerialNumbers, gBloatLog); } return NS_OK; }
nsresult nsTraceRefcnt::DumpStatistics(StatisticsType aType, FILE* aOut) { #ifdef NS_IMPL_REFCNT_LOGGING if (!gBloatLog || !gBloatView) { return NS_ERROR_FAILURE; } if (!aOut) { aOut = gBloatLog; } AutoTraceLogLock lock; // Don't try to log while we hold the lock, we'd deadlock. AutoRestore<LoggingType> saveLogging(gLogging); gLogging = NoLogging; BloatEntry total("TOTAL", 0); PL_HashTableEnumerateEntries(gBloatView, BloatEntry::TotalEntries, &total); const char* msg; if (aType == NEW_STATS) { if (gLogLeaksOnly) { msg = "NEW (incremental) LEAK STATISTICS"; } else { msg = "NEW (incremental) LEAK AND BLOAT STATISTICS"; } } else { if (gLogLeaksOnly) { msg = "ALL (cumulative) LEAK STATISTICS"; } else { msg = "ALL (cumulative) LEAK AND BLOAT STATISTICS"; } } const bool leaked = total.PrintDumpHeader(aOut, msg, aType); nsTArray<BloatEntry*> entries; PL_HashTableEnumerateEntries(gBloatView, BloatEntry::DumpEntry, &entries); const uint32_t count = entries.Length(); if (!gLogLeaksOnly || leaked) { // Sort the entries alphabetically by classname. entries.Sort(); for (uint32_t i = 0; i < count; ++i) { BloatEntry* entry = entries[i]; entry->Dump(i, aOut, aType); } fprintf(aOut, "\n"); } fprintf(aOut, "nsTraceRefcnt::DumpStatistics: %d entries\n", count); if (gSerialNumbers) { fprintf(aOut, "\nSerial Numbers of Leaked Objects:\n"); PL_HashTableEnumerateEntries(gSerialNumbers, DumpSerialNumbers, aOut); } #endif return NS_OK; }