summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/webkit/JavaScriptCore/runtime/Structure.cpp
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@nokia.com>2009-06-15 09:06:43 (GMT)
committerSimon Hausmann <simon.hausmann@nokia.com>2009-06-15 09:31:31 (GMT)
commitc411f16870f112c3407c28c22b617f613a82cff4 (patch)
tree29a1bcd590c8b31af2aab445bfe8a978dc5bf582 /src/3rdparty/webkit/JavaScriptCore/runtime/Structure.cpp
parent3d77b56b32a0c53ec0bbfaa07236fedb900ff336 (diff)
downloadQt-c411f16870f112c3407c28c22b617f613a82cff4.zip
Qt-c411f16870f112c3407c28c22b617f613a82cff4.tar.gz
Qt-c411f16870f112c3407c28c22b617f613a82cff4.tar.bz2
Updated WebKit from /home/shausman/src/webkit/trunk to qtwebkit-4.6-snapshot-15062009 ( 65232bf00dc494ebfd978f998c88f58d18ecce1e )
Diffstat (limited to 'src/3rdparty/webkit/JavaScriptCore/runtime/Structure.cpp')
-rw-r--r--src/3rdparty/webkit/JavaScriptCore/runtime/Structure.cpp263
1 files changed, 182 insertions, 81 deletions
diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/Structure.cpp b/src/3rdparty/webkit/JavaScriptCore/runtime/Structure.cpp
index 5fcde7b..3597a5c 100644
--- a/src/3rdparty/webkit/JavaScriptCore/runtime/Structure.cpp
+++ b/src/3rdparty/webkit/JavaScriptCore/runtime/Structure.cpp
@@ -65,15 +65,15 @@ static const unsigned newTableSize = 16;
static WTF::RefCountedLeakCounter structureCounter("Structure");
#if ENABLE(JSC_MULTIPLE_THREADS)
-static Mutex ignoreSetMutex;
+static Mutex& ignoreSetMutex = *(new Mutex);
#endif
static bool shouldIgnoreLeaks;
-static HashSet<Structure*> ignoreSet;
+static HashSet<Structure*>& ignoreSet = *(new HashSet<Structure*>);
#endif
#if DUMP_STRUCTURE_ID_STATISTICS
-static HashSet<Structure*> liveStructureSet;
+static HashSet<Structure*>& liveStructureSet = *(new HashSet<Structure*>);
#endif
void Structure::dumpStatistics()
@@ -120,12 +120,10 @@ void Structure::dumpStatistics()
#endif
}
-Structure::Structure(JSValuePtr prototype, const TypeInfo& typeInfo)
+Structure::Structure(JSValue prototype, const TypeInfo& typeInfo)
: m_typeInfo(typeInfo)
, m_prototype(prototype)
- , m_cachedPrototypeChain(0)
- , m_previous(0)
- , m_nameInPrevious(0)
+ , m_specificValueInPrevious(0)
, m_propertyTable(0)
, m_propertyStorageCapacity(JSObject::inlineStorageCapacity)
, m_offset(noOffset)
@@ -136,7 +134,7 @@ Structure::Structure(JSValuePtr prototype, const TypeInfo& typeInfo)
, m_attributesInPrevious(0)
{
ASSERT(m_prototype);
- ASSERT(m_prototype->isObject() || m_prototype->isNull());
+ ASSERT(m_prototype.isObject() || m_prototype.isNull());
m_transitions.singleTransition = 0;
@@ -161,8 +159,8 @@ Structure::~Structure()
if (m_previous->m_usingSingleTransitionSlot) {
m_previous->m_transitions.singleTransition = 0;
} else {
- ASSERT(m_previous->m_transitions.table->contains(make_pair(m_nameInPrevious.get(), m_attributesInPrevious)));
- m_previous->m_transitions.table->remove(make_pair(m_nameInPrevious.get(), m_attributesInPrevious));
+ ASSERT(m_previous->m_transitions.table->contains(make_pair(m_nameInPrevious.get(), make_pair(m_attributesInPrevious, m_specificValueInPrevious))));
+ m_previous->m_transitions.table->remove(make_pair(m_nameInPrevious.get(), make_pair(m_attributesInPrevious, m_specificValueInPrevious)));
}
}
@@ -178,6 +176,8 @@ Structure::~Structure()
if (UString::Rep* key = m_propertyTable->entries()[i].key)
key->deref();
}
+
+ delete m_propertyTable->deletedOffsets;
fastFree(m_propertyTable);
}
@@ -280,59 +280,34 @@ void Structure::materializePropertyMap()
for (ptrdiff_t i = structures.size() - 2; i >= 0; --i) {
structure = structures[i];
structure->m_nameInPrevious->ref();
- PropertyMapEntry entry(structure->m_nameInPrevious.get(), structure->m_offset, structure->m_attributesInPrevious, ++m_propertyTable->lastIndexUsed);
+ PropertyMapEntry entry(structure->m_nameInPrevious.get(), structure->m_offset, structure->m_attributesInPrevious, structure->m_specificValueInPrevious, ++m_propertyTable->lastIndexUsed);
insertIntoPropertyMapHashTable(entry);
}
}
void Structure::getEnumerablePropertyNames(ExecState* exec, PropertyNameArray& propertyNames, JSObject* baseObject)
{
- bool shouldCache = propertyNames.cacheable() && !(propertyNames.size() || m_isDictionary);
+ bool shouldCache = propertyNames.shouldCache() && !(propertyNames.size() || m_isDictionary);
- if (shouldCache) {
- if (m_cachedPropertyNameArrayData) {
- if (structureChainsAreEqual(m_cachedPropertyNameArrayData->cachedPrototypeChain(), cachedPrototypeChain())) {
- propertyNames.setData(m_cachedPropertyNameArrayData);
- return;
- }
+ if (shouldCache && m_cachedPropertyNameArrayData) {
+ if (m_cachedPropertyNameArrayData->cachedPrototypeChain() == prototypeChain(exec)) {
+ propertyNames.setData(m_cachedPropertyNameArrayData);
+ return;
}
- propertyNames.setCacheable(false);
+ clearEnumerationCache();
}
- getEnumerablePropertyNamesInternal(propertyNames);
+ getEnumerableNamesFromPropertyTable(propertyNames);
+ getEnumerableNamesFromClassInfoTable(exec, baseObject->classInfo(), propertyNames);
- // Add properties from the static hashtables of properties
- for (const ClassInfo* info = baseObject->classInfo(); info; info = info->parentClass) {
- const HashTable* table = info->propHashTable(exec);
- if (!table)
- continue;
- table->initializeIfNeeded(exec);
- ASSERT(table->table);
-#if ENABLE(PERFECT_HASH_SIZE)
- int hashSizeMask = table->hashSizeMask;
-#else
- int hashSizeMask = table->compactSize - 1;
-#endif
- const HashEntry* entry = table->table;
- for (int i = 0; i <= hashSizeMask; ++i, ++entry) {
- if (entry->key() && !(entry->attributes() & DontEnum))
- propertyNames.add(entry->key());
- }
- }
-
- if (m_prototype->isObject())
+ if (m_prototype.isObject()) {
+ propertyNames.setShouldCache(false); // No need for our prototypes to waste memory on caching, since they're not being enumerated directly.
asObject(m_prototype)->getPropertyNames(exec, propertyNames);
+ }
if (shouldCache) {
- if (m_cachedPropertyNameArrayData)
- m_cachedPropertyNameArrayData->setCachedStructure(0);
-
m_cachedPropertyNameArrayData = propertyNames.data();
-
- StructureChain* chain = cachedPrototypeChain();
- if (!chain)
- chain = createCachedPrototypeChain();
- m_cachedPropertyNameArrayData->setCachedPrototypeChain(chain);
+ m_cachedPropertyNameArrayData->setCachedPrototypeChain(prototypeChain(exec));
m_cachedPropertyNameArrayData->setCachedStructure(this);
}
}
@@ -352,20 +327,69 @@ void Structure::growPropertyStorageCapacity()
m_propertyStorageCapacity *= 2;
}
-PassRefPtr<Structure> Structure::addPropertyTransitionToExistingStructure(Structure* structure, const Identifier& propertyName, unsigned attributes, size_t& offset)
+void Structure::despecifyDictionaryFunction(const Identifier& propertyName)
+{
+ const UString::Rep* rep = propertyName._ustring.rep();
+
+ materializePropertyMapIfNecessary();
+
+ ASSERT(m_isDictionary);
+ ASSERT(m_propertyTable);
+
+ unsigned i = rep->computedHash();
+
+#if DUMP_PROPERTYMAP_STATS
+ ++numProbes;
+#endif
+
+ unsigned entryIndex = m_propertyTable->entryIndices[i & m_propertyTable->sizeMask];
+ ASSERT(entryIndex != emptyEntryIndex);
+
+ if (rep == m_propertyTable->entries()[entryIndex - 1].key) {
+ m_propertyTable->entries()[entryIndex - 1].specificValue = 0;
+ return;
+ }
+
+#if DUMP_PROPERTYMAP_STATS
+ ++numCollisions;
+#endif
+
+ unsigned k = 1 | doubleHash(rep->computedHash());
+
+ while (1) {
+ i += k;
+
+#if DUMP_PROPERTYMAP_STATS
+ ++numRehashes;
+#endif
+
+ entryIndex = m_propertyTable->entryIndices[i & m_propertyTable->sizeMask];
+ ASSERT(entryIndex != emptyEntryIndex);
+
+ if (rep == m_propertyTable->entries()[entryIndex - 1].key) {
+ m_propertyTable->entries()[entryIndex - 1].specificValue = 0;
+ return;
+ }
+ }
+}
+
+PassRefPtr<Structure> Structure::addPropertyTransitionToExistingStructure(Structure* structure, const Identifier& propertyName, unsigned attributes, JSCell* specificValue, size_t& offset)
{
ASSERT(!structure->m_isDictionary);
ASSERT(structure->typeInfo().type() == ObjectType);
if (structure->m_usingSingleTransitionSlot) {
Structure* existingTransition = structure->m_transitions.singleTransition;
- if (existingTransition && existingTransition->m_nameInPrevious.get() == propertyName.ustring().rep() && existingTransition->m_attributesInPrevious == attributes) {
+ if (existingTransition && existingTransition->m_nameInPrevious.get() == propertyName.ustring().rep()
+ && existingTransition->m_attributesInPrevious == attributes
+ && existingTransition->m_specificValueInPrevious == specificValue) {
+
ASSERT(structure->m_transitions.singleTransition->m_offset != noOffset);
offset = structure->m_transitions.singleTransition->m_offset;
return existingTransition;
}
} else {
- if (Structure* existingTransition = structure->m_transitions.table->get(make_pair(propertyName.ustring().rep(), attributes))) {
+ if (Structure* existingTransition = structure->m_transitions.table->get(make_pair(propertyName.ustring().rep(), make_pair(attributes, specificValue)))) {
ASSERT(existingTransition->m_offset != noOffset);
offset = existingTransition->m_offset;
return existingTransition;
@@ -375,25 +399,27 @@ PassRefPtr<Structure> Structure::addPropertyTransitionToExistingStructure(Struct
return 0;
}
-PassRefPtr<Structure> Structure::addPropertyTransition(Structure* structure, const Identifier& propertyName, unsigned attributes, size_t& offset)
+PassRefPtr<Structure> Structure::addPropertyTransition(Structure* structure, const Identifier& propertyName, unsigned attributes, JSCell* specificValue, size_t& offset)
{
ASSERT(!structure->m_isDictionary);
ASSERT(structure->typeInfo().type() == ObjectType);
- ASSERT(!Structure::addPropertyTransitionToExistingStructure(structure, propertyName, attributes, offset));
+ ASSERT(!Structure::addPropertyTransitionToExistingStructure(structure, propertyName, attributes, specificValue, offset));
if (structure->transitionCount() > s_maxTransitionLength) {
RefPtr<Structure> transition = toDictionaryTransition(structure);
- offset = transition->put(propertyName, attributes);
+ offset = transition->put(propertyName, attributes, specificValue);
if (transition->propertyStorageSize() > transition->propertyStorageCapacity())
transition->growPropertyStorageCapacity();
return transition.release();
}
RefPtr<Structure> transition = create(structure->m_prototype, structure->typeInfo());
+
transition->m_cachedPrototypeChain = structure->m_cachedPrototypeChain;
transition->m_previous = structure;
transition->m_nameInPrevious = propertyName.ustring().rep();
transition->m_attributesInPrevious = attributes;
+ transition->m_specificValueInPrevious = specificValue;
transition->m_propertyStorageCapacity = structure->m_propertyStorageCapacity;
transition->m_hasGetterSetterProperties = structure->m_hasGetterSetterProperties;
@@ -411,7 +437,7 @@ PassRefPtr<Structure> Structure::addPropertyTransition(Structure* structure, con
transition->createPropertyMapHashTable();
}
- offset = transition->put(propertyName, attributes);
+ offset = transition->put(propertyName, attributes, specificValue);
if (transition->propertyStorageSize() > transition->propertyStorageCapacity())
transition->growPropertyStorageCapacity();
@@ -427,9 +453,9 @@ PassRefPtr<Structure> Structure::addPropertyTransition(Structure* structure, con
structure->m_usingSingleTransitionSlot = false;
StructureTransitionTable* transitionTable = new StructureTransitionTable;
structure->m_transitions.table = transitionTable;
- transitionTable->add(make_pair(existingTransition->m_nameInPrevious.get(), existingTransition->m_attributesInPrevious), existingTransition);
+ transitionTable->add(make_pair(existingTransition->m_nameInPrevious.get(), make_pair(existingTransition->m_attributesInPrevious, existingTransition->m_specificValueInPrevious)), existingTransition);
}
- structure->m_transitions.table->add(make_pair(propertyName.ustring().rep(), attributes), transition.get());
+ structure->m_transitions.table->add(make_pair(propertyName.ustring().rep(), make_pair(attributes, specificValue)), transition.get());
return transition.release();
}
@@ -444,7 +470,7 @@ PassRefPtr<Structure> Structure::removePropertyTransition(Structure* structure,
return transition.release();
}
-PassRefPtr<Structure> Structure::changePrototypeTransition(Structure* structure, JSValuePtr prototype)
+PassRefPtr<Structure> Structure::changePrototypeTransition(Structure* structure, JSValue prototype)
{
RefPtr<Structure> transition = create(prototype, structure->typeInfo());
@@ -460,6 +486,25 @@ PassRefPtr<Structure> Structure::changePrototypeTransition(Structure* structure,
return transition.release();
}
+PassRefPtr<Structure> Structure::despecifyFunctionTransition(Structure* structure, const Identifier& replaceFunction)
+{
+ RefPtr<Structure> transition = create(structure->storedPrototype(), structure->typeInfo());
+
+ transition->m_propertyStorageCapacity = structure->m_propertyStorageCapacity;
+ transition->m_hasGetterSetterProperties = structure->m_hasGetterSetterProperties;
+
+ // Don't set m_offset, as one can not transition to this.
+
+ structure->materializePropertyMapIfNecessary();
+ transition->m_propertyTable = structure->copyPropertyTable();
+ transition->m_isPinnedPropertyTable = true;
+
+ bool removed = transition->despecifyFunction(replaceFunction);
+ ASSERT_UNUSED(removed, removed);
+
+ return transition.release();
+}
+
PassRefPtr<Structure> Structure::getterSetterTransition(Structure* structure)
{
RefPtr<Structure> transition = create(structure->storedPrototype(), structure->typeInfo());
@@ -507,14 +552,14 @@ PassRefPtr<Structure> Structure::fromDictionaryTransition(Structure* structure)
return structure;
}
-size_t Structure::addPropertyWithoutTransition(const Identifier& propertyName, unsigned attributes)
+size_t Structure::addPropertyWithoutTransition(const Identifier& propertyName, unsigned attributes, JSCell* specificValue)
{
ASSERT(!m_transitions.singleTransition);
materializePropertyMapIfNecessary();
m_isPinnedPropertyTable = true;
- size_t offset = put(propertyName, attributes);
+ size_t offset = put(propertyName, attributes, specificValue);
if (propertyStorageSize() > propertyStorageCapacity())
growPropertyStorageCapacity();
clearEnumerationCache();
@@ -534,20 +579,6 @@ size_t Structure::removePropertyWithoutTransition(const Identifier& propertyName
return offset;
}
-StructureChain* Structure::createCachedPrototypeChain()
-{
- ASSERT(typeInfo().type() == ObjectType);
- ASSERT(!m_cachedPrototypeChain);
-
- JSValuePtr prototype = storedPrototype();
- if (JSImmediate::isImmediate(prototype))
- return 0;
-
- RefPtr<StructureChain> chain = StructureChain::create(asObject(prototype)->structure());
- setCachedPrototypeChain(chain.release());
- return cachedPrototypeChain();
-}
-
#if DUMP_PROPERTYMAP_STATS
static int numProbes;
@@ -604,16 +635,12 @@ PropertyMapHashTable* Structure::copyPropertyTable()
return newTable;
}
-size_t Structure::get(const Identifier& propertyName, unsigned& attributes)
+size_t Structure::get(const UString::Rep* rep, unsigned& attributes, JSCell*& specificValue)
{
- ASSERT(!propertyName.isNull());
-
materializePropertyMapIfNecessary();
if (!m_propertyTable)
return notFound;
- UString::Rep* rep = propertyName._ustring.rep();
-
unsigned i = rep->computedHash();
#if DUMP_PROPERTYMAP_STATS
@@ -626,6 +653,7 @@ size_t Structure::get(const Identifier& propertyName, unsigned& attributes)
if (rep == m_propertyTable->entries()[entryIndex - 1].key) {
attributes = m_propertyTable->entries()[entryIndex - 1].attributes;
+ specificValue = m_propertyTable->entries()[entryIndex - 1].specificValue;
return m_propertyTable->entries()[entryIndex - 1].offset;
}
@@ -648,12 +676,64 @@ size_t Structure::get(const Identifier& propertyName, unsigned& attributes)
if (rep == m_propertyTable->entries()[entryIndex - 1].key) {
attributes = m_propertyTable->entries()[entryIndex - 1].attributes;
+ specificValue = m_propertyTable->entries()[entryIndex - 1].specificValue;
return m_propertyTable->entries()[entryIndex - 1].offset;
}
}
}
-size_t Structure::put(const Identifier& propertyName, unsigned attributes)
+bool Structure::despecifyFunction(const Identifier& propertyName)
+{
+ ASSERT(!propertyName.isNull());
+
+ materializePropertyMapIfNecessary();
+ if (!m_propertyTable)
+ return false;
+
+ UString::Rep* rep = propertyName._ustring.rep();
+
+ unsigned i = rep->computedHash();
+
+#if DUMP_PROPERTYMAP_STATS
+ ++numProbes;
+#endif
+
+ unsigned entryIndex = m_propertyTable->entryIndices[i & m_propertyTable->sizeMask];
+ if (entryIndex == emptyEntryIndex)
+ return false;
+
+ if (rep == m_propertyTable->entries()[entryIndex - 1].key) {
+ ASSERT(m_propertyTable->entries()[entryIndex - 1].specificValue);
+ m_propertyTable->entries()[entryIndex - 1].specificValue = 0;
+ return true;
+ }
+
+#if DUMP_PROPERTYMAP_STATS
+ ++numCollisions;
+#endif
+
+ unsigned k = 1 | doubleHash(rep->computedHash());
+
+ while (1) {
+ i += k;
+
+#if DUMP_PROPERTYMAP_STATS
+ ++numRehashes;
+#endif
+
+ entryIndex = m_propertyTable->entryIndices[i & m_propertyTable->sizeMask];
+ if (entryIndex == emptyEntryIndex)
+ return false;
+
+ if (rep == m_propertyTable->entries()[entryIndex - 1].key) {
+ ASSERT(m_propertyTable->entries()[entryIndex - 1].specificValue);
+ m_propertyTable->entries()[entryIndex - 1].specificValue = 0;
+ return true;
+ }
+ }
+}
+
+size_t Structure::put(const Identifier& propertyName, unsigned attributes, JSCell* specificValue)
{
ASSERT(!propertyName.isNull());
ASSERT(get(propertyName) == notFound);
@@ -723,6 +803,7 @@ size_t Structure::put(const Identifier& propertyName, unsigned attributes)
rep->ref();
m_propertyTable->entries()[entryIndex - 1].key = rep;
m_propertyTable->entries()[entryIndex - 1].attributes = attributes;
+ m_propertyTable->entries()[entryIndex - 1].specificValue = specificValue;
m_propertyTable->entries()[entryIndex - 1].index = ++m_propertyTable->lastIndexUsed;
unsigned newOffset;
@@ -795,6 +876,7 @@ size_t Structure::remove(const Identifier& propertyName)
key->deref();
m_propertyTable->entries()[entryIndex - 1].key = 0;
m_propertyTable->entries()[entryIndex - 1].attributes = 0;
+ m_propertyTable->entries()[entryIndex - 1].specificValue = 0;
m_propertyTable->entries()[entryIndex - 1].offset = 0;
if (!m_propertyTable->deletedOffsets)
@@ -922,7 +1004,7 @@ static int comparePropertyMapEntryIndices(const void* a, const void* b)
return 0;
}
-void Structure::getEnumerablePropertyNamesInternal(PropertyNameArray& propertyNames)
+void Structure::getEnumerableNamesFromPropertyTable(PropertyNameArray& propertyNames)
{
materializePropertyMapIfNecessary();
if (!m_propertyTable)
@@ -979,6 +1061,25 @@ void Structure::getEnumerablePropertyNamesInternal(PropertyNameArray& propertyNa
}
}
+void Structure::getEnumerableNamesFromClassInfoTable(ExecState* exec, const ClassInfo* classInfo, PropertyNameArray& propertyNames)
+{
+ // Add properties from the static hashtables of properties
+ for (; classInfo; classInfo = classInfo->parentClass) {
+ const HashTable* table = classInfo->propHashTable(exec);
+ if (!table)
+ continue;
+ table->initializeIfNeeded(exec);
+ ASSERT(table->table);
+
+ int hashSizeMask = table->compactSize - 1;
+ const HashEntry* entry = table->table;
+ for (int i = 0; i <= hashSizeMask; ++i, ++entry) {
+ if (entry->key() && !(entry->attributes() & DontEnum))
+ propertyNames.add(entry->key());
+ }
+ }
+}
+
#if DO_PROPERTYMAP_CONSTENCY_CHECK
void Structure::checkConsistency()