- 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); }