зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1057912 - Privatize most of PLDHashTable's fields. r=roc.
--HG-- extra : rebase_source : 0f55e70b63d9c191fbd9418cb1177ff534deeed9
This commit is contained in:
Родитель
7d82bae00d
Коммит
df1c26a45e
|
@ -993,7 +993,7 @@ nsContentList::RemoveFromHashtable()
|
|||
&key,
|
||||
PL_DHASH_REMOVE);
|
||||
|
||||
if (gContentListHashTable.entryCount == 0) {
|
||||
if (gContentListHashTable.EntryCount() == 0) {
|
||||
PL_DHashTableFinish(&gContentListHashTable);
|
||||
gContentListHashTable.ops = nullptr;
|
||||
}
|
||||
|
@ -1036,7 +1036,7 @@ nsCacheableFuncStringContentList::RemoveFromFuncStringHashtable()
|
|||
&key,
|
||||
PL_DHASH_REMOVE);
|
||||
|
||||
if (gFuncStringContentListHashTable.entryCount == 0) {
|
||||
if (gFuncStringContentListHashTable.EntryCount() == 0) {
|
||||
PL_DHashTableFinish(&gFuncStringContentListHashTable);
|
||||
gFuncStringContentListHashTable.ops = nullptr;
|
||||
}
|
||||
|
|
|
@ -1781,7 +1781,7 @@ nsContentUtils::Shutdown()
|
|||
sUserDefinedEvents = nullptr;
|
||||
|
||||
if (sEventListenerManagersHash.ops) {
|
||||
NS_ASSERTION(sEventListenerManagersHash.entryCount == 0,
|
||||
NS_ASSERTION(sEventListenerManagersHash.EntryCount() == 0,
|
||||
"Event listener manager hash not empty at shutdown!");
|
||||
|
||||
// See comment above.
|
||||
|
@ -1793,7 +1793,7 @@ nsContentUtils::Shutdown()
|
|||
// it could leave dangling references in DOMClassInfo's preserved
|
||||
// wrapper table.
|
||||
|
||||
if (sEventListenerManagersHash.entryCount == 0) {
|
||||
if (sEventListenerManagersHash.EntryCount() == 0) {
|
||||
PL_DHashTableFinish(&sEventListenerManagersHash);
|
||||
sEventListenerManagersHash.ops = nullptr;
|
||||
}
|
||||
|
|
|
@ -274,7 +274,7 @@ OnWrapperDestroyed()
|
|||
}
|
||||
|
||||
if (sNPObjWrappers.ops) {
|
||||
MOZ_ASSERT(sNPObjWrappers.entryCount == 0);
|
||||
MOZ_ASSERT(sNPObjWrappers.EntryCount() == 0);
|
||||
|
||||
// No more wrappers, and our hash was initialized. Finish the
|
||||
// hash to prevent leaking it.
|
||||
|
@ -1763,14 +1763,14 @@ nsNPObjWrapper::GetNewOrUsed(NPP npp, JSContext *cx, NPObject *npobj)
|
|||
entry->mNPObj = npobj;
|
||||
entry->mNpp = npp;
|
||||
|
||||
uint32_t generation = sNPObjWrappers.generation;
|
||||
uint32_t generation = sNPObjWrappers.Generation();
|
||||
|
||||
// No existing JSObject, create one.
|
||||
|
||||
JS::Rooted<JSObject*> obj(cx, ::JS_NewObject(cx, &sNPObjectJSWrapperClass, JS::NullPtr(),
|
||||
JS::NullPtr()));
|
||||
|
||||
if (generation != sNPObjWrappers.generation) {
|
||||
if (generation != sNPObjWrappers.Generation()) {
|
||||
// Reload entry if the JS_NewObject call caused a GC and reallocated
|
||||
// the table (see bug 445229). This is guaranteed to succeed.
|
||||
|
||||
|
|
|
@ -485,7 +485,7 @@ void
|
|||
IID2ThisTranslatorMap::Entry::Clear(PLDHashTable *table, PLDHashEntryHdr *entry)
|
||||
{
|
||||
static_cast<Entry*>(entry)->value = nullptr;
|
||||
memset(entry, 0, table->entrySize);
|
||||
memset(entry, 0, table->EntrySize());
|
||||
}
|
||||
|
||||
const struct PLDHashTableOps IID2ThisTranslatorMap::Entry::sOps =
|
||||
|
|
|
@ -147,7 +147,7 @@ public:
|
|||
PL_DHashTableOperate(mTable, wrapper->GetIdentityObject(), PL_DHASH_REMOVE);
|
||||
}
|
||||
|
||||
inline uint32_t Count() {return mTable->entryCount;}
|
||||
inline uint32_t Count() { return mTable->EntryCount(); }
|
||||
inline uint32_t Enumerate(PLDHashEnumerator f, void *arg)
|
||||
{return PL_DHashTableEnumerate(mTable, f, arg);}
|
||||
|
||||
|
@ -209,7 +209,7 @@ public:
|
|||
PL_DHashTableOperate(mTable, &clazz->GetIID(), PL_DHASH_REMOVE);
|
||||
}
|
||||
|
||||
inline uint32_t Count() {return mTable->entryCount;}
|
||||
inline uint32_t Count() { return mTable->EntryCount(); }
|
||||
inline uint32_t Enumerate(PLDHashEnumerator f, void *arg)
|
||||
{return PL_DHashTableEnumerate(mTable, f, arg);}
|
||||
|
||||
|
@ -266,7 +266,7 @@ public:
|
|||
PL_DHashTableOperate(mTable, iface->GetIID(), PL_DHASH_REMOVE);
|
||||
}
|
||||
|
||||
inline uint32_t Count() {return mTable->entryCount;}
|
||||
inline uint32_t Count() { return mTable->EntryCount(); }
|
||||
inline uint32_t Enumerate(PLDHashEnumerator f, void *arg)
|
||||
{return PL_DHashTableEnumerate(mTable, f, arg);}
|
||||
|
||||
|
@ -325,7 +325,7 @@ public:
|
|||
PL_DHashTableOperate(mTable, info, PL_DHASH_REMOVE);
|
||||
}
|
||||
|
||||
inline uint32_t Count() {return mTable->entryCount;}
|
||||
inline uint32_t Count() { return mTable->EntryCount(); }
|
||||
inline uint32_t Enumerate(PLDHashEnumerator f, void *arg)
|
||||
{return PL_DHashTableEnumerate(mTable, f, arg);}
|
||||
|
||||
|
@ -385,7 +385,7 @@ public:
|
|||
PL_DHashTableOperate(mTable, info, PL_DHASH_REMOVE);
|
||||
}
|
||||
|
||||
inline uint32_t Count() {return mTable->entryCount;}
|
||||
inline uint32_t Count() { return mTable->EntryCount(); }
|
||||
inline uint32_t Enumerate(PLDHashEnumerator f, void *arg)
|
||||
{return PL_DHashTableEnumerate(mTable, f, arg);}
|
||||
|
||||
|
@ -458,7 +458,7 @@ public:
|
|||
PL_DHashTableOperate(mTable, &key, PL_DHASH_REMOVE);
|
||||
}
|
||||
|
||||
inline uint32_t Count() {return mTable->entryCount;}
|
||||
inline uint32_t Count() { return mTable->EntryCount(); }
|
||||
inline uint32_t Enumerate(PLDHashEnumerator f, void *arg)
|
||||
{return PL_DHashTableEnumerate(mTable, f, arg);}
|
||||
|
||||
|
@ -525,7 +525,7 @@ public:
|
|||
PL_DHashTableOperate(mTable, &iid, PL_DHASH_REMOVE);
|
||||
}
|
||||
|
||||
inline uint32_t Count() {return mTable->entryCount;}
|
||||
inline uint32_t Count() { return mTable->EntryCount(); }
|
||||
inline uint32_t Enumerate(PLDHashEnumerator f, void *arg)
|
||||
{return PL_DHashTableEnumerate(mTable, f, arg);}
|
||||
|
||||
|
@ -562,7 +562,7 @@ public:
|
|||
bool GetNewOrUsed(uint32_t flags, char* name, uint32_t interfacesBitmap,
|
||||
XPCNativeScriptableInfo* si);
|
||||
|
||||
inline uint32_t Count() {return mTable->entryCount;}
|
||||
inline uint32_t Count() { return mTable->EntryCount(); }
|
||||
inline uint32_t Enumerate(PLDHashEnumerator f, void *arg)
|
||||
{return PL_DHashTableEnumerate(mTable, f, arg);}
|
||||
|
||||
|
@ -600,7 +600,7 @@ public:
|
|||
PL_DHashTableOperate(mTable, proto, PL_DHASH_REMOVE);
|
||||
}
|
||||
|
||||
inline uint32_t Count() {return mTable->entryCount;}
|
||||
inline uint32_t Count() { return mTable->EntryCount(); }
|
||||
inline uint32_t Enumerate(PLDHashEnumerator f, void *arg)
|
||||
{return PL_DHashTableEnumerate(mTable, f, arg);}
|
||||
|
||||
|
|
|
@ -2550,7 +2550,7 @@ nsCSSRuleProcessor::RulesMatching(AnonBoxRuleProcessorData* aData)
|
|||
{
|
||||
RuleCascadeData* cascade = GetRuleCascade(aData->mPresContext);
|
||||
|
||||
if (cascade && cascade->mAnonBoxRules.entryCount) {
|
||||
if (cascade && cascade->mAnonBoxRules.EntryCount()) {
|
||||
RuleHashTagTableEntry* entry = static_cast<RuleHashTagTableEntry*>
|
||||
(PL_DHashTableOperate(&cascade->mAnonBoxRules, aData->mPseudoTag,
|
||||
PL_DHASH_LOOKUP));
|
||||
|
@ -2571,7 +2571,7 @@ nsCSSRuleProcessor::RulesMatching(XULTreeRuleProcessorData* aData)
|
|||
{
|
||||
RuleCascadeData* cascade = GetRuleCascade(aData->mPresContext);
|
||||
|
||||
if (cascade && cascade->mXULTreeRules.entryCount) {
|
||||
if (cascade && cascade->mXULTreeRules.EntryCount()) {
|
||||
RuleHashTagTableEntry* entry = static_cast<RuleHashTagTableEntry*>
|
||||
(PL_DHashTableOperate(&cascade->mXULTreeRules, aData->mPseudoTag,
|
||||
PL_DHASH_LOOKUP));
|
||||
|
@ -3509,7 +3509,7 @@ nsCSSRuleProcessor::RefreshRuleCascade(nsPresContext* aPresContext)
|
|||
}
|
||||
|
||||
// Sort the hash table of per-weight linked lists by weight.
|
||||
uint32_t weightCount = data.mRulesByWeight.entryCount;
|
||||
uint32_t weightCount = data.mRulesByWeight.EntryCount();
|
||||
nsAutoArrayPtr<PerWeightData> weightArray(new PerWeightData[weightCount]);
|
||||
FillWeightArrayData fwData(weightArray);
|
||||
PL_DHashTableEnumerate(&data.mRulesByWeight, FillWeightArray, &fwData);
|
||||
|
|
|
@ -500,12 +500,12 @@ nsHTMLStyleSheet::DropMappedAttributes(nsMappedAttributes* aMapped)
|
|||
|
||||
NS_ASSERTION(mMappedAttrTable.ops, "table uninitialized");
|
||||
#ifdef DEBUG
|
||||
uint32_t entryCount = mMappedAttrTable.entryCount - 1;
|
||||
uint32_t entryCount = mMappedAttrTable.EntryCount() - 1;
|
||||
#endif
|
||||
|
||||
PL_DHashTableOperate(&mMappedAttrTable, aMapped, PL_DHASH_REMOVE);
|
||||
|
||||
NS_ASSERTION(entryCount == mMappedAttrTable.entryCount, "not removed");
|
||||
NS_ASSERTION(entryCount == mMappedAttrTable.EntryCount(), "not removed");
|
||||
}
|
||||
|
||||
nsIStyleRule*
|
||||
|
|
|
@ -9005,9 +9005,9 @@ nsRuleNode::SweepChildren(nsTArray<nsRuleNode*>& aSweepQueue)
|
|||
nsRuleNode* survivorsWithChildren = nullptr;
|
||||
if (ChildrenAreHashed()) {
|
||||
PLDHashTable* children = ChildrenHash();
|
||||
uint32_t oldChildCount = children->entryCount;
|
||||
uint32_t oldChildCount = children->EntryCount();
|
||||
PL_DHashTableEnumerate(children, SweepHashEntry, &survivorsWithChildren);
|
||||
childrenDestroyed = oldChildCount - children->entryCount;
|
||||
childrenDestroyed = oldChildCount - children->EntryCount();
|
||||
if (childrenDestroyed == oldChildCount) {
|
||||
PL_DHashTableDestroy(children);
|
||||
mChildren.asVoid = nullptr;
|
||||
|
|
|
@ -153,20 +153,20 @@ SpanningCellSorter::GetNext(int32_t *aColSpan)
|
|||
mEnumerationIndex = 0;
|
||||
if (mHashTable.ops) {
|
||||
HashTableEntry **sh =
|
||||
new HashTableEntry*[mHashTable.entryCount];
|
||||
new HashTableEntry*[mHashTable.EntryCount()];
|
||||
if (!sh) {
|
||||
// give up
|
||||
mState = DONE;
|
||||
return nullptr;
|
||||
}
|
||||
PL_DHashTableEnumerate(&mHashTable, FillSortedArray, sh);
|
||||
NS_QuickSort(sh, mHashTable.entryCount, sizeof(sh[0]),
|
||||
NS_QuickSort(sh, mHashTable.EntryCount(), sizeof(sh[0]),
|
||||
SortArray, nullptr);
|
||||
mSortedHashTable = sh;
|
||||
}
|
||||
/* fall through */
|
||||
case ENUMERATING_HASH:
|
||||
if (mHashTable.ops && mEnumerationIndex < mHashTable.entryCount) {
|
||||
if (mHashTable.ops && mEnumerationIndex < mHashTable.EntryCount()) {
|
||||
Item *result = mSortedHashTable[mEnumerationIndex]->mItems;
|
||||
*aColSpan = mSortedHashTable[mEnumerationIndex]->mColSpan;
|
||||
NS_ASSERTION(result, "holes in hash table");
|
||||
|
|
|
@ -745,7 +745,7 @@ Preferences::GetPreference(PrefSetting* aPref)
|
|||
void
|
||||
Preferences::GetPreferences(InfallibleTArray<PrefSetting>* aPrefs)
|
||||
{
|
||||
aPrefs->SetCapacity(PL_DHASH_TABLE_CAPACITY(&gHashTable));
|
||||
aPrefs->SetCapacity(gHashTable.Capacity());
|
||||
PL_DHashTableEnumerate(&gHashTable, pref_GetPrefs, aPrefs);
|
||||
}
|
||||
|
||||
|
@ -971,8 +971,8 @@ Preferences::WritePrefFile(nsIFile* aFile)
|
|||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
nsAutoArrayPtr<char*> valueArray(new char*[gHashTable.entryCount]);
|
||||
memset(valueArray, 0, gHashTable.entryCount * sizeof(char*));
|
||||
nsAutoArrayPtr<char*> valueArray(new char*[gHashTable.EntryCount()]);
|
||||
memset(valueArray, 0, gHashTable.EntryCount() * sizeof(char*));
|
||||
pref_saveArgs saveArgs;
|
||||
saveArgs.prefArray = valueArray;
|
||||
saveArgs.saveTypes = SAVE_ALL;
|
||||
|
@ -981,13 +981,13 @@ Preferences::WritePrefFile(nsIFile* aFile)
|
|||
PL_DHashTableEnumerate(&gHashTable, pref_savePref, &saveArgs);
|
||||
|
||||
/* Sort the preferences to make a readable file on disk */
|
||||
NS_QuickSort(valueArray, gHashTable.entryCount, sizeof(char *), pref_CompareStrings, nullptr);
|
||||
NS_QuickSort(valueArray, gHashTable.EntryCount(), sizeof(char *), pref_CompareStrings, nullptr);
|
||||
|
||||
// write out the file header
|
||||
outStream->Write(outHeader, sizeof(outHeader) - 1, &writeAmount);
|
||||
|
||||
char** walker = valueArray;
|
||||
for (uint32_t valueIdx = 0; valueIdx < gHashTable.entryCount; valueIdx++, walker++) {
|
||||
for (uint32_t valueIdx = 0; valueIdx < gHashTable.EntryCount(); valueIdx++, walker++) {
|
||||
if (*walker) {
|
||||
outStream->Write(*walker, strlen(*walker), &writeAmount);
|
||||
outStream->Write(NS_LINEBREAK, NS_LINEBREAK_LEN, &writeAmount);
|
||||
|
|
|
@ -895,4 +895,4 @@ NS_IMETHODIMP nsRelativeFilePref::SetRelativeToKey(const nsACString& aRelativeTo
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
#undef ENSURE_MAIN_PROCESS
|
||||
#undef ENSURE_MAIN_PROCESS
|
||||
|
|
|
@ -47,7 +47,7 @@ clearPrefEntry(PLDHashTable *table, PLDHashEntryHdr *entry)
|
|||
// don't need to free this as it's allocated in memory owned by
|
||||
// gPrefNameArena
|
||||
pref->key = nullptr;
|
||||
memset(entry, 0, table->entrySize);
|
||||
memset(entry, 0, table->EntrySize());
|
||||
}
|
||||
|
||||
static bool
|
||||
|
@ -65,7 +65,7 @@ matchPrefEntry(PLDHashTable*, const PLDHashEntryHdr* entry,
|
|||
return (strcmp(prefEntry->key, otherKey) == 0);
|
||||
}
|
||||
|
||||
PLDHashTable gHashTable = { nullptr };
|
||||
PLDHashTable gHashTable;
|
||||
static PLArenaPool gPrefNameArena;
|
||||
bool gDirty = false;
|
||||
|
||||
|
|
|
@ -230,7 +230,7 @@ nsLoadGroup::Cancel(nsresult status)
|
|||
|
||||
NS_ASSERTION(NS_FAILED(status), "shouldn't cancel with a success code");
|
||||
nsresult rv;
|
||||
uint32_t count = mRequests.entryCount;
|
||||
uint32_t count = mRequests.EntryCount();
|
||||
|
||||
nsAutoTArray<nsIRequest*, 8> requests;
|
||||
|
||||
|
@ -301,7 +301,7 @@ nsLoadGroup::Cancel(nsresult status)
|
|||
}
|
||||
|
||||
#if defined(DEBUG)
|
||||
NS_ASSERTION(mRequests.entryCount == 0, "Request list is not empty.");
|
||||
NS_ASSERTION(mRequests.EntryCount() == 0, "Request list is not empty.");
|
||||
NS_ASSERTION(mForegroundCount == 0, "Foreground URLs are active.");
|
||||
#endif
|
||||
|
||||
|
@ -316,7 +316,7 @@ NS_IMETHODIMP
|
|||
nsLoadGroup::Suspend()
|
||||
{
|
||||
nsresult rv, firstError;
|
||||
uint32_t count = mRequests.entryCount;
|
||||
uint32_t count = mRequests.EntryCount();
|
||||
|
||||
nsAutoTArray<nsIRequest*, 8> requests;
|
||||
|
||||
|
@ -368,7 +368,7 @@ NS_IMETHODIMP
|
|||
nsLoadGroup::Resume()
|
||||
{
|
||||
nsresult rv, firstError;
|
||||
uint32_t count = mRequests.entryCount;
|
||||
uint32_t count = mRequests.EntryCount();
|
||||
|
||||
nsAutoTArray<nsIRequest*, 8> requests;
|
||||
|
||||
|
@ -489,7 +489,7 @@ nsLoadGroup::AddRequest(nsIRequest *request, nsISupports* ctxt)
|
|||
nsAutoCString nameStr;
|
||||
request->GetName(nameStr);
|
||||
LOG(("LOADGROUP [%x]: Adding request %x %s (count=%d).\n",
|
||||
this, request, nameStr.get(), mRequests.entryCount));
|
||||
this, request, nameStr.get(), mRequests.EntryCount()));
|
||||
}
|
||||
#endif /* PR_LOGGING */
|
||||
|
||||
|
@ -602,7 +602,7 @@ nsLoadGroup::RemoveRequest(nsIRequest *request, nsISupports* ctxt,
|
|||
nsAutoCString nameStr;
|
||||
request->GetName(nameStr);
|
||||
LOG(("LOADGROUP [%x]: Removing request %x %s status %x (count=%d).\n",
|
||||
this, request, nameStr.get(), aStatus, mRequests.entryCount-1));
|
||||
this, request, nameStr.get(), aStatus, mRequests.EntryCount() - 1));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -664,7 +664,7 @@ nsLoadGroup::RemoveRequest(nsIRequest *request, nsISupports* ctxt,
|
|||
}
|
||||
}
|
||||
|
||||
if (mRequests.entryCount == 0) {
|
||||
if (mRequests.EntryCount() == 0) {
|
||||
TelemetryReport();
|
||||
}
|
||||
|
||||
|
@ -720,7 +720,7 @@ NS_IMETHODIMP
|
|||
nsLoadGroup::GetRequests(nsISimpleEnumerator * *aRequests)
|
||||
{
|
||||
nsCOMArray<nsIRequest> requests;
|
||||
requests.SetCapacity(mRequests.entryCount);
|
||||
requests.SetCapacity(mRequests.EntryCount());
|
||||
|
||||
PL_DHashTableEnumerate(&mRequests, AppendRequestsToCOMArray, &requests);
|
||||
|
||||
|
|
|
@ -42,7 +42,7 @@ struct HttpHeapAtom {
|
|||
char value[1];
|
||||
};
|
||||
|
||||
static struct PLDHashTable sAtomTable = {0};
|
||||
static struct PLDHashTable sAtomTable;
|
||||
static struct HttpHeapAtom *sHeapAtoms = nullptr;
|
||||
static Mutex *sLock = nullptr;
|
||||
|
||||
|
|
|
@ -73,8 +73,8 @@ static const PLDHashTableOps UnicodeToEntityOps = {
|
|||
nullptr,
|
||||
};
|
||||
|
||||
static PLDHashTable gEntityToUnicode = { 0 };
|
||||
static PLDHashTable gUnicodeToEntity = { 0 };
|
||||
static PLDHashTable gEntityToUnicode;
|
||||
static PLDHashTable gUnicodeToEntity;
|
||||
static nsrefcnt gTableRefCnt = 0;
|
||||
|
||||
#define HTML_ENTITY(_name, _value) { #_name, _value },
|
||||
|
|
|
@ -1316,7 +1316,7 @@ InMemoryDataSource::LockedUnassert(nsIRDFResource* aSource,
|
|||
}
|
||||
else {
|
||||
// If this second-level hash empties out, clean it up.
|
||||
if (!root->u.hash.mPropertyHash->entryCount) {
|
||||
if (!root->u.hash.mPropertyHash->EntryCount()) {
|
||||
root->Release();
|
||||
SetForwardArcs(aSource, nullptr);
|
||||
}
|
||||
|
@ -1661,7 +1661,7 @@ NS_IMETHODIMP
|
|||
InMemoryDataSource::GetAllResources(nsISimpleEnumerator** aResult)
|
||||
{
|
||||
nsCOMArray<nsIRDFNode> nodes;
|
||||
nodes.SetCapacity(mForwardArcs.entryCount);
|
||||
nodes.SetCapacity(mForwardArcs.EntryCount());
|
||||
|
||||
// Enumerate all of our entries into an nsCOMArray
|
||||
PL_DHashTableEnumerate(&mForwardArcs, ResourceEnumerator, &nodes);
|
||||
|
@ -1920,7 +1920,7 @@ InMemoryDataSource::SweepForwardArcsEntries(PLDHashTable* aTable,
|
|||
SweepForwardArcsEntries, info);
|
||||
|
||||
// If the sub-hash is now empty, clean it up.
|
||||
if (!as->u.hash.mPropertyHash->entryCount) {
|
||||
if (!as->u.hash.mPropertyHash->EntryCount()) {
|
||||
as->Release();
|
||||
result = PL_DHASH_REMOVE;
|
||||
}
|
||||
|
|
|
@ -1385,7 +1385,7 @@ RemoveInfoCallback(PLDHashTable *table, PLDHashEntryHdr *hdr, uint32_t number,
|
|||
|
||||
void nsDocLoader::ClearRequestInfoHash(void)
|
||||
{
|
||||
if (!mRequestInfoHash.ops || !mRequestInfoHash.entryCount) {
|
||||
if (!mRequestInfoHash.ops || !mRequestInfoHash.EntryCount()) {
|
||||
// No hash, or the hash is empty, nothing to do here then...
|
||||
|
||||
return;
|
||||
|
|
|
@ -878,7 +878,7 @@ public:
|
|||
|
||||
uint32_t MapCount() const
|
||||
{
|
||||
return mPtrToNodeMap.entryCount;
|
||||
return mPtrToNodeMap.EntryCount();
|
||||
}
|
||||
|
||||
void SizeOfExcludingThis(MallocSizeOf aMallocSizeOf,
|
||||
|
|
|
@ -343,13 +343,12 @@ NS_PurgeAtomTable()
|
|||
if (dumpAtomLeaks && *dumpAtomLeaks) {
|
||||
uint32_t leaked = 0;
|
||||
printf("*** %d atoms still exist (including permanent):\n",
|
||||
gAtomTable.entryCount);
|
||||
gAtomTable.EntryCount());
|
||||
PL_DHashTableEnumerate(&gAtomTable, DumpAtomLeaks, &leaked);
|
||||
printf("*** %u non-permanent atoms leaked\n", leaked);
|
||||
}
|
||||
#endif
|
||||
PL_DHashTableFinish(&gAtomTable);
|
||||
gAtomTable.entryCount = 0;
|
||||
gAtomTable.ops = nullptr;
|
||||
}
|
||||
}
|
||||
|
@ -406,9 +405,9 @@ AtomImpl::~AtomImpl()
|
|||
if (!IsPermanentInDestructor()) {
|
||||
AtomTableKey key(mString, mLength, mHash);
|
||||
PL_DHashTableOperate(&gAtomTable, &key, PL_DHASH_REMOVE);
|
||||
if (gAtomTable.entryCount == 0) {
|
||||
if (gAtomTable.ops && gAtomTable.EntryCount() == 0) {
|
||||
PL_DHashTableFinish(&gAtomTable);
|
||||
NS_ASSERTION(gAtomTable.entryCount == 0,
|
||||
NS_ASSERTION(gAtomTable.EntryCount() == 0,
|
||||
"PL_DHashTableFinish changed the entry count");
|
||||
}
|
||||
}
|
||||
|
@ -558,7 +557,7 @@ GetAtomHashEntry(const char* aString, uint32_t aLength, uint32_t* aHashOut)
|
|||
AtomTableEntry* e = static_cast<AtomTableEntry*>(
|
||||
PL_DHashTableOperate(&gAtomTable, &key, PL_DHASH_ADD));
|
||||
if (!e) {
|
||||
NS_ABORT_OOM(gAtomTable.entryCount * gAtomTable.entrySize);
|
||||
NS_ABORT_OOM(gAtomTable.EntryCount() * gAtomTable.EntrySize());
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
@ -572,7 +571,7 @@ GetAtomHashEntry(const char16_t* aString, uint32_t aLength, uint32_t* aHashOut)
|
|||
AtomTableEntry* e = static_cast<AtomTableEntry*>(
|
||||
PL_DHashTableOperate(&gAtomTable, &key, PL_DHASH_ADD));
|
||||
if (!e) {
|
||||
NS_ABORT_OOM(gAtomTable.entryCount * gAtomTable.entrySize);
|
||||
NS_ABORT_OOM(gAtomTable.EntryCount() * gAtomTable.EntrySize());
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
@ -719,7 +718,7 @@ NS_NewPermanentAtom(const nsAString& aUTF16String)
|
|||
nsrefcnt
|
||||
NS_GetNumberOfAtoms(void)
|
||||
{
|
||||
return gAtomTable.entryCount;
|
||||
return gAtomTable.EntryCount();
|
||||
}
|
||||
|
||||
nsIAtom*
|
||||
|
|
|
@ -607,11 +607,11 @@ nsPersistentProperties::Enumerate(nsISimpleEnumerator** aResult)
|
|||
nsCOMArray<nsIPropertyElement> props;
|
||||
|
||||
// We know the necessary size; we can avoid growing it while adding elements
|
||||
props.SetCapacity(mTable.entryCount);
|
||||
props.SetCapacity(mTable.EntryCount());
|
||||
|
||||
// Step through hash entries populating a transient array
|
||||
uint32_t n = PL_DHashTableEnumerate(&mTable, AddElemToArray, (void*)&props);
|
||||
if (n < mTable.entryCount) {
|
||||
if (n < mTable.EntryCount()) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
|
|
|
@ -116,7 +116,7 @@ nsStaticCaseInsensitiveNameTable::~nsStaticCaseInsensitiveNameTable()
|
|||
{
|
||||
if (mNameArray) {
|
||||
// manually call the destructor on placement-new'ed objects
|
||||
for (uint32_t index = 0; index < mNameTable.entryCount; index++) {
|
||||
for (uint32_t index = 0; index < mNameTable.EntryCount(); index++) {
|
||||
mNameArray[index].~nsDependentCString();
|
||||
}
|
||||
nsMemory::Free((void*)mNameArray);
|
||||
|
@ -231,7 +231,7 @@ nsStaticCaseInsensitiveNameTable::GetStringValue(int32_t aIndex)
|
|||
NS_ASSERTION(mNameArray, "not inited");
|
||||
NS_ASSERTION(mNameTable.ops, "not inited");
|
||||
|
||||
if ((NOT_FOUND < aIndex) && ((uint32_t)aIndex < mNameTable.entryCount)) {
|
||||
if ((NOT_FOUND < aIndex) && ((uint32_t)aIndex < mNameTable.EntryCount())) {
|
||||
return mNameArray[aIndex];
|
||||
}
|
||||
return mNullStr;
|
||||
|
|
|
@ -124,7 +124,7 @@ public:
|
|||
void Put(KeyType aKey, const UserDataType& aData)
|
||||
{
|
||||
if (!Put(aKey, aData, fallible_t())) {
|
||||
NS_ABORT_OOM(this->mTable.entrySize * this->mTable.entryCount);
|
||||
NS_ABORT_OOM(this->mTable.EntrySize() * this->mTable.EntryCount());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -148,7 +148,7 @@ nsRefPtrHashtable<KeyClass, RefPtr>::Put(KeyType aKey,
|
|||
already_AddRefed<RefPtr> aData)
|
||||
{
|
||||
if (!Put(aKey, mozilla::Move(aData), mozilla::fallible_t())) {
|
||||
NS_ABORT_OOM(this->mTable.entrySize * this->mTable.entryCount);
|
||||
NS_ABORT_OOM(this->mTable.EntrySize() * this->mTable.EntryCount());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -99,7 +99,7 @@ public:
|
|||
* Return the generation number for the table. This increments whenever
|
||||
* the table data items are moved.
|
||||
*/
|
||||
uint32_t GetGeneration() const { return mTable.generation; }
|
||||
uint32_t GetGeneration() const { return mTable.Generation(); }
|
||||
|
||||
/**
|
||||
* KeyType is typedef'ed for ease of use.
|
||||
|
@ -115,7 +115,7 @@ public:
|
|||
* Return the number of entries in the table.
|
||||
* @return number of entries
|
||||
*/
|
||||
uint32_t Count() const { return mTable.entryCount; }
|
||||
uint32_t Count() const { return mTable.EntryCount(); }
|
||||
|
||||
/**
|
||||
* Get the entry associated with a key.
|
||||
|
@ -150,7 +150,7 @@ public:
|
|||
{
|
||||
EntryType* e = PutEntry(aKey, fallible_t());
|
||||
if (!e) {
|
||||
NS_ABORT_OOM(mTable.entrySize * mTable.entryCount);
|
||||
NS_ABORT_OOM(mTable.EntrySize() * mTable.EntryCount());
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
|
|
@ -115,27 +115,46 @@ PL_DHashMatchStringKey(PLDHashTable* aTable,
|
|||
strcmp((const char*)stub->key, (const char*)aKey) == 0);
|
||||
}
|
||||
|
||||
MOZ_ALWAYS_INLINE void
|
||||
PLDHashTable::MoveEntryStub(const PLDHashEntryHdr* aFrom,
|
||||
PLDHashEntryHdr* aTo)
|
||||
{
|
||||
memcpy(aTo, aFrom, entrySize);
|
||||
}
|
||||
|
||||
void
|
||||
PL_DHashMoveEntryStub(PLDHashTable* aTable,
|
||||
const PLDHashEntryHdr* aFrom,
|
||||
PLDHashEntryHdr* aTo)
|
||||
{
|
||||
memcpy(aTo, aFrom, aTable->entrySize);
|
||||
aTable->MoveEntryStub(aFrom, aTo);
|
||||
}
|
||||
|
||||
MOZ_ALWAYS_INLINE void
|
||||
PLDHashTable::ClearEntryStub(PLDHashEntryHdr* aEntry)
|
||||
{
|
||||
memset(aEntry, 0, entrySize);
|
||||
}
|
||||
|
||||
void
|
||||
PL_DHashClearEntryStub(PLDHashTable* aTable, PLDHashEntryHdr* aEntry)
|
||||
{
|
||||
memset(aEntry, 0, aTable->entrySize);
|
||||
aTable->ClearEntryStub(aEntry);
|
||||
}
|
||||
|
||||
MOZ_ALWAYS_INLINE void
|
||||
PLDHashTable::FreeStringKey(PLDHashEntryHdr* aEntry)
|
||||
{
|
||||
const PLDHashEntryStub* stub = (const PLDHashEntryStub*)aEntry;
|
||||
|
||||
free((void*)stub->key);
|
||||
memset(aEntry, 0, entrySize);
|
||||
}
|
||||
|
||||
void
|
||||
PL_DHashFreeStringKey(PLDHashTable* aTable, PLDHashEntryHdr* aEntry)
|
||||
{
|
||||
const PLDHashEntryStub* stub = (const PLDHashEntryStub*)aEntry;
|
||||
|
||||
free((void*)stub->key);
|
||||
memset(aEntry, 0, aTable->entrySize);
|
||||
aTable->FreeStringKey(aEntry);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -220,17 +239,16 @@ MinCapacity(uint32_t aLength)
|
|||
return (aLength * 4 + (3 - 1)) / 3; // == ceil(aLength * 4 / 3)
|
||||
}
|
||||
|
||||
bool
|
||||
PL_DHashTableInit(PLDHashTable* aTable, const PLDHashTableOps* aOps,
|
||||
void* aData, uint32_t aEntrySize, const fallible_t&,
|
||||
uint32_t aLength)
|
||||
MOZ_ALWAYS_INLINE bool
|
||||
PLDHashTable::Init(const PLDHashTableOps* aOps, void* aData,
|
||||
uint32_t aEntrySize, const fallible_t&, uint32_t aLength)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
if (aEntrySize > 16 * sizeof(void*)) {
|
||||
printf_stderr(
|
||||
"pldhash: for the aTable at address %p, the given aEntrySize"
|
||||
"pldhash: for the table at address %p, the given aEntrySize"
|
||||
" of %lu definitely favors chaining over double hashing.\n",
|
||||
(void*)aTable,
|
||||
(void*)this,
|
||||
(unsigned long) aEntrySize);
|
||||
}
|
||||
#endif
|
||||
|
@ -239,8 +257,8 @@ PL_DHashTableInit(PLDHashTable* aTable, const PLDHashTableOps* aOps,
|
|||
return false;
|
||||
}
|
||||
|
||||
aTable->ops = aOps;
|
||||
aTable->data = aData;
|
||||
ops = aOps;
|
||||
data = aData;
|
||||
|
||||
// Compute the smallest capacity allowing |aLength| elements to be inserted
|
||||
// without rehashing.
|
||||
|
@ -253,29 +271,37 @@ PL_DHashTableInit(PLDHashTable* aTable, const PLDHashTableOps* aOps,
|
|||
|
||||
capacity = 1u << log2;
|
||||
MOZ_ASSERT(capacity <= PL_DHASH_MAX_CAPACITY);
|
||||
aTable->hashShift = PL_DHASH_BITS - log2;
|
||||
aTable->entrySize = aEntrySize;
|
||||
aTable->entryCount = aTable->removedCount = 0;
|
||||
aTable->generation = 0;
|
||||
hashShift = PL_DHASH_BITS - log2;
|
||||
entrySize = aEntrySize;
|
||||
entryCount = removedCount = 0;
|
||||
generation = 0;
|
||||
uint32_t nbytes;
|
||||
if (!SizeOfEntryStore(capacity, aEntrySize, &nbytes)) {
|
||||
return false; // overflowed
|
||||
}
|
||||
|
||||
aTable->entryStore = (char*)aOps->allocTable(aTable, nbytes);
|
||||
if (!aTable->entryStore) {
|
||||
entryStore = (char*)aOps->allocTable(this, nbytes);
|
||||
if (!entryStore) {
|
||||
return false;
|
||||
}
|
||||
memset(aTable->entryStore, 0, nbytes);
|
||||
METER(memset(&aTable->stats, 0, sizeof(aTable->stats)));
|
||||
memset(entryStore, 0, nbytes);
|
||||
METER(memset(&stats, 0, sizeof(stats)));
|
||||
|
||||
#ifdef DEBUG
|
||||
aTable->recursionLevel = 0;
|
||||
recursionLevel = 0;
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
PL_DHashTableInit(PLDHashTable* aTable, const PLDHashTableOps* aOps,
|
||||
void* aData, uint32_t aEntrySize,
|
||||
const fallible_t& aFallible, uint32_t aLength)
|
||||
{
|
||||
return aTable->Init(aOps, aData, aEntrySize, aFallible, aLength);
|
||||
}
|
||||
|
||||
void
|
||||
PL_DHashTableInit(PLDHashTable* aTable, const PLDHashTableOps* aOps,
|
||||
void* aData, uint32_t aEntrySize, uint32_t aLength)
|
||||
|
@ -307,16 +333,12 @@ PL_DHashTableInit(PLDHashTable* aTable, const PLDHashTableOps* aOps,
|
|||
* flag in addition to the removed-entry sentinel value. Multiplicative hash
|
||||
* uses the high order bits of keyHash, so this least-significant reservation
|
||||
* should not hurt the hash function's effectiveness much.
|
||||
*
|
||||
* If you change any of these magic numbers, also update PL_DHASH_ENTRY_IS_LIVE
|
||||
* in pldhash.h. It used to be private to pldhash.c, but then became public to
|
||||
* assist iterator writers who inspect table->entryStore directly.
|
||||
*/
|
||||
#define COLLISION_FLAG ((PLDHashNumber) 1)
|
||||
#define MARK_ENTRY_FREE(entry) ((entry)->keyHash = 0)
|
||||
#define MARK_ENTRY_REMOVED(entry) ((entry)->keyHash = 1)
|
||||
#define ENTRY_IS_REMOVED(entry) ((entry)->keyHash == 1)
|
||||
#define ENTRY_IS_LIVE(entry) PL_DHASH_ENTRY_IS_LIVE(entry)
|
||||
#define ENTRY_IS_LIVE(entry) ((entry)->keyHash >= 2)
|
||||
#define ENSURE_LIVE_KEYHASH(hash0) if (hash0 < 2) hash0 -= 2; else (void)0
|
||||
|
||||
/* Match an entry's keyHash against an unstored one computed from a key. */
|
||||
|
@ -327,63 +349,67 @@ PL_DHashTableInit(PLDHashTable* aTable, const PLDHashTableOps* aOps,
|
|||
#define ADDRESS_ENTRY(table, index) \
|
||||
((PLDHashEntryHdr *)((table)->entryStore + (index) * (table)->entrySize))
|
||||
|
||||
void
|
||||
PL_DHashTableFinish(PLDHashTable* aTable)
|
||||
MOZ_ALWAYS_INLINE void
|
||||
PLDHashTable::Finish()
|
||||
{
|
||||
INCREMENT_RECURSION_LEVEL(aTable);
|
||||
INCREMENT_RECURSION_LEVEL(this);
|
||||
|
||||
/* Call finalize before clearing entries, so it can enumerate them. */
|
||||
aTable->ops->finalize(aTable);
|
||||
ops->finalize(this);
|
||||
|
||||
/* Clear any remaining live entries. */
|
||||
char* entryAddr = aTable->entryStore;
|
||||
uint32_t entrySize = aTable->entrySize;
|
||||
char* entryLimit = entryAddr + PL_DHASH_TABLE_CAPACITY(aTable) * entrySize;
|
||||
char* entryAddr = entryStore;
|
||||
char* entryLimit = entryAddr + Capacity() * entrySize;
|
||||
while (entryAddr < entryLimit) {
|
||||
PLDHashEntryHdr* entry = (PLDHashEntryHdr*)entryAddr;
|
||||
if (ENTRY_IS_LIVE(entry)) {
|
||||
METER(aTable->stats.removeEnums++);
|
||||
aTable->ops->clearEntry(aTable, entry);
|
||||
METER(stats.removeEnums++);
|
||||
ops->clearEntry(this, entry);
|
||||
}
|
||||
entryAddr += entrySize;
|
||||
}
|
||||
|
||||
DECREMENT_RECURSION_LEVEL(aTable);
|
||||
MOZ_ASSERT(RECURSION_LEVEL_SAFE_TO_FINISH(aTable));
|
||||
DECREMENT_RECURSION_LEVEL(this);
|
||||
MOZ_ASSERT(RECURSION_LEVEL_SAFE_TO_FINISH(this));
|
||||
|
||||
/* Free entry storage last. */
|
||||
aTable->ops->freeTable(aTable, aTable->entryStore);
|
||||
ops->freeTable(this, entryStore);
|
||||
}
|
||||
|
||||
static PLDHashEntryHdr* PL_DHASH_FASTCALL
|
||||
SearchTable(PLDHashTable* aTable, const void* aKey, PLDHashNumber aKeyHash,
|
||||
PLDHashOperator aOp)
|
||||
void
|
||||
PL_DHashTableFinish(PLDHashTable* aTable)
|
||||
{
|
||||
METER(aTable->stats.searches++);
|
||||
aTable->Finish();
|
||||
}
|
||||
|
||||
PLDHashEntryHdr* PL_DHASH_FASTCALL
|
||||
PLDHashTable::SearchTable(const void* aKey, PLDHashNumber aKeyHash,
|
||||
PLDHashOperator aOp)
|
||||
{
|
||||
METER(stats.searches++);
|
||||
NS_ASSERTION(!(aKeyHash & COLLISION_FLAG),
|
||||
"!(aKeyHash & COLLISION_FLAG)");
|
||||
|
||||
/* Compute the primary hash address. */
|
||||
int hashShift = aTable->hashShift;
|
||||
PLDHashNumber hash1 = HASH1(aKeyHash, hashShift);
|
||||
PLDHashEntryHdr* entry = ADDRESS_ENTRY(aTable, hash1);
|
||||
PLDHashEntryHdr* entry = ADDRESS_ENTRY(this, hash1);
|
||||
|
||||
/* Miss: return space for a new entry. */
|
||||
if (PL_DHASH_ENTRY_IS_FREE(entry)) {
|
||||
METER(aTable->stats.misses++);
|
||||
METER(stats.misses++);
|
||||
return entry;
|
||||
}
|
||||
|
||||
/* Hit: return entry. */
|
||||
PLDHashMatchEntry matchEntry = aTable->ops->matchEntry;
|
||||
PLDHashMatchEntry matchEntry = ops->matchEntry;
|
||||
if (MATCH_ENTRY_KEYHASH(entry, aKeyHash) &&
|
||||
matchEntry(aTable, entry, aKey)) {
|
||||
METER(aTable->stats.hits++);
|
||||
matchEntry(this, entry, aKey)) {
|
||||
METER(stats.hits++);
|
||||
return entry;
|
||||
}
|
||||
|
||||
/* Collision: double hash. */
|
||||
int sizeLog2 = PL_DHASH_BITS - aTable->hashShift;
|
||||
int sizeLog2 = PL_DHASH_BITS - hashShift;
|
||||
PLDHashNumber hash2 = HASH2(aKeyHash, sizeLog2, hashShift);
|
||||
uint32_t sizeMask = (1u << sizeLog2) - 1;
|
||||
|
||||
|
@ -401,19 +427,19 @@ SearchTable(PLDHashTable* aTable, const void* aKey, PLDHashNumber aKeyHash,
|
|||
}
|
||||
}
|
||||
|
||||
METER(aTable->stats.steps++);
|
||||
METER(stats.steps++);
|
||||
hash1 -= hash2;
|
||||
hash1 &= sizeMask;
|
||||
|
||||
entry = ADDRESS_ENTRY(aTable, hash1);
|
||||
entry = ADDRESS_ENTRY(this, hash1);
|
||||
if (PL_DHASH_ENTRY_IS_FREE(entry)) {
|
||||
METER(aTable->stats.misses++);
|
||||
METER(stats.misses++);
|
||||
return (firstRemoved && aOp == PL_DHASH_ADD) ? firstRemoved : entry;
|
||||
}
|
||||
|
||||
if (MATCH_ENTRY_KEYHASH(entry, aKeyHash) &&
|
||||
matchEntry(aTable, entry, aKey)) {
|
||||
METER(aTable->stats.hits++);
|
||||
matchEntry(this, entry, aKey)) {
|
||||
METER(stats.hits++);
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
|
@ -432,26 +458,25 @@ SearchTable(PLDHashTable* aTable, const void* aKey, PLDHashNumber aKeyHash,
|
|||
* entries to keys, which means callers can use complex key types more
|
||||
* easily.
|
||||
*/
|
||||
static PLDHashEntryHdr* PL_DHASH_FASTCALL
|
||||
FindFreeEntry(PLDHashTable* aTable, PLDHashNumber aKeyHash)
|
||||
PLDHashEntryHdr* PL_DHASH_FASTCALL
|
||||
PLDHashTable::FindFreeEntry(PLDHashNumber aKeyHash)
|
||||
{
|
||||
METER(aTable->stats.searches++);
|
||||
METER(stats.searches++);
|
||||
NS_ASSERTION(!(aKeyHash & COLLISION_FLAG),
|
||||
"!(aKeyHash & COLLISION_FLAG)");
|
||||
|
||||
/* Compute the primary hash address. */
|
||||
int hashShift = aTable->hashShift;
|
||||
PLDHashNumber hash1 = HASH1(aKeyHash, hashShift);
|
||||
PLDHashEntryHdr* entry = ADDRESS_ENTRY(aTable, hash1);
|
||||
PLDHashEntryHdr* entry = ADDRESS_ENTRY(this, hash1);
|
||||
|
||||
/* Miss: return space for a new entry. */
|
||||
if (PL_DHASH_ENTRY_IS_FREE(entry)) {
|
||||
METER(aTable->stats.misses++);
|
||||
METER(stats.misses++);
|
||||
return entry;
|
||||
}
|
||||
|
||||
/* Collision: double hash. */
|
||||
int sizeLog2 = PL_DHASH_BITS - aTable->hashShift;
|
||||
int sizeLog2 = PL_DHASH_BITS - hashShift;
|
||||
PLDHashNumber hash2 = HASH2(aKeyHash, sizeLog2, hashShift);
|
||||
uint32_t sizeMask = (1u << sizeLog2) - 1;
|
||||
|
||||
|
@ -460,13 +485,13 @@ FindFreeEntry(PLDHashTable* aTable, PLDHashNumber aKeyHash)
|
|||
"!ENTRY_IS_REMOVED(entry)");
|
||||
entry->keyHash |= COLLISION_FLAG;
|
||||
|
||||
METER(aTable->stats.steps++);
|
||||
METER(stats.steps++);
|
||||
hash1 -= hash2;
|
||||
hash1 &= sizeMask;
|
||||
|
||||
entry = ADDRESS_ENTRY(aTable, hash1);
|
||||
entry = ADDRESS_ENTRY(this, hash1);
|
||||
if (PL_DHASH_ENTRY_IS_FREE(entry)) {
|
||||
METER(aTable->stats.misses++);
|
||||
METER(stats.misses++);
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
|
@ -475,45 +500,44 @@ FindFreeEntry(PLDHashTable* aTable, PLDHashNumber aKeyHash)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
static bool
|
||||
ChangeTable(PLDHashTable* aTable, int aDeltaLog2)
|
||||
bool
|
||||
PLDHashTable::ChangeTable(int aDeltaLog2)
|
||||
{
|
||||
/* Look, but don't touch, until we succeed in getting new entry store. */
|
||||
int oldLog2 = PL_DHASH_BITS - aTable->hashShift;
|
||||
int oldLog2 = PL_DHASH_BITS - hashShift;
|
||||
int newLog2 = oldLog2 + aDeltaLog2;
|
||||
uint32_t newCapacity = 1u << newLog2;
|
||||
if (newCapacity > PL_DHASH_MAX_CAPACITY) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t entrySize = aTable->entrySize;
|
||||
uint32_t nbytes;
|
||||
if (!SizeOfEntryStore(newCapacity, entrySize, &nbytes)) {
|
||||
return false; // overflowed
|
||||
}
|
||||
|
||||
char* newEntryStore = (char*)aTable->ops->allocTable(aTable, nbytes);
|
||||
char* newEntryStore = (char*)ops->allocTable(this, nbytes);
|
||||
if (!newEntryStore) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* We can't fail from here on, so update table parameters. */
|
||||
#ifdef DEBUG
|
||||
uint32_t recursionLevel = aTable->recursionLevel;
|
||||
uint32_t recursionLevelTmp = recursionLevel;
|
||||
#endif
|
||||
aTable->hashShift = PL_DHASH_BITS - newLog2;
|
||||
aTable->removedCount = 0;
|
||||
aTable->generation++;
|
||||
hashShift = PL_DHASH_BITS - newLog2;
|
||||
removedCount = 0;
|
||||
generation++;
|
||||
|
||||
/* Assign the new entry store to table. */
|
||||
memset(newEntryStore, 0, nbytes);
|
||||
char* oldEntryStore;
|
||||
char* oldEntryAddr;
|
||||
oldEntryAddr = oldEntryStore = aTable->entryStore;
|
||||
aTable->entryStore = newEntryStore;
|
||||
PLDHashMoveEntry moveEntry = aTable->ops->moveEntry;
|
||||
oldEntryAddr = oldEntryStore = entryStore;
|
||||
entryStore = newEntryStore;
|
||||
PLDHashMoveEntry moveEntry = ops->moveEntry;
|
||||
#ifdef DEBUG
|
||||
aTable->recursionLevel = recursionLevel;
|
||||
recursionLevel = recursionLevelTmp;
|
||||
#endif
|
||||
|
||||
/* Copy only live entries, leaving removed ones behind. */
|
||||
|
@ -522,28 +546,28 @@ ChangeTable(PLDHashTable* aTable, int aDeltaLog2)
|
|||
PLDHashEntryHdr* oldEntry = (PLDHashEntryHdr*)oldEntryAddr;
|
||||
if (ENTRY_IS_LIVE(oldEntry)) {
|
||||
oldEntry->keyHash &= ~COLLISION_FLAG;
|
||||
PLDHashEntryHdr* newEntry = FindFreeEntry(aTable, oldEntry->keyHash);
|
||||
PLDHashEntryHdr* newEntry = FindFreeEntry(oldEntry->keyHash);
|
||||
NS_ASSERTION(PL_DHASH_ENTRY_IS_FREE(newEntry),
|
||||
"PL_DHASH_ENTRY_IS_FREE(newEntry)");
|
||||
moveEntry(aTable, oldEntry, newEntry);
|
||||
moveEntry(this, oldEntry, newEntry);
|
||||
newEntry->keyHash = oldEntry->keyHash;
|
||||
}
|
||||
oldEntryAddr += entrySize;
|
||||
}
|
||||
|
||||
aTable->ops->freeTable(aTable, oldEntryStore);
|
||||
ops->freeTable(this, oldEntryStore);
|
||||
return true;
|
||||
}
|
||||
|
||||
PLDHashEntryHdr* PL_DHASH_FASTCALL
|
||||
PL_DHashTableOperate(PLDHashTable* aTable, const void* aKey, PLDHashOperator aOp)
|
||||
MOZ_ALWAYS_INLINE PLDHashEntryHdr*
|
||||
PLDHashTable::Operate(const void* aKey, PLDHashOperator aOp)
|
||||
{
|
||||
PLDHashEntryHdr* entry;
|
||||
|
||||
MOZ_ASSERT(aOp == PL_DHASH_LOOKUP || aTable->recursionLevel == 0);
|
||||
INCREMENT_RECURSION_LEVEL(aTable);
|
||||
MOZ_ASSERT(aOp == PL_DHASH_LOOKUP || recursionLevel == 0);
|
||||
INCREMENT_RECURSION_LEVEL(this);
|
||||
|
||||
PLDHashNumber keyHash = aTable->ops->hashKey(aTable, aKey);
|
||||
PLDHashNumber keyHash = ops->hashKey(this, aKey);
|
||||
keyHash *= PL_DHASH_GOLDEN_RATIO;
|
||||
|
||||
/* Avoid 0 and 1 hash codes, they indicate free and removed entries. */
|
||||
|
@ -552,8 +576,8 @@ PL_DHashTableOperate(PLDHashTable* aTable, const void* aKey, PLDHashOperator aOp
|
|||
|
||||
switch (aOp) {
|
||||
case PL_DHASH_LOOKUP:
|
||||
METER(aTable->stats.lookups++);
|
||||
entry = SearchTable(aTable, aKey, keyHash, aOp);
|
||||
METER(stats.lookups++);
|
||||
entry = SearchTable(aKey, keyHash, aOp);
|
||||
break;
|
||||
|
||||
case PL_DHASH_ADD: {
|
||||
|
@ -562,27 +586,27 @@ PL_DHashTableOperate(PLDHashTable* aTable, const void* aKey, PLDHashOperator aOp
|
|||
* in the table, we may grow once more than necessary, but only if we
|
||||
* are on the edge of being overloaded.
|
||||
*/
|
||||
uint32_t capacity = PL_DHASH_TABLE_CAPACITY(aTable);
|
||||
if (aTable->entryCount + aTable->removedCount >= MaxLoad(capacity)) {
|
||||
uint32_t capacity = Capacity();
|
||||
if (entryCount + removedCount >= MaxLoad(capacity)) {
|
||||
/* Compress if a quarter or more of all entries are removed. */
|
||||
int deltaLog2;
|
||||
if (aTable->removedCount >= capacity >> 2) {
|
||||
METER(aTable->stats.compresses++);
|
||||
if (removedCount >= capacity >> 2) {
|
||||
METER(stats.compresses++);
|
||||
deltaLog2 = 0;
|
||||
} else {
|
||||
METER(aTable->stats.grows++);
|
||||
METER(stats.grows++);
|
||||
deltaLog2 = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Grow or compress aTable. If ChangeTable() fails, allow
|
||||
* Grow or compress the table. If ChangeTable() fails, allow
|
||||
* overloading up to the secondary max. Once we hit the secondary
|
||||
* max, return null.
|
||||
*/
|
||||
if (!ChangeTable(aTable, deltaLog2) &&
|
||||
aTable->entryCount + aTable->removedCount >=
|
||||
if (!ChangeTable(deltaLog2) &&
|
||||
entryCount + removedCount >=
|
||||
MaxLoadOnGrowthFailure(capacity)) {
|
||||
METER(aTable->stats.addFailures++);
|
||||
METER(stats.addFailures++);
|
||||
entry = nullptr;
|
||||
break;
|
||||
}
|
||||
|
@ -592,48 +616,47 @@ PL_DHashTableOperate(PLDHashTable* aTable, const void* aKey, PLDHashOperator aOp
|
|||
* Look for entry after possibly growing, so we don't have to add it,
|
||||
* then skip it while growing the table and re-add it after.
|
||||
*/
|
||||
entry = SearchTable(aTable, aKey, keyHash, aOp);
|
||||
entry = SearchTable(aKey, keyHash, aOp);
|
||||
if (!ENTRY_IS_LIVE(entry)) {
|
||||
/* Initialize the entry, indicating that it's no longer free. */
|
||||
METER(aTable->stats.addMisses++);
|
||||
METER(stats.addMisses++);
|
||||
if (ENTRY_IS_REMOVED(entry)) {
|
||||
METER(aTable->stats.addOverRemoved++);
|
||||
aTable->removedCount--;
|
||||
METER(stats.addOverRemoved++);
|
||||
removedCount--;
|
||||
keyHash |= COLLISION_FLAG;
|
||||
}
|
||||
if (aTable->ops->initEntry &&
|
||||
!aTable->ops->initEntry(aTable, entry, aKey)) {
|
||||
if (ops->initEntry && !ops->initEntry(this, entry, aKey)) {
|
||||
/* We haven't claimed entry yet; fail with null return. */
|
||||
memset(entry + 1, 0, aTable->entrySize - sizeof(*entry));
|
||||
memset(entry + 1, 0, entrySize - sizeof(*entry));
|
||||
entry = nullptr;
|
||||
break;
|
||||
}
|
||||
entry->keyHash = keyHash;
|
||||
aTable->entryCount++;
|
||||
entryCount++;
|
||||
}
|
||||
METER(else {
|
||||
aTable->stats.addHits++;
|
||||
stats.addHits++;
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
case PL_DHASH_REMOVE:
|
||||
entry = SearchTable(aTable, aKey, keyHash, aOp);
|
||||
entry = SearchTable(aKey, keyHash, aOp);
|
||||
if (ENTRY_IS_LIVE(entry)) {
|
||||
/* Clear this entry and mark it as "removed". */
|
||||
METER(aTable->stats.removeHits++);
|
||||
PL_DHashTableRawRemove(aTable, entry);
|
||||
METER(stats.removeHits++);
|
||||
PL_DHashTableRawRemove(this, entry);
|
||||
|
||||
/* Shrink if alpha is <= .25 and aTable isn't too small already. */
|
||||
uint32_t capacity = PL_DHASH_TABLE_CAPACITY(aTable);
|
||||
/* Shrink if alpha is <= .25 and the table isn't too small already. */
|
||||
uint32_t capacity = Capacity();
|
||||
if (capacity > PL_DHASH_MIN_CAPACITY &&
|
||||
aTable->entryCount <= MinLoad(capacity)) {
|
||||
METER(aTable->stats.shrinks++);
|
||||
(void) ChangeTable(aTable, -1);
|
||||
entryCount <= MinLoad(capacity)) {
|
||||
METER(stats.shrinks++);
|
||||
(void) ChangeTable(-1);
|
||||
}
|
||||
}
|
||||
METER(else {
|
||||
aTable->stats.removeMisses++;
|
||||
stats.removeMisses++;
|
||||
});
|
||||
entry = nullptr;
|
||||
break;
|
||||
|
@ -643,40 +666,50 @@ PL_DHashTableOperate(PLDHashTable* aTable, const void* aKey, PLDHashOperator aOp
|
|||
entry = nullptr;
|
||||
}
|
||||
|
||||
DECREMENT_RECURSION_LEVEL(aTable);
|
||||
DECREMENT_RECURSION_LEVEL(this);
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
PLDHashEntryHdr* PL_DHASH_FASTCALL
|
||||
PL_DHashTableOperate(PLDHashTable* aTable, const void* aKey, PLDHashOperator aOp)
|
||||
{
|
||||
return aTable->Operate(aKey, aOp);
|
||||
}
|
||||
|
||||
MOZ_ALWAYS_INLINE void
|
||||
PLDHashTable::RawRemove(PLDHashEntryHdr* aEntry)
|
||||
{
|
||||
MOZ_ASSERT(recursionLevel != IMMUTABLE_RECURSION_LEVEL);
|
||||
|
||||
NS_ASSERTION(ENTRY_IS_LIVE(aEntry), "ENTRY_IS_LIVE(aEntry)");
|
||||
|
||||
/* Load keyHash first in case clearEntry() goofs it. */
|
||||
PLDHashNumber keyHash = aEntry->keyHash;
|
||||
ops->clearEntry(this, aEntry);
|
||||
if (keyHash & COLLISION_FLAG) {
|
||||
MARK_ENTRY_REMOVED(aEntry);
|
||||
removedCount++;
|
||||
} else {
|
||||
METER(stats.removeFrees++);
|
||||
MARK_ENTRY_FREE(aEntry);
|
||||
}
|
||||
entryCount--;
|
||||
}
|
||||
|
||||
void
|
||||
PL_DHashTableRawRemove(PLDHashTable* aTable, PLDHashEntryHdr* aEntry)
|
||||
{
|
||||
MOZ_ASSERT(aTable->recursionLevel != IMMUTABLE_RECURSION_LEVEL);
|
||||
|
||||
NS_ASSERTION(PL_DHASH_ENTRY_IS_LIVE(aEntry),
|
||||
"PL_DHASH_ENTRY_IS_LIVE(aEntry)");
|
||||
|
||||
/* Load keyHash first in case clearEntry() goofs it. */
|
||||
PLDHashNumber keyHash = aEntry->keyHash;
|
||||
aTable->ops->clearEntry(aTable, aEntry);
|
||||
if (keyHash & COLLISION_FLAG) {
|
||||
MARK_ENTRY_REMOVED(aEntry);
|
||||
aTable->removedCount++;
|
||||
} else {
|
||||
METER(aTable->stats.removeFrees++);
|
||||
MARK_ENTRY_FREE(aEntry);
|
||||
}
|
||||
aTable->entryCount--;
|
||||
aTable->RawRemove(aEntry);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
PL_DHashTableEnumerate(PLDHashTable* aTable, PLDHashEnumerator aEtor, void* aArg)
|
||||
MOZ_ALWAYS_INLINE uint32_t
|
||||
PLDHashTable::Enumerate(PLDHashEnumerator aEtor, void* aArg)
|
||||
{
|
||||
INCREMENT_RECURSION_LEVEL(aTable);
|
||||
INCREMENT_RECURSION_LEVEL(this);
|
||||
|
||||
char* entryAddr = aTable->entryStore;
|
||||
uint32_t entrySize = aTable->entrySize;
|
||||
uint32_t capacity = PL_DHASH_TABLE_CAPACITY(aTable);
|
||||
char* entryAddr = entryStore;
|
||||
uint32_t capacity = Capacity();
|
||||
uint32_t tableSize = capacity * entrySize;
|
||||
char* entryLimit = entryAddr + tableSize;
|
||||
uint32_t i = 0;
|
||||
|
@ -695,10 +728,10 @@ PL_DHashTableEnumerate(PLDHashTable* aTable, PLDHashEnumerator aEtor, void* aArg
|
|||
for (uint32_t e = 0; e < capacity; ++e) {
|
||||
PLDHashEntryHdr* entry = (PLDHashEntryHdr*)entryAddr;
|
||||
if (ENTRY_IS_LIVE(entry)) {
|
||||
PLDHashOperator op = aEtor(aTable, entry, i++, aArg);
|
||||
PLDHashOperator op = aEtor(this, entry, i++, aArg);
|
||||
if (op & PL_DHASH_REMOVE) {
|
||||
METER(aTable->stats.removeEnums++);
|
||||
PL_DHashTableRawRemove(aTable, entry);
|
||||
METER(stats.removeEnums++);
|
||||
PL_DHashTableRawRemove(this, entry);
|
||||
didRemove = true;
|
||||
}
|
||||
if (op & PL_DHASH_STOP) {
|
||||
|
@ -711,37 +744,44 @@ PL_DHashTableEnumerate(PLDHashTable* aTable, PLDHashEnumerator aEtor, void* aArg
|
|||
}
|
||||
}
|
||||
|
||||
MOZ_ASSERT(!didRemove || aTable->recursionLevel == 1);
|
||||
MOZ_ASSERT(!didRemove || recursionLevel == 1);
|
||||
|
||||
/*
|
||||
* Shrink or compress if a quarter or more of all entries are removed, or
|
||||
* if the table is underloaded according to the minimum alpha, and is not
|
||||
* minimal-size already. Do this only if we removed above, so non-removing
|
||||
* enumerations can count on stable aTable->entryStore until the next
|
||||
* enumerations can count on stable |entryStore| until the next
|
||||
* non-lookup-Operate or removing-Enumerate.
|
||||
*/
|
||||
if (didRemove &&
|
||||
(aTable->removedCount >= capacity >> 2 ||
|
||||
(removedCount >= capacity >> 2 ||
|
||||
(capacity > PL_DHASH_MIN_CAPACITY &&
|
||||
aTable->entryCount <= MinLoad(capacity)))) {
|
||||
METER(aTable->stats.enumShrinks++);
|
||||
capacity = aTable->entryCount;
|
||||
entryCount <= MinLoad(capacity)))) {
|
||||
METER(stats.enumShrinks++);
|
||||
capacity = entryCount;
|
||||
capacity += capacity >> 1;
|
||||
if (capacity < PL_DHASH_MIN_CAPACITY) {
|
||||
capacity = PL_DHASH_MIN_CAPACITY;
|
||||
}
|
||||
|
||||
uint32_t ceiling = CeilingLog2(capacity);
|
||||
ceiling -= PL_DHASH_BITS - aTable->hashShift;
|
||||
ceiling -= PL_DHASH_BITS - hashShift;
|
||||
|
||||
(void) ChangeTable(aTable, ceiling);
|
||||
(void) ChangeTable(ceiling);
|
||||
}
|
||||
|
||||
DECREMENT_RECURSION_LEVEL(aTable);
|
||||
DECREMENT_RECURSION_LEVEL(this);
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
PL_DHashTableEnumerate(PLDHashTable* aTable, PLDHashEnumerator aEtor,
|
||||
void* aArg)
|
||||
{
|
||||
return aTable->Enumerate(aEtor, aArg);
|
||||
}
|
||||
|
||||
struct SizeOfEntryExcludingThisArg
|
||||
{
|
||||
size_t total;
|
||||
|
@ -759,23 +799,41 @@ SizeOfEntryExcludingThisEnumerator(PLDHashTable* aTable, PLDHashEntryHdr* aHdr,
|
|||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
MOZ_ALWAYS_INLINE size_t
|
||||
PLDHashTable::SizeOfExcludingThis(
|
||||
PLDHashSizeOfEntryExcludingThisFun aSizeOfEntryExcludingThis,
|
||||
MallocSizeOf aMallocSizeOf, void* aArg /* = nullptr */) const
|
||||
{
|
||||
size_t n = 0;
|
||||
n += aMallocSizeOf(entryStore);
|
||||
if (aSizeOfEntryExcludingThis) {
|
||||
SizeOfEntryExcludingThisArg arg2 = {
|
||||
0, aSizeOfEntryExcludingThis, aMallocSizeOf, aArg
|
||||
};
|
||||
PL_DHashTableEnumerate(const_cast<PLDHashTable*>(this),
|
||||
SizeOfEntryExcludingThisEnumerator, &arg2);
|
||||
n += arg2.total;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
MOZ_ALWAYS_INLINE size_t
|
||||
PLDHashTable::SizeOfIncludingThis(
|
||||
PLDHashSizeOfEntryExcludingThisFun aSizeOfEntryExcludingThis,
|
||||
MallocSizeOf aMallocSizeOf, void* aArg /* = nullptr */) const
|
||||
{
|
||||
return aMallocSizeOf(this) +
|
||||
SizeOfExcludingThis(aSizeOfEntryExcludingThis, aMallocSizeOf, aArg);
|
||||
}
|
||||
|
||||
size_t
|
||||
PL_DHashTableSizeOfExcludingThis(
|
||||
const PLDHashTable* aTable,
|
||||
PLDHashSizeOfEntryExcludingThisFun aSizeOfEntryExcludingThis,
|
||||
MallocSizeOf aMallocSizeOf, void* aArg /* = nullptr */)
|
||||
{
|
||||
size_t n = 0;
|
||||
n += aMallocSizeOf(aTable->entryStore);
|
||||
if (aSizeOfEntryExcludingThis) {
|
||||
SizeOfEntryExcludingThisArg arg2 = {
|
||||
0, aSizeOfEntryExcludingThis, aMallocSizeOf, aArg
|
||||
};
|
||||
PL_DHashTableEnumerate(const_cast<PLDHashTable*>(aTable),
|
||||
SizeOfEntryExcludingThisEnumerator, &arg2);
|
||||
n += arg2.total;
|
||||
}
|
||||
return n;
|
||||
return aTable->SizeOfExcludingThis(aSizeOfEntryExcludingThis,
|
||||
aMallocSizeOf, aArg);
|
||||
}
|
||||
|
||||
size_t
|
||||
|
@ -784,16 +842,21 @@ PL_DHashTableSizeOfIncludingThis(
|
|||
PLDHashSizeOfEntryExcludingThisFun aSizeOfEntryExcludingThis,
|
||||
MallocSizeOf aMallocSizeOf, void* aArg /* = nullptr */)
|
||||
{
|
||||
return aMallocSizeOf(aTable) +
|
||||
PL_DHashTableSizeOfExcludingThis(aTable, aSizeOfEntryExcludingThis,
|
||||
aMallocSizeOf, aArg);
|
||||
return aTable->SizeOfIncludingThis(aSizeOfEntryExcludingThis,
|
||||
aMallocSizeOf, aArg);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
MOZ_ALWAYS_INLINE void
|
||||
PLDHashTable::MarkImmutable()
|
||||
{
|
||||
recursionLevel = IMMUTABLE_RECURSION_LEVEL;
|
||||
}
|
||||
|
||||
void
|
||||
PL_DHashMarkTableImmutable(PLDHashTable* aTable)
|
||||
{
|
||||
aTable->recursionLevel = IMMUTABLE_RECURSION_LEVEL;
|
||||
aTable->MarkImmutable();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -801,17 +864,15 @@ PL_DHashMarkTableImmutable(PLDHashTable* aTable)
|
|||
#include <math.h>
|
||||
|
||||
void
|
||||
PL_DHashTableDumpMeter(PLDHashTable* aTable, PLDHashEnumerator aDump, FILE* aFp)
|
||||
PLDHashTable::DumpMeter(PLDHashEnumerator aDump, FILE* aFp)
|
||||
{
|
||||
PLDHashNumber hash1, hash2, maxChainHash1, maxChainHash2;
|
||||
double sqsum, mean, variance, sigma;
|
||||
PLDHashEntryHdr* entry;
|
||||
|
||||
char* entryAddr = aTable->entryStore;
|
||||
uint32_t entrySize = aTable->entrySize;
|
||||
int hashShift = aTable->hashShift;
|
||||
char* entryAddr = entryStore;
|
||||
int sizeLog2 = PL_DHASH_BITS - hashShift;
|
||||
uint32_t capacity = PL_DHASH_TABLE_CAPACITY(aTable);
|
||||
uint32_t capacity = Capacity();
|
||||
uint32_t sizeMask = (1u << sizeLog2) - 1;
|
||||
uint32_t chainCount = 0, maxChainLen = 0;
|
||||
hash2 = 0;
|
||||
|
@ -825,7 +886,7 @@ PL_DHashTableDumpMeter(PLDHashTable* aTable, PLDHashEnumerator aDump, FILE* aFp)
|
|||
}
|
||||
hash1 = HASH1(entry->keyHash & ~COLLISION_FLAG, hashShift);
|
||||
PLDHashNumber saveHash1 = hash1;
|
||||
PLDHashEntryHdr* probe = ADDRESS_ENTRY(aTable, hash1);
|
||||
PLDHashEntryHdr* probe = ADDRESS_ENTRY(this, hash1);
|
||||
uint32_t chainLen = 1;
|
||||
if (probe == entry) {
|
||||
/* Start of a (possibly unit-length) chain. */
|
||||
|
@ -837,7 +898,7 @@ PL_DHashTableDumpMeter(PLDHashTable* aTable, PLDHashEnumerator aDump, FILE* aFp)
|
|||
chainLen++;
|
||||
hash1 -= hash2;
|
||||
hash1 &= sizeMask;
|
||||
probe = ADDRESS_ENTRY(aTable, hash1);
|
||||
probe = ADDRESS_ENTRY(this, hash1);
|
||||
} while (probe != entry);
|
||||
}
|
||||
sqsum += chainLen * chainLen;
|
||||
|
@ -848,7 +909,6 @@ PL_DHashTableDumpMeter(PLDHashTable* aTable, PLDHashEnumerator aDump, FILE* aFp)
|
|||
}
|
||||
}
|
||||
|
||||
uint32_t entryCount = aTable->entryCount;
|
||||
if (entryCount && chainCount) {
|
||||
mean = (double)entryCount / chainCount;
|
||||
variance = chainCount * sqsum - entryCount * entryCount;
|
||||
|
@ -864,45 +924,50 @@ PL_DHashTableDumpMeter(PLDHashTable* aTable, PLDHashEnumerator aDump, FILE* aFp)
|
|||
|
||||
fprintf(aFp, "Double hashing statistics:\n");
|
||||
fprintf(aFp, " table size (in entries): %u\n", tableSize);
|
||||
fprintf(aFp, " number of entries: %u\n", aTable->entryCount);
|
||||
fprintf(aFp, " number of removed entries: %u\n", aTable->removedCount);
|
||||
fprintf(aFp, " number of searches: %u\n", aTable->stats.searches);
|
||||
fprintf(aFp, " number of hits: %u\n", aTable->stats.hits);
|
||||
fprintf(aFp, " number of misses: %u\n", aTable->stats.misses);
|
||||
fprintf(aFp, " number of entries: %u\n", entryCount);
|
||||
fprintf(aFp, " number of removed entries: %u\n", removedCount);
|
||||
fprintf(aFp, " number of searches: %u\n", stats.searches);
|
||||
fprintf(aFp, " number of hits: %u\n", stats.hits);
|
||||
fprintf(aFp, " number of misses: %u\n", stats.misses);
|
||||
fprintf(aFp, " mean steps per search: %g\n",
|
||||
aTable->stats.searches ?
|
||||
(double)aTable->stats.steps / aTable->stats.searches : 0.);
|
||||
stats.searches ? (double)stats.steps / stats.searches : 0.);
|
||||
fprintf(aFp, " mean hash chain length: %g\n", mean);
|
||||
fprintf(aFp, " standard deviation: %g\n", sigma);
|
||||
fprintf(aFp, " maximum hash chain length: %u\n", maxChainLen);
|
||||
fprintf(aFp, " number of lookups: %u\n", aTable->stats.lookups);
|
||||
fprintf(aFp, " adds that made a new entry: %u\n", aTable->stats.addMisses);
|
||||
fprintf(aFp, "adds that recycled removeds: %u\n", aTable->stats.addOverRemoved);
|
||||
fprintf(aFp, " adds that found an entry: %u\n", aTable->stats.addHits);
|
||||
fprintf(aFp, " add failures: %u\n", aTable->stats.addFailures);
|
||||
fprintf(aFp, " useful removes: %u\n", aTable->stats.removeHits);
|
||||
fprintf(aFp, " useless removes: %u\n", aTable->stats.removeMisses);
|
||||
fprintf(aFp, "removes that freed an entry: %u\n", aTable->stats.removeFrees);
|
||||
fprintf(aFp, " removes while enumerating: %u\n", aTable->stats.removeEnums);
|
||||
fprintf(aFp, " number of grows: %u\n", aTable->stats.grows);
|
||||
fprintf(aFp, " number of shrinks: %u\n", aTable->stats.shrinks);
|
||||
fprintf(aFp, " number of compresses: %u\n", aTable->stats.compresses);
|
||||
fprintf(aFp, "number of enumerate shrinks: %u\n", aTable->stats.enumShrinks);
|
||||
fprintf(aFp, " number of lookups: %u\n", stats.lookups);
|
||||
fprintf(aFp, " adds that made a new entry: %u\n", stats.addMisses);
|
||||
fprintf(aFp, "adds that recycled removeds: %u\n", stats.addOverRemoved);
|
||||
fprintf(aFp, " adds that found an entry: %u\n", stats.addHits);
|
||||
fprintf(aFp, " add failures: %u\n", stats.addFailures);
|
||||
fprintf(aFp, " useful removes: %u\n", stats.removeHits);
|
||||
fprintf(aFp, " useless removes: %u\n", stats.removeMisses);
|
||||
fprintf(aFp, "removes that freed an entry: %u\n", stats.removeFrees);
|
||||
fprintf(aFp, " removes while enumerating: %u\n", stats.removeEnums);
|
||||
fprintf(aFp, " number of grows: %u\n", stats.grows);
|
||||
fprintf(aFp, " number of shrinks: %u\n", stats.shrinks);
|
||||
fprintf(aFp, " number of compresses: %u\n", stats.compresses);
|
||||
fprintf(aFp, "number of enumerate shrinks: %u\n", stats.enumShrinks);
|
||||
|
||||
if (aDump && maxChainLen && hash2) {
|
||||
fputs("Maximum hash chain:\n", aFp);
|
||||
hash1 = maxChainHash1;
|
||||
hash2 = maxChainHash2;
|
||||
entry = ADDRESS_ENTRY(aTable, hash1);
|
||||
entry = ADDRESS_ENTRY(this, hash1);
|
||||
uint32_t i = 0;
|
||||
do {
|
||||
if (aDump(aTable, entry, i++, aFp) != PL_DHASH_NEXT) {
|
||||
if (aDump(this, entry, i++, aFp) != PL_DHASH_NEXT) {
|
||||
break;
|
||||
}
|
||||
hash1 -= hash2;
|
||||
hash1 &= sizeMask;
|
||||
entry = ADDRESS_ENTRY(aTable, hash1);
|
||||
entry = ADDRESS_ENTRY(this, hash1);
|
||||
} while (PL_DHASH_ENTRY_IS_BUSY(entry));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PL_DHashTableDumpMeter(PLDHashTable* aTable, PLDHashEnumerator aDump, FILE* aFp)
|
||||
{
|
||||
aTable->DumpMeter(aDump, aFp);
|
||||
}
|
||||
#endif /* PL_DHASHMETER */
|
||||
|
|
|
@ -75,11 +75,6 @@ typedef struct PLDHashTableOps PLDHashTableOps;
|
|||
* maintained automatically by PL_DHashTableOperate -- users should never set
|
||||
* it, and its only uses should be via the entry macros below.
|
||||
*
|
||||
* The PL_DHASH_ENTRY_IS_LIVE function tests whether entry is neither free nor
|
||||
* removed. An entry may be either busy or free; if busy, it may be live or
|
||||
* removed. Consumers of this API should not access members of entries that
|
||||
* are not live.
|
||||
*
|
||||
* However, use PL_DHASH_ENTRY_IS_BUSY for faster liveness testing of entries
|
||||
* returned by PL_DHashTableOperate, as PL_DHashTableOperate never returns a
|
||||
* non-live, busy (i.e., removed) entry pointer to its caller. See below for
|
||||
|
@ -102,11 +97,66 @@ PL_DHASH_ENTRY_IS_BUSY(PLDHashEntryHdr* aEntry)
|
|||
return !PL_DHASH_ENTRY_IS_FREE(aEntry);
|
||||
}
|
||||
|
||||
MOZ_ALWAYS_INLINE bool
|
||||
PL_DHASH_ENTRY_IS_LIVE(PLDHashEntryHdr* aEntry)
|
||||
/*
|
||||
* To consolidate keyHash computation and table grow/shrink code, we use a
|
||||
* single entry point for lookup, add, and remove operations. The operation
|
||||
* codes are declared here, along with codes returned by PLDHashEnumerator
|
||||
* functions, which control PL_DHashTableEnumerate's behavior.
|
||||
*/
|
||||
typedef enum PLDHashOperator
|
||||
{
|
||||
return aEntry->keyHash >= 2;
|
||||
}
|
||||
PL_DHASH_LOOKUP = 0, /* lookup entry */
|
||||
PL_DHASH_ADD = 1, /* add entry */
|
||||
PL_DHASH_REMOVE = 2, /* remove entry, or enumerator says remove */
|
||||
PL_DHASH_NEXT = 0, /* enumerator says continue */
|
||||
PL_DHASH_STOP = 1 /* enumerator says stop */
|
||||
} PLDHashOperator;
|
||||
|
||||
/*
|
||||
* Enumerate entries in table using etor:
|
||||
*
|
||||
* count = PL_DHashTableEnumerate(table, etor, arg);
|
||||
*
|
||||
* PL_DHashTableEnumerate calls etor like so:
|
||||
*
|
||||
* op = etor(table, entry, number, arg);
|
||||
*
|
||||
* where number is a zero-based ordinal assigned to live entries according to
|
||||
* their order in aTable->entryStore.
|
||||
*
|
||||
* The return value, op, is treated as a set of flags. If op is PL_DHASH_NEXT,
|
||||
* then continue enumerating. If op contains PL_DHASH_REMOVE, then clear (via
|
||||
* aTable->ops->clearEntry) and free entry. Then we check whether op contains
|
||||
* PL_DHASH_STOP; if so, stop enumerating and return the number of live entries
|
||||
* that were enumerated so far. Return the total number of live entries when
|
||||
* enumeration completes normally.
|
||||
*
|
||||
* If etor calls PL_DHashTableOperate on table with op != PL_DHASH_LOOKUP, it
|
||||
* must return PL_DHASH_STOP; otherwise undefined behavior results.
|
||||
*
|
||||
* If any enumerator returns PL_DHASH_REMOVE, aTable->entryStore may be shrunk
|
||||
* or compressed after enumeration, but before PL_DHashTableEnumerate returns.
|
||||
* Such an enumerator therefore can't safely set aside entry pointers, but an
|
||||
* enumerator that never returns PL_DHASH_REMOVE can set pointers to entries
|
||||
* aside, e.g., to avoid copying live entries into an array of the entry type.
|
||||
* Copying entry pointers is cheaper, and safe so long as the caller of such a
|
||||
* "stable" Enumerate doesn't use the set-aside pointers after any call either
|
||||
* to PL_DHashTableOperate, or to an "unstable" form of Enumerate, which might
|
||||
* grow or shrink entryStore.
|
||||
*
|
||||
* If your enumerator wants to remove certain entries, but set aside pointers
|
||||
* to other entries that it retains, it can use PL_DHashTableRawRemove on the
|
||||
* entries to be removed, returning PL_DHASH_NEXT to skip them. Likewise, if
|
||||
* you want to remove entries, but for some reason you do not want entryStore
|
||||
* to be shrunk or compressed, you can call PL_DHashTableRawRemove safely on
|
||||
* the entry being enumerated, rather than returning PL_DHASH_REMOVE.
|
||||
*/
|
||||
typedef PLDHashOperator (*PLDHashEnumerator)(PLDHashTable* aTable,
|
||||
PLDHashEntryHdr* aHdr,
|
||||
uint32_t aNumber, void* aArg);
|
||||
|
||||
typedef size_t (*PLDHashSizeOfEntryExcludingThisFun)(
|
||||
PLDHashEntryHdr* aHdr, mozilla::MallocSizeOf aMallocSizeOf, void* aArg);
|
||||
|
||||
/*
|
||||
* A PLDHashTable is currently 8 words (without the PL_DHASHMETER overhead)
|
||||
|
@ -182,8 +232,15 @@ PL_DHASH_ENTRY_IS_LIVE(PLDHashEntryHdr* aEntry)
|
|||
*/
|
||||
struct PLDHashTable
|
||||
{
|
||||
const PLDHashTableOps* ops; /* virtual operations, see below */
|
||||
/*
|
||||
* Virtual operations; see below. This field is public because it's commonly
|
||||
* zeroed to indicate that a table is no longer live.
|
||||
*/
|
||||
const PLDHashTableOps* ops;
|
||||
|
||||
void* data; /* ops- and instance-specific data */
|
||||
|
||||
private:
|
||||
int16_t hashShift; /* multiplicative hash shift */
|
||||
/*
|
||||
* |recursionLevel| is only used in debug builds, but is present in opt
|
||||
|
@ -197,6 +254,7 @@ struct PLDHashTable
|
|||
uint32_t removedCount; /* removed entry sentinels in table */
|
||||
uint32_t generation; /* entry storage generation number */
|
||||
char* entryStore; /* entry storage */
|
||||
|
||||
#ifdef PL_DHASHMETER
|
||||
struct PLDHashStats
|
||||
{
|
||||
|
@ -219,15 +277,63 @@ struct PLDHashTable
|
|||
uint32_t enumShrinks; /* contractions after Enumerate */
|
||||
} stats;
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
* Size in entries (gross, not net of free and removed sentinels) for table.
|
||||
* We store hashShift rather than sizeLog2 to optimize the collision-free case
|
||||
* in SearchTable.
|
||||
*/
|
||||
#define PL_DHASH_TABLE_CAPACITY(table) \
|
||||
((uint32_t)1 << (PL_DHASH_BITS - (table)->hashShift))
|
||||
public:
|
||||
/*
|
||||
* Size in entries (gross, not net of free and removed sentinels) for table.
|
||||
* We store hashShift rather than sizeLog2 to optimize the collision-free case
|
||||
* in SearchTable.
|
||||
*/
|
||||
uint32_t Capacity() const
|
||||
{
|
||||
return ((uint32_t)1 << (PL_DHASH_BITS - hashShift));
|
||||
}
|
||||
|
||||
uint32_t EntrySize() const { return entrySize; }
|
||||
uint32_t EntryCount() const { return entryCount; }
|
||||
uint32_t Generation() const { return generation; }
|
||||
|
||||
bool Init(const PLDHashTableOps* aOps, void* aData, uint32_t aEntrySize,
|
||||
const mozilla::fallible_t&, uint32_t aLength);
|
||||
|
||||
void Finish();
|
||||
|
||||
PLDHashEntryHdr* Operate(const void* aKey, PLDHashOperator aOp);
|
||||
|
||||
void RawRemove(PLDHashEntryHdr* aEntry);
|
||||
|
||||
uint32_t Enumerate(PLDHashEnumerator aEtor, void* aArg);
|
||||
|
||||
size_t SizeOfIncludingThis(
|
||||
PLDHashSizeOfEntryExcludingThisFun aSizeOfEntryExcludingThis,
|
||||
mozilla::MallocSizeOf aMallocSizeOf, void* aArg = nullptr) const;
|
||||
|
||||
size_t SizeOfExcludingThis(
|
||||
PLDHashSizeOfEntryExcludingThisFun aSizeOfEntryExcludingThis,
|
||||
mozilla::MallocSizeOf aMallocSizeOf, void* aArg = nullptr) const;
|
||||
|
||||
#ifdef DEBUG
|
||||
void MarkImmutable();
|
||||
#endif
|
||||
|
||||
void MoveEntryStub(const PLDHashEntryHdr* aFrom, PLDHashEntryHdr* aTo);
|
||||
|
||||
void ClearEntryStub(PLDHashEntryHdr* aEntry);
|
||||
|
||||
void FreeStringKey(PLDHashEntryHdr* aEntry);
|
||||
|
||||
#ifdef PL_DHASHMETER
|
||||
void DumpMeter(PLDHashEnumerator aDump, FILE* aFp);
|
||||
#endif
|
||||
|
||||
private:
|
||||
PLDHashEntryHdr* PL_DHASH_FASTCALL
|
||||
SearchTable(const void* aKey, PLDHashNumber aKeyHash, PLDHashOperator aOp);
|
||||
|
||||
PLDHashEntryHdr* PL_DHASH_FASTCALL FindFreeEntry(PLDHashNumber aKeyHash);
|
||||
|
||||
bool ChangeTable(int aDeltaLog2);
|
||||
};
|
||||
|
||||
/*
|
||||
* Table space at entryStore is allocated and freed using these callbacks.
|
||||
|
@ -424,21 +530,6 @@ MOZ_WARN_UNUSED_RESULT NS_COM_GLUE bool PL_DHashTableInit(
|
|||
*/
|
||||
NS_COM_GLUE void PL_DHashTableFinish(PLDHashTable* aTable);
|
||||
|
||||
/*
|
||||
* To consolidate keyHash computation and table grow/shrink code, we use a
|
||||
* single entry point for lookup, add, and remove operations. The operation
|
||||
* codes are declared here, along with codes returned by PLDHashEnumerator
|
||||
* functions, which control PL_DHashTableEnumerate's behavior.
|
||||
*/
|
||||
typedef enum PLDHashOperator
|
||||
{
|
||||
PL_DHASH_LOOKUP = 0, /* lookup entry */
|
||||
PL_DHASH_ADD = 1, /* add entry */
|
||||
PL_DHASH_REMOVE = 2, /* remove entry, or enumerator says remove */
|
||||
PL_DHASH_NEXT = 0, /* enumerator says continue */
|
||||
PL_DHASH_STOP = 1 /* enumerator says stop */
|
||||
} PLDHashOperator;
|
||||
|
||||
/*
|
||||
* To lookup a key in table, call:
|
||||
*
|
||||
|
@ -485,56 +576,10 @@ PL_DHashTableOperate(PLDHashTable* aTable, const void* aKey,
|
|||
NS_COM_GLUE void PL_DHashTableRawRemove(PLDHashTable* aTable,
|
||||
PLDHashEntryHdr* aEntry);
|
||||
|
||||
/*
|
||||
* Enumerate entries in table using etor:
|
||||
*
|
||||
* count = PL_DHashTableEnumerate(table, etor, arg);
|
||||
*
|
||||
* PL_DHashTableEnumerate calls etor like so:
|
||||
*
|
||||
* op = etor(table, entry, number, arg);
|
||||
*
|
||||
* where number is a zero-based ordinal assigned to live entries according to
|
||||
* their order in aTable->entryStore.
|
||||
*
|
||||
* The return value, op, is treated as a set of flags. If op is PL_DHASH_NEXT,
|
||||
* then continue enumerating. If op contains PL_DHASH_REMOVE, then clear (via
|
||||
* aTable->ops->clearEntry) and free entry. Then we check whether op contains
|
||||
* PL_DHASH_STOP; if so, stop enumerating and return the number of live entries
|
||||
* that were enumerated so far. Return the total number of live entries when
|
||||
* enumeration completes normally.
|
||||
*
|
||||
* If etor calls PL_DHashTableOperate on table with op != PL_DHASH_LOOKUP, it
|
||||
* must return PL_DHASH_STOP; otherwise undefined behavior results.
|
||||
*
|
||||
* If any enumerator returns PL_DHASH_REMOVE, aTable->entryStore may be shrunk
|
||||
* or compressed after enumeration, but before PL_DHashTableEnumerate returns.
|
||||
* Such an enumerator therefore can't safely set aside entry pointers, but an
|
||||
* enumerator that never returns PL_DHASH_REMOVE can set pointers to entries
|
||||
* aside, e.g., to avoid copying live entries into an array of the entry type.
|
||||
* Copying entry pointers is cheaper, and safe so long as the caller of such a
|
||||
* "stable" Enumerate doesn't use the set-aside pointers after any call either
|
||||
* to PL_DHashTableOperate, or to an "unstable" form of Enumerate, which might
|
||||
* grow or shrink entryStore.
|
||||
*
|
||||
* If your enumerator wants to remove certain entries, but set aside pointers
|
||||
* to other entries that it retains, it can use PL_DHashTableRawRemove on the
|
||||
* entries to be removed, returning PL_DHASH_NEXT to skip them. Likewise, if
|
||||
* you want to remove entries, but for some reason you do not want entryStore
|
||||
* to be shrunk or compressed, you can call PL_DHashTableRawRemove safely on
|
||||
* the entry being enumerated, rather than returning PL_DHASH_REMOVE.
|
||||
*/
|
||||
typedef PLDHashOperator (*PLDHashEnumerator)(PLDHashTable* aTable,
|
||||
PLDHashEntryHdr* aHdr,
|
||||
uint32_t aNumber, void* aArg);
|
||||
|
||||
NS_COM_GLUE uint32_t
|
||||
PL_DHashTableEnumerate(PLDHashTable* aTable, PLDHashEnumerator aEtor,
|
||||
void* aArg);
|
||||
|
||||
typedef size_t (*PLDHashSizeOfEntryExcludingThisFun)(
|
||||
PLDHashEntryHdr* aHdr, 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
|
||||
|
|
Загрузка…
Ссылка в новой задаче