author | Nicholas Nethercote <nnethercote@mozilla.com> |
Mon, 14 Jan 2013 16:26:47 -0800 | |
changeset 118844 | f6cf84d5ec1a8179cfd7564e45357efac1dc52cb |
parent 118843 | d88715bba2ca3fd5c3380b5ae77d190dba73cef3 |
child 118845 | 6925a363cddf9878026275346fa7e4e378c78997 |
push id | 21306 |
push user | nnethercote@mozilla.com |
push date | Tue, 15 Jan 2013 02:14:59 +0000 |
treeherder | mozilla-inbound@6925a363cddf [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | jlebar |
bugs | 829439 |
milestone | 21.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/content/base/src/nsContentUtils.cpp +++ b/content/base/src/nsContentUtils.cpp @@ -1,10 +1,10 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=2 sw=2 et tw=78: */ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* A namespace class for static layout utilities. */ #include "mozilla/DebugOnly.h" #include "mozilla/Util.h" @@ -242,35 +242,39 @@ bool nsContentUtils::sFragmentParsingAct namespace { static const char kJSStackContractID[] = "@mozilla.org/js/xpc/ContextStack;1"; static NS_DEFINE_CID(kParserServiceCID, NS_PARSERSERVICE_CID); static NS_DEFINE_CID(kCParserCID, NS_PARSER_CID); static PLDHashTable sEventListenerManagersHash; -static nsCOMPtr<nsIMemoryReporter> sEventListenerManagersHashReporter; - -NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(EventListenerManagersHashMallocSizeOf) - -static int64_t GetEventListenerManagersHash() -{ - // We don't measure the |nsEventListenerManager| objects pointed to by the - // entries because those references are non-owning. - return PL_DHashTableSizeOfExcludingThis(&sEventListenerManagersHash, - nullptr, - EventListenerManagersHashMallocSizeOf); -} - -NS_MEMORY_REPORTER_IMPLEMENT(EventListenerManagersHash, - "explicit/dom/event-listener-managers-hash", - KIND_HEAP, - UNITS_BYTES, - GetEventListenerManagersHash, - "Memory used by the event listener manager's hash table.") + +class DOMEventListenerManagersHashReporter MOZ_FINAL : public MemoryReporterBase +{ +public: + DOMEventListenerManagersHashReporter() + : MemoryReporterBase( + "explicit/dom/event-listener-managers-hash", + KIND_HEAP, + UNITS_BYTES, + "Memory used by the event listener manager's hash table.") + {} + +private: + int64_t Amount() + { + // We don't measure the |nsEventListenerManager| objects pointed to by the + // entries because those references are non-owning. + return sEventListenerManagersHash.ops + ? PL_DHashTableSizeOfExcludingThis(&sEventListenerManagersHash, + nullptr, MallocSizeOf) + : 0; + } +}; class EventListenerManagerMapEntry : public PLDHashEntryHdr { public: EventListenerManagerMapEntry(const void *aKey) : mKey(aKey) { } @@ -398,19 +402,17 @@ nsContentUtils::Init() if (!PL_DHashTableInit(&sEventListenerManagersHash, &hash_table_ops, nullptr, sizeof(EventListenerManagerMapEntry), 16)) { sEventListenerManagersHash.ops = nullptr; return NS_ERROR_OUT_OF_MEMORY; } - sEventListenerManagersHashReporter = - new NS_MEMORY_REPORTER_NAME(EventListenerManagersHash); - (void)::NS_RegisterMemoryReporter(sEventListenerManagersHashReporter); + NS_RegisterMemoryReporter(new DOMEventListenerManagersHashReporter); } sBlockedScriptRunners = new nsTArray< nsCOMPtr<nsIRunnable> >; Preferences::AddBoolVarCache(&sAllowXULXBL_for_file, "dom.allow_XUL_XBL_for_file"); Preferences::AddBoolVarCache(&sIsFullScreenApiEnabled, @@ -1482,19 +1484,16 @@ nsContentUtils::Shutdown() // in case any elements are destroyed. Because if they are, we need // their event listener managers to be destroyed too, or otherwise // it could leave dangling references in DOMClassInfo's preserved // wrapper table. if (sEventListenerManagersHash.entryCount == 0) { PL_DHashTableFinish(&sEventListenerManagersHash); sEventListenerManagersHash.ops = nullptr; - - (void)::NS_UnregisterMemoryReporter(sEventListenerManagersHashReporter); - sEventListenerManagersHashReporter = nullptr; } } NS_ASSERTION(!sBlockedScriptRunners || sBlockedScriptRunners->Length() == 0, "How'd this happen?"); delete sBlockedScriptRunners; sBlockedScriptRunners = nullptr;
--- a/content/canvas/src/CanvasRenderingContext2D.cpp +++ b/content/canvas/src/CanvasRenderingContext2D.cpp @@ -125,17 +125,16 @@ namespace dom { static float kDefaultFontSize = 10.0; static NS_NAMED_LITERAL_STRING(kDefaultFontName, "sans-serif"); static NS_NAMED_LITERAL_STRING(kDefaultFontStyle, "10px sans-serif"); // Cap sigma to avoid overly large temp surfaces. const Float SIGMA_MAX = 100; /* Memory reporter stuff */ -static nsIMemoryReporter *gCanvasAzureMemoryReporter = nullptr; static int64_t gCanvasAzureMemoryUsed = 0; static int64_t GetCanvasAzureMemoryUsed() { return gCanvasAzureMemoryUsed; } // This is KIND_OTHER because it's not always clear where in memory the pixels // of a canvas are stored. Furthermore, this memory will be tracked by the @@ -787,19 +786,20 @@ CanvasRenderingContext2D::EnsureTarget() if (layerManager) { mTarget = layerManager->CreateDrawTarget(size, format); } else { mTarget = gfxPlatform::GetPlatform()->CreateOffscreenDrawTarget(size, format); } } if (mTarget) { - if (gCanvasAzureMemoryReporter == nullptr) { - gCanvasAzureMemoryReporter = new NS_MEMORY_REPORTER_NAME(CanvasAzureMemory); - NS_RegisterMemoryReporter(gCanvasAzureMemoryReporter); + static bool registered = false; + if (!registered) { + registered = true; + NS_RegisterMemoryReporter(new NS_MEMORY_REPORTER_NAME(CanvasAzureMemory)); } gCanvasAzureMemoryUsed += mWidth * mHeight * 4; JSContext* context = nsContentUtils::GetCurrentJSContext(); if (context) { JS_updateMallocCounter(context, mWidth * mHeight * 4); }
--- a/dom/base/nsJSEnvironment.cpp +++ b/dom/base/nsJSEnvironment.cpp @@ -1,10 +1,10 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=2 sw=2 et tw=78: */ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "nsError.h" #include "nsJSEnvironment.h" #include "nsIScriptGlobalObject.h" #include "nsIScriptObjectPrincipal.h" @@ -170,34 +170,16 @@ static uint32_t sRemovedPurples = 0; static uint32_t sForgetSkippableBeforeCC = 0; static uint32_t sPreviousSuspectedCount = 0; static uint32_t sCompartmentGCCount = NS_MAX_COMPARTMENT_GC_COUNT; static uint32_t sCleanupsSinceLastGC = UINT32_MAX; static bool sNeedsFullCC = false; static nsJSContext *sContextList = nullptr; static nsScriptNameSpaceManager *gNameSpaceManager; -static nsIMemoryReporter *gReporter; - -NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(ScriptNameSpaceManagerMallocSizeOf) - -static int64_t -GetScriptNameSpaceManagerSize() -{ - MOZ_ASSERT(gNameSpaceManager); - return gNameSpaceManager->SizeOfIncludingThis( - ScriptNameSpaceManagerMallocSizeOf); -} - -NS_MEMORY_REPORTER_IMPLEMENT(ScriptNameSpaceManager, - "explicit/script-namespace-manager", - KIND_HEAP, - nsIMemoryReporter::UNITS_BYTES, - GetScriptNameSpaceManagerSize, - "Memory used for the script namespace manager.") static nsIJSRuntimeService *sRuntimeService; JSRuntime *nsJSRuntime::sRuntime; static const char kJSRuntimeServiceContractID[] = "@mozilla.org/js/xpc/RuntimeService;1"; static PRTime sFirstCollectionTime; @@ -3724,17 +3706,16 @@ nsJSRuntime::Startup() sLastCCEndTime = 0; sPendingLoadCount = 0; sLoadingInProgress = false; sCCollectedWaitingForGC = 0; sPostGCEventsToConsole = false; sDisableExplicitCompartmentGC = false; sNeedsFullCC = false; gNameSpaceManager = nullptr; - gReporter = nullptr; sRuntimeService = nullptr; sRuntime = nullptr; sIsInitialized = false; sDidShutdown = false; sContextCount = 0; sSecurityManager = nullptr; } @@ -4067,39 +4048,32 @@ nsJSRuntime::GetNameSpaceManager() return nullptr; if (!gNameSpaceManager) { gNameSpaceManager = new nsScriptNameSpaceManager; NS_ADDREF(gNameSpaceManager); nsresult rv = gNameSpaceManager->Init(); NS_ENSURE_SUCCESS(rv, nullptr); - - gReporter = new NS_MEMORY_REPORTER_NAME(ScriptNameSpaceManager); - NS_RegisterMemoryReporter(gReporter); } return gNameSpaceManager; } /* static */ void nsJSRuntime::Shutdown() { nsJSContext::KillGCTimer(); nsJSContext::KillShrinkGCBuffersTimer(); nsJSContext::KillCCTimer(); nsJSContext::KillFullGCTimer(); nsJSContext::KillInterSliceGCTimer(); NS_IF_RELEASE(gNameSpaceManager); - if (gReporter) { - (void)::NS_UnregisterMemoryReporter(gReporter); - gReporter = nullptr; - } if (!sContextCount) { // We're being shutdown, and there are no more contexts // alive, release the JS runtime service and the security manager. NS_IF_RELEASE(sRuntimeService); NS_IF_RELEASE(sSecurityManager); }
--- a/dom/base/nsScriptNameSpaceManager.cpp +++ b/dom/base/nsScriptNameSpaceManager.cpp @@ -1,9 +1,10 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "nsScriptNameSpaceManager.h" #include "nsCOMPtr.h" #include "nsIComponentManager.h" #include "nsIComponentRegistrar.h" @@ -106,29 +107,48 @@ GlobalNameHashInitEntry(PLDHashTable *ta new (&e->mKey) nsString(*keyStr); // This will set e->mGlobalName.mType to // nsGlobalNameStruct::eTypeNotInitialized memset(&e->mGlobalName, 0, sizeof(nsGlobalNameStruct)); return true; } +class ScriptNameSpaceManagerReporter MOZ_FINAL : public MemoryReporterBase +{ +public: + ScriptNameSpaceManagerReporter(nsScriptNameSpaceManager* aManager) + : MemoryReporterBase( + "explicit/script-namespace-manager", + KIND_HEAP, + nsIMemoryReporter::UNITS_BYTES, + "Memory used for the script namespace manager.") + , mManager(aManager) + {} + +private: + int64_t Amount() { return mManager->SizeOfIncludingThis(MallocSizeOf); } + + nsScriptNameSpaceManager* mManager; +}; + NS_IMPL_ISUPPORTS2(nsScriptNameSpaceManager, nsIObserver, nsISupportsWeakReference) nsScriptNameSpaceManager::nsScriptNameSpaceManager() : mIsInitialized(false) { MOZ_COUNT_CTOR(nsScriptNameSpaceManager); } nsScriptNameSpaceManager::~nsScriptNameSpaceManager() { if (mIsInitialized) { + NS_UnregisterMemoryReporter(mReporter); // Destroy the hash PL_DHashTableFinish(&mGlobalNames); PL_DHashTableFinish(&mNavigatorNames); } MOZ_COUNT_DTOR(nsScriptNameSpaceManager); } nsGlobalNameStruct * @@ -393,16 +413,19 @@ nsScriptNameSpaceManager::Init() sizeof(GlobalNameMapEntry), GLOBALNAME_HASHTABLE_INITIAL_SIZE); if (!mIsInitialized) { PL_DHashTableFinish(&mGlobalNames); return NS_ERROR_OUT_OF_MEMORY; } + mReporter = new ScriptNameSpaceManagerReporter(this); + NS_RegisterMemoryReporter(mReporter); + nsresult rv = NS_OK; rv = FillHashWithDOMInterfaces(); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr<nsICategoryManager> cm = do_GetService(NS_CATEGORYMANAGER_CONTRACTID, &rv); NS_ENSURE_SUCCESS(rv, rv);
--- a/dom/base/nsScriptNameSpaceManager.h +++ b/dom/base/nsScriptNameSpaceManager.h @@ -1,11 +1,11 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * - * This Source Code Form is subject to the terms of the Mozilla Public +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * * This Original Code has been modified by IBM Corporation. * Modifications made by IBM described herein are * Copyright (c) International Business Machines * Corporation, 2000 @@ -73,16 +73,17 @@ struct nsGlobalNameStruct private: // copy constructor }; class nsIScriptContext; class nsICategoryManager; +class nsIMemoryReporter; class GlobalNameMapEntry; class nsScriptNameSpaceManager : public nsIObserver, public nsSupportsWeakReference { public: NS_DECL_ISUPPORTS @@ -186,11 +187,13 @@ private: nsGlobalNameStruct* LookupNameInternal(const nsAString& aName, const PRUnichar **aClassName = nullptr); PLDHashTable mGlobalNames; PLDHashTable mNavigatorNames; bool mIsInitialized; + + nsCOMPtr<nsIMemoryReporter> mReporter; }; #endif /* nsScriptNameSpaceManager_h__ */
--- a/netwerk/cache/nsCacheService.cpp +++ b/netwerk/cache/nsCacheService.cpp @@ -1,10 +1,10 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* vim: set sw=4 ts=8 et tw=80 : */ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* vim: set ts=8 sts=4 et sw=4 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "mozilla/Attributes.h" #include "mozilla/DebugOnly.h" #include "mozilla/Util.h" @@ -16,17 +16,16 @@ #include "nsCacheEntry.h" #include "nsCacheEntryDescriptor.h" #include "nsCacheDevice.h" #include "nsMemoryCacheDevice.h" #include "nsICacheVisitor.h" #include "nsDiskCacheDevice.h" #include "nsDiskCacheDeviceSQL.h" -#include "nsIMemoryReporter.h" #include "nsIObserverService.h" #include "nsIPrefService.h" #include "nsIPrefBranch.h" #include "nsIFile.h" #include "nsIOService.h" #include "nsDirectoryServiceDefs.h" #include "nsAppDirectoryServiceDefs.h" #include "nsThreadUtils.h" @@ -1066,36 +1065,16 @@ private: nsCOMPtr<nsIThread> mThread; }; /****************************************************************************** * nsCacheService *****************************************************************************/ nsCacheService * nsCacheService::gService = nullptr; -static nsCOMPtr<nsIMemoryReporter> MemoryCacheReporter = nullptr; - -NS_THREADSAFE_MEMORY_REPORTER_IMPLEMENT(NetworkMemoryCache, - "explicit/network/memory-cache", - KIND_HEAP, - UNITS_BYTES, - nsCacheService::MemoryDeviceSize, - "Memory used by the network memory cache.") - -NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(NetworkDiskCacheMallocSizeOf) - -static nsCOMPtr<nsIMemoryReporter> DiskCacheReporter = nullptr; - -NS_THREADSAFE_MEMORY_REPORTER_IMPLEMENT(NetworkDiskCache, - "explicit/network/disk-cache", - KIND_HEAP, - UNITS_BYTES, - nsCacheService::DiskDeviceHeapSize, - "Memory used by the network disk cache.") - NS_IMPL_THREADSAFE_ISUPPORTS1(nsCacheService, nsICacheService) nsCacheService::nsCacheService() : mObserver(nullptr), mLock("nsCacheService.mLock"), mCondVar(mLock, "nsCacheService.mCondVar"), mInitialized(false), mClearingEntries(false), @@ -1239,24 +1218,16 @@ nsCacheService::Shutdown() // Make sure to wait for any pending cache-operations before // proceeding with destructive actions (bug #620660) (void) SyncWithCacheIOThread(); // obtain the disk cache directory in case we need to sanitize it parentDir = mObserver->DiskCacheParentDirectory(); shouldSanitize = mObserver->SanitizeAtShutdown(); - - // unregister memory reporters, before deleting the devices, just - // to be safe - NS_UnregisterMemoryReporter(MemoryCacheReporter); - MemoryCacheReporter = nullptr; - - NS_UnregisterMemoryReporter(DiskCacheReporter); - DiskCacheReporter = nullptr; // deallocate memory and disk caches delete mMemoryDevice; mMemoryDevice = nullptr; delete mDiskDevice; mDiskDevice = nullptr; @@ -1561,26 +1532,26 @@ nsCacheService::CreateDiskDevice() mDiskDevice = new nsDiskCacheDevice; if (!mDiskDevice) return NS_ERROR_OUT_OF_MEMORY; // set the preferences mDiskDevice->SetCacheParentDirectory(mObserver->DiskCacheParentDirectory()); mDiskDevice->SetCapacity(mObserver->DiskCacheCapacity()); mDiskDevice->SetMaxEntrySize(mObserver->DiskCacheMaxEntrySize()); - + nsresult rv = mDiskDevice->Init(); if (NS_FAILED(rv)) { #if DEBUG printf("###\n"); printf("### mDiskDevice->Init() failed (0x%.8x)\n", static_cast<uint32_t>(rv)); printf("### - disabling disk cache for this session.\n"); printf("###\n"); -#endif +#endif mEnableDiskDevice = false; delete mDiskDevice; mDiskDevice = nullptr; return rv; } Telemetry::Accumulate(Telemetry::DISK_CACHE_SMART_SIZE_USING_OLD_MAX, mObserver->ShouldUseOldMaxSmartSize()); @@ -1600,19 +1571,16 @@ nsCacheService::CreateDiskDevice() mSmartSizeTimer = nullptr; } } else { NS_WARNING("Can't create smart size timer"); } // Ignore state of the timer and return success since the purpose of the // method (create the disk-device) has been fulfilled - DiskCacheReporter = new NS_MEMORY_REPORTER_NAME(NetworkDiskCache); - NS_RegisterMemoryReporter(DiskCacheReporter); - return NS_OK; } // Runnable sent from cache thread to main thread class nsDisableOldMaxSmartSizePrefEvent: public nsRunnable { public: nsDisableOldMaxSmartSizePrefEvent() {} @@ -1768,20 +1736,16 @@ nsCacheService::CreateMemoryDevice() nsresult rv = mMemoryDevice->Init(); if (NS_FAILED(rv)) { NS_WARNING("Initialization of Memory Cache failed."); delete mMemoryDevice; mMemoryDevice = nullptr; } - MemoryCacheReporter = - new NS_MEMORY_REPORTER_NAME(NetworkMemoryCache); - NS_RegisterMemoryReporter(MemoryCacheReporter); - return rv; } nsresult nsCacheService::RemoveCustomOfflineDevice(nsOfflineCacheDevice *aDevice) { nsCOMPtr<nsIFile> profileDir = aDevice->BaseDirectory(); if (!profileDir) @@ -2269,31 +2233,16 @@ nsCacheService::EnsureEntryHasDevice(nsC } } if (device) entry->SetCacheDevice(device); return device; } -int64_t -nsCacheService::MemoryDeviceSize() -{ - nsMemoryCacheDevice *memoryDevice = GlobalInstance()->mMemoryDevice; - return memoryDevice ? memoryDevice->TotalSize() : 0; -} - -int64_t -nsCacheService::DiskDeviceHeapSize() -{ - nsCacheServiceAutoLock lock(LOCK_TELEM(NSCACHESERVICE_DISKDEVICEHEAPSIZE)); - nsDiskCacheDevice *diskDevice = GlobalInstance()->mDiskDevice; - return (int64_t)(diskDevice ? diskDevice->SizeOfIncludingThis(NetworkDiskCacheMallocSizeOf) : 0); -} - nsresult nsCacheService::DoomEntry(nsCacheEntry * entry) { return gService->DoomEntry_Internal(entry, true); } nsresult
--- a/netwerk/cache/nsCacheService.h +++ b/netwerk/cache/nsCacheService.h @@ -1,15 +1,14 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * This Source Code Form is subject to the terms of the Mozilla Public +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* vim: set ts=8 sts=4 et sw=4 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - #ifndef _nsCacheService_h_ #define _nsCacheService_h_ #include "nsICacheService.h" #include "nsCacheSession.h" #include "nsCacheDevice.h" #include "nsCacheEntry.h" #include "nsThreadUtils.h" @@ -61,17 +60,17 @@ private: * nsCacheService ******************************************************************************/ class nsCacheService : public nsICacheService { public: NS_DECL_ISUPPORTS NS_DECL_NSICACHESERVICE - + nsCacheService(); virtual ~nsCacheService(); // Define a Create method to be used with a factory: static nsresult Create(nsISupports* outer, const nsIID& iid, void* *result); @@ -125,20 +124,16 @@ public: /** * Methods called by any cache classes */ static nsCacheService * GlobalInstance() { return gService; } - static int64_t MemoryDeviceSize(); - - static int64_t DiskDeviceHeapSize(); - static nsresult DoomEntry(nsCacheEntry * entry); static bool IsStorageEnabledForPolicy_Locked(nsCacheStoragePolicy policy); /** * Called by disk cache to notify us to use the new max smart size */ static void MarkStartingFresh(); @@ -311,45 +306,45 @@ private: nsresult SetDiskSmartSize_Locked(); /** * Data Members */ static nsCacheService * gService; // there can be only one... - + nsCacheProfilePrefObserver * mObserver; - + mozilla::Mutex mLock; mozilla::CondVar mCondVar; nsCOMPtr<nsIThread> mCacheIOThread; nsTArray<nsISupports*> mDoomedObjects; nsCOMPtr<nsITimer> mSmartSizeTimer; - + bool mInitialized; bool mClearingEntries; - + bool mEnableMemoryDevice; bool mEnableDiskDevice; bool mEnableOfflineDevice; nsMemoryCacheDevice * mMemoryDevice; nsDiskCacheDevice * mDiskDevice; nsOfflineCacheDevice * mOfflineDevice; nsRefPtrHashtable<nsStringHashKey, nsOfflineCacheDevice> mCustomOfflineDevices; nsCacheEntryHashTable mActiveEntries; PRCList mDoomedEntries; // stats - + uint32_t mTotalEntries; uint32_t mCacheHits; uint32_t mCacheMisses; uint32_t mMaxKeyLength; uint32_t mMaxDataSize; uint32_t mMaxMetaSize; // Unexpected error totals
--- a/netwerk/cache/nsDiskCacheDevice.cpp +++ b/netwerk/cache/nsDiskCacheDevice.cpp @@ -4,16 +4,17 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include <limits.h> #include "mozilla/DebugOnly.h" #include "nsCache.h" +#include "nsIMemoryReporter.h" // include files for ftruncate (or equivalent) #if defined(XP_UNIX) #include <unistd.h> #elif defined(XP_WIN) #include <windows.h> #elif defined(XP_OS2) #define INCL_DOSERRORS @@ -363,26 +364,53 @@ nsDiskCache::Truncate(PRFileDesc * fd, return NS_OK; } /****************************************************************************** * nsDiskCacheDevice *****************************************************************************/ +class NetworkDiskCacheReporter MOZ_FINAL : public MemoryReporterBase +{ +public: + NetworkDiskCacheReporter(nsDiskCacheDevice* aDevice) + : MemoryReporterBase( + "explicit/network/disk-cache", + KIND_HEAP, + UNITS_BYTES, + "Memory used by the network disk cache.") + , mDevice(aDevice) + {} + +private: + int64_t Amount() + { + nsCacheServiceAutoLock + lock(LOCK_TELEM(NSCACHESERVICE_DISKDEVICEHEAPSIZE)); + return mDevice->SizeOfIncludingThis(MallocSizeOf); + } + + nsDiskCacheDevice* mDevice; +}; + nsDiskCacheDevice::nsDiskCacheDevice() : mCacheCapacity(0) , mMaxEntrySize(-1) // -1 means "no limit" , mInitialized(false) , mClearingDiskCache(false) + , mReporter(nullptr) { + mReporter = new NetworkDiskCacheReporter(this); + NS_RegisterMemoryReporter(mReporter); } nsDiskCacheDevice::~nsDiskCacheDevice() { + NS_UnregisterMemoryReporter(mReporter); Shutdown(); } /** * methods of nsCacheDevice */ nsresult
--- a/netwerk/cache/nsDiskCacheDevice.h +++ b/netwerk/cache/nsDiskCacheDevice.h @@ -12,16 +12,17 @@ #include "nsDiskCacheBlockFile.h" #include "nsDiskCacheEntry.h" #include "nsIFile.h" #include "nsIObserver.h" #include "nsCOMArray.h" class nsDiskCacheMap; +class nsIMemoryReporter; class nsDiskCacheDevice : public nsCacheDevice { public: nsDiskCacheDevice(); virtual ~nsDiskCacheDevice(); virtual nsresult Init(); @@ -105,11 +106,13 @@ private: nsCOMPtr<nsIFile> mCacheDirectory; nsDiskCacheBindery mBindery; uint32_t mCacheCapacity; // Unit is KiB's int32_t mMaxEntrySize; // Unit is bytes internally // XXX need soft/hard limits, currentTotal nsDiskCacheMap mCacheMap; bool mInitialized; bool mClearingDiskCache; + + nsCOMPtr<nsIMemoryReporter> mReporter; }; #endif // _nsDiskCacheDevice_h_
--- a/netwerk/cache/nsMemoryCacheDevice.cpp +++ b/netwerk/cache/nsMemoryCacheDevice.cpp @@ -1,53 +1,79 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * This Source Code Form is subject to the terms of the Mozilla Public +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* vim: set ts=8 sts=4 et sw=4 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "nsCache.h" #include "nsMemoryCacheDevice.h" #include "nsCacheService.h" #include "nsICacheService.h" +#include "nsICacheVisitor.h" #include "nsIStorageStream.h" -#include "nsICacheVisitor.h" +#include "nsIMemoryReporter.h" #include "nsCRT.h" #include "nsReadableUtils.h" #include "mozilla/Telemetry.h" // The memory cache implements the "LRU-SP" caching algorithm // described in "LRU-SP: A Size-Adjusted and Popularity-Aware LRU Replacement // Algorithm for Web Caching" by Kai Cheng and Yahiko Kambayashi. // We keep kQueueCount LRU queues, which should be about ceil(log2(mHardLimit)) // The queues hold exponentially increasing ranges of floor(log2((size/nref))) // values for entries. // Entries larger than 2^(kQueueCount-1) go in the last queue. // Entries with no expiration go in the first queue. const char *gMemoryDeviceID = "memory"; +class NetworkMemoryCacheReporter MOZ_FINAL : + public mozilla::MemoryReporterBase +{ +public: + NetworkMemoryCacheReporter(nsMemoryCacheDevice* aDevice) + : MemoryReporterBase( + "explicit/network/memory-cache", + KIND_HEAP, + UNITS_BYTES, + "Memory used by the network memory cache.") + , mDevice(aDevice) + {} + +private: + int64_t Amount() { return mDevice->TotalSize(); } + + nsMemoryCacheDevice* mDevice; +}; + + nsMemoryCacheDevice::nsMemoryCacheDevice() : mInitialized(false), mHardLimit(4 * 1024 * 1024), // default, if no pref mSoftLimit((mHardLimit * 9) / 10), // default, if no pref mTotalSize(0), mInactiveSize(0), mEntryCount(0), mMaxEntryCount(0), - mMaxEntrySize(-1) // -1 means "no limit" + mMaxEntrySize(-1), // -1 means "no limit" + mReporter(nullptr) { for (int i=0; i<kQueueCount; ++i) PR_INIT_CLIST(&mEvictionList[i]); + + mReporter = new NetworkMemoryCacheReporter(this); + NS_RegisterMemoryReporter(mReporter); } nsMemoryCacheDevice::~nsMemoryCacheDevice() -{ +{ + NS_UnregisterMemoryReporter(mReporter); Shutdown(); } nsresult nsMemoryCacheDevice::Init() { if (mInitialized) return NS_ERROR_ALREADY_INITIALIZED;
--- a/netwerk/cache/nsMemoryCacheDevice.h +++ b/netwerk/cache/nsMemoryCacheDevice.h @@ -1,22 +1,23 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * This Source Code Form is subject to the terms of the Mozilla Public +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* vim: set ts=8 sts=4 et sw=4 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef _nsMemoryCacheDevice_h_ #define _nsMemoryCacheDevice_h_ #include "nsCacheDevice.h" #include "pldhash.h" #include "nsCacheEntry.h" +class nsIMemoryReporter; class nsMemoryCacheDeviceInfo; /****************************************************************************** * nsMemoryCacheDevice ******************************************************************************/ class nsMemoryCacheDevice : public nsCacheDevice { public: @@ -94,16 +95,18 @@ private: int32_t mTotalSize; int32_t mInactiveSize; int32_t mEntryCount; int32_t mMaxEntryCount; int32_t mMaxEntrySize; // internal unit is bytes // XXX what other stats do we want to keep? + + nsCOMPtr<nsIMemoryReporter> mReporter; }; /****************************************************************************** * nsMemoryCacheDeviceInfo - used to call nsIVisitor for about:cache ******************************************************************************/ class nsMemoryCacheDeviceInfo : public nsICacheDeviceInfo { public:
--- a/xpcom/base/nsCycleCollector.cpp +++ b/xpcom/base/nsCycleCollector.cpp @@ -1,10 +1,10 @@ /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* vim: set cindent tabstop=4 expandtab shiftwidth=4: */ +/* vim: set ts=8 sts=4 et sw=4 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ // // This file implements a garbage-cycle collector based on the paper // // Concurrent Cycle Collection in Reference Counted Systems @@ -1036,16 +1036,18 @@ struct nsCycleCollector // mVisitedRefCounted and mVisitedGCed are only used for telemetry uint32_t mVisitedRefCounted; uint32_t mVisitedGCed; CC_BeforeUnlinkCallback mBeforeUnlinkCB; CC_ForgetSkippableCallback mForgetSkippableCB; + nsCOMPtr<nsIMemoryMultiReporter> mReporter; + nsPurpleBuffer mPurpleBuf; void RegisterJSRuntime(nsCycleCollectionJSRuntime *aJSRuntime); void ForgetJSRuntime(); void SelectPurple(GCGraphBuilder &builder); void MarkRoots(GCGraphBuilder &builder); void ScanRoots(); @@ -1134,17 +1136,16 @@ public: //////////////////////////////////////////////////////////////////////// // The static collector object //////////////////////////////////////////////////////////////////////// static nsCycleCollector *sCollector = nullptr; -static nsIMemoryMultiReporter *sCollectorReporter = nullptr; //////////////////////////////////////////////////////////////////////// // Utility functions //////////////////////////////////////////////////////////////////////// MOZ_NEVER_INLINE static void Fault(const char *msg, const void *ptr=nullptr) @@ -2435,62 +2436,154 @@ nsCycleCollector::CollectWhite(nsICycleC if (ms2.lTotalCount < ms1.lTotalCount) mStats.mFreedBytes += (ms1.lTotalCount - ms2.lTotalCount); #endif return count > 0; } +//////////////////////// +// Memory reporter +//////////////////////// + +class CycleCollectorMultiReporter MOZ_FINAL : public nsIMemoryMultiReporter +{ + public: + CycleCollectorMultiReporter(nsCycleCollector* aCollector) + : mCollector(aCollector) + {} + + NS_DECL_ISUPPORTS + + NS_IMETHOD GetName(nsACString& name) + { + name.AssignLiteral("cycle-collector"); + return NS_OK; + } + + NS_IMETHOD CollectReports(nsIMemoryMultiReporterCallback* aCb, + nsISupports* aClosure) + { + size_t objectSize, graphNodesSize, graphEdgesSize, whiteNodesSize, + purpleBufferSize; + mCollector->SizeOfIncludingThis(MallocSizeOf, + &objectSize, &graphNodesSize, + &graphEdgesSize, &whiteNodesSize, + &purpleBufferSize); + + #define REPORT(_path, _amount, _desc) \ + do { \ + size_t amount = _amount; /* evaluate |_amount| only once */ \ + if (amount > 0) { \ + nsresult rv; \ + rv = aCb->Callback(EmptyCString(), NS_LITERAL_CSTRING(_path), \ + nsIMemoryReporter::KIND_HEAP, \ + nsIMemoryReporter::UNITS_BYTES, _amount, \ + NS_LITERAL_CSTRING(_desc), aClosure); \ + NS_ENSURE_SUCCESS(rv, rv); \ + } \ + } while (0) + + REPORT("explicit/cycle-collector/collector-object", objectSize, + "Memory used for the cycle collector object itself."); + + REPORT("explicit/cycle-collector/graph-nodes", graphNodesSize, + "Memory used for the nodes of the cycle collector's graph. " + "This should be zero when the collector is idle."); + + REPORT("explicit/cycle-collector/graph-edges", graphEdgesSize, + "Memory used for the edges of the cycle collector's graph. " + "This should be zero when the collector is idle."); + + REPORT("explicit/cycle-collector/white-nodes", whiteNodesSize, + "Memory used for the cycle collector's white nodes array. " + "This should be zero when the collector is idle."); + + REPORT("explicit/cycle-collector/purple-buffer", purpleBufferSize, + "Memory used for the cycle collector's purple buffer."); + + #undef REPORT + + return NS_OK; + } + + NS_IMETHOD GetExplicitNonHeap(int64_t* n) + { + // This reporter does neither "explicit" nor NONHEAP measurements. + *n = 0; + return NS_OK; + } + + private: + NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(MallocSizeOf) + + nsCycleCollector* mCollector; +}; + +NS_IMPL_ISUPPORTS1(CycleCollectorMultiReporter, nsIMemoryMultiReporter) + + //////////////////////////////////////////////////////////////////////// // Collector implementation //////////////////////////////////////////////////////////////////////// nsCycleCollector::nsCycleCollector() : mCollectionInProgress(false), mScanInProgress(false), mResults(nullptr), mJSRuntime(nullptr), mWhiteNodes(nullptr), mWhiteNodeCount(0), mVisitedRefCounted(0), mVisitedGCed(0), mBeforeUnlinkCB(nullptr), mForgetSkippableCB(nullptr), + mReporter(nullptr), #ifdef DEBUG_CC mPurpleBuf(mParams, mStats), mPtrLog(nullptr) #else mPurpleBuf(mParams) #endif { #ifdef DEBUG_CC mExpectedGarbage.Init(); #endif } nsCycleCollector::~nsCycleCollector() { + NS_UnregisterMemoryMultiReporter(mReporter); } -void +void nsCycleCollector::RegisterJSRuntime(nsCycleCollectionJSRuntime *aJSRuntime) { if (mParams.mDoNothing) return; if (mJSRuntime) Fault("multiple registrations of cycle collector JS runtime", aJSRuntime); mJSRuntime = aJSRuntime; + + // We can't register the reporter in nsCycleCollector() because that runs + // before the memory reporter manager is initialized. So we do it here + // instead. + static bool registered = false; + if (!registered) { + NS_RegisterMemoryMultiReporter(new CycleCollectorMultiReporter(this)); + registered = true; + } } -void +void nsCycleCollector::ForgetJSRuntime() { if (mParams.mDoNothing) return; if (!mJSRuntime) Fault("forgetting non-registered cycle collector JS runtime"); @@ -3018,23 +3111,16 @@ void nsCycleCollector::WasFreed(nsISupports *n) { if (n) { mExpectedGarbage.RemoveEntry(n); } } #endif - -//////////////////////// -// Memory reporter -//////////////////////// - -NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(CycleCollectorMallocSizeOf) - void nsCycleCollector::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf, size_t *aObjectSize, size_t *aGraphNodesSize, size_t *aGraphEdgesSize, size_t *aWhiteNodeSize, size_t *aPurpleBufferSize) const { @@ -3052,111 +3138,34 @@ nsCycleCollector::SizeOfIncludingThis(ns // These fields are deliberately not measured: // - mResults: because it's tiny and only contains scalars. // - mJSRuntime: because it's non-owning and measured by JS reporters. // - mParams: because it only contains scalars. // - mStats, mPtrLog, mExpectedGarbage: because they're DEBUG_CC-only. } -class CycleCollectorMultiReporter MOZ_FINAL : public nsIMemoryMultiReporter -{ - public: - NS_DECL_ISUPPORTS - - NS_IMETHOD GetName(nsACString &name) - { - name.AssignLiteral("cycle-collector"); - return NS_OK; - } - - NS_IMETHOD CollectReports(nsIMemoryMultiReporterCallback *aCb, - nsISupports *aClosure) - { - if (!sCollector) - return NS_OK; - - size_t objectSize, graphNodesSize, graphEdgesSize, whiteNodesSize, - purpleBufferSize; - sCollector->SizeOfIncludingThis(CycleCollectorMallocSizeOf, - &objectSize, &graphNodesSize, - &graphEdgesSize, &whiteNodesSize, - &purpleBufferSize); - - #define REPORT(_path, _amount, _desc) \ - do { \ - size_t amount = _amount; /* evaluate |_amount| just once */ \ - if (amount > 0) { \ - nsresult rv; \ - rv = aCb->Callback(EmptyCString(), NS_LITERAL_CSTRING(_path), \ - nsIMemoryReporter::KIND_HEAP, \ - nsIMemoryReporter::UNITS_BYTES, _amount, \ - NS_LITERAL_CSTRING(_desc), aClosure); \ - NS_ENSURE_SUCCESS(rv, rv); \ - } \ - } while (0) - - REPORT("explicit/cycle-collector/collector-object", objectSize, - "Memory used for the cycle collector object itself."); - - REPORT("explicit/cycle-collector/graph-nodes", graphNodesSize, - "Memory used for the nodes of the cycle collector's graph. " - "This should be zero when the collector is idle."); - - REPORT("explicit/cycle-collector/graph-edges", graphEdgesSize, - "Memory used for the edges of the cycle collector's graph. " - "This should be zero when the collector is idle."); - - REPORT("explicit/cycle-collector/white-nodes", whiteNodesSize, - "Memory used for the cycle collector's white nodes array. " - "This should be zero when the collector is idle."); - - REPORT("explicit/cycle-collector/purple-buffer", purpleBufferSize, - "Memory used for the cycle collector's purple buffer."); - - return NS_OK; - } - - NS_IMETHOD GetExplicitNonHeap(int64_t *n) - { - // This reporter does neither "explicit" nor NONHEAP measurements. - *n = 0; - return NS_OK; - } -}; - -NS_IMPL_ISUPPORTS1(CycleCollectorMultiReporter, nsIMemoryMultiReporter) //////////////////////////////////////////////////////////////////////// // Module public API (exported in nsCycleCollector.h) // Just functions that redirect into the singleton, once it's built. //////////////////////////////////////////////////////////////////////// void nsCycleCollector_registerJSRuntime(nsCycleCollectionJSRuntime *rt) { - static bool regMemReport = true; if (sCollector) sCollector->RegisterJSRuntime(rt); - if (regMemReport) { - regMemReport = false; - sCollectorReporter = new CycleCollectorMultiReporter; - NS_RegisterMemoryMultiReporter(sCollectorReporter); - } } void nsCycleCollector_forgetJSRuntime() { if (sCollector) sCollector->ForgetJSRuntime(); - if (sCollectorReporter) { - NS_UnregisterMemoryMultiReporter(sCollectorReporter); - sCollectorReporter = nullptr; - } } nsPurpleBufferEntry* NS_CycleCollectorSuspect2(void *n, nsCycleCollectionParticipant *cp) { if (sCollector) return sCollector->Suspect2(n, cp); return nullptr;
--- a/xpcom/base/nsIMemoryReporter.idl +++ b/xpcom/base/nsIMemoryReporter.idl @@ -1,9 +1,10 @@ -/* -*- Mode: C++; tab-width: 50; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "nsISupports.idl" interface nsISimpleEnumerator; interface nsIRunnable; @@ -299,46 +300,48 @@ interface nsIMemoryReporterManager : nsI * usage. When we're finished, we invoke the given runnable if it's not * null. Returns a reference to the runnable used for carrying out the task. */ nsICancelableRunnable minimizeMemoryUsage(in nsIRunnable callback); }; %{C++ -/* - * Note that this defaults 'process' to "", which is usually what's desired. - */ +#include "nsStringGlue.h" + +// The NS_*MEMORY_REPORTER_IMPLEMENT* macros are the deprecated short-cut way +// of defining memory reporters. You should instead subclass the +// MemoryReporterBase class below. + +// Note that this defaults 'process' to "", which is usually what's desired. #define NS_MEMORY_REPORTER_IMPLEMENT_HELPER(_classname, _path, _kind, _units, _amountFunction, _desc, _ts) \ class MemoryReporter_##_classname MOZ_FINAL : public nsIMemoryReporter { \ public: \ NS_DECL_ISUPPORTS \ NS_IMETHOD GetProcess(nsACString &process) { process.Truncate(); return NS_OK; } \ NS_IMETHOD GetPath(nsACString &memoryPath) { memoryPath.AssignLiteral(_path); return NS_OK; } \ NS_IMETHOD GetKind(int *kind) { *kind = _kind; return NS_OK; } \ NS_IMETHOD GetUnits(int *units) { *units = _units; return NS_OK; } \ NS_IMETHOD GetAmount(int64_t *amount) { *amount = _amountFunction(); return NS_OK; } \ NS_IMETHOD GetDescription(nsACString &desc) { desc.AssignLiteral(_desc); return NS_OK; } \ }; \ NS_IMPL##_ts##ISUPPORTS1(MemoryReporter_##_classname, nsIMemoryReporter) -/* - * The only difference between this and NS_MEMORY_REPORTER_IMPLEMENT_HELPER - * is that the function used to implement GetAmount is fallible. - */ +// The only difference between this and NS_MEMORY_REPORTER_IMPLEMENT_HELPER +// is that the function used to implement GetAmount is fallible. #define NS_FALLIBLE_MEMORY_REPORTER_IMPLEMENT_HELPER(_classname, _path, _kind, _units, _amountFunction, _desc, _ts) \ class MemoryReporter_##_classname MOZ_FINAL : public nsIMemoryReporter { \ public: \ NS_DECL_ISUPPORTS \ NS_IMETHOD GetProcess(nsACString &process) { process.Truncate(); return NS_OK; } \ NS_IMETHOD GetPath(nsACString &memoryPath) { memoryPath.AssignLiteral(_path); return NS_OK; } \ - NS_IMETHOD GetKind(int *kind) { *kind = _kind; return NS_OK; } \ - NS_IMETHOD GetUnits(int *units) { *units = _units; return NS_OK; } \ + NS_IMETHOD GetKind(int32_t *kind) { *kind = _kind; return NS_OK; } \ + NS_IMETHOD GetUnits(int32_t *units) { *units = _units; return NS_OK; } \ NS_IMETHOD GetAmount(int64_t *amount) { return _amountFunction(amount); } \ - NS_IMETHOD GetDescription(nsACString &desc) { desc.AssignLiteral(_desc); return NS_OK; } \ + NS_IMETHOD GetDescription(nsACString &desc) { desc.AssignLiteral(_desc); return NS_OK; }\ }; \ NS_IMPL##_ts##ISUPPORTS1(MemoryReporter_##_classname, nsIMemoryReporter) #define NS_MEMORY_REPORTER_IMPLEMENT(_c, _p, _k, _u, _a, _d) \ NS_MEMORY_REPORTER_IMPLEMENT_HELPER(_c, _p, _k, _u, _a, _d, _) #define NS_THREADSAFE_MEMORY_REPORTER_IMPLEMENT(_c, _p, _k, _u, _a, _d) \ NS_MEMORY_REPORTER_IMPLEMENT_HELPER(_c, _p, _k, _u, _a, _d, _THREADSAFE_) #define NS_FALLIBLE_MEMORY_REPORTER_IMPLEMENT(_c, _p, _k, _u, _a, _d) \ @@ -416,9 +419,87 @@ void RunReporters(); return moz_malloc_size_of(ptr); \ } #define NS_MEMORY_REPORTER_MALLOC_SIZEOF_ON_FREE_FUN(fn) \ static size_t fn(const void *ptr) \ { \ return moz_malloc_size_of(ptr); \ } +namespace mozilla { + +// The following base class reduces the amount of boilerplate code required for +// memory reporters. You just need to provide the following. +// - The constant values: path, kind, units, and description. They are passed +// to the MemoryReporterBase constructor. +// - An Amount() method. It can use the MallocSizeOf method if necessary. +// +// The class name of subclasses should match the path, minus the "explicit" +// (if present), and with "Reporter" at the end. For example: +// - "explicit/dom/xyzzy" --> DOMXyzzyReporter +// - "js-compartments/system" --> JSCompartmentsSystemReporter +// +class MemoryReporterBase : public nsIMemoryReporter +{ +public: + MemoryReporterBase(const char* aPath, int32_t aKind, int32_t aUnits, + const char* aDescription) + : mPath(aPath) + , mKind(aKind) + , mUnits(aUnits) + , mDescription(aDescription) + {} + + virtual ~MemoryReporterBase() {} + + NS_DECL_ISUPPORTS + + NS_IMETHOD GetProcess(nsACString& aProcess) + { + aProcess.Truncate(); + return NS_OK; + } + + NS_IMETHOD GetPath(nsACString& aPath) + { + aPath.Assign(mPath); + return NS_OK; + } + + NS_IMETHOD GetKind(int32_t* aKind) + { + *aKind = mKind; + return NS_OK; + } + + NS_IMETHOD GetUnits(int32_t* aUnits) + { + *aUnits = mUnits; + return NS_OK; + } + + NS_IMETHOD GetAmount(int64_t* aAmount) + { + *aAmount = Amount(); + return NS_OK; + } + + NS_IMETHOD GetDescription(nsACString& aDescription) + { + aDescription.Assign(mDescription); + return NS_OK; + } + +protected: + virtual int64_t Amount() = 0; + + NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(MallocSizeOf) + + const nsCString mPath; + const int32_t mKind; + const int32_t mUnits; + const nsCString mDescription; +}; + +} // namespace mozilla + + %}
--- a/xpcom/base/nsMemoryReporterManager.cpp +++ b/xpcom/base/nsMemoryReporterManager.cpp @@ -1,10 +1,10 @@ -/* -*- Mode: C++; tab-width: 50; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* vim: set ts=4 et sw=4 tw=80: */ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* vim: set ts=8 sts=4 et sw=4 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "nsAtomTable.h" #include "nsAutoPtr.h" #include "nsCOMPtr.h" #include "nsDirectoryServiceUtils.h" @@ -1062,32 +1062,37 @@ NS_IMETHODIMP nsMemoryReporter::GetPath( NS_IMETHODIMP nsMemoryReporter::GetKind(int32_t *aKind) { *aKind = mKind; return NS_OK; } NS_IMETHODIMP nsMemoryReporter::GetUnits(int32_t *aUnits) { - *aUnits = mUnits; - return NS_OK; + *aUnits = mUnits; + return NS_OK; } NS_IMETHODIMP nsMemoryReporter::GetAmount(int64_t *aAmount) { *aAmount = mAmount; return NS_OK; } NS_IMETHODIMP nsMemoryReporter::GetDescription(nsACString &aDescription) { aDescription.Assign(mDesc); return NS_OK; } +// Most memory reporters don't need thread safety, but some do. Make them all +// thread-safe just to be safe. Memory reporters are created and destroyed +// infrequently enough that the performance cost should be negligible. +NS_IMPL_THREADSAFE_ISUPPORTS1(MemoryReporterBase, nsIMemoryReporter) + nsresult NS_RegisterMemoryReporter (nsIMemoryReporter *reporter) { nsCOMPtr<nsIMemoryReporterManager> mgr = do_GetService("@mozilla.org/memory-reporter-manager;1"); if (mgr == nullptr) return NS_ERROR_FAILURE; return mgr->RegisterReporter(reporter); }