Title: [102631] trunk/Source/_javascript_Core
Revision
102631
Author
msab...@apple.com
Date
2011-12-12 15:21:51 -0800 (Mon, 12 Dec 2011)

Log Message

Eliminate Duplicate word at a time equal code in StringImpl.cpp and StringHash.h
https://bugs.webkit.org/show_bug.cgi?id=73622

Reviewed by Oliver Hunt.

Moved equal(charType1 *, charType2, unsigned) template methods
from static StringImpl.cpp to StringImpl.h and then replaced the
processor specific character comparison code in StringHash::equal
with calls to these methods.

This change is worth 3% on SunSpider string-unpack-code as reported
by the SunSpider command line harness.  No other tests appear to
have measurable performance changes.

* wtf/text/AtomicString.h:
(WTF::operator==):
* wtf/text/StringHash.h:
(WTF::StringHash::equal):
* wtf/text/StringImpl.cpp:
* wtf/text/StringImpl.h:
(WTF::LChar):
(WTF::UChar):
(WTF::equal):

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (102630 => 102631)


--- trunk/Source/_javascript_Core/ChangeLog	2011-12-12 23:17:52 UTC (rev 102630)
+++ trunk/Source/_javascript_Core/ChangeLog	2011-12-12 23:21:51 UTC (rev 102631)
@@ -1,3 +1,29 @@
+2011-12-12  Michael Saboff  <msab...@apple.com>
+
+        Eliminate Duplicate word at a time equal code in StringImpl.cpp and StringHash.h
+        https://bugs.webkit.org/show_bug.cgi?id=73622
+
+        Reviewed by Oliver Hunt.
+
+        Moved equal(charType1 *, charType2, unsigned) template methods
+        from static StringImpl.cpp to StringImpl.h and then replaced the
+        processor specific character comparison code in StringHash::equal
+        with calls to these methods.
+
+        This change is worth 3% on SunSpider string-unpack-code as reported
+        by the SunSpider command line harness.  No other tests appear to
+        have measurable performance changes.
+
+        * wtf/text/AtomicString.h:
+        (WTF::operator==):
+        * wtf/text/StringHash.h:
+        (WTF::StringHash::equal):
+        * wtf/text/StringImpl.cpp:
+        * wtf/text/StringImpl.h:
+        (WTF::LChar):
+        (WTF::UChar):
+        (WTF::equal):
+
 2011-12-12  Filip Pizlo  <fpi...@apple.com>
 
         ARMv7 version of DFG soft modulo does register allocation inside of control flow

Modified: trunk/Source/_javascript_Core/wtf/text/AtomicString.h (102630 => 102631)


--- trunk/Source/_javascript_Core/wtf/text/AtomicString.h	2011-12-12 23:17:52 UTC (rev 102630)
+++ trunk/Source/_javascript_Core/wtf/text/AtomicString.h	2011-12-12 23:21:51 UTC (rev 102631)
@@ -139,7 +139,7 @@
 inline bool operator==(const AtomicString& a, const AtomicString& b) { return a.impl() == b.impl(); }
 bool operator==(const AtomicString&, const LChar*);
 inline bool operator==(const AtomicString& a, const char* b) { return WTF::equal(a.impl(), reinterpret_cast<const LChar*>(b)); }
-inline bool operator==(const AtomicString& a, const Vector<UChar>& b) { return a.impl() && equal(a.impl(), b.data(), b.size()); }    
+inline bool operator==(const AtomicString& a, const Vector<UChar>& b) { return a.impl() && equal(static_cast<StringImpl*>(a.impl()), b.data(), b.size()); }    
 inline bool operator==(const AtomicString& a, const String& b) { return equal(a.impl(), b.impl()); }
 inline bool operator==(const LChar* a, const AtomicString& b) { return b == a; }
 inline bool operator==(const String& a, const AtomicString& b) { return equal(a.impl(), b.impl()); }

Modified: trunk/Source/_javascript_Core/wtf/text/StringHash.h (102630 => 102631)


