2008-10-07 Cameron Zwarich <zwarich@apple.com>
authorcwzwarich@webkit.org <cwzwarich@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 7 Oct 2008 18:17:37 +0000 (18:17 +0000)
committercwzwarich@webkit.org <cwzwarich@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 7 Oct 2008 18:17:37 +0000 (18:17 +0000)
        Rubber-stamped by Mark Rowe.

        Roll out r37370.

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@37381 268f45cc-cd09-0410-ab3c-d52691b4dbfc

JavaScriptCore/ChangeLog
JavaScriptCore/JavaScriptCore.exp
JavaScriptCore/VM/CTI.cpp
JavaScriptCore/VM/Machine.cpp
JavaScriptCore/kjs/JSObject.cpp
JavaScriptCore/kjs/JSObject.h
JavaScriptCore/kjs/PropertyMap.cpp
JavaScriptCore/kjs/PropertyMap.h
JavaScriptCore/kjs/StructureID.cpp
JavaScriptCore/kjs/StructureID.h

index ebef1046f8dfd1fc89efbbd949eb62a5ac218abe..62d0d098fcd26b536959248f61152f92a999f177 100644 (file)
@@ -1,3 +1,9 @@
+2008-10-07  Cameron Zwarich  <zwarich@apple.com>
+
+        Rubber-stamped by Mark Rowe.
+
+        Roll out r37370.
+
 2008-10-06  Sam Weinig  <sam@webkit.org>
 
         Reviewed by Cameron Zwarich.
index 20c7631f016ba2baa0ff245505f9906dd24e40ad..a558c4f2a4060b327711b3ca0af13525947b3d3b 100644 (file)
@@ -108,14 +108,13 @@ __ZN3JSC11JSImmediate8toStringEPKNS_7JSValueE
 __ZN3JSC11JSImmediate9prototypeEPKNS_7JSValueEPNS_9ExecStateE
 __ZN3JSC11ProfileNode4sortEPFbRKN3WTF6RefPtrIS0_EES5_E
 __ZN3JSC11ProgramNode6createEPNS_12JSGlobalDataEPNS_14SourceElementsEPN3WTF6VectorISt4pairINS_10IdentifierEjELm16EEEPNS6_INS5_6RefPtrINS_12FuncDeclNodeEEELm16EEERKNS_10SourceCodeEji
-__ZN3JSC11PropertyMap3getERKNS_10IdentifierERj
-__ZN3JSC11PropertyMap3putERKNS_10IdentifierEj
+__ZN3JSC11PropertyMap3putERKNS_10IdentifierEPNS_7JSValueEjbPNS_8JSObjectERNS_15PutPropertySlotERPS5_
+__ZN3JSC11PropertyMap9getOffsetERKNS_10IdentifierERj
 __ZN3JSC11PropertyMapD1Ev
-__ZN3JSC11StructureID21addPropertyTransitionEPS0_RKNS_10IdentifierEjRm
+__ZN3JSC11StructureID21addPropertyTransitionEPS0_RKNS_10IdentifierEPNS_7JSValueEjPNS_8JSObjectERNS_15PutPropertySlotERPS6_
 __ZN3JSC11StructureID21clearEnumerationCacheEv
 __ZN3JSC11StructureID24fromDictionaryTransitionEPS0_
 __ZN3JSC11StructureID25changePrototypeTransitionEPS0_PNS_7JSValueE
-__ZN3JSC11StructureID27growPropertyStorageCapacityEv
 __ZN3JSC11StructureIDC1EPNS_7JSValueERKNS_8TypeInfoE
 __ZN3JSC11StructureIDD1Ev
 __ZN3JSC12DateInstance4infoE
