Changeset 173188 in webkit


Ignore:
Timestamp:
Sep 2, 2014 3:29:59 PM (10 years ago)
Author:
akling@apple.com
Message:

Optimize own property GetByVals with rope string subscripts.
<https://webkit.org/b/136458>

For simple JSObjects that don't override getOwnPropertySlot to implement
custom properties, we have a fast path that grabs directly at the object
property storage.

Make this fast path even faster when the property name is an unresolved
rope string by using JSString::toExistingAtomicString(). This is faster
because it avoids allocating a new StringImpl if the string is already
a known Identifier, which is guaranteed to be the case if it's present
as an own property on the object.)

~10% speed-up on Dromaeo/dom-attr.html

Reviewed by Geoffrey Garen.

  • dfg/DFGOperations.cpp:
  • jit/JITOperations.cpp:

(JSC::getByVal):

  • llint/LLIntSlowPaths.cpp:

(JSC::LLInt::getByVal):

When using the fastGetOwnProperty() optimization, get the String
out of JSString by using toExistingAtomicString(). This avoids
StringImpl allocation and lets us bypass the PropertyTable lookup
entirely if no AtomicString is found.

  • runtime/JSCell.h:
  • runtime/JSCellInlines.h:

(JSC::JSCell::fastGetOwnProperty):

Make fastGetOwnProperty() take a PropertyName instead of a String.
This avoids churning the ref count, since we don't need to create
a temporary wrapper around the AtomicStringImpl* found in GetByVal.

  • runtime/PropertyName.h:

(JSC::PropertyName::PropertyName):

Add constructor: PropertyName(AtomicStringImpl*)

  • runtime/PropertyMapHashTable.h:

(JSC::PropertyTable::get):
(JSC::PropertyTable::findWithString): Deleted.

  • runtime/Structure.h:
  • runtime/StructureInlines.h:

(JSC::Structure::get):

Remove code for querying a PropertyTable with an unhashed string key
since the only client is now gone.

