Dromaeo tests usage of StringImpl find routines cause 8->16 bit conversions
authormsaboff@apple.com <msaboff@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 26 Jan 2012 19:23:50 +0000 (19:23 +0000)
committermsaboff@apple.com <msaboff@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 26 Jan 2012 19:23:50 +0000 (19:23 +0000)
https://bugs.webkit.org/show_bug.cgi?id=76645

Reviewed by Geoffrey Garen.

* wtf/text/StringImpl.cpp:
(WTF::equalIgnoringCase): New LChar version.
(WTF::findInner): New helper function.
(WTF::StringImpl::find): Added 8 bit path.
(WTF::reverseFindInner): New helper funciton.
(WTF::StringImpl::reverseFind): Added 8 bit path.
(WTF::StringImpl::reverseFindIgnoringCase): Added 8 bit path.
* wtf/text/StringImpl.h:
(WTF):

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@106019 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/wtf/text/StringImpl.cpp
Source/JavaScriptCore/wtf/text/StringImpl.h

index 6584b38..4fb5bca 100644 (file)
@@ -1,3 +1,20 @@
+2012-01-26  Michael Saboff  <msaboff@apple.com>
+
+        Dromaeo tests usage of StringImpl find routines cause 8->16 bit conversions
+        https://bugs.webkit.org/show_bug.cgi?id=76645
+
+        Reviewed by Geoffrey Garen.
+
+        * wtf/text/StringImpl.cpp:
+        (WTF::equalIgnoringCase): New LChar version.
+        (WTF::findInner): New helper function.
+        (WTF::StringImpl::find): Added 8 bit path.
+        (WTF::reverseFindInner): New helper funciton.
+        (WTF::StringImpl::reverseFind): Added 8 bit path.
+        (WTF::StringImpl::reverseFindIgnoringCase): Added 8 bit path.
+        * wtf/text/StringImpl.h:
+        (WTF):
+
 2012-01-26  Csaba Osztrogonác  <ossy@webkit.org>
 
         [Qt][Win] One more speculative buildfix after r105970.
index aa5a8d5..7b1b626 100644 (file)
@@ -715,6 +715,16 @@ float StringImpl::toFloat(bool* ok, bool* didReadNumber)
     return charactersToFloat(characters16(), m_length, ok, didReadNumber);
 }
 
+bool equalIgnoringCase(const LChar* a, const LChar* b, unsigned length)
+{
+    while (length--) {
+        LChar bc = *b++;
+        if (foldCase(*a++) != foldCase(bc))
+            return false;
+    }
+    return true;
+}
+
 bool equalIgnoringCase(const UChar* a, const LChar* b, unsigned length)
 {
     while (length--) {
@@ -849,6 +859,35 @@ size_t StringImpl::findIgnoringCase(const LChar* matchString, unsigned index)
     return index + i;
 }
 
+template <typename CharType>
+ALWAYS_INLINE static size_t findInner(const CharType* searchCharacters, const CharType* matchCharacters, unsigned index, unsigned searchLength, unsigned matchLength)
+{
+    // Optimization: keep a running hash of the strings,
+    // only call memcmp if the hashes match.
+
+    // delta is the number of additional times to test; delta == 0 means test only once.
+    unsigned delta = searchLength - matchLength;
+
+    unsigned searchHash = 0;
+    unsigned matchHash = 0;
+
+    for (unsigned i = 0; i < matchLength; ++i) {
+        searchHash += searchCharacters[i];
+        matchHash += matchCharacters[i];
+    }
+
+    unsigned i = 0;
+    // keep looping until we match
+    while (searchHash != matchHash || memcmp(searchCharacters + i, matchCharacters, matchLength * sizeof(CharType))) {
+        if (i == delta)
+            return notFound;
+        searchHash += searchCharacters[i + matchLength];
+        searchHash -= searchCharacters[i];
+        ++i;
+    }
+    return index + i;        
+}
+
 size_t StringImpl::find(StringImpl* matchString, unsigned index)
 {
     // Check for null or empty string to match against
@@ -871,31 +910,12 @@ size_t StringImpl::find(StringImpl* matchString, unsigned index)
     unsigned searchLength = length() - index;
     if (matchLength > searchLength)
         return notFound;
-    // delta is the number of additional times to test; delta == 0 means test only once.
-    unsigned delta = searchLength - matchLength;
 
-    const UChar* searchCharacters = characters() + index;
-    const UChar* matchCharacters = matchString->characters();
+    if (is8Bit() && matchString->is8Bit())
+        return findInner(characters8() + index, matchString->characters8(), index, searchLength, matchLength);
 
-    // Optimization 2: keep a running hash of the strings,
-    // only call memcmp if the hashes match.
-    unsigned searchHash = 0;
-    unsigned matchHash = 0;
-    for (unsigned i = 0; i < matchLength; ++i) {
-        searchHash += searchCharacters[i];
-        matchHash += matchCharacters[i];
-    }
+    return findInner(characters() + index, matchString->characters(), index, searchLength, matchLength);
 
-    unsigned i = 0;
-    // keep looping until we match
-    while (searchHash != matchHash || memcmp(searchCharacters + i, matchCharacters, matchLength * sizeof(UChar))) {
-        if (i == delta)
-            return notFound;
-        searchHash += searchCharacters[i + matchLength];
-        searchHash -= searchCharacters[i];
-        ++i;
-    }
-    return index + i;
 }
 
 size_t StringImpl::findIgnoringCase(StringImpl* matchString, unsigned index)
@@ -936,33 +956,15 @@ size_t StringImpl::reverseFind(UChar c, unsigned index)
     return WTF::reverseFind(characters16(), m_length, c, index);
 }
 
