Title: [97371] trunk/Source/_javascript_Core
Revision
97371
Author
commit-qu...@webkit.org
Date
2011-10-13 10:00:59 -0700 (Thu, 13 Oct 2011)

Log Message

Use realloc() to expand/shrink StringBuilder buffer
https://bugs.webkit.org/show_bug.cgi?id=69913

Patch by Xianzhu Wang <wangxian...@chromium.org> on 2011-10-13
Reviewed by Darin Adler.

* wtf/text/StringBuilder.cpp:
(WTF::StringBuilder::reserveCapacity):
(WTF::StringBuilder::reallocateBuffer):
(WTF::StringBuilder::appendUninitialized):
(WTF::StringBuilder::shrinkToFit):
* wtf/text/StringBuilder.h:
* wtf/text/StringImpl.cpp:
(WTF::StringImpl::reallocate): Added to allow StringBuilder to reallocate the buffer.
* wtf/text/StringImpl.h:

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (97370 => 97371)


--- trunk/Source/_javascript_Core/ChangeLog	2011-10-13 16:55:13 UTC (rev 97370)
+++ trunk/Source/_javascript_Core/ChangeLog	2011-10-13 17:00:59 UTC (rev 97371)
@@ -1,3 +1,20 @@
+2011-10-13  Xianzhu Wang  <wangxian...@chromium.org>
+
+        Use realloc() to expand/shrink StringBuilder buffer
+        https://bugs.webkit.org/show_bug.cgi?id=69913
+
+        Reviewed by Darin Adler.
+
+        * wtf/text/StringBuilder.cpp:
+        (WTF::StringBuilder::reserveCapacity):
+        (WTF::StringBuilder::reallocateBuffer):
+        (WTF::StringBuilder::appendUninitialized):
+        (WTF::StringBuilder::shrinkToFit):
+        * wtf/text/StringBuilder.h:
+        * wtf/text/StringImpl.cpp:
+        (WTF::StringImpl::reallocate): Added to allow StringBuilder to reallocate the buffer.
+        * wtf/text/StringImpl.h:
+
 2011-10-12  Filip Pizlo  <fpi...@apple.com>
 
         If an Arguments object is being used to copy the arguments, then

Modified: trunk/Source/_javascript_Core/wtf/text/StringBuilder.cpp (97370 => 97371)


--- trunk/Source/_javascript_Core/wtf/text/StringBuilder.cpp	2011-10-13 16:55:13 UTC (rev 97370)
+++ trunk/Source/_javascript_Core/wtf/text/StringBuilder.cpp	2011-10-13 17:00:59 UTC (rev 97371)
@@ -83,7 +83,7 @@
     if (m_buffer) {
         // If there is already a buffer, then grow if necessary.
         if (newCapacity > m_buffer->length())
-            allocateBuffer(m_buffer->characters(), newCapacity);
+            reallocateBuffer(newCapacity);
     } else {
         // Grow the string, if necessary.
         if (newCapacity > m_length)
@@ -104,13 +104,24 @@
     m_string = String();
 }
 
+void StringBuilder::reallocateBuffer(unsigned requiredLength)
+{
+    // If the buffer has only one ref (by this StringBuilder), reallocate it,
+    // otherwise fall back to "allocate and copy" method.
+    m_string = String();
+    if (m_buffer->hasOneRef())
+        m_buffer = StringImpl::reallocate(m_buffer.release(), requiredLength, m_bufferCharacters);
+    else
+        allocateBuffer(m_buffer->characters(), requiredLength);
+}
+
 // Make 'length' additional capacity be available in m_buffer, update m_string & m_length,
 // return a pointer to the newly allocated storage.
 UChar* StringBuilder::appendUninitialized(unsigned length)
 {
     ASSERT(length);
 
-    // Calcuate the new size of the builder after appending.
+    // Calculate the new size of the builder after appending.
     unsigned requiredLength = length + m_length;
     if (requiredLength < length)
         CRASH();
@@ -127,8 +138,7 @@
             return m_bufferCharacters + currentLength;
         }
 
