Title: [92569] trunk/Source/_javascript_Core
Revision
92569
Author
[email protected]
Date
2011-08-06 20:44:45 -0700 (Sat, 06 Aug 2011)

Log 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).

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (92568 => 92569)


--- trunk/Source/_javascript_Core/ChangeLog	2011-08-07 01:09:23 UTC (rev 92568)
+++ trunk/Source/_javascript_Core/ChangeLog	2011-08-07 03:44:45 UTC (rev 92569)
@@ -1,3 +1,32 @@
+2011-08-06  Gavin Barraclough  <[email protected]>
+
+        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).
+
 2011-08-06  Aron Rosenberg  <[email protected]>
 
         Reviewed by Benjamin Poulain.

Modified: trunk/Source/_javascript_Core/dfg/DFGOperations.cpp (92568 => 92569)


--- trunk/Source/_javascript_Core/dfg/DFGOperations.cpp	2011-08-07 01:09:23 UTC (rev 92568)
+++ trunk/Source/_javascript_Core/dfg/DFGOperations.cpp	2011-08-07 03:44:45 UTC (rev 92569)
@@ -210,10 +210,8 @@
             if (propertyAsUInt32 == propertyAsDouble)
                 return getByVal(exec, base, propertyAsUInt32);
         } else if (property.isString()) {
-            Identifier propertyName(exec, asString(property)->value(exec));
-            PropertySlot slot(base);
-            if (base->fastGetOwnPropertySlot(exec, propertyName, slot))
-                return JSValue::encode(slot.getValue(exec, propertyName));
+            if (JSValue result = base->fastGetOwnProperty(exec, asString(property)->value(exec)))
+                return JSValue::encode(result);
         }
     }
 

Modified: trunk/Source/_javascript_Core/jit/JITStubs.cpp (92568 => 92569)


--- trunk/Source/_javascript_Core/jit/JITStubs.cpp	2011-08-07 01:09:23 UTC (rev 92568)
+++ trunk/Source/_javascript_Core/jit/JITStubs.cpp	2011-08-07 03:44:45 UTC (rev 92569)
@@ -2249,12 +2249,7 @@
     JSValue subscript = stackFrame.args[1].jsValue();
 
     if (LIKELY(baseValue.isCell() && subscript.isString())) {
-        Identifier propertyName(callFrame, asString(subscript)->value(callFrame));
-        PropertySlot slot(baseValue.asCell());
-        // JSString::value may have thrown, but we shouldn't find a property with a null identifier,
-        // so we should miss this case and wind up in the CHECK_FOR_EXCEPTION_AT_END, below.
-        if (baseValue.asCell()->fastGetOwnPropertySlot(callFrame, propertyName, slot)) {
-            JSValue result = slot.getValue(callFrame, propertyName);
+        if (JSValue result = baseValue.asCell()->fastGetOwnProperty(callFrame, asString(subscript)->value(callFrame))) {
             CHECK_FOR_EXCEPTION();
             return JSValue::encode(result);
         }

Modified: trunk/Source/_javascript_Core/runtime/JSCell.h (92568 => 92569)


--- trunk/Source/_javascript_Core/runtime/JSCell.h	2011-08-07 01:09:23 UTC (rev 92568)
+++ trunk/Source/_javascript_Core/runtime/JSCell.h	2011-08-07 03:44:45 UTC (rev 92569)
@@ -137,6 +137,7 @@
         // call this function, not its slower virtual counterpart. (For integer
         // property names, we want a similar interface with appropriate optimizations.)
         bool fastGetOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
+        JSValue fastGetOwnProperty(ExecState*, const UString&);
 
         static ptrdiff_t structureOffset()
         {

Modified: trunk/Source/_javascript_Core/runtime/JSObject.h (92568 => 92569)


--- trunk/Source/_javascript_Core/runtime/JSObject.h	2011-08-07 01:09:23 UTC (rev 92568)
+++ trunk/Source/_javascript_Core/runtime/JSObject.h	2011-08-07 03:44:45 UTC (rev 92569)
@@ -536,6 +536,22 @@
     return getOwnPropertySlot(exec, propertyName, slot);
 }
 
+// Fast call to get a property where we may not yet have converted the string to an
+// identifier. The first time we perform a property access with a given string, try
+// performing the property map lookup without forming an identifier. We detect this
+// case by checking whether the hash has yet been set for this string.
+ALWAYS_INLINE JSValue JSCell::fastGetOwnProperty(ExecState* exec, const UString& name)
+{
+    if (!m_structure->typeInfo().overridesGetOwnPropertySlot() && !m_structure->hasGetterSetterProperties()) {
+        size_t offset = name.impl()->hasHash()
+            ? m_structure->get(exec->globalData(), Identifier(exec, name))
+            : m_structure->get(exec->globalData(), name);
+        if (offset != WTF::notFound)
+            return asObject(this)->locationForOffset(offset)->get();
+    }
+    return JSValue();
+}
+
 // It may seem crazy to inline a function this large but it makes a big difference
 // since this is function very hot in variable lookup
 ALWAYS_INLINE bool JSObject::getPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)

Modified: trunk/Source/_javascript_Core/runtime/PropertyMapHashTable.h (92568 => 92569)


--- trunk/Source/_javascript_Core/runtime/PropertyMapHashTable.h	2011-08-07 01:09:23 UTC (rev 92568)
+++ trunk/Source/_javascript_Core/runtime/PropertyMapHashTable.h	2011-08-07 03:44:45 UTC (rev 92569)
@@ -154,7 +154,8 @@
     const_iterator end() const;
 
     // Find a value in the table.
-    find_iterator find(const KeyType& key);
+    find_iterator find(const KeyType&);
+    find_iterator findWithString(const KeyType&);
     // Add a value to the table
     std::pair<find_iterator, bool> add(const ValueType& entry);
     // Remove a value from the table.
@@ -324,6 +325,7 @@
 inline PropertyTable::find_iterator PropertyTable::find(const KeyType& key)
 {
     ASSERT(key);
+    ASSERT(key->isIdentifier());
     unsigned hash = key->existingHash();
     unsigned step = 0;
 
@@ -343,7 +345,7 @@
 #endif
 
         if (!step)
-            step =WTF::doubleHash(key->existingHash()) | 1;
+            step = WTF::doubleHash(key->existingHash()) | 1;
         hash += step;
 
 #if DUMP_PROPERTYMAP_STATS
@@ -352,6 +354,38 @@
     }
 }
 
