Title: [135972] trunk/Source
Revision
135972
Author
msab...@apple.com
Date
2012-11-27 21:27:34 -0800 (Tue, 27 Nov 2012)

Log Message

TextIterator unnecessarily converts 8 bit strings to 16 bits
https://bugs.webkit.org/show_bug.cgi?id=103295

Reviewed by Brent Fulgham.

Source/WebCore:

Changed TextIterator to use the contained string instead of calling characters() on that string.
Other sources of text, like emitCharacter() still use the contained UChar* buffer.
Added appendTextToStringBuilder() to append the text contents of the current iterator to a string builder
irrespective of the source of the text.

No new tests as functionality covered by existing tests.

* WebCore.exp.in: Updated plainText export and eliminated plainTextToMallocAllocatedBuffer export
* accessibility/AccessibilityObject.cpp:
(WebCore::AccessibilityObject::stringForVisiblePositionRange): Updated to use TextIterator::appendTextToStringBuilder()
* editing/TextIterator.cpp:
(WebCore::TextIterator::characterAt): New function to return the indexed character of the current TextIterator
(WebCore::TextIterator::appendTextToStringBuilder): Added method to append whatever the current text to a StringBuilder
(WebCore::TextIterator::emitText): Eliminated accessing the character data via characters().
(WebCore::TextIterator::rangeFromLocationAndLength): Changed to use characterAt().
(WebCore::plainText): Combined with plainTextToMallocAllocatedBuffer().
* editing/TextIterator.h:
(WebCore::TextIterator::startOffset): New getter.
(WebCore::TextIterator::string): New getter.
(WebCore::TextIterator::characters): Updated to use correct test source.
* page/ContextMenuController.cpp:
(WebCore::selectionContainsPossibleWord): Changed to use characterAt().

Source/WebKit/mac:

Updated _stringForRange to use plainText() instead of removed plainTextToMallocAllocatedBuffer().

* WebView/WebFrame.mm:
(-[WebFrame _stringForRange:]):

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (135971 => 135972)


--- trunk/Source/WebCore/ChangeLog	2012-11-28 05:24:15 UTC (rev 135971)
+++ trunk/Source/WebCore/ChangeLog	2012-11-28 05:27:34 UTC (rev 135972)
@@ -1,3 +1,33 @@
+2012-11-27  Michael Saboff  <msab...@apple.com>
+
+        TextIterator unnecessarily converts 8 bit strings to 16 bits
+        https://bugs.webkit.org/show_bug.cgi?id=103295
+
+        Reviewed by Brent Fulgham.
+
+        Changed TextIterator to use the contained string instead of calling characters() on that string.
+        Other sources of text, like emitCharacter() still use the contained UChar* buffer.
+        Added appendTextToStringBuilder() to append the text contents of the current iterator to a string builder
+        irrespective of the source of the text.
+
+        No new tests as functionality covered by existing tests.
+
+        * WebCore.exp.in: Updated plainText export and eliminated plainTextToMallocAllocatedBuffer export
+        * accessibility/AccessibilityObject.cpp:
+        (WebCore::AccessibilityObject::stringForVisiblePositionRange): Updated to use TextIterator::appendTextToStringBuilder()
+        * editing/TextIterator.cpp:
+        (WebCore::TextIterator::characterAt): New function to return the indexed character of the current TextIterator
+        (WebCore::TextIterator::appendTextToStringBuilder): Added method to append whatever the current text to a StringBuilder
+        (WebCore::TextIterator::emitText): Eliminated accessing the character data via characters().
+        (WebCore::TextIterator::rangeFromLocationAndLength): Changed to use characterAt().
+        (WebCore::plainText): Combined with plainTextToMallocAllocatedBuffer().
+        * editing/TextIterator.h:
+        (WebCore::TextIterator::startOffset): New getter.
+        (WebCore::TextIterator::string): New getter.
+        (WebCore::TextIterator::characters): Updated to use correct test source.
+        * page/ContextMenuController.cpp:
+        (WebCore::selectionContainsPossibleWord): Changed to use characterAt().
+
 2012-11-27  Noel Gordon  <noel.gor...@gmail.com>
 
         Inline ImageFrame width() and height()

Modified: trunk/Source/WebCore/WebCore.exp.in (135971 => 135972)


--- trunk/Source/WebCore/WebCore.exp.in	2012-11-28 05:24:15 UTC (rev 135971)
+++ trunk/Source/WebCore/WebCore.exp.in	2012-11-28 05:27:34 UTC (rev 135972)
@@ -691,7 +691,6 @@
 __ZN7WebCore30overrideUserPreferredLanguagesERKN3WTF6VectorINS0_6StringELm0EEE
 __ZN7WebCore31CrossOriginPreflightResultCache5emptyEv
 __ZN7WebCore31CrossOriginPreflightResultCache6sharedEv