-        // We need to realloc the buffer.
-        allocateBuffer(m_buffer->characters(), std::max(requiredLength, std::max(minimumCapacity, m_buffer->length() * 2)));
+        reallocateBuffer(std::max(requiredLength, std::max(minimumCapacity, m_buffer->length() * 2)));
     } else {
         ASSERT(m_string.length() == m_length);
         allocateBuffer(m_string.characters(), std::max(requiredLength, std::max(minimumCapacity, m_length * 2)));
@@ -164,9 +174,8 @@
 {
     // If the buffer is at least 80% full, don't bother copying. Need to tune this heuristic!
     if (m_buffer && m_buffer->length() > (m_length + (m_length >> 2))) {
-        UChar* result;
-        m_string = StringImpl::createUninitialized(m_length, result);
-        memcpy(result, m_buffer->characters(), static_cast<size_t>(m_length) * 2); // This can't overflow.
+        reallocateBuffer(m_length);
+        m_string = m_buffer;
         m_buffer = 0;
     }
 }

Modified: trunk/Source/_javascript_Core/wtf/text/StringBuilder.h (97370 => 97371)


--- trunk/Source/_javascript_Core/wtf/text/StringBuilder.h	2011-10-13 16:55:13 UTC (rev 97370)
+++ trunk/Source/_javascript_Core/wtf/text/StringBuilder.h	2011-10-13 17:00:59 UTC (rev 97371)
@@ -130,6 +130,7 @@
 
 private:
     void allocateBuffer(const UChar* currentCharacters, unsigned requiredLength);
+    void reallocateBuffer(unsigned requiredLength);
     UChar* appendUninitialized(unsigned length);
     void reifyString();
 

Modified: trunk/Source/_javascript_Core/wtf/text/StringImpl.cpp (97370 => 97371)


--- trunk/Source/_javascript_Core/wtf/text/StringImpl.cpp	2011-10-13 16:55:13 UTC (rev 97370)
+++ trunk/Source/_javascript_Core/wtf/text/StringImpl.cpp	2011-10-13 17:00:59 UTC (rev 97371)
@@ -90,6 +90,26 @@
     return adoptRef(new (string) StringImpl(length));
 }
 
+PassRefPtr<StringImpl> StringImpl::reallocate(PassRefPtr<StringImpl> originalString, unsigned length, UChar*& data)
+{
+    ASSERT(originalString->hasOneRef() && originalString->bufferOwnership() == BufferInternal);
+
+    if (!length) {
+        data = ""
+        return empty();
+    }
+
+    // Same as createUninitialized() except here we use fastRealloc.
+    if (length > ((std::numeric_limits<unsigned>::max() - sizeof(StringImpl)) / sizeof(UChar)))
+        CRASH();
+    size_t size = sizeof(StringImpl) + length * sizeof(UChar);
+    originalString->~StringImpl();
+    StringImpl* string = static_cast<StringImpl*>(fastRealloc(originalString.leakRef(), size));
+
+    data = "" + 1);
+    return adoptRef(new (string) StringImpl(length));
+}
+
 PassRefPtr<StringImpl> StringImpl::create(const UChar* characters, unsigned length)
 {
     if (!characters || !length)

Modified: trunk/Source/_javascript_Core/wtf/text/StringImpl.h (97370 => 97371)


--- trunk/Source/_javascript_Core/wtf/text/StringImpl.h	2011-10-13 16:55:13 UTC (rev 97370)
+++ trunk/Source/_javascript_Core/wtf/text/StringImpl.h	2011-10-13 17:00:59 UTC (rev 97371)
@@ -181,6 +181,11 @@
         return adoptRef(new(resultImpl) StringImpl(length));
     }
 
+    // Reallocate the StringImpl. The originalString must be only owned by the PassRefPtr,
+    // and the buffer ownership must be BufferInternal. Just like the input pointer of realloc(),
+    // the originalString can't be used after this function.
+    static PassRefPtr<StringImpl> reallocate(PassRefPtr<StringImpl> originalString, unsigned length, UChar*& data);
+
     static unsigned dataOffset() { return OBJECT_OFFSETOF(StringImpl, m_data); }
     static PassRefPtr<StringImpl> createWithTerminatingNullCharacter(const StringImpl&);
     static PassRefPtr<StringImpl> createStrippingNullCharacters(const UChar*, unsigned length);
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to