summaryrefslogtreecommitdiffstats
path: root/tools/memory-profiler
diff options
context:
space:
mode:
Diffstat (limited to 'tools/memory-profiler')
-rw-r--r--tools/memory-profiler/GCHeapProfilerImpl.cpp168
-rw-r--r--tools/memory-profiler/GCHeapProfilerImpl.h53
-rw-r--r--tools/memory-profiler/MemoryProfiler.cpp324
-rw-r--r--tools/memory-profiler/MemoryProfiler.h159
-rw-r--r--tools/memory-profiler/NativeProfilerImpl.cpp82
-rw-r--r--tools/memory-profiler/NativeProfilerImpl.h43
-rw-r--r--tools/memory-profiler/UncensoredAllocator.cpp121
-rw-r--r--tools/memory-profiler/UncensoredAllocator.h48
-rw-r--r--tools/memory-profiler/moz.build21
-rw-r--r--tools/memory-profiler/nsIMemoryProfiler.idl72
-rw-r--r--tools/memory-profiler/nsMemoryProfilerFactory.cpp32
11 files changed, 0 insertions, 1123 deletions
diff --git a/tools/memory-profiler/GCHeapProfilerImpl.cpp b/tools/memory-profiler/GCHeapProfilerImpl.cpp
deleted file mode 100644
index 528a05501..000000000
--- a/tools/memory-profiler/GCHeapProfilerImpl.cpp
+++ /dev/null
@@ -1,168 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=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 "GCHeapProfilerImpl.h"
-
-#include "UncensoredAllocator.h"
-
-namespace mozilla {
-
-GCHeapProfilerImpl::GCHeapProfilerImpl()
-{
- mLock = PR_NewLock();
- mMarking = false;
-}
-
-GCHeapProfilerImpl::~GCHeapProfilerImpl()
-{
- if (mLock) {
- PR_DestroyLock(mLock);
- }
-}
-
-nsTArray<nsCString>
-GCHeapProfilerImpl::GetNames() const
-{
- return mTraceTable.GetNames();
-}
-
-nsTArray<TrieNode>
-GCHeapProfilerImpl::GetTraces() const
-{
- return mTraceTable.GetTraces();
-}
-
-const nsTArray<AllocEvent>&
-GCHeapProfilerImpl::GetEvents() const
-{
- return mAllocEvents;
-}
-
-void
-GCHeapProfilerImpl::reset()
-{
- mTraceTable.Reset();
- mAllocEvents.Clear();
- mNurseryEntries.Clear();
- mTenuredEntriesFG.Clear();
- mTenuredEntriesBG.Clear();
-}
-
-void
-GCHeapProfilerImpl::sampleTenured(void* addr, uint32_t size)
-{
- SampleInternal(addr, size, mTenuredEntriesFG);
-}
-
-void
-GCHeapProfilerImpl::sampleNursery(void* addr, uint32_t size)
-{
- SampleInternal(addr, size, mNurseryEntries);
-}
-
-void
-GCHeapProfilerImpl::markTenuredStart()
-{
- AutoUseUncensoredAllocator ua;
- AutoMPLock lock(mLock);
- if (!mMarking) {
- mMarking = true;
- mTenuredEntriesFG.SwapElements(mTenuredEntriesBG);
- MOZ_ASSERT(mTenuredEntriesFG.Count() == 0);
- }
-}
-
-void
-GCHeapProfilerImpl::markTenured(void* addr)
-{
- AutoUseUncensoredAllocator ua;
- AutoMPLock lock(mLock);
- if (mMarking) {
- AllocEntry entry;
- if (mTenuredEntriesBG.Get(addr, &entry)) {
- entry.mMarked = true;
- mTenuredEntriesBG.Put(addr, entry);
- }
- }
-}
-
-void
-GCHeapProfilerImpl::sweepTenured()
-{
- AutoUseUncensoredAllocator ua;
- AutoMPLock lock(mLock);
- if (mMarking) {
- mMarking = false;
- for (auto iter = mTenuredEntriesBG.Iter(); !iter.Done(); iter.Next()) {
- if (iter.Data().mMarked) {
- iter.Data().mMarked = false;
- mTenuredEntriesFG.Put(iter.Key(), iter.Data());
- } else {
- AllocEvent& oldEvent = mAllocEvents[iter.Data().mEventIdx];
- AllocEvent newEvent(oldEvent.mTraceIdx, -oldEvent.mSize, TimeStamp::Now());
- mAllocEvents.AppendElement(newEvent);
- }
- }
- mTenuredEntriesBG.Clear();
- }
-}
-
-void
-GCHeapProfilerImpl::sweepNursery()
-{
- AutoUseUncensoredAllocator ua;
- AutoMPLock lock(mLock);
- for (auto iter = mNurseryEntries.Iter(); !iter.Done(); iter.Next()) {
- AllocEvent& oldEvent = mAllocEvents[iter.Data().mEventIdx];
- AllocEvent newEvent(oldEvent.mTraceIdx, -oldEvent.mSize, TimeStamp::Now());
- mAllocEvents.AppendElement(newEvent);
- }
- mNurseryEntries.Clear();
-}
-
-void
-GCHeapProfilerImpl::moveNurseryToTenured(void* addrOld, void* addrNew)
-{
- AutoUseUncensoredAllocator ua;
- AutoMPLock lock(mLock);
- AllocEntry entryOld;
- if (!mNurseryEntries.Get(addrOld, &entryOld)) {
- return;
- }
-
- // Because the tenured heap is sampled, the address might already be there.
- // If not, the address is inserted with the old event.
- AllocEntry tenuredEntryOld;
- if (!mTenuredEntriesFG.Get(addrNew, &tenuredEntryOld)) {
- mTenuredEntriesFG.Put(addrNew, AllocEntry(entryOld.mEventIdx));
- } else {
- // If it is already inserted, the insertion above will fail and the
- // iterator of the already-inserted element is returned.
- // We choose to ignore the the new event by setting its size zero and point
- // the newly allocated address to the old event.
- // An event of size zero will be skipped when reporting.
- mAllocEvents[entryOld.mEventIdx].mSize = 0;
- tenuredEntryOld.mEventIdx = entryOld.mEventIdx;
- mTenuredEntriesFG.Put(addrNew, tenuredEntryOld);
- }
- mNurseryEntries.Remove(addrOld);
-}
-
-void
-GCHeapProfilerImpl::SampleInternal(void* aAddr, uint32_t aSize, AllocMap& aTable)
-{
- AutoUseUncensoredAllocator ua;
- AutoMPLock lock(mLock);
- size_t nSamples = AddBytesSampled(aSize);
- if (nSamples > 0) {
- nsTArray<nsCString> trace = GetStacktrace();
- AllocEvent ai(mTraceTable.Insert(trace), nSamples * mSampleSize, TimeStamp::Now());
- aTable.Put(aAddr, AllocEntry(mAllocEvents.Length()));
- mAllocEvents.AppendElement(ai);
- }
-}
-
-} // namespace mozilla
diff --git a/tools/memory-profiler/GCHeapProfilerImpl.h b/tools/memory-profiler/GCHeapProfilerImpl.h
deleted file mode 100644
index e84e97017..000000000
--- a/tools/memory-profiler/GCHeapProfilerImpl.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=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/. */
-
-#ifndef memory_profiler_GCHeapProfilerImpl_h
-#define memory_profiler_GCHeapProfilerImpl_h
-
-#include "CompactTraceTable.h"
-#include "MemoryProfiler.h"
-
-#include "jsfriendapi.h"
-
-namespace mozilla {
-
-class GCHeapProfilerImpl final : public GCHeapProfiler
- , public ProfilerImpl
-{
-public:
- GCHeapProfilerImpl();
- ~GCHeapProfilerImpl() override;
-
- nsTArray<nsCString> GetNames() const override;
- nsTArray<TrieNode> GetTraces() const override;
- const nsTArray<AllocEvent>& GetEvents() const override;
-
- void reset() override;
- void sampleTenured(void* addr, uint32_t size) override;
- void sampleNursery(void* addr, uint32_t size) override;
- void markTenuredStart() override;
- void markTenured(void* addr) override;
- void sweepTenured() override;
- void sweepNursery() override;
- void moveNurseryToTenured(void* addrOld, void* addrNew) override;
-
-private:
- void SampleInternal(void* addr, uint32_t size, AllocMap& table);
-
- PRLock* mLock;
- bool mMarking;
-
- AllocMap mNurseryEntries;
- AllocMap mTenuredEntriesFG;
- AllocMap mTenuredEntriesBG;
-
- nsTArray<AllocEvent> mAllocEvents;
- CompactTraceTable mTraceTable;
-};
-
-} // namespace mozilla
-
-#endif // memory_profiler_GCHeapProfilerImpl_h
diff --git a/tools/memory-profiler/MemoryProfiler.cpp b/tools/memory-profiler/MemoryProfiler.cpp
deleted file mode 100644
index c2b8cbd1d..000000000
--- a/tools/memory-profiler/MemoryProfiler.cpp
+++ /dev/null
@@ -1,324 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=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 "MemoryProfiler.h"
-
-#include <cmath>
-#include <cstdlib>
-
-#include "mozilla/ClearOnShutdown.h"
-#include "mozilla/Move.h"
-#include "mozilla/TimeStamp.h"
-#include "mozilla/UniquePtr.h"
-
-#include "GCHeapProfilerImpl.h"
-#include "GeckoProfiler.h"
-#include "NativeProfilerImpl.h"
-#include "UncensoredAllocator.h"
-#include "js/TypeDecls.h"
-#include "jsfriendapi.h"
-#include "nsIDOMClassInfo.h"
-#include "nsIGlobalObject.h"
-#include "prtime.h"
-#include "xpcprivate.h"
-
-namespace mozilla {
-
-#define MEMORY_PROFILER_SAMPLE_SIZE 65536
-#define BACKTRACE_BUFFER_SIZE 16384
-
-ProfilerImpl::ProfilerImpl()
- : mSampleSize(MEMORY_PROFILER_SAMPLE_SIZE)
-{
- mLog1minusP = std::log(1.0 - 1.0 / mSampleSize);
- mRemainingBytes = std::floor(std::log(1.0 - DRandom()) / mLog1minusP);
-}
-
-nsTArray<nsCString>
-ProfilerImpl::GetStacktrace()
-{
- nsTArray<nsCString> trace;
- auto output = MakeUnique<char[]>(BACKTRACE_BUFFER_SIZE);
-
- profiler_get_backtrace_noalloc(output.get(), BACKTRACE_BUFFER_SIZE);
- for (const char* p = output.get(); *p; p += strlen(p) + 1) {
- trace.AppendElement()->Assign(p);
- }
-
- return trace;
-}
-
-// Generate a random number in [0, 1).
-double
-ProfilerImpl::DRandom()
-{
- return double(((uint64_t(std::rand()) & ((1 << 26) - 1)) << 27) +
- (uint64_t(std::rand()) & ((1 << 27) - 1)))
- / (uint64_t(1) << 53);
-}
-
-size_t
-ProfilerImpl::AddBytesSampled(uint32_t aBytes)
-{
- size_t nSamples = 0;
- while (mRemainingBytes <= aBytes) {
- mRemainingBytes += std::floor(std::log(1.0 - DRandom()) / mLog1minusP);
- nSamples++;
- }
- mRemainingBytes -= aBytes;
- return nSamples;
-}
-
-NS_IMPL_ISUPPORTS(MemoryProfiler, nsIMemoryProfiler)
-
-PRLock* MemoryProfiler::sLock;
-uint32_t MemoryProfiler::sProfileContextCount;
-StaticAutoPtr<NativeProfilerImpl> MemoryProfiler::sNativeProfiler;
-StaticAutoPtr<JSContextProfilerMap> MemoryProfiler::sJSContextProfilerMap;
-TimeStamp MemoryProfiler::sStartTime;
-
-void
-MemoryProfiler::InitOnce()
-{
- MOZ_ASSERT(NS_IsMainThread());
-
- static bool initialized = false;
-
- if (!initialized) {
- MallocHook::Initialize();
- sLock = PR_NewLock();
- sProfileContextCount = 0;
- sJSContextProfilerMap = new JSContextProfilerMap();
- ClearOnShutdown(&sJSContextProfilerMap);
- ClearOnShutdown(&sNativeProfiler);
- std::srand(PR_Now());
- bool ignored;
- sStartTime = TimeStamp::ProcessCreation(ignored);
- initialized = true;
- }
-}
-
-NS_IMETHODIMP
-MemoryProfiler::StartProfiler()
-{
- InitOnce();
- AutoUseUncensoredAllocator ua;
- AutoMPLock lock(sLock);
- JSContext* context = XPCJSContext::Get()->Context();
- ProfilerForJSContext profiler;
- if (!sJSContextProfilerMap->Get(context, &profiler) ||
- !profiler.mEnabled) {
- if (sProfileContextCount == 0) {
- js::EnableContextProfilingStack(context, true);
- if (!sNativeProfiler) {
- sNativeProfiler = new NativeProfilerImpl();
- }
- MemProfiler::SetNativeProfiler(sNativeProfiler);
- }
- GCHeapProfilerImpl* gp = new GCHeapProfilerImpl();
- profiler.mEnabled = true;
- profiler.mProfiler = gp;
- sJSContextProfilerMap->Put(context, profiler);
- MemProfiler::GetMemProfiler(context)->start(gp);
- if (sProfileContextCount == 0) {
- MallocHook::Enable(sNativeProfiler);
- }
- sProfileContextCount++;
- }
- return NS_OK;
-}
-
-NS_IMETHODIMP
-MemoryProfiler::StopProfiler()
-{
- InitOnce();
- AutoUseUncensoredAllocator ua;
- AutoMPLock lock(sLock);
- JSContext* context = XPCJSContext::Get()->Context();
- ProfilerForJSContext profiler;
- if (sJSContextProfilerMap->Get(context, &profiler) &&
- profiler.mEnabled) {
- MemProfiler::GetMemProfiler(context)->stop();
- if (--sProfileContextCount == 0) {
- MallocHook::Disable();
- MemProfiler::SetNativeProfiler(nullptr);
- js::EnableContextProfilingStack(context, false);
- }
- profiler.mEnabled = false;
- sJSContextProfilerMap->Put(context, profiler);
- }
- return NS_OK;
-}
-
-NS_IMETHODIMP
-MemoryProfiler::ResetProfiler()
-{
- InitOnce();
- AutoUseUncensoredAllocator ua;
- AutoMPLock lock(sLock);
- JSContext* context = XPCJSContext::Get()->Context();
- ProfilerForJSContext profiler;
- if (!sJSContextProfilerMap->Get(context, &profiler) ||
- !profiler.mEnabled) {
- delete profiler.mProfiler;
- profiler.mProfiler = nullptr;
- sJSContextProfilerMap->Put(context, profiler);
- }
- if (sProfileContextCount == 0) {
- sNativeProfiler = nullptr;
- }
- return NS_OK;
-}
-
-struct MergedTraces
-{
- nsTArray<nsCString> mNames;
- nsTArray<TrieNode> mTraces;
- nsTArray<AllocEvent> mEvents;
-};
-
-// Merge events and corresponding traces and names.
-static MergedTraces
-MergeResults(const nsTArray<nsCString>& names0,
- const nsTArray<TrieNode>& traces0,
- const nsTArray<AllocEvent>& events0,
- const nsTArray<nsCString>& names1,
- const nsTArray<TrieNode>& traces1,
- const nsTArray<AllocEvent>& events1)
-{
- NodeIndexMap<nsCStringHashKey, nsCString> names;
- NodeIndexMap<nsGenericHashKey<TrieNode>, TrieNode> traces;
- nsTArray<AllocEvent> events;
-
- nsTArray<size_t> names1Tonames0(names1.Length());
- nsTArray<size_t> traces1Totraces0(traces1.Length());
-
- // Merge names.
- for (auto& i: names0) {
- names.Insert(i);
- }
- for (auto& i: names1) {
- names1Tonames0.AppendElement(names.Insert(i));
- }
-
- // Merge traces. Note that traces1[i].parentIdx < i for all i > 0.
- for (auto& i: traces0) {
- traces.Insert(i);
- }
- traces1Totraces0.AppendElement(0);
- for (size_t i = 1; i < traces1.Length(); i++) {
- TrieNode node = traces1[i];
- node.parentIdx = traces1Totraces0[node.parentIdx];
- node.nameIdx = names1Tonames0[node.nameIdx];
- traces1Totraces0.AppendElement(traces.Insert(node));
- }
-
- // Merge the events according to timestamps.
- auto p0 = events0.begin();
- auto p1 = events1.begin();
-
- while (p0 != events0.end() && p1 != events1.end()) {
- if (p0->mTimestamp < p1->mTimestamp) {
- events.AppendElement(*p0++);
- } else {
- events.AppendElement(*p1++);
- events.LastElement().mTraceIdx =
- traces1Totraces0[events.LastElement().mTraceIdx];
- }
- }
-
- while (p0 != events0.end()) {
- events.AppendElement(*p0++);
- }
-
- while (p1 != events1.end()) {
- events.AppendElement(*p1++);
- events.LastElement().mTraceIdx =
- traces1Totraces0[events.LastElement().mTraceIdx];
- }
-
- return MergedTraces{names.Serialize(), traces.Serialize(), Move(events)};
-}
-
-NS_IMETHODIMP
-MemoryProfiler::GetResults(JSContext* cx, JS::MutableHandle<JS::Value> aResult)
-{
- InitOnce();
- AutoUseUncensoredAllocator ua;
- AutoMPLock lock(sLock);
- JSContext* context = XPCJSContext::Get()->Context();
- // Getting results when the profiler is running is not allowed.
- if (sProfileContextCount > 0) {
- return NS_OK;
- }
- // Return immediately when native profiler does not exist.
- if (!sNativeProfiler) {
- return NS_OK;
- }
- // Return immediately when there's no result in current context.
- ProfilerForJSContext profiler;
- if (!sJSContextProfilerMap->Get(context, &profiler) ||
- !profiler.mProfiler) {
- return NS_OK;
- }
- GCHeapProfilerImpl* gp = profiler.mProfiler;
-
- auto results = MergeResults(gp->GetNames(), gp->GetTraces(), gp->GetEvents(),
- sNativeProfiler->GetNames(),
- sNativeProfiler->GetTraces(),
- sNativeProfiler->GetEvents());
- const nsTArray<nsCString>& names = results.mNames;
- const nsTArray<TrieNode>& traces = results.mTraces;
- const nsTArray<AllocEvent>& events = results.mEvents;
-
- JS::RootedObject jsnames(cx, JS_NewArrayObject(cx, names.Length()));
- JS::RootedObject jstraces(cx, JS_NewArrayObject(cx, traces.Length()));
- JS::RootedObject jsevents(cx, JS_NewArrayObject(cx, events.Length()));
-
- for (size_t i = 0; i < names.Length(); i++) {
- JS::RootedString name(cx, JS_NewStringCopyZ(cx, names[i].get()));
- JS_SetElement(cx, jsnames, i, name);
- }
-
- for (size_t i = 0; i < traces.Length(); i++) {
- JS::RootedObject tn(cx, JS_NewPlainObject(cx));
- JS::RootedValue nameIdx(cx, JS_NumberValue(traces[i].nameIdx));
- JS::RootedValue parentIdx(cx, JS_NumberValue(traces[i].parentIdx));
- JS_SetProperty(cx, tn, "nameIdx", nameIdx);
- JS_SetProperty(cx, tn, "parentIdx", parentIdx);
- JS_SetElement(cx, jstraces, i, tn);
- }
-
- int i = 0;
- for (auto ent: events) {
- if (ent.mSize == 0) {
- continue;
- }
- MOZ_ASSERT(!sStartTime.IsNull());
- double time = (ent.mTimestamp - sStartTime).ToMilliseconds();
- JS::RootedObject tn(cx, JS_NewPlainObject(cx));
- JS::RootedValue size(cx, JS_NumberValue(ent.mSize));
- JS::RootedValue traceIdx(cx, JS_NumberValue(ent.mTraceIdx));
- JS::RootedValue timestamp(cx, JS_NumberValue(time));
- JS_SetProperty(cx, tn, "size", size);
- JS_SetProperty(cx, tn, "traceIdx", traceIdx);
- JS_SetProperty(cx, tn, "timestamp", timestamp);
- JS_SetElement(cx, jsevents, i++, tn);
- }
- JS_SetArrayLength(cx, jsevents, i);
-
- JS::RootedObject result(cx, JS_NewPlainObject(cx));
- JS::RootedValue objnames(cx, ObjectOrNullValue(jsnames));
- JS_SetProperty(cx, result, "names", objnames);
- JS::RootedValue objtraces(cx, ObjectOrNullValue(jstraces));
- JS_SetProperty(cx, result, "traces", objtraces);
- JS::RootedValue objevents(cx, ObjectOrNullValue(jsevents));
- JS_SetProperty(cx, result, "events", objevents);
- aResult.setObject(*result);
- return NS_OK;
-}
-
-} // namespace mozilla
diff --git a/tools/memory-profiler/MemoryProfiler.h b/tools/memory-profiler/MemoryProfiler.h
deleted file mode 100644
index 85a378fb2..000000000
--- a/tools/memory-profiler/MemoryProfiler.h
+++ /dev/null
@@ -1,159 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=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/. */
-
-#ifndef tools_profiler_MemoryProfiler_h
-#define tools_profiler_MemoryProfiler_h
-
-#include "nsIMemoryProfiler.h"
-
-#include "mozilla/StaticPtr.h"
-#include "mozilla/TimeStamp.h"
-
-#include "CompactTraceTable.h"
-#include "nsTArray.h"
-#include "prlock.h"
-
-#define MEMORY_PROFILER_CID \
- { 0xf976eaa2, 0xcc1f, 0x47ee, \
- { 0x81, 0x29, 0xb8, 0x26, 0x2a, 0x3d, 0xb6, 0xb2 } }
-
-#define MEMORY_PROFILER_CONTRACT_ID "@mozilla.org/tools/memory-profiler;1"
-
-struct PRLock;
-
-namespace mozilla {
-
-class NativeProfilerImpl;
-class GCHeapProfilerImpl;
-
-struct ProfilerForJSContext
-{
- ProfilerForJSContext()
- : mProfiler(nullptr)
- , mEnabled(false)
- {}
- GCHeapProfilerImpl* mProfiler;
- bool mEnabled;
-};
-using JSContextProfilerMap =
- nsDataHashtable<nsClearingPtrHashKey<JSContext>, ProfilerForJSContext>;
-
-class MemoryProfiler final : public nsIMemoryProfiler
-{
-public:
- NS_DECL_ISUPPORTS
- NS_DECL_NSIMEMORYPROFILER
-
-private:
- static void InitOnce();
- ~MemoryProfiler() {}
-
- // The accesses to other static member are guarded by sLock and
- // sProfileContextCount.
- static PRLock* sLock;
- static uint32_t sProfileContextCount;
-
- static StaticAutoPtr<NativeProfilerImpl> sNativeProfiler;
- static StaticAutoPtr<JSContextProfilerMap> sJSContextProfilerMap;
- static TimeStamp sStartTime;
-};
-
-// Allocation events to be reported.
-struct AllocEvent {
- TimeStamp mTimestamp;
- // index to a stacktrace singleton.
- uint32_t mTraceIdx;
- // Allocation size
- int32_t mSize;
-
- AllocEvent(uint32_t aTraceIdx, int32_t aSize, TimeStamp aTimestamp)
- : mTimestamp(aTimestamp)
- , mTraceIdx(aTraceIdx)
- , mSize(aSize)
- {}
-};
-
-// Index to allocation events but also a mark bit to be GC-able.
-struct AllocEntry {
- uint32_t mEventIdx : 31;
- bool mMarked : 1;
-
- // Default constructor for uninitialized stack value required by
- // getter methods.
- AllocEntry()
- : mEventIdx(0)
- , mMarked(false)
- {}
- explicit AllocEntry(int aEventIdx)
- : mEventIdx(aEventIdx)
- , mMarked(false)
- {}
-};
-
-using AllocMap = nsDataHashtable<nsClearingVoidPtrHashKey, AllocEntry>;
-
-class ProfilerImpl
-{
-public:
- static nsTArray<nsCString> GetStacktrace();
- static double DRandom();
-
- ProfilerImpl();
- virtual nsTArray<nsCString> GetNames() const = 0;
- virtual nsTArray<TrieNode> GetTraces() const = 0;
- virtual const nsTArray<AllocEvent>& GetEvents() const = 0;
-
-protected:
- /**
- * The sampler generates a random variable which conforms to a geometric
- * distribution of probability p = 1 / mSampleSize to calculate the
- * next-to-be-sampled byte directly; It avoids rolling a dice on each byte.
- *
- * Let Bn denote a Bernoulli process with first success on n-th trial, the
- * cumulative distribution function of Bn is Cn = 1 - (1 - p) ^ n.
- * Let U denote a uniformly distributed random variable in [0, 1).
- * A geometric random variable can be generated by Cn's reverse function:
- * G = floor(log(1 - U) / log(1 - p)).
- *
- * @param aSize the number of bytes seen
- * @return the number of events sampled
- */
- size_t AddBytesSampled(uint32_t aBytes);
-
- uint32_t mSampleSize;
-
-private:
- uint32_t mRemainingBytes;
- double mLog1minusP;
-};
-
-/*
- * This class is used to make sure the profile data is only accessed
- * on one thread at a time. Don't use mozilla::Mutex because we don't
- * want to allocate memory.
- */
-class AutoMPLock
-{
-public:
- explicit AutoMPLock(PRLock* aLock)
- {
- MOZ_ASSERT(aLock);
- mLock = aLock;
- PR_Lock(mLock);
- }
-
- ~AutoMPLock()
- {
- PR_Unlock(mLock);
- }
-
-private:
- PRLock* mLock;
-};
-
-} // namespace mozilla
-
-#endif
diff --git a/tools/memory-profiler/NativeProfilerImpl.cpp b/tools/memory-profiler/NativeProfilerImpl.cpp
deleted file mode 100644
index 48c684c72..000000000
--- a/tools/memory-profiler/NativeProfilerImpl.cpp
+++ /dev/null
@@ -1,82 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=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 "NativeProfilerImpl.h"
-
-#include "UncensoredAllocator.h"
-
-namespace mozilla {
-
-NativeProfilerImpl::NativeProfilerImpl()
-{
- mLock = PR_NewLock();
-}
-
-NativeProfilerImpl::~NativeProfilerImpl()
-{
- if (mLock) {
- PR_DestroyLock(mLock);
- }
-}
-
-nsTArray<nsCString>
-NativeProfilerImpl::GetNames() const
-{
- return mTraceTable.GetNames();
-}
-
-nsTArray<TrieNode>
-NativeProfilerImpl::GetTraces() const
-{
- return mTraceTable.GetTraces();
-}
-
-const nsTArray<AllocEvent>&
-NativeProfilerImpl::GetEvents() const
-{
- return mAllocEvents;
-}
-
-void
-NativeProfilerImpl::reset()
-{
- mTraceTable.Reset();
- mAllocEvents.Clear();
- mNativeEntries.Clear();
-}
-
-void
-NativeProfilerImpl::sampleNative(void* addr, uint32_t size)
-{
- AutoUseUncensoredAllocator ua;
- AutoMPLock lock(mLock);
- size_t nSamples = AddBytesSampled(size);
- if (nSamples > 0) {
- nsTArray<nsCString> trace = GetStacktrace();
- AllocEvent ai(mTraceTable.Insert(trace), nSamples * mSampleSize, TimeStamp::Now());
- mNativeEntries.Put(addr, AllocEntry(mAllocEvents.Length()));
- mAllocEvents.AppendElement(ai);
- }
-}
-
-void
-NativeProfilerImpl::removeNative(void* addr)
-{
- AutoUseUncensoredAllocator ua;
- AutoMPLock lock(mLock);
-
- AllocEntry entry;
- if (!mNativeEntries.Get(addr, &entry)) {
- return;
- }
-
- AllocEvent& oldEvent = mAllocEvents[entry.mEventIdx];
- AllocEvent newEvent(oldEvent.mTraceIdx, -oldEvent.mSize, TimeStamp::Now());
- mAllocEvents.AppendElement(newEvent);
- mNativeEntries.Remove(addr);
-}
-
-} // namespace mozilla
diff --git a/tools/memory-profiler/NativeProfilerImpl.h b/tools/memory-profiler/NativeProfilerImpl.h
deleted file mode 100644
index 95cc2ec13..000000000
--- a/tools/memory-profiler/NativeProfilerImpl.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=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/. */
-
-#ifndef memory_profiler_NativeProfilerImpl_h
-#define memory_profiler_NativeProfilerImpl_h
-
-#include "CompactTraceTable.h"
-#include "MemoryProfiler.h"
-
-#include "jsfriendapi.h"
-
-struct PRLock;
-
-namespace mozilla {
-
-class NativeProfilerImpl final : public NativeProfiler
- , public ProfilerImpl
-{
-public:
- NativeProfilerImpl();
- ~NativeProfilerImpl() override;
-
- nsTArray<nsCString> GetNames() const override;
- nsTArray<TrieNode> GetTraces() const override;
- const nsTArray<AllocEvent>& GetEvents() const override;
-
- void reset() override;
- void sampleNative(void* addr, uint32_t size) override;
- void removeNative(void* addr) override;
-
-private:
- PRLock* mLock;
- AllocMap mNativeEntries;
- nsTArray<AllocEvent> mAllocEvents;
- CompactTraceTable mTraceTable;
-};
-
-} // namespace mozilla
-
-#endif // memory_profiler_NativeProfilerImpl_h
diff --git a/tools/memory-profiler/UncensoredAllocator.cpp b/tools/memory-profiler/UncensoredAllocator.cpp
deleted file mode 100644
index 92caeb633..000000000
--- a/tools/memory-profiler/UncensoredAllocator.cpp
+++ /dev/null
@@ -1,121 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=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 "UncensoredAllocator.h"
-
-#include "mozilla/Assertions.h"
-#include "mozilla/Unused.h"
-
-#include "MainThreadUtils.h"
-#include "jsfriendapi.h"
-#include "nsDebug.h"
-#include "prlock.h"
-#ifdef MOZ_REPLACE_MALLOC
-#include "replace_malloc_bridge.h"
-#endif
-
-namespace mozilla {
-
-#ifdef MOZ_REPLACE_MALLOC
-MOZ_THREAD_LOCAL(bool) MallocHook::mEnabledTLS;
-NativeProfiler* MallocHook::mNativeProfiler;
-malloc_hook_table_t MallocHook::mMallocHook;
-#endif
-
-AutoUseUncensoredAllocator::AutoUseUncensoredAllocator()
-{
-#ifdef MOZ_REPLACE_MALLOC
- MallocHook::mEnabledTLS.set(false);
-#endif
-}
-
-AutoUseUncensoredAllocator::~AutoUseUncensoredAllocator()
-{
-#ifdef MOZ_REPLACE_MALLOC
- MallocHook::mEnabledTLS.set(true);
-#endif
-}
-
-bool
-MallocHook::Enabled()
-{
-#ifdef MOZ_REPLACE_MALLOC
- return mEnabledTLS.get() && mNativeProfiler;
-#else
- return false;
-#endif
-}
-
-void*
-MallocHook::SampleNative(void* aAddr, size_t aSize)
-{
-#ifdef MOZ_REPLACE_MALLOC
- if (MallocHook::Enabled()) {
- mNativeProfiler->sampleNative(aAddr, aSize);
- }
-#endif
- return aAddr;
-}
-
-void
-MallocHook::RemoveNative(void* aAddr)
-{
-#ifdef MOZ_REPLACE_MALLOC
- if (MallocHook::Enabled()) {
- mNativeProfiler->removeNative(aAddr);
- }
-#endif
-}
-
-void
-MallocHook::Initialize()
-{
-#ifdef MOZ_REPLACE_MALLOC
- MOZ_ASSERT(NS_IsMainThread());
- mMallocHook.free_hook = RemoveNative;
- mMallocHook.malloc_hook = SampleNative;
- ReplaceMallocBridge* bridge = ReplaceMallocBridge::Get(3);
- if (bridge) {
- mozilla::Unused << bridge->RegisterHook("memory-profiler", nullptr, nullptr);
- }
-
- bool success = mEnabledTLS.init();
- if (NS_WARN_IF(!success)) {
- return;
- }
-#endif
-}
-
-void
-MallocHook::Enable(NativeProfiler* aNativeProfiler)
-{
-#ifdef MOZ_REPLACE_MALLOC
- MOZ_ASSERT(NS_IsMainThread());
- ReplaceMallocBridge* bridge = ReplaceMallocBridge::Get(3);
- if (bridge) {
- const malloc_table_t* alloc_funcs =
- bridge->RegisterHook("memory-profiler", nullptr, &mMallocHook);
- if (alloc_funcs) {
- mNativeProfiler = aNativeProfiler;
- }
- }
-#endif
-}
-
-void
-MallocHook::Disable()
-{
-#ifdef MOZ_REPLACE_MALLOC
- MOZ_ASSERT(NS_IsMainThread());
- ReplaceMallocBridge* bridge = ReplaceMallocBridge::Get(3);
- if (bridge) {
- bridge->RegisterHook("memory-profiler", nullptr, nullptr);
- mNativeProfiler = nullptr;
- }
-#endif
-}
-
-} // namespace mozilla
diff --git a/tools/memory-profiler/UncensoredAllocator.h b/tools/memory-profiler/UncensoredAllocator.h
deleted file mode 100644
index b9074c738..000000000
--- a/tools/memory-profiler/UncensoredAllocator.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=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/. */
-
-#ifndef memory_profiler_UncensoredAllocator_h
-#define memory_profiler_UncensoredAllocator_h
-
-#include "mozilla/Attributes.h"
-#include "mozilla/ThreadLocal.h"
-
-#ifdef MOZ_REPLACE_MALLOC
-#include "replace_malloc_bridge.h"
-#endif
-
-class NativeProfiler;
-
-namespace mozilla {
-
-class MallocHook final
-{
-public:
- static void Initialize();
- static void Enable(NativeProfiler* aNativeProfiler);
- static void Disable();
- static bool Enabled();
-private:
- static void* SampleNative(void* aAddr, size_t aSize);
- static void RemoveNative(void* aAddr);
-#ifdef MOZ_REPLACE_MALLOC
- static MOZ_THREAD_LOCAL(bool) mEnabledTLS;
- static NativeProfiler* mNativeProfiler;
- static malloc_hook_table_t mMallocHook;
-#endif
- friend class AutoUseUncensoredAllocator;
-};
-
-class MOZ_RAII AutoUseUncensoredAllocator final
-{
-public:
- AutoUseUncensoredAllocator();
- ~AutoUseUncensoredAllocator();
-};
-
-} // namespace mozilla
-
-#endif // memory_profiler_UncensoredAllocator_h
diff --git a/tools/memory-profiler/moz.build b/tools/memory-profiler/moz.build
index be2fe7432..cd37ffdb2 100644
--- a/tools/memory-profiler/moz.build
+++ b/tools/memory-profiler/moz.build
@@ -4,26 +4,5 @@
# 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/.
-if CONFIG['MOZ_ENABLE_PROFILER_SPS']:
- XPIDL_MODULE = 'memory_profiler'
- XPIDL_SOURCES += [
- 'nsIMemoryProfiler.idl',
- ]
-
- UNIFIED_SOURCES += [
- 'GCHeapProfilerImpl.cpp',
- 'MemoryProfiler.cpp',
- 'NativeProfilerImpl.cpp',
- 'nsMemoryProfilerFactory.cpp',
- 'UncensoredAllocator.cpp',
- ]
-
- LOCAL_INCLUDES += [
- '/js/xpconnect/src',
- '/xpcom/base',
- ]
-
- FINAL_LIBRARY = 'xul'
-
if CONFIG['GNU_CXX']:
CXXFLAGS += ['-Wno-error=shadow']
diff --git a/tools/memory-profiler/nsIMemoryProfiler.idl b/tools/memory-profiler/nsIMemoryProfiler.idl
deleted file mode 100644
index 4ca386f9d..000000000
--- a/tools/memory-profiler/nsIMemoryProfiler.idl
+++ /dev/null
@@ -1,72 +0,0 @@
-/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* 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"
-
-/**
- * The memory profiler samples allocation events. An allocation event
- * includes a type (what and at where is going to be allocated), a
- * size, a timestamp and the corresponding stack trace. Free events
- * are also tracked. For managed languages, namely languages relying
- * on garbage collection, a free event is generated when an object is
- * reclaimed by the garbage collector. These sampled events can be
- * used to approximate the full history of allocations afterwards.
- * That means we can get various memory profiles of a program in
- * different perspectives by post-processing the history in different
- * ways. The profiler is designed at the very beginning to support not
- * only JavaScript but also native codes. Naturally, not only
- * JavaScript objects but also native allocations are tracked.
- *
- * The result returned is the sampled allocation event traces in a
- * compact format. The events is sorted according to the timestamp
- * when the event happened. Each event has a trace index pointing to
- * the traces table. Each trace entry has a name index pointing to the
- * names table and a parent index pointing to the parent trace in the
- * traces table. By following the trace index one could rebuild the
- * complete backtrace of an allocation event.
- *
- * [ Events ]
- * +-------+-------+ +-------+
- * | Size | Size | | Size |
- * |-------|-------| |-------|
- * | Time | Time |......| Time |
- * |-------|-------| |-------|
- * +-- Trace | Trace | | Trace |
- * | +-------+-------+ +-------+
- * |
- * | [ Traces ]
- * +->--------+--------+ +--------+ +--------+
- * -| Name | Name | | Name | | Name |
- * / |--------|--------|...|--------|...|--------|
- * | | Parent | Parent | | Parent | | Parent |
- * | +---|----+----^--++ +--^--|--+ +---^----+
- * | | | | | | |
- * | +---------+ +-------+ +----------+
- * | [ Names ]
- * | +-----------------+-----------------+
- * +-> Function name | Function name |
- * | & line numbers | & line numbers |......
- * +-----------------+-----------------+
- *
- */
-[scriptable, uuid(1e10e7a9-bc05-4878-a687-36c9ea4428b1)]
-interface nsIMemoryProfiler : nsISupports
-{
- void startProfiler();
- void stopProfiler();
- void resetProfiler();
-
- /**
- * Get results in an object which contains three tables:
- * {
- * names, // an array of function names and positions
- * traces, // an array of {nameIdx, parentIdx}
- * events, // an array of {size, timestamp, traceIdx}
- * }
- * Should only be called after stopProfiler.
- */
- [implicit_jscontext]
- jsval getResults();
-};
diff --git a/tools/memory-profiler/nsMemoryProfilerFactory.cpp b/tools/memory-profiler/nsMemoryProfilerFactory.cpp
deleted file mode 100644
index b962a6604..000000000
--- a/tools/memory-profiler/nsMemoryProfilerFactory.cpp
+++ /dev/null
@@ -1,32 +0,0 @@
-/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* 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/ModuleUtils.h"
-#include "nsCOMPtr.h"
-#include "MemoryProfiler.h"
-
-using mozilla::MemoryProfiler;
-
-NS_GENERIC_FACTORY_CONSTRUCTOR(MemoryProfiler)
-
-NS_DEFINE_NAMED_CID(MEMORY_PROFILER_CID);
-
-static const mozilla::Module::CIDEntry kMemoryProfilerCIDs[] = {
- { &kMEMORY_PROFILER_CID, false, nullptr, MemoryProfilerConstructor },
- { nullptr }
-};
-
-static const mozilla::Module::ContractIDEntry kMemoryProfilerContracts[] = {
- { MEMORY_PROFILER_CONTRACT_ID, &kMEMORY_PROFILER_CID },
- { nullptr }
-};
-
-static const mozilla::Module kMemoryProfilerModule = {
- mozilla::Module::kVersion,
- kMemoryProfilerCIDs,
- kMemoryProfilerContracts
-};
-
-NSMODULE_DEFN(nsMemoryProfilerModule) = &kMemoryProfilerModule;