diff options
Diffstat (limited to 'xpcom/base')
-rw-r--r-- | xpcom/base/CycleCollectedJSContext.h | 1 | ||||
-rw-r--r-- | xpcom/base/CycleCollectedJSRuntime.cpp | 18 | ||||
-rw-r--r-- | xpcom/base/CycleCollectedJSRuntime.h | 5 | ||||
-rw-r--r-- | xpcom/base/DarwinObjectPtr.h | 144 | ||||
-rw-r--r-- | xpcom/base/moz.build | 1 | ||||
-rw-r--r-- | xpcom/base/nsCycleCollector.cpp | 92 | ||||
-rw-r--r-- | xpcom/base/nsCycleCollector.h | 3 | ||||
-rw-r--r-- | xpcom/base/nsICycleCollectorListener.idl | 3 | ||||
-rw-r--r-- | xpcom/base/nsIDebug2.idl | 2 | ||||
-rw-r--r-- | xpcom/base/nsIMacPreferencesReader.idl | 2 | ||||
-rw-r--r-- | xpcom/base/nsIMemoryInfoDumper.idl | 8 | ||||
-rw-r--r-- | xpcom/base/nsINIParser.cpp | 1 | ||||
-rw-r--r-- | xpcom/base/nsMemoryInfoDumper.cpp | 2 | ||||
-rw-r--r-- | xpcom/base/nsMemoryReporterManager.cpp | 63 | ||||
-rw-r--r-- | xpcom/base/nsrootidl.idl | 28 |
15 files changed, 284 insertions, 89 deletions
diff --git a/xpcom/base/CycleCollectedJSContext.h b/xpcom/base/CycleCollectedJSContext.h index bbe47a57a5..631afc1504 100644 --- a/xpcom/base/CycleCollectedJSContext.h +++ b/xpcom/base/CycleCollectedJSContext.h @@ -296,6 +296,7 @@ class CycleCollectedJSContext : dom::PerThreadAtomCache, private JS::JobQueue { MOZ_CAN_RUN_SCRIPT_BOUNDARY void runJobs(JSContext* cx) override; bool empty() const override; + bool isDrainingStopped() const override { return false; } class SavedMicroTaskQueue; js::UniquePtr<SavedJobQueue> saveJobQueue(JSContext*) override; diff --git a/xpcom/base/CycleCollectedJSRuntime.cpp b/xpcom/base/CycleCollectedJSRuntime.cpp index c3f9d56857..6833dee791 100644 --- a/xpcom/base/CycleCollectedJSRuntime.cpp +++ b/xpcom/base/CycleCollectedJSRuntime.cpp @@ -1563,17 +1563,27 @@ void CycleCollectedJSRuntime::GarbageCollect(JS::GCOptions aOptions, void CycleCollectedJSRuntime::JSObjectsTenured() { JSContext* cx = CycleCollectedJSContext::Get()->Context(); - for (auto iter = mNurseryObjects.Iter(); !iter.Done(); iter.Next()) { + + NurseryObjectsVector objects; + std::swap(objects, mNurseryObjects); + + for (auto iter = objects.Iter(); !iter.Done(); iter.Next()) { nsWrapperCache* cache = iter.Get(); JSObject* wrapper = cache->GetWrapperMaybeDead(); MOZ_DIAGNOSTIC_ASSERT(wrapper); - if (!JS::ObjectIsTenured(wrapper)) { + + if (!js::gc::IsInsideNursery(wrapper)) { + continue; + } + + if (js::gc::IsDeadNurseryObject(wrapper)) { MOZ_ASSERT(!cache->PreservingWrapper()); js::gc::FinalizeDeadNurseryObject(cx, wrapper); + continue; } - } - mNurseryObjects.Clear(); + mNurseryObjects.InfallibleAppend(cache); + } } void CycleCollectedJSRuntime::NurseryWrapperAdded(nsWrapperCache* aCache) { diff --git a/xpcom/base/CycleCollectedJSRuntime.h b/xpcom/base/CycleCollectedJSRuntime.h index 6f03d3ee99..af837e1ae7 100644 --- a/xpcom/base/CycleCollectedJSRuntime.h +++ b/xpcom/base/CycleCollectedJSRuntime.h @@ -473,8 +473,9 @@ class CycleCollectedJSRuntime { OOMState mLargeAllocationFailureState; static const size_t kSegmentSize = 512; - SegmentedVector<nsWrapperCache*, kSegmentSize, InfallibleAllocPolicy> - mNurseryObjects; + using NurseryObjectsVector = + SegmentedVector<nsWrapperCache*, kSegmentSize, InfallibleAllocPolicy>; + NurseryObjectsVector mNurseryObjects; nsTHashSet<JS::Zone*> mZonesWaitingForGC; diff --git a/xpcom/base/DarwinObjectPtr.h b/xpcom/base/DarwinObjectPtr.h new file mode 100644 index 0000000000..3d5842553b --- /dev/null +++ b/xpcom/base/DarwinObjectPtr.h @@ -0,0 +1,144 @@ +/* + * Copyright (C) 2014-2021 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +// Adapted from +// https://github.com/WebKit/WebKit/blob/ad340677c00a4b4b6a299c93a6e18cd073b3f4e9/Source/WTF/wtf/OSObjectPtr.h + +#ifndef mozilla_DarwinObjectPtr_h +#define mozilla_DarwinObjectPtr_h + +#include <os/object.h> +#include <utility> +#include "mozilla/Attributes.h" + +// Because ARC enablement is a compile-time choice, and we compile this header +// both ways, we need a separate copy of our code when ARC is enabled. +#if __has_feature(objc_arc) +# define AdoptDarwinObject AdoptDarwinObjectArc +# define RetainDarwinObject RetainDarwinObjectArc +# define ReleaseDarwinObject ReleaseDarwinObjectArc +#endif + +namespace mozilla { + +template <typename> +class DarwinObjectPtr; +template <typename T> +[[nodiscard]] DarwinObjectPtr<T> AdoptDarwinObject(T); + +template <typename T> +static inline void RetainDarwinObject(T aPtr) { +#if !__has_feature(objc_arc) + os_retain(aPtr); +#endif +} + +template <typename T> +static inline void ReleaseDarwinObject(T aPtr) { +#if !__has_feature(objc_arc) + os_release(aPtr); +#endif +} + +template <typename T> +class DarwinObjectPtr { + public: + DarwinObjectPtr() : mPtr(nullptr) {} + + ~DarwinObjectPtr() { + if (mPtr) { + ReleaseDarwinObject(mPtr); + } + } + + T get() const { return mPtr; } + + explicit operator bool() const { return mPtr; } + bool operator!() const { return !mPtr; } + + DarwinObjectPtr(const DarwinObjectPtr& aOther) : mPtr(aOther.mPtr) { + if (mPtr) { + RetainDarwinObject(mPtr); + } + } + + DarwinObjectPtr(DarwinObjectPtr&& aOther) : mPtr(std::move(aOther.mPtr)) { + aOther.mPtr = nullptr; + } + + MOZ_IMPLICIT DarwinObjectPtr(T aPtr) : mPtr(std::move(aPtr)) { + if (mPtr) { + RetainDarwinObject(mPtr); + } + } + + DarwinObjectPtr& operator=(const DarwinObjectPtr& aOther) { + DarwinObjectPtr ptr = aOther; + swap(ptr); + return *this; + } + + DarwinObjectPtr& operator=(DarwinObjectPtr&& aOther) { + DarwinObjectPtr ptr = std::move(aOther); + swap(ptr); + return *this; + } + + DarwinObjectPtr& operator=(std::nullptr_t) { + if (mPtr) { + ReleaseDarwinObject(mPtr); + } + mPtr = nullptr; + return *this; + } + + DarwinObjectPtr& operator=(T aOther) { + DarwinObjectPtr ptr = std::move(aOther); + swap(ptr); + return *this; + } + + void swap(DarwinObjectPtr& aOther) { std::swap(mPtr, aOther.mPtr); } + + [[nodiscard]] T forget() { return std::exchange(mPtr, nullptr); } + + friend DarwinObjectPtr AdoptDarwinObject<T>(T); + + private: + struct AdoptDarwinObjectTag {}; + DarwinObjectPtr(AdoptDarwinObjectTag, T aPtr) : mPtr(std::move(aPtr)) {} + + T mPtr; +}; + +template <typename T> +inline DarwinObjectPtr<T> AdoptDarwinObject(T aPtr) { + return DarwinObjectPtr<T>{typename DarwinObjectPtr<T>::AdoptDarwinObjectTag{}, + std::move(aPtr)}; +} + +} // namespace mozilla + +#endif diff --git a/xpcom/base/moz.build b/xpcom/base/moz.build index 16870a9dbc..b7779a67db 100644 --- a/xpcom/base/moz.build +++ b/xpcom/base/moz.build @@ -41,6 +41,7 @@ if CONFIG["OS_ARCH"] == "Darwin": "nsObjCExceptions.h", ] EXPORTS.mozilla += [ + "DarwinObjectPtr.h", "MacStringHelpers.h", ] UNIFIED_SOURCES += [ diff --git a/xpcom/base/nsCycleCollector.cpp b/xpcom/base/nsCycleCollector.cpp index 9c39dee475..7908fe8037 100644 --- a/xpcom/base/nsCycleCollector.cpp +++ b/xpcom/base/nsCycleCollector.cpp @@ -159,6 +159,7 @@ #include "mozilla/HashFunctions.h" #include "mozilla/HashTable.h" #include "mozilla/HoldDropJSObjects.h" +#include "mozilla/Maybe.h" /* This must occur *after* base/process_util.h to avoid typedefs conflicts. */ #include <stdint.h> #include <stdio.h> @@ -269,6 +270,11 @@ static void SuspectUsingNurseryPurpleBuffer( // MOZ_CC_LOG_DIRECTORY: The directory in which logs are placed (such as // logs from MOZ_CC_LOG_ALL and MOZ_CC_LOG_SHUTDOWN, or other uses // of nsICycleCollectorListener) +// +// MOZ_CC_DISABLE_GC_LOG: If defined, don't make a GC log whenever we make a +// cycle collector log. This can be useful for leaks that go away when shutdown +// gets slower, when the JS heap is not involved in the leak. The default is to +// make the GC log. // Various parameters of this collector can be tuned using environment // variables. @@ -279,13 +285,15 @@ struct nsCycleCollectorParams { bool mAllTracesAll; bool mAllTracesShutdown; bool mLogThisThread; + bool mLogGC; int32_t mLogShutdownSkip = 0; nsCycleCollectorParams() : mLogAll(PR_GetEnv("MOZ_CC_LOG_ALL") != nullptr), mLogShutdown(PR_GetEnv("MOZ_CC_LOG_SHUTDOWN") != nullptr), mAllTracesAll(false), - mAllTracesShutdown(false) { + mAllTracesShutdown(false), + mLogGC(!PR_GetEnv("MOZ_CC_DISABLE_GC_LOG")) { if (const char* lssEnv = PR_GetEnv("MOZ_CC_LOG_SHUTDOWN_SKIP")) { mLogShutdown = true; nsDependentCString lssString(lssEnv); @@ -352,6 +360,8 @@ struct nsCycleCollectorParams { bool AllTracesThisCC(bool aIsShutdown) { return mAllTracesAll || (aIsShutdown && mAllTracesShutdown); } + + bool LogThisGC() const { return mLogGC; } }; #ifdef COLLECT_TIME_DEBUG @@ -1376,10 +1386,12 @@ class nsCycleCollectorLogSinkToFile final : public nsICycleCollectorLogSink { public: NS_DECL_ISUPPORTS - nsCycleCollectorLogSinkToFile() - : mProcessIdentifier(base::GetCurrentProcId()), - mGCLog("gc-edges"), - mCCLog("cc-edges") {} + explicit nsCycleCollectorLogSinkToFile(bool aLogGC) + : mProcessIdentifier(base::GetCurrentProcId()), mCCLog("cc-edges") { + if (aLogGC) { + mGCLog.emplace("gc-edges"); + } + } NS_IMETHOD GetFilenameIdentifier(nsAString& aIdentifier) override { aIdentifier = mFilenameIdentifier; @@ -1402,7 +1414,10 @@ class nsCycleCollectorLogSinkToFile final : public nsICycleCollectorLogSink { } NS_IMETHOD GetGcLog(nsIFile** aPath) override { - NS_IF_ADDREF(*aPath = mGCLog.mFile); + if (mGCLog.isNothing()) { + return NS_ERROR_UNEXPECTED; + } + NS_IF_ADDREF(*aPath = mGCLog.ref().mFile); return NS_OK; } @@ -1414,13 +1429,21 @@ class nsCycleCollectorLogSinkToFile final : public nsICycleCollectorLogSink { NS_IMETHOD Open(FILE** aGCLog, FILE** aCCLog) override { nsresult rv; - if (mGCLog.mStream || mCCLog.mStream) { + if (mCCLog.mStream) { return NS_ERROR_UNEXPECTED; } - rv = OpenLog(&mGCLog); - NS_ENSURE_SUCCESS(rv, rv); - *aGCLog = mGCLog.mStream; + if (mGCLog.isSome()) { + if (mGCLog.ref().mStream) { + return NS_ERROR_UNEXPECTED; + } + + rv = OpenLog(&mGCLog.ref()); + NS_ENSURE_SUCCESS(rv, rv); + *aGCLog = mGCLog.ref().mStream; + } else { + *aGCLog = nullptr; + } rv = OpenLog(&mCCLog); NS_ENSURE_SUCCESS(rv, rv); @@ -1430,10 +1453,13 @@ class nsCycleCollectorLogSinkToFile final : public nsICycleCollectorLogSink { } NS_IMETHOD CloseGCLog() override { - if (!mGCLog.mStream) { + if (mGCLog.isNothing()) { + return NS_OK; + } + if (!mGCLog.ref().mStream) { return NS_ERROR_UNEXPECTED; } - CloseLog(&mGCLog, u"Garbage"_ns); + CloseLog(&mGCLog.ref(), u"Garbage"_ns); return NS_OK; } @@ -1447,9 +1473,9 @@ class nsCycleCollectorLogSinkToFile final : public nsICycleCollectorLogSink { private: ~nsCycleCollectorLogSinkToFile() { - if (mGCLog.mStream) { - MozillaUnRegisterDebugFILE(mGCLog.mStream); - fclose(mGCLog.mStream); + if (mGCLog.isSome() && mGCLog.ref().mStream) { + MozillaUnRegisterDebugFILE(mGCLog.ref().mStream); + fclose(mGCLog.ref().mStream); } if (mCCLog.mStream) { MozillaUnRegisterDebugFILE(mCCLog.mStream); @@ -1566,7 +1592,7 @@ class nsCycleCollectorLogSinkToFile final : public nsICycleCollectorLogSink { int32_t mProcessIdentifier; nsString mFilenameIdentifier; - FileInfo mGCLog; + Maybe<FileInfo> mGCLog; FileInfo mCCLog; }; @@ -1576,8 +1602,8 @@ class nsCycleCollectorLogger final : public nsICycleCollectorListener { ~nsCycleCollectorLogger() { ClearDescribers(); } public: - nsCycleCollectorLogger() - : mLogSink(nsCycleCollector_createLogSink()), + explicit nsCycleCollectorLogger(bool aLogGC) + : mLogSink(nsCycleCollector_createLogSink(aLogGC)), mWantAllTraces(false), mDisableLog(false), mWantAfterProcessing(false), @@ -1646,13 +1672,14 @@ class nsCycleCollectorLogger final : public nsICycleCollectorListener { rv = mLogSink->Open(&gcLog, &mCCLog); NS_ENSURE_SUCCESS(rv, rv); // Dump the JS heap. - CollectorData* data = sCollectorData.get(); - if (data && data->mContext) { - data->mContext->Runtime()->DumpJSHeap(gcLog); + if (gcLog) { + CollectorData* data = sCollectorData.get(); + if (data && data->mContext) { + data->mContext->Runtime()->DumpJSHeap(gcLog); + } + rv = mLogSink->CloseGCLog(); + NS_ENSURE_SUCCESS(rv, rv); } - rv = mLogSink->CloseGCLog(); - NS_ENSURE_SUCCESS(rv, rv); - fprintf(mCCLog, "# WantAllTraces=%s\n", mWantAllTraces ? "true" : "false"); return NS_OK; } @@ -1822,7 +1849,8 @@ class nsCycleCollectorLogger final : public nsICycleCollectorListener { NS_IMPL_ISUPPORTS(nsCycleCollectorLogger, nsICycleCollectorListener) already_AddRefed<nsICycleCollectorListener> nsCycleCollector_createLogger() { - nsCOMPtr<nsICycleCollectorListener> logger = new nsCycleCollectorLogger(); + nsCOMPtr<nsICycleCollectorListener> logger = + new nsCycleCollectorLogger(/* aLogGC = */ true); return logger.forget(); } @@ -3283,7 +3311,11 @@ void nsCycleCollector::SuspectNurseryEntries() { while (gNurseryPurpleBufferEntryCount) { NurseryPurpleBufferEntry& entry = gNurseryPurpleBufferEntry[--gNurseryPurpleBufferEntryCount]; - mPurpleBuf.Put(entry.mPtr, entry.mParticipant, entry.mRefCnt); + if (!entry.mRefCnt->IsPurple() && IsIdle()) { + entry.mRefCnt->RemoveFromPurpleBuffer(); + } else { + mPurpleBuf.Put(entry.mPtr, entry.mParticipant, entry.mRefCnt); + } } } @@ -3628,7 +3660,7 @@ void nsCycleCollector::BeginCollection( aManualListener = nullptr; if (!mLogger && mParams.LogThisCC(mShutdownCount)) { - mLogger = new nsCycleCollectorLogger(); + mLogger = new nsCycleCollectorLogger(mParams.LogThisGC()); if (mParams.AllTracesThisCC(isShutdown)) { mLogger->SetAllTraces(); } @@ -3963,8 +3995,10 @@ bool nsCycleCollector_doDeferredDeletionWithBudget(js::SliceBudget& aBudget) { return data->mCollector->FreeSnowWhiteWithBudget(aBudget); } -already_AddRefed<nsICycleCollectorLogSink> nsCycleCollector_createLogSink() { - nsCOMPtr<nsICycleCollectorLogSink> sink = new nsCycleCollectorLogSinkToFile(); +already_AddRefed<nsICycleCollectorLogSink> nsCycleCollector_createLogSink( + bool aLogGC) { + nsCOMPtr<nsICycleCollectorLogSink> sink = + new nsCycleCollectorLogSinkToFile(aLogGC); return sink.forget(); } diff --git a/xpcom/base/nsCycleCollector.h b/xpcom/base/nsCycleCollector.h index 1c583e04cf..e25647175e 100644 --- a/xpcom/base/nsCycleCollector.h +++ b/xpcom/base/nsCycleCollector.h @@ -49,7 +49,8 @@ void nsCycleCollector_dispatchDeferredDeletion(bool aContinuation = false, bool nsCycleCollector_doDeferredDeletion(); bool nsCycleCollector_doDeferredDeletionWithBudget(js::SliceBudget& aBudget); -already_AddRefed<nsICycleCollectorLogSink> nsCycleCollector_createLogSink(); +already_AddRefed<nsICycleCollectorLogSink> nsCycleCollector_createLogSink( + bool aLogGC); already_AddRefed<nsICycleCollectorListener> nsCycleCollector_createLogger(); // Run a cycle collection and return whether anything was collected. diff --git a/xpcom/base/nsICycleCollectorListener.idl b/xpcom/base/nsICycleCollectorListener.idl index 5e0b059a13..c93f3c9174 100644 --- a/xpcom/base/nsICycleCollectorListener.idl +++ b/xpcom/base/nsICycleCollectorListener.idl @@ -72,8 +72,11 @@ interface nsICycleCollectorHandler : nsISupports [scriptable, builtinclass, uuid(3ad9875f-d0e4-4ac2-87e3-f127f6c02ce1)] interface nsICycleCollectorLogSink : nsISupports { + // aGCLog can be null, if the sink was not configured to create a GC log. [noscript] void open(out FILE aGCLog, out FILE aCCLog); + void closeGCLog(); + void closeCCLog(); // This string will appear somewhere in the log's filename. diff --git a/xpcom/base/nsIDebug2.idl b/xpcom/base/nsIDebug2.idl index 4672fea7ea..f60a8eafa5 100644 --- a/xpcom/base/nsIDebug2.idl +++ b/xpcom/base/nsIDebug2.idl @@ -33,7 +33,7 @@ interface nsIDebug2 : nsISupports * Whether a debugger is currently attached. * Supports Windows + Mac */ - readonly attribute bool isDebuggerAttached; + readonly attribute boolean isDebuggerAttached; /** * Show an assertion and trigger nsIDebug2.break(). diff --git a/xpcom/base/nsIMacPreferencesReader.idl b/xpcom/base/nsIMacPreferencesReader.idl index 470fd92ec9..29461f862a 100644 --- a/xpcom/base/nsIMacPreferencesReader.idl +++ b/xpcom/base/nsIMacPreferencesReader.idl @@ -22,7 +22,7 @@ interface nsIMacPreferencesReader : nsISupports * * @return true if macOS policies are enabled, false otherwise. */ - bool policiesEnabled(); + boolean policiesEnabled(); /** * This method reads and returns the macOS preferences. diff --git a/xpcom/base/nsIMemoryInfoDumper.idl b/xpcom/base/nsIMemoryInfoDumper.idl index 79b03a709d..83290b57ab 100644 --- a/xpcom/base/nsIMemoryInfoDumper.idl +++ b/xpcom/base/nsIMemoryInfoDumper.idl @@ -36,7 +36,7 @@ interface nsIDumpGCAndCCLogsCallback : nsISupports */ void onDump(in nsIFile aGCLog, in nsIFile aCCLog, - in bool aIsParent); + in boolean aIsParent); /** * Called when GC/CC logging has finished, after all calls to |onDump|. @@ -153,8 +153,8 @@ interface nsIMemoryInfoDumper : nsISupports * */ void dumpGCAndCCLogsToFile(in AString aIdentifier, - in bool aDumpAllTraces, - in bool aDumpChildProcesses, + in boolean aDumpAllTraces, + in boolean aDumpChildProcesses, in nsIDumpGCAndCCLogsCallback aCallback); /** @@ -162,6 +162,6 @@ interface nsIMemoryInfoDumper : nsISupports * sink object instead of accessing the filesystem directly, and * dumps the current process only. */ - void dumpGCAndCCLogsToSink(in bool aDumpAllTraces, + void dumpGCAndCCLogsToSink(in boolean aDumpAllTraces, in nsICycleCollectorLogSink aSink); }; diff --git a/xpcom/base/nsINIParser.cpp b/xpcom/base/nsINIParser.cpp index 1447aa6fbf..df3f1fcc0d 100644 --- a/xpcom/base/nsINIParser.cpp +++ b/xpcom/base/nsINIParser.cpp @@ -243,7 +243,6 @@ nsresult nsINIParser::DeleteString(const char* aSection, const char* aKey) { mSections.Remove(aSection); } else { mSections.InsertOrUpdate(aSection, std::move(val->next)); - delete val; } return NS_OK; } diff --git a/xpcom/base/nsMemoryInfoDumper.cpp b/xpcom/base/nsMemoryInfoDumper.cpp index 28af408178..433919146a 100644 --- a/xpcom/base/nsMemoryInfoDumper.cpp +++ b/xpcom/base/nsMemoryInfoDumper.cpp @@ -323,7 +323,7 @@ nsMemoryInfoDumper::DumpGCAndCCLogsToFile( for (uint32_t i = 0; i < children.Length(); i++) { ContentParent* cp = children[i]; nsCOMPtr<nsICycleCollectorLogSink> logSink = - nsCycleCollector_createLogSink(); + nsCycleCollector_createLogSink(/* aLogGC = */ true); logSink->SetFilenameIdentifier(identifier); logSink->SetProcessIdentifier(cp->Pid()); diff --git a/xpcom/base/nsMemoryReporterManager.cpp b/xpcom/base/nsMemoryReporterManager.cpp index aaf1baeea2..a3a2a247f6 100644 --- a/xpcom/base/nsMemoryReporterManager.cpp +++ b/xpcom/base/nsMemoryReporterManager.cpp @@ -1247,7 +1247,7 @@ NS_IMPL_ISUPPORTS(PageFaultsHardReporter, nsIMemoryReporter) #ifdef HAVE_JEMALLOC_STATS static size_t HeapOverhead(const jemalloc_stats_t& aStats) { - return aStats.waste + aStats.bookkeeping + aStats.page_cache + + return aStats.waste + aStats.bookkeeping + aStats.pages_dirty + aStats.bin_unused; } @@ -1278,7 +1278,7 @@ class JemallocHeapReporter final : public nsIMemoryReporter { // clang-format off MOZ_COLLECT_REPORT( - "heap-committed/allocated", KIND_OTHER, UNITS_BYTES, stats.allocated, + "heap/committed/allocated", KIND_OTHER, UNITS_BYTES, stats.allocated, "Memory mapped by the heap allocator that is currently allocated to the " "application. This may exceed the amount of memory requested by the " "application because the allocator regularly rounds up request sizes. (The " @@ -1286,14 +1286,14 @@ class JemallocHeapReporter final : public nsIMemoryReporter { MOZ_COLLECT_REPORT( "heap-allocated", KIND_OTHER, UNITS_BYTES, stats.allocated, -"The same as 'heap-committed/allocated'."); +"The same as 'heap/committed/allocated'."); - // We mark this and the other heap-overhead reporters as KIND_NONHEAP + // We mark this and the other heap/committed/overhead reporters as KIND_NONHEAP // because KIND_HEAP memory means "counted in heap-allocated", which // this is not. for (auto& bin : bin_stats) { MOZ_ASSERT(bin.size); - nsPrintfCString path("explicit/heap-overhead/bin-unused/bin-%zu", + nsPrintfCString path("heap/committed/bin-unused/bin-%zu", bin.size); aHandleReport->Callback(EmptyCString(), path, KIND_NONHEAP, UNITS_BYTES, bin.bytes_unused, @@ -1304,36 +1304,63 @@ class JemallocHeapReporter final : public nsIMemoryReporter { if (stats.waste > 0) { MOZ_COLLECT_REPORT( - "explicit/heap-overhead/waste", KIND_NONHEAP, UNITS_BYTES, + "heap/committed/waste", KIND_NONHEAP, UNITS_BYTES, stats.waste, "Committed bytes which do not correspond to an active allocation and which the " "allocator is not intentionally keeping alive (i.e., not " -"'explicit/heap-overhead/{bookkeeping,page-cache,bin-unused}')."); +"'heap/{bookkeeping,unused-pages,bin-unused}')."); } MOZ_COLLECT_REPORT( - "explicit/heap-overhead/bookkeeping", KIND_NONHEAP, UNITS_BYTES, + "heap/committed/bookkeeping", KIND_NONHEAP, UNITS_BYTES, stats.bookkeeping, "Committed bytes which the heap allocator uses for internal data structures."); MOZ_COLLECT_REPORT( - "explicit/heap-overhead/page-cache", KIND_NONHEAP, UNITS_BYTES, - stats.page_cache, + "heap/committed/unused-pages/dirty", KIND_NONHEAP, UNITS_BYTES, + stats.pages_dirty, "Memory which the allocator could return to the operating system, but hasn't. " "The allocator keeps this memory around as an optimization, so it doesn't " "have to ask the OS the next time it needs to fulfill a request. This value " "is typically not larger than a few megabytes."); MOZ_COLLECT_REPORT( - "heap-committed/overhead", KIND_OTHER, UNITS_BYTES, - HeapOverhead(stats), -"The sum of 'explicit/heap-overhead/*'."); + "heap/decommitted/unused-pages/fresh", KIND_OTHER, UNITS_BYTES, stats.pages_fresh, +"Amount of memory currently mapped but has never been used."); + // A duplicate entry in the decommitted part of the tree. + MOZ_COLLECT_REPORT( + "decommitted/heap/unused-pages/fresh", KIND_OTHER, UNITS_BYTES, stats.pages_fresh, +"Amount of memory currently mapped but has never been used."); +// On MacOS madvised memory is still counted in the resident set until the OS +// actually decommits it. +#ifdef XP_MACOSX +#define MADVISED_GROUP "committed" +#else +#define MADVISED_GROUP "decommitted" +#endif + MOZ_COLLECT_REPORT( + "heap/" MADVISED_GROUP "/unused-pages/madvised", KIND_OTHER, UNITS_BYTES, + stats.pages_madvised, +"Amount of memory currently mapped, not used and that the OS should remove " +"from the application's resident set."); + // A duplicate entry in the decommitted part of the tree. MOZ_COLLECT_REPORT( - "heap-mapped", KIND_OTHER, UNITS_BYTES, stats.mapped, -"Amount of memory currently mapped. Includes memory that is uncommitted, i.e. " -"neither in physical memory nor paged to disk."); + "decommitted/heap/unused-pages/madvised", KIND_OTHER, UNITS_BYTES, stats.pages_madvised, +"Amount of memory currently mapped, not used and that the OS should remove " +"from the application's resident set."); + { + size_t decommitted = stats.mapped - stats.allocated - stats.waste - stats.pages_dirty - stats.pages_fresh - stats.bookkeeping - stats.bin_unused; + MOZ_COLLECT_REPORT( + "heap/decommitted/unmapped", KIND_OTHER, UNITS_BYTES, decommitted, + "Amount of memory currently mapped but not committed, " + "neither in physical memory nor paged to disk."); + MOZ_COLLECT_REPORT( + "decommitted/heap/decommitted", KIND_OTHER, UNITS_BYTES, decommitted, + "Amount of memory currently mapped but not committed, " + "neither in physical memory nor paged to disk."); + } MOZ_COLLECT_REPORT( "heap-chunksize", KIND_OTHER, UNITS_BYTES, stats.chunksize, "Size of chunks."); @@ -1343,11 +1370,11 @@ class JemallocHeapReporter final : public nsIMemoryReporter { mozilla::phc::PHCMemoryUsage(usage); MOZ_COLLECT_REPORT( - "explicit/heap-overhead/phc/metadata", KIND_NONHEAP, UNITS_BYTES, + "explicit/phc/metadata", KIND_NONHEAP, UNITS_BYTES, usage.mMetadataBytes, "Memory used by PHC to store stacks and other metadata for each allocation"); MOZ_COLLECT_REPORT( - "explicit/heap-overhead/phc/fragmentation", KIND_NONHEAP, UNITS_BYTES, + "explicit/phc/fragmentation", KIND_NONHEAP, UNITS_BYTES, usage.mFragmentationBytes, "The amount of memory lost due to rounding up allocations to the next page " "size. " diff --git a/xpcom/base/nsrootidl.idl b/xpcom/base/nsrootidl.idl index 292ea54890..364d0b75eb 100644 --- a/xpcom/base/nsrootidl.idl +++ b/xpcom/base/nsrootidl.idl @@ -11,7 +11,6 @@ #include "nscore.h" #include "nsID.h" -typedef int64_t PRTime; /* * Forward declarations for new string types @@ -29,27 +28,9 @@ class Promise; } // namespace dom } // namespace mozilla -/* - * Start commenting out the C++ versions of the below in the output header - */ -#if 0 %} -// [substitute] typedefs emit the underlying builtin type directly, and -// avoid polluting bindings for other languages with C++ stdint types. - -[substitute] typedef boolean bool ; -[substitute] typedef octet uint8_t ; -[substitute] typedef unsigned short uint16_t ; -[substitute] typedef unsigned long uint32_t ; -[substitute] typedef unsigned long long uint64_t ; -[substitute] typedef short int16_t ; -[substitute] typedef long int32_t ; -[substitute] typedef long long int64_t ; - - typedef unsigned short char16_t ; - typedef unsigned long nsresult ; - typedef long long PRTime ; +typedef long long PRTime; // If we ever want to use `size_t` in scriptable interfaces, this will need to // be built into the xpidl compiler, as the size varies based on platform. @@ -99,10 +80,3 @@ class Promise; native jsid(jsid); [ptr, promise] native Promise(ignored); - -%{C++ -/* - * End commenting out the C++ versions of the above in the output header - */ -#endif -%} |