diff options
Diffstat (limited to 'JavaScriptCore/runtime/Structure.cpp')
| -rw-r--r-- | JavaScriptCore/runtime/Structure.cpp | 140 |
1 files changed, 122 insertions, 18 deletions
diff --git a/JavaScriptCore/runtime/Structure.cpp b/JavaScriptCore/runtime/Structure.cpp index 546e2bf..d06a239 100644 --- a/JavaScriptCore/runtime/Structure.cpp +++ b/JavaScriptCore/runtime/Structure.cpp @@ -79,6 +79,106 @@ static HashSet<Structure*>& liveStructureSet = *(new HashSet<Structure*>); static int comparePropertyMapEntryIndices(const void* a, const void* b); +inline void Structure::setTransitionTable(TransitionTable* table) +{ + ASSERT(m_isUsingSingleSlot); +#ifndef NDEBUG + setSingleTransition(0); +#endif + m_isUsingSingleSlot = false; + m_transitions.m_table = table; + // This implicitly clears the flag that indicates we're using a single transition + ASSERT(!m_isUsingSingleSlot); +} + +// The contains and get methods accept imprecise matches, so if an unspecialised transition exists +// for the given key they will consider that transition to be a match. If a specialised transition +// exists and it matches the provided specificValue, get will return the specific transition. +inline bool Structure::transitionTableContains(const StructureTransitionTableHash::Key& key, JSCell* specificValue) +{ + if (m_isUsingSingleSlot) { + Structure* existingTransition = singleTransition(); + return existingTransition && existingTransition->m_nameInPrevious.get() == key.first + && existingTransition->m_attributesInPrevious == key.second + && (existingTransition->m_specificValueInPrevious == specificValue || existingTransition->m_specificValueInPrevious == 0); + } + TransitionTable::iterator find = transitionTable()->find(key); + if (find == transitionTable()->end()) + return false; + + return find->second.first || find->second.second->transitionedFor(specificValue); +} + +inline Structure* Structure::transitionTableGet(const StructureTransitionTableHash::Key& key, JSCell* specificValue) const +{ + if (m_isUsingSingleSlot) { + Structure* existingTransition = singleTransition(); + if (existingTransition && existingTransition->m_nameInPrevious.get() == key.first + && existingTransition->m_attributesInPrevious == key.second + && (existingTransition->m_specificValueInPrevious == specificValue || existingTransition->m_specificValueInPrevious == 0)) + return existingTransition; + return 0; + } + + Transition transition = transitionTable()->get(key); + if (transition.second && transition.second->transitionedFor(specificValue)) + return transition.second; + return transition.first; +} + +inline bool Structure::transitionTableHasTransition(const StructureTransitionTableHash::Key& key) const +{ + if (m_isUsingSingleSlot) { + Structure* transition = singleTransition(); + return transition && transition->m_nameInPrevious == key.first + && transition->m_attributesInPrevious == key.second; + } + return transitionTable()->contains(key); +} + +inline void Structure::transitionTableRemove(const StructureTransitionTableHash::Key& key, JSCell* specificValue) +{ + if (m_isUsingSingleSlot) { + ASSERT(transitionTableContains(key, specificValue)); + setSingleTransition(0); + return; + } + TransitionTable::iterator find = transitionTable()->find(key); + if (!specificValue) + find->second.first = 0; + else + find->second.second = 0; + if (!find->second.first && !find->second.second) + transitionTable()->remove(find); +} + +inline void Structure::transitionTableAdd(const StructureTransitionTableHash::Key& key, Structure* structure, JSCell* specificValue) +{ + if (m_isUsingSingleSlot) { + if (!singleTransition()) { + setSingleTransition(structure); + return; + } + Structure* existingTransition = singleTransition(); + TransitionTable* transitionTable = new TransitionTable; + setTransitionTable(transitionTable); + if (existingTransition) + transitionTableAdd(std::make_pair(existingTransition->m_nameInPrevious.get(), existingTransition->m_attributesInPrevious), existingTransition, existingTransition->m_specificValueInPrevious); + } + if (!specificValue) { + TransitionTable::iterator find = transitionTable()->find(key); + if (find == transitionTable()->end()) + transitionTable()->add(key, Transition(structure, static_cast<Structure*>(0))); + else + find->second.first = structure; + } else { + // If we're adding a transition to a specific value, then there cannot be + // an existing transition + ASSERT(!transitionTable()->contains(key)); + transitionTable()->add(key, Transition(static_cast<Structure*>(0), structure)); + } +} + void Structure::dumpStatistics() { #if DUMP_STRUCTURE_ID_STATISTICS @@ -136,7 +236,10 @@ Structure::Structure(JSValue prototype, const TypeInfo& typeInfo, unsigned anony , m_attributesInPrevious(0) , m_specificFunctionThrashCount(0) , m_anonymousSlotCount(anonymousSlotCount) + , m_isUsingSingleSlot(true) { + m_transitions.m_singleTransition = 0; + ASSERT(m_prototype); ASSERT(m_prototype.isObject() || m_prototype.isNull()); @@ -159,17 +262,15 @@ Structure::~Structure() { if (m_previous) { ASSERT(m_nameInPrevious); - m_previous->table.remove(make_pair(m_nameInPrevious.get(), m_attributesInPrevious), m_specificValueInPrevious); + m_previous->transitionTableRemove(make_pair(m_nameInPrevious.get(), m_attributesInPrevious), m_specificValueInPrevious); } - - if (m_enumerationCache) - m_enumerationCache->setCachedStructure(0); + ASSERT(!m_enumerationCache.hasDeadObject()); if (m_propertyTable) { unsigned entryCount = m_propertyTable->keyCount + m_propertyTable->deletedSentinelCount; for (unsigned i = 1; i <= entryCount; i++) { - if (UString::Rep* key = m_propertyTable->entries()[i].key) + if (StringImpl* key = m_propertyTable->entries()[i].key) key->deref(); } @@ -177,6 +278,9 @@ Structure::~Structure() fastFree(m_propertyTable); } + if (!m_isUsingSingleSlot) + delete transitionTable(); + #ifndef NDEBUG #if ENABLE(JSC_MULTIPLE_THREADS) MutexLocker protect(ignoreSetMutex); @@ -291,7 +395,7 @@ void Structure::growPropertyStorageCapacity() void Structure::despecifyDictionaryFunction(const Identifier& propertyName) { - const UString::Rep* rep = propertyName._ustring.rep(); + const StringImpl* rep = propertyName.impl(); materializePropertyMapIfNecessary(); @@ -340,7 +444,7 @@ PassRefPtr<Structure> Structure::addPropertyTransitionToExistingStructure(Struct ASSERT(!structure->isDictionary()); ASSERT(structure->typeInfo().type() == ObjectType); - if (Structure* existingTransition = structure->table.get(make_pair(propertyName.ustring().rep(), attributes), specificValue)) { + if (Structure* existingTransition = structure->transitionTableGet(make_pair(propertyName.impl(), attributes), specificValue)) { ASSERT(existingTransition->m_offset != noOffset); offset = existingTransition->m_offset + existingTransition->m_anonymousSlotCount; ASSERT(offset >= structure->m_anonymousSlotCount); @@ -375,7 +479,7 @@ PassRefPtr<Structure> Structure::addPropertyTransition(Structure* structure, con transition->m_cachedPrototypeChain = structure->m_cachedPrototypeChain; transition->m_previous = structure; - transition->m_nameInPrevious = propertyName.ustring().rep(); + transition->m_nameInPrevious = propertyName.impl(); transition->m_attributesInPrevious = attributes; transition->m_specificValueInPrevious = specificValue; transition->m_propertyStorageCapacity = structure->m_propertyStorageCapacity; @@ -405,7 +509,7 @@ PassRefPtr<Structure> Structure::addPropertyTransition(Structure* structure, con transition->m_offset = offset - structure->m_anonymousSlotCount; ASSERT(structure->anonymousSlotCount() == transition->anonymousSlotCount()); - structure->table.add(make_pair(propertyName.ustring().rep(), attributes), transition.get(), specificValue); + structure->transitionTableAdd(make_pair(propertyName.impl(), attributes), transition.get(), specificValue); return transition.release(); } @@ -634,7 +738,7 @@ PropertyMapHashTable* Structure::copyPropertyTable() unsigned entryCount = m_propertyTable->keyCount + m_propertyTable->deletedSentinelCount; for (unsigned i = 1; i <= entryCount; ++i) { - if (UString::Rep* key = newTable->entries()[i].key) + if (StringImpl* key = newTable->entries()[i].key) key->ref(); } @@ -645,7 +749,7 @@ PropertyMapHashTable* Structure::copyPropertyTable() return newTable; } -size_t Structure::get(const UString::Rep* rep, unsigned& attributes, JSCell*& specificValue) +size_t Structure::get(const StringImpl* rep, unsigned& attributes, JSCell*& specificValue) { materializePropertyMapIfNecessary(); if (!m_propertyTable) @@ -702,7 +806,7 @@ bool Structure::despecifyFunction(const Identifier& propertyName) if (!m_propertyTable) return false; - UString::Rep* rep = propertyName._ustring.rep(); + StringImpl* rep = propertyName.impl(); unsigned i = rep->existingHash(); @@ -766,7 +870,7 @@ size_t Structure::put(const Identifier& propertyName, unsigned attributes, JSCel if (attributes & DontEnum) m_hasNonEnumerableProperties = true; - UString::Rep* rep = propertyName._ustring.rep(); + StringImpl* rep = propertyName.impl(); if (!m_propertyTable) createPropertyMapHashTable(); @@ -850,9 +954,9 @@ size_t Structure::put(const Identifier& propertyName, unsigned attributes, JSCel return newOffset; } -bool Structure::hasTransition(UString::Rep* rep, unsigned attributes) +bool Structure::hasTransition(StringImpl* rep, unsigned attributes) { - return table.hasTransition(make_pair(rep, attributes)); + return transitionTableHasTransition(make_pair(rep, attributes)); } size_t Structure::remove(const Identifier& propertyName) @@ -861,7 +965,7 @@ size_t Structure::remove(const Identifier& propertyName) checkConsistency(); - UString::Rep* rep = propertyName._ustring.rep(); + StringImpl* rep = propertyName.impl(); if (!m_propertyTable) return notFound; @@ -875,7 +979,7 @@ size_t Structure::remove(const Identifier& propertyName) unsigned i = rep->existingHash(); unsigned k = 0; unsigned entryIndex; - UString::Rep* key = 0; + StringImpl* key = 0; while (1) { entryIndex = m_propertyTable->entryIndices[i & m_propertyTable->sizeMask]; if (entryIndex == emptyEntryIndex) @@ -1137,7 +1241,7 @@ void Structure::checkConsistency() unsigned nonEmptyEntryCount = 0; for (unsigned c = 1; c <= m_propertyTable->keyCount + m_propertyTable->deletedSentinelCount; ++c) { ASSERT(m_hasNonEnumerableProperties || !(m_propertyTable->entries()[c].attributes & DontEnum)); - UString::Rep* rep = m_propertyTable->entries()[c].key; + StringImpl* rep = m_propertyTable->entries()[c].key; ASSERT(m_propertyTable->entries()[c].offset >= m_anonymousSlotCount); if (!rep) continue; |