index e5ba06cad5b065d2868836808078c2f1045b0e1c..ea8263ad994eec12ba53cafe2387b4155d0e2698 100644 (file)
@@ -2743,7 +2743,13 @@ extern "C" {
 
 static JSValue* SFX_CALL transitionObject(StructureID* newStructureID, size_t cachedOffset, JSObject* baseObject, JSValue* value)
 {
+    StructureID* oldStructureID = newStructureID->previousID();
+
     baseObject->transitionTo(newStructureID);
+
+    if (oldStructureID->propertyMap().storageSize() == JSObject::inlineStorageCapacity)
+        baseObject->allocatePropertyStorage(oldStructureID->propertyMap().storageSize(), oldStructureID->propertyMap().size());
+
     baseObject->putDirectOffset(cachedOffset, value);
     return baseObject;
 }
@@ -2752,7 +2758,16 @@ static JSValue* SFX_CALL transitionObject(StructureID* newStructureID, size_t ca
 
 static inline bool transitionWillNeedStorageRealloc(StructureID* oldStructureID, StructureID* newStructureID)
 {
-    return oldStructureID->propertyStorageCapacity() != newStructureID->propertyStorageCapacity();
+    if (oldStructureID->propertyMap().storageSize() == JSObject::inlineStorageCapacity)
+        return true;
+
+    if (oldStructureID->propertyMap().storageSize() < JSObject::inlineStorageCapacity)
+        return false;
+
+    if (oldStructureID->propertyMap().size() != newStructureID->propertyMap().size())
+        return true;
+
+    return false;
 }
 
 void CTI::privateCompilePutByIdTransition(StructureID* oldStructureID, StructureID* newStructureID, size_t cachedOffset, StructureIDChain* sIDC, void* returnAddress)
index b9f0c997727830ad1a22372392126d408728027b..89306ce93cf48db59cadfb43f8f4ba79125f5b65 100644 (file)
@@ -2721,6 +2721,8 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, RegisterFile* registerFile,
                 }
 
                 baseObject->transitionTo(newStructureID);
+                if (oldStructureID->propertyMap().storageSize() == JSObject::inlineStorageCapacity)
+                    baseObject->allocatePropertyStorage(oldStructureID->propertyMap().storageSize(), oldStructureID->propertyMap().size());
 
                 int value = vPC[3].u.operand;
                 unsigned offset = vPC[7].u.operand;
index 21ead06b3b0e66000784655f773ebdc257e6e5c4..cf5132e852a90d4796fcbf7bad46f9dc5effebb0 100644 (file)
@@ -134,7 +134,7 @@ void JSObject::put(ExecState* exec, const Identifier& propertyName, JSValue* val
     }
     
     unsigned attributes;
-    if ((m_structureID->propertyMap().get(propertyName, attributes) != WTF::notFound) && attributes & ReadOnly)
+    if ((m_structureID->propertyMap().getOffset(propertyName, attributes) != WTF::notFound) && attributes & ReadOnly)
         return;
 
     for (JSObject* obj = this; ; obj = static_cast<JSObject*>(prototype)) {
@@ -200,7 +200,7 @@ bool JSObject::hasProperty(ExecState* exec, unsigned propertyName) const
 bool JSObject::deleteProperty(ExecState* exec, const Identifier& propertyName)
 {
     unsigned attributes;
-    if (m_structureID->propertyMap().get(propertyName, attributes) != WTF::notFound) {
+    if (m_structureID->propertyMap().getOffset(propertyName, attributes) != WTF::notFound) {
         if ((attributes & DontDelete))
             return false;
         removeDirect(propertyName);
@@ -412,7 +412,7 @@ bool JSObject::propertyIsEnumerable(ExecState* exec, const Identifier& propertyN
 
 bool JSObject::getPropertyAttributes(ExecState* exec, const Identifier& propertyName, unsigned& attributes) const
 {
-    if (m_structureID->propertyMap().get(propertyName, attributes) != WTF::notFound)
+    if (m_structureID->propertyMap().getOffset(propertyName, attributes) != WTF::notFound)
         return true;
     
     // Look in the static hashtable of properties
@@ -468,20 +468,14 @@ JSGlobalObject* JSObject::toGlobalObject(ExecState*) const
 
 void JSObject::removeDirect(const Identifier& propertyName)
 {
-    size_t offset;
     if (m_structureID->isDictionary()) {
-        offset = m_structureID->propertyMap().remove(propertyName);
-        if (offset != WTF::notFound) {
-            m_propertyStorage[offset] = jsUndefined();
-            m_structureID->clearEnumerationCache();
-        }
+        m_structureID->propertyMap().remove(propertyName, m_propertyStorage);
+        m_structureID->clearEnumerationCache();
         return;
     }
 
     RefPtr<StructureID> structureID = StructureID::toDictionaryTransition(m_structureID);
-    offset = structureID->propertyMap().remove(propertyName);
-    if (offset != WTF::notFound)
-        m_propertyStorage[offset] = jsUndefined();
+    structureID->propertyMap().remove(propertyName, m_propertyStorage);
     setStructureID(structureID.release());
 }
 
@@ -506,8 +500,6 @@ StructureID* JSObject::createInheritorID()
 
 void JSObject::allocatePropertyStorage(size_t oldSize, size_t newSize)
 {
-    ASSERT(newSize > oldSize);
-
     JSValue** oldPropertStorage = m_propertyStorage;
     m_propertyStorage = new JSValue*[newSize];
 
index 9e313433901943855c0cf00be11d2a3c2eabbdb0..c6c9cb99bdf62765fc7f3661f14d15ac8e01e3d7 100644 (file)
@@ -122,19 +122,19 @@ namespace JSC {
         // This get function only looks at the property map.
         JSValue* getDirect(const Identifier& propertyName) const
         {
-            size_t offset = m_structureID->propertyMap().get(propertyName);
+            size_t offset = m_structureID->propertyMap().getOffset(propertyName);
             return offset != WTF::notFound ? m_propertyStorage[offset] : 0;
         }
 
         JSValue** getDirectLocation(const Identifier& propertyName)
         {
-            size_t offset = m_structureID->propertyMap().get(propertyName);
+            size_t offset = m_structureID->propertyMap().getOffset(propertyName);
             return offset != WTF::notFound ? locationForOffset(offset) : 0;
         }
 
         JSValue** getDirectLocation(const Identifier& propertyName, unsigned& attributes)
         {
-            size_t offset = m_structureID->propertyMap().get(propertyName, attributes);
+            size_t offset = m_structureID->propertyMap().getOffset(propertyName, attributes);
             return offset != WTF::notFound ? locationForOffset(offset) : 0;
         }
 
@@ -178,7 +178,6 @@ namespace JSC {
         bool usingInlineStorage() const { return m_propertyStorage == m_inlineStorage; }
 
         static const size_t inlineStorageCapacity = 2;
-        static const size_t nonInlineBaseStorageCapacity = 16;
 
         static PassRefPtr<StructureID> createStructureID(JSValue* proto) { return StructureID::create(proto, TypeInfo(ObjectType)); }
 
@@ -365,32 +364,26 @@ inline void JSObject::putDirect(const Identifier& propertyName, JSValue* value,
 {
     ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this));
 
-    if (m_structureID->isDictionary()) {
-        unsigned currentAttributes;
-        size_t offset = m_structureID->propertyMap().get(propertyName, currentAttributes);
-        if (offset != WTF::notFound) {
-            if (checkReadOnly && currentAttributes & ReadOnly)
-                return;
-            m_propertyStorage[offset] = value;
-            slot.setExistingProperty(this, offset);
-            return;
-        }
-
-        size_t currentCapacity = m_structureID->propertyStorageCapacity();
-        offset = m_structureID->propertyMap().put(propertyName, attributes);
-        if (m_structureID->propertyMap().storageSize() > m_structureID->propertyStorageCapacity()) {
-            m_structureID->growPropertyStorageCapacity();
-            allocatePropertyStorage(currentCapacity, m_structureID->propertyStorageCapacity());
-        }
-
-        m_propertyStorage[offset] = value;
-        slot.setNewProperty(this, offset);
-        m_structureID->clearEnumerationCache();
-        return;
-    }
+     if (m_structureID->isDictionary()) {
+         unsigned currentAttributes;
+         size_t offset = m_structureID->propertyMap().getOffset(propertyName, currentAttributes);
+         if (offset != WTF::notFound) {
+             if (checkReadOnly && currentAttributes & ReadOnly)
+                 return;
+             m_propertyStorage[offset] = value;
+             slot.setExistingProperty(this, offset);
+             return;
+         }
+
+         if (m_structureID->propertyMap().storageSize() == inlineStorageCapacity)
+             allocatePropertyStorage(m_structureID->propertyMap().storageSize(), m_structureID->propertyMap().size());
+         m_structureID->propertyMap().put(propertyName, value, attributes, checkReadOnly, this, slot, m_propertyStorage);
+         m_structureID->clearEnumerationCache();
+         return;
+     }
 
     unsigned currentAttributes;
-    size_t offset = m_structureID->propertyMap().get(propertyName, currentAttributes);
+    size_t offset = m_structureID->propertyMap().getOffset(propertyName, currentAttributes);
     if (offset != WTF::notFound) {
         if (checkReadOnly && currentAttributes & ReadOnly)
             return;
@@ -399,22 +392,17 @@ inline void JSObject::putDirect(const Identifier& propertyName, JSValue* value,
         return;
     }
 
-    size_t currentCapacity = m_structureID->propertyStorageCapacity();
-    RefPtr<StructureID> structureID = StructureID::addPropertyTransition(m_structureID, propertyName, attributes, offset);
-    if (currentCapacity != structureID->propertyStorageCapacity())
-        allocatePropertyStorage(currentCapacity, structureID->propertyStorageCapacity());
+     if (m_structureID->propertyMap().storageSize() == inlineStorageCapacity)
+         allocatePropertyStorage(m_structureID->propertyMap().storageSize(), m_structureID->propertyMap().size());
 
-    ASSERT(offset < structureID->propertyStorageCapacity());
-    m_propertyStorage[offset] = value;
-    slot.setNewProperty(this, offset);
-    slot.setWasTransition(true);
-    setStructureID(structureID.release());
+     RefPtr<StructureID> structureID = StructureID::addPropertyTransition(m_structureID, propertyName, value, attributes, this, slot, m_propertyStorage);
+     slot.setWasTransition(true);
+     setStructureID(structureID.release());
 }
 
 inline void JSObject::transitionTo(StructureID* newStructureID)
 {
-    if (m_structureID->propertyStorageCapacity() != newStructureID->propertyStorageCapacity())
-        allocatePropertyStorage(m_structureID->propertyStorageCapacity(), newStructureID->propertyStorageCapacity());
+    StructureID::transitionTo(m_structureID, newStructureID, this);
     setStructureID(newStructureID);
 }
 
index 81c0964cc235a578e7a14ef28c01e64dc3836d50..85931d010852cfd55cc93d1ad265dbf7f5650a12 100644 (file)
@@ -77,7 +77,7 @@ static const unsigned deletedSentinelIndex = 1;
 
 #if !DO_PROPERTYMAP_CONSTENCY_CHECK
 
-inline void PropertyMap::checkConsistency()
+inline void PropertyMap::checkConsistency(PropertyStorage&)
 {
 }
 
@@ -97,7 +97,6 @@ PropertyMap& PropertyMap::operator=(const PropertyMap& other)
         }
     }
 
-    m_deletedOffsets = other.m_deletedOffsets;
     m_getterSetterFlag = other.m_getterSetterFlag;
     return *this;
 }
@@ -115,17 +114,17 @@ PropertyMap::~PropertyMap()
     fastFree(m_table);
 }
 
-size_t PropertyMap::put(const Identifier& propertyName, unsigned attributes)
+size_t PropertyMap::put(const Identifier& propertyName, JSValue* value, unsigned attributes, bool checkReadOnly, JSObject* slotBase, PutPropertySlot& slot, PropertyStorage& propertyStorage)
 {
     ASSERT(!propertyName.isNull());
-    ASSERT(get(propertyName) == WTF::notFound);
+    ASSERT(value);
 
-    checkConsistency();
+    checkConsistency(propertyStorage);
 
     UString::Rep* rep = propertyName._ustring.rep();
 
     if (!m_table)
-        createTable();
+        expand(propertyStorage);
 
     // FIXME: Consider a fast case for tables with no deleted sentinels.
 
@@ -143,7 +142,15 @@ size_t PropertyMap::put(const Identifier& propertyName, unsigned attributes)
         if (entryIndex == emptyEntryIndex)
             break;
 
-        if (entryIndex == deletedSentinelIndex) {
+        if (m_table->entries()[entryIndex - 1].key == rep) {
+            if (checkReadOnly && (m_table->entries()[entryIndex - 1].attributes & ReadOnly))
+                return WTF::notFound;
+            // Put a new value in an existing hash table entry.
+            propertyStorage[entryIndex - 2] = value;
+            // Attributes are intentionally not updated.
+            slot.setExistingProperty(slotBase, entryIndex - 2);
+            return entryIndex - 2;
+        } else if (entryIndex == deletedSentinelIndex) {
             // If we find a deleted-element sentinel, remember it for use later.
             if (!foundDeletedElement) {
                 foundDeletedElement = true;
@@ -186,35 +193,28 @@ size_t PropertyMap::put(const Identifier& propertyName, unsigned attributes)
     m_table->entries()[entryIndex - 1].key = rep;
     m_table->entries()[entryIndex - 1].attributes = attributes;
     m_table->entries()[entryIndex - 1].index = ++m_table->lastIndexUsed;
-
-    unsigned newOffset;
-    if (!m_deletedOffsets.isEmpty()) {
-        newOffset = m_deletedOffsets.last();
-        m_deletedOffsets.removeLast();
-    } else
-        newOffset = m_table->keyCount + m_table->deletedSentinelCount;
-    m_table->entries()[entryIndex - 1].offset = newOffset;
-
     ++m_table->keyCount;
 
+    propertyStorage[entryIndex - 2] = value;
+
     if ((m_table->keyCount + m_table->deletedSentinelCount) * 2 >= m_table->size)
-        expand();
+        expand(propertyStorage);
 
-    checkConsistency();
-    return newOffset;
+    checkConsistency(propertyStorage);
+    slot.setNewProperty(slotBase, entryIndex - 2);
+    return entryIndex - 2;
 }
 
-size_t PropertyMap::remove(const Identifier& propertyName)
+void PropertyMap::remove(const Identifier& propertyName, PropertyStorage& propertyStorage)
 {
     ASSERT(!propertyName.isNull());
 
-    checkConsistency();
+    checkConsistency(propertyStorage);
 
     UString::Rep* rep = propertyName._ustring.rep();
 
     if (!m_table)
-        return WTF::notFound;
-
+        return;
 
 #if DUMP_PROPERTYMAP_STATS
     ++numProbes;
@@ -229,7 +229,7 @@ size_t PropertyMap::remove(const Identifier& propertyName)
     while (1) {
         entryIndex = m_table->entryIndices[i & m_table->sizeMask];
         if (entryIndex == emptyEntryIndex)
-            return WTF::notFound;
+            return;
 
         key = m_table->entries()[entryIndex - 1].key;
         if (rep == key)
@@ -252,27 +252,23 @@ size_t PropertyMap::remove(const Identifier& propertyName)
     // Replace this one element with the deleted sentinel. Also clear out
     // the entry so we can iterate all the entries as needed.
     m_table->entryIndices[i & m_table->sizeMask] = deletedSentinelIndex;
-
-    size_t offset = m_table->entries()[entryIndex - 1].offset;
-
     key->deref();
     m_table->entries()[entryIndex - 1].key = 0;
     m_table->entries()[entryIndex - 1].attributes = 0;
-    m_table->entries()[entryIndex - 1].offset = 0;
-    m_deletedOffsets.append(offset);
+
+    propertyStorage[entryIndex - 2] = jsUndefined();
 
     ASSERT(m_table->keyCount >= 1);
     --m_table->keyCount;
     ++m_table->deletedSentinelCount;
 
     if (m_table->deletedSentinelCount * 4 >= m_table->size)
-        rehash();
+        rehash(propertyStorage);
 
-    checkConsistency();
-    return offset;
+    checkConsistency(propertyStorage);
 }
 
-size_t PropertyMap::get(const Identifier& propertyName, unsigned& attributes)
+size_t PropertyMap::getOffset(const Identifier& propertyName, unsigned& attributes)
 {
     ASSERT(!propertyName.isNull());
 
@@ -293,7 +289,7 @@ size_t PropertyMap::get(const Identifier& propertyName, unsigned& attributes)
 
     if (rep == m_table->entries()[entryIndex - 1].key) {
         attributes = m_table->entries()[entryIndex - 1].attributes;
-        return m_table->entries()[entryIndex - 1].offset;
+        return entryIndex - 2;
     }
 
 #if DUMP_PROPERTYMAP_STATS
@@ -315,12 +311,12 @@ size_t PropertyMap::get(const Identifier& propertyName, unsigned& attributes)
 
         if (rep == m_table->entries()[entryIndex - 1].key) {
             attributes = m_table->entries()[entryIndex - 1].attributes;
-            return m_table->entries()[entryIndex - 1].offset;
+            return entryIndex - 2;
         }
     }
 }
 
-void PropertyMap::insert(const Entry& entry)
+void PropertyMap::insert(const Entry& entry, JSValue* value, PropertyStorage& propertyStorage)
 {
     ASSERT(m_table);
 
@@ -354,62 +350,70 @@ void PropertyMap::insert(const Entry& entry)
     m_table->entryIndices[i & m_table->sizeMask] = entryIndex;
     m_table->entries()[entryIndex - 1] = entry;
 
+    propertyStorage[entryIndex - 2] = value;
+
     ++m_table->keyCount;
 }
 
-void PropertyMap::expand()
+void PropertyMap::expand(PropertyStorage& propertyStorage)
+{
+    if (!m_table)
+        createTable(propertyStorage);
+    else
+        rehash(m_table->size * 2, propertyStorage);
+}
+
+void PropertyMap::rehash(PropertyStorage& propertyStorage)
 {
     ASSERT(m_table);
-    rehash(m_table->size * 2);
+    ASSERT(m_table->size);
+    rehash(m_table->size, propertyStorage);
 }
 
-void PropertyMap::createTable()
+void PropertyMap::createTable(PropertyStorage& propertyStorage)
 {
     const unsigned newTableSize = 16;
 
     ASSERT(!m_table);
 
-    checkConsistency();
+    checkConsistency(propertyStorage);
 
     m_table = static_cast<Table*>(fastZeroedMalloc(Table::allocationSize(newTableSize)));
     m_table->size = newTableSize;
     m_table->sizeMask = newTableSize - 1;
 
-    checkConsistency();
-}
-
-void PropertyMap::rehash()
-{
-    ASSERT(m_table);
-    ASSERT(m_table->size);
-    rehash(m_table->size);
+    checkConsistency(propertyStorage);
 }
 
-void PropertyMap::rehash(unsigned newTableSize)
+void PropertyMap::rehash(unsigned newTableSize, PropertyStorage& propertyStorage)
 {
     ASSERT(m_table);
 
-    checkConsistency();
+    checkConsistency(propertyStorage);
 
     Table* oldTable = m_table;
+    JSValue** oldPropertStorage = propertyStorage;
 
     m_table = static_cast<Table*>(fastZeroedMalloc(Table::allocationSize(newTableSize)));
     m_table->size = newTableSize;
     m_table->sizeMask = newTableSize - 1;
 
+    propertyStorage = new JSValue*[m_table->size];
+
     unsigned lastIndexUsed = 0;
     unsigned entryCount = oldTable->keyCount + oldTable->deletedSentinelCount;
     for (unsigned i = 1; i <= entryCount; ++i) {
         if (oldTable->entries()[i].key) {
             lastIndexUsed = max(oldTable->entries()[i].index, lastIndexUsed);
-            insert(oldTable->entries()[i]);
+            insert(oldTable->entries()[i], oldPropertStorage[i - 1], propertyStorage);
         }
     }
     m_table->lastIndexUsed = lastIndexUsed;
 
     fastFree(oldTable);
+    delete [] oldPropertStorage;
 
-    checkConsistency();
+    checkConsistency(propertyStorage);
 }
 
 static int comparePropertyMapEntryIndices(const void* a, const void* b)
@@ -481,7 +485,7 @@ void PropertyMap::getEnumerablePropertyNames(PropertyNameArray& propertyNames) c
 
 #if DO_PROPERTYMAP_CONSTENCY_CHECK
 
-void PropertyMap::checkConsistency()
+void PropertyMap::checkConsistency(PropertyStorage& propertyStorage)
 {
     if (!m_table)
         return;
@@ -521,8 +525,10 @@ void PropertyMap::checkConsistency()
     unsigned nonEmptyEntryCount = 0;
     for (unsigned c = 1; c <= m_table->keyCount + m_table->deletedSentinelCount; ++c) {
         UString::Rep* rep = m_table->entries()[c].key;
-        if (!rep)
+        if (!rep) {
+            ASSERT(propertyStorage[c - 1]->isUndefined());
             continue;
+        }
         ++nonEmptyEntryCount;
         unsigned i = rep->computedHash();
         unsigned k = 0;
index efa76698ec295b0e50f803f9bcfa6b68ef77e10f..b92a11e6d6fc1858f2f30903e22fa0d4571cbb77 100644 (file)
@@ -42,13 +42,11 @@ namespace JSC {
 
     struct PropertyMapEntry {
         UString::Rep* key;
-        unsigned offset;
         unsigned attributes;
         unsigned index;
 
         PropertyMapEntry(UString::Rep* k, int a)
             : key(k)
-            , offset(0)
             , attributes(a)
             , index(0)
         {
@@ -96,10 +94,11 @@ namespace JSC {
 
         bool isEmpty() { return !m_table; }
 
-        size_t get(const Identifier& propertyName);
-        size_t get(const Identifier& propertyName, unsigned& attributes);
-        size_t put(const Identifier& propertyName, unsigned attributes);
-        size_t remove(const Identifier& propertyName);
+        size_t put(const Identifier& propertyName, JSValue*, unsigned attributes, bool checkReadOnly, JSObject* slotBase, PutPropertySlot&, PropertyStorage&);
+        void remove(const Identifier& propertyName, PropertyStorage&);
+
+        size_t getOffset(const Identifier& propertyName);
+        size_t getOffset(const Identifier& propertyName, unsigned& attributes);
 
         void getEnumerablePropertyNames(PropertyNameArray&) const;
 
@@ -115,17 +114,16 @@ namespace JSC {
         typedef PropertyMapEntry Entry;
         typedef PropertyMapHashTable Table;
 
-        void expand();
-        void rehash();
-        void rehash(unsigned newTableSize);
-        void createTable();
+        void expand(PropertyStorage&);
+        void rehash(PropertyStorage&);
+        void rehash(unsigned newTableSize, PropertyStorage&);
+        void createTable(PropertyStorage&);
 
-        void insert(const Entry&);
+        void insert(const Entry&, JSValue*, PropertyStorage&);
 
-        void checkConsistency();
+        void checkConsistency(PropertyStorage&);
 
         Table* m_table;
-        Vector<unsigned> m_deletedOffsets;
         bool m_getterSetterFlag : 1;
     };
 
@@ -135,7 +133,7 @@ namespace JSC {
     {
     }
 
-    inline size_t PropertyMap::get(const Identifier& propertyName)
+    inline size_t PropertyMap::getOffset(const Identifier& propertyName)
     {
         ASSERT(!propertyName.isNull());
 
@@ -155,7 +153,7 @@ namespace JSC {
             return WTF::notFound;
 
         if (rep == m_table->entries()[entryIndex - 1].key)
-            return m_table->entries()[entryIndex - 1].offset;
+            return entryIndex - 2;
 
 #if DUMP_PROPERTYMAP_STATS
         ++numCollisions;
@@ -175,7 +173,7 @@ namespace JSC {
                 return WTF::notFound;
 
             if (rep == m_table->entries()[entryIndex - 1].key)
-                return m_table->entries()[entryIndex - 1].offset;
+                return entryIndex - 2;
         }
     }
 
index 30f02a8e282b6ca32bae587f7bd0e6723a53b816..dd419923c2951b06f55eeb98f7f7519fdea695c6 100644 (file)
@@ -44,7 +44,6 @@ StructureID::StructureID(JSValue* prototype, const TypeInfo& typeInfo)
     , m_previous(0)
     , m_nameInPrevious(0)
     , m_transitionCount(0)
-    , m_propertyStorageCapacity(JSObject::inlineStorageCapacity)
     , m_cachedTransistionOffset(WTF::notFound)
 {
     ASSERT(m_prototype);
@@ -103,30 +102,32 @@ void StructureID::clearEnumerationCache()
     m_cachedPropertyNameArrayData.clear();
 }
 
-void StructureID::growPropertyStorageCapacity()
+void StructureID::transitionTo(StructureID* oldStructureID, StructureID* newStructureID, JSObject* slotBase)
 {
-    if (m_propertyStorageCapacity == JSObject::inlineStorageCapacity)
-        m_propertyStorageCapacity = JSObject::nonInlineBaseStorageCapacity;
-    else
-        m_propertyStorageCapacity *= 2;
+    if (!slotBase->usingInlineStorage() && oldStructureID->m_propertyMap.size() != newStructureID->m_propertyMap.size())
+        slotBase->allocatePropertyStorage(oldStructureID->m_propertyMap.size(), newStructureID->m_propertyMap.size());
 }
 
-PassRefPtr<StructureID> StructureID::addPropertyTransition(StructureID* structureID, const Identifier& propertyName, unsigned attributes, size_t& offset)
+PassRefPtr<StructureID> StructureID::addPropertyTransition(StructureID* structureID, const Identifier& propertyName, JSValue* value, unsigned attributes, JSObject* slotBase, PutPropertySlot& slot, PropertyStorage& propertyStorage)
 {
     ASSERT(!structureID->m_isDictionary);
     ASSERT(structureID->typeInfo().type() == ObjectType);
 
     if (StructureID* existingTransition = structureID->m_transitionTable.get(make_pair(propertyName.ustring().rep(), attributes))) {
-        offset = existingTransition->cachedTransistionOffset();
+        if (!slotBase->usingInlineStorage() && structureID->m_propertyMap.size() != existingTransition->m_propertyMap.size())
+            slotBase->allocatePropertyStorage(structureID->m_propertyMap.size(), existingTransition->m_propertyMap.size());
+
+        size_t offset = existingTransition->cachedTransistionOffset();
         ASSERT(offset != WTF::notFound);
+        propertyStorage[offset] = value;
+        slot.setNewProperty(slotBase, offset);
+
         return existingTransition;
     }
 
     if (structureID->m_transitionCount > s_maxTransitionLength) {
         RefPtr<StructureID> transition = toDictionaryTransition(structureID);
-        offset = transition->m_propertyMap.put(propertyName, attributes);
-        if (transition->m_propertyMap.storageSize() > transition->propertyStorageCapacity())
-            transition->growPropertyStorageCapacity();
+        transition->m_propertyMap.put(propertyName, value, attributes, false, slotBase, slot, propertyStorage);
         return transition.release();
     }
 
@@ -137,12 +138,8 @@ PassRefPtr<StructureID> StructureID::addPropertyTransition(StructureID* structur
     transition->m_attributesInPrevious = attributes;
     transition->m_transitionCount = structureID->m_transitionCount + 1;
     transition->m_propertyMap = structureID->m_propertyMap;
-    transition->m_propertyStorageCapacity = structureID->m_propertyStorageCapacity;
-
-    offset = transition->m_propertyMap.put(propertyName, attributes);
-    if (transition->m_propertyMap.storageSize() > transition->propertyStorageCapacity())
-        transition->growPropertyStorageCapacity();
 
+    size_t offset = transition->m_propertyMap.put(propertyName, value, attributes, false, slotBase, slot, propertyStorage);
     transition->setCachedTransistionOffset(offset);
 
     structureID->m_transitionTable.add(make_pair(propertyName.ustring().rep(), attributes), transition.get());
@@ -156,7 +153,6 @@ PassRefPtr<StructureID> StructureID::toDictionaryTransition(StructureID* structu
     RefPtr<StructureID> transition = create(structureID->m_prototype, structureID->typeInfo());
     transition->m_isDictionary = true;
     transition->m_propertyMap = structureID->m_propertyMap;
-    transition->m_propertyStorageCapacity = structureID->m_propertyStorageCapacity;
     return transition.release();
 }
 
@@ -176,7 +172,6 @@ PassRefPtr<StructureID> StructureID::changePrototypeTransition(StructureID* stru
     RefPtr<StructureID> transition = create(prototype, structureID->typeInfo());
     transition->m_transitionCount = structureID->m_transitionCount + 1;
     transition->m_propertyMap = structureID->m_propertyMap;
-    transition->m_propertyStorageCapacity = structureID->m_propertyStorageCapacity;
     return transition.release();
 }
 
@@ -185,7 +180,6 @@ PassRefPtr<StructureID> StructureID::getterSetterTransition(StructureID* structu
     RefPtr<StructureID> transition = create(structureID->storedPrototype(), structureID->typeInfo());
     transition->m_transitionCount = structureID->m_transitionCount + 1;
     transition->m_propertyMap = structureID->m_propertyMap;
-    transition->m_propertyStorageCapacity = structureID->m_propertyStorageCapacity;
     return transition.release();
 }
 
index 80e7a5e1429a51fe4f81f96b9c5cc756052b7da5..fbbe4995fda2e1b557e982fde24c92ff7bd5e158 100644 (file)
@@ -83,7 +83,7 @@ namespace JSC {
         }
 
         static PassRefPtr<StructureID> changePrototypeTransition(StructureID*, JSValue* prototype);
-        static PassRefPtr<StructureID> addPropertyTransition(StructureID*, const Identifier& propertyName, unsigned attributes, size_t& offset);
+        static PassRefPtr<StructureID> addPropertyTransition(StructureID*, const Identifier& propertyName, JSValue*, unsigned attributes, JSObject* slotBase, PutPropertySlot&, PropertyStorage&);
         static PassRefPtr<StructureID> getterSetterTransition(StructureID*);
         static PassRefPtr<StructureID> toDictionaryTransition(StructureID*);
         static PassRefPtr<StructureID> fromDictionaryTransition(StructureID*);
@@ -118,12 +118,11 @@ namespace JSC {
         void setCachedTransistionOffset(size_t offset) { m_cachedTransistionOffset = offset; }
         size_t cachedTransistionOffset() const { return m_cachedTransistionOffset; }
 
-        void growPropertyStorageCapacity();
-        size_t propertyStorageCapacity() const { return m_propertyStorageCapacity; }
-
         void getEnumerablePropertyNames(ExecState*, PropertyNameArray&, JSObject*);
         void clearEnumerationCache();
 
+        static void transitionTo(StructureID* oldStructureID, StructureID* newStructureID, JSObject* slotBase);
+
     private:
         typedef std::pair<RefPtr<UString::Rep>, unsigned> TransitionTableKey;
         typedef HashMap<TransitionTableKey, StructureID*, TransitionTableHash, TransitionTableHashTraits> TransitionTable;
@@ -149,7 +148,6 @@ namespace JSC {
         RefPtr<PropertyNameArrayData> m_cachedPropertyNameArrayData;
 
         PropertyMap m_propertyMap;
-        size_t m_propertyStorageCapacity;
 
         size_t m_cachedTransistionOffset;
     };