2009-02-12 Darin Adler <darin@apple.com>
authordarin@apple.com <darin@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 13 Feb 2009 16:20:16 +0000 (16:20 +0000)
committerdarin@apple.com <darin@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 13 Feb 2009 16:20:16 +0000 (16:20 +0000)
        Reviewed by Oliver Hunt.

        Speed up document.write a bit.

        * bindings/js/JSHTMLDocumentCustom.cpp:
        (WebCore::documentWrite): Added. Uses SegmentedString to avoid conversion from
        UString to String and to avoid appending strings. Also added code to handle
        newlines efficiently.
        (WebCore::JSHTMLDocument::write): Changed to use documentWrite.
        (WebCore::JSHTMLDocument::writeln): Ditto.

        * dom/Document.cpp:
        (WebCore::Document::prepareToWrite): Added. Refactored the initialization part
        of write into a separate function for use in the JavaScript binding.
        (WebCore::Document::write): Changed to call prepareToWrite.

        * dom/Document.h: Added declaration for prepareToWrite.

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

WebCore/ChangeLog
WebCore/bindings/js/JSHTMLDocumentCustom.cpp
WebCore/dom/Document.cpp
WebCore/dom/Document.h

index fccaa7e..5ca4547 100644 (file)
@@ -1,3 +1,23 @@
+2009-02-12  Darin Adler  <darin@apple.com>
+
+        Reviewed by Oliver Hunt.
+
+        Speed up document.write a bit.
+
+        * bindings/js/JSHTMLDocumentCustom.cpp:
+        (WebCore::documentWrite): Added. Uses SegmentedString to avoid conversion from
+        UString to String and to avoid appending strings. Also added code to handle
+        newlines efficiently.
+        (WebCore::JSHTMLDocument::write): Changed to use documentWrite.
+        (WebCore::JSHTMLDocument::writeln): Ditto.
+
+        * dom/Document.cpp:
+        (WebCore::Document::prepareToWrite): Added. Refactored the initialization part
+        of write into a separate function for use in the JavaScript binding.
+        (WebCore::Document::write): Changed to call prepareToWrite.
+
+        * dom/Document.h: Added declaration for prepareToWrite.
+
 2009-02-13  Prasanth Ullattil  <pullatti@trolltech.com>
 
         Reviewed by Simon Hausmann.
index be2d158..310cde2 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -26,6 +26,7 @@
 #include "config.h"
 #include "JSHTMLDocument.h"
 
+#include "CharacterNames.h"
 #include "Frame.h"
 #include "HTMLBodyElement.h"
 #include "HTMLCollection.h"
@@ -37,6 +38,8 @@
 #include "JSDOMWindowCustom.h"
 #include "JSDOMWindowShell.h"
 #include "JSHTMLCollection.h"
+#include "SegmentedString.h"
+#include "Tokenizer.h"
 #include <runtime/Error.h>
 
 using namespace JSC;
@@ -124,32 +127,47 @@ JSValuePtr JSHTMLDocument::open(ExecState* exec, const ArgList& args)
     return this;
 }
 
-static String writeHelper(ExecState* exec, const ArgList& args)
-{
-    // DOM only specifies single string argument, but NS & IE allow multiple
-    // or no arguments.
+enum NewlineRequirement { DoNotAddNewline, DoAddNewline };
 
-    unsigned size = args.size();
-    if (size == 1)
-        return args.at(exec, 0).toString(exec);
+static inline void documentWrite(ExecState* exec, const ArgList& args, HTMLDocument* document, NewlineRequirement addNewline)
+{
+    // DOM only specifies single string argument, but browsers allow multiple or no arguments.
+
+    size_t size = args.size();
+
+    UString firstString = args.at(exec, 0).toString(exec);
+    SegmentedString segmentedString(firstString.data(), firstString.size());
+    Vector<UString> subsequentStrings; // Keeps strings alive until Tokenizer::write is called on them.
+    if (size != 1) {
+        if (!size)
+            segmentedString.clear();
+        else {
+            subsequentStrings.reserveInitialCapacity(size - 1);
+            for (size_t i = 1; i < size; ++i) {
+                UString subsequentString = args.at(exec, i).toString(exec);
+                segmentedString.append(SegmentedString(subsequentString.data(), subsequentString.size()));
+                subsequentStrings.append(subsequentString);
+            }
+        }
+    }
+    if (addNewline)
+        segmentedString.append(SegmentedString(&newlineCharacter, 1));
 
-    Vector<UChar> result;
-    for (unsigned i = 0; i < size; ++i)
-        append(result, args.at(exec, i).toString(exec));
-    return String::adopt(result);
+    Document* activeDocument = asJSDOMWindow(exec->lexicalGlobalObject())->impl()->document();
+    document->prepareToWrite(activeDocument);
+    if (Tokenizer* tokenizer = document->tokenizer())
+        tokenizer->write(segmentedString, false);
 }
 
 JSValuePtr JSHTMLDocument::write(ExecState* exec, const ArgList& args)
 {
-    Document* activeDocument = asJSDOMWindow(exec->lexicalGlobalObject())->impl()->document();
-    static_cast<HTMLDocument*>(impl())->write(writeHelper(exec, args), activeDocument);
+    documentWrite(exec, args, static_cast<HTMLDocument*>(impl()), DoNotAddNewline);
     return jsUndefined();
 }
 
 JSValuePtr JSHTMLDocument::writeln(ExecState* exec, const ArgList& args)
 {
-    Document* activeDocument = asJSDOMWindow(exec->lexicalGlobalObject())->impl()->document();
-    static_cast<HTMLDocument*>(impl())->write(writeHelper(exec, args) + "\n", activeDocument);
+    documentWrite(exec, args, static_cast<HTMLDocument*>(impl()), DoAddNewline);
     return jsUndefined();
 }
 
index f8b3cb7..8a0ed0c 100644 (file)
@@ -1687,22 +1687,29 @@ int Document::elapsedTime() const
     return static_cast<int>((currentTime() - m_startTime) * 1000);
 }
 
+void Document::prepareToWrite(Document* ownerDocument)
+{
+    if (m_tokenizer)
+        return;
+    open(ownerDocument);
+    ASSERT(m_tokenizer);
+    if (!m_tokenizer)
+        return;
+    UChar documentPrefix[] = { '<', 'h', 't', 'm', 'l', '>' };
+    m_tokenizer->write(SegmentedString(documentPrefix, sizeof(documentPrefix) / sizeof(documentPrefix[0])), false);
+}
+
 void Document::write(const String& text, Document* ownerDocument)
 {
 #ifdef INSTRUMENT_LAYOUT_SCHEDULING
     if (!ownerElement())
         printf("Beginning a document.write at %d\n", elapsedTime());
 #endif
-    
-    if (!m_tokenizer) {
-        open(ownerDocument);
-        ASSERT(m_tokenizer);
-        if (!m_tokenizer)
-            return;
-        write("<html>", ownerDocument);
-    }
-    m_tokenizer->write(text, false);
-    
+
+    prepareToWrite(ownerDocument);
+    if (m_tokenizer)
+        m_tokenizer->write(text, false);
+
 #ifdef INSTRUMENT_LAYOUT_SCHEDULING
     if (!ownerElement())
         printf("Ending a document.write at %d\n", elapsedTime());
index 12085c3..885b889 100644 (file)
@@ -426,6 +426,7 @@ public:
     void implicitClose();
     void cancelParsing();
 
+    void prepareToWrite(Document* ownerDocument);
     void write(const String& text, Document* ownerDocument = 0);
     void writeln(const String& text, Document* ownerDocument = 0);
     void finishParsing();