Changeset 102631 in webkit
- Timestamp:
- Dec 12, 2011 3:21:51 PM (12 years ago)
- Location:
- trunk/Source/JavaScriptCore
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/ChangeLog
r102629 r102631 1 2011-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 1 27 2011-12-12 Filip Pizlo <fpizlo@apple.com> 2 28 -
trunk/Source/JavaScriptCore/wtf/text/AtomicString.h
r101778 r102631 140 140 bool operator==(const AtomicString&, const LChar*); 141 141 inline 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()); }142 inline bool operator==(const AtomicString& a, const Vector<UChar>& b) { return a.impl() && equal(static_cast<StringImpl*>(a.impl()), b.data(), b.size()); } 143 143 inline bool operator==(const AtomicString& a, const String& b) { return equal(a.impl(), b.impl()); } 144 144 inline bool operator==(const LChar* a, const AtomicString& b) { return b == a; } -
trunk/Source/JavaScriptCore/wtf/text/StringHash.h
r98624 r102631 57 57 if (b->is8Bit()) { 58 58 // 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); 86 60 } 87 61 88 62 // 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); 97 64 } 98 65 99 66 if (b->is8Bit()) { 100 67 // 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); 109 69 } 110 70 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); 137 72 } 138 73 -
trunk/Source/JavaScriptCore/wtf/text/StringImpl.cpp
r102298 r102631 716 716 } 717 717 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 #endif833 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 845 718 bool equalIgnoringCase(const UChar* a, const LChar* b, unsigned length) 846 719 { -
trunk/Source/JavaScriptCore/wtf/text/StringImpl.h
r102298 r102631 563 563 inline bool equal(const char* a, StringImpl* b) { return equal(b, reinterpret_cast<const LChar*>(a)); } 564 564 bool equal(const StringImpl*, const UChar*, unsigned); 565 template <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) 570 template <> 571 ALWAYS_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 610 template <> 611 ALWAYS_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) 642 template <> 643 ALWAYS_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 669 template <> 670 ALWAYS_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 688 template <typename CharTypeL, typename CharTypeR> 689 ALWAYS_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 } 565 698 566 699 bool equalIgnoringCase(StringImpl*, StringImpl*);
Note: See TracChangeset
for help on using the changeset viewer.