--- trunk/Source/_javascript_Core/wtf/text/StringHash.h	2011-12-12 23:17:52 UTC (rev 102630)
+++ trunk/Source/_javascript_Core/wtf/text/StringHash.h	2011-12-12 23:21:51 UTC (rev 102631)
@@ -56,84 +56,19 @@
             if (a->is8Bit()) {
                 if (b->is8Bit()) {
                     // Both a & b are 8 bit.
-                    const LChar* aChars = a->characters8();
-                    const LChar* bChars = b->characters8();
-
-                    unsigned i = 0;
-
-                    // FIXME: perhaps we should have a more abstract macro that indicates when
-                    // going 4 bytes at a time is unsafe
-#if (CPU(X86) || CPU(X86_64))
-                    const unsigned charsPerInt = sizeof(uint32_t) / sizeof(char);
-                    
-                    if (aLength > charsPerInt) {
-                        unsigned stopCount = aLength & ~(charsPerInt - 1);
-                        
-                        const uint32_t* aIntCharacters = reinterpret_cast<const uint32_t*>(aChars);
-                        const uint32_t* bIntCharacters = reinterpret_cast<const uint32_t*>(bChars);
-                        for (unsigned j = 0; i < stopCount; i += charsPerInt, ++j) {
-                            if (aIntCharacters[j] != bIntCharacters[j])
-                                return false;
-                        }
-                    }
-#endif
-                    for (; i < aLength; ++i) {
-                        if (aChars[i] != bChars[i])
-                            return false;
-                    }
-                    
-                    return true;
+                    return WTF::equal(a->characters8(), b->characters8(), aLength);
                 }
 
                 // We know that a is 8 bit & b is 16 bit.
-                const LChar* aChars = a->characters8();
-                const UChar* bChars = b->characters16();
-                for (unsigned i = 0; i != aLength; ++i) {
-                    if (*aChars++ != *bChars++)
-                        return false;
-                }
-
-                return true;
+                return WTF::equal(a->characters8(), b->characters16(), aLength);
             }
 
             if (b->is8Bit()) {
                 // We know that a is 8 bit and b is 16 bit.
-                const UChar* aChars = a->characters16();
-                const LChar* bChars = b->characters8();
-                for (unsigned i = 0; i != aLength; ++i) {
-                    if (*aChars++ != *bChars++)
-                        return false;
-                }
-
-                return true;
+                return WTF::equal(a->characters16(), b->characters8(), aLength);
             }
 
-            // Both a & b are 16 bit.
-            // FIXME: perhaps we should have a more abstract macro that indicates when
-            // going 4 bytes at a time is unsafe
-#if CPU(ARM) || CPU(SH4) || CPU(MIPS) || CPU(SPARC)
-            const UChar* aChars = a->characters16();
-            const UChar* bChars = b->characters16();
-            for (unsigned i = 0; i != aLength; ++i) {
-                if (*aChars++ != *bChars++)
-                    return false;
-            }
-            return true;
-#else
-            /* Do it 4-bytes-at-a-time on architectures where it's safe */
-            const uint32_t* aChars = reinterpret_cast<const uint32_t*>(a->characters16());
-            const uint32_t* bChars = reinterpret_cast<const uint32_t*>(b->characters16());
-
-            unsigned halfLength = aLength >> 1;
-            for (unsigned i = 0; i != halfLength; ++i)
-                if (*aChars++ != *bChars++)
-                    return false;
-
-            if (aLength & 1 && *reinterpret_cast<const uint16_t*>(aChars) != *reinterpret_cast<const uint16_t*>(bChars))
-                return false;
-
-            return true;
-#endif
+            return WTF::equal(a->characters16(), b->characters16(), aLength);
         }
 
         static unsigned hash(const RefPtr<StringImpl>& key) { return key->hash(); }

Modified: trunk/Source/_javascript_Core/wtf/text/StringImpl.cpp (102630 => 102631)


--- trunk/Source/_javascript_Core/wtf/text/StringImpl.cpp	2011-12-12 23:17:52 UTC (rev 102630)
+++ trunk/Source/_javascript_Core/wtf/text/StringImpl.cpp	2011-12-12 23:21:51 UTC (rev 102631)
@@ -715,133 +715,6 @@
     return charactersToFloat(characters16(), m_length, ok, didReadNumber);
 }
 
