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:
2021-08-30 09:33:31 +08:00
parent be0dbe88f0
commit d43e6f58e1
73 changed files with 829 additions and 1432 deletions
+2 -1
View File
@@ -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;
}
+2 -2
View File
@@ -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(
+5 -11
View File
@@ -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;
+1 -1
View File
@@ -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);
+1 -5
View File
@@ -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();
+1 -1
View File
@@ -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;
}
+15 -13
View File
@@ -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;
}
+1 -1
View File
@@ -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();
+1 -1
View File
@@ -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();
}
}
+1 -2
View File
@@ -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)
+2 -2
View File
@@ -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;
}
+1 -2
View File
@@ -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;
}
+1 -2
View File
@@ -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);
+1 -3
View File
@@ -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();
+1 -1
View File
@@ -657,7 +657,7 @@ gfxDWriteFont::AddSizeOfExcludingThis(MallocSizeOf aMallocSizeOf,
aSizes->mFontInstances += aMallocSizeOf(mMetrics);
if (mGlyphWidths) {
aSizes->mFontInstances +=
mGlyphWidths->SizeOfIncludingThis(nullptr, aMallocSizeOf);
mGlyphWidths->ShallowSizeOfIncludingThis(aMallocSizeOf);
}
}
+1 -1
View File
@@ -185,7 +185,7 @@ protected:
nsTHashtable<nsStringHashKey> mSkipSpaceLookupCheckFamilies;
private:
nsRefPtrHashtable<nsStringHashKey, gfxFontFamily> mHiddenFontFamilies;
FontFamilyTable mHiddenFontFamilies;
};
#endif /* GFX_FT2FONTLIST_H */
+1 -1
View File
@@ -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
View File
@@ -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
-4
View File
@@ -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);
+1 -1
View File
@@ -503,7 +503,7 @@ gfxGDIFont::AddSizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf,
aSizes->mFontInstances += aMallocSizeOf(mMetrics);
if (mGlyphWidths) {
aSizes->mFontInstances +=
mGlyphWidths->SizeOfIncludingThis(nullptr, aMallocSizeOf);
mGlyphWidths->ShallowSizeOfIncludingThis(aMallocSizeOf);
}
}
+1 -2
View File
@@ -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) {
+1 -3
View File
@@ -348,9 +348,7 @@ private:
void ActivateBundledFonts();
#endif
typedef nsRefPtrHashtable<nsStringHashKey, gfxFontFamily> FontTable;
FontTable mFontSubstitutes;
FontFamilyTable mFontSubstitutes;
nsTArray<nsString> mNonExistingFonts;
};
+1 -1
View File
@@ -143,7 +143,7 @@ size_t
gfxGlyphExtents::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const
{
return mContainedGlyphWidths.SizeOfExcludingThis(aMallocSizeOf) +
mTightGlyphExtents.SizeOfExcludingThis(nullptr, aMallocSizeOf);
mTightGlyphExtents.ShallowSizeOfExcludingThis(aMallocSizeOf);
}
size_t
+47 -73
View File
@@ -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
+15 -10
View File
@@ -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
View File
@@ -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() {
-6
View File
@@ -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++)
+21
View File
@@ -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]);
+1
View File
@@ -264,6 +264,7 @@ class BaselineCompiler : public BaselineCompilerSpecific
void emitIsDebuggeeCheck();
bool emitDebugPrologue();
bool emitDebugTrap();
void emitCoverage(jsbytecode* pc);
bool emitTraceLoggerEnter();
bool emitTraceLoggerExit();
+22 -11
View File
@@ -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
View File
@@ -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()) {
+7 -6
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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())
+1 -1
View File
@@ -2011,7 +2011,7 @@ CASE(EnableInterruptsPseudoOpcode)
if (script->hasScriptCounts()) {
PCCounts counts = script->getPCCounts(REGS.pc);
counts.get(PCCounts::BASE_INTERP)++;
counts.numExec()++;
moreInterrupts = true;
}
+2 -2
View File
@@ -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
View File
@@ -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
+16 -22
View File
@@ -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
+30 -49
View File
@@ -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...
+4 -12
View File
@@ -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;
};
+2 -6
View File
@@ -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);
+5 -13
View File
@@ -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
View File
@@ -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
+35 -48
View File
@@ -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;
}
+9 -14
View File
@@ -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
+5 -15
View File
@@ -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:
+6 -15
View File
@@ -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.
+9 -17
View File
@@ -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.
+3 -1
View File
@@ -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;
+17 -25
View File
@@ -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);
+1 -1
View File
@@ -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:
+6 -10
View File
@@ -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
-48
View File
@@ -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)
+32 -29
View File
@@ -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)))
+19
View File
@@ -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]
+11 -10
View File
@@ -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
+3 -8
View File
@@ -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;
+8 -13
View File
@@ -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);
+2 -1
View File
@@ -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; }
+3 -3
View File
@@ -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;
}
+6 -14
View File
@@ -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;
}
+16 -26
View File
@@ -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);
+1 -1
View File
@@ -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
View File
@@ -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;
}
+5 -10
View File
@@ -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;
+9 -77
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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;
}
+1 -4
View File
@@ -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