-__ZN7WebCore32plainTextToMallocAllocatedBufferEPKNS_5RangeERjbNS_20TextIteratorBehaviorE
 __ZN7WebCore33stripLeadingAndTrailingHTMLSpacesERKN3WTF6StringE
 __ZN7WebCore37WidgetHierarchyUpdatesSuspensionScope11moveWidgetsEv
 __ZN7WebCore37WidgetHierarchyUpdatesSuspensionScope35s_widgetHierarchyUpdateSuspendCountE
@@ -1094,7 +1093,7 @@
 __ZN7WebCore9fontCacheEv
 __ZN7WebCore9makeRangeERKNS_15VisiblePositionES2_
 __ZN7WebCore9pageCacheEv
-__ZN7WebCore9plainTextEPKNS_5RangeENS_20TextIteratorBehaviorE
+__ZN7WebCore9plainTextEPKNS_5RangeENS_20TextIteratorBehaviorEb
 __ZN7WebCore9toElementEN3JSC7JSValueE
 __ZN7WebCore9unionRectERKN3WTF6VectorINS_9FloatRectELm0EEE
 __ZNK3JSC8Bindings10RootObject12globalObjectEv

Modified: trunk/Source/WebCore/accessibility/AccessibilityObject.cpp (135971 => 135972)


--- trunk/Source/WebCore/accessibility/AccessibilityObject.cpp	2012-11-28 05:24:15 UTC (rev 135971)
+++ trunk/Source/WebCore/accessibility/AccessibilityObject.cpp	2012-11-28 05:27:34 UTC (rev 135972)
@@ -840,7 +840,7 @@
             if (!listMarkerText.isEmpty())
                 builder.append(listMarkerText);
 
-            builder.append(it.characters(), it.length());
+            it.appendTextToStringBuilder(builder);
         } else {
             // locate the node and starting offset for this replaced range
             int exception = 0;

Modified: trunk/Source/WebCore/editing/TextIterator.cpp (135971 => 135972)


--- trunk/Source/WebCore/editing/TextIterator.cpp	2012-11-28 05:24:15 UTC (rev 135971)
+++ trunk/Source/WebCore/editing/TextIterator.cpp	2012-11-28 05:27:34 UTC (rev 135972)
@@ -462,6 +462,26 @@
     }
 }
 
