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)