Bug 691001 part 1. Hoist property check out of tight loop / prevent unnecessary Namespace object creation. r=brendan
authorAndrew Paprocki <andrew@ishiboo.com>
Mon, 24 Oct 2011 21:45:17 -0400
changeset 79241 2fef1412e0e8ec4ef8b60f0c4194907ac17bc58f
parent 79240 8f1b74f0b569841beb197ea4c38a2b3772ea455b
child 79242 bdbdde9ab432abde409bf1be9322bff54b4e925c
push id21380
push userbmo@edmorley.co.uk
push dateWed, 26 Oct 2011 23:31:27 +0000
treeherdermozilla-central@16a8d2ab5240 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbrendan
bugs691001
milestone10.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 691001 part 1. Hoist property check out of tight loop / prevent unnecessary Namespace object creation. r=brendan
js/src/jsxml.cpp
--- a/js/src/jsxml.cpp
+++ b/js/src/jsxml.cpp
@@ -2371,29 +2371,26 @@ namespace_match(const void *a, const voi
     return EqualStrings(nsa->getNameURI(), nsb->getNameURI());
 }
 
 /* ECMA-357 10.2.1 and 10.2.2 */
 #define TO_SOURCE_FLAG 0x80000000
 
 static JSString *
 XMLToXMLString(JSContext *cx, JSXML *xml, const JSXMLArray *ancestorNSes,
-               uint32 indentLevel)
-{
-    JSBool pretty, indentKids;
+               uint32 indentLevel, JSBool pretty)
+{
+    JSBool indentKids;
     StringBuffer sb(cx);
     JSString *str;
     JSLinearString *prefix, *nsuri;
     uint32 i, n, nextIndentLevel;
     JSObject *ns, *ns2;
     AutoNamespaceArray empty(cx), decls(cx), ancdecls(cx);
 
-    if (!GetBooleanXMLSetting(cx, js_prettyPrinting_str, &pretty))
-        return NULL;
-
     if (pretty) {
         if (!sb.appendN(' ', indentLevel & ~TO_SOURCE_FLAG))
             return NULL;
     }
 
     str = NULL;
 
     switch (xml->xml_class) {
@@ -2428,17 +2425,17 @@ XMLToXMLString(JSContext *cx, JSXML *xml
             JSXMLArrayCursor cursor(&xml->xml_kids);
             i = 0;
             while (JSXML *kid = (JSXML *) cursor.getNext()) {
                 if (pretty && i != 0) {
                     if (!sb.append('\n'))
                         return NULL;
                 }
 
-                JSString *kidstr = XMLToXMLString(cx, kid, ancestorNSes, indentLevel);
+                JSString *kidstr = XMLToXMLString(cx, kid, ancestorNSes, indentLevel, pretty);
                 if (!kidstr || !sb.append(kidstr))
                     return NULL;
                 ++i;
             }
         }
 
         if (sb.empty())
             return cx->runtime->emptyString;
@@ -2447,18 +2444,26 @@ XMLToXMLString(JSContext *cx, JSXML *xml
       default:;
     }
 
     /* After this point, control must flow through label out: to exit. */
     if (!js_EnterLocalRootScope(cx))
         return NULL;
 
     /* ECMA-357 10.2.1 step 8 onward: handle ToXMLString on an XML element. */
-    if (!ancestorNSes)
+    if (!ancestorNSes) {
+        // Ensure a namespace with empty strings exists in the initial array,
+        // otherwise every call to GetNamespace() when running toString() on
+        // an XML object with no namespace defined will create a new Namespace
+        // object on every call.
+        JSObject *emptyns = NewXMLNamespace(cx, cx->runtime->emptyString, cx->runtime->emptyString, JS_FALSE);
+        if (!emptyns || !XMLARRAY_APPEND(cx, &empty.array, emptyns))
+            goto out;
         ancestorNSes = &empty.array;
+    }
 
     /* Clone in-scope namespaces not in ancestorNSes into decls. */
     {
         JSXMLArrayCursor cursor(&xml->xml_namespaces);
         while ((ns = (JSObject *) cursor.getNext()) != NULL) {
             if (!IsDeclared(ns))
                 continue;
             if (!XMLARRAY_HAS_MEMBER(ancestorNSes, ns, namespace_identity)) {
@@ -2687,17 +2692,17 @@ XMLToXMLString(JSContext *cx, JSXML *xml
         {
             JSXMLArrayCursor cursor(&xml->xml_kids);
             while (JSXML *kid = (JSXML *) cursor.getNext()) {
                 if (pretty && indentKids) {
                     if (!sb.append('\n'))
                         goto out;
                 }
 
-                JSString *kidstr = XMLToXMLString(cx, kid, &ancdecls.array, nextIndentLevel);
+                JSString *kidstr = XMLToXMLString(cx, kid, &ancdecls.array, nextIndentLevel, pretty);
                 if (!kidstr)
                     goto out;
 
                 if (!sb.append(kidstr))
                     goto out;
             }
         }
 
@@ -2752,20 +2757,24 @@ ToXMLString(JSContext *cx, jsval v, uint
             return NULL;
         JSString *str = js_ValueToString(cx, v);
         if (!str)
             return NULL;
         StringBuffer sb(cx);
         return EscapeElementValue(cx, sb, str, toSourceFlag);
     }
 
+    JSBool pretty;
+    if (!GetBooleanXMLSetting(cx, js_prettyPrinting_str, &pretty))
+        return NULL;
+
     /* Handle non-element cases in this switch, returning from each case. */
     JS::Anchor<JSObject *> anch(obj);
     JSXML *xml = reinterpret_cast<JSXML *>(obj->getPrivate());
-    return XMLToXMLString(cx, xml, NULL, toSourceFlag | 0);
+    return XMLToXMLString(cx, xml, NULL, toSourceFlag | 0, pretty);
 }
 
 static JSObject *
 ToAttributeName(JSContext *cx, jsval v)
 {
     JSLinearString *uri, *prefix;
     JSObject *obj;
     Class *clasp;