Bug 1441754 - Shrink CallbackNode by combining mMatchKind and mNext into a tagged pointer. r=glandium
The following table shows the effect of this change:
> old 64-bit new 64-bit old 32-bit new 32-bit
> sizeof(CallbackNode) 40 32 20 16
> size when heap allocated 48 32 32 16
This reduces memory usage by about 15--40 KB per process.
MozReview-Commit-ID: 4gXgGI3SiJz
--- a/modules/libpref/Preferences.cpp
+++ b/modules/libpref/Preferences.cpp
@@ -751,51 +751,71 @@ class CallbackNode
public:
CallbackNode(const char* aDomain,
PrefChangedFunc aFunc,
void* aData,
Preferences::MatchKind aMatchKind)
: mDomain(moz_xstrdup(aDomain))
, mFunc(aFunc)
, mData(aData)
- , mMatchKind(aMatchKind)
- , mNext(nullptr)
+ , mNextAndMatchKind(aMatchKind)
{
}
// mDomain is a UniquePtr<>, so any uses of Domain() should only be temporary
// borrows.
const char* Domain() const { return mDomain.get(); }
PrefChangedFunc Func() const { return mFunc; }
void ClearFunc() { mFunc = nullptr; }
void* Data() const { return mData; }
- Preferences::MatchKind MatchKind() const { return mMatchKind; }
-
- CallbackNode* Next() const { return mNext; }
- void SetNext(CallbackNode* aNext) { mNext = aNext; }
+ Preferences::MatchKind MatchKind() const
+ {
+ return static_cast<Preferences::MatchKind>(mNextAndMatchKind &
+ kMatchKindMask);
+ }
+
+ CallbackNode* Next() const
+ {
+ return reinterpret_cast<CallbackNode*>(mNextAndMatchKind & kNextMask);
+ }
+
+ void SetNext(CallbackNode* aNext)
+ {
+ uintptr_t matchKind = mNextAndMatchKind & kMatchKindMask;
+ mNextAndMatchKind = reinterpret_cast<uintptr_t>(aNext);
+ MOZ_ASSERT(mNextAndMatchKind & kMatchKindMask == 0);
+ mNextAndMatchKind |= matchKind;
+ }
void AddSizeOfIncludingThis(MallocSizeOf aMallocSizeOf, PrefsSizes& aSizes)
{
aSizes.mCallbacksObjects += aMallocSizeOf(this);
aSizes.mCallbacksDomains += aMallocSizeOf(mDomain.get());
}
private:
+ static const uintptr_t kMatchKindMask = uintptr_t(0x1);
+ static const uintptr_t kNextMask = ~kMatchKindMask;
+
UniqueFreePtr<const char> mDomain;
// If someone attempts to remove the node from the callback list while
// NotifyCallbacks() is running, |func| is set to nullptr. Such nodes will
// be removed at the end of NotifyCallbacks().
PrefChangedFunc mFunc;
void* mData;
- Preferences::MatchKind mMatchKind;
- CallbackNode* mNext;
+
+ // Conceptually this is two fields:
+ // - CallbackNode* mNext;
+ // - Preferences::MatchKind mMatchKind;
+ // They are combined into a tagged pointer to save memory.
+ uintptr_t mNextAndMatchKind;
};
static PLDHashTable* gHashTable;
// The callback list contains all the priority callbacks followed by the
// non-priority callbacks. gLastPriorityNode records where the first part ends.
static CallbackNode* gFirstCallback = nullptr;
static CallbackNode* gLastPriorityNode = nullptr;