Changeset 37370 in webkit for trunk/JavaScriptCore/kjs/JSObject.h


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.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • 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}
Note: See TracChangeset for help on using the changeset viewer.