+inline PropertyTable::find_iterator PropertyTable::findWithString(const KeyType& key)
+{
+    ASSERT(key);
+    ASSERT(!key->isIdentifier() && !key->hasHash());
+    unsigned hash = key->hash();
+    unsigned step = 0;
+
+#if DUMP_PROPERTYMAP_STATS
+    ++numProbes;
+#endif
+
+    while (true) {
+        unsigned entryIndex = m_index[hash & m_indexMask];
+        if (entryIndex == EmptyEntryIndex)
+            return std::make_pair((ValueType*)0, hash & m_indexMask);
+        if (equal(key, table()[entryIndex - 1].key))
+            return std::make_pair(&table()[entryIndex - 1], hash & m_indexMask);
+
+#if DUMP_PROPERTYMAP_STATS
+        ++numCollisions;
+#endif
+
+        if (!step)
+            step = WTF::doubleHash(key->existingHash()) | 1;
+        hash += step;
+
+#if DUMP_PROPERTYMAP_STATS
+        ++numRehashes;
+#endif
+    }
+}
+
 inline std::pair<PropertyTable::find_iterator, bool> PropertyTable::add(const ValueType& entry)
 {
     // Look for a value with a matching key already in the array.

Modified: trunk/Source/_javascript_Core/runtime/Structure.h (92568 => 92569)


--- trunk/Source/_javascript_Core/runtime/Structure.h	2011-08-07 01:09:23 UTC (rev 92568)
+++ trunk/Source/_javascript_Core/runtime/Structure.h	2011-08-07 03:44:45 UTC (rev 92569)
@@ -112,6 +112,7 @@
         bool isUsingInlineStorage() const;
 
         size_t get(JSGlobalData&, const Identifier& propertyName);
+        size_t get(JSGlobalData&, const UString& name);
         size_t get(JSGlobalData&, StringImpl* propertyName, unsigned& attributes, JSCell*& specificValue);
         size_t get(JSGlobalData& globalData, const Identifier& propertyName, unsigned& attributes, JSCell*& specificValue)
         {
@@ -265,6 +266,18 @@
         return entry ? entry->offset : notFound;
     }
 
+    inline size_t Structure::get(JSGlobalData& globalData, const UString& name)
+    {
+        ASSERT(structure()->classInfo() == &s_info);
+        materializePropertyMapIfNecessary(globalData);
+        if (!m_propertyTable)
+            return notFound;
+
+        PropertyMapEntry* entry = m_propertyTable->findWithString(name.impl()).first;
+        ASSERT(!entry || entry->offset >= m_anonymousSlotCount);
+        return entry ? entry->offset : notFound;
+    }
+
     inline bool JSCell::isObject() const
     {
         return m_structure->typeInfo().type() == ObjectType;

Modified: trunk/Source/_javascript_Core/wtf/text/StringImpl.h (92568 => 92569)


--- trunk/Source/_javascript_Core/wtf/text/StringImpl.h	2011-08-07 01:09:23 UTC (rev 92568)
+++ trunk/Source/_javascript_Core/wtf/text/StringImpl.h	2011-08-07 03:44:45 UTC (rev 92569)
@@ -238,6 +238,7 @@
 
     unsigned hash() const { if (!m_hash) m_hash = StringHasher::computeHash(m_data, m_length); return m_hash; }
     unsigned existingHash() const { ASSERT(m_hash); return m_hash; }
+    bool hasHash() const { return m_hash; }
 
     ALWAYS_INLINE void deref() { m_refCountAndFlags -= s_refCountIncrement; if (!(m_refCountAndFlags & (s_refCountMask | s_refCountFlagStatic))) delete this; }
     ALWAYS_INLINE bool hasOneRef() const { return (m_refCountAndFlags & (s_refCountMask | s_refCountFlagStatic)) == s_refCountIncrement; }
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to