зеркало из https://github.com/mozilla/pjs.git
Avoid the need for a getKey callback in jsdhash/pldhash. b=374906 r=brendan
This commit is contained in:
Родитель
8d6f188743
Коммит
4984d6ed39
|
@ -22,6 +22,7 @@
|
|||
* Contributor(s):
|
||||
* Brendan Eich <brendan@mozilla.org> (Original Author)
|
||||
* Chris Waterson <waterson@netscape.com>
|
||||
* L. David Baron <dbaron@dbaron.org>, Mozilla Corporation
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
|
@ -461,6 +462,65 @@ SearchTable(JSDHashTable *table, const void *key, JSDHashNumber keyHash,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is a copy of SearchTable, used by ChangeTable, hardcoded to
|
||||
* 1. assume |op == PL_DHASH_ADD|,
|
||||
* 2. assume that |key| will never match an existing entry, and
|
||||
* 3. assume that no entries have been removed from the current table
|
||||
* structure.
|
||||
* Avoiding the need for |key| means we can avoid needing a way to map
|
||||
* entries to keys, which means callers can use complex key types more
|
||||
* easily.
|
||||
*/
|
||||
static JSDHashEntryHdr * JS_DHASH_FASTCALL
|
||||
FindFreeEntry(JSDHashTable *table, JSDHashNumber keyHash)
|
||||
{
|
||||
JSDHashNumber hash1, hash2;
|
||||
int hashShift, sizeLog2;
|
||||
JSDHashEntryHdr *entry;
|
||||
uint32 sizeMask;
|
||||
|
||||
METER(table->stats.searches++);
|
||||
JS_ASSERT(!(keyHash & COLLISION_FLAG));
|
||||
|
||||
/* Compute the primary hash address. */
|
||||
hashShift = table->hashShift;
|
||||
hash1 = HASH1(keyHash, hashShift);
|
||||
entry = ADDRESS_ENTRY(table, hash1);
|
||||
|
||||
/* Miss: return space for a new entry. */
|
||||
if (JS_DHASH_ENTRY_IS_FREE(entry)) {
|
||||
METER(table->stats.misses++);
|
||||
return entry;
|
||||
}
|
||||
|
||||
/* Collision: double hash. */
|
||||
sizeLog2 = JS_DHASH_BITS - table->hashShift;
|
||||
hash2 = HASH2(keyHash, sizeLog2, hashShift);
|
||||
sizeMask = JS_BITMASK(sizeLog2);
|
||||
|
||||
JS_ASSERT(!ENTRY_IS_REMOVED(entry));
|
||||
entry->keyHash |= COLLISION_FLAG;
|
||||
|
||||
for (;;) {
|
||||
METER(table->stats.steps++);
|
||||
hash1 -= hash2;
|
||||
hash1 &= sizeMask;
|
||||
|
||||
entry = ADDRESS_ENTRY(table, hash1);
|
||||
if (JS_DHASH_ENTRY_IS_FREE(entry)) {
|
||||
METER(table->stats.misses++);
|
||||
return entry;
|
||||
}
|
||||
|
||||
JS_ASSERT(!ENTRY_IS_REMOVED(entry));
|
||||
entry->keyHash |= COLLISION_FLAG;
|
||||
}
|
||||
|
||||
/* NOTREACHED */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
ChangeTable(JSDHashTable *table, int deltaLog2)
|
||||
{
|
||||
|
@ -469,7 +529,6 @@ ChangeTable(JSDHashTable *table, int deltaLog2)
|
|||
char *newEntryStore, *oldEntryStore, *oldEntryAddr;
|
||||
uint32 entrySize, i, nbytes;
|
||||
JSDHashEntryHdr *oldEntry, *newEntry;
|
||||
JSDHashGetKey getKey;
|
||||
JSDHashMoveEntry moveEntry;
|
||||
#ifdef DEBUG
|
||||
uint32 recursionLevel;
|
||||
|
@ -501,7 +560,6 @@ ChangeTable(JSDHashTable *table, int deltaLog2)
|
|||
memset(newEntryStore, 0, nbytes);
|
||||
oldEntryAddr = oldEntryStore = table->entryStore;
|
||||
table->entryStore = newEntryStore;
|
||||
getKey = table->ops->getKey;
|
||||
moveEntry = table->ops->moveEntry;
|
||||
#ifdef DEBUG
|
||||
RECURSION_LEVEL(table) = recursionLevel;
|
||||
|
@ -512,8 +570,7 @@ ChangeTable(JSDHashTable *table, int deltaLog2)
|
|||
oldEntry = (JSDHashEntryHdr *)oldEntryAddr;
|
||||
if (ENTRY_IS_LIVE(oldEntry)) {
|
||||
oldEntry->keyHash &= ~COLLISION_FLAG;
|
||||
newEntry = SearchTable(table, getKey(table, oldEntry),
|
||||
oldEntry->keyHash, JS_DHASH_ADD);
|
||||
newEntry = FindFreeEntry(table, oldEntry->keyHash);
|
||||
JS_ASSERT(JS_DHASH_ENTRY_IS_FREE(newEntry));
|
||||
moveEntry(table, oldEntry, newEntry);
|
||||
newEntry->keyHash = oldEntry->keyHash;
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
* Contributor(s):
|
||||
* Brendan Eich <brendan@mozilla.org> (Original Author)
|
||||
* Chris Waterson <waterson@netscape.com>
|
||||
* L. David Baron <dbaron@dbaron.org>, Mozilla Corporation
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
|
@ -467,6 +468,68 @@ SearchTable(PLDHashTable *table, const void *key, PLDHashNumber keyHash,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is a copy of SearchTable, used by ChangeTable, hardcoded to
|
||||
* 1. assume |op == PL_DHASH_ADD|,
|
||||
* 2. assume that |key| will never match an existing entry, and
|
||||
* 3. assume that no entries have been removed from the current table
|
||||
* structure.
|
||||
* Avoiding the need for |key| means we can avoid needing a way to map
|
||||
* entries to keys, which means callers can use complex key types more
|
||||
* easily.
|
||||
*/
|
||||
static PLDHashEntryHdr * PL_DHASH_FASTCALL
|
||||
FindFreeEntry(PLDHashTable *table, PLDHashNumber keyHash)
|
||||
{
|
||||
PLDHashNumber hash1, hash2;
|
||||
int hashShift, sizeLog2;
|
||||
PLDHashEntryHdr *entry;
|
||||
PRUint32 sizeMask;
|
||||
|
||||
METER(table->stats.searches++);
|
||||
NS_ASSERTION(!(keyHash & COLLISION_FLAG),
|
||||
"!(keyHash & COLLISION_FLAG)");
|
||||
|
||||
/* Compute the primary hash address. */
|
||||
hashShift = table->hashShift;
|
||||
hash1 = HASH1(keyHash, hashShift);
|
||||
entry = ADDRESS_ENTRY(table, hash1);
|
||||
|
||||
/* Miss: return space for a new entry. */
|
||||
if (PL_DHASH_ENTRY_IS_FREE(entry)) {
|
||||
METER(table->stats.misses++);
|
||||
return entry;
|
||||
}
|
||||
|
||||
/* Collision: double hash. */
|
||||
sizeLog2 = PL_DHASH_BITS - table->hashShift;
|
||||
hash2 = HASH2(keyHash, sizeLog2, hashShift);
|
||||
sizeMask = PR_BITMASK(sizeLog2);
|
||||
|
||||
NS_ASSERTION(!ENTRY_IS_REMOVED(entry),
|
||||
"!ENTRY_IS_REMOVED(entry)");
|
||||
entry->keyHash |= COLLISION_FLAG;
|
||||
|
||||
for (;;) {
|
||||
METER(table->stats.steps++);
|
||||
hash1 -= hash2;
|
||||
hash1 &= sizeMask;
|
||||
|
||||
entry = ADDRESS_ENTRY(table, hash1);
|
||||
if (PL_DHASH_ENTRY_IS_FREE(entry)) {
|
||||
METER(table->stats.misses++);
|
||||
return entry;
|
||||
}
|
||||
|
||||
NS_ASSERTION(!ENTRY_IS_REMOVED(entry),
|
||||
"!ENTRY_IS_REMOVED(entry)");
|
||||
entry->keyHash |= COLLISION_FLAG;
|
||||
}
|
||||
|
||||
/* NOTREACHED */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static PRBool
|
||||
ChangeTable(PLDHashTable *table, int deltaLog2)
|
||||
{
|
||||
|
@ -475,7 +538,6 @@ ChangeTable(PLDHashTable *table, int deltaLog2)
|
|||
char *newEntryStore, *oldEntryStore, *oldEntryAddr;
|
||||
PRUint32 entrySize, i, nbytes;
|
||||
PLDHashEntryHdr *oldEntry, *newEntry;
|
||||
PLDHashGetKey getKey;
|
||||
PLDHashMoveEntry moveEntry;
|
||||
#ifdef DEBUG
|
||||
PRUint32 recursionLevel;
|
||||
|
@ -507,7 +569,6 @@ ChangeTable(PLDHashTable *table, int deltaLog2)
|
|||
memset(newEntryStore, 0, nbytes);
|
||||
oldEntryAddr = oldEntryStore = table->entryStore;
|
||||
table->entryStore = newEntryStore;
|
||||
getKey = table->ops->getKey;
|
||||
moveEntry = table->ops->moveEntry;
|
||||
#ifdef DEBUG
|
||||
RECURSION_LEVEL(table) = recursionLevel;
|
||||
|
@ -518,8 +579,7 @@ ChangeTable(PLDHashTable *table, int deltaLog2)
|
|||
oldEntry = (PLDHashEntryHdr *)oldEntryAddr;
|
||||
if (ENTRY_IS_LIVE(oldEntry)) {
|
||||
oldEntry->keyHash &= ~COLLISION_FLAG;
|
||||
newEntry = SearchTable(table, getKey(table, oldEntry),
|
||||
oldEntry->keyHash, PL_DHASH_ADD);
|
||||
newEntry = FindFreeEntry(table, oldEntry->keyHash);
|
||||
NS_ASSERTION(PL_DHASH_ENTRY_IS_FREE(newEntry),
|
||||
"PL_DHASH_ENTRY_IS_FREE(newEntry)");
|
||||
moveEntry(table, oldEntry, newEntry);
|
||||
|
|
Загрузка…
Ссылка в новой задаче