Changeset 92569 in webkit


Ignore:
Timestamp:
Aug 6, 2011 8:44:45 PM (13 years ago)
Author:
barraclough@apple.com
Message:

https://bugs.webkit.org/show_bug.cgi?id=65821
Don't form identifiers the first time a string is used as a property name.

Reviewed by Oliver Hunt.

This is a 1% win on SunSpider.

  • dfg/DFGOperations.cpp:
    • Use fastGetOwnProperty.
  • jit/JITStubs.cpp:

(JSC::DEFINE_STUB_FUNCTION):

  • Use fastGetOwnProperty.
  • runtime/JSCell.h:
  • runtime/JSObject.h:

(JSC::JSCell::fastGetOwnProperty):

  • Fast call to get a property without creating an identifier the first time.
  • runtime/PropertyMapHashTable.h:

(JSC::PropertyTable::find):
(JSC::PropertyTable::findWithString):

  • Add interface to look up by either strinsg or identifiers.
  • runtime/Structure.h:

(JSC::Structure::get):

  • Add a get() call that takes a UString, not an Identifier.
  • wtf/text/StringImpl.h:

(WTF::StringImpl::hasHash):

  • Add a call to check if the has has been set (to detect the first use as a property name).
Location:
trunk/Source/JavaScriptCore
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r92555 r92569  
     12011-08-06  Gavin Barraclough  <barraclough@apple.com>
     2
     3        https://bugs.webkit.org/show_bug.cgi?id=65821
     4        Don't form identifiers the first time a string is used as a property name.
     5
     6        Reviewed by Oliver Hunt.
     7
     8        This is a 1% win on SunSpider.
     9
     10        * dfg/DFGOperations.cpp:
     11            - Use fastGetOwnProperty.
     12        * jit/JITStubs.cpp:
     13        (JSC::DEFINE_STUB_FUNCTION):
     14            - Use fastGetOwnProperty.
     15        * runtime/JSCell.h:
     16        * runtime/JSObject.h:
     17        (JSC::JSCell::fastGetOwnProperty):
     18            - Fast call to get a property without creating an identifier the first time.
     19        * runtime/PropertyMapHashTable.h:
     20        (JSC::PropertyTable::find):
     21        (JSC::PropertyTable::findWithString):
     22            - Add interface to look up by either strinsg or identifiers.
     23        * runtime/Structure.h:
     24        (JSC::Structure::get):
     25            - Add a get() call that takes a UString, not an Identifier.
     26        * wtf/text/StringImpl.h:
     27        (WTF::StringImpl::hasHash):
     28            - Add a call to check if the has has been set (to detect the first use as a property name).
     29
    1302011-08-06  Aron Rosenberg  <arosenberg@logitech.com>
    231
  • trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp

    r91883 r92569  
    211211                return getByVal(exec, base, propertyAsUInt32);
    212212        } else if (property.isString()) {
    213             Identifier propertyName(exec, asString(property)->value(exec));
    214             PropertySlot slot(base);
    215             if (base->fastGetOwnPropertySlot(exec, propertyName, slot))
    216                 return JSValue::encode(slot.getValue(exec, propertyName));
     213            if (JSValue result = base->fastGetOwnProperty(exec, asString(property)->value(exec)))
     214                return JSValue::encode(result);
    217215        }
    218216    }
  • trunk/Source/JavaScriptCore/jit/JITStubs.cpp

    r91903 r92569  
    22502250
    22512251    if (LIKELY(baseValue.isCell() && subscript.isString())) {
    2252         Identifier propertyName(callFrame, asString(subscript)->value(callFrame));
    2253         PropertySlot slot(baseValue.asCell());
    2254         // JSString::value may have thrown, but we shouldn't find a property with a null identifier,
    2255         // so we should miss this case and wind up in the CHECK_FOR_EXCEPTION_AT_END, below.
    2256         if (baseValue.asCell()->fastGetOwnPropertySlot(callFrame, propertyName, slot)) {
    2257             JSValue result = slot.getValue(callFrame, propertyName);
     2252        if (JSValue result = baseValue.asCell()->fastGetOwnProperty(callFrame, asString(subscript)->value(callFrame))) {
    22582253            CHECK_FOR_EXCEPTION();
    22592254            return JSValue::encode(result);
  • trunk/Source/JavaScriptCore/runtime/JSCell.h

    r92233 r92569  
    138138        // property names, we want a similar interface with appropriate optimizations.)
    139139        bool fastGetOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
     140        JSValue fastGetOwnProperty(ExecState*, const UString&);
    140141
    141142        static ptrdiff_t structureOffset()
  • trunk/Source/JavaScriptCore/runtime/JSObject.h

    r91199 r92569  
    537537}
    538538
     539// Fast call to get a property where we may not yet have converted the string to an
     540// identifier. The first time we perform a property access with a given string, try
     541// performing the property map lookup without forming an identifier. We detect this
     542// case by checking whether the hash has yet been set for this string.
     543ALWAYS_INLINE JSValue JSCell::fastGetOwnProperty(ExecState* exec, const UString& name)
     544{
     545    if (!m_structure->typeInfo().overridesGetOwnPropertySlot() && !m_structure->hasGetterSetterProperties()) {
     546        size_t offset = name.impl()->hasHash()
     547            ? m_structure->get(exec->globalData(), Identifier(exec, name))
     548            : m_structure->get(exec->globalData(), name);
     549        if (offset != WTF::notFound)
     550            return asObject(this)->locationForOffset(offset)->get();
     551    }
     552    return JSValue();
     553}
     554
    539555// It may seem crazy to inline a function this large but it makes a big difference
    540556// since this is function very hot in variable lookup
  • trunk/Source/JavaScriptCore/runtime/PropertyMapHashTable.h

    r86499 r92569  
    155155
    156156    // Find a value in the table.
    157     find_iterator find(const KeyType& key);
     157    find_iterator find(const KeyType&);
     158    find_iterator findWithString(const KeyType&);
    158159    // Add a value to the table
    159160    std::pair<find_iterator, bool> add(const ValueType& entry);
     
    325326{
    326327    ASSERT(key);
     328    ASSERT(key->isIdentifier());
    327329    unsigned hash = key->existingHash();
    328330    unsigned step = 0;
     
    344346
    345347        if (!step)
    346             step =WTF::doubleHash(key->existingHash()) | 1;
     348            step = WTF::doubleHash(key->existingHash()) | 1;
     349        hash += step;
     350
     351#if DUMP_PROPERTYMAP_STATS
     352        ++numRehashes;
     353#endif
     354    }
     355}
     356
     357inline PropertyTable::find_iterator PropertyTable::findWithString(const KeyType& key)
     358{
     359    ASSERT(key);
     360    ASSERT(!key->isIdentifier() && !key->hasHash());
     361    unsigned hash = key->hash();
     362    unsigned step = 0;
     363
     364#if DUMP_PROPERTYMAP_STATS
     365    ++numProbes;
     366#endif
     367
     368    while (true) {
     369        unsigned entryIndex = m_index[hash & m_indexMask];
     370        if (entryIndex == EmptyEntryIndex)
     371            return std::make_pair((ValueType*)0, hash & m_indexMask);
     372        if (equal(key, table()[entryIndex - 1].key))
     373            return std::make_pair(&table()[entryIndex - 1], hash & m_indexMask);
     374
     375#if DUMP_PROPERTYMAP_STATS
     376        ++numCollisions;
     377#endif
     378
     379        if (!step)
     380            step = WTF::doubleHash(key->existingHash()) | 1;
    347381        hash += step;
    348382
  • trunk/Source/JavaScriptCore/runtime/Structure.h

    r92233 r92569  
    113113
    114114        size_t get(JSGlobalData&, const Identifier& propertyName);
     115        size_t get(JSGlobalData&, const UString& name);
    115116        size_t get(JSGlobalData&, StringImpl* propertyName, unsigned& attributes, JSCell*& specificValue);
    116117        size_t get(JSGlobalData& globalData, const Identifier& propertyName, unsigned& attributes, JSCell*& specificValue)
     
    266267    }
    267268
     269    inline size_t Structure::get(JSGlobalData& globalData, const UString& name)
     270    {
     271        ASSERT(structure()->classInfo() == &s_info);
     272        materializePropertyMapIfNecessary(globalData);
     273        if (!m_propertyTable)
     274            return notFound;
     275
     276        PropertyMapEntry* entry = m_propertyTable->findWithString(name.impl()).first;
     277        ASSERT(!entry || entry->offset >= m_anonymousSlotCount);
     278        return entry ? entry->offset : notFound;
     279    }
     280
    268281    inline bool JSCell::isObject() const
    269282    {
  • trunk/Source/JavaScriptCore/wtf/text/StringImpl.h

    r91913 r92569  
    239239    unsigned hash() const { if (!m_hash) m_hash = StringHasher::computeHash(m_data, m_length); return m_hash; }
    240240    unsigned existingHash() const { ASSERT(m_hash); return m_hash; }
     241    bool hasHash() const { return m_hash; }
    241242
    242243    ALWAYS_INLINE void deref() { m_refCountAndFlags -= s_refCountIncrement; if (!(m_refCountAndFlags & (s_refCountMask | s_refCountFlagStatic))) delete this; }
Note: See TracChangeset for help on using the changeset viewer.