diff options
author | Simon Hausmann <simon.hausmann@nokia.com> | 2009-06-15 09:06:43 (GMT) |
---|---|---|
committer | Simon Hausmann <simon.hausmann@nokia.com> | 2009-06-15 09:31:31 (GMT) |
commit | c411f16870f112c3407c28c22b617f613a82cff4 (patch) | |
tree | 29a1bcd590c8b31af2aab445bfe8a978dc5bf582 /src/3rdparty/webkit/JavaScriptCore/runtime/Structure.cpp | |
parent | 3d77b56b32a0c53ec0bbfaa07236fedb900ff336 (diff) | |
download | Qt-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.cpp | 263 |
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() |