DOM/textarea-edit.html spends 35% of time in numGraphemeClusters
authorrniwa@webkit.org <rniwa@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 9 Oct 2012 22:19:16 +0000 (22:19 +0000)
committerrniwa@webkit.org <rniwa@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 9 Oct 2012 22:19:16 +0000 (22:19 +0000)
https://bugs.webkit.org/show_bug.cgi?id=98711

Reviewed by Kent Tamura.

Since the number of characters is always greater than the number of grapheme clusters,
we can avoid calling computeLengthForSubmission when the number of characters is less
than maxlength. We still have to count the number of LFs since they all need to be
converted into CRLFs. This improves WebKit's score on DOM/textarea-edit.html by 45%.

* html/HTMLTextAreaElement.cpp:
(WebCore::computeLengthForSubmission):
(WebCore::numberOfLineBreaks):
(WebCore::upperBoundForLengthForSubmission): Added.
(WebCore::HTMLTextAreaElement::handleBeforeTextInsertedEvent):
(WebCore::HTMLTextAreaElement::tooLong):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@130818 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebCore/ChangeLog
Source/WebCore/html/HTMLTextAreaElement.cpp

index e87e0e5..77ce8bd 100644 (file)
@@ -1,3 +1,22 @@
+2012-10-09  Ryosuke Niwa  <rniwa@webkit.org>
+
+        DOM/textarea-edit.html spends 35% of time in numGraphemeClusters
+        https://bugs.webkit.org/show_bug.cgi?id=98711
+
+        Reviewed by Kent Tamura.
+
+        Since the number of characters is always greater than the number of grapheme clusters,
+        we can avoid calling computeLengthForSubmission when the number of characters is less
+        than maxlength. We still have to count the number of LFs since they all need to be
+        converted into CRLFs. This improves WebKit's score on DOM/textarea-edit.html by 45%.
+
+        * html/HTMLTextAreaElement.cpp:
+        (WebCore::computeLengthForSubmission):
+        (WebCore::numberOfLineBreaks):
+        (WebCore::upperBoundForLengthForSubmission): Added.
+        (WebCore::HTMLTextAreaElement::handleBeforeTextInsertedEvent):
+        (WebCore::HTMLTextAreaElement::tooLong):
+
 2012-10-09  Nate Chapin  <japhet@chromium.org>
 
         Make CachedResourceLoader RefCounted and have both Document
index a42aa78..db98ccc 100644 (file)
@@ -56,10 +56,15 @@ static const int defaultCols = 20;
 
 // On submission, LF characters are converted into CRLF.
 // This function returns number of characters considering this.
-static unsigned computeLengthForSubmission(const String& text)
+static inline unsigned computeLengthForSubmission(const String& text, unsigned numberOfLineBreaks)
+{
+    return numGraphemeClusters(text) + numberOfLineBreaks;
+}
+
+static unsigned numberOfLineBreaks(const String& text)
 {
-    unsigned count =  numGraphemeClusters(text);
     unsigned length = text.length();
+    unsigned count = 0;
     for (unsigned i = 0; i < length; i++) {
         if (text[i] == '\n')
             count++;
@@ -67,6 +72,16 @@ static unsigned computeLengthForSubmission(const String& text)
     return count;
 }
 
+static inline unsigned computeLengthForSubmission(const String& text)
+{
+    return numGraphemeClusters(text) + numberOfLineBreaks(text);
+}
+
+static inline unsigned upperBoundForLengthForSubmission(const String& text, unsigned numberOfLineBreaks)
+{
+    return text.length() + numberOfLineBreaks;
+}
+
 HTMLTextAreaElement::HTMLTextAreaElement(const QualifiedName& tagName, Document* document, HTMLFormElement* form)
     : HTMLTextFormControlElement(tagName, document, form)
     , m_rows(defaultRows)
@@ -280,7 +295,13 @@ void HTMLTextAreaElement::handleBeforeTextInsertedEvent(BeforeTextInsertedEvent*
         return;
     unsigned unsignedMaxLength = static_cast<unsigned>(signedMaxLength);
 
-    unsigned currentLength = computeLengthForSubmission(innerTextValue());
+    const String& currentValue = innerTextValue();
+    unsigned numberOfLineBreaksInCurrentValue = numberOfLineBreaks(currentValue);
+    if (upperBoundForLengthForSubmission(currentValue, numberOfLineBreaksInCurrentValue)
+        + upperBoundForLengthForSubmission(event->text(), numberOfLineBreaks(event->text())) < unsignedMaxLength)
+        return;
+
+    unsigned currentLength = computeLengthForSubmission(currentValue, numberOfLineBreaksInCurrentValue);
     // selectionLength represents the selection length of this text field to be
     // removed by this insertion.
     // If the text field has no focus, we don't need to take account of the
@@ -466,7 +487,10 @@ bool HTMLTextAreaElement::tooLong(const String& value, NeedsToCheckDirtyFlag che
     int max = maxLength();
     if (max < 0)
         return false;
-    return computeLengthForSubmission(value) > static_cast<unsigned>(max);
+    unsigned unsignedMax = static_cast<unsigned>(max);
+    unsigned numberOfLineBreaksInValue = numberOfLineBreaks(value);
+    return upperBoundForLengthForSubmission(value, numberOfLineBreaksInValue) > unsignedMax
+        && computeLengthForSubmission(value, numberOfLineBreaksInValue) > unsignedMax;
 }
 
 bool HTMLTextAreaElement::isValidValue(const String& candidate) const