Changeset 37370 in webkit for trunk/JavaScriptCore/kjs


Ignore:
Timestamp:
Oct 6, 2008, 10:43:06 PM (17 years ago)
Author:
[email protected]
Message:

2008-10-06 Sam Weinig <[email protected]>

Reviewed by Cameron Zwarich.

Fix for https://bugs.webkit.org/show_bug.cgi?id=21415
Improve the division between PropertyStorageArray and PropertyMap

  • Rework ProperyMap to store offsets in the value so that they don't change when rehashing. This allows us not to have to keep the PropertyStorageArray in sync and thus not have to pass it in.
  • Rename PropertyMap::getOffset -> PropertyMap::get since put/remove now also return offsets.
  • A Vector of deleted offsets is now needed since the storage is out of band.

1% win on SunSpider. Wash on V8 suite.

  • JavaScriptCore.exp:
  • VM/CTI.cpp: (JSC::transitionWillNeedStorageRealloc):
  • VM/Machine.cpp: (JSC::Machine::privateExecute): Transition logic can be greatly simplified by the fact that the storage capacity is always known, and is correct for the inline case.
  • kjs/JSObject.cpp: (JSC::JSObject::put): Rename getOffset -> get. (JSC::JSObject::deleteProperty): Ditto. (JSC::JSObject::getPropertyAttributes): Ditto. (JSC::JSObject::removeDirect): Use returned offset to clear the value in the PropertyNameArray. (JSC::JSObject::allocatePropertyStorage): Add assert.
  • kjs/JSObject.h: (JSC::JSObject::getDirect): Rename getOffset -> get (JSC::JSObject::getDirectLocation): Rename getOffset -> get (JSC::JSObject::putDirect): Use propertyStorageCapacity to determine whether or not to resize. Also, since put now returns an offset (and thus addPropertyTransition does also) setting of the PropertyStorageArray is now done here. (JSC::JSObject::transitionTo):
  • kjs/PropertyMap.cpp: (JSC::PropertyMap::checkConsistency): PropertyStorageArray is no longer passed in. (JSC::PropertyMap::operator=): Copy the delete offsets vector. (JSC::PropertyMap::put): Instead of setting the PropertyNameArray explicitly, return the offset where the value should go. (JSC::PropertyMap::remove): Instead of removing from the PropertyNameArray explicitly, return the offset where the value should be removed. (JSC::PropertyMap::get): Switch to using the stored offset, instead of the implicit one. (JSC::PropertyMap::insert): (JSC::PropertyMap::expand): This is never called when m_table is null, so remove that branch and add it as an assertion. (JSC::PropertyMap::createTable): Consistency checks no longer take a PropertyNameArray. (JSC::PropertyMap::rehash): No need to rehash the PropertyNameArray now that it is completely out of band.
  • kjs/PropertyMap.h: (JSC::PropertyMapEntry::PropertyMapEntry): Store offset into PropertyNameArray. (JSC::PropertyMap::get): Switch to using the stored offset, instead of the implicit one.
  • kjs/StructureID.cpp: (JSC::StructureID::StructureID): Initialize the propertyStorageCapacity to JSObject::inlineStorageCapacity. (JSC::StructureID::growPropertyStorageCapacity): Grow the storage capacity as described below. (JSC::StructureID::addPropertyTransition): Copy the storage capacity. (JSC::StructureID::toDictionaryTransition): Ditto. (JSC::StructureID::changePrototypeTransition): Ditto. (JSC::StructureID::getterSetterTransition): Ditto.
  • kjs/StructureID.h: (JSC::StructureID::propertyStorageCapacity): Add propertyStorageCapacity which is the current capacity for the JSObjects PropertyStorageArray. It starts at the JSObject::inlineStorageCapacity (currently 2), then when it first needs to be resized moves to the JSObject::nonInlineBaseStorageCapacity (currently 16), and after that doubles each time.
