mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 822148 (part 2) - DMD: Treat twice-reported blocks more like other blocks. r=jlebar.
--HG-- extra : rebase_source : 345123de945a3c26ec6ca88a599b45efddc4209e
This commit is contained in:
parent
0d26120cb5
commit
d1985a03e0
@ -772,8 +772,7 @@ StackTrace::Print(const Writer& aWriter, LocationService* aLocService) const
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < mLength; i++) {
|
||||
void* pc = mPcs[i];
|
||||
aLocService->WriteLocation(aWriter, pc);
|
||||
aLocService->WriteLocation(aWriter, Pc(i));
|
||||
}
|
||||
}
|
||||
|
||||
@ -815,50 +814,88 @@ StackTrace::Get(Thread* aT)
|
||||
// Heap blocks
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
// This class combines a 2-byte-aligned pointer (i.e. one whose bottom bit
|
||||
// is zero) with a 1-bit tag.
|
||||
//
|
||||
// |T| is the pointer type, e.g. |int*|, not the pointed-to type. This makes
|
||||
// is easier to have const pointers, e.g. |TaggedPtr<const int*>|.
|
||||
template <typename T>
|
||||
class TaggedPtr
|
||||
{
|
||||
union
|
||||
{
|
||||
T mPtr;
|
||||
uintptr_t mUint;
|
||||
};
|
||||
|
||||
static const uintptr_t kTagMask = uintptr_t(0x1);
|
||||
static const uintptr_t kPtrMask = ~kTagMask;
|
||||
|
||||
static bool IsTwoByteAligned(T aPtr)
|
||||
{
|
||||
return (uintptr_t(aPtr) & kTagMask) == 0;
|
||||
}
|
||||
|
||||
public:
|
||||
TaggedPtr()
|
||||
: mPtr(nullptr)
|
||||
{}
|
||||
|
||||
TaggedPtr(T aPtr, bool aBool)
|
||||
: mPtr(aPtr)
|
||||
{
|
||||
MOZ_ASSERT(IsTwoByteAligned(aPtr));
|
||||
uintptr_t tag = uintptr_t(aBool);
|
||||
MOZ_ASSERT(tag <= kTagMask);
|
||||
mUint |= (tag & kTagMask);
|
||||
}
|
||||
|
||||
void Set(T aPtr, bool aBool)
|
||||
{
|
||||
MOZ_ASSERT(IsTwoByteAligned(aPtr));
|
||||
mPtr = aPtr;
|
||||
uintptr_t tag = uintptr_t(aBool);
|
||||
MOZ_ASSERT(tag <= kTagMask);
|
||||
mUint |= (tag & kTagMask);
|
||||
}
|
||||
|
||||
T Ptr() const { return reinterpret_cast<T>(mUint & kPtrMask); }
|
||||
|
||||
bool Tag() const { return bool(mUint & kTagMask); }
|
||||
};
|
||||
|
||||
// A live heap block.
|
||||
class LiveBlock
|
||||
{
|
||||
const void* mPtr;
|
||||
const size_t mReqSize; // size requested
|
||||
|
||||
// This assumes that we'll never request an allocation of 2 GiB or more on
|
||||
// 32-bit platforms.
|
||||
static const size_t kReqBits = sizeof(size_t) * 8 - 1; // 31 or 63
|
||||
const size_t mReqSize:kReqBits; // size requested
|
||||
const size_t mSampled:1; // was this block sampled? (if so, slop == 0)
|
||||
// Ptr: |mAllocStackTrace| - stack trace where this block was allocated.
|
||||
// Tag bit 0: |mSampled| - was this block sampled? (if so, slop == 0).
|
||||
TaggedPtr<const StackTrace* const>
|
||||
mAllocStackTrace_mSampled;
|
||||
|
||||
public:
|
||||
const StackTrace* const mAllocStackTrace; // never null
|
||||
|
||||
// Live blocks can be reported in two ways.
|
||||
// - The most common is via a memory reporter traversal -- the block is
|
||||
// reported when the reporter runs, causing DMD to mark it as reported,
|
||||
// and DMD must clear the marking once it has finished its analysis.
|
||||
// - Less common are ones that are reported immediately on allocation. DMD
|
||||
// must *not* clear the markings of these blocks once it has finished its
|
||||
// analysis. The |mReportedOnAlloc| field is set for such blocks.
|
||||
// This array has two elements because we record at most two reports of a
|
||||
// block.
|
||||
// - Ptr: |mReportStackTrace| - stack trace where this block was reported.
|
||||
// nullptr if not reported.
|
||||
// - Tag bit 0: |mReportedOnAlloc| - was the block reported immediately on
|
||||
// allocation? If so, DMD must not clear the report at the end of Dump().
|
||||
// Only relevant if |mReportStackTrace| is non-nullptr.
|
||||
//
|
||||
// |mPtr| is used as the key in LiveBlockTable, so it's ok for these fields
|
||||
// |mPtr| is used as the key in LiveBlockTable, so it's ok for this member
|
||||
// to be |mutable|.
|
||||
private:
|
||||
mutable const StackTrace* mReportStackTrace; // nullptr if unreported
|
||||
mutable bool mReportedOnAlloc; // true if block was reported
|
||||
// immediately after alloc
|
||||
mutable TaggedPtr<const StackTrace*> mReportStackTrace_mReportedOnAlloc[2];
|
||||
|
||||
public:
|
||||
LiveBlock(const void* aPtr, size_t aReqSize,
|
||||
const StackTrace* aAllocStackTrace, bool aSampled)
|
||||
: mPtr(aPtr),
|
||||
mReqSize(aReqSize),
|
||||
mSampled(aSampled),
|
||||
mAllocStackTrace(aAllocStackTrace),
|
||||
mReportStackTrace(nullptr),
|
||||
mReportedOnAlloc(false)
|
||||
{
|
||||
if (mReqSize != aReqSize)
|
||||
{
|
||||
MOZ_CRASH(); // overflowed mReqSize
|
||||
}
|
||||
MOZ_ASSERT(mAllocStackTrace);
|
||||
mAllocStackTrace_mSampled(aAllocStackTrace, aSampled),
|
||||
mReportStackTrace_mReportedOnAlloc() // all fields get zeroed
|
||||
{
|
||||
MOZ_ASSERT(aAllocStackTrace);
|
||||
}
|
||||
|
||||
size_t ReqSize() const { return mReqSize; }
|
||||
@ -866,24 +903,78 @@ public:
|
||||
// Sampled blocks always have zero slop.
|
||||
size_t SlopSize() const
|
||||
{
|
||||
return mSampled ? 0 : MallocSizeOf(mPtr) - mReqSize;
|
||||
return IsSampled() ? 0 : MallocSizeOf(mPtr) - mReqSize;
|
||||
}
|
||||
|
||||
size_t UsableSize() const
|
||||
{
|
||||
return mSampled ? mReqSize : MallocSizeOf(mPtr);
|
||||
return IsSampled() ? mReqSize : MallocSizeOf(mPtr);
|
||||
}
|
||||
|
||||
bool IsSampled() const { return mSampled; }
|
||||
bool IsSampled() const
|
||||
{
|
||||
return mAllocStackTrace_mSampled.Tag();
|
||||
}
|
||||
|
||||
bool IsReported() const { return !!mReportStackTrace; }
|
||||
const StackTrace* AllocStackTrace() const
|
||||
{
|
||||
return mAllocStackTrace_mSampled.Ptr();
|
||||
}
|
||||
|
||||
const StackTrace* ReportStackTrace() const { return mReportStackTrace; }
|
||||
const StackTrace* ReportStackTrace1() const {
|
||||
return mReportStackTrace_mReportedOnAlloc[0].Ptr();
|
||||
}
|
||||
|
||||
const StackTrace* ReportStackTrace2() const {
|
||||
return mReportStackTrace_mReportedOnAlloc[1].Ptr();
|
||||
}
|
||||
|
||||
bool ReportedOnAlloc1() const {
|
||||
return mReportStackTrace_mReportedOnAlloc[0].Tag();
|
||||
}
|
||||
|
||||
bool ReportedOnAlloc2() const {
|
||||
return mReportStackTrace_mReportedOnAlloc[1].Tag();
|
||||
}
|
||||
|
||||
uint32_t NumReports() const {
|
||||
if (ReportStackTrace2()) {
|
||||
MOZ_ASSERT(ReportStackTrace1());
|
||||
return 2;
|
||||
}
|
||||
if (ReportStackTrace1()) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// This is |const| thanks to the |mutable| fields above.
|
||||
void Report(Thread* aT, bool aReportedOnAlloc) const;
|
||||
void Report(Thread* aT, bool aReportedOnAlloc) const
|
||||
{
|
||||
// We don't bother recording reports after the 2nd one.
|
||||
uint32_t numReports = NumReports();
|
||||
if (numReports < 2) {
|
||||
mReportStackTrace_mReportedOnAlloc[numReports].Set(StackTrace::Get(aT),
|
||||
aReportedOnAlloc);
|
||||
}
|
||||
}
|
||||
|
||||
void UnreportIfNotReportedOnAlloc() const;
|
||||
void UnreportIfNotReportedOnAlloc() const
|
||||
{
|
||||
if (!ReportedOnAlloc1() && !ReportedOnAlloc2()) {
|
||||
mReportStackTrace_mReportedOnAlloc[0].Set(nullptr, 0);
|
||||
mReportStackTrace_mReportedOnAlloc[1].Set(nullptr, 0);
|
||||
|
||||
} else if (!ReportedOnAlloc1() && ReportedOnAlloc2()) {
|
||||
// Shift the 2nd report down to the 1st one.
|
||||
mReportStackTrace_mReportedOnAlloc[0] =
|
||||
mReportStackTrace_mReportedOnAlloc[1];
|
||||
mReportStackTrace_mReportedOnAlloc[1].Set(nullptr, 0);
|
||||
|
||||
} else if (ReportedOnAlloc1() && !ReportedOnAlloc2()) {
|
||||
mReportStackTrace_mReportedOnAlloc[1].Set(nullptr, 0);
|
||||
}
|
||||
}
|
||||
|
||||
// Hash policy.
|
||||
|
||||
@ -1102,81 +1193,38 @@ namespace mozilla {
|
||||
namespace dmd {
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Live and double-report block groups
|
||||
// Block groups
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
class LiveBlockKey
|
||||
class BlockGroupKey
|
||||
{
|
||||
public:
|
||||
const StackTrace* const mAllocStackTrace; // never null
|
||||
protected:
|
||||
const StackTrace* const mReportStackTrace; // nullptr if unreported
|
||||
const StackTrace* const mReportStackTrace1; // nullptr if unreported
|
||||
const StackTrace* const mReportStackTrace2; // nullptr if not 2x-reported
|
||||
|
||||
public:
|
||||
LiveBlockKey(const LiveBlock& aB)
|
||||
: mAllocStackTrace(aB.mAllocStackTrace),
|
||||
mReportStackTrace(aB.ReportStackTrace())
|
||||
BlockGroupKey(const LiveBlock& aB)
|
||||
: mAllocStackTrace(aB.AllocStackTrace()),
|
||||
mReportStackTrace1(aB.ReportStackTrace1()),
|
||||
mReportStackTrace2(aB.ReportStackTrace2())
|
||||
{
|
||||
MOZ_ASSERT(mAllocStackTrace);
|
||||
}
|
||||
|
||||
bool IsReported() const
|
||||
{
|
||||
return !!mReportStackTrace;
|
||||
}
|
||||
|
||||
// Hash policy.
|
||||
|
||||
typedef LiveBlockKey Lookup;
|
||||
typedef BlockGroupKey Lookup;
|
||||
|
||||
static uint32_t hash(const LiveBlockKey& aKey)
|
||||
{
|
||||
return mozilla::HashGeneric(aKey.mAllocStackTrace,
|
||||
aKey.mReportStackTrace);
|
||||
}
|
||||
|
||||
static bool match(const LiveBlockKey& aA, const LiveBlockKey& aB)
|
||||
{
|
||||
return aA.mAllocStackTrace == aB.mAllocStackTrace &&
|
||||
aA.mReportStackTrace == aB.mReportStackTrace;
|
||||
}
|
||||
};
|
||||
|
||||
class DoubleReportBlockKey
|
||||
{
|
||||
public:
|
||||
const StackTrace* const mAllocStackTrace; // never null
|
||||
|
||||
protected:
|
||||
// When double-reports occur we record (and later print) the stack trace
|
||||
// of *both* the reporting locations.
|
||||
const StackTrace* const mReportStackTrace1; // never null
|
||||
const StackTrace* const mReportStackTrace2; // never null
|
||||
|
||||
public:
|
||||
DoubleReportBlockKey(const StackTrace* aAllocStackTrace,
|
||||
const StackTrace* aReportStackTrace1,
|
||||
const StackTrace* aReportStackTrace2)
|
||||
: mAllocStackTrace(aAllocStackTrace),
|
||||
mReportStackTrace1(aReportStackTrace1),
|
||||
mReportStackTrace2(aReportStackTrace2)
|
||||
{
|
||||
MOZ_ASSERT(mAllocStackTrace && mReportStackTrace1 && mReportStackTrace2);
|
||||
}
|
||||
|
||||
// Hash policy.
|
||||
|
||||
typedef DoubleReportBlockKey Lookup;
|
||||
|
||||
static uint32_t hash(const DoubleReportBlockKey& aKey)
|
||||
static uint32_t hash(const BlockGroupKey& aKey)
|
||||
{
|
||||
return mozilla::HashGeneric(aKey.mAllocStackTrace,
|
||||
aKey.mReportStackTrace1,
|
||||
aKey.mReportStackTrace2);
|
||||
}
|
||||
|
||||
static bool match(const DoubleReportBlockKey& aA,
|
||||
const DoubleReportBlockKey& aB)
|
||||
static bool match(const BlockGroupKey& aA, const BlockGroupKey& aB)
|
||||
{
|
||||
return aA.mAllocStackTrace == aB.mAllocStackTrace &&
|
||||
aA.mReportStackTrace1 == aB.mReportStackTrace1 &&
|
||||
@ -1221,11 +1269,15 @@ public:
|
||||
|
||||
static int Cmp(const GroupSize& aA, const GroupSize& aB)
|
||||
{
|
||||
// Primary sort: put bigger usable sizes before smaller usable sizes.
|
||||
// Primary sort: put bigger usable sizes first.
|
||||
if (aA.Usable() > aB.Usable()) return -1;
|
||||
if (aA.Usable() < aB.Usable()) return 1;
|
||||
|
||||
// Secondary sort: put non-sampled groups before sampled groups.
|
||||
// Secondary sort: put bigger requested sizes first.
|
||||
if (aA.Req() > aB.Req()) return -1;
|
||||
if (aA.Req() < aB.Req()) return 1;
|
||||
|
||||
// Tertiary sort: put non-sampled groups before sampled groups.
|
||||
if (!aA.mSampled && aB.mSampled) return -1;
|
||||
if ( aA.mSampled && !aB.mSampled) return 1;
|
||||
|
||||
@ -1233,18 +1285,20 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class BlockGroup
|
||||
// A group of one or more heap blocks with a common BlockGroupKey.
|
||||
class BlockGroup : public BlockGroupKey
|
||||
{
|
||||
protected:
|
||||
// {Live,DoubleReport}BlockKey serve as the key in
|
||||
// {Live,DoubleReport}BlockGroupTable. Thes two fields constitute the value,
|
||||
// so it's ok for them to be |mutable|.
|
||||
friend class FrameGroup; // FrameGroups are created from BlockGroups
|
||||
|
||||
// The BlockGroupKey base class serves as the key in BlockGroupTables. These
|
||||
// two fields constitute the value, so it's ok for them to be |mutable|.
|
||||
mutable uint32_t mNumBlocks; // number of blocks with this LiveBlockKey
|
||||
mutable GroupSize mGroupSize; // combined size of those blocks
|
||||
|
||||
public:
|
||||
BlockGroup()
|
||||
: mNumBlocks(0),
|
||||
explicit BlockGroup(const BlockGroupKey& aKey)
|
||||
: BlockGroupKey(aKey),
|
||||
mNumBlocks(0),
|
||||
mGroupSize()
|
||||
{}
|
||||
|
||||
@ -1258,20 +1312,6 @@ public:
|
||||
}
|
||||
|
||||
static const char* const kName; // for PrintSortedGroups
|
||||
};
|
||||
|
||||
const char* const BlockGroup::kName = "block";
|
||||
|
||||
// A group of one or more live heap blocks with a common LiveBlockKey.
|
||||
class LiveBlockGroup : public LiveBlockKey, public BlockGroup
|
||||
{
|
||||
friend class FrameGroup; // FrameGroups are created from LiveBlockGroups
|
||||
|
||||
public:
|
||||
explicit LiveBlockGroup(const LiveBlockKey& aKey)
|
||||
: LiveBlockKey(aKey),
|
||||
BlockGroup()
|
||||
{}
|
||||
|
||||
void Print(const Writer& aWriter, LocationService* aLocService,
|
||||
uint32_t aM, uint32_t aN, const char* aStr, const char* astr,
|
||||
@ -1280,24 +1320,25 @@ public:
|
||||
|
||||
static int QsortCmp(const void* aA, const void* aB)
|
||||
{
|
||||
const LiveBlockGroup* const a =
|
||||
*static_cast<const LiveBlockGroup* const*>(aA);
|
||||
const LiveBlockGroup* const b =
|
||||
*static_cast<const LiveBlockGroup* const*>(aB);
|
||||
const BlockGroup* const a =
|
||||
*static_cast<const BlockGroup* const*>(aA);
|
||||
const BlockGroup* const b =
|
||||
*static_cast<const BlockGroup* const*>(aB);
|
||||
|
||||
return GroupSize::Cmp(a->mGroupSize, b->mGroupSize);
|
||||
}
|
||||
};
|
||||
|
||||
typedef js::HashSet<LiveBlockGroup, LiveBlockGroup, InfallibleAllocPolicy>
|
||||
LiveBlockGroupTable;
|
||||
const char* const BlockGroup::kName = "block";
|
||||
|
||||
typedef js::HashSet<BlockGroup, BlockGroup, InfallibleAllocPolicy>
|
||||
BlockGroupTable;
|
||||
|
||||
void
|
||||
LiveBlockGroup::Print(const Writer& aWriter, LocationService* aLocService,
|
||||
uint32_t aM, uint32_t aN,
|
||||
const char* aStr, const char* astr,
|
||||
size_t aCategoryUsableSize, size_t aCumulativeUsableSize,
|
||||
size_t aTotalUsableSize) const
|
||||
BlockGroup::Print(const Writer& aWriter, LocationService* aLocService,
|
||||
uint32_t aM, uint32_t aN, const char* aStr, const char* astr,
|
||||
size_t aCategoryUsableSize, size_t aCumulativeUsableSize,
|
||||
size_t aTotalUsableSize) const
|
||||
{
|
||||
bool showTilde = mGroupSize.IsSampled();
|
||||
|
||||
@ -1323,74 +1364,14 @@ LiveBlockGroup::Print(const Writer& aWriter, LocationService* aLocService,
|
||||
W(" Allocated at\n");
|
||||
mAllocStackTrace->Print(aWriter, aLocService);
|
||||
|
||||
if (IsReported()) {
|
||||
if (mReportStackTrace1) {
|
||||
W("\n Reported at\n");
|
||||
mReportStackTrace->Print(aWriter, aLocService);
|
||||
mReportStackTrace1->Print(aWriter, aLocService);
|
||||
}
|
||||
|
||||
W("\n");
|
||||
}
|
||||
|
||||
// A group of one or more double-reported heap blocks with a common
|
||||
// DoubleReportBlockKey.
|
||||
class DoubleReportBlockGroup : public DoubleReportBlockKey, public BlockGroup
|
||||
{
|
||||
public:
|
||||
explicit DoubleReportBlockGroup(const DoubleReportBlockKey& aKey)
|
||||
: DoubleReportBlockKey(aKey),
|
||||
BlockGroup()
|
||||
{}
|
||||
|
||||
void Print(const Writer& aWriter, LocationService* aLocService,
|
||||
uint32_t aM, uint32_t aN, const char* aStr, const char* astr,
|
||||
size_t aCategoryUsableSize, size_t aCumulativeUsableSize,
|
||||
size_t aTotalUsableSize) const;
|
||||
|
||||
static int QsortCmp(const void* aA, const void* aB)
|
||||
{
|
||||
const DoubleReportBlockGroup* const a =
|
||||
*static_cast<const DoubleReportBlockGroup* const*>(aA);
|
||||
const DoubleReportBlockGroup* const b =
|
||||
*static_cast<const DoubleReportBlockGroup* const*>(aB);
|
||||
|
||||
return GroupSize::Cmp(a->mGroupSize, b->mGroupSize);
|
||||
if (mReportStackTrace2) {
|
||||
W("\n Reported again at\n");
|
||||
mReportStackTrace2->Print(aWriter, aLocService);
|
||||
}
|
||||
};
|
||||
|
||||
typedef js::HashSet<DoubleReportBlockGroup, DoubleReportBlockGroup,
|
||||
InfallibleAllocPolicy> DoubleReportBlockGroupTable;
|
||||
DoubleReportBlockGroupTable* gDoubleReportBlockGroupTable = nullptr;
|
||||
|
||||
void
|
||||
DoubleReportBlockGroup::Print(const Writer& aWriter,
|
||||
LocationService* aLocService,
|
||||
uint32_t aM, uint32_t aN,
|
||||
const char* aStr, const char* astr,
|
||||
size_t aCategoryUsableSize,
|
||||
size_t aCumulativeUsableSize,
|
||||
size_t aTotalUsableSize) const
|
||||
{
|
||||
bool showTilde = mGroupSize.IsSampled();
|
||||
|
||||
W("%s: %s block%s in block group %s of %s\n",
|
||||
aStr,
|
||||
Show(mNumBlocks, gBuf1, kBufLen, showTilde), Plural(mNumBlocks),
|
||||
Show(aM, gBuf2, kBufLen),
|
||||
Show(aN, gBuf3, kBufLen));
|
||||
|
||||
W(" %s bytes (%s requested / %s slop)\n",
|
||||
Show(mGroupSize.Usable(), gBuf1, kBufLen, showTilde),
|
||||
Show(mGroupSize.Req(), gBuf2, kBufLen, showTilde),
|
||||
Show(mGroupSize.Slop(), gBuf3, kBufLen, showTilde));
|
||||
|
||||
W(" Allocated at\n");
|
||||
mAllocStackTrace->Print(aWriter, aLocService);
|
||||
|
||||
W("\n Previously reported at\n");
|
||||
mReportStackTrace1->Print(aWriter, aLocService);
|
||||
|
||||
W("\n Now reported at\n");
|
||||
mReportStackTrace2->Print(aWriter, aLocService);
|
||||
|
||||
W("\n");
|
||||
}
|
||||
@ -1421,7 +1402,7 @@ public:
|
||||
const GroupSize& GetGroupSize() const { return mGroupSize; }
|
||||
|
||||
// This is |const| thanks to the |mutable| fields above.
|
||||
void Add(const LiveBlockGroup& aBg) const
|
||||
void Add(const BlockGroup& aBg) const
|
||||
{
|
||||
mNumBlocks += aBg.mNumBlocks;
|
||||
mNumBlockGroups++;
|
||||
@ -1696,10 +1677,6 @@ Init(const malloc_table_t* aMallocTable)
|
||||
gLiveBlockTable = InfallibleAllocPolicy::new_<LiveBlockTable>();
|
||||
gLiveBlockTable->init(8192);
|
||||
|
||||
gDoubleReportBlockGroupTable =
|
||||
InfallibleAllocPolicy::new_<DoubleReportBlockGroupTable>();
|
||||
gDoubleReportBlockGroupTable->init(0);
|
||||
|
||||
if (gMode == Test) {
|
||||
// OpenTestOrStressFile() can allocate. So do this before setting
|
||||
// gIsDMDRunning so those allocations don't show up in our results. Once
|
||||
@ -1732,36 +1709,8 @@ Init(const malloc_table_t* aMallocTable)
|
||||
// DMD reporting and unreporting
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void
|
||||
LiveBlock::Report(Thread* aT, bool aOnAlloc) const
|
||||
{
|
||||
if (IsReported()) {
|
||||
DoubleReportBlockKey key(mAllocStackTrace, mReportStackTrace,
|
||||
StackTrace::Get(aT));
|
||||
DoubleReportBlockGroupTable::AddPtr p =
|
||||
gDoubleReportBlockGroupTable->lookupForAdd(key);
|
||||
if (!p) {
|
||||
DoubleReportBlockGroup bg(key);
|
||||
(void)gDoubleReportBlockGroupTable->add(p, bg);
|
||||
}
|
||||
p->Add(*this);
|
||||
|
||||
} else {
|
||||
mReportStackTrace = StackTrace::Get(aT);
|
||||
mReportedOnAlloc = aOnAlloc;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
LiveBlock::UnreportIfNotReportedOnAlloc() const
|
||||
{
|
||||
if (!mReportedOnAlloc) {
|
||||
mReportStackTrace = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ReportHelper(const void* aPtr, bool aOnAlloc)
|
||||
ReportHelper(const void* aPtr, bool aReportedOnAlloc)
|
||||
{
|
||||
if (!gIsDMDRunning || !aPtr) {
|
||||
return;
|
||||
@ -1773,7 +1722,7 @@ ReportHelper(const void* aPtr, bool aOnAlloc)
|
||||
AutoLockState lock;
|
||||
|
||||
if (LiveBlockTable::Ptr p = gLiveBlockTable->lookup(aPtr)) {
|
||||
p->Report(t, aOnAlloc);
|
||||
p->Report(t, aReportedOnAlloc);
|
||||
} else {
|
||||
// We have no record of the block. Do nothing. Either:
|
||||
// - We're sampling and we skipped this block. This is likely.
|
||||
@ -1798,7 +1747,7 @@ ReportOnAlloc(const void* aPtr)
|
||||
// DMD output
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
// This works for LiveBlockGroups, DoubleReportBlockGroups and FrameGroups.
|
||||
// This works for BlockGroups and FrameGroups.
|
||||
template <class TGroup>
|
||||
static void
|
||||
PrintSortedGroups(const Writer& aWriter, LocationService* aLocService,
|
||||
@ -1856,11 +1805,11 @@ static void
|
||||
PrintSortedBlockAndFrameGroups(const Writer& aWriter,
|
||||
LocationService* aLocService,
|
||||
const char* aStr, const char* astr,
|
||||
const LiveBlockGroupTable& aLiveBlockGroupTable,
|
||||
const BlockGroupTable& aBlockGroupTable,
|
||||
size_t aCategoryUsableSize,
|
||||
size_t aTotalUsableSize)
|
||||
{
|
||||
PrintSortedGroups(aWriter, aLocService, aStr, astr, aLiveBlockGroupTable,
|
||||
PrintSortedGroups(aWriter, aLocService, aStr, astr, aBlockGroupTable,
|
||||
aCategoryUsableSize, aTotalUsableSize);
|
||||
|
||||
// Frame groups are totally dependent on vagaries of stack traces, so we
|
||||
@ -1871,10 +1820,10 @@ PrintSortedBlockAndFrameGroups(const Writer& aWriter,
|
||||
|
||||
FrameGroupTable frameGroupTable;
|
||||
(void)frameGroupTable.init(2048);
|
||||
for (LiveBlockGroupTable::Range r = aLiveBlockGroupTable.all();
|
||||
for (BlockGroupTable::Range r = aBlockGroupTable.all();
|
||||
!r.empty();
|
||||
r.popFront()) {
|
||||
const LiveBlockGroup& bg = r.front();
|
||||
const BlockGroup& bg = r.front();
|
||||
const StackTrace* st = bg.mAllocStackTrace;
|
||||
|
||||
// A single PC can appear multiple times in a stack trace. We ignore
|
||||
@ -1925,9 +1874,6 @@ SizeOf(Sizes* aSizes)
|
||||
gStackTraceTable->sizeOfIncludingThis(MallocSizeOf);
|
||||
|
||||
aSizes->mLiveBlockTable = gLiveBlockTable->sizeOfIncludingThis(MallocSizeOf);
|
||||
|
||||
aSizes->mDoubleReportTable =
|
||||
gDoubleReportBlockGroupTable->sizeOfIncludingThis(MallocSizeOf);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1940,10 +1886,6 @@ ClearGlobalState()
|
||||
r.popFront()) {
|
||||
r.front().UnreportIfNotReportedOnAlloc();
|
||||
}
|
||||
|
||||
// Clear errors.
|
||||
gDoubleReportBlockGroupTable->finish();
|
||||
(void)gDoubleReportBlockGroupTable->init();
|
||||
}
|
||||
|
||||
MOZ_EXPORT void
|
||||
@ -1962,15 +1904,19 @@ Dump(Writer aWriter)
|
||||
static int dumpCount = 1;
|
||||
StatusMsg("Dump %d {\n", dumpCount++);
|
||||
|
||||
StatusMsg(" gathering live block groups...\n");
|
||||
StatusMsg(" gathering block groups...\n");
|
||||
|
||||
LiveBlockGroupTable unreportedLiveBlockGroupTable;
|
||||
(void)unreportedLiveBlockGroupTable.init(1024);
|
||||
BlockGroupTable unreportedBlockGroupTable;
|
||||
(void)unreportedBlockGroupTable.init(1024);
|
||||
size_t unreportedUsableSize = 0;
|
||||
|
||||
LiveBlockGroupTable reportedLiveBlockGroupTable;
|
||||
(void)reportedLiveBlockGroupTable.init(1024);
|
||||
size_t reportedUsableSize = 0;
|
||||
BlockGroupTable onceReportedBlockGroupTable;
|
||||
(void)onceReportedBlockGroupTable.init(1024);
|
||||
size_t onceReportedUsableSize = 0;
|
||||
|
||||
BlockGroupTable twiceReportedBlockGroupTable;
|
||||
(void)twiceReportedBlockGroupTable.init(0);
|
||||
size_t twiceReportedUsableSize = 0;
|
||||
|
||||
bool anyBlocksSampled = false;
|
||||
|
||||
@ -1979,23 +1925,31 @@ Dump(Writer aWriter)
|
||||
r.popFront()) {
|
||||
const LiveBlock& b = r.front();
|
||||
|
||||
size_t& size = !b.IsReported() ? unreportedUsableSize : reportedUsableSize;
|
||||
size += b.UsableSize();
|
||||
|
||||
LiveBlockGroupTable& table = !b.IsReported()
|
||||
? unreportedLiveBlockGroupTable
|
||||
: reportedLiveBlockGroupTable;
|
||||
LiveBlockKey liveKey(b);
|
||||
LiveBlockGroupTable::AddPtr p = table.lookupForAdd(liveKey);
|
||||
BlockGroupTable* table;
|
||||
uint32_t numReports = b.NumReports();
|
||||
if (numReports == 0) {
|
||||
unreportedUsableSize += b.UsableSize();
|
||||
table = &unreportedBlockGroupTable;
|
||||
} else if (numReports == 1) {
|
||||
onceReportedUsableSize += b.UsableSize();
|
||||
table = &onceReportedBlockGroupTable;
|
||||
} else {
|
||||
MOZ_ASSERT(numReports == 2);
|
||||
twiceReportedUsableSize += b.UsableSize();
|
||||
table = &twiceReportedBlockGroupTable;
|
||||
}
|
||||
BlockGroupKey key(b);
|
||||
BlockGroupTable::AddPtr p = table->lookupForAdd(key);
|
||||
if (!p) {
|
||||
LiveBlockGroup bg(b);
|
||||
(void)table.add(p, bg);
|
||||
BlockGroup bg(b);
|
||||
(void)table->add(p, bg);
|
||||
}
|
||||
p->Add(b);
|
||||
|
||||
anyBlocksSampled = anyBlocksSampled || b.IsSampled();
|
||||
}
|
||||
size_t totalUsableSize = unreportedUsableSize + reportedUsableSize;
|
||||
size_t totalUsableSize =
|
||||
unreportedUsableSize + onceReportedUsableSize + twiceReportedUsableSize;
|
||||
|
||||
WriteTitle("Invocation\n");
|
||||
W("$DMD = '%s'\n", gDMDEnvVar);
|
||||
@ -2004,29 +1958,33 @@ Dump(Writer aWriter)
|
||||
// Allocate this on the heap instead of the stack because it's fairly large.
|
||||
LocationService* locService = InfallibleAllocPolicy::new_<LocationService>();
|
||||
|
||||
PrintSortedGroups(aWriter, locService, "Double-reported", "double-reported",
|
||||
*gDoubleReportBlockGroupTable, kNoSize, kNoSize);
|
||||
PrintSortedGroups(aWriter, locService, "Twice-reported", "twice-reported",
|
||||
twiceReportedBlockGroupTable, twiceReportedUsableSize,
|
||||
totalUsableSize);
|
||||
|
||||
PrintSortedBlockAndFrameGroups(aWriter, locService,
|
||||
"Unreported", "unreported",
|
||||
unreportedLiveBlockGroupTable,
|
||||
unreportedBlockGroupTable,
|
||||
unreportedUsableSize, totalUsableSize);
|
||||
|
||||
PrintSortedBlockAndFrameGroups(aWriter, locService,
|
||||
"Reported", "reported",
|
||||
reportedLiveBlockGroupTable,
|
||||
reportedUsableSize, totalUsableSize);
|
||||
"Once-reported", "once-reported",
|
||||
onceReportedBlockGroupTable,
|
||||
onceReportedUsableSize, totalUsableSize);
|
||||
|
||||
bool showTilde = anyBlocksSampled;
|
||||
WriteTitle("Summary\n");
|
||||
W("Total: %s bytes\n",
|
||||
W("Total: %10s bytes\n",
|
||||
Show(totalUsableSize, gBuf1, kBufLen, showTilde));
|
||||
W("Reported: %s bytes (%5.2f%%)\n",
|
||||
Show(reportedUsableSize, gBuf1, kBufLen, showTilde),
|
||||
Percent(reportedUsableSize, totalUsableSize));
|
||||
W("Unreported: %s bytes (%5.2f%%)\n",
|
||||
W("Unreported: %10s bytes (%5.2f%%)\n",
|
||||
Show(unreportedUsableSize, gBuf1, kBufLen, showTilde),
|
||||
Percent(unreportedUsableSize, totalUsableSize));
|
||||
W("Once-reported: %10s bytes (%5.2f%%)\n",
|
||||
Show(onceReportedUsableSize, gBuf1, kBufLen, showTilde),
|
||||
Percent(onceReportedUsableSize, totalUsableSize));
|
||||
W("Twice-reported: %10s bytes (%5.2f%%)\n",
|
||||
Show(twiceReportedUsableSize, gBuf1, kBufLen, showTilde),
|
||||
Percent(twiceReportedUsableSize, totalUsableSize));
|
||||
|
||||
W("\n");
|
||||
|
||||
@ -2039,43 +1997,43 @@ Dump(Writer aWriter)
|
||||
|
||||
W("Data structures that persist after Dump() ends:\n");
|
||||
|
||||
W(" Stack traces: %10s bytes\n",
|
||||
W(" Stack traces: %10s bytes\n",
|
||||
Show(sizes.mStackTraces, gBuf1, kBufLen));
|
||||
|
||||
W(" Stack trace table: %10s bytes (%s entries, %s used)\n",
|
||||
W(" Stack trace table: %10s bytes (%s entries, %s used)\n",
|
||||
Show(sizes.mStackTraceTable, gBuf1, kBufLen),
|
||||
Show(gStackTraceTable->capacity(), gBuf2, kBufLen),
|
||||
Show(gStackTraceTable->count(), gBuf3, kBufLen));
|
||||
|
||||
W(" Live block table: %10s bytes (%s entries, %s used)\n",
|
||||
W(" Live block table: %10s bytes (%s entries, %s used)\n",
|
||||
Show(sizes.mLiveBlockTable, gBuf1, kBufLen),
|
||||
Show(gLiveBlockTable->capacity(), gBuf2, kBufLen),
|
||||
Show(gLiveBlockTable->count(), gBuf3, kBufLen));
|
||||
|
||||
W("\nData structures that are partly cleared after Dump() ends:\n");
|
||||
|
||||
W(" Double-report table: %10s bytes (%s entries, %s used)\n",
|
||||
Show(sizes.mDoubleReportTable, gBuf1, kBufLen),
|
||||
Show(gDoubleReportBlockGroupTable->capacity(), gBuf2, kBufLen),
|
||||
Show(gDoubleReportBlockGroupTable->count(), gBuf3, kBufLen));
|
||||
|
||||
W("\nData structures that are destroyed after Dump() ends:\n");
|
||||
|
||||
size_t unreportedSize =
|
||||
unreportedLiveBlockGroupTable.sizeOfIncludingThis(MallocSizeOf);
|
||||
W(" Unreported table: %10s bytes (%s entries, %s used)\n",
|
||||
Show(unreportedSize, gBuf1, kBufLen),
|
||||
Show(unreportedLiveBlockGroupTable.capacity(), gBuf2, kBufLen),
|
||||
Show(unreportedLiveBlockGroupTable.count(), gBuf3, kBufLen));
|
||||
unreportedBlockGroupTable.sizeOfIncludingThis(MallocSizeOf);
|
||||
W(" Unreported table: %10s bytes (%s entries, %s used)\n",
|
||||
Show(unreportedSize, gBuf1, kBufLen),
|
||||
Show(unreportedBlockGroupTable.capacity(), gBuf2, kBufLen),
|
||||
Show(unreportedBlockGroupTable.count(), gBuf3, kBufLen));
|
||||
|
||||
size_t reportedSize =
|
||||
reportedLiveBlockGroupTable.sizeOfIncludingThis(MallocSizeOf);
|
||||
W(" Reported table: %10s bytes (%s entries, %s used)\n",
|
||||
Show(reportedSize, gBuf1, kBufLen),
|
||||
Show(reportedLiveBlockGroupTable.capacity(), gBuf2, kBufLen),
|
||||
Show(reportedLiveBlockGroupTable.count(), gBuf3, kBufLen));
|
||||
size_t onceReportedSize =
|
||||
onceReportedBlockGroupTable.sizeOfIncludingThis(MallocSizeOf);
|
||||
W(" Once-reported table: %10s bytes (%s entries, %s used)\n",
|
||||
Show(onceReportedSize, gBuf1, kBufLen),
|
||||
Show(onceReportedBlockGroupTable.capacity(), gBuf2, kBufLen),
|
||||
Show(onceReportedBlockGroupTable.count(), gBuf3, kBufLen));
|
||||
|
||||
W(" Location service: %10s bytes\n",
|
||||
size_t twiceReportedSize =
|
||||
twiceReportedBlockGroupTable.sizeOfIncludingThis(MallocSizeOf);
|
||||
W(" Twice-reported table: %10s bytes (%s entries, %s used)\n",
|
||||
Show(twiceReportedSize, gBuf1, kBufLen),
|
||||
Show(twiceReportedBlockGroupTable.capacity(), gBuf2, kBufLen),
|
||||
Show(twiceReportedBlockGroupTable.count(), gBuf3, kBufLen));
|
||||
|
||||
W(" Location service: %10s bytes\n",
|
||||
Show(locService->SizeOfIncludingThis(), gBuf1, kBufLen));
|
||||
|
||||
W("\nCounts:\n");
|
||||
@ -2158,7 +2116,7 @@ RunTestMode(FILE* fp)
|
||||
|
||||
// Min-sized block.
|
||||
// 1st Dump: reported.
|
||||
// 2nd Dump: re-reported, twice; double-report warning.
|
||||
// 2nd Dump: thrice-reported.
|
||||
char* a2 = (char*) malloc(0);
|
||||
Report(a2);
|
||||
|
||||
@ -2175,7 +2133,7 @@ RunTestMode(FILE* fp)
|
||||
ReportOnAlloc(b2);
|
||||
free(b2);
|
||||
|
||||
// 1st Dump: reported, plus 3 double-report warnings.
|
||||
// 1st Dump: reported 4 times.
|
||||
// 2nd Dump: freed, irrelevant.
|
||||
char* c = (char*) calloc(10, 3);
|
||||
Report(c);
|
||||
@ -2223,6 +2181,24 @@ RunTestMode(FILE* fp)
|
||||
foo();
|
||||
foo();
|
||||
|
||||
// 1st Dump: twice-reported.
|
||||
// 2nd Dump: twice-reported.
|
||||
char* g1 = (char*) malloc(77);
|
||||
ReportOnAlloc(g1);
|
||||
ReportOnAlloc(g1);
|
||||
|
||||
// 1st Dump: twice-reported.
|
||||
// 2nd Dump: once-reported.
|
||||
char* g2 = (char*) malloc(78);
|
||||
Report(g2);
|
||||
ReportOnAlloc(g2);
|
||||
|
||||
// 1st Dump: twice-reported.
|
||||
// 2nd Dump: once-reported.
|
||||
char* g3 = (char*) malloc(79);
|
||||
ReportOnAlloc(g3);
|
||||
Report(g3);
|
||||
|
||||
// All the odd-ball ones.
|
||||
// 1st Dump: all unreported.
|
||||
// 2nd Dump: all freed, irrelevant.
|
||||
|
@ -55,7 +55,6 @@ struct Sizes
|
||||
size_t mStackTraces;
|
||||
size_t mStackTraceTable;
|
||||
size_t mLiveBlockTable;
|
||||
size_t mDoubleReportTable;
|
||||
|
||||
Sizes() { Clear(); }
|
||||
void Clear() { memset(this, 0, sizeof(Sizes)); }
|
||||
|
@ -6,7 +6,7 @@ $DMD = '--mode=test'
|
||||
Sample-below size = 1
|
||||
|
||||
------------------------------------------------------------------
|
||||
Double-reported blocks
|
||||
Twice-reported blocks
|
||||
------------------------------------------------------------------
|
||||
|
||||
(none)
|
||||
@ -18,7 +18,7 @@ Unreported blocks
|
||||
(none)
|
||||
|
||||
------------------------------------------------------------------
|
||||
Reported blocks
|
||||
Once-reported blocks
|
||||
------------------------------------------------------------------
|
||||
|
||||
(none)
|
||||
@ -27,9 +27,10 @@ Reported blocks
|
||||
Summary
|
||||
------------------------------------------------------------------
|
||||
|
||||
Total: 0 bytes
|
||||
Reported: 0 bytes ( 0.00%)
|
||||
Unreported: 0 bytes ( 0.00%)
|
||||
Total: 0 bytes
|
||||
Unreported: 0 bytes ( 0.00%)
|
||||
Once-reported: 0 bytes ( 0.00%)
|
||||
Twice-reported: 0 bytes ( 0.00%)
|
||||
|
||||
------------------------------------------------------------------
|
||||
Invocation
|
||||
@ -39,18 +40,55 @@ $DMD = '--mode=test'
|
||||
Sample-below size = 1
|
||||
|
||||
------------------------------------------------------------------
|
||||
Double-reported blocks
|
||||
Twice-reported blocks
|
||||
------------------------------------------------------------------
|
||||
|
||||
Double-reported: 3 blocks in block group 1 of 1
|
||||
96 bytes (90 requested / 6 slop)
|
||||
Twice-reported: 1 block in block group 1 of 4
|
||||
80 bytes (79 requested / 1 slop)
|
||||
0.53% of the heap (0.53% cumulative); 29.41% of twice-reported (29.41% cumulative)
|
||||
Allocated at
|
||||
(stack omitted due to test mode)
|
||||
|
||||
Previously reported at
|
||||
Reported at
|
||||
(stack omitted due to test mode)
|
||||
|
||||
Now reported at
|
||||
Reported again at
|
||||
(stack omitted due to test mode)
|
||||
|
||||
Twice-reported: 1 block in block group 2 of 4
|
||||
80 bytes (78 requested / 2 slop)
|
||||
0.53% of the heap (1.05% cumulative); 29.41% of twice-reported (58.82% cumulative)
|
||||
Allocated at
|
||||
(stack omitted due to test mode)
|
||||
|
||||
Reported at
|
||||
(stack omitted due to test mode)
|
||||
|
||||
Reported again at
|
||||
(stack omitted due to test mode)
|
||||
|
||||
Twice-reported: 1 block in block group 3 of 4
|
||||
80 bytes (77 requested / 3 slop)
|
||||
0.53% of the heap (1.58% cumulative); 29.41% of twice-reported (88.24% cumulative)
|
||||
Allocated at
|
||||
(stack omitted due to test mode)
|
||||
|
||||
Reported at
|
||||
(stack omitted due to test mode)
|
||||
|
||||
Reported again at
|
||||
(stack omitted due to test mode)
|
||||
|
||||
Twice-reported: 1 block in block group 4 of 4
|
||||
32 bytes (30 requested / 2 slop)
|
||||
0.21% of the heap (1.79% cumulative); 11.76% of twice-reported (100.00% cumulative)
|
||||
Allocated at
|
||||
(stack omitted due to test mode)
|
||||
|
||||
Reported at
|
||||
(stack omitted due to test mode)
|
||||
|
||||
Reported again at
|
||||
(stack omitted due to test mode)
|
||||
|
||||
------------------------------------------------------------------
|
||||
@ -59,134 +97,125 @@ Unreported blocks
|
||||
|
||||
Unreported: 1 block in block group 1 of 4
|
||||
4,096 bytes (1 requested / 4,095 slop)
|
||||
27.44% of the heap (27.44% cumulative); 76.88% of unreported (76.88% cumulative)
|
||||
27.00% of the heap (27.00% cumulative); 76.88% of unreported (76.88% cumulative)
|
||||
Allocated at
|
||||
(stack omitted due to test mode)
|
||||
|
||||
Unreported: 9 blocks in block group 2 of 4
|
||||
1,008 bytes (900 requested / 108 slop)
|
||||
6.75% of the heap (34.19% cumulative); 18.92% of unreported (95.80% cumulative)
|
||||
6.65% of the heap (33.65% cumulative); 18.92% of unreported (95.80% cumulative)
|
||||
Allocated at
|
||||
(stack omitted due to test mode)
|
||||
|
||||
Unreported: 2 blocks in block group 3 of 4
|
||||
112 bytes (112 requested / 0 slop)
|
||||
0.75% of the heap (34.94% cumulative); 2.10% of unreported (97.90% cumulative)
|
||||
0.74% of the heap (34.39% cumulative); 2.10% of unreported (97.90% cumulative)
|
||||
Allocated at
|
||||
(stack omitted due to test mode)
|
||||
|
||||
Unreported: 2 blocks in block group 4 of 4
|
||||
112 bytes (112 requested / 0 slop)
|
||||
0.75% of the heap (35.69% cumulative); 2.10% of unreported (100.00% cumulative)
|
||||
0.74% of the heap (35.13% cumulative); 2.10% of unreported (100.00% cumulative)
|
||||
Allocated at
|
||||
(stack omitted due to test mode)
|
||||
|
||||
------------------------------------------------------------------
|
||||
Reported blocks
|
||||
Once-reported blocks
|
||||
------------------------------------------------------------------
|
||||
|
||||
Reported: 1 block in block group 1 of 12
|
||||
Once-reported: 1 block in block group 1 of 11
|
||||
8,192 bytes (4,097 requested / 4,095 slop)
|
||||
54.88% of the heap (54.88% cumulative); 85.33% of reported (85.33% cumulative)
|
||||
54.01% of the heap (54.01% cumulative); 85.62% of once-reported (85.62% cumulative)
|
||||
Allocated at
|
||||
(stack omitted due to test mode)
|
||||
|
||||
Reported at
|
||||
(stack omitted due to test mode)
|
||||
|
||||
Reported: 1 block in block group 2 of 12
|
||||
Once-reported: 1 block in block group 2 of 11
|
||||
512 bytes (512 requested / 0 slop)
|
||||
3.43% of the heap (58.31% cumulative); 5.33% of reported (90.67% cumulative)
|
||||
3.38% of the heap (57.38% cumulative); 5.35% of once-reported (90.97% cumulative)
|
||||
Allocated at
|
||||
(stack omitted due to test mode)
|
||||
|
||||
Reported at
|
||||
(stack omitted due to test mode)
|
||||
|
||||
Reported: 2 blocks in block group 3 of 12
|
||||
Once-reported: 2 blocks in block group 3 of 11
|
||||
240 bytes (240 requested / 0 slop)
|
||||
1.61% of the heap (59.91% cumulative); 2.50% of reported (93.17% cumulative)
|
||||
1.58% of the heap (58.97% cumulative); 2.51% of once-reported (93.48% cumulative)
|
||||
Allocated at
|
||||
(stack omitted due to test mode)
|
||||
|
||||
Reported at
|
||||
(stack omitted due to test mode)
|
||||
|
||||
Reported: 2 blocks in block group 4 of 12
|
||||
Once-reported: 2 blocks in block group 4 of 11
|
||||
240 bytes (240 requested / 0 slop)
|
||||
1.61% of the heap (61.52% cumulative); 2.50% of reported (95.67% cumulative)
|
||||
1.58% of the heap (60.55% cumulative); 2.51% of once-reported (95.99% cumulative)
|
||||
Allocated at
|
||||
(stack omitted due to test mode)
|
||||
|
||||
Reported at
|
||||
(stack omitted due to test mode)
|
||||
|
||||
Reported: 1 block in block group 5 of 12
|
||||
Once-reported: 1 block in block group 5 of 11
|
||||
96 bytes (96 requested / 0 slop)
|
||||
0.64% of the heap (62.17% cumulative); 1.00% of reported (96.67% cumulative)
|
||||
0.63% of the heap (61.18% cumulative); 1.00% of once-reported (96.99% cumulative)
|
||||
Allocated at
|
||||
(stack omitted due to test mode)
|
||||
|
||||
Reported at
|
||||
(stack omitted due to test mode)
|
||||
|
||||
Reported: 1 block in block group 6 of 12
|
||||
Once-reported: 1 block in block group 6 of 11
|
||||
96 bytes (96 requested / 0 slop)
|
||||
0.64% of the heap (62.81% cumulative); 1.00% of reported (97.67% cumulative)
|
||||
0.63% of the heap (61.81% cumulative); 1.00% of once-reported (97.99% cumulative)
|
||||
Allocated at
|
||||
(stack omitted due to test mode)
|
||||
|
||||
Reported at
|
||||
(stack omitted due to test mode)
|
||||
|
||||
Reported: 1 block in block group 7 of 12
|
||||
Once-reported: 1 block in block group 7 of 11
|
||||
80 bytes (80 requested / 0 slop)
|
||||
0.54% of the heap (63.34% cumulative); 0.83% of reported (98.50% cumulative)
|
||||
0.53% of the heap (62.34% cumulative); 0.84% of once-reported (98.83% cumulative)
|
||||
Allocated at
|
||||
(stack omitted due to test mode)
|
||||
|
||||
Reported at
|
||||
(stack omitted due to test mode)
|
||||
|
||||
Reported: 1 block in block group 8 of 12
|
||||
Once-reported: 1 block in block group 8 of 11
|
||||
80 bytes (80 requested / 0 slop)
|
||||
0.54% of the heap (63.88% cumulative); 0.83% of reported (99.33% cumulative)
|
||||
0.53% of the heap (62.87% cumulative); 0.84% of once-reported (99.67% cumulative)
|
||||
Allocated at
|
||||
(stack omitted due to test mode)
|
||||
|
||||
Reported at
|
||||
(stack omitted due to test mode)
|
||||
|
||||
Reported: 1 block in block group 9 of 12
|
||||
32 bytes (30 requested / 2 slop)
|
||||
0.21% of the heap (64.09% cumulative); 0.33% of reported (99.67% cumulative)
|
||||
Allocated at
|
||||
(stack omitted due to test mode)
|
||||
|
||||
Reported at
|
||||
(stack omitted due to test mode)
|
||||
|
||||
Reported: 1 block in block group 10 of 12
|
||||
Once-reported: 1 block in block group 9 of 11
|
||||
16 bytes (10 requested / 6 slop)
|
||||
0.11% of the heap (64.20% cumulative); 0.17% of reported (99.83% cumulative)
|
||||
0.11% of the heap (62.97% cumulative); 0.17% of once-reported (99.83% cumulative)
|
||||
Allocated at
|
||||
(stack omitted due to test mode)
|
||||
|
||||
Reported at
|
||||
(stack omitted due to test mode)
|
||||
|
||||
Reported: 1 block in block group 11 of 12
|
||||
Once-reported: 1 block in block group 10 of 11
|
||||
8 bytes (0 requested / 8 slop)
|
||||
0.05% of the heap (64.26% cumulative); 0.08% of reported (99.92% cumulative)
|
||||
0.05% of the heap (63.03% cumulative); 0.08% of once-reported (99.92% cumulative)
|
||||
Allocated at
|
||||
(stack omitted due to test mode)
|
||||
|
||||
Reported at
|
||||
(stack omitted due to test mode)
|
||||
|
||||
Reported: 1 block in block group 12 of 12
|
||||
Once-reported: 1 block in block group 11 of 11
|
||||
8 bytes (0 requested / 8 slop)
|
||||
0.05% of the heap (64.31% cumulative); 0.08% of reported (100.00% cumulative)
|
||||
0.05% of the heap (63.08% cumulative); 0.08% of once-reported (100.00% cumulative)
|
||||
Allocated at
|
||||
(stack omitted due to test mode)
|
||||
|
||||
@ -197,9 +226,10 @@ Reported: 1 block in block group 12 of 12
|
||||
Summary
|
||||
------------------------------------------------------------------
|
||||
|
||||
Total: 14,928 bytes
|
||||
Reported: 9,600 bytes (64.31%)
|
||||
Unreported: 5,328 bytes (35.69%)
|
||||
Total: 15,168 bytes
|
||||
Unreported: 5,328 bytes (35.13%)
|
||||
Once-reported: 9,568 bytes (63.08%)
|
||||
Twice-reported: 272 bytes ( 1.79%)
|
||||
|
||||
------------------------------------------------------------------
|
||||
Invocation
|
||||
@ -209,18 +239,31 @@ $DMD = '--mode=test'
|
||||
Sample-below size = 1
|
||||
|
||||
------------------------------------------------------------------
|
||||
Double-reported blocks
|
||||
Twice-reported blocks
|
||||
------------------------------------------------------------------
|
||||
|
||||
Double-reported: 1 block in block group 1 of 1
|
||||
8 bytes (0 requested / 8 slop)
|
||||
Twice-reported: 1 block in block group 1 of 2
|
||||
80 bytes (77 requested / 3 slop)
|
||||
2.82% of the heap (2.82% cumulative); 90.91% of twice-reported (90.91% cumulative)
|
||||
Allocated at
|
||||
(stack omitted due to test mode)
|
||||
|
||||
Previously reported at
|
||||
Reported at
|
||||
(stack omitted due to test mode)
|
||||
|
||||
Now reported at
|
||||
Reported again at
|
||||
(stack omitted due to test mode)
|
||||
|
||||
Twice-reported: 1 block in block group 2 of 2
|
||||
8 bytes (0 requested / 8 slop)
|
||||
0.28% of the heap (3.10% cumulative); 9.09% of twice-reported (100.00% cumulative)
|
||||
Allocated at
|
||||
(stack omitted due to test mode)
|
||||
|
||||
Reported at
|
||||
(stack omitted due to test mode)
|
||||
|
||||
Reported again at
|
||||
(stack omitted due to test mode)
|
||||
|
||||
------------------------------------------------------------------
|
||||
@ -229,47 +272,56 @@ Unreported blocks
|
||||
|
||||
Unreported: 9 blocks in block group 1 of 3
|
||||
1,008 bytes (900 requested / 108 slop)
|
||||
38.77% of the heap (38.77% cumulative); 48.84% of unreported (48.84% cumulative)
|
||||
35.49% of the heap (35.49% cumulative); 48.84% of unreported (48.84% cumulative)
|
||||
Allocated at
|
||||
(stack omitted due to test mode)
|
||||
|
||||
Unreported: 6 blocks in block group 2 of 3
|
||||
528 bytes (528 requested / 0 slop)
|
||||
20.31% of the heap (59.08% cumulative); 25.58% of unreported (74.42% cumulative)
|
||||
18.59% of the heap (54.08% cumulative); 25.58% of unreported (74.42% cumulative)
|
||||
Allocated at
|
||||
(stack omitted due to test mode)
|
||||
|
||||
Unreported: 6 blocks in block group 3 of 3
|
||||
528 bytes (528 requested / 0 slop)
|
||||
20.31% of the heap (79.38% cumulative); 25.58% of unreported (100.00% cumulative)
|
||||
18.59% of the heap (72.68% cumulative); 25.58% of unreported (100.00% cumulative)
|
||||
Allocated at
|
||||
(stack omitted due to test mode)
|
||||
|
||||
------------------------------------------------------------------
|
||||
Reported blocks
|
||||
Once-reported blocks
|
||||
------------------------------------------------------------------
|
||||
|
||||
Reported: 1 block in block group 1 of 3
|
||||
Once-reported: 1 block in block group 1 of 4
|
||||
512 bytes (512 requested / 0 slop)
|
||||
19.69% of the heap (19.69% cumulative); 95.52% of reported (95.52% cumulative)
|
||||
18.03% of the heap (18.03% cumulative); 74.42% of once-reported (74.42% cumulative)
|
||||
Allocated at
|
||||
(stack omitted due to test mode)
|
||||
|
||||
Reported at
|
||||
(stack omitted due to test mode)
|
||||
|
||||
Reported: 1 block in block group 2 of 3
|
||||
Once-reported: 1 block in block group 2 of 4
|
||||
80 bytes (79 requested / 1 slop)
|
||||
2.82% of the heap (20.85% cumulative); 11.63% of once-reported (86.05% cumulative)
|
||||
Allocated at
|
||||
(stack omitted due to test mode)
|
||||
|
||||
Reported at
|
||||
(stack omitted due to test mode)
|
||||
|
||||
Once-reported: 1 block in block group 3 of 4
|
||||
80 bytes (78 requested / 2 slop)
|
||||
2.82% of the heap (23.66% cumulative); 11.63% of once-reported (97.67% cumulative)
|
||||
Allocated at
|
||||
(stack omitted due to test mode)
|
||||
|
||||
Reported at
|
||||
(stack omitted due to test mode)
|
||||
|
||||
Once-reported: 1 block in block group 4 of 4
|
||||
16 bytes (10 requested / 6 slop)
|
||||
0.62% of the heap (20.31% cumulative); 2.99% of reported (98.51% cumulative)
|
||||
Allocated at
|
||||
(stack omitted due to test mode)
|
||||
|
||||
Reported at
|
||||
(stack omitted due to test mode)
|
||||
|
||||
Reported: 1 block in block group 3 of 3
|
||||
8 bytes (0 requested / 8 slop)
|
||||
0.31% of the heap (20.62% cumulative); 1.49% of reported (100.00% cumulative)
|
||||
0.56% of the heap (24.23% cumulative); 2.33% of once-reported (100.00% cumulative)
|
||||
Allocated at
|
||||
(stack omitted due to test mode)
|
||||
|
||||
@ -280,9 +332,10 @@ Reported: 1 block in block group 3 of 3
|
||||
Summary
|
||||
------------------------------------------------------------------
|
||||
|
||||
Total: 2,600 bytes
|
||||
Reported: 536 bytes (20.62%)
|
||||
Unreported: 2,064 bytes (79.38%)
|
||||
Total: 2,840 bytes
|
||||
Unreported: 2,064 bytes (72.68%)
|
||||
Once-reported: 688 bytes (24.23%)
|
||||
Twice-reported: 88 bytes ( 3.10%)
|
||||
|
||||
------------------------------------------------------------------
|
||||
Invocation
|
||||
@ -292,7 +345,7 @@ $DMD = '--mode=test'
|
||||
Sample-below size = 128
|
||||
|
||||
------------------------------------------------------------------
|
||||
Double-reported blocks
|
||||
Twice-reported blocks
|
||||
------------------------------------------------------------------
|
||||
|
||||
(none)
|
||||
@ -344,7 +397,7 @@ Unreported: ~1 block in block group 7 of 7
|
||||
(stack omitted due to test mode)
|
||||
|
||||
------------------------------------------------------------------
|
||||
Reported blocks
|
||||
Once-reported blocks
|
||||
------------------------------------------------------------------
|
||||
|
||||
(none)
|
||||
@ -353,7 +406,8 @@ Reported blocks
|
||||
Summary
|
||||
------------------------------------------------------------------
|
||||
|
||||
Total: ~1,424 bytes
|
||||
Reported: ~0 bytes ( 0.00%)
|
||||
Unreported: ~1,424 bytes (100.00%)
|
||||
Total: ~1,424 bytes
|
||||
Unreported: ~1,424 bytes (100.00%)
|
||||
Once-reported: ~0 bytes ( 0.00%)
|
||||
Twice-reported: ~0 bytes ( 0.00%)
|
||||
|
||||
|
@ -608,10 +608,6 @@ public:
|
||||
sizes.mLiveBlockTable,
|
||||
"Memory used by DMD's live block table.");
|
||||
|
||||
REPORT("explicit/dmd/double-report-table",
|
||||
sizes.mDoubleReportTable,
|
||||
"Memory used by DMD's double-report table.");
|
||||
|
||||
#undef REPORT
|
||||
|
||||
return NS_OK;
|
||||
|
Loading…
Reference in New Issue
Block a user