-size_t StringImpl::reverseFind(StringImpl* matchString, unsigned index)
+template <typename CharType>
+ALWAYS_INLINE static size_t reverseFindInner(const CharType* searchCharacters, const CharType* matchCharacters, unsigned index, unsigned length, unsigned matchLength)
 {
-    // Check for null or empty string to match against
-    if (!matchString)
-        return notFound;
-    unsigned matchLength = matchString->length();
-    if (!matchLength)
-        return min(index, length());
-
-    // Optimization 1: fast case for strings of length 1.
-    if (matchLength == 1) {
-        if (is8Bit() && matchString->is8Bit())
-            return WTF::reverseFind(characters8(), length(), matchString->characters8()[0], index);
-        return WTF::reverseFind(characters(), length(), matchString->characters()[0], index);
-    }
+    // Optimization: keep a running hash of the strings,
+    // only call memcmp if the hashes match.
 
-    // Check index & matchLength are in range.
-    if (matchLength > length())
-        return notFound;
     // delta is the number of additional times to test; delta == 0 means test only once.
-    unsigned delta = min(index, length() - matchLength);
-
-    const UChar *searchCharacters = characters();
-    const UChar *matchCharacters = matchString->characters();
-
-    // Optimization 2: keep a running hash of the strings,
-    // only call memcmp if the hashes match.
+    unsigned delta = min(index, length - matchLength);
+    
     unsigned searchHash = 0;
     unsigned matchHash = 0;
     for (unsigned i = 0; i < matchLength; ++i) {
@@ -971,7 +973,7 @@ size_t StringImpl::reverseFind(StringImpl* matchString, unsigned index)
     }
 
     // keep looping until we match
-    while (searchHash != matchHash || memcmp(searchCharacters + delta, matchCharacters, matchLength * sizeof(UChar))) {
+    while (searchHash != matchHash || memcmp(searchCharacters + delta, matchCharacters, matchLength * sizeof(CharType))) {
         if (!delta)
             return notFound;
         delta--;
@@ -981,6 +983,33 @@ size_t StringImpl::reverseFind(StringImpl* matchString, unsigned index)
     return delta;
 }
 
+size_t StringImpl::reverseFind(StringImpl* matchString, unsigned index)
+{
+    // Check for null or empty string to match against
+    if (!matchString)
+        return notFound;
+    unsigned matchLength = matchString->length();
+    unsigned ourLength = length();
+    if (!matchLength)
+        return min(index, ourLength);
+
+    // Optimization 1: fast case for strings of length 1.
+    if (matchLength == 1) {
+        if (is8Bit() && matchString->is8Bit())
+            return WTF::reverseFind(characters8(), ourLength, matchString->characters8()[0], index);
+        return WTF::reverseFind(characters(), ourLength, matchString->characters()[0], index);
+    }
+
+    // Check index & matchLength are in range.
+    if (matchLength > ourLength)
+        return notFound;
+
+    if (is8Bit() && matchString->is8Bit())
+        return reverseFindInner(characters8(), matchString->characters8(), index, ourLength, matchLength);
+
+    return reverseFindInner(characters(), matchString->characters(), index, ourLength, matchLength);
+}
+
 size_t StringImpl::reverseFindIgnoringCase(StringImpl* matchString, unsigned index)
 {
     // Check for null or empty string to match against
@@ -995,7 +1024,20 @@ size_t StringImpl::reverseFindIgnoringCase(StringImpl* matchString, unsigned ind
         return notFound;
     // delta is the number of additional times to test; delta == 0 means test only once.
     unsigned delta = min(index, length() - matchLength);
-    
+
+    if (is8Bit() && matchString->is8Bit()) {
+        const LChar *searchCharacters = characters8();
+        const LChar *matchCharacters = matchString->characters8();
+
+        // keep looping until we match
+        while (!equalIgnoringCase(searchCharacters + delta, matchCharacters, matchLength)) {
+            if (!delta)
+                return notFound;
+            delta--;
+        }
+        return delta;
+    }
+
     const UChar *searchCharacters = characters();
     const UChar *matchCharacters = matchString->characters();
 
index 1c743cb..154e8e0 100644 (file)
@@ -720,6 +720,7 @@ ALWAYS_INLINE bool equal(const UChar* a, const LChar* b, unsigned length)
 WTF_EXPORT_PRIVATE bool equalIgnoringCase(StringImpl*, StringImpl*);
 WTF_EXPORT_PRIVATE bool equalIgnoringCase(StringImpl*, const LChar*);
 inline bool equalIgnoringCase(const LChar* a, StringImpl* b) { return equalIgnoringCase(b, a); }
+WTF_EXPORT_PRIVATE bool equalIgnoringCase(const LChar*, const LChar*, unsigned);
 WTF_EXPORT_PRIVATE bool equalIgnoringCase(const UChar*, const LChar*, unsigned);
 inline bool equalIgnoringCase(const UChar* a, const char* b, unsigned length) { return equalIgnoringCase(a, reinterpret_cast<const LChar*>(b), length); }
 inline bool equalIgnoringCase(const LChar* a, const UChar* b, unsigned length) { return equalIgnoringCase(b, a, length); }