Location:
trunk/JavaScriptCore/kjs
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/kjs/JSObject.cpp

    r37337 r37370  
    135135   
    136136    unsigned attributes;
    137     if ((m_structureID->propertyMap().getOffset(propertyName, attributes) != WTF::notFound) && attributes & ReadOnly)
     137    if ((m_structureID->propertyMap().get(propertyName, attributes) != WTF::notFound) && attributes & ReadOnly)
    138138        return;
    139139
     
    201201{
    202202    unsigned attributes;
    203     if (m_structureID->propertyMap().getOffset(propertyName, attributes) != WTF::notFound) {
     203    if (m_structureID->propertyMap().get(propertyName, attributes) != WTF::notFound) {
    204204        if ((attributes & DontDelete))
    205205            return false;
     
    413413bool JSObject::getPropertyAttributes(ExecState* exec, const Identifier& propertyName, unsigned& attributes) const
    414414{
    415     if (m_structureID->propertyMap().getOffset(propertyName, attributes) != WTF::notFound)
     415    if (m_structureID->propertyMap().get(propertyName, attributes) != WTF::notFound)
    416416        return true;
    417417   
     
    469469void JSObject::removeDirect(const Identifier& propertyName)
    470470{
     471    size_t offset;
    471472    if (m_structureID->isDictionary()) {
    472         m_structureID->propertyMap().remove(propertyName, m_propertyStorage);
    473         m_structureID->clearEnumerationCache();
     473        offset = m_structureID->propertyMap().remove(propertyName);
     474        if (offset != WTF::notFound) {
     475            m_propertyStorage[offset] = jsUndefined();
     476            m_structureID->clearEnumerationCache();
     477        }
    474478        return;
    475479    }
    476480
    477481    RefPtr<StructureID> structureID = StructureID::toDictionaryTransition(m_structureID);
    478     structureID->propertyMap().remove(propertyName, m_propertyStorage);
     482    offset = structureID->propertyMap().remove(propertyName);
     483    if (offset != WTF::notFound)
     484        m_propertyStorage[offset] = jsUndefined();
    479485    setStructureID(structureID.release());
    480486}
     
    501507void JSObject::allocatePropertyStorage(size_t oldSize, size_t newSize)
    502508{
     509    ASSERT(newSize > oldSize);
     510
    503511    JSValue** oldPropertStorage = m_propertyStorage;
    504512    m_propertyStorage = new JSValue*[newSize];
  • trunk/JavaScriptCore/kjs/JSObject.h

    r37337 r37370  
    123123        JSValue* getDirect(const Identifier& propertyName) const
    124124        {
    125             size_t offset = m_structureID->propertyMap().getOffset(propertyName);
     125            size_t offset = m_structureID->propertyMap().get(propertyName);
    126126            return offset != WTF::notFound ? m_propertyStorage[offset] : 0;
    127127        }
     
    129129        JSValue** getDirectLocation(const Identifier& propertyName)
    130130        {
    131             size_t offset = m_structureID->propertyMap().getOffset(propertyName);
     131            size_t offset = m_structureID->propertyMap().get(propertyName);
    132132            return offset != WTF::notFound ? locationForOffset(offset) : 0;
    133133        }
     
    135135        JSValue** getDirectLocation(const Identifier& propertyName, unsigned& attributes)
    136136        {
    137             size_t offset = m_structureID->propertyMap().getOffset(propertyName, attributes);
     137            size_t offset = m_structureID->propertyMap().get(propertyName, attributes);
    138138            return offset != WTF::notFound ? locationForOffset(offset) : 0;
    139139        }
     
    179179
    180180        static const size_t inlineStorageCapacity = 2;
     181        static const size_t nonInlineBaseStorageCapacity = 16;
    181182
    182183        static PassRefPtr<StructureID> createStructureID(JSValue* proto) { return StructureID::create(proto, TypeInfo(ObjectType)); }
     
    365366    ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this));
    366367
    367      if (m_structureID->isDictionary()) {
    368          unsigned currentAttributes;
    369          size_t offset = m_structureID->propertyMap().getOffset(propertyName, currentAttributes);
    370          if (offset != WTF::notFound) {
    371              if (checkReadOnly && currentAttributes & ReadOnly)
    372                  return;
    373              m_propertyStorage[offset] = value;
    374              slot.setExistingProperty(this, offset);
    375              return;
    376          }
    377 
    378          if (m_structureID->propertyMap().storageSize() == inlineStorageCapacity)
    379              allocatePropertyStorage(m_structureID->propertyMap().storageSize(), m_structureID->propertyMap().size());
    380          m_structureID->propertyMap().put(propertyName, value, attributes, checkReadOnly, this, slot, m_propertyStorage);
    381          m_structureID->clearEnumerationCache();
    382          return;
    383      }
     368    if (m_structureID->isDictionary()) {
     369        unsigned currentAttributes;
     370        size_t offset = m_structureID->propertyMap().get(propertyName, currentAttributes);
     371        if (offset != WTF::notFound) {
     372            if (checkReadOnly && currentAttributes & ReadOnly)
     373                return;
     374            m_propertyStorage[offset] = value;
     375            slot.setExistingProperty(this, offset);
     376            return;
     377        }
     378
     379        size_t currentCapacity = m_structureID->propertyStorageCapacity();
     380        offset = m_structureID->propertyMap().put(propertyName, attributes);
     381        if (m_structureID->propertyMap().storageSize() > m_structureID->propertyStorageCapacity()) {
     382            m_structureID->growPropertyStorageCapacity();
     383            allocatePropertyStorage(currentCapacity, m_structureID->propertyStorageCapacity());
     384        }
     385
     386        m_propertyStorage[offset] = value;
     387        slot.setNewProperty(this, offset);
     388        m_structureID->clearEnumerationCache();
     389        return;
     390    }
    384391
    385392    unsigned currentAttributes;
    386     size_t offset = m_structureID->propertyMap().getOffset(propertyName, currentAttributes);
     393    size_t offset = m_structureID->propertyMap().get(propertyName, currentAttributes);
    387394    if (offset != WTF::notFound) {
    388395        if (checkReadOnly && currentAttributes & ReadOnly)
     
    393400    }
    394401
    395      if (m_structureID->propertyMap().storageSize() == inlineStorageCapacity)
    396          allocatePropertyStorage(m_structureID->propertyMap().storageSize(), m_structureID->propertyMap().size());
    397 
    398      RefPtr<StructureID> structureID = StructureID::addPropertyTransition(m_structureID, propertyName, value, attributes, this, slot, m_propertyStorage);
    399      slot.setWasTransition(true);
    400      setStructureID(structureID.release());
     402    size_t currentCapacity = m_structureID->propertyStorageCapacity();
     403    RefPtr<StructureID> structureID = StructureID::addPropertyTransition(m_structureID, propertyName, attributes, offset);
     404    if (currentCapacity != structureID->propertyStorageCapacity())
     405        allocatePropertyStorage(currentCapacity, structureID->propertyStorageCapacity());
     406
     407    ASSERT(offset < structureID->propertyStorageCapacity());
     408    m_propertyStorage[offset] = value;
     409    slot.setNewProperty(this, offset);
     410    slot.setWasTransition(true);
     411    setStructureID(structureID.release());
    401412}
    402413
    403414inline void JSObject::transitionTo(StructureID* newStructureID)
    404415{
    405     StructureID::transitionTo(m_structureID, newStructureID, this);
     416    if (m_structureID->propertyStorageCapacity() != newStructureID->propertyStorageCapacity())
     417        allocatePropertyStorage(m_structureID->propertyStorageCapacity(), newStructureID->propertyStorageCapacity());
    406418    setStructureID(newStructureID);
    407419}
  • trunk/JavaScriptCore/kjs/PropertyMap.cpp

    r37321 r37370  
    7878#if !DO_PROPERTYMAP_CONSTENCY_CHECK
    7979
    80 inline void PropertyMap::checkConsistency(PropertyStorage&)
     80inline void PropertyMap::checkConsistency()
    8181{
    8282}
     
    9898    }
    9999
     100    m_deletedOffsets = other.m_deletedOffsets;
    100101    m_getterSetterFlag = other.m_getterSetterFlag;
    101102    return *this;
     
    115116}
    116117
    117 size_t PropertyMap::put(const Identifier& propertyName, JSValue* value, unsigned attributes, bool checkReadOnly, JSObject* slotBase, PutPropertySlot& slot, PropertyStorage& propertyStorage)
     118size_t PropertyMap::put(const Identifier& propertyName, unsigned attributes)
    118119{
    119120    ASSERT(!propertyName.isNull());
    120     ASSERT(value);
    121 
    122     checkConsistency(propertyStorage);
     121    ASSERT(get(propertyName) == WTF::notFound);
     122
     123    checkConsistency();
    123124
    124125    UString::Rep* rep = propertyName._ustring.rep();
    125126
    126127    if (!m_table)
    127         expand(propertyStorage);
     128        createTable();
    128129
    129130    // FIXME: Consider a fast case for tables with no deleted sentinels.
     
    143144            break;
    144145
    145         if (m_table->entries()[entryIndex - 1].key == rep) {
    146             if (checkReadOnly && (m_table->entries()[entryIndex - 1].attributes & ReadOnly))
    147                 return WTF::notFound;
    148             // Put a new value in an existing hash table entry.
    149             propertyStorage[entryIndex - 2] = value;
    150             // Attributes are intentionally not updated.
    151             slot.setExistingProperty(slotBase, entryIndex - 2);
    152             return entryIndex - 2;
    153         } else if (entryIndex == deletedSentinelIndex) {
     146        if (entryIndex == deletedSentinelIndex) {
    154147            // If we find a deleted-element sentinel, remember it for use later.
    155148            if (!foundDeletedElement) {
     
    194187    m_table->entries()[entryIndex - 1].attributes = attributes;
    195188    m_table->entries()[entryIndex - 1].index = ++m_table->lastIndexUsed;
     189
     190    unsigned newOffset;
     191    if (!m_deletedOffsets.isEmpty()) {
     192        newOffset = m_deletedOffsets.last();
     193        m_deletedOffsets.removeLast();
     194    } else
     195        newOffset = m_table->keyCount + m_table->deletedSentinelCount;
     196    m_table->entries()[entryIndex - 1].offset = newOffset;
     197
    196198    ++m_table->keyCount;
    197199
    198     propertyStorage[entryIndex - 2] = value;
    199 
    200200    if ((m_table->keyCount + m_table->deletedSentinelCount) * 2 >= m_table->size)
    201         expand(propertyStorage);
    202 
    203     checkConsistency(propertyStorage);
    204     slot.setNewProperty(slotBase, entryIndex - 2);
    205     return entryIndex - 2;
    206 }
    207 
    208 void PropertyMap::remove(const Identifier& propertyName, PropertyStorage& propertyStorage)
     201        expand();
     202
     203    checkConsistency();
     204    return newOffset;
     205}
     206
     207size_t PropertyMap::remove(const Identifier& propertyName)
    209208{
    210209    ASSERT(!propertyName.isNull());
    211210
    212     checkConsistency(propertyStorage);
     211    checkConsistency();
    213212
    214213    UString::Rep* rep = propertyName._ustring.rep();
    215214
    216215    if (!m_table)
    217         return;
     216        return WTF::notFound;
     217
    218218
    219219#if DUMP_PROPERTYMAP_STATS
     
    230230        entryIndex = m_table->entryIndices[i & m_table->sizeMask];
    231231        if (entryIndex == emptyEntryIndex)
    232             return;
     232            return WTF::notFound;
    233233
    234234        key = m_table->entries()[entryIndex - 1].key;
     
    253253    // the entry so we can iterate all the entries as needed.
    254254    m_table->entryIndices[i & m_table->sizeMask] = deletedSentinelIndex;
     255
     256    size_t offset = m_table->entries()[entryIndex - 1].offset;
     257
    255258    key->deref();
    256259    m_table->entries()[entryIndex - 1].key = 0;
    257260    m_table->entries()[entryIndex - 1].attributes = 0;
    258 
    259     propertyStorage[entryIndex - 2] = jsUndefined();
     261    m_table->entries()[entryIndex - 1].offset = 0;
     262    m_deletedOffsets.append(offset);
    260263
    261264    ASSERT(m_table->keyCount >= 1);
     
    264267
    265268    if (m_table->deletedSentinelCount * 4 >= m_table->size)
    266         rehash(propertyStorage);
    267 
    268     checkConsistency(propertyStorage);
    269 }
    270 
    271 size_t PropertyMap::getOffset(const Identifier& propertyName, unsigned& attributes)
     269        rehash();
     270
     271    checkConsistency();
     272    return offset;
     273}
     274
     275size_t PropertyMap::get(const Identifier& propertyName, unsigned& attributes)
    272276{
    273277    ASSERT(!propertyName.isNull());
     
    290294    if (rep == m_table->entries()[entryIndex - 1].key) {
    291295        attributes = m_table->entries()[entryIndex - 1].attributes;
    292         return entryIndex - 2;
     296        return m_table->entries()[entryIndex - 1].offset;
    293297    }
    294298
     
    312316        if (rep == m_table->entries()[entryIndex - 1].key) {
    313317            attributes = m_table->entries()[entryIndex - 1].attributes;
    314             return entryIndex - 2;
    315         }
    316     }
    317 }
    318 
    319 void PropertyMap::insert(const Entry& entry, JSValue* value, PropertyStorage& propertyStorage)
     318            return m_table->entries()[entryIndex - 1].offset;
     319        }
     320    }
     321}
     322
     323void PropertyMap::insert(const Entry& entry)
    320324{
    321325    ASSERT(m_table);
     
    351355    m_table->entries()[entryIndex - 1] = entry;
    352356
    353     propertyStorage[entryIndex - 2] = value;
    354 
    355357    ++m_table->keyCount;
    356358}
    357359
    358 void PropertyMap::expand(PropertyStorage& propertyStorage)
    359 {
    360     if (!m_table)
    361         createTable(propertyStorage);
    362     else
    363         rehash(m_table->size * 2, propertyStorage);
    364 }
    365 
    366 void PropertyMap::rehash(PropertyStorage& propertyStorage)
     360void PropertyMap::expand()
    367361{
    368362    ASSERT(m_table);
    369     ASSERT(m_table->size);
    370     rehash(m_table->size, propertyStorage);
    371 }
    372 
    373 void PropertyMap::createTable(PropertyStorage& propertyStorage)
     363    rehash(m_table->size * 2);
     364}
     365
     366void PropertyMap::createTable()
    374367{
    375368    const unsigned newTableSize = 16;
     
    377370    ASSERT(!m_table);
    378371
    379     checkConsistency(propertyStorage);
     372    checkConsistency();
    380373
    381374    m_table = static_cast<Table*>(fastZeroedMalloc(Table::allocationSize(newTableSize)));
     
    383376    m_table->sizeMask = newTableSize - 1;
    384377
    385     checkConsistency(propertyStorage);
    386 }
    387 
    388 void PropertyMap::rehash(unsigned newTableSize, PropertyStorage& propertyStorage)
     378    checkConsistency();
     379}
     380
     381void PropertyMap::rehash()
    389382{
    390383    ASSERT(m_table);
    391 
    392     checkConsistency(propertyStorage);
     384    ASSERT(m_table->size);
     385    rehash(m_table->size);
     386}
     387
     388void PropertyMap::rehash(unsigned newTableSize)
     389{
     390    ASSERT(m_table);
     391
     392    checkConsistency();
    393393
    394394    Table* oldTable = m_table;
    395     JSValue** oldPropertStorage = propertyStorage;
    396395
    397396    m_table = static_cast<Table*>(fastZeroedMalloc(Table::allocationSize(newTableSize)));
    398397    m_table->size = newTableSize;
    399398    m_table->sizeMask = newTableSize - 1;
    400 
    401     propertyStorage = new JSValue*[m_table->size];
    402399
    403400    unsigned lastIndexUsed = 0;
     
    406403        if (oldTable->entries()[i].key) {
    407404            lastIndexUsed = max(oldTable->entries()[i].index, lastIndexUsed);
    408             insert(oldTable->entries()[i], oldPropertStorage[i - 1], propertyStorage);
     405            insert(oldTable->entries()[i]);
    409406        }
    410407    }
     
    412409
    413410    fastFree(oldTable);
    414     delete [] oldPropertStorage;
    415 
    416     checkConsistency(propertyStorage);
     411
     412    checkConsistency();
    417413}
    418414
     
    486482#if DO_PROPERTYMAP_CONSTENCY_CHECK
    487483
    488 void PropertyMap::checkConsistency(PropertyStorage& propertyStorage)
     484void PropertyMap::checkConsistency()
    489485{
    490486    if (!m_table)
     
    526522    for (unsigned c = 1; c <= m_table->keyCount + m_table->deletedSentinelCount; ++c) {
    527523        UString::Rep* rep = m_table->entries()[c].key;
    528         if (!rep) {
    529             ASSERT(propertyStorage[c - 1]->isUndefined());
     524        if (!rep)
    530525            continue;
    531         }
    532526        ++nonEmptyEntryCount;
    533527        unsigned i = rep->computedHash();
  • trunk/JavaScriptCore/kjs/PropertyMap.h

    r37321 r37370  
    4343    struct PropertyMapEntry {
    4444        UString::Rep* key;
     45        unsigned offset;
    4546        unsigned attributes;
    4647        unsigned index;
     
    4849        PropertyMapEntry(UString::Rep* k, int a)
    4950            : key(k)
     51            , offset(0)
    5052            , attributes(a)
    5153            , index(0)
     
    9597        bool isEmpty() { return !m_table; }
    9698
    97         size_t put(const Identifier& propertyName, JSValue*, unsigned attributes, bool checkReadOnly, JSObject* slotBase, PutPropertySlot&, PropertyStorage&);
    98         void remove(const Identifier& propertyName, PropertyStorage&);
    99 
    100         size_t getOffset(const Identifier& propertyName);
    101         size_t getOffset(const Identifier& propertyName, unsigned& attributes);
     99        size_t get(const Identifier& propertyName);
     100        size_t get(const Identifier& propertyName, unsigned& attributes);
     101        size_t put(const Identifier& propertyName, unsigned attributes);
     102        size_t remove(const Identifier& propertyName);
    102103
    103104        void getEnumerablePropertyNames(PropertyNameArray&) const;
     
    115116        typedef PropertyMapHashTable Table;
    116117
    117         void expand(PropertyStorage&);
    118         void rehash(PropertyStorage&);
    119         void rehash(unsigned newTableSize, PropertyStorage&);
    120         void createTable(PropertyStorage&);
     118        void expand();
     119        void rehash();
     120        void rehash(unsigned newTableSize);
     121        void createTable();
    121122
    122         void insert(const Entry&, JSValue*, PropertyStorage&);
     123        void insert(const Entry&);
    123124
    124         void checkConsistency(PropertyStorage&);
     125        void checkConsistency();
    125126
    126127        Table* m_table;
     128        Vector<unsigned> m_deletedOffsets;
    127129        bool m_getterSetterFlag : 1;
    128130    };
     
    134136    }
    135137
    136     inline size_t PropertyMap::getOffset(const Identifier& propertyName)
     138    inline size_t PropertyMap::get(const Identifier& propertyName)
    137139    {
    138140        ASSERT(!propertyName.isNull());
     
    154156
    155157        if (rep == m_table->entries()[entryIndex - 1].key)
    156             return entryIndex - 2;
     158            return m_table->entries()[entryIndex - 1].offset;
    157159
    158160#if DUMP_PROPERTYMAP_STATS
     
    174176
    175177            if (rep == m_table->entries()[entryIndex - 1].key)
    176                 return entryIndex - 2;
     178                return m_table->entries()[entryIndex - 1].offset;
    177179        }
    178180    }
  • trunk/JavaScriptCore/kjs/StructureID.cpp

    r37321 r37370  
    4545    , m_nameInPrevious(0)
    4646    , m_transitionCount(0)
     47    , m_propertyStorageCapacity(JSObject::inlineStorageCapacity)
    4748    , m_cachedTransistionOffset(WTF::notFound)
    4849{
     
    103104}
    104105
    105 void StructureID::transitionTo(StructureID* oldStructureID, StructureID* newStructureID, JSObject* slotBase)
    106 {
    107     if (!slotBase->usingInlineStorage() && oldStructureID->m_propertyMap.size() != newStructureID->m_propertyMap.size())
    108         slotBase->allocatePropertyStorage(oldStructureID->m_propertyMap.size(), newStructureID->m_propertyMap.size());
    109 }
    110 
    111 PassRefPtr<StructureID> StructureID::addPropertyTransition(StructureID* structureID, const Identifier& propertyName, JSValue* value, unsigned attributes, JSObject* slotBase, PutPropertySlot& slot, PropertyStorage& propertyStorage)
     106void StructureID::growPropertyStorageCapacity()
     107{
     108    if (m_propertyStorageCapacity == JSObject::inlineStorageCapacity)
     109        m_propertyStorageCapacity = JSObject::nonInlineBaseStorageCapacity;
     110    else
     111        m_propertyStorageCapacity *= 2;
     112}
     113
     114PassRefPtr<StructureID> StructureID::addPropertyTransition(StructureID* structureID, const Identifier& propertyName, unsigned attributes, size_t& offset)
    112115{
    113116    ASSERT(!structureID->m_isDictionary);
     
    115118
    116119    if (StructureID* existingTransition = structureID->m_transitionTable.get(make_pair(propertyName.ustring().rep(), attributes))) {
    117         if (!slotBase->usingInlineStorage() && structureID->m_propertyMap.size() != existingTransition->m_propertyMap.size())
    118             slotBase->allocatePropertyStorage(structureID->m_propertyMap.size(), existingTransition->m_propertyMap.size());
    119 
    120         size_t offset = existingTransition->cachedTransistionOffset();
     120        offset = existingTransition->cachedTransistionOffset();
    121121        ASSERT(offset != WTF::notFound);
    122         propertyStorage[offset] = value;
    123         slot.setNewProperty(slotBase, offset);
    124 
    125122        return existingTransition;
    126123    }
     
    128125    if (structureID->m_transitionCount > s_maxTransitionLength) {
    129126        RefPtr<StructureID> transition = toDictionaryTransition(structureID);
    130         transition->m_propertyMap.put(propertyName, value, attributes, false, slotBase, slot, propertyStorage);
     127        offset = transition->m_propertyMap.put(propertyName, attributes);
     128        if (transition->m_propertyMap.storageSize() > transition->propertyStorageCapacity())
     129            transition->growPropertyStorageCapacity();
    131130        return transition.release();
    132131    }
     
    139138    transition->m_transitionCount = structureID->m_transitionCount + 1;
    140139    transition->m_propertyMap = structureID->m_propertyMap;
    141 
    142     size_t offset = transition->m_propertyMap.put(propertyName, value, attributes, false, slotBase, slot, propertyStorage);
     140    transition->m_propertyStorageCapacity = structureID->m_propertyStorageCapacity;
     141
     142    offset = transition->m_propertyMap.put(propertyName, attributes);
     143    if (transition->m_propertyMap.storageSize() > transition->propertyStorageCapacity())
     144        transition->growPropertyStorageCapacity();
     145
    143146    transition->setCachedTransistionOffset(offset);
    144147
     
    154157    transition->m_isDictionary = true;
    155158    transition->m_propertyMap = structureID->m_propertyMap;
     159    transition->m_propertyStorageCapacity = structureID->m_propertyStorageCapacity;
    156160    return transition.release();
    157161}
     
    173177    transition->m_transitionCount = structureID->m_transitionCount + 1;
    174178    transition->m_propertyMap = structureID->m_propertyMap;
     179    transition->m_propertyStorageCapacity = structureID->m_propertyStorageCapacity;
    175180    return transition.release();
    176181}
     
    181186    transition->m_transitionCount = structureID->m_transitionCount + 1;
    182187    transition->m_propertyMap = structureID->m_propertyMap;
     188    transition->m_propertyStorageCapacity = structureID->m_propertyStorageCapacity;
    183189    return transition.release();
    184190}
  • trunk/JavaScriptCore/kjs/StructureID.h

    r37321 r37370  
    8484
    8585        static PassRefPtr<StructureID> changePrototypeTransition(StructureID*, JSValue* prototype);
    86         static PassRefPtr<StructureID> addPropertyTransition(StructureID*, const Identifier& propertyName, JSValue*, unsigned attributes, JSObject* slotBase, PutPropertySlot&, PropertyStorage&);
     86        static PassRefPtr<StructureID> addPropertyTransition(StructureID*, const Identifier& propertyName, unsigned attributes, size_t& offset);
    8787        static PassRefPtr<StructureID> getterSetterTransition(StructureID*);
    8888        static PassRefPtr<StructureID> toDictionaryTransition(StructureID*);
     
    119119        size_t cachedTransistionOffset() const { return m_cachedTransistionOffset; }
    120120
     121        void growPropertyStorageCapacity();
     122        size_t propertyStorageCapacity() const { return m_propertyStorageCapacity; }
     123
    121124        void getEnumerablePropertyNames(ExecState*, PropertyNameArray&, JSObject*);
    122125        void clearEnumerationCache();
    123 
    124         static void transitionTo(StructureID* oldStructureID, StructureID* newStructureID, JSObject* slotBase);
    125126
    126127    private:
     
    149150
    150151        PropertyMap m_propertyMap;
     152        size_t m_propertyStorageCapacity;
    151153
    152154        size_t m_cachedTransistionOffset;
Note: See TracChangeset for help on using the changeset viewer.