+UChar TextIterator::characterAt(unsigned index) const
+{
+    ASSERT(index < static_cast<unsigned>(length()));
+    if (!(index < static_cast<unsigned>(length())))
+        return 0;
+
+    if (!m_textCharacters)
+        return string()[startOffset() + index];
+
+    return m_textCharacters[index];
+}
+
+void TextIterator::appendTextToStringBuilder(StringBuilder& builder) const
+{
+    if (!m_textCharacters)
+        builder.append(string(), startOffset(), length());
+    else
+        builder.append(characters(), length());
+}
+
 bool TextIterator::handleTextNode()
 {
     if (m_fullyClippedStack.top() && !m_ignoresStyleVisibility)
@@ -1007,7 +1027,7 @@
 {
     RenderText* renderer = toRenderText(renderObject);
     m_text = m_emitsOriginalText ? renderer->originalText() : (m_emitsTextWithoutTranscoding ? renderer->textWithoutTranscoding() : renderer->text());
-    ASSERT(m_text.characters());
+    ASSERT(!m_text.isEmpty());
     ASSERT(0 <= textStartOffset && textStartOffset < static_cast<int>(m_text.length()));
     ASSERT(0 <= textEndOffset && textEndOffset <= static_cast<int>(m_text.length()));
     ASSERT(textStartOffset <= textEndOffset);
@@ -1016,7 +1036,7 @@
     m_positionOffsetBaseNode = 0;
     m_positionStartOffset = textStartOffset;
     m_positionEndOffset = textEndOffset;
-    m_textCharacters = m_text.characters() + textStartOffset;
+    m_textCharacters = 0;
     m_textLength = textEndOffset - textStartOffset;
     m_lastCharacter = m_text[textEndOffset - 1];
 
@@ -2439,7 +2459,7 @@
         if (foundEnd) {
             // FIXME: This is a workaround for the fact that the end of a run is often at the wrong
             // position for emitted '\n's.
-            if (len == 1 && it.characters()[0] == '\n') {
+            if (len == 1 && it.characterAt(0) == '\n') {
                 scope->document()->updateLayoutIgnorePendingStylesheets();
                 it.advance();
                 if (!it.atEnd()) {
@@ -2531,82 +2551,38 @@
 }
 
 // --------
-    
-UChar* plainTextToMallocAllocatedBuffer(const Range* r, unsigned& bufferLength, bool isDisplayString, TextIteratorBehavior defaultBehavior)
-{
-    UChar* result = 0;
 
+String plainText(const Range* r, TextIteratorBehavior defaultBehavior, bool isDisplayString)
+{
     // The initial buffer size can be critical for performance: https://bugs.webkit.org/show_bug.cgi?id=81192
     static const unsigned cMaxSegmentSize = 1 << 15;
-    bufferLength = 0;
-    typedef pair<UChar*, unsigned> TextSegment;
-    OwnPtr<Vector<TextSegment> > textSegments;
-    Vector<UChar> textBuffer;
-    textBuffer.reserveInitialCapacity(cMaxSegmentSize);
+
+    unsigned bufferLength = 0;
+    StringBuilder builder;
+    builder.reserveCapacity(cMaxSegmentSize);
     TextIteratorBehavior behavior = defaultBehavior;
     if (!isDisplayString)
         behavior = static_cast<TextIteratorBehavior>(behavior | TextIteratorEmitsTextsWithoutTranscoding);
     
     for (TextIterator it(r, behavior); !it.atEnd(); it.advance()) {
-        if (textBuffer.size() && textBuffer.size() + it.length() > cMaxSegmentSize) {
-            UChar* newSegmentBuffer = static_cast<UChar*>(malloc(textBuffer.size() * sizeof(UChar)));
-            if (!newSegmentBuffer)
-                goto exit;
-            memcpy(newSegmentBuffer, textBuffer.data(), textBuffer.size() * sizeof(UChar));
-            if (!textSegments)
-                textSegments = adoptPtr(new Vector<TextSegment>);
-            textSegments->append(make_pair(newSegmentBuffer, (unsigned)textBuffer.size()));
-            textBuffer.clear();
-        }
-        textBuffer.append(it.characters(), it.length());
+        if (builder.capacity() < builder.length() + it.length())
+            builder.reserveCapacity(builder.capacity() + cMaxSegmentSize);
+
+        it.appendTextToStringBuilder(builder);
         bufferLength += it.length();
     }
 
     if (!bufferLength)
-        return 0;
+        return emptyString();
 
-    // Since we know the size now, we can make a single buffer out of the pieces with one big alloc
-    result = static_cast<UChar*>(malloc(bufferLength * sizeof(UChar)));
-    if (!result)
-        goto exit;
+    String result = builder.toString();
 
-    {
-        UChar* resultPos = result;
-        if (textSegments) {
-            unsigned size = textSegments->size();
-            for (unsigned i = 0; i < size; ++i) {
-                const TextSegment& segment = textSegments->at(i);
-                memcpy(resultPos, segment.first, segment.second * sizeof(UChar));
-                resultPos += segment.second;
-            }
-        }
-        memcpy(resultPos, textBuffer.data(), textBuffer.size() * sizeof(UChar));
-    }
-
-exit:
-    if (textSegments) {
-        unsigned size = textSegments->size();
-        for (unsigned i = 0; i < size; ++i)
-            free(textSegments->at(i).first);
-    }
-    
     if (isDisplayString && r->ownerDocument())
-        r->ownerDocument()->displayBufferModifiedByEncoding(result, bufferLength);
+        r->ownerDocument()->displayStringModifiedByEncoding(result);
 
     return result;
 }
 
-String plainText(const Range* r, TextIteratorBehavior defaultBehavior)
-{
-    unsigned length;
-    UChar* buf = plainTextToMallocAllocatedBuffer(r, length, false, defaultBehavior);
-    if (!buf)
-        return "";
-    String result(buf, length);
-    free(buf);
-    return result;
-}
-
 static inline bool isAllCollapsibleWhitespace(const String& string)
 {
     const UChar* characters = string.characters();

Modified: trunk/Source/WebCore/editing/TextIterator.h (135971 => 135972)


--- trunk/Source/WebCore/editing/TextIterator.h	2012-11-28 05:24:15 UTC (rev 135971)
+++ trunk/Source/WebCore/editing/TextIterator.h	2012-11-28 05:27:34 UTC (rev 135972)
@@ -60,8 +60,7 @@
     }
 }
 
-String plainText(const Range*, TextIteratorBehavior defaultBehavior = TextIteratorDefaultBehavior);
-UChar* plainTextToMallocAllocatedBuffer(const Range*, unsigned& bufferLength, bool isDisplayString, TextIteratorBehavior = TextIteratorDefaultBehavior);
+String plainText(const Range*, TextIteratorBehavior defaultBehavior = TextIteratorDefaultBehavior, bool isDisplayString = false);
 PassRefPtr<Range> findPlainText(const Range*, const String&, FindOptions);
 
 class BitStack {
@@ -94,7 +93,9 @@
     void advance();
     
     int length() const { return m_textLength; }
-    const UChar* characters() const { return m_textCharacters; }
+    const UChar* characters() const { return m_textCharacters ? m_textCharacters : m_text.characters() + startOffset(); }
+    UChar characterAt(unsigned index) const;
+    void appendTextToStringBuilder(StringBuilder&) const;
     
     PassRefPtr<Range> range() const;
     Node* node() const;
@@ -105,6 +106,8 @@
     static PassRefPtr<Range> subrange(Range* entireRange, int characterOffset, int characterCount);
     
 private:
+    int startOffset() const { return m_positionStartOffset; }
+    const String& string() const { return m_text; }
     void exitNode();
     bool shouldRepresentNodeOffsetZero();
     bool shouldEmitSpaceBeforeAndAfterNode(Node*);
@@ -139,7 +142,7 @@
     mutable Node* m_positionOffsetBaseNode;
     mutable int m_positionStartOffset;
     mutable int m_positionEndOffset;
-    const UChar* m_textCharacters;
+    const UChar* m_textCharacters; // If null, then use m_text for character data.
     int m_textLength;
     // Hold string m_textCharacters points to so we ensure it won't be deleted.
     String m_text;

Modified: trunk/Source/WebCore/page/ContextMenuController.cpp (135971 => 135972)


--- trunk/Source/WebCore/page/ContextMenuController.cpp	2012-11-28 05:24:15 UTC (rev 135971)
+++ trunk/Source/WebCore/page/ContextMenuController.cpp	2012-11-28 05:27:34 UTC (rev 135972)
@@ -702,9 +702,8 @@
     // Current algorithm: look for a character that's not just a separator.
     for (TextIterator it(frame->selection()->toNormalizedRange().get()); !it.atEnd(); it.advance()) {
         int length = it.length();
-        const UChar* characters = it.characters();
         for (int i = 0; i < length; ++i)
-            if (!(category(characters[i]) & (Separator_Space | Separator_Line | Separator_Paragraph)))
+            if (!(category(it.characterAt(i)) & (Separator_Space | Separator_Line | Separator_Paragraph)))
                 return true;
     }
     return false;

Modified: trunk/Source/WebKit/mac/ChangeLog (135971 => 135972)


--- trunk/Source/WebKit/mac/ChangeLog	2012-11-28 05:24:15 UTC (rev 135971)
+++ trunk/Source/WebKit/mac/ChangeLog	2012-11-28 05:27:34 UTC (rev 135972)
@@ -1,3 +1,15 @@
+2012-11-27  Michael Saboff  <msab...@apple.com>
+
+        TextIterator unnecessarily converts 8 bit strings to 16 bits
+        https://bugs.webkit.org/show_bug.cgi?id=103295
+
+        Reviewed by Brent Fulgham.
+
+        Updated _stringForRange to use plainText() instead of removed plainTextToMallocAllocatedBuffer().
+
+        * WebView/WebFrame.mm:
+        (-[WebFrame _stringForRange:]):
+
 2012-11-27  James Simonsen  <simon...@chromium.org>
 
         Consolidate FrameLoader::load() into one function taking a FrameLoadRequest

Modified: trunk/Source/WebKit/mac/WebView/WebFrame.mm (135971 => 135972)


--- trunk/Source/WebKit/mac/WebView/WebFrame.mm	2012-11-28 05:24:15 UTC (rev 135971)
+++ trunk/Source/WebKit/mac/WebView/WebFrame.mm	2012-11-28 05:27:34 UTC (rev 135972)
@@ -498,15 +498,7 @@
 
 - (NSString *)_stringForRange:(DOMRange *)range
 {
-    // This will give a system malloc'd buffer that can be turned directly into an NSString
-    unsigned length;
-    UChar* buf = plainTextToMallocAllocatedBuffer(core(range), length, true);
-    
-    if (!buf)
-        return [NSString string];
-
-    // Transfer buffer ownership to NSString
-    return [[[NSString alloc] initWithCharactersNoCopy:buf length:length freeWhenDone:YES] autorelease];
+    return plainText(core(range), TextIteratorDefaultBehavior, true);
 }
 
 - (BOOL)_shouldFlattenCompositingLayers:(CGContextRef)context
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
http://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to