Changeset 36117 in webkit for trunk/JavaScriptCore
- Timestamp:
- Sep 5, 2008, 2:51:22 PM (17 years ago)
- Location:
- trunk/JavaScriptCore
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JavaScriptCore/ChangeLog
r36114 r36117 1 2008-09-05 Darin Adler <[email protected]> 2 3 Reviewed by Sam Weinig. 4 5 - fix https://bugs.webkit.org/show_bug.cgi?id=20671 6 JavaScriptCore string manipulation spends too much time in memcpy 7 8 1.011x as fast on SunSpider overall 9 1.028x as fast on SunSpider string tests 10 11 For small strings, use a loop rather than calling memcpy. The loop can 12 be faster because there's no function call overhead, and because it can 13 assume the pointers are aligned instead of checking that. Currently the 14 threshold is set at 20 characters, based on some testing on one particular 15 computer. Later we can tune this for various platforms by setting 16 USTRING_COPY_CHARS_INLINE_CUTOFF appropriately, but it does no great harm 17 if not perfectly tuned. 18 19 * kjs/ustring.cpp: 20 (KJS::overflowIndicator): Removed bogus const. 21 (KJS::maxUChars): Ditto. 22 (KJS::copyChars): Added. 23 (KJS::UString::Rep::createCopying): Call copyChars instead of memcpy. 24 Also eliminated need for const_cast. 25 (KJS::UString::expandPreCapacity): Ditto. 26 (KJS::concatenate): Ditto. 27 (KJS::UString::spliceSubstringsWithSeparators): Ditto. 28 (KJS::UString::append): Ditto. 29 1 30 2008-09-05 Kevin McCullough <[email protected]> 2 31 -
trunk/JavaScriptCore/kjs/ustring.cpp
r36006 r36117 52 52 using namespace std; 53 53 54 // This can be tuned differently per platform by putting platform #ifs right here. 55 // If you don't define this macro at all, then copyChars will just call directly 56 // to memcpy. 57 #define USTRING_COPY_CHARS_INLINE_CUTOFF 20 58 54 59 namespace KJS { 55 60 56 61 extern const double NaN; 57 62 extern const double Inf; 58 63 59 static inline constsize_t overflowIndicator() { return std::numeric_limits<size_t>::max(); }60 static inline constsize_t maxUChars() { return std::numeric_limits<size_t>::max() / sizeof(UChar); }64 static inline size_t overflowIndicator() { return std::numeric_limits<size_t>::max(); } 65 static inline size_t maxUChars() { return std::numeric_limits<size_t>::max() / sizeof(UChar); } 61 66 62 67 static inline UChar* allocChars(size_t length) … … 74 79 return 0; 75 80 return static_cast<UChar*>(tryFastRealloc(buffer, sizeof(UChar) * length)); 81 } 82 83 static inline void copyChars(UChar* destination, const UChar* source, unsigned numCharacters) 84 { 85 #ifdef USTRING_COPY_CHARS_INLINE_CUTOFF 86 if (numCharacters <= USTRING_COPY_CHARS_INLINE_CUTOFF) { 87 for (unsigned i = 0; i < numCharacters; ++i) 88 destination[i] = source[i]; 89 return; 90 } 91 #endif 92 memcpy(destination, source, numCharacters * sizeof(UChar)); 76 93 } 77 94 … … 177 194 PassRefPtr<UString::Rep> UString::Rep::createCopying(const UChar* d, int l) 178 195 { 179 int sizeInBytes = l * sizeof(UChar); 180 UChar* copyD = static_cast<UChar*>(fastMalloc(sizeInBytes)); 181 memcpy(copyD, d, sizeInBytes); 182 196 UChar* copyD = static_cast<UChar*>(fastMalloc(l * sizeof(UChar))); 197 copyChars(copyD, d, l); 183 198 return create(copyD, l); 184 199 } … … 458 473 return; 459 474 } 460 memcpy(newBuf + delta, r->buf, (r->capacity + r->preCapacity) * sizeof(UChar));475 copyChars(newBuf + delta, r->buf, r->capacity + r->preCapacity); 461 476 fastFree(r->buf); 462 477 r->buf = newBuf; … … 556 571 if (!a->data() || !x.data()) 557 572 return 0; 558 memcpy(a->data() + aSize, b->data(), bSize * sizeof(UChar));573 copyChars(a->data() + aSize, b->data(), bSize); 559 574 PassRefPtr<UString::Rep> result = UString::Rep::create(a, 0, length); 560 575 … … 566 581 } 567 582 568 if (-bOffset == b->baseString->usedPreCapacity && bSize >= minShareSize 583 if (-bOffset == b->baseString->usedPreCapacity && bSize >= minShareSize && 4 * bSize >= aSize) { 569 584 // - b reaches the beginning of its buffer so it qualifies for shared prepend 570 585 // - also, it's at least a quarter the length of a - prepending to a much shorter … … 574 589 if (!b->data() || !y.data()) 575 590 return 0; 576 memcpy(b->data() - aSize, a->data(), aSize * sizeof(UChar));591 copyChars(b->data() - aSize, a->data(), aSize); 577 592 PassRefPtr<UString::Rep> result = UString::Rep::create(b, -aSize, length); 578 593 … … 589 604 if (!d) 590 605 return 0; 591 memcpy(d, a->data(), aSize * sizeof(UChar));592 memcpy(d + aSize, b->data(), bSize * sizeof(UChar));606 copyChars(d, a->data(), aSize); 607 copyChars(d + aSize, b->data(), bSize); 593 608 PassRefPtr<UString::Rep> result = UString::Rep::create(d, length); 594 609 result->capacity = newCapacity; … … 779 794 for (int i = 0; i < maxCount; i++) { 780 795 if (i < rangeCount) { 781 memcpy(buffer + bufferPos, data() + substringRanges[i].position, substringRanges[i].length * sizeof(UChar));796 copyChars(buffer + bufferPos, data() + substringRanges[i].position, substringRanges[i].length); 782 797 bufferPos += substringRanges[i].length; 783 798 } 784 799 if (i < separatorCount) { 785 memcpy(buffer + bufferPos, separators[i].data(), separators[i].size() * sizeof(UChar));800 copyChars(buffer + bufferPos, separators[i].data(), separators[i].size()); 786 801 bufferPos += separators[i].size(); 787 802 } … … 811 826 expandCapacity(thisOffset + length); 812 827 if (data()) { 813 memcpy(const_cast<UChar*>(data() + thisSize), t.data(), tSize * sizeof(UChar));828 copyChars(m_rep->data() + thisSize, t.data(), tSize); 814 829 m_rep->len = length; 815 830 m_rep->_hash = 0; … … 819 834 expandCapacity(thisOffset + length); 820 835 if (data()) { 821 memcpy(const_cast<UChar*>(data() + thisSize), t.data(), tSize * sizeof(UChar));836 copyChars(m_rep->data() + thisSize, t.data(), tSize); 822 837 m_rep = Rep::create(m_rep, 0, length); 823 838 } … … 829 844 makeNull(); 830 845 else { 831 memcpy(d, data(), thisSize * sizeof(UChar));832 memcpy(const_cast<UChar*>(d + thisSize), t.data(), tSize * sizeof(UChar));846 copyChars(d, data(), thisSize); 847 copyChars(d + thisSize, t.data(), tSize); 833 848 m_rep = Rep::create(d, length); 834 849 m_rep->capacity = newCapacity; … … 860 875 expandCapacity(thisOffset + length); 861 876 if (data()) { 862 memcpy(const_cast<UChar*>(data() + thisSize), tData, tSize * sizeof(UChar));877 copyChars(m_rep->data() + thisSize, tData, tSize); 863 878 m_rep->len = length; 864 879 m_rep->_hash = 0; … … 868 883 expandCapacity(thisOffset + length); 869 884 if (data()) { 870 memcpy(const_cast<UChar*>(data() + thisSize), tData, tSize * sizeof(UChar));885 copyChars(m_rep->data() + thisSize, tData, tSize); 871 886 m_rep = Rep::create(m_rep, 0, length); 872 887 } … … 878 893 makeNull(); 879 894 else { 880 memcpy(d, data(), thisSize * sizeof(UChar));881 memcpy(const_cast<UChar*>(d + thisSize), tData, tSize * sizeof(UChar));895 copyChars(d, data(), thisSize); 896 copyChars(d + thisSize, tData, tSize); 882 897 m_rep = Rep::create(d, length); 883 898 m_rep->capacity = newCapacity; … … 908 923 // this is direct and has refcount of 1 (so we can just alter it directly) 909 924 expandCapacity(thisOffset + length); 910 UChar* d = const_cast<UChar*>(data());925 UChar* d = m_rep->data(); 911 926 if (d) { 912 927 for (int i = 0; i < tSize; ++i) … … 918 933 // this string reaches the end of the buffer - extend it 919 934 expandCapacity(thisOffset + length); 920 UChar* d = const_cast<UChar*>(data());935 UChar* d = m_rep->data(); 921 936 if (d) { 922 937 for (int i = 0; i < tSize; ++i) … … 931 946 makeNull(); 932 947 else { 933 memcpy(d, data(), thisSize * sizeof(UChar));948 copyChars(d, data(), thisSize); 934 949 for (int i = 0; i < tSize; ++i) 935 950 d[thisSize + i] = static_cast<unsigned char>(t[i]); // use unsigned char to zero-extend instead of sign-extend … … 966 981 // this is direct and has refcount of 1 (so we can just alter it directly) 967 982 expandCapacity(thisOffset + length + 1); 968 UChar* d = const_cast<UChar*>(data());983 UChar* d = m_rep->data(); 969 984 if (d) { 970 985 d[length] = c; … … 975 990 // this reaches the end of the string - extend it and share 976 991 expandCapacity(thisOffset + length + 1); 977 UChar* d = const_cast<UChar*>(data());992 UChar* d = m_rep->data(); 978 993 if (d) { 979 994 d[length] = c; … … 987 1002 makeNull(); 988 1003 else { 989 memcpy(d, data(), length * sizeof(UChar));1004 copyChars(d, data(), length); 990 1005 d[length] = c; 991 1006 m_rep = Rep::create(d, length + 1);
Note:
See TracChangeset
for help on using the changeset viewer.