--- a/modules/libpref/Preferences.cpp
+++ b/modules/libpref/Preferences.cpp
@@ -155,19 +155,31 @@ PrefTypeToString(PrefType aType)
case PrefType::Bool:
return "bool";
default:
MOZ_CRASH("Unhandled enum value");
}
}
#endif
+static ArenaAllocator<8192, 1> gPrefNameArena;
+
class PrefHashEntry : public PLDHashEntryHdr
{
public:
+ PrefHashEntry(const char* aName, PrefType aType)
+ {
+ mName = ArenaStrdup(aName, gPrefNameArena);
+ SetType(aType);
+ // We don't set the other fields because PLDHashTable always zeroes new
+ // entries.
+ }
+
+ const char* Name() { return mName; }
+
// Types.
PrefType Type() const { return static_cast<PrefType>(mType); }
void SetType(PrefType aType) { mType = static_cast<uint32_t>(aType); }
bool IsType(PrefType aType) const { return Type() == aType; }
bool IsTypeString() const { return IsType(PrefType::String); }
bool IsTypeInt() const { return IsType(PrefType::Int); }
@@ -187,41 +199,41 @@ public:
bool HasUserValue() const { return mHasUserValue; }
void SetHasUserValue(bool aValue) { mHasUserValue = aValue; }
// Other operations.
static bool MatchEntry(const PLDHashEntryHdr* aEntry, const void* aKey)
{
auto pref = static_cast<const PrefHashEntry*>(aEntry);
-
- if (pref->mKey == aKey) {
+ auto key = static_cast<const char*>(aKey);
+
+ if (pref->mName == aKey) {
return true;
}
- if (!pref->mKey || !aKey) {
+ if (!pref->mName || !aKey) {
return false;
}
- auto otherKey = static_cast<const char*>(aKey);
- return (strcmp(pref->mKey, otherKey) == 0);
+ return strcmp(pref->mName, key) == 0;
}
static void ClearEntry(PLDHashTable* aTable, PLDHashEntryHdr* aEntry)
{
auto pref = static_cast<PrefHashEntry*>(aEntry);
if (pref->IsTypeString()) {
free(const_cast<char*>(pref->mDefaultValue.mStringVal));
free(const_cast<char*>(pref->mUserValue.mStringVal));
}
// Don't need to free this because it's allocated in memory owned by
// gPrefNameArena.
- pref->mKey = nullptr;
+ pref->mName = nullptr;
memset(aEntry, 0, aTable->EntrySize());
}
private:
static void AssignPrefValueToDomPrefValue(PrefType aType,
PrefValue* aValue,
dom::PrefValue* aDomValue)
{
@@ -241,17 +253,17 @@ private:
default:
MOZ_CRASH();
}
}
public:
void ToSetting(dom::PrefSetting* aSetting)
{
- aSetting->name() = mKey;
+ aSetting->name() = mName;
if (HasDefaultValue()) {
aSetting->defaultValue() = dom::PrefValue();
AssignPrefValueToDomPrefValue(
Type(), &mDefaultValue, &aSetting->defaultValue().get_PrefValue());
} else {
aSetting->defaultValue() = null_t();
}
@@ -292,17 +304,17 @@ public:
}
}
return true;
}
size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf)
{
- // Note: mKey is allocated in gPrefNameArena, measured elsewhere.
+ // Note: mName is allocated in gPrefNameArena, measured elsewhere.
size_t n = 0;
if (IsTypeString()) {
if (HasDefaultValue()) {
n += aMallocSizeOf(mDefaultValue.mStringVal);
}
if (HasUserValue()) {
n += aMallocSizeOf(mUserValue.mStringVal);
}
@@ -315,18 +327,19 @@ private:
// this a subclass of PLDHashEntryHdr, there's a preceding 32-bit mKeyHash
// field.)
uint32_t mType : 2;
uint32_t mIsSticky : 1;
uint32_t mIsLocked : 1;
uint32_t mHasUserValue : 1;
uint32_t mHasDefaultValue : 1;
+ const char* mName;
+
public:
- const char* mKey;
PrefValue mDefaultValue;
PrefValue mUserValue;
};
struct CallbackNode
{
const char* mDomain;
@@ -336,18 +349,16 @@ struct CallbackNode
PrefChangedFunc mFunc;
void* mData;
Preferences::MatchKind mMatchKind;
CallbackNode* mNext;
};
static PLDHashTable* gHashTable;
-static ArenaAllocator<8192, 1> gPrefNameArena;
-
// 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;
static bool gIsAnyPrefLocked = false;
// These are only used during the call to pref_DoCallback.
@@ -456,17 +467,17 @@ pref_savePrefs()
!pref->HasDefaultValue() || pref->IsSticky())) {
sourceValue = &pref->mUserValue;
} else {
// do not save default prefs that haven't changed
continue;
}
nsAutoCString prefName;
- StrEscape(pref->mKey, prefName);
+ StrEscape(pref->Name(), prefName);
nsAutoCString prefValue;
if (pref->IsTypeString()) {
StrEscape(sourceValue->mStringVal, prefValue);
} else if (pref->IsTypeInt()) {
prefValue.AppendInt(sourceValue->mIntVal);
@@ -524,17 +535,17 @@ PREF_ClearAllUserPrefs()
return NS_ERROR_NOT_INITIALIZED;
}
Vector<const char*> prefNames;
for (auto iter = gHashTable->Iter(); !iter.Done(); iter.Next()) {
auto pref = static_cast<PrefHashEntry*>(iter.Get());
if (pref->HasUserValue()) {
- if (!prefNames.append(pref->mKey)) {
+ if (!prefNames.append(pref->Name())) {
return NS_ERROR_OUT_OF_MEMORY;
}
pref->SetHasUserValue(false);
if (!pref->HasDefaultValue()) {
iter.Remove();
}
}
@@ -692,43 +703,42 @@ pref_HashTableLookup(const char* aKey)
"accessing non-init pref %s before the rest of the prefs are sent", aKey);
}
#endif
return static_cast<PrefHashEntry*>(gHashTable->Search(aKey));
}
static nsresult
-pref_SetPref(const char* aKey,
+pref_SetPref(const char* aPrefName,
PrefValue aValue,
PrefType aType,
uint32_t aFlags)
{
MOZ_ASSERT(NS_IsMainThread());
if (!gHashTable) {
return NS_ERROR_OUT_OF_MEMORY;
}
- auto pref = static_cast<PrefHashEntry*>(gHashTable->Add(aKey, fallible));
+ auto pref = static_cast<PrefHashEntry*>(gHashTable->Add(aPrefName, fallible));
if (!pref) {
return NS_ERROR_OUT_OF_MEMORY;
}
- if (!pref->mKey) {
+ if (!pref->Name()) {
// New (zeroed) entry. Initialize it.
- pref->SetType(aType);
- pref->mKey = ArenaStrdup(aKey, gPrefNameArena);
+ new (pref) PrefHashEntry(aPrefName, aType);
} else if (pref->HasDefaultValue() && !pref->IsType(aType)) {
NS_WARNING(
nsPrintfCString(
"Ignoring attempt to overwrite value of default pref %s (type %s) with "
"the wrong type (%s)!",
- aKey,
+ aPrefName,
PrefTypeToString(pref->Type()),
PrefTypeToString(aType))
.get());
return NS_ERROR_UNEXPECTED;
}
bool valueChanged = false;
@@ -773,17 +783,17 @@ pref_SetPref(const char* aKey,
if (!pref->IsLocked()) {
Preferences::HandleDirty();
valueChanged = true;
}
}
}
if (valueChanged) {
- return pref_DoCallback(aKey);
+ return pref_DoCallback(aPrefName);
}
return NS_OK;
}
// Bool function that returns whether or not the preference is locked and
// therefore cannot be changed.
static bool
@@ -2510,21 +2520,21 @@ nsPrefBranch::DeleteBranch(const char* a
const nsACString& branchNameNoDot =
Substring(branchName, 0, branchName.Length() - 1);
for (auto iter = gHashTable->Iter(); !iter.Done(); iter.Next()) {
auto pref = static_cast<PrefHashEntry*>(iter.Get());
// The first disjunct matches branches: e.g. a branch name "foo.bar."
- // matches an mKey "foo.bar.baz" (but it won't match "foo.barrel.baz").
+ // matches a name "foo.bar.baz" (but it won't match "foo.barrel.baz").
// The second disjunct matches leaf nodes: e.g. a branch name "foo.bar."
- // matches an mKey "foo.bar" (by ignoring the trailing '.').
- nsDependentCString key(pref->mKey);
- if (StringBeginsWith(key, branchName) || key.Equals(branchNameNoDot)) {
+ // matches a name "foo.bar" (by ignoring the trailing '.').
+ nsDependentCString name(pref->Name());
+ if (StringBeginsWith(name, branchName) || name.Equals(branchNameNoDot)) {
iter.Remove();
}
}
Preferences::HandleDirty();
return NS_OK;
}
@@ -2547,18 +2557,18 @@ nsPrefBranch::GetChildList(const char* a
// This will contain a list of all the pref name strings. Allocated on the
// stack for speed.
const PrefName& parent = GetPrefName(aStartingAt);
size_t parentLen = parent.Length();
for (auto iter = gHashTable->Iter(); !iter.Done(); iter.Next()) {
auto pref = static_cast<PrefHashEntry*>(iter.Get());
- if (strncmp(pref->mKey, parent.get(), parentLen) == 0) {
- prefArray.AppendElement(pref->mKey);
+ if (strncmp(pref->Name(), parent.get(), parentLen) == 0) {
+ prefArray.AppendElement(pref->Name());
}
}
// Now that we've built up the list, run the callback on all the matching
// elements.
numPrefs = prefArray.Length();
if (numPrefs) {