summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore/runtime/PropertyMapHashTable.h
diff options
context:
space:
mode:
Diffstat (limited to 'Source/JavaScriptCore/runtime/PropertyMapHashTable.h')
-rw-r--r--Source/JavaScriptCore/runtime/PropertyMapHashTable.h154
1 files changed, 79 insertions, 75 deletions
diff --git a/Source/JavaScriptCore/runtime/PropertyMapHashTable.h b/Source/JavaScriptCore/runtime/PropertyMapHashTable.h
index 9ddb6997c..b068b991d 100644
--- a/Source/JavaScriptCore/runtime/PropertyMapHashTable.h
+++ b/Source/JavaScriptCore/runtime/PropertyMapHashTable.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2014 Apple Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -21,34 +21,40 @@
#ifndef PropertyMapHashTable_h
#define PropertyMapHashTable_h
+#include "JSExportMacros.h"
#include "PropertyOffset.h"
#include "Structure.h"
#include "WriteBarrier.h"
+#include <wtf/CryptographicallyRandomNumber.h>
#include <wtf/HashTable.h>
#include <wtf/MathExtras.h>
-#include <wtf/PassOwnPtr.h>
#include <wtf/Vector.h>
-#include <wtf/text/StringImpl.h>
+#include <wtf/text/AtomicStringImpl.h>
-#ifndef NDEBUG
-#define DUMP_PROPERTYMAP_STATS 0
-#else
#define DUMP_PROPERTYMAP_STATS 0
-#endif
+#define DUMP_PROPERTYMAP_COLLISIONS 0
-#if DUMP_PROPERTYMAP_STATS
+#define PROPERTY_MAP_DELETED_ENTRY_KEY ((UniquedStringImpl*)1)
-extern int numProbes;
-extern int numCollisions;
-extern int numRehashes;
-extern int numRemoves;
+namespace JSC {
-#endif
+#if DUMP_PROPERTYMAP_STATS
-#define PROPERTY_MAP_DELETED_ENTRY_KEY ((StringImpl*)1)
+struct PropertyMapHashTableStats {
+ std::atomic<unsigned> numFinds;
+ std::atomic<unsigned> numCollisions;
+ std::atomic<unsigned> numLookups;
+ std::atomic<unsigned> numLookupProbing;
+ std::atomic<unsigned> numAdds;
+ std::atomic<unsigned> numRemoves;
+ std::atomic<unsigned> numRehashes;
+ std::atomic<unsigned> numReinserts;
+};
-namespace JSC {
+JS_EXPORTDATA extern PropertyMapHashTableStats* propertyMapHashTableStats;
+
+#endif
inline bool isPowerOf2(unsigned v)
{
@@ -71,22 +77,7 @@ inline unsigned nextPowerOf2(unsigned v)
return v;
}
-struct PropertyMapEntry {
- StringImpl* key;
- PropertyOffset offset;
- unsigned attributes;
- WriteBarrier<JSCell> specificValue;
-
- PropertyMapEntry(VM& vm, JSCell* owner, StringImpl* key, PropertyOffset offset, unsigned attributes, JSCell* specificValue)
- : key(key)
- , offset(offset)
- , attributes(attributes)
- , specificValue(vm, owner, specificValue, WriteBarrier<JSCell>::MayBeNull)
- {
- }
-};
-
-class PropertyTable : public JSCell {
+class PropertyTable final : public JSCell {
// This is the implementation for 'iterator' and 'const_iterator',
// used for iterating over the table in insertion order.
@@ -129,20 +120,20 @@ class PropertyTable : public JSCell {
};
public:
+ typedef JSCell Base;
+ static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;
+
static const bool needsDestruction = true;
- static const bool hasImmortalStructure = true;
static void destroy(JSCell*);
- static JS_EXPORTDATA const ClassInfo s_info;
+ DECLARE_EXPORT_INFO;
static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
{
- return Structure::create(vm, globalObject, prototype, TypeInfo(CompoundType, OverridesVisitChildren), &s_info);
+ return Structure::create(vm, globalObject, prototype, TypeInfo(CellType, StructureFlags), info());
}
- static void visitChildren(JSCell*, SlotVisitor&);
-
- typedef StringImpl* KeyType;
+ typedef UniquedStringImpl* KeyType;
typedef PropertyMapEntry ValueType;
// The in order iterator provides overloaded * and -> to access the Value at the current position.
@@ -156,8 +147,8 @@ public:
// Constructor is passed an initial capacity, a PropertyTable to copy, or both.
static PropertyTable* create(VM&, unsigned initialCapacity);
- static PropertyTable* clone(VM&, JSCell* owner, const PropertyTable&);
- static PropertyTable* clone(VM&, JSCell* owner, unsigned initialCapacity, const PropertyTable&);
+ static PropertyTable* clone(VM&, const PropertyTable&);
+ static PropertyTable* clone(VM&, unsigned initialCapacity, const PropertyTable&);
~PropertyTable();
// Ordered iteration methods.
@@ -168,7 +159,7 @@ public:
// Find a value in the table.
find_iterator find(const KeyType&);
- find_iterator findWithString(const KeyType&);
+ ValueType* get(const KeyType&);
// Add a value to the table
enum EffectOnPropertyOffset { PropertyOffsetMayChange, PropertyOffsetMustNotChange };
std::pair<find_iterator, bool> add(const ValueType& entry, PropertyOffset&, EffectOnPropertyOffset);
@@ -194,7 +185,7 @@ public:
PropertyOffset nextOffset(PropertyOffset inlineCapacity);
// Copy this PropertyTable, ensuring the copy has at least the capacity provided.
- PropertyTable* copy(VM&, JSCell* owner, unsigned newCapacity);
+ PropertyTable* copy(VM&, unsigned newCapacity);
#ifndef NDEBUG
size_t sizeInMemory();
@@ -203,8 +194,8 @@ public:
private:
PropertyTable(VM&, unsigned initialCapacity);
- PropertyTable(VM&, JSCell*, const PropertyTable&);
- PropertyTable(VM&, JSCell*, unsigned initialCapacity, const PropertyTable&);
+ PropertyTable(VM&, const PropertyTable&);
+ PropertyTable(VM&, unsigned initialCapacity, const PropertyTable&);
PropertyTable(const PropertyTable&);
// Used to insert a value known not to be in the table, and where we know capacity to be available.
@@ -250,9 +241,9 @@ private:
unsigned* m_index;
unsigned m_keyCount;
unsigned m_deletedCount;
- OwnPtr< Vector<PropertyOffset> > m_deletedOffsets;
+ std::unique_ptr<Vector<PropertyOffset>> m_deletedOffsets;
- static const unsigned MinimumTableSize = 8;
+ static const unsigned MinimumTableSize = 16;
static const unsigned EmptyEntryIndex = 0;
};
@@ -279,12 +270,12 @@ inline PropertyTable::const_iterator PropertyTable::end() const
inline PropertyTable::find_iterator PropertyTable::find(const KeyType& key)
{
ASSERT(key);
- ASSERT(key->isIdentifier() || key->isEmptyUnique());
- unsigned hash = key->existingHash();
+ ASSERT(key->isAtomic() || key->isSymbol());
+ unsigned hash = IdentifierRepHash::hash(key);
unsigned step = 0;
#if DUMP_PROPERTYMAP_STATS
- ++numProbes;
+ ++propertyMapHashTableStats->numFinds;
#endif
while (true) {
@@ -294,50 +285,51 @@ inline PropertyTable::find_iterator PropertyTable::find(const KeyType& key)
if (key == table()[entryIndex - 1].key)
return std::make_pair(&table()[entryIndex - 1], hash & m_indexMask);
-#if DUMP_PROPERTYMAP_STATS
- ++numCollisions;
-#endif
-
if (!step)
- step = WTF::doubleHash(key->existingHash()) | 1;
- hash += step;
+ step = WTF::doubleHash(IdentifierRepHash::hash(key)) | 1;
#if DUMP_PROPERTYMAP_STATS
- ++numRehashes;
+ ++propertyMapHashTableStats->numCollisions;
#endif
+
+#if DUMP_PROPERTYMAP_COLLISIONS
+ dataLog("PropertyTable collision for ", key, " (", hash, ") with step ", step, "\n");
+ dataLog("Collided with ", table()[entryIndex - 1].key, "(", IdentifierRepHash::hash(table()[entryIndex - 1].key), ")\n");
+#endif
+
+ hash += step;
}
}
-inline PropertyTable::find_iterator PropertyTable::findWithString(const KeyType& key)
+inline PropertyTable::ValueType* PropertyTable::get(const KeyType& key)
{
ASSERT(key);
- ASSERT(!key->isIdentifier() && !key->hasHash());
- unsigned hash = key->hash();
+ ASSERT(key->isAtomic() || key->isSymbol());
+
+ if (!m_keyCount)
+ return nullptr;
+
+ unsigned hash = IdentifierRepHash::hash(key);
unsigned step = 0;
#if DUMP_PROPERTYMAP_STATS
- ++numProbes;
+ ++propertyMapHashTableStats->numLookups;
#endif
while (true) {
unsigned entryIndex = m_index[hash & m_indexMask];
if (entryIndex == EmptyEntryIndex)
- return std::make_pair((ValueType*)0, hash & m_indexMask);
- const KeyType& keyInMap = table()[entryIndex - 1].key;
- if (equal(key, keyInMap) && keyInMap->isIdentifier())
- return std::make_pair(&table()[entryIndex - 1], hash & m_indexMask);
+ return nullptr;
+ if (key == table()[entryIndex - 1].key)
+ return &table()[entryIndex - 1];
#if DUMP_PROPERTYMAP_STATS
- ++numCollisions;
+ ++propertyMapHashTableStats->numLookupProbing;
#endif
if (!step)
- step = WTF::doubleHash(key->existingHash()) | 1;
+ step = WTF::doubleHash(IdentifierRepHash::hash(key)) | 1;
hash += step;
-
-#if DUMP_PROPERTYMAP_STATS
- ++numRehashes;
-#endif
}
}
@@ -350,6 +342,10 @@ inline std::pair<PropertyTable::find_iterator, bool> PropertyTable::add(const Va
return std::make_pair(iter, false);
}
+#if DUMP_PROPERTYMAP_STATS
+ ++propertyMapHashTableStats->numAdds;
+#endif
+
// Ref the key
entry.key->ref();
@@ -383,7 +379,7 @@ inline void PropertyTable::remove(const find_iterator& iter)
return;
#if DUMP_PROPERTYMAP_STATS
- ++numRemoves;
+ ++propertyMapHashTableStats->numRemoves;
#endif
// Replace this one element with the deleted sentinel. Also clear out
@@ -423,7 +419,7 @@ inline unsigned PropertyTable::propertyStorageSize() const
inline void PropertyTable::clearDeletedOffsets()
{
- m_deletedOffsets.clear();
+ m_deletedOffsets = nullptr;
}
inline bool PropertyTable::hasDeletedOffset()
@@ -441,7 +437,7 @@ inline PropertyOffset PropertyTable::getDeletedOffset()
inline void PropertyTable::addDeletedOffset(PropertyOffset offset)
{
if (!m_deletedOffsets)
- m_deletedOffsets = adoptPtr(new Vector<PropertyOffset>);
+ m_deletedOffsets = std::make_unique<Vector<PropertyOffset>>();
m_deletedOffsets->append(offset);
}
@@ -453,15 +449,15 @@ inline PropertyOffset PropertyTable::nextOffset(PropertyOffset inlineCapacity)
return offsetForPropertyNumber(size(), inlineCapacity);
}
-inline PropertyTable* PropertyTable::copy(VM& vm, JSCell* owner, unsigned newCapacity)
+inline PropertyTable* PropertyTable::copy(VM& vm, unsigned newCapacity)
{
ASSERT(newCapacity >= m_keyCount);
// Fast case; if the new table will be the same m_indexSize as this one, we can memcpy it,
// save rehashing all keys.
if (sizeForCapacity(newCapacity) == m_indexSize)
- return PropertyTable::clone(vm, owner, *this);
- return PropertyTable::clone(vm, owner, newCapacity, *this);
+ return PropertyTable::clone(vm, *this);
+ return PropertyTable::clone(vm, newCapacity, *this);
}
#ifndef NDEBUG
@@ -476,6 +472,10 @@ inline size_t PropertyTable::sizeInMemory()
inline void PropertyTable::reinsert(const ValueType& entry)
{
+#if DUMP_PROPERTYMAP_STATS
+ ++propertyMapHashTableStats->numReinserts;
+#endif
+
// Used to insert a value known not to be in the table, and where
// we know capacity to be available.
ASSERT(canInsert());
@@ -491,6 +491,10 @@ inline void PropertyTable::reinsert(const ValueType& entry)
inline void PropertyTable::rehash(unsigned newCapacity)
{
+#if DUMP_PROPERTYMAP_STATS
+ ++propertyMapHashTableStats->numRehashes;
+#endif
+
unsigned* oldEntryIndices = m_index;
iterator iter = this->begin();
iterator end = this->end();