-// Do comparisons 8 or 4 bytes-at-a-time on architectures where it's safe.
-#if CPU(X86_64)
-ALWAYS_INLINE static bool equal(const LChar* a, const LChar* b, unsigned length)
-{
-    unsigned dwordLength = length >> 3;
-
-    if (dwordLength) {
-        const uint64_t* aDWordCharacters = reinterpret_cast<const uint64_t*>(a);
-        const uint64_t* bDWordCharacters = reinterpret_cast<const uint64_t*>(b);
-
-        for (unsigned i = 0; i != dwordLength; ++i) {
-            if (*aDWordCharacters++ != *bDWordCharacters++)
-                return false;
-        }
-
-        a = reinterpret_cast<const LChar*>(aDWordCharacters);
-        b = reinterpret_cast<const LChar*>(bDWordCharacters);
-    }
-
-    if (length & 4) {
-        if (*reinterpret_cast<const uint32_t*>(a) != *reinterpret_cast<const uint32_t*>(b))
-            return false;
-
-        a += 4;
-        b += 4;
-    }
-
-    if (length & 2) {
-        if (*reinterpret_cast<const uint16_t*>(a) != *reinterpret_cast<const uint16_t*>(b))
-            return false;
-
-        a += 2;
-        b += 2;
-    }
-
-    if (length & 1 && (*a != *b))
-        return false;
-
-    return true;
-}
-
-ALWAYS_INLINE static bool equal(const UChar* a, const UChar* b, unsigned length)
-{
-    unsigned dwordLength = length >> 2;
-
-    if (dwordLength) {
-        const uint64_t* aDWordCharacters = reinterpret_cast<const uint64_t*>(a);
-        const uint64_t* bDWordCharacters = reinterpret_cast<const uint64_t*>(b);
-
-        for (unsigned i = 0; i != dwordLength; ++i) {
-            if (*aDWordCharacters++ != *bDWordCharacters++)
-                return false;
-        }
-
-        a = reinterpret_cast<const UChar*>(aDWordCharacters);
-        b = reinterpret_cast<const UChar*>(bDWordCharacters);
-    }
-
-    if (length & 2) {
-        if (*reinterpret_cast<const uint32_t*>(a) != *reinterpret_cast<const uint32_t*>(b))
-            return false;
-
-        a += 2;
-        b += 2;
-    }
-
-    if (length & 1 && (*a != *b))
-        return false;
-
-    return true;
-}
-#elif CPU(X86)
-ALWAYS_INLINE static bool equal(const LChar* a, const LChar* b, unsigned length)
-{
-    const uint32_t* aCharacters = reinterpret_cast<const uint32_t*>(a);
-    const uint32_t* bCharacters = reinterpret_cast<const uint32_t*>(b);
-
-    unsigned wordLength = length >> 2;
-    for (unsigned i = 0; i != wordLength; ++i) {
-        if (*aCharacters++ != *bCharacters++)
-            return false;
-    }
-
-    length &= 3;
-
-    if (length) {
-        const LChar* aRemainder = reinterpret_cast<const LChar*>(aCharacters);
-        const LChar* bRemainder = reinterpret_cast<const LChar*>(bCharacters);
-
-        for (unsigned i = 0; i <  length; ++i) {
-            if (aRemainder[i] != bRemainder[i])
-                return false;
-        }
-    }
-
-    return true;
-}
-
-ALWAYS_INLINE static bool equal(const UChar* a, const UChar* b, unsigned length)
-{
-    const uint32_t* aCharacters = reinterpret_cast<const uint32_t*>(a);
-    const uint32_t* bCharacters = reinterpret_cast<const uint32_t*>(b);
-
-    unsigned wordLength = length >> 1;
-    for (unsigned i = 0; i != wordLength; ++i) {
-        if (*aCharacters++ != *bCharacters++)
-            return false;
-    }
-
-    if (length & 1 && *reinterpret_cast<const UChar*>(aCharacters) != *reinterpret_cast<const UChar*>(bCharacters))
-        return false;
-
-    return true;
-}
-#endif
-
-template <typename CharTypeL, typename CharTypeR>
-ALWAYS_INLINE static bool equal(const CharTypeL* a, const CharTypeR* b, unsigned length)
-{
-    for (unsigned i = 0; i != length; ++i) {
-        if (a[i] != b[i])
-            return false;
-    }
-
-    return true;
-}
-
 bool equalIgnoringCase(const UChar* a, const LChar* b, unsigned length)
 {
     while (length--) {

Modified: trunk/Source/_javascript_Core/wtf/text/StringImpl.h (102630 => 102631)


--- trunk/Source/_javascript_Core/wtf/text/StringImpl.h	2011-12-12 23:17:52 UTC (rev 102630)
+++ trunk/Source/_javascript_Core/wtf/text/StringImpl.h	2011-12-12 23:21:51 UTC (rev 102631)
@@ -562,7 +562,140 @@
 inline bool equal(const LChar* a, StringImpl* b) { return equal(b, a); }
 inline bool equal(const char* a, StringImpl* b) { return equal(b, reinterpret_cast<const LChar*>(a)); }
 bool equal(const StringImpl*, const UChar*, unsigned);
+template <typename CharTypeL, typename CharTypeR>
+    ALWAYS_INLINE bool equal(const CharTypeL*, const CharTypeR*, unsigned);
 
+// Do comparisons 8 or 4 bytes-at-a-time on architectures where it's safe.
+#if CPU(X86_64)
+template <>
+ALWAYS_INLINE bool equal<LChar, LChar>(const LChar* a, const LChar* b, unsigned length)
+{
+    unsigned dwordLength = length >> 3;
+    
+    if (dwordLength) {
+        const uint64_t* aDWordCharacters = reinterpret_cast<const uint64_t*>(a);
+        const uint64_t* bDWordCharacters = reinterpret_cast<const uint64_t*>(b);
+        
+        for (unsigned i = 0; i != dwordLength; ++i) {
+            if (*aDWordCharacters++ != *bDWordCharacters++)
+                return false;
+        }
+        
+        a = reinterpret_cast<const LChar*>(aDWordCharacters);
+        b = reinterpret_cast<const LChar*>(bDWordCharacters);
+    }
+    
+    if (length & 4) {
+        if (*reinterpret_cast<const uint32_t*>(a) != *reinterpret_cast<const uint32_t*>(b))
+            return false;
+        
+        a += 4;
+        b += 4;
+    }
+    
+    if (length & 2) {
+        if (*reinterpret_cast<const uint16_t*>(a) != *reinterpret_cast<const uint16_t*>(b))
+            return false;
+        
+        a += 2;
+        b += 2;
+    }
+    
+    if (length & 1 && (*a != *b))
+        return false;
+    
+    return true;
+}
+
+template <>
+ALWAYS_INLINE bool equal<UChar, UChar>(const UChar* a, const UChar* b, unsigned length)
+{
+    unsigned dwordLength = length >> 2;
+    
+    if (dwordLength) {
+        const uint64_t* aDWordCharacters = reinterpret_cast<const uint64_t*>(a);
+        const uint64_t* bDWordCharacters = reinterpret_cast<const uint64_t*>(b);
+        
+        for (unsigned i = 0; i != dwordLength; ++i) {
+            if (*aDWordCharacters++ != *bDWordCharacters++)
+                return false;
+        }
+        
+        a = reinterpret_cast<const UChar*>(aDWordCharacters);
+        b = reinterpret_cast<const UChar*>(bDWordCharacters);
+    }
+    
+    if (length & 2) {
+        if (*reinterpret_cast<const uint32_t*>(a) != *reinterpret_cast<const uint32_t*>(b))
+            return false;
+        
+        a += 2;
+        b += 2;
+    }
+    
+    if (length & 1 && (*a != *b))
+        return false;
+    
+    return true;
+}
+#elif CPU(X86)
+template <>
+ALWAYS_INLINE bool equal<LChar, LChar>(const LChar* a, const LChar* b, unsigned length)
+{
+    const uint32_t* aCharacters = reinterpret_cast<const uint32_t*>(a);
+    const uint32_t* bCharacters = reinterpret_cast<const uint32_t*>(b);
+    
+    unsigned wordLength = length >> 2;
+    for (unsigned i = 0; i != wordLength; ++i) {
+        if (*aCharacters++ != *bCharacters++)
+            return false;
+    }
+    
+    length &= 3;
+    
+    if (length) {
+        const LChar* aRemainder = reinterpret_cast<const LChar*>(aCharacters);
+        const LChar* bRemainder = reinterpret_cast<const LChar*>(bCharacters);
+        
+        for (unsigned i = 0; i <  length; ++i) {
+            if (aRemainder[i] != bRemainder[i])
+                return false;
+        }
+    }
+    
+    return true;
+}
+
+template <>
+ALWAYS_INLINE bool equal<UChar, UChar>(const UChar* a, const UChar* b, unsigned length)
+{
+    const uint32_t* aCharacters = reinterpret_cast<const uint32_t*>(a);
+    const uint32_t* bCharacters = reinterpret_cast<const uint32_t*>(b);
+    
+    unsigned wordLength = length >> 1;
+    for (unsigned i = 0; i != wordLength; ++i) {
+        if (*aCharacters++ != *bCharacters++)
+            return false;
+    }
+    
+    if (length & 1 && *reinterpret_cast<const UChar*>(aCharacters) != *reinterpret_cast<const UChar*>(bCharacters))
+        return false;
+    
+    return true;
+}
+#endif
+
+template <typename CharTypeL, typename CharTypeR>
+ALWAYS_INLINE bool equal(const CharTypeL* a, const CharTypeR* b, unsigned length)
+{
+    for (unsigned i = 0; i != length; ++i) {
+        if (a[i] != b[i])
+            return false;
+    }
+    
+    return true;
+}
+
 bool equalIgnoringCase(StringImpl*, StringImpl*);
 bool equalIgnoringCase(StringImpl*, const LChar*);
 inline bool equalIgnoringCase(const LChar* a, StringImpl* b) { return equalIgnoringCase(b, a); }
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to