Changeset 102631 in webkit


Ignore:
Timestamp:
Dec 12, 2011 3:21:51 PM (12 years ago)
Author:
msaboff@apple.com
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):

Location:
trunk/Source/JavaScriptCore
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r102629 r102631  
     12011-12-12  Michael Saboff  <msaboff@apple.com>
     2
     3        Eliminate Duplicate word at a time equal code in StringImpl.cpp and StringHash.h
     4        https://bugs.webkit.org/show_bug.cgi?id=73622
     5
     6        Reviewed by Oliver Hunt.
     7
     8        Moved equal(charType1 *, charType2, unsigned) template methods
     9        from static StringImpl.cpp to StringImpl.h and then replaced the
     10        processor specific character comparison code in StringHash::equal
     11        with calls to these methods.
     12
     13        This change is worth 3% on SunSpider string-unpack-code as reported
     14        by the SunSpider command line harness.  No other tests appear to
     15        have measurable performance changes.
     16
     17        * wtf/text/AtomicString.h:
     18        (WTF::operator==):
     19        * wtf/text/StringHash.h:
     20        (WTF::StringHash::equal):
     21        * wtf/text/StringImpl.cpp:
     22        * wtf/text/StringImpl.h:
     23        (WTF::LChar):
     24        (WTF::UChar):
     25        (WTF::equal):
     26
    1272011-12-12  Filip Pizlo  <fpizlo@apple.com>
    228
  • trunk/Source/JavaScriptCore/wtf/text/AtomicString.h

    r101778 r102631  
    140140bool operator==(const AtomicString&, const LChar*);
    141141inline bool operator==(const AtomicString& a, const char* b) { return WTF::equal(a.impl(), reinterpret_cast<const LChar*>(b)); }
    142 inline bool operator==(const AtomicString& a, const Vector<UChar>& b) { return a.impl() && equal(a.impl(), b.data(), b.size()); }   
     142inline bool operator==(const AtomicString& a, const Vector<UChar>& b) { return a.impl() && equal(static_cast<StringImpl*>(a.impl()), b.data(), b.size()); }   
    143143inline bool operator==(const AtomicString& a, const String& b) { return equal(a.impl(), b.impl()); }
    144144inline bool operator==(const LChar* a, const AtomicString& b) { return b == a; }
  • trunk/Source/JavaScriptCore/wtf/text/StringHash.h

    r98624 r102631  
    5757                if (b->is8Bit()) {
    5858                    // Both a & b are 8 bit.
    59                     const LChar* aChars = a->characters8();
    60                     const LChar* bChars = b->characters8();
    61 
    62                     unsigned i = 0;
    63 
    64                     // FIXME: perhaps we should have a more abstract macro that indicates when
    65                     // going 4 bytes at a time is unsafe
    66 #if (CPU(X86) || CPU(X86_64))
    67                     const unsigned charsPerInt = sizeof(uint32_t) / sizeof(char);
    68                    
    69                     if (aLength > charsPerInt) {
    70                         unsigned stopCount = aLength & ~(charsPerInt - 1);
    71                        
    72                         const uint32_t* aIntCharacters = reinterpret_cast<const uint32_t*>(aChars);
    73                         const uint32_t* bIntCharacters = reinterpret_cast<const uint32_t*>(bChars);
    74                         for (unsigned j = 0; i < stopCount; i += charsPerInt, ++j) {
    75                             if (aIntCharacters[j] != bIntCharacters[j])
    76                                 return false;
    77                         }
    78                     }
    79 #endif
    80                     for (; i < aLength; ++i) {
    81                         if (aChars[i] != bChars[i])
    82                             return false;
    83                     }
    84                    
    85                     return true;
     59                    return WTF::equal(a->characters8(), b->characters8(), aLength);
    8660                }
    8761
    8862                // We know that a is 8 bit & b is 16 bit.
    89                 const LChar* aChars = a->characters8();
    90                 const UChar* bChars = b->characters16();
    91                 for (unsigned i = 0; i != aLength; ++i) {
    92                     if (*aChars++ != *bChars++)
    93                         return false;
    94                 }
    95 
    96                 return true;
     63                return WTF::equal(a->characters8(), b->characters16(), aLength);
    9764            }
    9865
    9966            if (b->is8Bit()) {
    10067                // We know that a is 8 bit and b is 16 bit.
    101                 const UChar* aChars = a->characters16();
    102                 const LChar* bChars = b->characters8();
    103                 for (unsigned i = 0; i != aLength; ++i) {
    104                     if (*aChars++ != *bChars++)
    105                         return false;
    106                 }
    107 
    108                 return true;
     68                return WTF::equal(a->characters16(), b->characters8(), aLength);
    10969            }
    11070
    111             // Both a & b are 16 bit.
    112             // FIXME: perhaps we should have a more abstract macro that indicates when
    113             // going 4 bytes at a time is unsafe
    114 #if CPU(ARM) || CPU(SH4) || CPU(MIPS) || CPU(SPARC)
    115             const UChar* aChars = a->characters16();
    116             const UChar* bChars = b->characters16();
    117             for (unsigned i = 0; i != aLength; ++i) {
    118                 if (*aChars++ != *bChars++)
    119                     return false;
    120             }
    121             return true;
    122 #else
    123             /* Do it 4-bytes-at-a-time on architectures where it's safe */
    124             const uint32_t* aChars = reinterpret_cast<const uint32_t*>(a->characters16());
    125             const uint32_t* bChars = reinterpret_cast<const uint32_t*>(b->characters16());
    126 
    127             unsigned halfLength = aLength >> 1;
    128             for (unsigned i = 0; i != halfLength; ++i)
    129                 if (*aChars++ != *bChars++)
    130                     return false;
    131 
    132             if (aLength & 1 && *reinterpret_cast<const uint16_t*>(aChars) != *reinterpret_cast<const uint16_t*>(bChars))
    133                 return false;
    134 
    135             return true;
    136 #endif
     71            return WTF::equal(a->characters16(), b->characters16(), aLength);
    13772        }
    13873
  • trunk/Source/JavaScriptCore/wtf/text/StringImpl.cpp

    r102298 r102631  
    716716}
    717717
    718 // Do comparisons 8 or 4 bytes-at-a-time on architectures where it's safe.
    719 #if CPU(X86_64)
    720 ALWAYS_INLINE static bool equal(const LChar* a, const LChar* b, unsigned length)
    721 {
    722     unsigned dwordLength = length >> 3;
    723 
    724     if (dwordLength) {
    725         const uint64_t* aDWordCharacters = reinterpret_cast<const uint64_t*>(a);
    726         const uint64_t* bDWordCharacters = reinterpret_cast<const uint64_t*>(b);
    727 
    728         for (unsigned i = 0; i != dwordLength; ++i) {
    729             if (*aDWordCharacters++ != *bDWordCharacters++)
    730                 return false;
    731         }
    732 
    733         a = reinterpret_cast<const LChar*>(aDWordCharacters);
    734         b = reinterpret_cast<const LChar*>(bDWordCharacters);
    735     }
    736 
    737     if (length & 4) {
    738         if (*reinterpret_cast<const uint32_t*>(a) != *reinterpret_cast<const uint32_t*>(b))
    739             return false;
    740 
    741         a += 4;
    742         b += 4;
    743     }
    744 
    745     if (length & 2) {
    746         if (*reinterpret_cast<const uint16_t*>(a) != *reinterpret_cast<const uint16_t*>(b))
    747             return false;
    748 
    749         a += 2;
    750         b += 2;
    751     }
    752 
    753     if (length & 1 && (*a != *b))
    754         return false;
    755 
    756     return true;
    757 }
    758 
    759 ALWAYS_INLINE static bool equal(const UChar* a, const UChar* b, unsigned length)
    760 {
    761     unsigned dwordLength = length >> 2;
    762 
    763     if (dwordLength) {
    764         const uint64_t* aDWordCharacters = reinterpret_cast<const uint64_t*>(a);
    765         const uint64_t* bDWordCharacters = reinterpret_cast<const uint64_t*>(b);
    766 
    767         for (unsigned i = 0; i != dwordLength; ++i) {
    768             if (*aDWordCharacters++ != *bDWordCharacters++)
    769                 return false;
    770         }
    771 
    772         a = reinterpret_cast<const UChar*>(aDWordCharacters);
    773         b = reinterpret_cast<const UChar*>(bDWordCharacters);
    774     }
    775 
    776     if (length & 2) {
    777         if (*reinterpret_cast<const uint32_t*>(a) != *reinterpret_cast<const uint32_t*>(b))
    778             return false;
    779 
    780         a += 2;
    781         b += 2;
    782     }
    783 
    784     if (length & 1 && (*a != *b))
    785         return false;
    786 
    787     return true;
    788 }
    789 #elif CPU(X86)
    790 ALWAYS_INLINE static bool equal(const LChar* a, const LChar* b, unsigned length)
    791 {
    792     const uint32_t* aCharacters = reinterpret_cast<const uint32_t*>(a);
    793     const uint32_t* bCharacters = reinterpret_cast<const uint32_t*>(b);
    794 
    795     unsigned wordLength = length >> 2;
    796     for (unsigned i = 0; i != wordLength; ++i) {
    797         if (*aCharacters++ != *bCharacters++)
    798             return false;
    799     }
    800 
    801     length &= 3;
    802 
    803     if (length) {
    804         const LChar* aRemainder = reinterpret_cast<const LChar*>(aCharacters);
    805         const LChar* bRemainder = reinterpret_cast<const LChar*>(bCharacters);
    806 
    807         for (unsigned i = 0; i <  length; ++i) {
    808             if (aRemainder[i] != bRemainder[i])
    809                 return false;
    810         }
    811     }
    812 
    813     return true;
    814 }
    815 
    816 ALWAYS_INLINE static bool equal(const UChar* a, const UChar* b, unsigned length)
    817 {
    818     const uint32_t* aCharacters = reinterpret_cast<const uint32_t*>(a);
    819     const uint32_t* bCharacters = reinterpret_cast<const uint32_t*>(b);
    820 
    821     unsigned wordLength = length >> 1;
    822     for (unsigned i = 0; i != wordLength; ++i) {
    823         if (*aCharacters++ != *bCharacters++)
    824             return false;
    825     }
    826 
    827     if (length & 1 && *reinterpret_cast<const UChar*>(aCharacters) != *reinterpret_cast<const UChar*>(bCharacters))
    828         return false;
    829 
    830     return true;
    831 }
    832 #endif
    833 
    834 template <typename CharTypeL, typename CharTypeR>
    835 ALWAYS_INLINE static bool equal(const CharTypeL* a, const CharTypeR* b, unsigned length)
    836 {
    837     for (unsigned i = 0; i != length; ++i) {
    838         if (a[i] != b[i])
    839             return false;
    840     }
    841 
    842     return true;
    843 }
    844 
    845718bool equalIgnoringCase(const UChar* a, const LChar* b, unsigned length)
    846719{
  • trunk/Source/JavaScriptCore/wtf/text/StringImpl.h

    r102298 r102631  
    563563inline bool equal(const char* a, StringImpl* b) { return equal(b, reinterpret_cast<const LChar*>(a)); }
    564564bool equal(const StringImpl*, const UChar*, unsigned);
     565template <typename CharTypeL, typename CharTypeR>
     566    ALWAYS_INLINE bool equal(const CharTypeL*, const CharTypeR*, unsigned);
     567
     568// Do comparisons 8 or 4 bytes-at-a-time on architectures where it's safe.
     569#if CPU(X86_64)
     570template <>
     571ALWAYS_INLINE bool equal<LChar, LChar>(const LChar* a, const LChar* b, unsigned length)
     572{
     573    unsigned dwordLength = length >> 3;
     574   
     575    if (dwordLength) {
     576        const uint64_t* aDWordCharacters = reinterpret_cast<const uint64_t*>(a);
     577        const uint64_t* bDWordCharacters = reinterpret_cast<const uint64_t*>(b);
     578       
     579        for (unsigned i = 0; i != dwordLength; ++i) {
     580            if (*aDWordCharacters++ != *bDWordCharacters++)
     581                return false;
     582        }
     583       
     584        a = reinterpret_cast<const LChar*>(aDWordCharacters);
     585        b = reinterpret_cast<const LChar*>(bDWordCharacters);
     586    }
     587   
     588    if (length & 4) {
     589        if (*reinterpret_cast<const uint32_t*>(a) != *reinterpret_cast<const uint32_t*>(b))
     590            return false;
     591       
     592        a += 4;
     593        b += 4;
     594    }
     595   
     596    if (length & 2) {
     597        if (*reinterpret_cast<const uint16_t*>(a) != *reinterpret_cast<const uint16_t*>(b))
     598            return false;
     599       
     600        a += 2;
     601        b += 2;
     602    }
     603   
     604    if (length & 1 && (*a != *b))
     605        return false;
     606   
     607    return true;
     608}
     609
     610template <>
     611ALWAYS_INLINE bool equal<UChar, UChar>(const UChar* a, const UChar* b, unsigned length)
     612{
     613    unsigned dwordLength = length >> 2;
     614   
     615    if (dwordLength) {
     616        const uint64_t* aDWordCharacters = reinterpret_cast<const uint64_t*>(a);
     617        const uint64_t* bDWordCharacters = reinterpret_cast<const uint64_t*>(b);
     618       
     619        for (unsigned i = 0; i != dwordLength; ++i) {
     620            if (*aDWordCharacters++ != *bDWordCharacters++)
     621                return false;
     622        }
     623       
     624        a = reinterpret_cast<const UChar*>(aDWordCharacters);
     625        b = reinterpret_cast<const UChar*>(bDWordCharacters);
     626    }
     627   
     628    if (length & 2) {
     629        if (*reinterpret_cast<const uint32_t*>(a) != *reinterpret_cast<const uint32_t*>(b))
     630            return false;
     631       
     632        a += 2;
     633        b += 2;
     634    }
     635   
     636    if (length & 1 && (*a != *b))
     637        return false;
     638   
     639    return true;
     640}
     641#elif CPU(X86)
     642template <>
     643ALWAYS_INLINE bool equal<LChar, LChar>(const LChar* a, const LChar* b, unsigned length)
     644{
     645    const uint32_t* aCharacters = reinterpret_cast<const uint32_t*>(a);
     646    const uint32_t* bCharacters = reinterpret_cast<const uint32_t*>(b);
     647   
     648    unsigned wordLength = length >> 2;
     649    for (unsigned i = 0; i != wordLength; ++i) {
     650        if (*aCharacters++ != *bCharacters++)
     651            return false;
     652    }
     653   
     654    length &= 3;
     655   
     656    if (length) {
     657        const LChar* aRemainder = reinterpret_cast<const LChar*>(aCharacters);
     658        const LChar* bRemainder = reinterpret_cast<const LChar*>(bCharacters);
     659       
     660        for (unsigned i = 0; i <  length; ++i) {
     661            if (aRemainder[i] != bRemainder[i])
     662                return false;
     663        }
     664    }
     665   
     666    return true;
     667}
     668
     669template <>
     670ALWAYS_INLINE bool equal<UChar, UChar>(const UChar* a, const UChar* b, unsigned length)
     671{
     672    const uint32_t* aCharacters = reinterpret_cast<const uint32_t*>(a);
     673    const uint32_t* bCharacters = reinterpret_cast<const uint32_t*>(b);
     674   
     675    unsigned wordLength = length >> 1;
     676    for (unsigned i = 0; i != wordLength; ++i) {
     677        if (*aCharacters++ != *bCharacters++)
     678            return false;
     679    }
     680   
     681    if (length & 1 && *reinterpret_cast<const UChar*>(aCharacters) != *reinterpret_cast<const UChar*>(bCharacters))
     682        return false;
     683   
     684    return true;
     685}
     686#endif
     687
     688template <typename CharTypeL, typename CharTypeR>
     689ALWAYS_INLINE bool equal(const CharTypeL* a, const CharTypeR* b, unsigned length)
     690{
     691    for (unsigned i = 0; i != length; ++i) {
     692        if (a[i] != b[i])
     693            return false;
     694    }
     695   
     696    return true;
     697}
    565698
    566699bool equalIgnoringCase(StringImpl*, StringImpl*);
Note: See TracChangeset for help on using the changeset viewer.