Title: [101747] trunk/Source/_javascript_Core
Revision
101747
Author
msab...@apple.com
Date
2011-12-01 23:04:29 -0800 (Thu, 01 Dec 2011)

Log Message

Changes proposed for 73457 slow down Kraken json-parse-financial
https://bugs.webkit.org/show_bug.cgi?id=73584

Restructured StringImpl::equal to take advantage of 8 or 4 bytes
at a time when possible.

This is worth ~3% on Kraken json-parse-financial. It provides 
~2% on SunSpider string-unpack-code.

Reviewed by Sam Weinig.

* wtf/text/StringImpl.cpp:
(WTF::equal):

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (101746 => 101747)


--- trunk/Source/_javascript_Core/ChangeLog	2011-12-02 07:01:52 UTC (rev 101746)
+++ trunk/Source/_javascript_Core/ChangeLog	2011-12-02 07:04:29 UTC (rev 101747)
@@ -1,3 +1,19 @@
+2011-12-01  Michael Saboff  <msab...@apple.com>
+
+        Changes proposed for 73457 slow down Kraken json-parse-financial
+        https://bugs.webkit.org/show_bug.cgi?id=73584
+
+        Restructured StringImpl::equal to take advantage of 8 or 4 bytes
+        at a time when possible.
+
+        This is worth ~3% on Kraken json-parse-financial. It provides 
+        ~2% on SunSpider string-unpack-code.
+
+        Reviewed by Sam Weinig.
+
+        * wtf/text/StringImpl.cpp:
+        (WTF::equal):
+
 2011-12-01  Oliver Hunt  <oli...@apple.com>
 
         Support integer typed arrays in the DFG JIT

Modified: trunk/Source/_javascript_Core/wtf/text/StringImpl.cpp (101746 => 101747)


--- trunk/Source/_javascript_Core/wtf/text/StringImpl.cpp	2011-12-02 07:01:52 UTC (rev 101746)
+++ trunk/Source/_javascript_Core/wtf/text/StringImpl.cpp	2011-12-02 07:04:29 UTC (rev 101747)
@@ -711,17 +711,133 @@
     return charactersToFloat(characters16(), m_length, ok, didReadNumber);
 }
 
-static bool equal(const UChar* a, const LChar* b, int length)
+// 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)
 {
-    ASSERT(length >= 0);
-    while (length--) {
-        LChar bc = *b++;
-        if (*a++ != bc)
+    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--) {
@@ -1350,17 +1466,6 @@
     return StringHash::equal(a, b);
 }
 
-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 equal(const StringImpl* a, const LChar* b, unsigned length)
 {
     if (!a)
@@ -1420,39 +1525,9 @@
 
     if (a->length() != length)
         return false;
-    // 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* as = a->characters();
-    for (unsigned i = 0; i != length; ++i)
-        if (as[i] != b[i])
-            return false;
-    return true;
-#else
-    if (a->is8Bit()) {
-        const LChar* as = a->characters8();
-        for (unsigned i = 0; i != length; ++i)
-            if (as[i] != b[i])
-                return false;
-        return true;
-    }
-
-    // Do comparison 4-bytes-at-a-time on architectures where it's safe.
-
-    const uint32_t* aCharacters = reinterpret_cast<const uint32_t*>(a->characters16());
-    const uint32_t* bCharacters = reinterpret_cast<const uint32_t*>(b);
-
-    unsigned halfLength = length >> 1;
-    for (unsigned i = 0; i != halfLength; ++i) {
-        if (*aCharacters++ != *bCharacters++)
-            return false;
-    }
-
-    if (length & 1 &&  *reinterpret_cast<const uint16_t*>(aCharacters) != *reinterpret_cast<const uint16_t*>(bCharacters))
-        return false;
-
-    return true;
-#endif
+    if (a->is8Bit())
+        return equal(a->characters8(), b, length);
+    return equal(a->characters16(), b, length);
 }
 
 bool equalIgnoringCase(StringImpl* a, StringImpl* b)
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to