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