Location:
trunk/Source/JavaScriptCore
Files:
10 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r173179 r173188  
     12014-09-02  Andreas Kling  <akling@apple.com>
     2
     3        Optimize own property GetByVals with rope string subscripts.
     4        <https://webkit.org/b/136458>
     5
     6        For simple JSObjects that don't override getOwnPropertySlot to implement
     7        custom properties, we have a fast path that grabs directly at the object
     8        property storage.
     9
     10        Make this fast path even faster when the property name is an unresolved
     11        rope string by using JSString::toExistingAtomicString(). This is faster
     12        because it avoids allocating a new StringImpl if the string is already
     13        a known Identifier, which is guaranteed to be the case if it's present
     14        as an own property on the object.)
     15
     16        ~10% speed-up on Dromaeo/dom-attr.html
     17
     18        Reviewed by Geoffrey Garen.
     19
     20        * dfg/DFGOperations.cpp:
     21        * jit/JITOperations.cpp:
     22        (JSC::getByVal):
     23        * llint/LLIntSlowPaths.cpp:
     24        (JSC::LLInt::getByVal):
     25
     26            When using the fastGetOwnProperty() optimization, get the String
     27            out of JSString by using toExistingAtomicString(). This avoids
     28            StringImpl allocation and lets us bypass the PropertyTable lookup
     29            entirely if no AtomicString is found.
     30
     31        * runtime/JSCell.h:
     32        * runtime/JSCellInlines.h:
     33        (JSC::JSCell::fastGetOwnProperty):
     34
     35            Make fastGetOwnProperty() take a PropertyName instead of a String.
     36            This avoids churning the ref count, since we don't need to create
     37            a temporary wrapper around the AtomicStringImpl* found in GetByVal.
     38
     39        * runtime/PropertyName.h:
     40        (JSC::PropertyName::PropertyName):
     41
     42            Add constructor: PropertyName(AtomicStringImpl*)
     43
     44        * runtime/PropertyMapHashTable.h:
     45        (JSC::PropertyTable::get):
     46        (JSC::PropertyTable::findWithString): Deleted.
     47        * runtime/Structure.h:
     48        * runtime/StructureInlines.h:
     49        (JSC::Structure::get):
     50
     51            Remove code for querying a PropertyTable with an unhashed string key
     52            since the only client is now gone.
     53
    1542014-09-02  Dániel Bátyai  <dbatyai.u-szeged@partner.samsung.com>
    255
  • trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp

    r173120 r173188  
    298298            Structure& structure = *base->structure(vm);
    299299            if (JSCell::canUseFastGetOwnProperty(structure)) {
    300                 if (JSValue result = base->fastGetOwnProperty(vm, structure, asString(property)->value(exec)))
    301                     return JSValue::encode(result);
     300                if (AtomicStringImpl* existingAtomicString = asString(property)->toExistingAtomicString(exec)) {
     301                    if (JSValue result = base->fastGetOwnProperty(vm, structure, existingAtomicString))
     302                        return JSValue::encode(result);
     303                }
    302304            }
    303305        }
     
    328330        Structure& structure = *base->structure(vm);
    329331        if (JSCell::canUseFastGetOwnProperty(structure)) {
    330             if (JSValue result = base->fastGetOwnProperty(vm, structure, asString(property)->value(exec)))
    331                 return JSValue::encode(result);
     332            if (AtomicStringImpl* existingAtomicString = asString(property)->toExistingAtomicString(exec)) {
     333                if (JSValue result = base->fastGetOwnProperty(vm, structure, existingAtomicString))
     334                    return JSValue::encode(result);
     335            }
    332336        }
    333337    }
  • trunk/Source/JavaScriptCore/jit/JITOperations.cpp

    r173120 r173188  
    14241424        Structure& structure = *baseValue.asCell()->structure(vm);
    14251425        if (JSCell::canUseFastGetOwnProperty(structure)) {
    1426             if (JSValue result = baseValue.asCell()->fastGetOwnProperty(vm, structure, asString(subscript)->value(exec)))
    1427                 return result;
     1426            if (AtomicStringImpl* existingAtomicString = asString(subscript)->toExistingAtomicString(exec)) {
     1427                if (JSValue result = baseValue.asCell()->fastGetOwnProperty(vm, structure, existingAtomicString))
     1428                    return result;
     1429            }
    14281430        }
    14291431    }
  • trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp

    r173082 r173188  
    726726        Structure& structure = *baseValue.asCell()->structure(vm);
    727727        if (JSCell::canUseFastGetOwnProperty(structure)) {
    728             if (JSValue result = baseValue.asCell()->fastGetOwnProperty(vm, structure, asString(subscript)->value(exec)))
    729                 return result;
     728            if (AtomicStringImpl* existingAtomicString = asString(subscript)->toExistingAtomicString(exec)) {
     729                if (JSValue result = baseValue.asCell()->fastGetOwnProperty(vm, structure, existingAtomicString))
     730                    return result;
     731            }
    730732        }
    731733    }
  • trunk/Source/JavaScriptCore/runtime/JSCell.h

    r172196 r173188  
    4040class CopyVisitor;
    4141class ExecState;
     42class Identifier;
    4243class JSArrayBufferView;
    4344class JSDestructibleObject;
     
    142143
    143144    static bool canUseFastGetOwnProperty(const Structure&);
    144     JSValue fastGetOwnProperty(VM&, Structure&, const String&);
     145    JSValue fastGetOwnProperty(VM&, Structure&, PropertyName);
    145146
    146147    enum GCData : uint8_t {
  • trunk/Source/JavaScriptCore/runtime/JSCellInlines.h

    r171939 r173188  
    210210}
    211211
    212 // Fast call to get a property where we may not yet have converted the string to an
    213 // identifier. The first time we perform a property access with a given string, try
    214 // performing the property map lookup without forming an identifier. We detect this
    215 // case by checking whether the hash has yet been set for this string.
    216 ALWAYS_INLINE JSValue JSCell::fastGetOwnProperty(VM& vm, Structure& structure, const String& name)
     212ALWAYS_INLINE JSValue JSCell::fastGetOwnProperty(VM& vm, Structure& structure, PropertyName name)
    217213{
    218214    ASSERT(canUseFastGetOwnProperty(structure));
    219     PropertyOffset offset = name.impl()->hasHash()
    220         ? structure.get(vm, Identifier(&vm, name))
    221         : structure.get(vm, name);
     215    PropertyOffset offset = structure.get(vm, name);
    222216    if (offset != invalidOffset)
    223217        return asObject(this)->locationForOffset(offset)->get();
  • trunk/Source/JavaScriptCore/runtime/PropertyMapHashTable.h

    r172129 r173188  
    172172    // Find a value in the table.
    173173    find_iterator find(const KeyType&);
    174     find_iterator findWithString(const KeyType&);
    175174    ValueType* get(const KeyType&);
    176175    // Add a value to the table
     
    350349}
    351350
    352 inline PropertyTable::find_iterator PropertyTable::findWithString(const KeyType& key)
    353 {
    354     ASSERT(key);
    355     ASSERT(!key->isAtomic() && !key->hasHash());
    356     unsigned hash = key->hash();
    357     unsigned step = 0;
    358 
    359 #if DUMP_PROPERTYMAP_STATS
    360     ++propertyMapHashTableStats->numLookups;
    361 #endif
    362 
    363     while (true) {
    364         unsigned entryIndex = m_index[hash & m_indexMask];
    365         if (entryIndex == EmptyEntryIndex)
    366             return std::make_pair((ValueType*)0, hash & m_indexMask);
    367         const KeyType& keyInMap = table()[entryIndex - 1].key;
    368         if (equal(key, keyInMap) && keyInMap->isAtomic())
    369             return std::make_pair(&table()[entryIndex - 1], hash & m_indexMask);
    370 
    371 #if DUMP_PROPERTYMAP_STATS
    372         ++propertyMapHashTableStats->numLookupProbing;
    373 #endif
    374 
    375         if (!step)
    376             step = WTF::doubleHash(key->existingHash()) | 1;
    377         hash += step;
    378     }
    379 }
    380 
    381351inline std::pair<PropertyTable::find_iterator, bool> PropertyTable::add(const ValueType& entry, PropertyOffset& offset, EffectOnPropertyOffset offsetEffect)
    382352{
  • trunk/Source/JavaScriptCore/runtime/PropertyName.h

    r172129 r173188  
    7979class PropertyName {
    8080public:
    81     PropertyName(const Identifier& propertyName)
    82         : m_impl(static_cast<AtomicStringImpl*>(propertyName.impl()))
     81    PropertyName(AtomicStringImpl* propertyName)
     82        : m_impl(propertyName)
    8383    {
    8484        ASSERT(!m_impl || m_impl->isAtomic());
     85    }
     86
     87    PropertyName(const Identifier& propertyName)
     88        : PropertyName(static_cast<AtomicStringImpl*>(propertyName.impl()))
     89    {
    8590    }
    8691
  • trunk/Source/JavaScriptCore/runtime/Structure.h

    r172176 r173188  
    261261
    262262    PropertyOffset get(VM&, PropertyName);
    263     PropertyOffset get(VM&, const WTF::String& name);
    264263    PropertyOffset get(VM&, PropertyName, unsigned& attributes);
    265264
  • trunk/Source/JavaScriptCore/runtime/StructureInlines.h

    r172176 r173188  
    8686    return entry ? entry->offset : invalidOffset;
    8787}
    88 
    89 ALWAYS_INLINE PropertyOffset Structure::get(VM& vm, const WTF::String& name)
    90 {
    91     ASSERT(!isCompilationThread());
    92     ASSERT(structure()->classInfo() == info());
    93     PropertyTable* propertyTable;
    94     materializePropertyMapIfNecessary(vm, propertyTable);
    95     if (!propertyTable)
    96         return invalidOffset;
    97 
    98     PropertyMapEntry* entry = propertyTable->findWithString(name.impl()).first;
    99     return entry ? entry->offset : invalidOffset;
    100 }
    10188   
    10289ALWAYS_INLINE PropertyOffset Structure::get(VM& vm, PropertyName propertyName, unsigned& attributes)
Note: See TracChangeset for help on using the changeset viewer.