mirror of
https://github.com/roytam1/palemoon27.git
synced 2026-05-26 13:43:44 +00:00
import changes from `dev' branch of rmottola/Arctic-Fox:
- pointer style (8365db72a)
- remove stackDepth check not found anywhere in official gecko (98f65d05e)
- Bug 1134198 - Call Debugger::onPop at the point that caused the frame to pop before any unwinding in the JIT. (r=jandem) (5aea98ae6)
- Bug 1189750 - Remove unused JM-related PCCounts counters. r=bhackett (7410480af)
- Bug 1198245 - IonMonkey: Lock helperthread before finishing ionbuilder, r=jandem (0f28ef66a)
- Bug 1188620 - Use PersistentRooted for asyncActivation roots; r=fitzgen (4f6ae0e92)
- Bug 1190446 - Update Coverage information in Baseline. r=jandem (95935926e)
- Bug 1188129 - Use a universal constructor to create and init PersistentRooted; r=jonco (75db7ea8f)
- Bug 1187767 - Ensure PLDHashTable's generation is always updated when the entry store is modified. r=froydnj. (e49936dad)
- Bug 1189156 (part 1) - Don't use enumeration style for PLDHashTable::SizeOf{In,Ex}cludingThis(). r=froydnj. (3152ab914)
- Bug 1189156 (part 2) - Don't use enumeration style for nsTHashtable::SizeOf{In,Ex}cludingThis(). r=erahm. (de21442b7)
- Bug 1189156 (part 3) - Factor out FontTable better. r=jfkthame. (afdee9bd7)
- Bug 1189156 (part 4) - Don't use enumeration style for nsBaseHashtable::SizeOf{In,Ex}cludingThis(). r=erahm,jfkthame. (32d72520f)
- Bug 1189156 (part 5) - Add FontEntryTable typedef and factor out some related code. r=jfkthame. (9983134a9)
- Bug 1137437 - move security/apps/ cert header generation to moz.build; r=mshal,keeler (2f7abb37d)
- Bug 1180993 - Part 3: Correct use sites of functions which return already_AddRefed. r=ehsan (2a6289b6a)
This commit is contained in:
@@ -10,6 +10,7 @@
|
||||
#include "mozilla/gfx/DataSurfaceHelpers.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "mozilla/SyncRunnable.h"
|
||||
#include "mozilla/unused.h"
|
||||
#include "gfxUtils.h"
|
||||
#include "nsNetUtil.h"
|
||||
|
||||
@@ -206,7 +207,7 @@ public:
|
||||
rv = NS_DispatchToMainThread(mEncodingCompleteEvent);
|
||||
if (NS_FAILED(rv)) {
|
||||
// Better to leak than to crash.
|
||||
mEncodingCompleteEvent.forget();
|
||||
unused << mEncodingCompleteEvent.forget();
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
@@ -364,8 +364,8 @@ public:
|
||||
// We don't measure the |EventListenerManager| objects pointed to by the
|
||||
// entries because those references are non-owning.
|
||||
int64_t amount = sEventListenerManagersHash
|
||||
? PL_DHashTableSizeOfExcludingThis(
|
||||
sEventListenerManagersHash, nullptr, MallocSizeOf)
|
||||
? sEventListenerManagersHash->ShallowSizeOfIncludingThis(
|
||||
MallocSizeOf)
|
||||
: 0;
|
||||
|
||||
return MOZ_COLLECT_REPORT(
|
||||
|
||||
@@ -546,21 +546,15 @@ nsDOMAttributeMap::Enumerate(AttrCache::EnumReadFunction aFunc,
|
||||
return mAttributeCache.EnumerateRead(aFunc, aUserArg);
|
||||
}
|
||||
|
||||
size_t
|
||||
AttrCacheSizeEnumerator(const nsAttrKey& aKey,
|
||||
const nsRefPtr<Attr>& aValue,
|
||||
MallocSizeOf aMallocSizeOf,
|
||||
void* aUserArg)
|
||||
{
|
||||
return aMallocSizeOf(aValue.get());
|
||||
}
|
||||
|
||||
size_t
|
||||
nsDOMAttributeMap::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
|
||||
{
|
||||
size_t n = aMallocSizeOf(this);
|
||||
n += mAttributeCache.SizeOfExcludingThis(AttrCacheSizeEnumerator,
|
||||
aMallocSizeOf);
|
||||
|
||||
n += mAttributeCache.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
||||
for (auto iter = mAttributeCache.ConstIter(); !iter.Done(); iter.Next()) {
|
||||
n += aMallocSizeOf(iter.Data().get());
|
||||
}
|
||||
|
||||
// NB: mContent is non-owning and thus not counted.
|
||||
return n;
|
||||
|
||||
@@ -12819,7 +12819,7 @@ nsDocument::DocAddSizeOfExcludingThis(nsWindowSizes* aWindowSizes) const
|
||||
0;
|
||||
|
||||
aWindowSizes->mDOMOtherSize +=
|
||||
mStyledLinks.SizeOfExcludingThis(nullptr, aWindowSizes->mMallocSizeOf);
|
||||
mStyledLinks.ShallowSizeOfExcludingThis(aWindowSizes->mMallocSizeOf);
|
||||
|
||||
aWindowSizes->mDOMOtherSize +=
|
||||
mIdentifierMap.SizeOfExcludingThis(aWindowSizes->mMallocSizeOf);
|
||||
|
||||
@@ -13369,12 +13369,8 @@ nsGlobalWindow::AddSizeOfIncludingThis(nsWindowSizes* aWindowSizes) const
|
||||
mNavigator->SizeOfIncludingThis(aWindowSizes->mMallocSizeOf);
|
||||
}
|
||||
|
||||
// The things pointed to by the entries will be measured below, so we
|
||||
// use nullptr for the callback here.
|
||||
aWindowSizes->mDOMEventTargetsSize +=
|
||||
mEventTargetObjects.SizeOfExcludingThis(nullptr,
|
||||
aWindowSizes->mMallocSizeOf);
|
||||
|
||||
mEventTargetObjects.ShallowSizeOfExcludingThis(aWindowSizes->mMallocSizeOf);
|
||||
|
||||
for (auto iter = mEventTargetObjects.ConstIter(); !iter.Done(); iter.Next()) {
|
||||
DOMEventTargetHelper* et = iter.Get()->GetKey();
|
||||
|
||||
@@ -310,7 +310,7 @@ size_t
|
||||
nsPropertyTable::PropertyList::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf)
|
||||
{
|
||||
size_t n = aMallocSizeOf(this);
|
||||
n += PL_DHashTableSizeOfExcludingThis(&mObjectValueMap, nullptr, aMallocSizeOf);
|
||||
n += mObjectValueMap.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
@@ -717,14 +717,6 @@ nsScriptNameSpaceManager::RegisterNavigatorDOMConstructor(
|
||||
}
|
||||
}
|
||||
|
||||
static size_t
|
||||
SizeOfEntryExcludingThis(PLDHashEntryHdr *aHdr, MallocSizeOf aMallocSizeOf,
|
||||
void *aArg)
|
||||
{
|
||||
GlobalNameMapEntry* entry = static_cast<GlobalNameMapEntry*>(aHdr);
|
||||
return entry->SizeOfExcludingThis(aMallocSizeOf);
|
||||
}
|
||||
|
||||
MOZ_DEFINE_MALLOC_SIZE_OF(ScriptNameSpaceManagerMallocSizeOf)
|
||||
|
||||
NS_IMETHODIMP
|
||||
@@ -738,12 +730,22 @@ nsScriptNameSpaceManager::CollectReports(
|
||||
}
|
||||
|
||||
size_t
|
||||
nsScriptNameSpaceManager::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf)
|
||||
nsScriptNameSpaceManager::SizeOfIncludingThis(
|
||||
mozilla::MallocSizeOf aMallocSizeOf) const
|
||||
{
|
||||
size_t n = 0;
|
||||
n += PL_DHashTableSizeOfExcludingThis(&mGlobalNames,
|
||||
SizeOfEntryExcludingThis, aMallocSizeOf);
|
||||
n += PL_DHashTableSizeOfExcludingThis(&mNavigatorNames,
|
||||
SizeOfEntryExcludingThis, aMallocSizeOf);
|
||||
|
||||
n += mGlobalNames.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
||||
for (auto iter = mGlobalNames.ConstIter(); !iter.Done(); iter.Next()) {
|
||||
auto entry = static_cast<GlobalNameMapEntry*>(iter.Get());
|
||||
n += entry->SizeOfExcludingThis(aMallocSizeOf);
|
||||
}
|
||||
|
||||
n += mNavigatorNames.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
||||
for (auto iter = mNavigatorNames.ConstIter(); !iter.Done(); iter.Next()) {
|
||||
auto entry = static_cast<GlobalNameMapEntry*>(iter.Get());
|
||||
n += entry->SizeOfExcludingThis(aMallocSizeOf);
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
@@ -206,7 +206,7 @@ public:
|
||||
NameIterator GlobalNameIter() { return NameIterator(&mGlobalNames); }
|
||||
NameIterator NavigatorNameIter() { return NameIterator(&mNavigatorNames); }
|
||||
|
||||
size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf);
|
||||
size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
|
||||
|
||||
private:
|
||||
virtual ~nsScriptNameSpaceManager();
|
||||
|
||||
@@ -225,7 +225,7 @@ private:
|
||||
// Intentionally leak the runnable (but not the fd) rather
|
||||
// than crash when trying to release a main thread object
|
||||
// off the main thread.
|
||||
mTabParent.forget();
|
||||
mozilla::unused << mTabParent.forget();
|
||||
CloseFile();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -403,8 +403,7 @@ size_t MediaCacheStream::SizeOfExcludingThis(
|
||||
size_t MediaCacheStream::BlockList::SizeOfExcludingThis(
|
||||
MallocSizeOf aMallocSizeOf) const
|
||||
{
|
||||
return mEntries.SizeOfExcludingThis(/* sizeOfEntryExcludingThis = */ nullptr,
|
||||
aMallocSizeOf);
|
||||
return mEntries.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
||||
}
|
||||
|
||||
void MediaCacheStream::BlockList::AddFirstBlock(int32_t aBlock)
|
||||
|
||||
@@ -1034,8 +1034,8 @@ AudioContext::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
|
||||
for (uint32_t i = 0; i < mDecodeJobs.Length(); ++i) {
|
||||
amount += mDecodeJobs[i]->SizeOfIncludingThis(aMallocSizeOf);
|
||||
}
|
||||
amount += mActiveNodes.SizeOfExcludingThis(nullptr, aMallocSizeOf);
|
||||
amount += mPannerNodes.SizeOfExcludingThis(nullptr, aMallocSizeOf);
|
||||
amount += mActiveNodes.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
||||
amount += mPannerNodes.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
||||
return amount;
|
||||
}
|
||||
|
||||
|
||||
@@ -421,8 +421,7 @@ nsReverseStringSQLFunction::OnFunctionCall(
|
||||
rv = outVar->SetAsAUTF8String(result);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
*aResult = outVar.get();
|
||||
outVar.forget();
|
||||
outVar.forget(aResult);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -1341,8 +1341,7 @@ gfxDWriteFontList::AddSizeOfExcludingThis(MallocSizeOf aMallocSizeOf,
|
||||
gfxPlatformFontList::AddSizeOfExcludingThis(aMallocSizeOf, aSizes);
|
||||
|
||||
aSizes->mFontListSize +=
|
||||
mFontSubstitutes.SizeOfExcludingThis(SizeOfFamilyNameEntryExcludingThis,
|
||||
aMallocSizeOf);
|
||||
SizeOfFontFamilyTableExcludingThis(mFontSubstitutes, aMallocSizeOf);
|
||||
|
||||
aSizes->mFontListSize +=
|
||||
mNonExistingFonts.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
||||
|
||||
@@ -406,13 +406,11 @@ private:
|
||||
*/
|
||||
nsTArray<nsString> mNonExistingFonts;
|
||||
|
||||
typedef nsRefPtrHashtable<nsStringHashKey, gfxFontFamily> FontTable;
|
||||
|
||||
/**
|
||||
* Table of font substitutes, we grab this from the registry to get
|
||||
* alternative font names.
|
||||
*/
|
||||
FontTable mFontSubstitutes;
|
||||
FontFamilyTable mFontSubstitutes;
|
||||
|
||||
bool mInitialized;
|
||||
virtual nsresult DelayedInitFontList();
|
||||
|
||||
@@ -657,7 +657,7 @@ gfxDWriteFont::AddSizeOfExcludingThis(MallocSizeOf aMallocSizeOf,
|
||||
aSizes->mFontInstances += aMallocSizeOf(mMetrics);
|
||||
if (mGlyphWidths) {
|
||||
aSizes->mFontInstances +=
|
||||
mGlyphWidths->SizeOfIncludingThis(nullptr, aMallocSizeOf);
|
||||
mGlyphWidths->ShallowSizeOfIncludingThis(aMallocSizeOf);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -185,7 +185,7 @@ protected:
|
||||
nsTHashtable<nsStringHashKey> mSkipSpaceLookupCheckFamilies;
|
||||
|
||||
private:
|
||||
nsRefPtrHashtable<nsStringHashKey, gfxFontFamily> mHiddenFontFamilies;
|
||||
FontFamilyTable mHiddenFontFamilies;
|
||||
};
|
||||
|
||||
#endif /* GFX_FT2FONTLIST_H */
|
||||
|
||||
@@ -218,7 +218,7 @@ gfxFT2Font::AddSizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf,
|
||||
{
|
||||
gfxFont::AddSizeOfExcludingThis(aMallocSizeOf, aSizes);
|
||||
aSizes->mFontInstances +=
|
||||
mCharGlyphCache.SizeOfExcludingThis(nullptr, aMallocSizeOf);
|
||||
mCharGlyphCache.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
+4
-18
@@ -312,30 +312,16 @@ gfxFontCache::FlushShapedWordCaches()
|
||||
}
|
||||
}
|
||||
|
||||
/*static*/
|
||||
size_t
|
||||
gfxFontCache::AddSizeOfFontEntryExcludingThis(HashEntry* aHashEntry,
|
||||
MallocSizeOf aMallocSizeOf,
|
||||
void* aUserArg)
|
||||
{
|
||||
HashEntry *entry = static_cast<HashEntry*>(aHashEntry);
|
||||
FontCacheSizes *sizes = static_cast<FontCacheSizes*>(aUserArg);
|
||||
entry->mFont->AddSizeOfExcludingThis(aMallocSizeOf, sizes);
|
||||
|
||||
// The entry's size is recorded in the |sizes| parameter, so we return zero
|
||||
// here to the hashtable enumerator.
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
gfxFontCache::AddSizeOfExcludingThis(MallocSizeOf aMallocSizeOf,
|
||||
FontCacheSizes* aSizes) const
|
||||
{
|
||||
// TODO: add the overhead of the expiration tracker (generation arrays)
|
||||
|
||||
aSizes->mFontInstances +=
|
||||
mFonts.SizeOfExcludingThis(AddSizeOfFontEntryExcludingThis,
|
||||
aMallocSizeOf, aSizes);
|
||||
aSizes->mFontInstances += mFonts.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
||||
for (auto iter = mFonts.ConstIter(); !iter.Done(); iter.Next()) {
|
||||
iter.Get()->mFont->AddSizeOfExcludingThis(aMallocSizeOf, aSizes);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -387,10 +387,6 @@ protected:
|
||||
gfxFont* mFont;
|
||||
};
|
||||
|
||||
static size_t AddSizeOfFontEntryExcludingThis(HashEntry* aHashEntry,
|
||||
mozilla::MallocSizeOf aMallocSizeOf,
|
||||
void* aUserArg);
|
||||
|
||||
nsTHashtable<HashEntry> mFonts;
|
||||
|
||||
static void WordCacheExpirationTimerCallback(nsITimer* aTimer, void* aCache);
|
||||
|
||||
@@ -503,7 +503,7 @@ gfxGDIFont::AddSizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf,
|
||||
aSizes->mFontInstances += aMallocSizeOf(mMetrics);
|
||||
if (mGlyphWidths) {
|
||||
aSizes->mFontInstances +=
|
||||
mGlyphWidths->SizeOfIncludingThis(nullptr, aMallocSizeOf);
|
||||
mGlyphWidths->ShallowSizeOfIncludingThis(aMallocSizeOf);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -943,8 +943,7 @@ gfxGDIFontList::AddSizeOfExcludingThis(MallocSizeOf aMallocSizeOf,
|
||||
{
|
||||
gfxPlatformFontList::AddSizeOfExcludingThis(aMallocSizeOf, aSizes);
|
||||
aSizes->mFontListSize +=
|
||||
mFontSubstitutes.SizeOfExcludingThis(SizeOfFamilyNameEntryExcludingThis,
|
||||
aMallocSizeOf);
|
||||
SizeOfFontFamilyTableExcludingThis(mFontSubstitutes, aMallocSizeOf);
|
||||
aSizes->mFontListSize +=
|
||||
mNonExistingFonts.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
||||
for (uint32_t i = 0; i < mNonExistingFonts.Length(); ++i) {
|
||||
|
||||
@@ -348,9 +348,7 @@ private:
|
||||
void ActivateBundledFonts();
|
||||
#endif
|
||||
|
||||
typedef nsRefPtrHashtable<nsStringHashKey, gfxFontFamily> FontTable;
|
||||
|
||||
FontTable mFontSubstitutes;
|
||||
FontFamilyTable mFontSubstitutes;
|
||||
nsTArray<nsString> mNonExistingFonts;
|
||||
};
|
||||
|
||||
|
||||
@@ -143,7 +143,7 @@ size_t
|
||||
gfxGlyphExtents::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const
|
||||
{
|
||||
return mContainedGlyphWidths.SizeOfExcludingThis(aMallocSizeOf) +
|
||||
mTightGlyphExtents.SizeOfExcludingThis(nullptr, aMallocSizeOf);
|
||||
mTightGlyphExtents.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
||||
}
|
||||
|
||||
size_t
|
||||
|
||||
@@ -1038,72 +1038,34 @@ gfxPlatformFontList::RebuildLocalFonts()
|
||||
|
||||
// Support for memory reporting
|
||||
|
||||
static size_t
|
||||
SizeOfFamilyEntryExcludingThis(const nsAString& aKey,
|
||||
const nsRefPtr<gfxFontFamily>& aFamily,
|
||||
MallocSizeOf aMallocSizeOf,
|
||||
void* aUserArg)
|
||||
{
|
||||
FontListSizes *sizes = static_cast<FontListSizes*>(aUserArg);
|
||||
aFamily->AddSizeOfExcludingThis(aMallocSizeOf, sizes);
|
||||
|
||||
sizes->mFontListSize += aKey.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
|
||||
|
||||
// we return zero here because the measurements have been added directly
|
||||
// to the relevant fields of the FontListSizes record
|
||||
return 0;
|
||||
}
|
||||
|
||||
// this is also used by subclasses that hold additional hashes of family names
|
||||
// this is also used by subclasses that hold additional font tables
|
||||
/*static*/ size_t
|
||||
gfxPlatformFontList::SizeOfFamilyNameEntryExcludingThis
|
||||
(const nsAString& aKey,
|
||||
const nsRefPtr<gfxFontFamily>& aFamily,
|
||||
MallocSizeOf aMallocSizeOf,
|
||||
void* aUserArg)
|
||||
gfxPlatformFontList::SizeOfFontFamilyTableExcludingThis(
|
||||
const FontFamilyTable& aTable,
|
||||
MallocSizeOf aMallocSizeOf)
|
||||
{
|
||||
// we don't count the size of the family here, because this is an *extra*
|
||||
// reference to a family that will have already been counted in the main list
|
||||
return aKey.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
|
||||
size_t n = aTable.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
||||
for (auto iter = aTable.ConstIter(); !iter.Done(); iter.Next()) {
|
||||
// We don't count the size of the family here, because this is an
|
||||
// *extra* reference to a family that will have already been counted in
|
||||
// the main list.
|
||||
n += iter.Key().SizeOfExcludingThisIfUnshared(aMallocSizeOf);
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
static size_t
|
||||
SizeOfFontNameEntryExcludingThis(const nsAString& aKey,
|
||||
const nsRefPtr<gfxFontEntry>& aFont,
|
||||
MallocSizeOf aMallocSizeOf,
|
||||
void* aUserArg)
|
||||
/*static*/ size_t
|
||||
gfxPlatformFontList::SizeOfFontEntryTableExcludingThis(
|
||||
const FontEntryTable& aTable,
|
||||
MallocSizeOf aMallocSizeOf)
|
||||
{
|
||||
// the font itself is counted by its owning family; here we only care about
|
||||
// the name stored in the hashtable key
|
||||
return aKey.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
|
||||
}
|
||||
|
||||
static size_t
|
||||
SizeOfPrefFontEntryExcludingThis
|
||||
(const uint32_t& aKey,
|
||||
const nsTArray<nsRefPtr<gfxFontFamily> >& aList,
|
||||
MallocSizeOf aMallocSizeOf,
|
||||
void* aUserArg)
|
||||
{
|
||||
// again, we only care about the size of the array itself; we don't follow
|
||||
// the refPtrs stored in it, because they point to entries already owned
|
||||
// and accounted-for by the main font list
|
||||
return aList.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
||||
}
|
||||
|
||||
static size_t
|
||||
SizeOfSharedCmapExcludingThis(CharMapHashKey* aHashEntry,
|
||||
MallocSizeOf aMallocSizeOf,
|
||||
void* aUserArg)
|
||||
{
|
||||
FontListSizes *sizes = static_cast<FontListSizes*>(aUserArg);
|
||||
|
||||
uint32_t size = aHashEntry->GetKey()->SizeOfIncludingThis(aMallocSizeOf);
|
||||
sizes->mCharMapsSize += size;
|
||||
|
||||
// we return zero here because the measurements have been added directly
|
||||
// to the relevant fields of the FontListSizes record
|
||||
return 0;
|
||||
size_t n = aTable.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
||||
for (auto iter = aTable.ConstIter(); !iter.Done(); iter.Next()) {
|
||||
// The font itself is counted by its owning family; here we only care
|
||||
// about the names stored in the hashtable keys.
|
||||
n += iter.Key().SizeOfExcludingThisIfUnshared(aMallocSizeOf);
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1111,20 +1073,23 @@ gfxPlatformFontList::AddSizeOfExcludingThis(MallocSizeOf aMallocSizeOf,
|
||||
FontListSizes* aSizes) const
|
||||
{
|
||||
aSizes->mFontListSize +=
|
||||
mFontFamilies.SizeOfExcludingThis(SizeOfFamilyEntryExcludingThis,
|
||||
aMallocSizeOf, aSizes);
|
||||
mFontFamilies.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
||||
for (auto iter = mFontFamilies.ConstIter(); !iter.Done(); iter.Next()) {
|
||||
aSizes->mFontListSize +=
|
||||
iter.Key().SizeOfExcludingThisIfUnshared(aMallocSizeOf);
|
||||
iter.Data()->AddSizeOfIncludingThis(aMallocSizeOf, aSizes);
|
||||
}
|
||||
|
||||
aSizes->mFontListSize +=
|
||||
mOtherFamilyNames.SizeOfExcludingThis(SizeOfFamilyNameEntryExcludingThis,
|
||||
aMallocSizeOf);
|
||||
SizeOfFontFamilyTableExcludingThis(mOtherFamilyNames, aMallocSizeOf);
|
||||
|
||||
if (mExtraNames) {
|
||||
aSizes->mFontListSize +=
|
||||
mExtraNames->mFullnames.SizeOfExcludingThis(SizeOfFontNameEntryExcludingThis,
|
||||
aMallocSizeOf);
|
||||
SizeOfFontEntryTableExcludingThis(mExtraNames->mFullnames,
|
||||
aMallocSizeOf);
|
||||
aSizes->mFontListSize +=
|
||||
mExtraNames->mPostscriptNames.SizeOfExcludingThis(SizeOfFontNameEntryExcludingThis,
|
||||
aMallocSizeOf);
|
||||
SizeOfFontEntryTableExcludingThis(mExtraNames->mPostscriptNames,
|
||||
aMallocSizeOf);
|
||||
}
|
||||
|
||||
aSizes->mFontListSize +=
|
||||
@@ -1133,15 +1098,24 @@ gfxPlatformFontList::AddSizeOfExcludingThis(MallocSizeOf aMallocSizeOf,
|
||||
mFontFamiliesToLoad.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
||||
|
||||
aSizes->mFontListSize +=
|
||||
mPrefFonts.SizeOfExcludingThis(SizeOfPrefFontEntryExcludingThis,
|
||||
aMallocSizeOf);
|
||||
mPrefFonts.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
||||
for (auto iter = mPrefFonts.ConstIter(); !iter.Done(); iter.Next()) {
|
||||
// Again, we only care about the size of the array itself; we don't
|
||||
// follow the refPtrs stored in it, because they point to entries
|
||||
// already owned and accounted-for by the main font list.
|
||||
aSizes->mFontListSize +=
|
||||
iter.Data().ShallowSizeOfExcludingThis(aMallocSizeOf);
|
||||
}
|
||||
|
||||
aSizes->mFontListSize +=
|
||||
mBadUnderlineFamilyNames.SizeOfExcludingThis(aMallocSizeOf);
|
||||
|
||||
aSizes->mFontListSize +=
|
||||
mSharedCmaps.SizeOfExcludingThis(SizeOfSharedCmapExcludingThis,
|
||||
aMallocSizeOf, aSizes);
|
||||
mSharedCmaps.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
||||
for (auto iter = mSharedCmaps.ConstIter(); !iter.Done(); iter.Next()) {
|
||||
aSizes->mCharMapsSize +=
|
||||
iter.Get()->GetKey()->SizeOfIncludingThis(aMallocSizeOf);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -296,24 +296,28 @@ protected:
|
||||
|
||||
void RebuildLocalFonts();
|
||||
|
||||
// used by memory reporter to accumulate sizes of family names in the hash
|
||||
typedef nsRefPtrHashtable<nsStringHashKey, gfxFontFamily> FontFamilyTable;
|
||||
typedef nsRefPtrHashtable<nsStringHashKey, gfxFontEntry> FontEntryTable;
|
||||
|
||||
// used by memory reporter to accumulate sizes of family names in the table
|
||||
static size_t
|
||||
SizeOfFamilyNameEntryExcludingThis(const nsAString& aKey,
|
||||
const nsRefPtr<gfxFontFamily>& aFamily,
|
||||
mozilla::MallocSizeOf aMallocSizeOf,
|
||||
void* aUserArg);
|
||||
SizeOfFontFamilyTableExcludingThis(const FontFamilyTable& aTable,
|
||||
mozilla::MallocSizeOf aMallocSizeOf);
|
||||
static size_t
|
||||
SizeOfFontEntryTableExcludingThis(const FontEntryTable& aTable,
|
||||
mozilla::MallocSizeOf aMallocSizeOf);
|
||||
|
||||
// canonical family name ==> family entry (unique, one name per family entry)
|
||||
nsRefPtrHashtable<nsStringHashKey, gfxFontFamily> mFontFamilies;
|
||||
FontFamilyTable mFontFamilies;
|
||||
|
||||
#if defined(XP_MACOSX)
|
||||
// hidden system fonts used within UI elements
|
||||
nsRefPtrHashtable<nsStringHashKey, gfxFontFamily> mSystemFontFamilies;
|
||||
FontFamilyTable mSystemFontFamilies;
|
||||
#endif
|
||||
|
||||
// other family name ==> family entry (not unique, can have multiple names per
|
||||
// family entry, only names *other* than the canonical names are stored here)
|
||||
nsRefPtrHashtable<nsStringHashKey, gfxFontFamily> mOtherFamilyNames;
|
||||
FontFamilyTable mOtherFamilyNames;
|
||||
|
||||
// flag set after InitOtherFamilyNames is called upon first name lookup miss
|
||||
bool mOtherFamilyNamesInitialized;
|
||||
@@ -323,10 +327,11 @@ protected:
|
||||
|
||||
struct ExtraNames {
|
||||
ExtraNames() : mFullnames(64), mPostscriptNames(64) {}
|
||||
|
||||
// fullname ==> font entry (unique, one name per font entry)
|
||||
nsRefPtrHashtable<nsStringHashKey, gfxFontEntry> mFullnames;
|
||||
FontEntryTable mFullnames;
|
||||
// Postscript name ==> font entry (unique, one name per font entry)
|
||||
nsRefPtrHashtable<nsStringHashKey, gfxFontEntry> mPostscriptNames;
|
||||
FontEntryTable mPostscriptNames;
|
||||
};
|
||||
nsAutoPtr<ExtraNames> mExtraNames;
|
||||
|
||||
|
||||
+42
-40
@@ -626,6 +626,30 @@ struct GCMethods<JSFunction*>
|
||||
}
|
||||
};
|
||||
|
||||
inline RootLists&
|
||||
RootListsForRootingContext(JSContext* cx)
|
||||
{
|
||||
return ContextFriendFields::get(cx)->roots;
|
||||
}
|
||||
|
||||
inline RootLists&
|
||||
RootListsForRootingContext(js::ContextFriendFields* cx)
|
||||
{
|
||||
return cx->roots;
|
||||
}
|
||||
|
||||
inline RootLists&
|
||||
RootListsForRootingContext(JSRuntime* rt)
|
||||
{
|
||||
return PerThreadDataFriendFields::getMainThread(rt)->roots;
|
||||
}
|
||||
|
||||
inline RootLists&
|
||||
RootListsForRootingContext(js::PerThreadDataFriendFields* pt)
|
||||
{
|
||||
return pt->roots;
|
||||
}
|
||||
|
||||
} /* namespace js */
|
||||
|
||||
namespace JS {
|
||||
@@ -717,19 +741,6 @@ class MOZ_STACK_CLASS Rooted : public js::RootedBase<T>
|
||||
*stack = reinterpret_cast<Rooted<void*>*>(this);
|
||||
}
|
||||
|
||||
static js::RootLists& rootListsForRootingContext(JSContext* cx) {
|
||||
return js::ContextFriendFields::get(cx)->roots;
|
||||
}
|
||||
static js::RootLists& rootListsForRootingContext(js::ContextFriendFields* cx) {
|
||||
return cx->roots;
|
||||
}
|
||||
static js::RootLists& rootListsForRootingContext(JSRuntime* rt) {
|
||||
return js::PerThreadDataFriendFields::getMainThread(rt)->roots;
|
||||
}
|
||||
static js::RootLists& rootListsForRootingContext(js::PerThreadDataFriendFields* pt) {
|
||||
return pt->roots;
|
||||
}
|
||||
|
||||
public:
|
||||
template <typename RootingContext>
|
||||
explicit Rooted(const RootingContext& cx
|
||||
@@ -737,7 +748,7 @@ class MOZ_STACK_CLASS Rooted : public js::RootedBase<T>
|
||||
: ptr(js::GCMethods<T>::initial())
|
||||
{
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
|
||||
registerWithRootLists(rootListsForRootingContext(cx));
|
||||
registerWithRootLists(js::RootListsForRootingContext(cx));
|
||||
}
|
||||
|
||||
template <typename RootingContext, typename S>
|
||||
@@ -746,7 +757,7 @@ class MOZ_STACK_CLASS Rooted : public js::RootedBase<T>
|
||||
: ptr(mozilla::Forward<S>(initial))
|
||||
{
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
|
||||
registerWithRootLists(rootListsForRootingContext(cx));
|
||||
registerWithRootLists(js::RootListsForRootingContext(cx));
|
||||
}
|
||||
|
||||
~Rooted() {
|
||||
@@ -1074,20 +1085,18 @@ class PersistentRooted : public js::PersistentRootedBase<T>,
|
||||
public:
|
||||
PersistentRooted() : ptr(js::GCMethods<T>::initial()) {}
|
||||
|
||||
explicit PersistentRooted(JSContext* cx) {
|
||||
init(cx);
|
||||
template <typename RootingContext>
|
||||
explicit PersistentRooted(const RootingContext& cx)
|
||||
: ptr(js::GCMethods<T>::initial())
|
||||
{
|
||||
registerWithRootLists(js::RootListsForRootingContext(cx));
|
||||
}
|
||||
|
||||
PersistentRooted(JSContext* cx, T initial) {
|
||||
init(cx, initial);
|
||||
}
|
||||
|
||||
explicit PersistentRooted(JSRuntime* rt) {
|
||||
init(rt);
|
||||
}
|
||||
|
||||
PersistentRooted(JSRuntime* rt, T initial) {
|
||||
init(rt, initial);
|
||||
template <typename RootingContext, typename U>
|
||||
PersistentRooted(const RootingContext& cx, U&& initial)
|
||||
: ptr(mozilla::Forward<U>(initial))
|
||||
{
|
||||
registerWithRootLists(js::RootListsForRootingContext(cx));
|
||||
}
|
||||
|
||||
PersistentRooted(const PersistentRooted& rhs)
|
||||
@@ -1109,22 +1118,15 @@ class PersistentRooted : public js::PersistentRootedBase<T>,
|
||||
return ListBase::isInList();
|
||||
}
|
||||
|
||||
void init(JSContext* cx) {
|
||||
template <typename RootingContext>
|
||||
void init(const RootingContext& cx) {
|
||||
init(cx, js::GCMethods<T>::initial());
|
||||
}
|
||||
|
||||
void init(JSContext* cx, T initial) {
|
||||
ptr = initial;
|
||||
registerWithRootLists(js::ContextFriendFields::get(cx)->roots);
|
||||
}
|
||||
|
||||
void init(JSRuntime* rt) {
|
||||
init(rt, js::GCMethods<T>::initial());
|
||||
}
|
||||
|
||||
void init(JSRuntime* rt, T initial) {
|
||||
ptr = initial;
|
||||
registerWithRootLists(js::PerThreadDataFriendFields::getMainThread(rt)->roots);
|
||||
template <typename RootingContext, typename U>
|
||||
void init(const RootingContext& cx, U&& initial) {
|
||||
ptr = mozilla::Forward<U>(initial);
|
||||
registerWithRootLists(js::RootListsForRootingContext(cx));
|
||||
}
|
||||
|
||||
void reset() {
|
||||
|
||||
@@ -349,12 +349,6 @@ js::gc::GCRuntime::markRuntime(JSTracer* trc, TraceOrMarkRuntime traceOrMark)
|
||||
MarkPersistentRootedChains(trc);
|
||||
}
|
||||
|
||||
if (rt->asyncStackForNewActivations)
|
||||
TraceRoot(trc, &rt->asyncStackForNewActivations, "asyncStackForNewActivations");
|
||||
|
||||
if (rt->asyncCauseForNewActivations)
|
||||
TraceRoot(trc, &rt->asyncCauseForNewActivations, "asyncCauseForNewActivations");
|
||||
|
||||
if (rt->scriptAndCountsVector) {
|
||||
ScriptAndCountsVector& vec = *rt->scriptAndCountsVector;
|
||||
for (size_t i = 0; i < vec.length(); i++)
|
||||
|
||||
@@ -803,6 +803,22 @@ BaselineCompiler::emitDebugTrap()
|
||||
return appendICEntry(ICEntry::Kind_DebugTrap, masm.currentOffset());
|
||||
}
|
||||
|
||||
void
|
||||
BaselineCompiler::emitCoverage(jsbytecode* pc)
|
||||
{
|
||||
double* counterAddr = &script->getPCCounts(pc).numExec();
|
||||
AllocatableRegisterSet regs(RegisterSet::Volatile());
|
||||
Register counterAddrReg = R2.scratchReg();
|
||||
FloatRegister counter = regs.takeAnyFloat();
|
||||
FloatRegister one = regs.takeAnyFloat();
|
||||
|
||||
masm.movePtr(ImmPtr(counterAddr), counterAddrReg);
|
||||
masm.loadDouble(Address(counterAddrReg, 0), counter);
|
||||
masm.loadConstantDouble(1.0, one);
|
||||
masm.addDouble(one, counter);
|
||||
masm.storeDouble(counter, Address(counterAddrReg, 0));
|
||||
}
|
||||
|
||||
#ifdef JS_TRACE_LOGGING
|
||||
bool
|
||||
BaselineCompiler::emitTraceLoggerEnter()
|
||||
@@ -900,6 +916,7 @@ BaselineCompiler::emitBody()
|
||||
bool lastOpUnreachable = false;
|
||||
uint32_t emittedOps = 0;
|
||||
mozilla::DebugOnly<jsbytecode*> prevpc = pc;
|
||||
bool compileCoverage = script->hasScriptCounts();
|
||||
|
||||
while (true) {
|
||||
JSOp op = JSOp(*pc);
|
||||
@@ -954,6 +971,10 @@ BaselineCompiler::emitBody()
|
||||
if (compileDebugInstrumentation_ && !emitDebugTrap())
|
||||
return Method_Error;
|
||||
|
||||
// Emit code coverage code, to fill the same data as the interpreter.
|
||||
if (compileCoverage)
|
||||
emitCoverage(pc);
|
||||
|
||||
switch (op) {
|
||||
default:
|
||||
JitSpew(JitSpew_BaselineAbort, "Unhandled op: %s", js_CodeName[op]);
|
||||
|
||||
@@ -264,6 +264,7 @@ class BaselineCompiler : public BaselineCompilerSpecific
|
||||
void emitIsDebuggeeCheck();
|
||||
bool emitDebugPrologue();
|
||||
bool emitDebugTrap();
|
||||
void emitCoverage(jsbytecode* pc);
|
||||
bool emitTraceLoggerEnter();
|
||||
bool emitTraceLoggerExit();
|
||||
|
||||
|
||||
+22
-11
@@ -469,6 +469,8 @@ PrepareForDebuggerOnIonCompilationHook(JSContext* cx, jit::MIRGraph& graph,
|
||||
void
|
||||
jit::FinishOffThreadBuilder(JSContext* cx, IonBuilder* builder)
|
||||
{
|
||||
MOZ_ASSERT(HelperThreadState().isLocked());
|
||||
|
||||
// Clean the references to the pending IonBuilder, if we just finished it.
|
||||
if (builder->script()->baselineScript()->hasPendingIonBuilder() &&
|
||||
builder->script()->baselineScript()->pendingIonBuilder() == builder)
|
||||
@@ -574,18 +576,24 @@ class AutoLazyLinkExitFrame
|
||||
void
|
||||
jit::LazyLink(JSContext* cx, HandleScript calleeScript)
|
||||
{
|
||||
// Get the pending builder from the Ion frame.
|
||||
MOZ_ASSERT(calleeScript->hasBaselineScript());
|
||||
IonBuilder* builder = calleeScript->baselineScript()->pendingIonBuilder();
|
||||
calleeScript->baselineScript()->removePendingIonBuilder(calleeScript);
|
||||
IonBuilder* builder;
|
||||
|
||||
{
|
||||
AutoLockHelperThreadState lock;
|
||||
|
||||
// Get the pending builder from the Ion frame.
|
||||
MOZ_ASSERT(calleeScript->hasBaselineScript());
|
||||
builder = calleeScript->baselineScript()->pendingIonBuilder();
|
||||
calleeScript->baselineScript()->removePendingIonBuilder(calleeScript);
|
||||
|
||||
// Remove from pending.
|
||||
builder->removeFrom(HelperThreadState().ionLazyLinkList());
|
||||
}
|
||||
|
||||
// See PrepareForDebuggerOnIonCompilationHook
|
||||
AutoScriptVector debugScripts(cx);
|
||||
OnIonCompilationInfo info(builder->alloc().lifoAlloc());
|
||||
|
||||
// Remove from pending.
|
||||
builder->removeFrom(HelperThreadState().ionLazyLinkList());
|
||||
|
||||
{
|
||||
AutoEnterAnalysis enterTypes(cx);
|
||||
if (!LinkBackgroundCodeGen(cx, builder, &debugScripts, &info)) {
|
||||
@@ -599,7 +607,10 @@ jit::LazyLink(JSContext* cx, HandleScript calleeScript)
|
||||
if (info.filled())
|
||||
Debugger::onIonCompilation(cx, debugScripts, info.graph);
|
||||
|
||||
FinishOffThreadBuilder(cx, builder);
|
||||
{
|
||||
AutoLockHelperThreadState lock;
|
||||
FinishOffThreadBuilder(cx, builder);
|
||||
}
|
||||
|
||||
MOZ_ASSERT(calleeScript->hasBaselineScript());
|
||||
MOZ_ASSERT(calleeScript->baselineOrIonRawPointer());
|
||||
@@ -2592,15 +2603,15 @@ jit::SetEnterJitData(JSContext* cx, EnterJitData& data, RunState& state, AutoVal
|
||||
ScriptFrameIter iter(cx);
|
||||
if (iter.isFunctionFrame())
|
||||
data.calleeToken = CalleeToToken(iter.callee(cx), /* constructing = */ false);
|
||||
|
||||
|
||||
// Push newTarget onto the stack, as well as Argv.
|
||||
if (!vals.reserve(2))
|
||||
return false;
|
||||
|
||||
|
||||
data.maxArgc = 2;
|
||||
data.maxArgv = vals.begin();
|
||||
vals.infallibleAppend(state.asExecute()->thisv());
|
||||
if (iter.isFunctionFrame()) {
|
||||
if (iter.isFunctionFrame()) {
|
||||
if (state.asExecute()->newTarget().isNull())
|
||||
vals.infallibleAppend(iter.newTarget());
|
||||
else
|
||||
|
||||
+198
-184
@@ -68,7 +68,7 @@ ReadFrameSlot(JitFrameLayout* fp, int32_t slot)
|
||||
static inline void
|
||||
WriteFrameSlot(JitFrameLayout* fp, int32_t slot, uintptr_t value)
|
||||
{
|
||||
*(uintptr_t*) AddressOfFrameSlot(fp, slot) = value;
|
||||
*(uintptr_t*) AddressOfFrameSlot(fp, slot) = value;
|
||||
}
|
||||
|
||||
static inline double
|
||||
@@ -362,9 +362,9 @@ JitFrameIterator::machineState() const
|
||||
for (GeneralRegisterBackwardIterator iter(reader.allGprSpills()); iter.more(); iter++)
|
||||
machine.setRegisterLocation(*iter, --spill);
|
||||
|
||||
uint8_t *spillAlign = alignDoubleSpillWithOffset(reinterpret_cast<uint8_t *>(spill), 0);
|
||||
uint8_t* spillAlign = alignDoubleSpillWithOffset(reinterpret_cast<uint8_t *>(spill), 0);
|
||||
|
||||
char *floatSpill = reinterpret_cast<char *>(spillAlign);
|
||||
char* floatSpill = reinterpret_cast<char*>(spillAlign);
|
||||
FloatRegisterSet fregs = reader.allFloatSpills().set();
|
||||
fregs = fregs.reduceSetForPush();
|
||||
for (FloatRegisterBackwardIterator iter(fregs); iter.more(); iter++) {
|
||||
@@ -389,7 +389,7 @@ NumArgAndLocalSlots(const InlineFrameIterator& frame)
|
||||
}
|
||||
|
||||
static void
|
||||
CloseLiveIterator(JSContext* cx, const InlineFrameIterator& frame, uint32_t stackSlot)
|
||||
CloseLiveIteratorIon(JSContext* cx, const InlineFrameIterator& frame, uint32_t stackSlot)
|
||||
{
|
||||
SnapshotIterator si = frame.snapshotIterator();
|
||||
|
||||
@@ -408,6 +408,20 @@ CloseLiveIterator(JSContext* cx, const InlineFrameIterator& frame, uint32_t stac
|
||||
UnwindIteratorForUncatchableException(cx, obj);
|
||||
}
|
||||
|
||||
class IgnoreStackDepthOp
|
||||
{
|
||||
public:
|
||||
uint32_t operator()() { return UINT32_MAX; }
|
||||
};
|
||||
|
||||
class TryNoteIterIon : public TryNoteIter<IgnoreStackDepthOp>
|
||||
{
|
||||
public:
|
||||
TryNoteIterIon(JSContext* cx, JSScript* script, jsbytecode* pc)
|
||||
: TryNoteIter(cx, script, pc, IgnoreStackDepthOp())
|
||||
{ }
|
||||
};
|
||||
|
||||
static void
|
||||
HandleExceptionIon(JSContext* cx, const InlineFrameIterator& frame, ResumeFromException* rfe,
|
||||
bool* overrecursed)
|
||||
@@ -460,23 +474,8 @@ HandleExceptionIon(JSContext* cx, const InlineFrameIterator& frame, ResumeFromEx
|
||||
if (!script->hasTrynotes())
|
||||
return;
|
||||
|
||||
uint32_t base = NumArgAndLocalSlots(frame);
|
||||
SnapshotIterator si = frame.snapshotIterator();
|
||||
MOZ_ASSERT(si.numAllocations() >= base);
|
||||
const uint32_t stackDepth = si.numAllocations() - base;
|
||||
|
||||
JSTryNote* tn = script->trynotes()->vector;
|
||||
JSTryNote* tnEnd = tn + script->trynotes()->length;
|
||||
|
||||
uint32_t pcOffset = uint32_t(pc - script->main());
|
||||
for (; tn != tnEnd; ++tn) {
|
||||
if (pcOffset < tn->start)
|
||||
continue;
|
||||
if (pcOffset >= tn->start + tn->length)
|
||||
continue;
|
||||
|
||||
if (tn->stackDepth > stackDepth)
|
||||
continue;
|
||||
for (TryNoteIterIon tni(cx, script, pc); !tni.done(); ++tni) {
|
||||
JSTryNote* tn = *tni;
|
||||
|
||||
switch (tn->kind) {
|
||||
case JSTRY_FOR_IN: {
|
||||
@@ -484,7 +483,7 @@ HandleExceptionIon(JSContext* cx, const InlineFrameIterator& frame, ResumeFromEx
|
||||
MOZ_ASSERT(tn->stackDepth > 0);
|
||||
|
||||
uint32_t localSlot = tn->stackDepth;
|
||||
CloseLiveIterator(cx, frame, localSlot);
|
||||
CloseLiveIteratorIon(cx, frame, localSlot);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -518,50 +517,49 @@ HandleExceptionIon(JSContext* cx, const InlineFrameIterator& frame, ResumeFromEx
|
||||
}
|
||||
|
||||
static void
|
||||
ForcedReturn(JSContext* cx, const JitFrameIterator& frame, jsbytecode* pc,
|
||||
ResumeFromException* rfe, bool* calledDebugEpilogue)
|
||||
OnLeaveBaselineFrame(JSContext* cx, const JitFrameIterator& frame, jsbytecode* pc,
|
||||
ResumeFromException* rfe, bool frameOk)
|
||||
{
|
||||
BaselineFrame* baselineFrame = frame.baselineFrame();
|
||||
MOZ_ASSERT(baselineFrame->hasReturnValue());
|
||||
|
||||
if (jit::DebugEpilogue(cx, baselineFrame, pc, true)) {
|
||||
if (jit::DebugEpilogue(cx, baselineFrame, pc, frameOk)) {
|
||||
rfe->kind = ResumeFromException::RESUME_FORCED_RETURN;
|
||||
rfe->framePointer = frame.fp() - BaselineFrame::FramePointerOffset;
|
||||
rfe->stackPointer = reinterpret_cast<uint8_t*>(baselineFrame);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// DebugEpilogue threw an exception. Propagate to the caller frame.
|
||||
*calledDebugEpilogue = true;
|
||||
static inline void
|
||||
ForcedReturn(JSContext* cx, const JitFrameIterator& frame, jsbytecode* pc,
|
||||
ResumeFromException* rfe)
|
||||
{
|
||||
OnLeaveBaselineFrame(cx, frame, pc, rfe, true);
|
||||
}
|
||||
|
||||
static inline void
|
||||
BaselineFrameAndStackPointersFromTryNote(JSTryNote* tn, const JitFrameIterator& frame,
|
||||
uint8_t** framePointer, uint8_t** stackPointer)
|
||||
{
|
||||
JSScript* script = frame.baselineFrame()->script();
|
||||
*framePointer = frame.fp() - BaselineFrame::FramePointerOffset;
|
||||
*stackPointer = *framePointer - BaselineFrame::Size() -
|
||||
(script->nfixed() + tn->stackDepth) * sizeof(Value);
|
||||
}
|
||||
|
||||
static void
|
||||
HandleClosingGeneratorReturn(JSContext* cx, const JitFrameIterator& frame, jsbytecode* pc,
|
||||
jsbytecode* unwoundScopeToPc, ResumeFromException* rfe,
|
||||
bool* calledDebugEpilogue)
|
||||
SettleOnTryNote(JSContext* cx, JSTryNote *tn, const JitFrameIterator& frame,
|
||||
ScopeIter& si, ResumeFromException* rfe, jsbytecode** pc)
|
||||
{
|
||||
// If we're closing a legacy generator, we need to return to the caller
|
||||
// after executing the |finally| blocks. This is very similar to a forced
|
||||
// return from the debugger.
|
||||
RootedScript script(cx, frame.baselineFrame()->script());
|
||||
|
||||
if (!cx->isExceptionPending())
|
||||
return;
|
||||
RootedValue exception(cx);
|
||||
if (!cx->getPendingException(&exception))
|
||||
return;
|
||||
if (!exception.isMagic(JS_GENERATOR_CLOSING))
|
||||
return;
|
||||
// Unwind scope chain (pop block objects).
|
||||
if (cx->isExceptionPending())
|
||||
UnwindScope(cx, si, UnwindScopeToTryPc(script, tn));
|
||||
|
||||
cx->clearPendingException();
|
||||
SetReturnValueForClosingGenerator(cx, frame.baselineFrame());
|
||||
// Compute base pointer and stack pointer.
|
||||
BaselineFrameAndStackPointersFromTryNote(tn, frame, &rfe->framePointer, &rfe->stackPointer);
|
||||
|
||||
if (unwoundScopeToPc) {
|
||||
if (frame.baselineFrame()->isDebuggee())
|
||||
frame.baselineFrame()->setOverridePc(unwoundScopeToPc);
|
||||
pc = unwoundScopeToPc;
|
||||
}
|
||||
|
||||
ForcedReturn(cx, frame, pc, rfe, calledDebugEpilogue);
|
||||
// Compute the pc.
|
||||
*pc = script->main() + tn->start + tn->length;
|
||||
}
|
||||
|
||||
struct AutoBaselineHandlingException
|
||||
@@ -579,122 +577,101 @@ struct AutoBaselineHandlingException
|
||||
}
|
||||
};
|
||||
|
||||
static void
|
||||
HandleExceptionBaseline(JSContext* cx, const JitFrameIterator& frame, ResumeFromException* rfe,
|
||||
jsbytecode* pc, jsbytecode** unwoundScopeToPc, bool* calledDebugEpilogue)
|
||||
class BaselineFrameStackDepthOp
|
||||
{
|
||||
MOZ_ASSERT(frame.isBaselineJS());
|
||||
MOZ_ASSERT(!*calledDebugEpilogue);
|
||||
|
||||
// We may be propagating a forced return from the interrupt
|
||||
// callback, which cannot easily force a return.
|
||||
if (cx->isPropagatingForcedReturn()) {
|
||||
cx->clearPropagatingForcedReturn();
|
||||
ForcedReturn(cx, frame, pc, rfe, calledDebugEpilogue);
|
||||
return;
|
||||
BaselineFrame* frame_;
|
||||
public:
|
||||
explicit BaselineFrameStackDepthOp(BaselineFrame* frame)
|
||||
: frame_(frame)
|
||||
{ }
|
||||
uint32_t operator()() {
|
||||
MOZ_ASSERT(frame_->numValueSlots() >= frame_->script()->nfixed());
|
||||
return frame_->numValueSlots() - frame_->script()->nfixed();
|
||||
}
|
||||
};
|
||||
|
||||
RootedValue exception(cx);
|
||||
if (cx->isExceptionPending() && cx->compartment()->isDebuggee() &&
|
||||
!cx->isClosingGenerator())
|
||||
{
|
||||
switch (Debugger::onExceptionUnwind(cx, frame.baselineFrame())) {
|
||||
case JSTRAP_ERROR:
|
||||
// Uncatchable exception.
|
||||
MOZ_ASSERT(!cx->isExceptionPending());
|
||||
break;
|
||||
class TryNoteIterBaseline : public TryNoteIter<BaselineFrameStackDepthOp>
|
||||
{
|
||||
public:
|
||||
TryNoteIterBaseline(JSContext* cx, BaselineFrame* frame, jsbytecode* pc)
|
||||
: TryNoteIter(cx, frame->script(), pc, BaselineFrameStackDepthOp(frame))
|
||||
{ }
|
||||
};
|
||||
|
||||
case JSTRAP_CONTINUE:
|
||||
case JSTRAP_THROW:
|
||||
MOZ_ASSERT(cx->isExceptionPending());
|
||||
break;
|
||||
// Close all live iterators on a BaselineFrame due to exception unwinding. The
|
||||
// pc parameter is updated to where the scopes have been unwound to.
|
||||
static void
|
||||
CloseLiveIteratorsBaselineForUncatchableException(JSContext* cx, const JitFrameIterator& frame,
|
||||
jsbytecode* pc)
|
||||
{
|
||||
for (TryNoteIterBaseline tni(cx, frame.baselineFrame(), pc); !tni.done(); ++tni) {
|
||||
JSTryNote* tn = *tni;
|
||||
|
||||
case JSTRAP_RETURN:
|
||||
ForcedReturn(cx, frame, pc, rfe, calledDebugEpilogue);
|
||||
return;
|
||||
|
||||
default:
|
||||
MOZ_CRASH("Invalid trap status");
|
||||
if (tn->kind == JSTRY_FOR_IN) {
|
||||
uint8_t* framePointer;
|
||||
uint8_t* stackPointer;
|
||||
BaselineFrameAndStackPointersFromTryNote(tn, frame, &framePointer, &stackPointer);
|
||||
Value iterValue(*(Value*) stackPointer);
|
||||
RootedObject iterObject(cx, &iterValue.toObject());
|
||||
UnwindIteratorForUncatchableException(cx, iterObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
ProcessTryNotesBaseline(JSContext* cx, const JitFrameIterator& frame, ScopeIter& si,
|
||||
ResumeFromException* rfe, jsbytecode** pc)
|
||||
{
|
||||
RootedScript script(cx, frame.baselineFrame()->script());
|
||||
|
||||
if (!script->hasTrynotes()) {
|
||||
HandleClosingGeneratorReturn(cx, frame, pc, *unwoundScopeToPc, rfe, calledDebugEpilogue);
|
||||
return;
|
||||
}
|
||||
|
||||
JSTryNote* tn = script->trynotes()->vector;
|
||||
JSTryNote* tnEnd = tn + script->trynotes()->length;
|
||||
|
||||
uint32_t pcOffset = uint32_t(pc - script->main());
|
||||
ScopeIter si(cx, frame.baselineFrame(), pc);
|
||||
for (; tn != tnEnd; ++tn) {
|
||||
if (pcOffset < tn->start)
|
||||
continue;
|
||||
if (pcOffset >= tn->start + tn->length)
|
||||
continue;
|
||||
|
||||
// Skip if the try note's stack depth exceeds the frame's stack depth.
|
||||
// See the big comment in TryNoteIter::settle for more info.
|
||||
MOZ_ASSERT(frame.baselineFrame()->numValueSlots() >= script->nfixed());
|
||||
size_t stackDepth = frame.baselineFrame()->numValueSlots() - script->nfixed();
|
||||
if (tn->stackDepth > stackDepth)
|
||||
continue;
|
||||
|
||||
// Unwind scope chain (pop block objects).
|
||||
if (cx->isExceptionPending()) {
|
||||
*unwoundScopeToPc = UnwindScopeToTryPc(script, tn);
|
||||
UnwindScope(cx, si, *unwoundScopeToPc);
|
||||
}
|
||||
|
||||
// Compute base pointer and stack pointer.
|
||||
rfe->framePointer = frame.fp() - BaselineFrame::FramePointerOffset;
|
||||
rfe->stackPointer = rfe->framePointer - BaselineFrame::Size() -
|
||||
(script->nfixed() + tn->stackDepth) * sizeof(Value);
|
||||
for (TryNoteIterBaseline tni(cx, frame.baselineFrame(), *pc); !tni.done(); ++tni) {
|
||||
JSTryNote* tn = *tni;
|
||||
|
||||
MOZ_ASSERT(cx->isExceptionPending());
|
||||
switch (tn->kind) {
|
||||
case JSTRY_CATCH:
|
||||
if (cx->isExceptionPending()) {
|
||||
// If we're closing a legacy generator, we have to skip catch
|
||||
// blocks.
|
||||
if (cx->isClosingGenerator())
|
||||
continue;
|
||||
case JSTRY_CATCH: {
|
||||
// If we're closing a legacy generator, we have to skip catch
|
||||
// blocks.
|
||||
if (cx->isClosingGenerator())
|
||||
continue;
|
||||
|
||||
// Ion can compile try-catch, but bailing out to catch
|
||||
// exceptions is slow. Reset the warm-up counter so that if we
|
||||
// catch many exceptions we won't Ion-compile the script.
|
||||
script->resetWarmUpCounter();
|
||||
SettleOnTryNote(cx, tn, frame, si, rfe, pc);
|
||||
|
||||
// Resume at the start of the catch block.
|
||||
rfe->kind = ResumeFromException::RESUME_CATCH;
|
||||
jsbytecode* catchPC = script->main() + tn->start + tn->length;
|
||||
rfe->target = script->baselineScript()->nativeCodeForPC(script, catchPC);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
// Ion can compile try-catch, but bailing out to catch
|
||||
// exceptions is slow. Reset the warm-up counter so that if we
|
||||
// catch many exceptions we won't Ion-compile the script.
|
||||
script->resetWarmUpCounter();
|
||||
|
||||
case JSTRY_FINALLY:
|
||||
if (cx->isExceptionPending()) {
|
||||
rfe->kind = ResumeFromException::RESUME_FINALLY;
|
||||
jsbytecode* finallyPC = script->main() + tn->start + tn->length;
|
||||
rfe->target = script->baselineScript()->nativeCodeForPC(script, finallyPC);
|
||||
// Drop the exception instead of leaking cross compartment data.
|
||||
if (!cx->getPendingException(MutableHandleValue::fromMarkedLocation(&rfe->exception)))
|
||||
rfe->exception = UndefinedValue();
|
||||
cx->clearPendingException();
|
||||
return;
|
||||
}
|
||||
break;
|
||||
// Resume at the start of the catch block.
|
||||
rfe->kind = ResumeFromException::RESUME_CATCH;
|
||||
rfe->target = script->baselineScript()->nativeCodeForPC(script, *pc);
|
||||
return true;
|
||||
}
|
||||
|
||||
case JSTRY_FINALLY: {
|
||||
SettleOnTryNote(cx, tn, frame, si, rfe, pc);
|
||||
rfe->kind = ResumeFromException::RESUME_FINALLY;
|
||||
rfe->target = script->baselineScript()->nativeCodeForPC(script, *pc);
|
||||
// Drop the exception instead of leaking cross compartment data.
|
||||
if (!cx->getPendingException(MutableHandleValue::fromMarkedLocation(&rfe->exception)))
|
||||
rfe->exception = UndefinedValue();
|
||||
cx->clearPendingException();
|
||||
return true;
|
||||
}
|
||||
|
||||
case JSTRY_FOR_IN: {
|
||||
Value iterValue(* (Value*) rfe->stackPointer);
|
||||
uint8_t* framePointer;
|
||||
uint8_t* stackPointer;
|
||||
BaselineFrameAndStackPointersFromTryNote(tn, frame, &framePointer, &stackPointer);
|
||||
Value iterValue(*(Value*) stackPointer);
|
||||
RootedObject iterObject(cx, &iterValue.toObject());
|
||||
if (cx->isExceptionPending())
|
||||
UnwindIteratorForException(cx, iterObject);
|
||||
else
|
||||
UnwindIteratorForUncatchableException(cx, iterObject);
|
||||
if (!UnwindIteratorForException(cx, iterObject)) {
|
||||
// See comment in the JSTRY_FOR_IN case in Interpreter.cpp's
|
||||
// ProcessTryNotes.
|
||||
SettleOnTryNote(cx, tn, frame, si, rfe, pc);
|
||||
MOZ_ASSERT(**pc == JSOP_ENDITER);
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -706,8 +683,66 @@ HandleExceptionBaseline(JSContext* cx, const JitFrameIterator& frame, ResumeFrom
|
||||
MOZ_CRASH("Invalid try note");
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
HandleClosingGeneratorReturn(cx, frame, pc, *unwoundScopeToPc, rfe, calledDebugEpilogue);
|
||||
static void
|
||||
HandleExceptionBaseline(JSContext* cx, const JitFrameIterator& frame, ResumeFromException* rfe,
|
||||
jsbytecode* pc)
|
||||
{
|
||||
MOZ_ASSERT(frame.isBaselineJS());
|
||||
|
||||
// We may be propagating a forced return from the interrupt
|
||||
// callback, which cannot easily force a return.
|
||||
if (cx->isPropagatingForcedReturn()) {
|
||||
cx->clearPropagatingForcedReturn();
|
||||
ForcedReturn(cx, frame, pc, rfe);
|
||||
return;
|
||||
}
|
||||
|
||||
bool frameOk = false;
|
||||
RootedScript script(cx, frame.baselineFrame()->script());
|
||||
|
||||
again:
|
||||
if (cx->isExceptionPending()) {
|
||||
if (!cx->isClosingGenerator()) {
|
||||
switch (Debugger::onExceptionUnwind(cx, frame.baselineFrame())) {
|
||||
case JSTRAP_ERROR:
|
||||
// Uncatchable exception.
|
||||
MOZ_ASSERT(!cx->isExceptionPending());
|
||||
goto again;
|
||||
|
||||
case JSTRAP_CONTINUE:
|
||||
case JSTRAP_THROW:
|
||||
MOZ_ASSERT(cx->isExceptionPending());
|
||||
break;
|
||||
|
||||
case JSTRAP_RETURN:
|
||||
if (script->hasTrynotes())
|
||||
CloseLiveIteratorsBaselineForUncatchableException(cx, frame, pc);
|
||||
ForcedReturn(cx, frame, pc, rfe);
|
||||
return;
|
||||
|
||||
default:
|
||||
MOZ_CRASH("Invalid trap status");
|
||||
}
|
||||
}
|
||||
|
||||
if (script->hasTrynotes()) {
|
||||
ScopeIter si(cx, frame.baselineFrame(), pc);
|
||||
if (!ProcessTryNotesBaseline(cx, frame, si, rfe, &pc))
|
||||
goto again;
|
||||
if (rfe->kind != ResumeFromException::RESUME_ENTRY_FRAME)
|
||||
return;
|
||||
}
|
||||
|
||||
frameOk = HandleClosingGeneratorReturn(cx, frame.baselineFrame(), frameOk);
|
||||
frameOk = Debugger::onLeaveFrame(cx, frame.baselineFrame(), frameOk);
|
||||
} else if (script->hasTrynotes()) {
|
||||
CloseLiveIteratorsBaselineForUncatchableException(cx, frame, pc);
|
||||
}
|
||||
|
||||
OnLeaveBaselineFrame(cx, frame, pc, rfe, frameOk);
|
||||
}
|
||||
|
||||
struct AutoDeleteDebugModeOSRInfo
|
||||
@@ -832,12 +867,6 @@ HandleException(ResumeFromException* rfe)
|
||||
ionScript->decrementInvalidationCount(cx->runtime()->defaultFreeOp());
|
||||
|
||||
} else if (iter.isBaselineJS()) {
|
||||
// It's invalid to call DebugEpilogue twice for the same frame.
|
||||
bool calledDebugEpilogue = false;
|
||||
|
||||
// Remember the pc we unwound the scope to.
|
||||
jsbytecode* unwoundScopeToPc = nullptr;
|
||||
|
||||
// Set a flag on the frame to signal to DebugModeOSR that we're
|
||||
// handling an exception. Also ensure the frame has an override
|
||||
// pc. We clear the frame's override pc when we leave this block,
|
||||
@@ -854,7 +883,7 @@ HandleException(ResumeFromException* rfe)
|
||||
iter.baselineScriptAndPc(nullptr, &pc);
|
||||
AutoBaselineHandlingException handlingException(iter.baselineFrame(), pc);
|
||||
|
||||
HandleExceptionBaseline(cx, iter, rfe, pc, &unwoundScopeToPc, &calledDebugEpilogue);
|
||||
HandleExceptionBaseline(cx, iter, rfe, pc);
|
||||
|
||||
// If we are propagating an exception through a frame with
|
||||
// on-stack recompile info, we should free the allocated
|
||||
@@ -862,8 +891,11 @@ HandleException(ResumeFromException* rfe)
|
||||
// be returning to the recompile handler.
|
||||
AutoDeleteDebugModeOSRInfo deleteDebugModeOSRInfo(iter.baselineFrame());
|
||||
|
||||
if (rfe->kind != ResumeFromException::RESUME_ENTRY_FRAME)
|
||||
if (rfe->kind != ResumeFromException::RESUME_ENTRY_FRAME &&
|
||||
rfe->kind != ResumeFromException::RESUME_FORCED_RETURN)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
TraceLogStopEvent(logger, TraceLogger_Baseline);
|
||||
TraceLogStopEvent(logger, TraceLogger_Scripts);
|
||||
@@ -873,26 +905,8 @@ HandleException(ResumeFromException* rfe)
|
||||
probes::ExitScript(cx, script, script->functionNonDelazifying(),
|
||||
/* popSPSFrame = */ false);
|
||||
|
||||
if (iter.baselineFrame()->isDebuggee() && !calledDebugEpilogue) {
|
||||
// If we still need to call the DebugEpilogue, we must
|
||||
// remember the pc we unwound the scope chain to, as it will
|
||||
// be out of sync with the frame's actual pc.
|
||||
if (unwoundScopeToPc)
|
||||
iter.baselineFrame()->setOverridePc(unwoundScopeToPc);
|
||||
|
||||
// If DebugEpilogue returns |true|, we have to perform a forced
|
||||
// return, e.g. return frame->returnValue() to the caller.
|
||||
BaselineFrame* frame = iter.baselineFrame();
|
||||
jsbytecode* pc;
|
||||
iter.baselineScriptAndPc(nullptr, &pc);
|
||||
if (jit::DebugEpilogue(cx, frame, pc, false)) {
|
||||
MOZ_ASSERT(frame->hasReturnValue());
|
||||
rfe->kind = ResumeFromException::RESUME_FORCED_RETURN;
|
||||
rfe->framePointer = iter.fp() - BaselineFrame::FramePointerOffset;
|
||||
rfe->stackPointer = reinterpret_cast<uint8_t*>(frame);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (rfe->kind == ResumeFromException::RESUME_FORCED_RETURN)
|
||||
return;
|
||||
}
|
||||
|
||||
JitFrameLayout* current = iter.isScripted() ? iter.jsFrame() : nullptr;
|
||||
@@ -1099,7 +1113,7 @@ MarkIonJSFrame(JSTracer* trc, const JitFrameIterator& frame)
|
||||
TraceRoot(trc, v, "ion-gc-slot");
|
||||
}
|
||||
|
||||
uintptr_t *spill = frame.spillBase();
|
||||
uintptr_t* spill = frame.spillBase();
|
||||
LiveGeneralRegisterSet gcRegs = safepoint.gcSpills();
|
||||
LiveGeneralRegisterSet valueRegs = safepoint.valueSpills();
|
||||
for (GeneralRegisterBackwardIterator iter(safepoint.allGprSpills()); iter.more(); iter++) {
|
||||
@@ -1184,11 +1198,11 @@ UpdateIonJSFrameForMinorGC(JSTracer* trc, const JitFrameIterator& frame)
|
||||
|
||||
Nursery& nursery = trc->runtime()->gc.nursery;
|
||||
|
||||
const SafepointIndex *si = ionScript->getSafepointIndex(frame.returnAddressToFp());
|
||||
const SafepointIndex* si = ionScript->getSafepointIndex(frame.returnAddressToFp());
|
||||
SafepointReader safepoint(ionScript, si);
|
||||
|
||||
LiveGeneralRegisterSet slotsRegs = safepoint.slotsOrElementsSpills();
|
||||
uintptr_t *spill = frame.spillBase();
|
||||
uintptr_t* spill = frame.spillBase();
|
||||
for (GeneralRegisterBackwardIterator iter(safepoint.allGprSpills()); iter.more(); iter++) {
|
||||
--spill;
|
||||
if (slotsRegs.has(*iter))
|
||||
@@ -1309,7 +1323,7 @@ MarkJitExitFrameCopiedArguments(JSTracer* trc, const VMFunction* f, ExitFooterFr
|
||||
#endif
|
||||
|
||||
static void
|
||||
MarkJitExitFrame(JSTracer *trc, const JitFrameIterator &frame)
|
||||
MarkJitExitFrame(JSTracer* trc, const JitFrameIterator& frame)
|
||||
{
|
||||
// Ignore fake exit frames created by EnsureExitFrame.
|
||||
if (frame.isFakeExitFrame())
|
||||
@@ -1993,7 +2007,7 @@ SnapshotIterator::allocationValue(const RValueAllocation& alloc, ReadMethod rm)
|
||||
}
|
||||
}
|
||||
|
||||
const FloatRegisters::RegisterContent*
|
||||
const FloatRegisters::RegisterContent*
|
||||
SnapshotIterator::floatAllocationPointer(const RValueAllocation& alloc) const
|
||||
{
|
||||
switch (alloc.mode()) {
|
||||
|
||||
@@ -687,17 +687,18 @@ DebugEpilogueOnBaselineReturn(JSContext* cx, BaselineFrame* frame, jsbytecode* p
|
||||
bool
|
||||
DebugEpilogue(JSContext* cx, BaselineFrame* frame, jsbytecode* pc, bool ok)
|
||||
{
|
||||
// Unwind scope chain to stack depth 0.
|
||||
ScopeIter si(cx, frame, pc);
|
||||
UnwindAllScopesInFrame(cx, si);
|
||||
jsbytecode* unwindPc = frame->script()->main();
|
||||
frame->setOverridePc(unwindPc);
|
||||
|
||||
// If Debugger::onLeaveFrame returns |true| we have to return the frame's
|
||||
// return value. If it returns |false|, the debugger threw an exception.
|
||||
// In both cases we have to pop debug scopes.
|
||||
ok = Debugger::onLeaveFrame(cx, frame, ok);
|
||||
|
||||
// Unwind to the outermost scope and set pc to the end of the script,
|
||||
// regardless of error.
|
||||
ScopeIter si(cx, frame, pc);
|
||||
UnwindAllScopesInFrame(cx, si);
|
||||
JSScript* script = frame->script();
|
||||
frame->setOverridePc(script->lastPC());
|
||||
|
||||
if (frame->isNonEvalFunctionFrame()) {
|
||||
MOZ_ASSERT_IF(ok, frame->hasReturnValue());
|
||||
DebugScopes::onPopCall(frame, cx);
|
||||
|
||||
+15
-147
@@ -138,88 +138,7 @@ js::StackDefs(JSScript* script, jsbytecode* pc)
|
||||
return cs.ndefs;
|
||||
}
|
||||
|
||||
static const char * const countBaseNames[] = {
|
||||
"interp"
|
||||
};
|
||||
|
||||
JS_STATIC_ASSERT(JS_ARRAY_LENGTH(countBaseNames) == PCCounts::BASE_LIMIT);
|
||||
|
||||
static const char * const countAccessNames[] = {
|
||||
"infer_mono",
|
||||
"infer_di",
|
||||
"infer_poly",
|
||||
"infer_barrier",
|
||||
"infer_nobarrier",
|
||||
"observe_undefined",
|
||||
"observe_null",
|
||||
"observe_boolean",
|
||||
"observe_int32",
|
||||
"observe_double",
|
||||
"observe_string",
|
||||
"observe_object"
|
||||
};
|
||||
|
||||
JS_STATIC_ASSERT(JS_ARRAY_LENGTH(countBaseNames) +
|
||||
JS_ARRAY_LENGTH(countAccessNames) == PCCounts::ACCESS_LIMIT);
|
||||
|
||||
static const char * const countElementNames[] = {
|
||||
"id_int",
|
||||
"id_double",
|
||||
"id_other",
|
||||
"id_unknown",
|
||||
"elem_typed",
|
||||
"elem_packed",
|
||||
"elem_dense",
|
||||
"elem_other"
|
||||
};
|
||||
|
||||
JS_STATIC_ASSERT(JS_ARRAY_LENGTH(countBaseNames) +
|
||||
JS_ARRAY_LENGTH(countAccessNames) +
|
||||
JS_ARRAY_LENGTH(countElementNames) == PCCounts::ELEM_LIMIT);
|
||||
|
||||
static const char * const countPropertyNames[] = {
|
||||
"prop_static",
|
||||
"prop_definite",
|
||||
"prop_other"
|
||||
};
|
||||
|
||||
JS_STATIC_ASSERT(JS_ARRAY_LENGTH(countBaseNames) +
|
||||
JS_ARRAY_LENGTH(countAccessNames) +
|
||||
JS_ARRAY_LENGTH(countPropertyNames) == PCCounts::PROP_LIMIT);
|
||||
|
||||
static const char * const countArithNames[] = {
|
||||
"arith_int",
|
||||
"arith_double",
|
||||
"arith_other",
|
||||
"arith_unknown",
|
||||
};
|
||||
|
||||
JS_STATIC_ASSERT(JS_ARRAY_LENGTH(countBaseNames) +
|
||||
JS_ARRAY_LENGTH(countArithNames) == PCCounts::ARITH_LIMIT);
|
||||
|
||||
/* static */ const char*
|
||||
PCCounts::countName(JSOp op, size_t which)
|
||||
{
|
||||
MOZ_ASSERT(which < numCounts(op));
|
||||
|
||||
if (which < BASE_LIMIT)
|
||||
return countBaseNames[which];
|
||||
|
||||
if (accessOp(op)) {
|
||||
if (which < ACCESS_LIMIT)
|
||||
return countAccessNames[which - BASE_LIMIT];
|
||||
if (elementOp(op))
|
||||
return countElementNames[which - ACCESS_LIMIT];
|
||||
if (propertyOp(op))
|
||||
return countPropertyNames[which - ACCESS_LIMIT];
|
||||
MOZ_CRASH("bad op");
|
||||
}
|
||||
|
||||
if (arithOp(op))
|
||||
return countArithNames[which - BASE_LIMIT];
|
||||
|
||||
MOZ_CRASH("bad op");
|
||||
}
|
||||
const char * PCCounts::numExecName = "interp";
|
||||
|
||||
void
|
||||
js::DumpIonScriptCounts(Sprinter* sp, jit::IonScriptCounts* ionCounts)
|
||||
@@ -245,26 +164,15 @@ js::DumpPCCounts(JSContext* cx, HandleScript script, Sprinter* sp)
|
||||
#ifdef DEBUG
|
||||
jsbytecode* pc = script->code();
|
||||
while (pc < script->codeEnd()) {
|
||||
JSOp op = JSOp(*pc);
|
||||
jsbytecode* next = GetNextPc(pc);
|
||||
|
||||
if (!Disassemble1(cx, script, pc, script->pcToOffset(pc), true, sp))
|
||||
return;
|
||||
|
||||
size_t total = PCCounts::numCounts(op);
|
||||
double* raw = script->getPCCounts(pc).rawCounts();
|
||||
|
||||
Sprint(sp, " {");
|
||||
bool printed = false;
|
||||
for (size_t i = 0; i < total; i++) {
|
||||
double val = raw[i];
|
||||
if (val) {
|
||||
if (printed)
|
||||
Sprint(sp, ", ");
|
||||
Sprint(sp, "\"%s\": %.0f", PCCounts::countName(op, i), val);
|
||||
printed = true;
|
||||
}
|
||||
}
|
||||
double val = script->getPCCounts(pc).numExec();
|
||||
if (val)
|
||||
Sprint(sp, "\"%s\": %.0f", PCCounts::numExecName, val);
|
||||
Sprint(sp, "}\n");
|
||||
|
||||
pc = next;
|
||||
@@ -1851,39 +1759,13 @@ js::GetPCCountScriptSummary(JSContext* cx, size_t index)
|
||||
}
|
||||
}
|
||||
|
||||
double baseTotals[PCCounts::BASE_LIMIT] = {0.0};
|
||||
double accessTotals[PCCounts::ACCESS_LIMIT - PCCounts::BASE_LIMIT] = {0.0};
|
||||
double elementTotals[PCCounts::ELEM_LIMIT - PCCounts::ACCESS_LIMIT] = {0.0};
|
||||
double propertyTotals[PCCounts::PROP_LIMIT - PCCounts::ACCESS_LIMIT] = {0.0};
|
||||
double arithTotals[PCCounts::ARITH_LIMIT - PCCounts::BASE_LIMIT] = {0.0};
|
||||
double total = 0.0;
|
||||
|
||||
for (unsigned i = 0; i < script->length(); i++) {
|
||||
PCCounts& counts = sac.getPCCounts(script->offsetToPC(i));
|
||||
if (!counts)
|
||||
continue;
|
||||
|
||||
JSOp op = (JSOp)script->code()[i];
|
||||
unsigned numCounts = PCCounts::numCounts(op);
|
||||
|
||||
for (unsigned j = 0; j < numCounts; j++) {
|
||||
double value = counts.get(j);
|
||||
if (j < PCCounts::BASE_LIMIT) {
|
||||
baseTotals[j] += value;
|
||||
} else if (PCCounts::accessOp(op)) {
|
||||
if (j < PCCounts::ACCESS_LIMIT)
|
||||
accessTotals[j - PCCounts::BASE_LIMIT] += value;
|
||||
else if (PCCounts::elementOp(op))
|
||||
elementTotals[j - PCCounts::ACCESS_LIMIT] += value;
|
||||
else if (PCCounts::propertyOp(op))
|
||||
propertyTotals[j - PCCounts::ACCESS_LIMIT] += value;
|
||||
else
|
||||
MOZ_CRASH("Bad opcode");
|
||||
} else if (PCCounts::arithOp(op)) {
|
||||
arithTotals[j - PCCounts::BASE_LIMIT] += value;
|
||||
} else {
|
||||
MOZ_CRASH("Bad opcode");
|
||||
}
|
||||
}
|
||||
jsbytecode* codeEnd = script->codeEnd();
|
||||
for (jsbytecode* pc = script->code(); pc < codeEnd; pc = GetNextPc(pc)) {
|
||||
PCCounts& counts = sac.getPCCounts(pc);
|
||||
double value = counts.numExec();
|
||||
total += value;
|
||||
}
|
||||
|
||||
AppendJSONProperty(buf, "totals");
|
||||
@@ -1891,16 +1773,7 @@ js::GetPCCountScriptSummary(JSContext* cx, size_t index)
|
||||
|
||||
MaybeComma comma = NO_COMMA;
|
||||
|
||||
AppendArrayJSONProperties(cx, buf, baseTotals, countBaseNames,
|
||||
JS_ARRAY_LENGTH(baseTotals), comma);
|
||||
AppendArrayJSONProperties(cx, buf, accessTotals, countAccessNames,
|
||||
JS_ARRAY_LENGTH(accessTotals), comma);
|
||||
AppendArrayJSONProperties(cx, buf, elementTotals, countElementNames,
|
||||
JS_ARRAY_LENGTH(elementTotals), comma);
|
||||
AppendArrayJSONProperties(cx, buf, propertyTotals, countPropertyNames,
|
||||
JS_ARRAY_LENGTH(propertyTotals), comma);
|
||||
AppendArrayJSONProperties(cx, buf, arithTotals, countArithNames,
|
||||
JS_ARRAY_LENGTH(arithTotals), comma);
|
||||
AppendArrayJSONProperties(cx, buf, &total, &PCCounts::numExecName, 1, comma);
|
||||
|
||||
uint64_t ionActivity = 0;
|
||||
jit::IonScriptCounts* ionCounts = sac.getIonCounts();
|
||||
@@ -1991,19 +1864,14 @@ GetPCCountJSON(JSContext* cx, const ScriptAndCounts& sac, StringBuffer& buf)
|
||||
}
|
||||
|
||||
PCCounts& counts = sac.getPCCounts(pc);
|
||||
unsigned numCounts = PCCounts::numCounts(op);
|
||||
|
||||
AppendJSONProperty(buf, "counts");
|
||||
buf.append('{');
|
||||
|
||||
MaybeComma comma = NO_COMMA;
|
||||
for (unsigned i = 0; i < numCounts; i++) {
|
||||
double value = counts.get(i);
|
||||
if (value > 0) {
|
||||
AppendJSONProperty(buf, PCCounts::countName(op, i), comma);
|
||||
comma = COMMA;
|
||||
NumberValueToStringBuffer(cx, DoubleValue(value), buf);
|
||||
}
|
||||
double value = counts.numExec();
|
||||
if (value > 0) {
|
||||
AppendJSONProperty(buf, PCCounts::numExecName, NO_COMMA);
|
||||
NumberValueToStringBuffer(cx, DoubleValue(value), buf);
|
||||
}
|
||||
|
||||
buf.append('}');
|
||||
|
||||
+7
-112
@@ -772,123 +772,18 @@ GetBytecodeInteger(jsbytecode* pc)
|
||||
*/
|
||||
class PCCounts
|
||||
{
|
||||
friend class ::JSScript;
|
||||
double* counts;
|
||||
#ifdef DEBUG
|
||||
size_t capacity;
|
||||
#elif JS_BITS_PER_WORD == 32
|
||||
void* padding;
|
||||
#endif
|
||||
double numExec_;
|
||||
|
||||
public:
|
||||
|
||||
enum BaseCounts {
|
||||
BASE_INTERP = 0,
|
||||
|
||||
BASE_LIMIT
|
||||
};
|
||||
|
||||
enum AccessCounts {
|
||||
ACCESS_MONOMORPHIC = BASE_LIMIT,
|
||||
ACCESS_DIMORPHIC,
|
||||
ACCESS_POLYMORPHIC,
|
||||
|
||||
ACCESS_BARRIER,
|
||||
ACCESS_NOBARRIER,
|
||||
|
||||
ACCESS_UNDEFINED,
|
||||
ACCESS_NULL,
|
||||
ACCESS_BOOLEAN,
|
||||
ACCESS_INT32,
|
||||
ACCESS_DOUBLE,
|
||||
ACCESS_STRING,
|
||||
ACCESS_OBJECT,
|
||||
|
||||
ACCESS_LIMIT
|
||||
};
|
||||
|
||||
static bool accessOp(JSOp op) {
|
||||
/*
|
||||
* Access ops include all name, element and property reads, as well as
|
||||
* SETELEM and SETPROP (for ElementCounts/PropertyCounts alignment).
|
||||
*/
|
||||
if (op == JSOP_SETELEM || op == JSOP_SETPROP)
|
||||
return true;
|
||||
int format = js_CodeSpec[op].format;
|
||||
return !!(format & (JOF_NAME | JOF_GNAME | JOF_ELEM | JOF_PROP))
|
||||
&& !(format & JOF_SET);
|
||||
double& numExec() {
|
||||
return numExec_;
|
||||
}
|
||||
double numExec() const {
|
||||
return numExec_;
|
||||
}
|
||||
|
||||
enum ElementCounts {
|
||||
ELEM_ID_INT = ACCESS_LIMIT,
|
||||
ELEM_ID_DOUBLE,
|
||||
ELEM_ID_OTHER,
|
||||
ELEM_ID_UNKNOWN,
|
||||
|
||||
ELEM_OBJECT_TYPED,
|
||||
ELEM_OBJECT_PACKED,
|
||||
ELEM_OBJECT_DENSE,
|
||||
ELEM_OBJECT_OTHER,
|
||||
|
||||
ELEM_LIMIT
|
||||
};
|
||||
|
||||
static bool elementOp(JSOp op) {
|
||||
return accessOp(op) && (JOF_MODE(js_CodeSpec[op].format) == JOF_ELEM);
|
||||
}
|
||||
|
||||
enum PropertyCounts {
|
||||
PROP_STATIC = ACCESS_LIMIT,
|
||||
PROP_DEFINITE,
|
||||
PROP_OTHER,
|
||||
|
||||
PROP_LIMIT
|
||||
};
|
||||
|
||||
static bool propertyOp(JSOp op) {
|
||||
return accessOp(op) && (JOF_MODE(js_CodeSpec[op].format) == JOF_PROP);
|
||||
}
|
||||
|
||||
enum ArithCounts {
|
||||
ARITH_INT = BASE_LIMIT,
|
||||
ARITH_DOUBLE,
|
||||
ARITH_OTHER,
|
||||
ARITH_UNKNOWN,
|
||||
|
||||
ARITH_LIMIT
|
||||
};
|
||||
|
||||
static bool arithOp(JSOp op) {
|
||||
return !!(js_CodeSpec[op].format & JOF_ARITH);
|
||||
}
|
||||
|
||||
static size_t numCounts(JSOp op)
|
||||
{
|
||||
if (accessOp(op)) {
|
||||
if (elementOp(op))
|
||||
return ELEM_LIMIT;
|
||||
if (propertyOp(op))
|
||||
return PROP_LIMIT;
|
||||
return ACCESS_LIMIT;
|
||||
}
|
||||
if (arithOp(op))
|
||||
return ARITH_LIMIT;
|
||||
return BASE_LIMIT;
|
||||
}
|
||||
|
||||
static const char* countName(JSOp op, size_t which);
|
||||
|
||||
double* rawCounts() const { return counts; }
|
||||
|
||||
double& get(size_t which) {
|
||||
MOZ_ASSERT(which < capacity);
|
||||
return counts[which];
|
||||
}
|
||||
|
||||
/* Boolean conversion, for 'if (counters) ...' */
|
||||
operator void*() const {
|
||||
return counts;
|
||||
}
|
||||
static const char* numExecName;
|
||||
};
|
||||
|
||||
/* Necessary for alignment with the script. */
|
||||
|
||||
+7
-22
@@ -1274,17 +1274,16 @@ JSScript::initScriptCounts(JSContext* cx)
|
||||
{
|
||||
MOZ_ASSERT(!hasScriptCounts());
|
||||
|
||||
size_t n = 0;
|
||||
// We allocate one PCCounts for each offset, instead of for each bytecode,
|
||||
// because the pcCountsVector maps an offset to a PCCounts structure.
|
||||
size_t nbytes = length() * sizeof(PCCounts);
|
||||
|
||||
for (jsbytecode* pc = code(); pc < codeEnd(); pc += GetBytecodeLength(pc))
|
||||
n += PCCounts::numCounts(JSOp(*pc));
|
||||
|
||||
size_t nbytes = (length() * sizeof(PCCounts)) + (n * sizeof(double));
|
||||
// Initialize all PCCounts counters to 0.
|
||||
uint8_t* base = zone()->pod_calloc<uint8_t>(nbytes);
|
||||
if (!base)
|
||||
return false;
|
||||
|
||||
/* Create compartment's scriptCountsMap if necessary. */
|
||||
// Create compartment's scriptCountsMap if necessary.
|
||||
ScriptCountsMap* map = compartment()->scriptCountsMap;
|
||||
if (!map) {
|
||||
map = cx->new_<ScriptCountsMap>();
|
||||
@@ -1296,30 +1295,16 @@ JSScript::initScriptCounts(JSContext* cx)
|
||||
compartment()->scriptCountsMap = map;
|
||||
}
|
||||
|
||||
uint8_t* cursor = base;
|
||||
|
||||
ScriptCounts scriptCounts;
|
||||
scriptCounts.pcCountsVector = (PCCounts*) cursor;
|
||||
cursor += length() * sizeof(PCCounts);
|
||||
|
||||
for (jsbytecode* pc = code(); pc < codeEnd(); pc += GetBytecodeLength(pc)) {
|
||||
MOZ_ASSERT(uintptr_t(cursor) % sizeof(double) == 0);
|
||||
scriptCounts.pcCountsVector[pcToOffset(pc)].counts = (double*) cursor;
|
||||
size_t capacity = PCCounts::numCounts(JSOp(*pc));
|
||||
#ifdef DEBUG
|
||||
scriptCounts.pcCountsVector[pcToOffset(pc)].capacity = capacity;
|
||||
#endif
|
||||
cursor += capacity * sizeof(double);
|
||||
}
|
||||
scriptCounts.pcCountsVector = (PCCounts*) base;
|
||||
|
||||
// Register the current ScriptCount in the compartment's map.
|
||||
if (!map->putNew(this, scriptCounts)) {
|
||||
js_free(base);
|
||||
return false;
|
||||
}
|
||||
hasScriptCounts_ = true; // safe to set this; we can't fail after this point
|
||||
|
||||
MOZ_ASSERT(size_t(cursor - base) == nbytes);
|
||||
|
||||
/* Enable interrupts in any interpreter frames running on this script. */
|
||||
for (ActivationIterator iter(cx->runtime()); !iter.done(); ++iter) {
|
||||
if (iter->isInterpreter())
|
||||
|
||||
@@ -2011,7 +2011,7 @@ CASE(EnableInterruptsPseudoOpcode)
|
||||
|
||||
if (script->hasScriptCounts()) {
|
||||
PCCounts counts = script->getPCCounts(REGS.pc);
|
||||
counts.get(PCCounts::BASE_INTERP)++;
|
||||
counts.numExec()++;
|
||||
moreInterrupts = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -126,8 +126,8 @@ JSRuntime::JSRuntime(JSRuntime* parentRuntime)
|
||||
profilerSampleBufferGen_(0),
|
||||
profilerSampleBufferLapCount_(1),
|
||||
asmJSActivationStack_(nullptr),
|
||||
asyncStackForNewActivations(nullptr),
|
||||
asyncCauseForNewActivations(nullptr),
|
||||
asyncStackForNewActivations(this),
|
||||
asyncCauseForNewActivations(this),
|
||||
asyncCallIsExplicit(false),
|
||||
entryMonitor(nullptr),
|
||||
parentRuntime(parentRuntime),
|
||||
|
||||
+2
-2
@@ -695,12 +695,12 @@ struct JSRuntime : public JS::shadow::Runtime,
|
||||
* New activations will reset this to nullptr on construction after getting
|
||||
* the current value, and will restore the previous value on destruction.
|
||||
*/
|
||||
js::SavedFrame* asyncStackForNewActivations;
|
||||
JS::PersistentRooted<js::SavedFrame*> asyncStackForNewActivations;
|
||||
|
||||
/*
|
||||
* Value of asyncCause to be attached to asyncStackForNewActivations.
|
||||
*/
|
||||
JSString* asyncCauseForNewActivations;
|
||||
JS::PersistentRooted<JSString*> asyncCauseForNewActivations;
|
||||
|
||||
/*
|
||||
* True if the async call was explicitly requested, e.g. via
|
||||
|
||||
@@ -441,34 +441,28 @@ mozJSComponentLoader::FindTargetObject(JSContext* aCx,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* static */ size_t
|
||||
mozJSComponentLoader::DataEntrySizeOfExcludingThis(const nsACString& aKey,
|
||||
ModuleEntry* const& aData,
|
||||
MallocSizeOf aMallocSizeOf, void*)
|
||||
// This requires that the keys be strings and the values be pointers.
|
||||
template <class Key, class Data, class UserData>
|
||||
static size_t
|
||||
SizeOfTableExcludingThis(const nsBaseHashtable<Key, Data, UserData>& aTable,
|
||||
MallocSizeOf aMallocSizeOf)
|
||||
{
|
||||
return aKey.SizeOfExcludingThisIfUnshared(aMallocSizeOf) +
|
||||
aData->SizeOfIncludingThis(aMallocSizeOf);
|
||||
}
|
||||
|
||||
/* static */ size_t
|
||||
mozJSComponentLoader::ClassEntrySizeOfExcludingThis(const nsACString& aKey,
|
||||
const nsAutoPtr<ModuleEntry>& aData,
|
||||
MallocSizeOf aMallocSizeOf, void*)
|
||||
{
|
||||
return aKey.SizeOfExcludingThisIfUnshared(aMallocSizeOf) +
|
||||
aData->SizeOfIncludingThis(aMallocSizeOf);
|
||||
size_t n = aTable.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
||||
for (auto iter = aTable.ConstIter(); !iter.Done(); iter.Next()) {
|
||||
n += iter.Key().SizeOfExcludingThisIfUnshared(aMallocSizeOf);
|
||||
n += iter.Data()->SizeOfIncludingThis(aMallocSizeOf);
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t
|
||||
mozJSComponentLoader::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf)
|
||||
{
|
||||
size_t amount = aMallocSizeOf(this);
|
||||
|
||||
amount += mModules.SizeOfExcludingThis(DataEntrySizeOfExcludingThis, aMallocSizeOf);
|
||||
amount += mImports.SizeOfExcludingThis(ClassEntrySizeOfExcludingThis, aMallocSizeOf);
|
||||
amount += mInProgressImports.SizeOfExcludingThis(DataEntrySizeOfExcludingThis, aMallocSizeOf);
|
||||
|
||||
return amount;
|
||||
size_t n = aMallocSizeOf(this);
|
||||
n += SizeOfTableExcludingThis(mModules, aMallocSizeOf);
|
||||
n += SizeOfTableExcludingThis(mImports, aMallocSizeOf);
|
||||
n += SizeOfTableExcludingThis(mInProgressImports, aMallocSizeOf);
|
||||
return n;
|
||||
}
|
||||
|
||||
// Some stack based classes for cleaning up on early return
|
||||
|
||||
@@ -186,21 +186,17 @@ Native2WrappedNativeMap::~Native2WrappedNativeMap()
|
||||
}
|
||||
|
||||
size_t
|
||||
Native2WrappedNativeMap::SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf)
|
||||
Native2WrappedNativeMap::SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const
|
||||
{
|
||||
size_t n = 0;
|
||||
n += mallocSizeOf(this);
|
||||
n += PL_DHashTableSizeOfIncludingThis(mTable, SizeOfEntryExcludingThis, mallocSizeOf);
|
||||
size_t n = mallocSizeOf(this);
|
||||
n += mTable->ShallowSizeOfIncludingThis(mallocSizeOf);
|
||||
for (auto iter = mTable->Iter(); !iter.Done(); iter.Next()) {
|
||||
auto entry = static_cast<Native2WrappedNativeMap::Entry*>(iter.Get());
|
||||
n += mallocSizeOf(entry->value);
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
/* static */ size_t
|
||||
Native2WrappedNativeMap::SizeOfEntryExcludingThis(PLDHashEntryHdr* hdr,
|
||||
mozilla::MallocSizeOf mallocSizeOf, void*)
|
||||
{
|
||||
return mallocSizeOf(((Native2WrappedNativeMap::Entry*)hdr)->value);
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
// implement IID2WrappedJSClassMap...
|
||||
|
||||
@@ -258,22 +254,17 @@ IID2NativeInterfaceMap::~IID2NativeInterfaceMap()
|
||||
}
|
||||
|
||||
size_t
|
||||
IID2NativeInterfaceMap::SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf)
|
||||
IID2NativeInterfaceMap::SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const
|
||||
{
|
||||
size_t n = 0;
|
||||
n += mallocSizeOf(this);
|
||||
n += PL_DHashTableSizeOfIncludingThis(mTable, SizeOfEntryExcludingThis, mallocSizeOf);
|
||||
size_t n = mallocSizeOf(this);
|
||||
n += mTable->ShallowSizeOfIncludingThis(mallocSizeOf);
|
||||
for (auto iter = mTable->Iter(); !iter.Done(); iter.Next()) {
|
||||
auto entry = static_cast<IID2NativeInterfaceMap::Entry*>(iter.Get());
|
||||
n += entry->value->SizeOfIncludingThis(mallocSizeOf);
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
/* static */ size_t
|
||||
IID2NativeInterfaceMap::SizeOfEntryExcludingThis(PLDHashEntryHdr* hdr,
|
||||
mozilla::MallocSizeOf mallocSizeOf, void*)
|
||||
{
|
||||
XPCNativeInterface* iface = ((IID2NativeInterfaceMap::Entry*)hdr)->value;
|
||||
return iface->SizeOfIncludingThis(mallocSizeOf);
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
// implement ClassInfo2NativeSetMap...
|
||||
|
||||
@@ -297,10 +288,8 @@ ClassInfo2NativeSetMap::~ClassInfo2NativeSetMap()
|
||||
size_t
|
||||
ClassInfo2NativeSetMap::ShallowSizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf)
|
||||
{
|
||||
size_t n = 0;
|
||||
n += mallocSizeOf(this);
|
||||
// The second arg is nullptr because this is a "shallow" measurement of the map.
|
||||
n += PL_DHashTableSizeOfIncludingThis(mTable, nullptr, mallocSizeOf);
|
||||
size_t n = mallocSizeOf(this);
|
||||
n += mTable->ShallowSizeOfIncludingThis(mallocSizeOf);
|
||||
return n;
|
||||
}
|
||||
|
||||
@@ -333,21 +322,17 @@ ClassInfo2WrappedNativeProtoMap::~ClassInfo2WrappedNativeProtoMap()
|
||||
}
|
||||
|
||||
size_t
|
||||
ClassInfo2WrappedNativeProtoMap::SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf)
|
||||
ClassInfo2WrappedNativeProtoMap::SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const
|
||||
{
|
||||
size_t n = 0;
|
||||
n += mallocSizeOf(this);
|
||||
n += PL_DHashTableSizeOfIncludingThis(mTable, SizeOfEntryExcludingThis, mallocSizeOf);
|
||||
size_t n = mallocSizeOf(this);
|
||||
n += mTable->ShallowSizeOfIncludingThis(mallocSizeOf);
|
||||
for (auto iter = mTable->Iter(); !iter.Done(); iter.Next()) {
|
||||
auto entry = static_cast<ClassInfo2WrappedNativeProtoMap::Entry*>(iter.Get());
|
||||
n += mallocSizeOf(entry->value);
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
/* static */ size_t
|
||||
ClassInfo2WrappedNativeProtoMap::SizeOfEntryExcludingThis(PLDHashEntryHdr* hdr,
|
||||
mozilla::MallocSizeOf mallocSizeOf, void*)
|
||||
{
|
||||
return mallocSizeOf(((ClassInfo2WrappedNativeProtoMap::Entry*)hdr)->value);
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
// implement NativeSetMap...
|
||||
|
||||
@@ -449,21 +434,17 @@ NativeSetMap::~NativeSetMap()
|
||||
}
|
||||
|
||||
size_t
|
||||
NativeSetMap::SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf)
|
||||
NativeSetMap::SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const
|
||||
{
|
||||
size_t n = 0;
|
||||
n += mallocSizeOf(this);
|
||||
n += PL_DHashTableSizeOfIncludingThis(mTable, SizeOfEntryExcludingThis, mallocSizeOf);
|
||||
size_t n = mallocSizeOf(this);
|
||||
n += mTable->ShallowSizeOfIncludingThis(mallocSizeOf);
|
||||
for (auto iter = mTable->Iter(); !iter.Done(); iter.Next()) {
|
||||
auto entry = static_cast<NativeSetMap::Entry*>(iter.Get());
|
||||
n += entry->key_value->SizeOfIncludingThis(mallocSizeOf);
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
/* static */ size_t
|
||||
NativeSetMap::SizeOfEntryExcludingThis(PLDHashEntryHdr* hdr, mozilla::MallocSizeOf mallocSizeOf, void*)
|
||||
{
|
||||
XPCNativeSet* set = ((NativeSetMap::Entry*)hdr)->key_value;
|
||||
return set->SizeOfIncludingThis(mallocSizeOf);
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
// implement IID2ThisTranslatorMap...
|
||||
|
||||
|
||||
@@ -149,15 +149,13 @@ public:
|
||||
inline uint32_t Count() { return mTable->EntryCount(); }
|
||||
|
||||
PLDHashTable::Iterator Iter() const { return PLDHashTable::Iterator(mTable); }
|
||||
size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf);
|
||||
size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
|
||||
|
||||
~Native2WrappedNativeMap();
|
||||
private:
|
||||
Native2WrappedNativeMap(); // no implementation
|
||||
explicit Native2WrappedNativeMap(int size);
|
||||
|
||||
static size_t SizeOfEntryExcludingThis(PLDHashEntryHdr* hdr, mozilla::MallocSizeOf mallocSizeOf, void*);
|
||||
|
||||
private:
|
||||
PLDHashTable* mTable;
|
||||
};
|
||||
@@ -260,15 +258,13 @@ public:
|
||||
|
||||
PLDHashTable::Iterator Iter() { return PLDHashTable::Iterator(mTable); }
|
||||
|
||||
size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf);
|
||||
size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
|
||||
|
||||
~IID2NativeInterfaceMap();
|
||||
private:
|
||||
IID2NativeInterfaceMap(); // no implementation
|
||||
explicit IID2NativeInterfaceMap(int size);
|
||||
|
||||
static size_t SizeOfEntryExcludingThis(PLDHashEntryHdr* hdr, mozilla::MallocSizeOf mallocSizeOf, void*);
|
||||
|
||||
private:
|
||||
PLDHashTable* mTable;
|
||||
};
|
||||
@@ -372,15 +368,13 @@ public:
|
||||
PLDHashTable::Iterator Iter() const { return PLDHashTable::Iterator(mTable); }
|
||||
PLDHashTable::Iterator Iter() { return PLDHashTable::Iterator(mTable); }
|
||||
|
||||
size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf);
|
||||
size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
|
||||
|
||||
~ClassInfo2WrappedNativeProtoMap();
|
||||
private:
|
||||
ClassInfo2WrappedNativeProtoMap(); // no implementation
|
||||
explicit ClassInfo2WrappedNativeProtoMap(int size);
|
||||
|
||||
static size_t SizeOfEntryExcludingThis(PLDHashEntryHdr* hdr, mozilla::MallocSizeOf mallocSizeOf, void*);
|
||||
|
||||
private:
|
||||
PLDHashTable* mTable;
|
||||
};
|
||||
@@ -442,15 +436,13 @@ public:
|
||||
PLDHashTable::Iterator Iter() const { return PLDHashTable::Iterator(mTable); }
|
||||
PLDHashTable::Iterator Iter() { return PLDHashTable::Iterator(mTable); }
|
||||
|
||||
size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf);
|
||||
size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
|
||||
|
||||
~NativeSetMap();
|
||||
private:
|
||||
NativeSetMap(); // no implementation
|
||||
explicit NativeSetMap(int size);
|
||||
|
||||
static size_t SizeOfEntryExcludingThis(PLDHashEntryHdr* hdr, mozilla::MallocSizeOf mallocSizeOf, void*);
|
||||
|
||||
private:
|
||||
PLDHashTable* mTable;
|
||||
};
|
||||
|
||||
@@ -10662,12 +10662,8 @@ PresShell::AddSizeOfIncludingThis(MallocSizeOf aMallocSizeOf,
|
||||
if (mCaret) {
|
||||
*aPresShellSize += mCaret->SizeOfIncludingThis(aMallocSizeOf);
|
||||
}
|
||||
*aPresShellSize += mVisibleImages.SizeOfExcludingThis(nullptr,
|
||||
aMallocSizeOf,
|
||||
nullptr);
|
||||
*aPresShellSize += mFramesToDirty.SizeOfExcludingThis(nullptr,
|
||||
aMallocSizeOf,
|
||||
nullptr);
|
||||
*aPresShellSize += mVisibleImages.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
||||
*aPresShellSize += mFramesToDirty.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
||||
*aPresShellSize += aArenaObjectsSize->mOther;
|
||||
|
||||
*aStyleSetsSize += StyleSet()->SizeOfIncludingThis(aMallocSizeOf);
|
||||
|
||||
@@ -204,24 +204,16 @@ CSSVariableDeclarations::AddVariablesToResolver(
|
||||
aResolver);
|
||||
}
|
||||
|
||||
static size_t
|
||||
SizeOfTableEntry(const nsAString& aKey,
|
||||
const nsString& aValue,
|
||||
MallocSizeOf aMallocSizeOf,
|
||||
void* aUserArg)
|
||||
{
|
||||
size_t n = 0;
|
||||
n += aKey.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
|
||||
n += aValue.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t
|
||||
CSSVariableDeclarations::SizeOfIncludingThis(
|
||||
mozilla::MallocSizeOf aMallocSizeOf) const
|
||||
{
|
||||
size_t n = aMallocSizeOf(this);
|
||||
n += mVariables.SizeOfExcludingThis(SizeOfTableEntry, aMallocSizeOf);
|
||||
n += mVariables.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
||||
for (auto iter = mVariables.ConstIter(); !iter.Done(); iter.Next()) {
|
||||
n += iter.Key().SizeOfExcludingThisIfUnshared(aMallocSizeOf);
|
||||
n += iter.Data().SizeOfExcludingThisIfUnshared(aMallocSizeOf);
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
+15
-25
@@ -2589,36 +2589,26 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(Loader, AddRef)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(Loader, Release)
|
||||
|
||||
struct SheetMemoryCounter {
|
||||
size_t size;
|
||||
mozilla::MallocSizeOf mallocSizeOf;
|
||||
};
|
||||
|
||||
static size_t
|
||||
CountSheetMemory(URIPrincipalReferrerPolicyAndCORSModeHashKey* /* unused */,
|
||||
const nsRefPtr<CSSStyleSheet>& aSheet,
|
||||
mozilla::MallocSizeOf aMallocSizeOf,
|
||||
void* /* unused */)
|
||||
{
|
||||
// If aSheet has a parent, then its parent will report it so we don't
|
||||
// have to worry about it here.
|
||||
// Likewise, if aSheet has an owning node, then the document that
|
||||
// node is in will report it.
|
||||
if (aSheet->GetOwnerNode() || aSheet->GetParentSheet()) {
|
||||
return 0;
|
||||
}
|
||||
return aSheet->SizeOfIncludingThis(aMallocSizeOf);
|
||||
}
|
||||
|
||||
size_t
|
||||
Loader::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
|
||||
{
|
||||
size_t s = aMallocSizeOf(this);
|
||||
size_t n = aMallocSizeOf(this);
|
||||
|
||||
if (mSheets) {
|
||||
s += mSheets->mCompleteSheets.SizeOfExcludingThis(CountSheetMemory, aMallocSizeOf);
|
||||
n += mSheets->mCompleteSheets.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
||||
for (auto iter = mSheets->mCompleteSheets.ConstIter();
|
||||
!iter.Done();
|
||||
iter.Next()) {
|
||||
// If aSheet has a parent, then its parent will report it so we don't
|
||||
// have to worry about it here. Likewise, if aSheet has an owning node,
|
||||
// then the document that node is in will report it.
|
||||
const nsRefPtr<CSSStyleSheet>& aSheet = iter.Data();
|
||||
n += (aSheet->GetOwnerNode() || aSheet->GetParentSheet())
|
||||
? 0
|
||||
: aSheet->SizeOfIncludingThis(aMallocSizeOf);
|
||||
}
|
||||
}
|
||||
s += mObservers.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
||||
n += mObservers.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
||||
|
||||
// Measurement of the following members may be added later if DMD finds it is
|
||||
// worthwhile:
|
||||
@@ -2631,7 +2621,7 @@ Loader::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
|
||||
// - mDocument, because it's a weak backpointer
|
||||
// - mPreferredSheet, because it can be a shared string
|
||||
|
||||
return s;
|
||||
return n;
|
||||
}
|
||||
|
||||
} // namespace css
|
||||
|
||||
@@ -172,7 +172,7 @@ private:
|
||||
// Uses any of the sets of ops below.
|
||||
struct RuleHashTableEntry : public PLDHashEntryHdr {
|
||||
// If you add members that have heap allocated memory be sure to change the
|
||||
// logic in SizeOfRuleHashTableEntry().
|
||||
// logic in SizeOfRuleHashTable().
|
||||
// Auto length 1, because we always have at least one entry in mRules.
|
||||
nsAutoTArray<RuleValue, 1> mRules;
|
||||
};
|
||||
@@ -743,10 +743,14 @@ void RuleHash::EnumerateAllRules(Element* aElement, ElementDependentRuleProcesso
|
||||
}
|
||||
|
||||
static size_t
|
||||
SizeOfRuleHashTableEntry(PLDHashEntryHdr* aHdr, MallocSizeOf aMallocSizeOf, void *)
|
||||
SizeOfRuleHashTable(const PLDHashTable& aTable, MallocSizeOf aMallocSizeOf)
|
||||
{
|
||||
RuleHashTableEntry* entry = static_cast<RuleHashTableEntry*>(aHdr);
|
||||
return entry->mRules.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
||||
size_t n = aTable.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
||||
for (auto iter = aTable.ConstIter(); !iter.Done(); iter.Next()) {
|
||||
auto entry = static_cast<RuleHashTableEntry*>(iter.Get());
|
||||
n += entry->mRules.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t
|
||||
@@ -754,21 +758,13 @@ RuleHash::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const
|
||||
{
|
||||
size_t n = 0;
|
||||
|
||||
n += PL_DHashTableSizeOfExcludingThis(&mIdTable,
|
||||
SizeOfRuleHashTableEntry,
|
||||
aMallocSizeOf);
|
||||
n += SizeOfRuleHashTable(mIdTable, aMallocSizeOf);
|
||||
|
||||
n += PL_DHashTableSizeOfExcludingThis(&mClassTable,
|
||||
SizeOfRuleHashTableEntry,
|
||||
aMallocSizeOf);
|
||||
n += SizeOfRuleHashTable(mClassTable, aMallocSizeOf);
|
||||
|
||||
n += PL_DHashTableSizeOfExcludingThis(&mTagTable,
|
||||
SizeOfRuleHashTableEntry,
|
||||
aMallocSizeOf);
|
||||
n += SizeOfRuleHashTable(mTagTable, aMallocSizeOf);
|
||||
|
||||
n += PL_DHashTableSizeOfExcludingThis(&mNameSpaceTable,
|
||||
SizeOfRuleHashTableEntry,
|
||||
aMallocSizeOf);
|
||||
n += SizeOfRuleHashTable(mNameSpaceTable, aMallocSizeOf);
|
||||
|
||||
n += mUniversalRules.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
||||
|
||||
@@ -947,26 +943,14 @@ struct RuleCascadeData {
|
||||
};
|
||||
|
||||
static size_t
|
||||
SizeOfSelectorsEntry(PLDHashEntryHdr* aHdr, MallocSizeOf aMallocSizeOf, void *)
|
||||
SizeOfSelectorsHashTable(const PLDHashTable& aTable, MallocSizeOf aMallocSizeOf)
|
||||
{
|
||||
AtomSelectorEntry* entry = static_cast<AtomSelectorEntry*>(aHdr);
|
||||
return entry->mSelectors.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
||||
}
|
||||
|
||||
static size_t
|
||||
SizeOfKeyframesRuleEntryExcludingThis(nsStringHashKey::KeyType aKey,
|
||||
nsCSSKeyframesRule* const& aData,
|
||||
mozilla::MallocSizeOf aMallocSizeOf,
|
||||
void* aUserArg)
|
||||
{
|
||||
// We don't own the nsCSSKeyframesRule objects so we don't count them. We do
|
||||
// care about the size of the keys' nsAString members' buffers though.
|
||||
//
|
||||
// Note that we depend on nsStringHashKey::GetKey() returning a reference,
|
||||
// since otherwise aKey would be a copy of the string key and we would not be
|
||||
// measuring the right object here.
|
||||
|
||||
return aKey.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
|
||||
size_t n = aTable.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
||||
for (auto iter = aTable.ConstIter(); !iter.Done(); iter.Next()) {
|
||||
auto entry = static_cast<AtomSelectorEntry*>(iter.Get());
|
||||
n += entry->mSelectors.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t
|
||||
@@ -982,21 +966,16 @@ RuleCascadeData::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
|
||||
|
||||
n += mStateSelectors.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
||||
|
||||
n += PL_DHashTableSizeOfExcludingThis(&mIdSelectors,
|
||||
SizeOfSelectorsEntry, aMallocSizeOf);
|
||||
n += PL_DHashTableSizeOfExcludingThis(&mClassSelectors,
|
||||
SizeOfSelectorsEntry, aMallocSizeOf);
|
||||
n += SizeOfSelectorsHashTable(mIdSelectors, aMallocSizeOf);
|
||||
n += SizeOfSelectorsHashTable(mClassSelectors, aMallocSizeOf);
|
||||
|
||||
n += mPossiblyNegatedClassSelectors.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
||||
n += mPossiblyNegatedIDSelectors.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
||||
|
||||
n += PL_DHashTableSizeOfExcludingThis(&mAttributeSelectors,
|
||||
SizeOfSelectorsEntry, aMallocSizeOf);
|
||||
n += PL_DHashTableSizeOfExcludingThis(&mAnonBoxRules,
|
||||
SizeOfRuleHashTableEntry, aMallocSizeOf);
|
||||
n += SizeOfSelectorsHashTable(mAttributeSelectors, aMallocSizeOf);
|
||||
n += SizeOfRuleHashTable(mAnonBoxRules, aMallocSizeOf);
|
||||
#ifdef MOZ_XUL
|
||||
n += PL_DHashTableSizeOfExcludingThis(&mXULTreeRules,
|
||||
SizeOfRuleHashTableEntry, aMallocSizeOf);
|
||||
n += SizeOfRuleHashTable(mXULTreeRules, aMallocSizeOf);
|
||||
#endif
|
||||
|
||||
n += mFontFaceRules.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
||||
@@ -1004,9 +983,17 @@ RuleCascadeData::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
|
||||
n += mFontFeatureValuesRules.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
||||
n += mPageRules.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
||||
n += mCounterStyleRules.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
||||
n += mKeyframesRuleTable.SizeOfExcludingThis(SizeOfKeyframesRuleEntryExcludingThis,
|
||||
aMallocSizeOf,
|
||||
nullptr);
|
||||
|
||||
n += mKeyframesRuleTable.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
||||
for (auto iter = mKeyframesRuleTable.ConstIter(); !iter.Done(); iter.Next()) {
|
||||
// We don't own the nsCSSKeyframesRule objects so we don't count them. We
|
||||
// do care about the size of the keys' nsAString members' buffers though.
|
||||
//
|
||||
// Note that we depend on nsStringHashKey::GetKey() returning a reference,
|
||||
// since otherwise aKey would be a copy of the string key and we would not
|
||||
// be measuring the right object here.
|
||||
n += iter.Key().SizeOfExcludingThisIfUnshared(aMallocSizeOf);
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
@@ -161,26 +161,21 @@ nsHTMLCSSStyleSheet::MediumFeaturesChanged(nsPresContext* aPresContext)
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t
|
||||
SizeOfCachedStyleAttrsEntryExcludingThis(nsStringHashKey::KeyType& aKey,
|
||||
MiscContainer* const& aData,
|
||||
mozilla::MallocSizeOf aMallocSizeOf,
|
||||
void* userArg)
|
||||
{
|
||||
// We don't own the MiscContainers so we don't count them. We do care about
|
||||
// the size of the nsString members in the keys though.
|
||||
return aKey.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
|
||||
}
|
||||
|
||||
/* virtual */ size_t
|
||||
nsHTMLCSSStyleSheet::SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
|
||||
{
|
||||
// The size of mCachedStyleAttrs's mTable member (a PLDHashTable) is
|
||||
// significant in itself, but more significant is the size of the nsString
|
||||
// members of the nsStringHashKeys.
|
||||
return mCachedStyleAttrs.SizeOfExcludingThis(SizeOfCachedStyleAttrsEntryExcludingThis,
|
||||
aMallocSizeOf,
|
||||
nullptr);
|
||||
size_t n = 0;
|
||||
n += mCachedStyleAttrs.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
||||
for (auto iter = mCachedStyleAttrs.ConstIter(); !iter.Done(); iter.Next()) {
|
||||
// We don't own the MiscContainers (the hash table values) so we don't
|
||||
// count them. We do care about the size of the nsString members in the
|
||||
// keys though.
|
||||
n += iter.Key().SizeOfExcludingThisIfUnshared(aMallocSizeOf);
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
/* virtual */ size_t
|
||||
|
||||
@@ -500,26 +500,16 @@ nsHTMLStyleSheet::LangRuleFor(const nsString& aLanguage)
|
||||
return entry->mRule;
|
||||
}
|
||||
|
||||
static size_t
|
||||
SizeOfAttributesEntryExcludingThis(PLDHashEntryHdr* aEntry,
|
||||
MallocSizeOf aMallocSizeOf,
|
||||
void* aArg)
|
||||
{
|
||||
NS_PRECONDITION(aEntry, "The entry should not be null!");
|
||||
|
||||
MappedAttrTableEntry* entry = static_cast<MappedAttrTableEntry*>(aEntry);
|
||||
NS_ASSERTION(entry->mAttributes, "entry->mAttributes should not be null!");
|
||||
return entry->mAttributes->SizeOfIncludingThis(aMallocSizeOf);
|
||||
}
|
||||
|
||||
size_t
|
||||
nsHTMLStyleSheet::DOMSizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
|
||||
{
|
||||
size_t n = aMallocSizeOf(this);
|
||||
|
||||
n += PL_DHashTableSizeOfExcludingThis(&mMappedAttrTable,
|
||||
SizeOfAttributesEntryExcludingThis,
|
||||
aMallocSizeOf);
|
||||
n += mMappedAttrTable.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
||||
for (auto iter = mMappedAttrTable.ConstIter(); !iter.Done(); iter.Next()) {
|
||||
auto entry = static_cast<MappedAttrTableEntry*>(iter.Get());
|
||||
n += entry->mAttributes->SizeOfIncludingThis(aMallocSizeOf);
|
||||
}
|
||||
|
||||
// Measurement of the following members may be added later if DMD finds it is
|
||||
// worthwhile:
|
||||
|
||||
@@ -218,18 +218,6 @@ AssertNotAlreadyCached(const char* aPrefType,
|
||||
}
|
||||
#endif
|
||||
|
||||
static size_t
|
||||
SizeOfObserverEntryExcludingThis(ValueObserverHashKey* aKey,
|
||||
const nsRefPtr<ValueObserver>& aData,
|
||||
mozilla::MallocSizeOf aMallocSizeOf,
|
||||
void*)
|
||||
{
|
||||
size_t n = 0;
|
||||
n += aKey->mPrefName.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
|
||||
n += aData->mClosures.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
||||
return n;
|
||||
}
|
||||
|
||||
// Although this is a member of Preferences, it measures sPreferences and
|
||||
// several other global structures.
|
||||
/* static */ int64_t
|
||||
@@ -241,7 +229,7 @@ Preferences::SizeOfIncludingThisAndOtherStuff(mozilla::MallocSizeOf aMallocSizeO
|
||||
if (gHashTable) {
|
||||
// pref keys are allocated in a private arena, which we count elsewhere.
|
||||
// pref stringvals are allocated out of the same private arena.
|
||||
n += PL_DHashTableSizeOfExcludingThis(gHashTable, nullptr, aMallocSizeOf);
|
||||
n += gHashTable->ShallowSizeOfIncludingThis(aMallocSizeOf);
|
||||
}
|
||||
if (gCacheData) {
|
||||
n += gCacheData->ShallowSizeOfIncludingThis(aMallocSizeOf);
|
||||
@@ -251,8 +239,11 @@ Preferences::SizeOfIncludingThisAndOtherStuff(mozilla::MallocSizeOf aMallocSizeO
|
||||
}
|
||||
if (gObserverTable) {
|
||||
n += aMallocSizeOf(gObserverTable);
|
||||
n += gObserverTable->SizeOfExcludingThis(SizeOfObserverEntryExcludingThis,
|
||||
aMallocSizeOf);
|
||||
n += gObserverTable->ShallowSizeOfIncludingThis(aMallocSizeOf);
|
||||
for (auto iter = gObserverTable->Iter(); !iter.Done(); iter.Next()) {
|
||||
n += iter.Key()->mPrefName.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
|
||||
n += iter.Data()->mClosures.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
||||
}
|
||||
}
|
||||
// We don't measure sRootBranch and sDefaultRootBranch here because
|
||||
// DMD indicates they are not significant.
|
||||
|
||||
@@ -1947,20 +1947,6 @@ CacheFile::InitIndexEntry()
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Memory reporting
|
||||
|
||||
namespace {
|
||||
|
||||
size_t
|
||||
CollectChunkSize(uint32_t const & aIdx,
|
||||
nsRefPtr<mozilla::net::CacheFileChunk> const & aChunk,
|
||||
mozilla::MallocSizeOf mallocSizeOf, void* aClosure)
|
||||
{
|
||||
return aChunk->SizeOfIncludingThis(mallocSizeOf);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
size_t
|
||||
CacheFile::SizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const
|
||||
{
|
||||
@@ -1968,8 +1954,14 @@ CacheFile::SizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const
|
||||
|
||||
size_t n = 0;
|
||||
n += mKey.SizeOfExcludingThisIfUnshared(mallocSizeOf);
|
||||
n += mChunks.SizeOfExcludingThis(CollectChunkSize, mallocSizeOf);
|
||||
n += mCachedChunks.SizeOfExcludingThis(CollectChunkSize, mallocSizeOf);
|
||||
n += mChunks.ShallowSizeOfExcludingThis(mallocSizeOf);
|
||||
for (auto iter = mChunks.ConstIter(); !iter.Done(); iter.Next()) {
|
||||
n += iter.Data()->SizeOfIncludingThis(mallocSizeOf);
|
||||
}
|
||||
n += mCachedChunks.ShallowSizeOfExcludingThis(mallocSizeOf);
|
||||
for (auto iter = mCachedChunks.ConstIter(); !iter.Done(); iter.Next()) {
|
||||
n += iter.Data()->SizeOfIncludingThis(mallocSizeOf);
|
||||
}
|
||||
if (mMetadata) {
|
||||
n += mMetadata->SizeOfIncludingThis(mallocSizeOf);
|
||||
}
|
||||
@@ -1986,7 +1978,7 @@ CacheFile::SizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const
|
||||
}
|
||||
|
||||
// The listeners are usually classes reported just above.
|
||||
n += mChunkListeners.SizeOfExcludingThis(nullptr, mallocSizeOf);
|
||||
n += mChunkListeners.ShallowSizeOfExcludingThis(mallocSizeOf);
|
||||
n += mObjsToRelease.ShallowSizeOfExcludingThis(mallocSizeOf);
|
||||
|
||||
// mHandle reported directly from CacheFileIOManager.
|
||||
|
||||
@@ -20,6 +20,8 @@
|
||||
#include "nsITimer.h"
|
||||
#include "mozilla/AutoRestore.h"
|
||||
#include <algorithm>
|
||||
#include "mozilla/Telemetry.h"
|
||||
#include "mozilla/unused.h"
|
||||
|
||||
|
||||
#define kMinUnwrittenChanges 300
|
||||
@@ -2956,7 +2958,7 @@ CacheIndex::FinishUpdate(bool aSucceeded)
|
||||
NS_WARNING(("CacheIndex::FinishUpdate() - Leaking mDirEnumerator!"));
|
||||
// This can happen only in case dispatching event to IO thread failed in
|
||||
// CacheIndex::PreShutdown().
|
||||
mDirEnumerator.forget(); // Leak it since dir enumerator is not threadsafe
|
||||
unused << mDirEnumerator.forget(); // Leak it since dir enumerator is not threadsafe
|
||||
} else {
|
||||
mDirEnumerator->Close();
|
||||
mDirEnumerator = nullptr;
|
||||
|
||||
@@ -1865,7 +1865,7 @@ CacheStorageService::SizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) con
|
||||
n += Pool(false).mExpirationArray.ShallowSizeOfExcludingThis(mallocSizeOf);
|
||||
// Entries reported manually in CacheStorageService::CollectReports callback
|
||||
if (sGlobalEntryTables) {
|
||||
n += sGlobalEntryTables->SizeOfIncludingThis(nullptr, mallocSizeOf);
|
||||
n += sGlobalEntryTables->ShallowSizeOfIncludingThis(mallocSizeOf);
|
||||
}
|
||||
|
||||
return n;
|
||||
@@ -1886,36 +1886,28 @@ public:
|
||||
nsISupports *mData;
|
||||
};
|
||||
|
||||
size_t CollectEntryMemory(nsACString const & aKey,
|
||||
nsRefPtr<mozilla::net::CacheEntry> const & aEntry,
|
||||
mozilla::MallocSizeOf mallocSizeOf,
|
||||
void * aClosure)
|
||||
{
|
||||
CacheStorageService::Self()->Lock().AssertCurrentThreadOwns();
|
||||
|
||||
CacheEntryTable* aTable = static_cast<CacheEntryTable*>(aClosure);
|
||||
|
||||
size_t n = 0;
|
||||
n += aKey.SizeOfExcludingThisIfUnshared(mallocSizeOf);
|
||||
|
||||
// Bypass memory-only entries, those will be reported when iterating
|
||||
// the memory only table. Memory-only entries are stored in both ALL_ENTRIES
|
||||
// and MEMORY_ONLY hashtables.
|
||||
if (aTable->Type() == CacheEntryTable::MEMORY_ONLY || aEntry->IsUsingDisk())
|
||||
n += aEntry->SizeOfIncludingThis(mallocSizeOf);
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
PLDHashOperator ReportStorageMemory(const nsACString& aKey,
|
||||
CacheEntryTable* aTable,
|
||||
void* aClosure)
|
||||
{
|
||||
CacheStorageService::Self()->Lock().AssertCurrentThreadOwns();
|
||||
|
||||
size_t size = aTable->SizeOfIncludingThis(&CollectEntryMemory,
|
||||
CacheStorageService::MallocSizeOf,
|
||||
aTable);
|
||||
size_t size = 0;
|
||||
mozilla::MallocSizeOf mallocSizeOf = CacheStorageService::MallocSizeOf;
|
||||
|
||||
size += aTable->ShallowSizeOfIncludingThis(mallocSizeOf);
|
||||
for (auto iter = aTable->Iter(); !iter.Done(); iter.Next()) {
|
||||
size += iter.Key().SizeOfExcludingThisIfUnshared(mallocSizeOf);
|
||||
|
||||
// Bypass memory-only entries, those will be reported when iterating
|
||||
// the memory only table. Memory-only entries are stored in both ALL_ENTRIES
|
||||
// and MEMORY_ONLY hashtables.
|
||||
nsRefPtr<mozilla::net::CacheEntry> const& entry = iter.Data();
|
||||
if (aTable->Type() == CacheEntryTable::MEMORY_ONLY ||
|
||||
entry->IsUsingDisk()) {
|
||||
size += entry->SizeOfIncludingThis(mallocSizeOf);
|
||||
}
|
||||
}
|
||||
|
||||
ReportStorageMemoryData& data =
|
||||
*static_cast<ReportStorageMemoryData*>(aClosure);
|
||||
|
||||
@@ -122,7 +122,7 @@ size_t
|
||||
nsEffectiveTLDService::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf)
|
||||
{
|
||||
size_t n = aMallocSizeOf(this);
|
||||
n += mHash.SizeOfExcludingThis(nullptr, aMallocSizeOf);
|
||||
n += mHash.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
||||
|
||||
// Measurement of the following members may be added later if DMD finds it is
|
||||
// worthwhile:
|
||||
|
||||
@@ -1321,22 +1321,18 @@ nsHostResolver::CancelAsyncRequest(const char *host,
|
||||
}
|
||||
}
|
||||
|
||||
static size_t
|
||||
SizeOfHostDBEntExcludingThis(PLDHashEntryHdr* hdr, MallocSizeOf mallocSizeOf,
|
||||
void*)
|
||||
{
|
||||
nsHostDBEnt* ent = static_cast<nsHostDBEnt*>(hdr);
|
||||
return ent->rec->SizeOfIncludingThis(mallocSizeOf);
|
||||
}
|
||||
|
||||
size_t
|
||||
nsHostResolver::SizeOfIncludingThis(MallocSizeOf mallocSizeOf) const
|
||||
{
|
||||
MutexAutoLock lock(mLock);
|
||||
|
||||
size_t n = mallocSizeOf(this);
|
||||
n += PL_DHashTableSizeOfExcludingThis(&mDB, SizeOfHostDBEntExcludingThis,
|
||||
mallocSizeOf);
|
||||
|
||||
n += mDB.ShallowSizeOfExcludingThis(mallocSizeOf);
|
||||
for (auto iter = mDB.ConstIter(); !iter.Done(); iter.Next()) {
|
||||
auto entry = static_cast<nsHostDBEnt*>(iter.Get());
|
||||
n += entry->rec->SizeOfIncludingThis(mallocSizeOf);
|
||||
}
|
||||
|
||||
// The following fields aren't measured.
|
||||
// - mHighQ, mMediumQ, mLowQ, mEvictionQ, because they just point to
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
#
|
||||
# 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/.
|
||||
|
||||
GEN_CERT_HEADER = $(srcdir)/gen_cert_header.py
|
||||
TEST_SSL_PATH = $(srcdir)/../manager/ssl/tests/unit/test_signed_manifest/
|
||||
|
||||
marketplace-prod-public.inc: marketplace-prod-public.crt $(GEN_CERT_HEADER)
|
||||
$(PYTHON) $(GEN_CERT_HEADER) marketplaceProdPublicRoot $< > $@
|
||||
|
||||
marketplace-prod-reviewers.inc: marketplace-prod-reviewers.crt $(GEN_CERT_HEADER)
|
||||
$(PYTHON) $(GEN_CERT_HEADER) marketplaceProdReviewersRoot $< > $@
|
||||
|
||||
marketplace-dev-public.inc: marketplace-dev-public.crt $(GEN_CERT_HEADER)
|
||||
$(PYTHON) $(GEN_CERT_HEADER) marketplaceDevPublicRoot $< > $@
|
||||
|
||||
marketplace-dev-reviewers.inc: marketplace-dev-reviewers.crt $(GEN_CERT_HEADER)
|
||||
$(PYTHON) $(GEN_CERT_HEADER) marketplaceDevReviewersRoot $< > $@
|
||||
|
||||
marketplace-stage.inc: marketplace-stage.crt $(GEN_CERT_HEADER)
|
||||
$(PYTHON) $(GEN_CERT_HEADER) marketplaceStageRoot $< > $@
|
||||
|
||||
ifeq ($(shell test -s trusted-app-public.der; echo $$?),0)
|
||||
TRUSTED_APP_PUBLIC=trusted-app-public.der
|
||||
else
|
||||
TRUSTED_APP_PUBLIC=
|
||||
endif
|
||||
|
||||
manifest-signing-root.inc: $(TRUSTED_APP_PUBLIC) $(GEN_CERT_HEADER)
|
||||
$(PYTHON) $(GEN_CERT_HEADER) trustedAppPublicRoot $(TRUSTED_APP_PUBLIC) > $@
|
||||
|
||||
manifest-signing-test-root.inc: $(TEST_SSL_PATH)trusted_ca1.der $(GEN_CERT_HEADER)
|
||||
$(PYTHON) $(GEN_CERT_HEADER) trustedAppTestRoot $< > $@
|
||||
|
||||
xpcshell.inc: $(srcdir)/../manager/ssl/tests/unit/test_signed_apps/trusted_ca1.der $(GEN_CERT_HEADER)
|
||||
$(PYTHON) $(GEN_CERT_HEADER) xpcshellRoot $< > $@
|
||||
|
||||
export:: \
|
||||
marketplace-prod-public.inc \
|
||||
marketplace-prod-reviewers.inc \
|
||||
marketplace-dev-public.inc \
|
||||
marketplace-dev-reviewers.inc \
|
||||
marketplace-stage.inc \
|
||||
manifest-signing-root.inc \
|
||||
manifest-signing-test-root.inc \
|
||||
xpcshell.inc \
|
||||
$(NULL)
|
||||
@@ -2,38 +2,41 @@
|
||||
# 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/.
|
||||
|
||||
import sys
|
||||
import binascii
|
||||
|
||||
def file_byte_generator(filename, block_size = 512):
|
||||
def _file_byte_generator(filename):
|
||||
with open(filename, "rb") as f:
|
||||
while True:
|
||||
block = f.read(block_size)
|
||||
if block:
|
||||
for byte in block:
|
||||
yield byte
|
||||
else:
|
||||
break
|
||||
contents = f.read()
|
||||
|
||||
def create_header(array_name, in_filename):
|
||||
hexified = ["0x" + binascii.hexlify(byte) for byte in file_byte_generator(in_filename)]
|
||||
print "const uint8_t " + array_name + "[] = {"
|
||||
print ", ".join(hexified)
|
||||
print "};"
|
||||
return 0
|
||||
# Treat empty files the same as a file containing a lone 0;
|
||||
# a single-element array will fail cert verifcation just as an
|
||||
# empty array would.
|
||||
if not contents:
|
||||
return ['\0']
|
||||
|
||||
def create_empty_header(array_name):
|
||||
# mfbt/ArrayUtils.h will not be able to pick up the
|
||||
# correct specialization for ArrayLength(const array[0])
|
||||
# so add a value of 0 which will fail cert verification
|
||||
# just the same as an empty array
|
||||
print "const uint8_t " + array_name + "[] = { 0x0 };"
|
||||
return 0
|
||||
return contents
|
||||
|
||||
if __name__ == '__main__':
|
||||
if len(sys.argv) < 2:
|
||||
print 'ERROR: usage: gen_cert_header.py array_name in_filename'
|
||||
sys.exit(1);
|
||||
if len(sys.argv) == 2:
|
||||
sys.exit(create_empty_header(sys.argv[1]))
|
||||
sys.exit(create_header(sys.argv[1], sys.argv[2]))
|
||||
def _create_header(array_name, cert_bytes):
|
||||
hexified = ["0x" + binascii.hexlify(byte) for byte in cert_bytes]
|
||||
substs = { 'array_name': array_name, 'bytes': ', '.join(hexified) }
|
||||
return "const uint8_t %(array_name)s[] = {\n%(bytes)s\n};\n" % substs
|
||||
|
||||
# Create functions named the same as the data arrays that we're going to
|
||||
# write to the headers, so we don't have to duplicate the names like so:
|
||||
#
|
||||
# def arrayName(header, cert_filename):
|
||||
# header.write(_create_header("arrayName", cert_filename))
|
||||
array_names = [
|
||||
'marketplaceProdPublicRoot',
|
||||
'marketplaceProdReviewersRoot',
|
||||
'marketplaceDevPublicRoot',
|
||||
'marketplaceDevReviewersRoot',
|
||||
'marketplaceStageRoot',
|
||||
'trustedAppPublicRoot',
|
||||
'trustedAppTestRoot',
|
||||
'xpcshellRoot',
|
||||
]
|
||||
|
||||
for n in array_names:
|
||||
# Make sure the lambda captures the right string.
|
||||
globals()[n] = lambda header, cert_filename, name=n: header.write(_create_header(name, _file_byte_generator(cert_filename)))
|
||||
|
||||
@@ -22,3 +22,22 @@ LOCAL_INCLUDES += [
|
||||
DEFINES['NSS_ENABLE_ECC'] = 'True'
|
||||
for var in ('DLL_PREFIX', 'DLL_SUFFIX'):
|
||||
DEFINES[var] = '"%s"' % CONFIG[var]
|
||||
|
||||
test_ssl_path = TOPSRCDIR + '/security/manager/ssl/tests/unit'
|
||||
|
||||
headers_arrays_certs = [
|
||||
('marketplace-prod-public.inc', 'marketplaceProdPublicRoot', 'marketplace-prod-public.crt'),
|
||||
('marketplace-prod-reviewers.inc', 'marketplaceProdReviewersRoot', 'marketplace-prod-reviewers.crt'),
|
||||
('marketplace-dev-public.inc', 'marketplaceDevPublicRoot', 'marketplace-dev-public.crt'),
|
||||
('marketplace-dev-reviewers.inc', 'marketplaceDevReviewersRoot', 'marketplace-dev-reviewers.crt'),
|
||||
('marketplace-stage.inc', 'marketplaceStageRoot', 'marketplace-stage.crt'),
|
||||
('manifest-signing-root.inc', 'trustedAppPublicRoot', 'trusted-app-public.der'),
|
||||
('manifest-signing-test-root.inc', 'trustedAppTestRoot', test_ssl_path + '/test_signed_manifest/trusted_ca1.der'),
|
||||
('xpcshell.inc', 'xpcshellRoot', test_ssl_path + '/test_signed_apps/trusted_ca1.der'),
|
||||
]
|
||||
|
||||
for header, array_name, cert in headers_arrays_certs:
|
||||
GENERATED_FILES += [header]
|
||||
h = GENERATED_FILES[header]
|
||||
h.script = 'gen_cert_header.py:' + array_name
|
||||
h.inputs = [cert]
|
||||
|
||||
@@ -377,20 +377,21 @@ StartupCache::SizeOfMapping()
|
||||
}
|
||||
|
||||
size_t
|
||||
StartupCache::HeapSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf)
|
||||
StartupCache::HeapSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
|
||||
{
|
||||
// This function could measure more members, but they haven't been found by
|
||||
// DMD to be significant. They can be added later if necessary.
|
||||
return aMallocSizeOf(this) +
|
||||
mTable.SizeOfExcludingThis(SizeOfEntryExcludingThis, aMallocSizeOf) +
|
||||
mPendingWrites.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
||||
}
|
||||
|
||||
/* static */ size_t
|
||||
StartupCache::SizeOfEntryExcludingThis(const nsACString& key, const nsAutoPtr<CacheEntry>& data,
|
||||
mozilla::MallocSizeOf mallocSizeOf, void *)
|
||||
{
|
||||
return data->SizeOfExcludingThis(mallocSizeOf);
|
||||
size_t n = aMallocSizeOf(this);
|
||||
|
||||
n += mTable.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
||||
for (auto iter = mTable.ConstIter(); !iter.Done(); iter.Next()) {
|
||||
n += iter.Data()->SizeOfIncludingThis(aMallocSizeOf);
|
||||
}
|
||||
|
||||
n += mPendingWrites.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
struct CacheWriteHolder
|
||||
|
||||
@@ -85,8 +85,8 @@ struct CacheEntry
|
||||
{
|
||||
}
|
||||
|
||||
size_t SizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) {
|
||||
return mallocSizeOf(data);
|
||||
size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) {
|
||||
return mallocSizeOf(this) + mallocSizeOf(data);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -135,7 +135,7 @@ public:
|
||||
|
||||
// This measures all the heap memory used by the StartupCache, i.e. it
|
||||
// excludes the mapping.
|
||||
size_t HeapSizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf);
|
||||
size_t HeapSizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
|
||||
|
||||
size_t SizeOfMapping();
|
||||
|
||||
@@ -159,11 +159,6 @@ private:
|
||||
static void WriteTimeout(nsITimer *aTimer, void *aClosure);
|
||||
static void ThreadedWrite(void *aClosure);
|
||||
|
||||
static size_t SizeOfEntryExcludingThis(const nsACString& key,
|
||||
const nsAutoPtr<CacheEntry>& data,
|
||||
mozilla::MallocSizeOf mallocSizeOf,
|
||||
void *);
|
||||
|
||||
nsClassHashtable<nsCStringHashKey, CacheEntry> mTable;
|
||||
nsTArray<nsCString> mPendingWrites;
|
||||
nsRefPtr<nsZipArchive> mArchive;
|
||||
|
||||
@@ -396,10 +396,12 @@ public:
|
||||
}
|
||||
|
||||
size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const {
|
||||
size_t size;
|
||||
size = mFileStats.SizeOfExcludingThis(SizeOfFileIOEntryTypeExcludingThis,
|
||||
aMallocSizeOf) +
|
||||
mSafeDirs.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
||||
size_t size = 0;
|
||||
size += mFileStats.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
||||
for (auto iter = mFileStats.ConstIter(); !iter.Done(); iter.Next()) {
|
||||
size += iter.Get()->GetKey().SizeOfExcludingThisIfUnshared(aMallocSizeOf);
|
||||
}
|
||||
size += mSafeDirs.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
||||
uint32_t safeDirsLen = mSafeDirs.Length();
|
||||
for (uint32_t i = 0; i < safeDirsLen; ++i) {
|
||||
size += mSafeDirs[i].SizeOfExcludingThis(aMallocSizeOf);
|
||||
@@ -448,13 +450,6 @@ private:
|
||||
*/
|
||||
static bool ReflectFileStats(FileIOEntryType* entry, JSContext *cx,
|
||||
JS::Handle<JSObject*> obj);
|
||||
|
||||
static size_t SizeOfFileIOEntryTypeExcludingThis(FileIOEntryType* aEntry,
|
||||
mozilla::MallocSizeOf mallocSizeOf,
|
||||
void*)
|
||||
{
|
||||
return aEntry->GetKey().SizeOfExcludingThisIfUnshared(mallocSizeOf);
|
||||
}
|
||||
};
|
||||
|
||||
TelemetryIOInterposeObserver::TelemetryIOInterposeObserver(nsIFile* aXreDir)
|
||||
@@ -3293,8 +3288,8 @@ TelemetryImpl::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf)
|
||||
size_t n = aMallocSizeOf(this);
|
||||
|
||||
// Ignore the hashtables in mAddonMap; they are not significant.
|
||||
n += mAddonMap.SizeOfExcludingThis(nullptr, aMallocSizeOf);
|
||||
n += mHistogramMap.SizeOfExcludingThis(nullptr, aMallocSizeOf);
|
||||
n += mAddonMap.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
||||
n += mHistogramMap.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
||||
{ // Scope for mHashMutex lock
|
||||
MutexAutoLock lock(mHashMutex);
|
||||
n += mPrivateSQL.SizeOfExcludingThis(aMallocSizeOf);
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "nsDirectoryServiceDefs.h"
|
||||
#include "mozilla/FileUtils.h"
|
||||
#include "mozilla/Services.h"
|
||||
#include "mozilla/unused.h"
|
||||
#include "nsIStringBundle.h"
|
||||
#include "nsIXULAppInfo.h"
|
||||
#include "nsContentUtils.h"
|
||||
@@ -80,7 +81,7 @@ struct ScopedCanberraFile {
|
||||
}
|
||||
|
||||
void forget() {
|
||||
mFile.forget();
|
||||
mozilla::unused << mFile.forget();
|
||||
}
|
||||
nsIFile* operator->() { return mFile; }
|
||||
operator nsIFile*() { return mFile; }
|
||||
|
||||
@@ -475,9 +475,9 @@ CycleCollectedJSRuntime::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const
|
||||
{
|
||||
size_t n = 0;
|
||||
|
||||
// nullptr for the second arg; we're not measuring anything hanging off the
|
||||
// entries in mJSHolders.
|
||||
n += mJSHolders.SizeOfExcludingThis(nullptr, aMallocSizeOf);
|
||||
// We're deliberately not measuring anything hanging off the entries in
|
||||
// mJSHolders.
|
||||
n += mJSHolders.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
@@ -318,7 +318,7 @@ CategoryNode::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf)
|
||||
{
|
||||
// We don't measure the strings pointed to by the entries because the
|
||||
// pointers are non-owning.
|
||||
return mTable.SizeOfExcludingThis(nullptr, aMallocSizeOf);
|
||||
return mTable.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
||||
}
|
||||
|
||||
//
|
||||
@@ -455,17 +455,6 @@ nsCategoryManager::CollectReports(nsIHandleReportCallback* aHandleReport,
|
||||
"Memory used for the XPCOM category manager.");
|
||||
}
|
||||
|
||||
static size_t
|
||||
SizeOfCategoryManagerTableEntryExcludingThis(nsDepCharHashKey::KeyType aKey,
|
||||
const nsAutoPtr<CategoryNode>& aData,
|
||||
MallocSizeOf aMallocSizeOf,
|
||||
void* aUserArg)
|
||||
{
|
||||
// We don't measure the string pointed to by aKey because it's a non-owning
|
||||
// pointer.
|
||||
return aData.get()->SizeOfExcludingThis(aMallocSizeOf);
|
||||
}
|
||||
|
||||
size_t
|
||||
nsCategoryManager::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf)
|
||||
{
|
||||
@@ -473,8 +462,11 @@ nsCategoryManager::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf)
|
||||
|
||||
n += PL_SizeOfArenaPoolExcludingPool(&mArena, aMallocSizeOf);
|
||||
|
||||
n += mTable.SizeOfExcludingThis(SizeOfCategoryManagerTableEntryExcludingThis,
|
||||
aMallocSizeOf);
|
||||
n += mTable.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
||||
for (auto iter = mTable.ConstIter(); !iter.Done(); iter.Next()) {
|
||||
// We don't measure the key string because it's a non-owning pointer.
|
||||
n += iter.Data().get()->SizeOfExcludingThis(aMallocSizeOf);
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
@@ -1810,26 +1810,6 @@ nsComponentManagerImpl::ContractIDToCID(const char* aContractID,
|
||||
return NS_ERROR_FACTORY_NOT_REGISTERED;
|
||||
}
|
||||
|
||||
static size_t
|
||||
SizeOfFactoriesEntryExcludingThis(nsIDHashKey::KeyType aKey,
|
||||
nsFactoryEntry* const& aData,
|
||||
MallocSizeOf aMallocSizeOf,
|
||||
void* aUserArg)
|
||||
{
|
||||
return aData->SizeOfIncludingThis(aMallocSizeOf);
|
||||
}
|
||||
|
||||
static size_t
|
||||
SizeOfContractIDsEntryExcludingThis(nsCStringHashKey::KeyType aKey,
|
||||
nsFactoryEntry* const& aData,
|
||||
MallocSizeOf aMallocSizeOf,
|
||||
void* aUserArg)
|
||||
{
|
||||
// We don't measure the nsFactoryEntry data because its owned by mFactories
|
||||
// (which measures them in SizeOfFactoriesEntryExcludingThis).
|
||||
return aKey.SizeOfExcludingThisMustBeUnshared(aMallocSizeOf);
|
||||
}
|
||||
|
||||
MOZ_DEFINE_MALLOC_SIZE_OF(ComponentManagerMallocSizeOf)
|
||||
|
||||
NS_IMETHODIMP
|
||||
@@ -1844,19 +1824,29 @@ nsComponentManagerImpl::CollectReports(nsIHandleReportCallback* aHandleReport,
|
||||
|
||||
size_t
|
||||
nsComponentManagerImpl::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf)
|
||||
const
|
||||
{
|
||||
size_t n = aMallocSizeOf(this);
|
||||
n += mLoaderMap.SizeOfExcludingThis(nullptr, aMallocSizeOf);
|
||||
n += mFactories.SizeOfExcludingThis(SizeOfFactoriesEntryExcludingThis,
|
||||
aMallocSizeOf);
|
||||
n += mContractIDs.SizeOfExcludingThis(SizeOfContractIDsEntryExcludingThis,
|
||||
aMallocSizeOf);
|
||||
|
||||
n += mLoaderMap.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
||||
|
||||
n += mFactories.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
||||
for (auto iter = mFactories.ConstIter(); !iter.Done(); iter.Next()) {
|
||||
n += iter.Data()->SizeOfIncludingThis(aMallocSizeOf);
|
||||
}
|
||||
|
||||
n += mContractIDs.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
||||
for (auto iter = mContractIDs.ConstIter(); !iter.Done(); iter.Next()) {
|
||||
// We don't measure the nsFactoryEntry data because it's owned by
|
||||
// mFactories (which is measured above).
|
||||
n += iter.Key().SizeOfExcludingThisMustBeUnshared(aMallocSizeOf);
|
||||
}
|
||||
|
||||
n += sStaticModules->ShallowSizeOfIncludingThis(aMallocSizeOf);
|
||||
n += sModuleLocations->ShallowSizeOfIncludingThis(aMallocSizeOf);
|
||||
|
||||
n += mKnownStaticModules.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
||||
n += mKnownModules.SizeOfExcludingThis(nullptr, aMallocSizeOf);
|
||||
n += mKnownModules.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
||||
|
||||
n += PL_SizeOfArenaPoolExcludingPool(&mArena, aMallocSizeOf);
|
||||
|
||||
|
||||
@@ -336,7 +336,7 @@ public:
|
||||
|
||||
nsTArray<PendingServiceInfo> mPendingServices;
|
||||
|
||||
size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf);
|
||||
size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
|
||||
|
||||
#ifdef MOZ_B2G_LOADER
|
||||
// Preload XPT interface info for B2G loader.
|
||||
|
||||
+10
-16
@@ -502,29 +502,23 @@ AtomImpl::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf)
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
static size_t
|
||||
SizeOfAtomTableEntryExcludingThis(PLDHashEntryHdr* aHdr,
|
||||
MallocSizeOf aMallocSizeOf,
|
||||
void* aArg)
|
||||
{
|
||||
AtomTableEntry* entry = static_cast<AtomTableEntry*>(aHdr);
|
||||
return entry->mAtom->SizeOfIncludingThis(aMallocSizeOf);
|
||||
}
|
||||
|
||||
void
|
||||
NS_SizeOfAtomTablesIncludingThis(MallocSizeOf aMallocSizeOf,
|
||||
size_t* aMain, size_t* aStatic)
|
||||
{
|
||||
*aMain = gAtomTable
|
||||
? PL_DHashTableSizeOfExcludingThis(gAtomTable,
|
||||
SizeOfAtomTableEntryExcludingThis,
|
||||
aMallocSizeOf)
|
||||
: 0;
|
||||
*aMain = 0;
|
||||
if (gAtomTable) {
|
||||
*aMain += gAtomTable->ShallowSizeOfIncludingThis(aMallocSizeOf);
|
||||
for (auto iter = gAtomTable->Iter(); !iter.Done(); iter.Next()) {
|
||||
auto entry = static_cast<AtomTableEntry*>(iter.Get());
|
||||
*aMain += entry->mAtom->SizeOfIncludingThis(aMallocSizeOf);
|
||||
}
|
||||
}
|
||||
|
||||
// The atoms in the this table are almost certainly stored in static data, so
|
||||
// we don't need a SizeOfEntry function.
|
||||
// we don't need to measure entries separately.
|
||||
*aStatic = gStaticAtomTable
|
||||
? gStaticAtomTable->SizeOfIncludingThis(nullptr, aMallocSizeOf)
|
||||
? gStaticAtomTable->ShallowSizeOfIncludingThis(aMallocSizeOf)
|
||||
: 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -144,15 +144,6 @@ public:
|
||||
PR_DestroyLock(mLock);
|
||||
}
|
||||
|
||||
static size_t
|
||||
SizeOfEntryExcludingThis(const T* aKey, const nsAutoPtr<OrderingEntry>& aEntry,
|
||||
MallocSizeOf aMallocSizeOf, void* aUserArg)
|
||||
{
|
||||
// NB: Key is accounted for in the entry.
|
||||
size_t n = aEntry->SizeOfIncludingThis(aMallocSizeOf);
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t
|
||||
SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
|
||||
{
|
||||
@@ -160,7 +151,11 @@ public:
|
||||
|
||||
{
|
||||
PRAutoLock _(mLock);
|
||||
n += mOrdering.SizeOfExcludingThis(SizeOfEntryExcludingThis, aMallocSizeOf);
|
||||
n += mOrdering.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
||||
for (auto iter = mOrdering.ConstIter(); !iter.Done(); iter.Next()) {
|
||||
// NB: Key is accounted for in the entry.
|
||||
n += iter.Data()->SizeOfIncludingThis(aMallocSizeOf);
|
||||
}
|
||||
}
|
||||
|
||||
return n;
|
||||
|
||||
@@ -267,80 +267,28 @@ public:
|
||||
void Clear() { nsTHashtable<EntryType>::Clear(); }
|
||||
|
||||
/**
|
||||
* client must provide a SizeOfEntryExcludingThisFun function for
|
||||
* SizeOfExcludingThis.
|
||||
* @param aKey the key being enumerated
|
||||
* @param aData Reference to data being enumerated.
|
||||
* @param aMallocSizeOf the function used to measure heap-allocated blocks
|
||||
* @param aUserArg passed unchanged from SizeOf{In,Ex}cludingThis
|
||||
* @return summed size of the things pointed to by the entries
|
||||
*/
|
||||
typedef size_t
|
||||
(*SizeOfEntryExcludingThisFun)(KeyType aKey,
|
||||
const DataType& aData,
|
||||
mozilla::MallocSizeOf aMallocSizeOf,
|
||||
void* aUserArg);
|
||||
|
||||
/**
|
||||
* Measure the size of the table's entry storage and the table itself.
|
||||
* If |aSizeOfEntryExcludingThis| is non-nullptr, measure the size of things
|
||||
* pointed to by entries.
|
||||
* Measure the size of the table's entry storage. The size of things pointed
|
||||
* to by entries must be measured separately; hence the "Shallow" prefix.
|
||||
*
|
||||
* @param aSizeOfEntryExcludingThis
|
||||
* the <code>SizeOfEntryExcludingThisFun</code> function to call
|
||||
* @param aMallocSizeOf the function used to meeasure heap-allocated blocks
|
||||
* @param aUserArg a point to pass to the
|
||||
* <code>SizeOfEntryExcludingThisFun</code> function
|
||||
* @return the summed size of the entries, the table, and the table's storage
|
||||
* @param aMallocSizeOf the function used to measure heap-allocated blocks
|
||||
* @return the summed size of the table's storage
|
||||
*/
|
||||
size_t SizeOfIncludingThis(SizeOfEntryExcludingThisFun aSizeOfEntryExcludingThis,
|
||||
mozilla::MallocSizeOf aMallocSizeOf,
|
||||
void* aUserArg = nullptr)
|
||||
size_t ShallowSizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
|
||||
{
|
||||
return aMallocSizeOf(this) +
|
||||
this->SizeOfExcludingThis(aSizeOfEntryExcludingThis, aMallocSizeOf,
|
||||
aUserArg);
|
||||
return this->mTable.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
||||
}
|
||||
|
||||
/**
|
||||
* Measure the size of the table's entry storage, and if
|
||||
* |aSizeOfEntryExcludingThis| is non-nullptr, measure the size of things
|
||||
* pointed to by entries.
|
||||
*
|
||||
* @param aSizeOfEntryExcludingThis the
|
||||
* <code>SizeOfEntryExcludingThisFun</code> function to call
|
||||
* @param aMallocSizeOf the function used to measure heap-allocated blocks
|
||||
* @param aUserArg a pointer to pass to the
|
||||
* <code>SizeOfEntryExcludingThisFun</code> function
|
||||
* @return the summed size of all the entries
|
||||
* Like ShallowSizeOfExcludingThis, but includes sizeof(*this).
|
||||
*/
|
||||
size_t SizeOfExcludingThis(SizeOfEntryExcludingThisFun aSizeOfEntryExcludingThis,
|
||||
mozilla::MallocSizeOf aMallocSizeOf,
|
||||
void* aUserArg = nullptr) const
|
||||
size_t ShallowSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
|
||||
{
|
||||
if (aSizeOfEntryExcludingThis) {
|
||||
s_SizeOfArgs args = { aSizeOfEntryExcludingThis, aUserArg };
|
||||
return PL_DHashTableSizeOfExcludingThis(&this->mTable, s_SizeOfStub,
|
||||
aMallocSizeOf, &args);
|
||||
}
|
||||
return PL_DHashTableSizeOfExcludingThis(&this->mTable, nullptr,
|
||||
aMallocSizeOf);
|
||||
return aMallocSizeOf(this) + ShallowSizeOfExcludingThis(aMallocSizeOf);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
using nsTHashtable<EntryType>::MarkImmutable;
|
||||
#endif
|
||||
|
||||
protected:
|
||||
struct s_SizeOfArgs
|
||||
{
|
||||
SizeOfEntryExcludingThisFun func;
|
||||
void* userArg;
|
||||
};
|
||||
|
||||
static size_t s_SizeOfStub(PLDHashEntryHdr* aEntry,
|
||||
mozilla::MallocSizeOf aMallocSizeOf,
|
||||
void* aArg);
|
||||
};
|
||||
|
||||
//
|
||||
@@ -366,20 +314,4 @@ nsBaseHashtableET<KeyClass, DataType>::~nsBaseHashtableET()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// nsBaseHashtable definitions
|
||||
//
|
||||
|
||||
template<class KeyClass, class DataType, class UserDataType>
|
||||
size_t
|
||||
nsBaseHashtable<KeyClass, DataType, UserDataType>::s_SizeOfStub(
|
||||
PLDHashEntryHdr* aHdr, mozilla::MallocSizeOf aMallocSizeOf, void* aArg)
|
||||
{
|
||||
EntryType* ent = static_cast<EntryType*>(aHdr);
|
||||
s_SizeOfArgs* eargs = static_cast<s_SizeOfArgs*>(aArg);
|
||||
|
||||
return (eargs->func)(ent->GetKey(), ent->mData, aMallocSizeOf, eargs->userArg);
|
||||
}
|
||||
|
||||
#endif // nsBaseHashtable_h__
|
||||
|
||||
+25
-93
@@ -270,68 +270,47 @@ public:
|
||||
}
|
||||
|
||||
/**
|
||||
* client must provide a <code>SizeOfEntryExcludingThisFun</code> function for
|
||||
* SizeOfExcludingThis.
|
||||
* @param aEntry the entry being enumerated
|
||||
* @param mallocSizeOf the function used to measure heap-allocated blocks
|
||||
* @param arg passed unchanged from <code>SizeOf{In,Ex}cludingThis</code>
|
||||
* @return summed size of the things pointed to by the entries
|
||||
*/
|
||||
typedef size_t (*SizeOfEntryExcludingThisFun)(EntryType* aEntry,
|
||||
mozilla::MallocSizeOf aMallocSizeOf,
|
||||
void* aArg);
|
||||
|
||||
/**
|
||||
* Measure the size of the table's entry storage, and if
|
||||
* |aSizeOfEntryExcludingThis| is non-nullptr, measure the size of things
|
||||
* pointed to by entries.
|
||||
* Measure the size of the table's entry storage. Does *not* measure anything
|
||||
* hanging off table entries; hence the "Shallow" prefix. To measure that,
|
||||
* either use SizeOfExcludingThis() or iterate manually over the entries,
|
||||
* calling SizeOfExcludingThis() on each one.
|
||||
*
|
||||
* @param sizeOfEntryExcludingThis the
|
||||
* <code>SizeOfEntryExcludingThisFun</code> function to call
|
||||
* @param mallocSizeOf the function used to measure heap-allocated blocks
|
||||
* @param userArg a pointer to pass to the
|
||||
* <code>SizeOfEntryExcludingThisFun</code> function
|
||||
* @return the summed size of all the entries
|
||||
* @param aMallocSizeOf the function used to measure heap-allocated blocks
|
||||
* @return the measured shallow size of the table
|
||||
*/
|
||||
size_t SizeOfExcludingThis(SizeOfEntryExcludingThisFun aSizeOfEntryExcludingThis,
|
||||
mozilla::MallocSizeOf aMallocSizeOf,
|
||||
void* aUserArg = nullptr) const
|
||||
size_t ShallowSizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
|
||||
{
|
||||
if (aSizeOfEntryExcludingThis) {
|
||||
s_SizeOfArgs args = { aSizeOfEntryExcludingThis, aUserArg };
|
||||
return PL_DHashTableSizeOfExcludingThis(&mTable, s_SizeOfStub,
|
||||
aMallocSizeOf, &args);
|
||||
}
|
||||
return PL_DHashTableSizeOfExcludingThis(&mTable, nullptr, aMallocSizeOf);
|
||||
return mTable.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
||||
}
|
||||
|
||||
/**
|
||||
* If the EntryType defines SizeOfExcludingThis, there's no need to define a new
|
||||
* SizeOfEntryExcludingThisFun.
|
||||
* Like ShallowSizeOfExcludingThis, but includes sizeof(*this).
|
||||
*/
|
||||
size_t ShallowSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
|
||||
{
|
||||
return aMallocSizeOf(this) + ShallowSizeOfExcludingThis(aMallocSizeOf);
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a "deep" measurement of the table. To use it, |EntryType| must
|
||||
* define SizeOfExcludingThis, and that method will be called on all live
|
||||
* entries.
|
||||
*/
|
||||
size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
|
||||
{
|
||||
return SizeOfExcludingThis(BasicSizeOfEntryExcludingThisFun, aMallocSizeOf);
|
||||
size_t n = ShallowSizeOfExcludingThis(aMallocSizeOf);
|
||||
for (auto iter = ConstIter(); !iter.Done(); iter.Next()) {
|
||||
n += (*iter.Get()).SizeOfExcludingThis(aMallocSizeOf);
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
/**
|
||||
* Like SizeOfExcludingThis, but includes sizeof(*this).
|
||||
*/
|
||||
size_t SizeOfIncludingThis(SizeOfEntryExcludingThisFun aSizeOfEntryExcludingThis,
|
||||
mozilla::MallocSizeOf aMallocSizeOf,
|
||||
void* aUserArg = nullptr) const
|
||||
{
|
||||
return aMallocSizeOf(this) +
|
||||
SizeOfExcludingThis(aSizeOfEntryExcludingThis, aMallocSizeOf, aUserArg);
|
||||
}
|
||||
|
||||
/**
|
||||
* If the EntryType defines SizeOfExcludingThis, there's no need to define a new
|
||||
* SizeOfEntryExcludingThisFun.
|
||||
*/
|
||||
size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
|
||||
{
|
||||
return SizeOfIncludingThis(BasicSizeOfEntryExcludingThisFun, aMallocSizeOf);
|
||||
return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -374,22 +353,6 @@ protected:
|
||||
|
||||
static void s_InitEntry(PLDHashEntryHdr* aEntry, const void* aKey);
|
||||
|
||||
/**
|
||||
* passed internally during sizeOf counting. Allocated on the stack.
|
||||
*
|
||||
* @param userFunc the SizeOfEntryExcludingThisFun passed to
|
||||
* SizeOf{In,Ex}cludingThis by the client
|
||||
* @param userArg the userArg passed unaltered
|
||||
*/
|
||||
struct s_SizeOfArgs
|
||||
{
|
||||
SizeOfEntryExcludingThisFun userFunc;
|
||||
void* userArg;
|
||||
};
|
||||
|
||||
static size_t s_SizeOfStub(PLDHashEntryHdr* aEntry,
|
||||
mozilla::MallocSizeOf aMallocSizeOf, void* aArg);
|
||||
|
||||
private:
|
||||
// copy constructor, not implemented
|
||||
nsTHashtable(nsTHashtable<EntryType>& aToCopy) = delete;
|
||||
@@ -399,14 +362,6 @@ private:
|
||||
*/
|
||||
static const PLDHashTableOps* Ops();
|
||||
|
||||
/**
|
||||
* An implementation of SizeOfEntryExcludingThisFun that calls SizeOfExcludingThis()
|
||||
* on each entry.
|
||||
*/
|
||||
static size_t BasicSizeOfEntryExcludingThisFun(EntryType* aEntry,
|
||||
mozilla::MallocSizeOf aMallocSizeOf,
|
||||
void*);
|
||||
|
||||
// assignment operator, not implemented
|
||||
nsTHashtable<EntryType>& operator=(nsTHashtable<EntryType>& aToEqual) = delete;
|
||||
};
|
||||
@@ -447,16 +402,6 @@ nsTHashtable<EntryType>::Ops()
|
||||
return &sOps;
|
||||
}
|
||||
|
||||
// static
|
||||
template<class EntryType>
|
||||
size_t
|
||||
nsTHashtable<EntryType>::BasicSizeOfEntryExcludingThisFun(EntryType* aEntry,
|
||||
mozilla::MallocSizeOf aMallocSizeOf,
|
||||
void*)
|
||||
{
|
||||
return aEntry->SizeOfExcludingThis(aMallocSizeOf);
|
||||
}
|
||||
|
||||
// static definitions
|
||||
|
||||
template<class EntryType>
|
||||
@@ -506,19 +451,6 @@ nsTHashtable<EntryType>::s_InitEntry(PLDHashEntryHdr* aEntry,
|
||||
new (aEntry) EntryType(reinterpret_cast<KeyTypePointer>(aKey));
|
||||
}
|
||||
|
||||
template<class EntryType>
|
||||
size_t
|
||||
nsTHashtable<EntryType>::s_SizeOfStub(PLDHashEntryHdr* aEntry,
|
||||
mozilla::MallocSizeOf aMallocSizeOf,
|
||||
void* aArg)
|
||||
{
|
||||
// dereferences the function-pointer to the user's enumeration function
|
||||
return (*reinterpret_cast<s_SizeOfArgs*>(aArg)->userFunc)(
|
||||
static_cast<EntryType*>(aEntry),
|
||||
aMallocSizeOf,
|
||||
reinterpret_cast<s_SizeOfArgs*>(aArg)->userArg);
|
||||
}
|
||||
|
||||
class nsCycleCollectionTraversalCallback;
|
||||
|
||||
template<class EntryType>
|
||||
|
||||
+35
-74
@@ -218,8 +218,7 @@ PLDHashTable::PLDHashTable(const PLDHashTableOps* aOps, uint32_t aEntrySize,
|
||||
, mEntrySize(aEntrySize)
|
||||
, mEntryCount(0)
|
||||
, mRemovedCount(0)
|
||||
, mGeneration(0)
|
||||
, mEntryStore(nullptr)
|
||||
, mEntryStore()
|
||||
#ifdef DEBUG
|
||||
, mChecker()
|
||||
#endif
|
||||
@@ -248,7 +247,6 @@ PLDHashTable::operator=(PLDHashTable&& aOther)
|
||||
mHashShift = Move(aOther.mHashShift);
|
||||
mEntryCount = Move(aOther.mEntryCount);
|
||||
mRemovedCount = Move(aOther.mRemovedCount);
|
||||
mGeneration = Move(aOther.mGeneration);
|
||||
mEntryStore = Move(aOther.mEntryStore);
|
||||
#ifdef DEBUG
|
||||
mChecker = Move(aOther.mChecker);
|
||||
@@ -259,7 +257,7 @@ PLDHashTable::operator=(PLDHashTable&& aOther)
|
||||
#ifdef DEBUG
|
||||
AutoDestructorOp op(mChecker);
|
||||
#endif
|
||||
aOther.mEntryStore = nullptr;
|
||||
aOther.mEntryStore.Set(nullptr);
|
||||
}
|
||||
|
||||
return *this;
|
||||
@@ -327,7 +325,8 @@ PLDHashTable::MatchEntryKeyhash(PLDHashEntryHdr* aEntry, PLDHashNumber aKeyHash)
|
||||
PLDHashEntryHdr*
|
||||
PLDHashTable::AddressEntry(uint32_t aIndex)
|
||||
{
|
||||
return reinterpret_cast<PLDHashEntryHdr*>(mEntryStore + aIndex * mEntrySize);
|
||||
return reinterpret_cast<PLDHashEntryHdr*>(
|
||||
mEntryStore.Get() + aIndex * mEntrySize);
|
||||
}
|
||||
|
||||
PLDHashTable::~PLDHashTable()
|
||||
@@ -336,12 +335,12 @@ PLDHashTable::~PLDHashTable()
|
||||
AutoDestructorOp op(mChecker);
|
||||
#endif
|
||||
|
||||
if (!mEntryStore) {
|
||||
if (!mEntryStore.Get()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Clear any remaining live entries.
|
||||
char* entryAddr = mEntryStore;
|
||||
char* entryAddr = mEntryStore.Get();
|
||||
char* entryLimit = entryAddr + Capacity() * mEntrySize;
|
||||
while (entryAddr < entryLimit) {
|
||||
PLDHashEntryHdr* entry = (PLDHashEntryHdr*)entryAddr;
|
||||
@@ -351,9 +350,7 @@ PLDHashTable::~PLDHashTable()
|
||||
entryAddr += mEntrySize;
|
||||
}
|
||||
|
||||
// Free entry storage last.
|
||||
free(mEntryStore);
|
||||
mEntryStore = nullptr;
|
||||
// Entry storage is freed last, by ~EntryStore().
|
||||
}
|
||||
|
||||
void
|
||||
@@ -382,7 +379,7 @@ template <PLDHashTable::SearchReason Reason>
|
||||
PLDHashEntryHdr* PL_DHASH_FASTCALL
|
||||
PLDHashTable::SearchTable(const void* aKey, PLDHashNumber aKeyHash)
|
||||
{
|
||||
MOZ_ASSERT(mEntryStore);
|
||||
MOZ_ASSERT(mEntryStore.Get());
|
||||
NS_ASSERTION(!(aKeyHash & kCollisionFlag),
|
||||
"!(aKeyHash & kCollisionFlag)");
|
||||
|
||||
@@ -451,7 +448,7 @@ PLDHashTable::SearchTable(const void* aKey, PLDHashNumber aKeyHash)
|
||||
PLDHashEntryHdr* PL_DHASH_FASTCALL
|
||||
PLDHashTable::FindFreeEntry(PLDHashNumber aKeyHash)
|
||||
{
|
||||
MOZ_ASSERT(mEntryStore);
|
||||
MOZ_ASSERT(mEntryStore.Get());
|
||||
NS_ASSERTION(!(aKeyHash & kCollisionFlag),
|
||||
"!(aKeyHash & kCollisionFlag)");
|
||||
|
||||
@@ -490,7 +487,7 @@ PLDHashTable::FindFreeEntry(PLDHashNumber aKeyHash)
|
||||
bool
|
||||
PLDHashTable::ChangeTable(int32_t aDeltaLog2)
|
||||
{
|
||||
MOZ_ASSERT(mEntryStore);
|
||||
MOZ_ASSERT(mEntryStore.Get());
|
||||
|
||||
// Look, but don't touch, until we succeed in getting new entry store.
|
||||
int32_t oldLog2 = kHashBits - mHashShift;
|
||||
@@ -513,14 +510,13 @@ PLDHashTable::ChangeTable(int32_t aDeltaLog2)
|
||||
// We can't fail from here on, so update table parameters.
|
||||
mHashShift = kHashBits - newLog2;
|
||||
mRemovedCount = 0;
|
||||
mGeneration++;
|
||||
|
||||
// Assign the new entry store to table.
|
||||
memset(newEntryStore, 0, nbytes);
|
||||
char* oldEntryStore;
|
||||
char* oldEntryAddr;
|
||||
oldEntryAddr = oldEntryStore = mEntryStore;
|
||||
mEntryStore = newEntryStore;
|
||||
oldEntryAddr = oldEntryStore = mEntryStore.Get();
|
||||
mEntryStore.Set(newEntryStore);
|
||||
PLDHashMoveEntry moveEntry = mOps->moveEntry;
|
||||
|
||||
// Copy only live entries, leaving removed ones behind.
|
||||
@@ -544,7 +540,7 @@ PLDHashTable::ChangeTable(int32_t aDeltaLog2)
|
||||
MOZ_ALWAYS_INLINE PLDHashNumber
|
||||
PLDHashTable::ComputeKeyHash(const void* aKey)
|
||||
{
|
||||
MOZ_ASSERT(mEntryStore);
|
||||
MOZ_ASSERT(mEntryStore.Get());
|
||||
|
||||
PLDHashNumber keyHash = mOps->hashKey(this, aKey);
|
||||
keyHash *= kGoldenRatio;
|
||||
@@ -565,10 +561,10 @@ PLDHashTable::Search(const void* aKey)
|
||||
AutoReadOp op(mChecker);
|
||||
#endif
|
||||
|
||||
PLDHashEntryHdr* entry =
|
||||
mEntryStore ? SearchTable<ForSearchOrRemove>(aKey, ComputeKeyHash(aKey))
|
||||
: nullptr;
|
||||
|
||||
PLDHashEntryHdr* entry = mEntryStore.Get()
|
||||
? SearchTable<ForSearchOrRemove>(aKey,
|
||||
ComputeKeyHash(aKey))
|
||||
: nullptr;
|
||||
return entry;
|
||||
}
|
||||
|
||||
@@ -580,16 +576,16 @@ PLDHashTable::Add(const void* aKey, const mozilla::fallible_t&)
|
||||
#endif
|
||||
|
||||
// Allocate the entry storage if it hasn't already been allocated.
|
||||
if (!mEntryStore) {
|
||||
if (!mEntryStore.Get()) {
|
||||
uint32_t nbytes;
|
||||
// We already checked this in the constructor, so it must still be true.
|
||||
MOZ_RELEASE_ASSERT(SizeOfEntryStore(CapacityFromHashShift(), mEntrySize,
|
||||
&nbytes));
|
||||
mEntryStore = (char*)malloc(nbytes);
|
||||
if (!mEntryStore) {
|
||||
mEntryStore.Set((char*)malloc(nbytes));
|
||||
if (!mEntryStore.Get()) {
|
||||
return nullptr;
|
||||
}
|
||||
memset(mEntryStore, 0, nbytes);
|
||||
memset(mEntryStore.Get(), 0, nbytes);
|
||||
}
|
||||
|
||||
// If alpha is >= .75, grow or compress the table. If aKey is already in the
|
||||
@@ -638,7 +634,7 @@ PLDHashTable::Add(const void* aKey)
|
||||
{
|
||||
PLDHashEntryHdr* entry = Add(aKey, fallible);
|
||||
if (!entry) {
|
||||
if (!mEntryStore) {
|
||||
if (!mEntryStore.Get()) {
|
||||
// We OOM'd while allocating the initial entry storage.
|
||||
uint32_t nbytes;
|
||||
(void) SizeOfEntryStore(CapacityFromHashShift(), mEntrySize, &nbytes);
|
||||
@@ -661,9 +657,10 @@ PLDHashTable::Remove(const void* aKey)
|
||||
AutoWriteOp op(mChecker);
|
||||
#endif
|
||||
|
||||
PLDHashEntryHdr* entry =
|
||||
mEntryStore ? SearchTable<ForSearchOrRemove>(aKey, ComputeKeyHash(aKey))
|
||||
: nullptr;
|
||||
PLDHashEntryHdr* entry = mEntryStore.Get()
|
||||
? SearchTable<ForSearchOrRemove>(aKey,
|
||||
ComputeKeyHash(aKey))
|
||||
: nullptr;
|
||||
if (entry) {
|
||||
RawRemove(entry);
|
||||
ShrinkIfAppropriate();
|
||||
@@ -689,7 +686,7 @@ PLDHashTable::RawRemove(PLDHashEntryHdr* aEntry)
|
||||
// active, which doesn't fit well into how Checker's mState variable works.
|
||||
MOZ_ASSERT(mChecker.IsWritable());
|
||||
|
||||
MOZ_ASSERT(mEntryStore);
|
||||
MOZ_ASSERT(mEntryStore.Get());
|
||||
|
||||
MOZ_ASSERT(EntryIsLive(aEntry), "EntryIsLive(aEntry)");
|
||||
|
||||
@@ -730,56 +727,20 @@ PLDHashTable::ShrinkIfAppropriate()
|
||||
}
|
||||
}
|
||||
|
||||
MOZ_ALWAYS_INLINE size_t
|
||||
PLDHashTable::SizeOfExcludingThis(
|
||||
PLDHashSizeOfEntryExcludingThisFun aSizeOfEntryExcludingThis,
|
||||
MallocSizeOf aMallocSizeOf, void* aArg /* = nullptr */) const
|
||||
size_t
|
||||
PLDHashTable::ShallowSizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const
|
||||
{
|
||||
#ifdef DEBUG
|
||||
AutoReadOp op(mChecker);
|
||||
#endif
|
||||
|
||||
if (!mEntryStore) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t n = aMallocSizeOf(mEntryStore);
|
||||
if (aSizeOfEntryExcludingThis) {
|
||||
for (auto iter = ConstIter(); !iter.Done(); iter.Next()) {
|
||||
n += aSizeOfEntryExcludingThis(iter.Get(), aMallocSizeOf, aArg);
|
||||
}
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
MOZ_ALWAYS_INLINE size_t
|
||||
PLDHashTable::SizeOfIncludingThis(
|
||||
PLDHashSizeOfEntryExcludingThisFun aSizeOfEntryExcludingThis,
|
||||
MallocSizeOf aMallocSizeOf, void* aArg /* = nullptr */) const
|
||||
{
|
||||
return aMallocSizeOf(this) +
|
||||
SizeOfExcludingThis(aSizeOfEntryExcludingThis, aMallocSizeOf, aArg);
|
||||
return aMallocSizeOf(mEntryStore.Get());
|
||||
}
|
||||
|
||||
size_t
|
||||
PL_DHashTableSizeOfExcludingThis(
|
||||
const PLDHashTable* aTable,
|
||||
PLDHashSizeOfEntryExcludingThisFun aSizeOfEntryExcludingThis,
|
||||
MallocSizeOf aMallocSizeOf, void* aArg /* = nullptr */)
|
||||
PLDHashTable::ShallowSizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
|
||||
{
|
||||
return aTable->SizeOfExcludingThis(aSizeOfEntryExcludingThis,
|
||||
aMallocSizeOf, aArg);
|
||||
}
|
||||
|
||||
size_t
|
||||
PL_DHashTableSizeOfIncludingThis(
|
||||
const PLDHashTable* aTable,
|
||||
PLDHashSizeOfEntryExcludingThisFun aSizeOfEntryExcludingThis,
|
||||
MallocSizeOf aMallocSizeOf, void* aArg /* = nullptr */)
|
||||
{
|
||||
return aTable->SizeOfIncludingThis(aSizeOfEntryExcludingThis,
|
||||
aMallocSizeOf, aArg);
|
||||
return aMallocSizeOf(this) + ShallowSizeOfExcludingThis(aMallocSizeOf);
|
||||
}
|
||||
|
||||
PLDHashTable::Iterator::Iterator(Iterator&& aOther)
|
||||
@@ -803,9 +764,9 @@ PLDHashTable::Iterator::Iterator(Iterator&& aOther)
|
||||
|
||||
PLDHashTable::Iterator::Iterator(PLDHashTable* aTable)
|
||||
: mTable(aTable)
|
||||
, mStart(mTable->mEntryStore)
|
||||
, mLimit(mTable->mEntryStore + mTable->Capacity() * mTable->mEntrySize)
|
||||
, mCurrent(mTable->mEntryStore)
|
||||
, mStart(mTable->mEntryStore.Get())
|
||||
, mLimit(mTable->mEntryStore.Get() + mTable->Capacity() * mTable->mEntrySize)
|
||||
, mCurrent(mTable->mEntryStore.Get())
|
||||
, mNexts(0)
|
||||
, mNextsLimit(mTable->EntryCount())
|
||||
, mHaveRemoved(false)
|
||||
|
||||
+45
-35
@@ -52,9 +52,6 @@ private:
|
||||
PLDHashNumber mKeyHash;
|
||||
};
|
||||
|
||||
typedef size_t (*PLDHashSizeOfEntryExcludingThisFun)(
|
||||
PLDHashEntryHdr* aHdr, mozilla::MallocSizeOf aMallocSizeOf, void* aArg);
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
// This class does three kinds of checking:
|
||||
@@ -212,19 +209,48 @@ private:
|
||||
// hashing is more space-efficient unless the element size gets large (in which
|
||||
// case you should keep using double hashing but switch to using pointer
|
||||
// elements). Also, with double hashing, you can't safely hold an entry pointer
|
||||
// and use it after an ADD or REMOVE operation, unless you sample
|
||||
// aTable->mGeneration before adding or removing, and compare the sample after,
|
||||
// dereferencing the entry pointer only if aTable->mGeneration has not changed.
|
||||
// and use it after an add or remove operation, unless you sample Generation()
|
||||
// before adding or removing, and compare the sample after, dereferencing the
|
||||
// entry pointer only if Generation() has not changed.
|
||||
class PLDHashTable
|
||||
{
|
||||
private:
|
||||
// This class maintains the invariant that every time the entry store is
|
||||
// changed, the generation is updated.
|
||||
class EntryStore
|
||||
{
|
||||
private:
|
||||
char* mEntryStore;
|
||||
uint32_t mGeneration;
|
||||
|
||||
public:
|
||||
EntryStore() : mEntryStore(nullptr), mGeneration(0) {}
|
||||
|
||||
~EntryStore()
|
||||
{
|
||||
free(mEntryStore);
|
||||
mEntryStore = nullptr;
|
||||
mGeneration++; // a little paranoid, but why not be extra safe?
|
||||
}
|
||||
|
||||
char* Get() { return mEntryStore; }
|
||||
const char* Get() const { return mEntryStore; }
|
||||
|
||||
void Set(char* aEntryStore)
|
||||
{
|
||||
mEntryStore = aEntryStore;
|
||||
mGeneration++;
|
||||
}
|
||||
|
||||
uint32_t Generation() const { return mGeneration; }
|
||||
};
|
||||
|
||||
const PLDHashTableOps* const mOps; // Virtual operations; see below.
|
||||
int16_t mHashShift; // Multiplicative hash shift.
|
||||
const uint32_t mEntrySize; // Number of bytes in an entry.
|
||||
uint32_t mEntryCount; // Number of entries in table.
|
||||
uint32_t mRemovedCount; // Removed entry sentinels in table.
|
||||
uint32_t mGeneration; // Entry storage generation number.
|
||||
char* mEntryStore; // Entry storage; allocated lazily.
|
||||
EntryStore mEntryStore; // (Lazy) entry storage and generation.
|
||||
|
||||
#ifdef DEBUG
|
||||
mutable Checker mChecker;
|
||||
@@ -264,9 +290,9 @@ public:
|
||||
// move assignment operator cannot modify them.
|
||||
: mOps(aOther.mOps)
|
||||
, mEntrySize(aOther.mEntrySize)
|
||||
// Initialize these two fields because they are required for a safe call
|
||||
// to the destructor, which the move assignment operator does.
|
||||
, mEntryStore(nullptr)
|
||||
// Initialize this field because it is required for a safe call to the
|
||||
// destructor, which the move assignment operator does.
|
||||
, mEntryStore()
|
||||
#ifdef DEBUG
|
||||
, mChecker()
|
||||
#endif
|
||||
@@ -286,12 +312,12 @@ public:
|
||||
// entry storage will not have yet been allocated.
|
||||
uint32_t Capacity() const
|
||||
{
|
||||
return mEntryStore ? CapacityFromHashShift() : 0;
|
||||
return mEntryStore.Get() ? CapacityFromHashShift() : 0;
|
||||
}
|
||||
|
||||
uint32_t EntrySize() const { return mEntrySize; }
|
||||
uint32_t EntryCount() const { return mEntryCount; }
|
||||
uint32_t Generation() const { return mGeneration; }
|
||||
uint32_t Generation() const { return mEntryStore.Generation(); }
|
||||
|
||||
// To search for a |key| in |table|, call:
|
||||
//
|
||||
@@ -357,17 +383,13 @@ public:
|
||||
// a new |aLength| argument.
|
||||
void ClearAndPrepareForLength(uint32_t aLength);
|
||||
|
||||
// Measure the size of the table's entry storage, and if
|
||||
// |aSizeOfEntryExcludingThis| is non-nullptr, measure the size of things
|
||||
// pointed to by entries.
|
||||
size_t SizeOfIncludingThis(
|
||||
PLDHashSizeOfEntryExcludingThisFun aSizeOfEntryExcludingThis,
|
||||
mozilla::MallocSizeOf aMallocSizeOf, void* aArg = nullptr) const;
|
||||
// Measure the size of the table's entry storage. If the entries contain
|
||||
// pointers to other heap blocks, you have to iterate over the table and
|
||||
// measure those separately; hence the "Shallow" prefix.
|
||||
size_t ShallowSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
|
||||
|
||||
// Like SizeOfExcludingThis(), but includes sizeof(*this).
|
||||
size_t SizeOfExcludingThis(
|
||||
PLDHashSizeOfEntryExcludingThisFun aSizeOfEntryExcludingThis,
|
||||
mozilla::MallocSizeOf aMallocSizeOf, void* aArg = nullptr) const;
|
||||
// Like ShallowSizeOfExcludingThis(), but includes sizeof(*this).
|
||||
size_t ShallowSizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
|
||||
|
||||
#ifdef DEBUG
|
||||
// Mark a table as immutable for the remainder of its lifetime. This
|
||||
@@ -601,18 +623,6 @@ PL_DHashGetStubOps(void);
|
||||
void
|
||||
PL_DHashTableRawRemove(PLDHashTable* aTable, PLDHashEntryHdr* aEntry);
|
||||
|
||||
size_t
|
||||
PL_DHashTableSizeOfExcludingThis(
|
||||
const PLDHashTable* aTable,
|
||||
PLDHashSizeOfEntryExcludingThisFun aSizeOfEntryExcludingThis,
|
||||
mozilla::MallocSizeOf aMallocSizeOf, void* aArg = nullptr);
|
||||
|
||||
size_t
|
||||
PL_DHashTableSizeOfIncludingThis(
|
||||
const PLDHashTable* aTable,
|
||||
PLDHashSizeOfEntryExcludingThisFun aSizeOfEntryExcludingThis,
|
||||
mozilla::MallocSizeOf aMallocSizeOf, void* aArg = nullptr);
|
||||
|
||||
#ifdef DEBUG
|
||||
void
|
||||
PL_DHashMarkTableImmutable(PLDHashTable* aTable);
|
||||
|
||||
@@ -36,8 +36,8 @@ XPTInterfaceInfoManager::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf
|
||||
ReentrantMonitorAutoEnter monitor(mWorkingSet.mTableReentrantMonitor);
|
||||
// The entries themselves are allocated out of an arena accounted
|
||||
// for elsewhere, so don't measure them
|
||||
n += mWorkingSet.mIIDTable.SizeOfExcludingThis(nullptr, aMallocSizeOf);
|
||||
n += mWorkingSet.mNameTable.SizeOfExcludingThis(nullptr, aMallocSizeOf);
|
||||
n += mWorkingSet.mIIDTable.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
||||
n += mWorkingSet.mNameTable.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
@@ -137,10 +137,7 @@ TEST(PLDHashTableTest, LazyStorage)
|
||||
ASSERT_TRUE(false); // shouldn't hit this on an empty table
|
||||
}
|
||||
|
||||
// Using a null |mallocSizeOf| should be fine because it shouldn't be called
|
||||
// for an empty table.
|
||||
mozilla::MallocSizeOf mallocSizeOf = nullptr;
|
||||
ASSERT_EQ(PL_DHashTableSizeOfExcludingThis(&t, nullptr, mallocSizeOf), 0u);
|
||||
ASSERT_EQ(t.ShallowSizeOfExcludingThis(moz_malloc_size_of), 0u);
|
||||
}
|
||||
|
||||
// A trivial hash function is good enough here. It's also super-fast for
|
||||
|
||||
Reference in New Issue
Block a user