Bug 678998 - Make the QName localName slot store a local name that's been atomized, for simplicity. r=luke
authorJeff Walden <jwalden@mit.edu>
Mon, 15 Aug 2011 00:12:48 -0400
changeset 75295 c6a3b64dcac076dbca8ad87ff165be85d6fd3da2
parent 75294 36ddaaab6e57b212a8dc21d184d592c61796e1fc
child 75296 c36563ee6447afd04561b1ba9f30e740c43261b8
push id1224
push userjwalden@mit.edu
push dateMon, 15 Aug 2011 19:43:03 +0000
treeherdermozilla-inbound@c36563ee6447 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersluke
bugs678998
milestone8.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 678998 - Make the QName localName slot store a local name that's been atomized, for simplicity. r=luke
js/src/jscntxt.h
js/src/jsobj.h
js/src/jsobjinlines.h
js/src/jsxml.cpp
--- a/js/src/jscntxt.h
+++ b/js/src/jscntxt.h
@@ -530,17 +530,17 @@ struct JSRuntime
     JSTraceDataOp       gcExtraRootsTraceOp;
     void                *gcExtraRootsData;
 
     /* Well-known numbers held for use by this runtime's contexts. */
     js::Value           NaNValue;
     js::Value           negativeInfinityValue;
     js::Value           positiveInfinityValue;
 
-    JSFlatString        *emptyString;
+    JSAtom              *emptyString;
 
     /* List of active contexts sharing this runtime; protected by gcLock. */
     JSCList             contextList;
 
     /* Per runtime debug hooks -- see jsprvtd.h and jsdbgapi.h. */
     JSDebugHooks        globalDebugHooks;
 
     /* If true, new compartments are initially in debug mode. */
--- a/js/src/jsobj.h
+++ b/js/src/jsobj.h
@@ -1078,19 +1078,19 @@ struct JSObject : js::gc::Cell {
 
     inline JSLinearString *getNameURI() const;
     inline jsval getNameURIVal() const;
     inline void setNameURI(JSLinearString *uri);
 
     inline jsval getNamespaceDeclared() const;
     inline void setNamespaceDeclared(jsval decl);
 
-    inline JSLinearString *getQNameLocalName() const;
+    inline JSAtom *getQNameLocalName() const;
     inline jsval getQNameLocalNameVal() const;
-    inline void setQNameLocalName(JSLinearString *name);
+    inline void setQNameLocalName(JSAtom *name);
 
     /*
      * Proxy-specific getters and setters.
      */
 
     inline js::JSProxyHandler *getProxyHandler() const;
     inline const js::Value &getProxyPrivate() const;
     inline void setProxyPrivate(const js::Value &priv);
--- a/js/src/jsobjinlines.h
+++ b/js/src/jsobjinlines.h
@@ -640,33 +640,33 @@ JSObject::getNamespaceDeclared() const
 
 inline void
 JSObject::setNamespaceDeclared(jsval decl)
 {
     JS_ASSERT(isNamespace());
     setSlot(JSSLOT_NAMESPACE_DECLARED, js::Valueify(decl));
 }
 
-inline JSLinearString *
+inline JSAtom *
 JSObject::getQNameLocalName() const
 {
     JS_ASSERT(isQName());
     const js::Value &v = getSlot(JSSLOT_QNAME_LOCAL_NAME);
-    return !v.isUndefined() ? &v.toString()->asLinear() : NULL;
+    return !v.isUndefined() ? &v.toString()->asAtom() : NULL;
 }
 
 inline jsval
 JSObject::getQNameLocalNameVal() const
 {
     JS_ASSERT(isQName());
     return js::Jsvalify(getSlot(JSSLOT_QNAME_LOCAL_NAME));
 }
 
 inline void
-JSObject::setQNameLocalName(JSLinearString *name)
+JSObject::setQNameLocalName(JSAtom *name)
 {
     JS_ASSERT(isQName());
     setSlot(JSSLOT_QNAME_LOCAL_NAME, name ? js::StringValue(name) : js::UndefinedValue());
 }
 
 inline JSObject *
 JSObject::getWithThis() const
 {
--- a/js/src/jsxml.cpp
+++ b/js/src/jsxml.cpp
@@ -466,17 +466,17 @@ qname_toString(JSContext *cx, uintN argc
 static JSFunctionSpec qname_methods[] = {
     JS_FN(js_toString_str,  qname_toString,    0,0),
     JS_FS_END
 };
 
 
 static bool
 InitXMLQName(JSContext *cx, JSObject *obj, JSLinearString *uri, JSLinearString *prefix,
-             JSLinearString *localName)
+             JSAtom *localName)
 {
     JS_ASSERT(obj->isQName());
     JS_ASSERT(JSVAL_IS_VOID(obj->getNamePrefixVal()));
     JS_ASSERT(JSVAL_IS_VOID(obj->getNameURIVal()));
     JS_ASSERT(JSVAL_IS_VOID(obj->getQNameLocalNameVal()));
 
     /* Per ECMA-357, 13.3.5, these properties must be "own". */
     if (!JS_DefineProperties(cx, obj, qname_props))
@@ -488,29 +488,29 @@ InitXMLQName(JSContext *cx, JSObject *ob
         obj->setNamePrefix(prefix);
     if (localName)
         obj->setQNameLocalName(localName);
     return true;
 }
 
 static JSObject *
 NewXMLQName(JSContext *cx, JSLinearString *uri, JSLinearString *prefix,
-            JSLinearString *localName)
+            JSAtom *localName)
 {
     JSObject *obj = NewBuiltinClassInstanceXML(cx, &js_QNameClass);
     if (!obj)
         return NULL;
     if (!InitXMLQName(cx, obj, uri, prefix, localName))
         return NULL;
     return obj;
 }
 
 static JSObject *
 NewXMLAttributeName(JSContext *cx, JSLinearString *uri, JSLinearString *prefix,
-                    JSLinearString *localName)
+                    JSAtom *localName)
 {
     /*
      * AttributeName is an internal anonymous class which instances are not
      * exposed to scripts.
      */
     JSObject *parent = GetGlobalForScopeChain(cx);
     JSObject *obj = NewNonFunction<WithProto::Given>(cx, &js_AttributeNameClass, NULL, parent);
     if (!obj)
@@ -714,19 +714,20 @@ Namespace(JSContext *cx, uintN argc, Val
  * if argc is 1 and argv[0] is JSVAL_VOID.
  */
 static JSBool
 QNameHelper(JSContext *cx, JSObject *obj, intN argc, jsval *argv, jsval *rval)
 {
     jsval nameval, nsval;
     JSBool isQName, isNamespace;
     JSObject *qn;
-    JSLinearString *uri, *prefix, *name;
+    JSLinearString *uri, *prefix;
     JSObject *obj2;
 
+    JSAtom *name;
     if (argc <= 0) {
         nameval = JSVAL_VOID;
         isQName = JS_FALSE;
     } else {
         nameval = argv[argc > 1];
         isQName =
             !JSVAL_IS_PRIMITIVE(nameval) &&
             JSVAL_TO_OBJECT(nameval)->getClass() == &js_QNameClass;
@@ -761,23 +762,18 @@ QNameHelper(JSContext *cx, JSObject *obj
         nameval = qn->getQNameLocalNameVal();
     }
 
     if (argc == 0) {
         name = cx->runtime->emptyString;
     } else if (argc < 0) {
         name = cx->runtime->atomState.typeAtoms[JSTYPE_VOID];
     } else {
-        JSString *str = js_ValueToString(cx, Valueify(nameval));
-        if (!str)
-            return JS_FALSE;
-        name = str->ensureLinear(cx);
-        if (!name)
-            return JS_FALSE;
-        argv[argc > 1] = STRING_TO_JSVAL(name);
+        if (!js_ValueToAtom(cx, Valueify(nameval), &name))
+            return false;
     }
 
     if (argc > 1 && !JSVAL_IS_VOID(argv[0])) {
         nsval = argv[0];
     } else if (IS_STAR(name)) {
         nsval = JSVAL_NULL;
     } else {
         if (!js_GetDefaultXMLNamespace(cx, &nsval))
@@ -1161,30 +1157,32 @@ HAS_NS_AFTER_XML(const jschar *chars)
 static const char xml_namespace_str[] = "http://www.w3.org/XML/1998/namespace";
 static const char xmlns_namespace_str[] = "http://www.w3.org/2000/xmlns/";
 
 static JSObject *
 ParseNodeToQName(Parser *parser, JSParseNode *pn,
                  JSXMLArray *inScopeNSes, JSBool isAttributeName)
 {
     JSContext *cx = parser->context;
-    JSLinearString *str, *uri, *prefix, *localName;
+    JSLinearString *uri, *prefix;
     size_t length, offset;
     const jschar *start, *limit, *colon;
     uint32 n;
     JSObject *ns;
     JSLinearString *nsprefix;
 
     JS_ASSERT(pn->pn_arity == PN_NULLARY);
-    str = pn->pn_atom;
+    JSAtom *str = pn->pn_atom;
     start = str->chars();
     length = str->length();
     JS_ASSERT(length != 0 && *start != '@');
     JS_ASSERT(length != 1 || *start != '*');
 
+    JSAtom *localName;
+
     uri = cx->runtime->emptyString;
     limit = start + length;
     colon = js_strchr_limit(start, ':', limit);
     if (colon) {
         offset = colon - start;
         prefix = js_NewDependentString(cx, str, 0, offset);
         if (!prefix)
             return NULL;
@@ -1220,17 +1218,17 @@ ParseNodeToQName(Parser *parser, JSParse
             JSAutoByteString bytes;
             if (js_ValueToPrintable(parser->context, v, &bytes)) {
                 ReportCompileErrorNumber(parser->context, &parser->tokenStream, pn,
                                          JSREPORT_ERROR, JSMSG_BAD_XML_NAMESPACE, bytes.ptr());
             }
             return NULL;
         }
 
-        localName = js_NewStringCopyN(parser->context, colon + 1, length - (offset + 1));
+        localName = js_AtomizeChars(parser->context, colon + 1, length - (offset + 1));
         if (!localName)
             return NULL;
     } else {
         if (isAttributeName) {
             /*
              * An unprefixed attribute is not in any namespace, so set prefix
              * as well as uri to the empty string.
              */
@@ -2759,24 +2757,24 @@ ToXMLString(JSContext *cx, jsval v, uint
     JS::Anchor<JSObject *> anch(obj);
     JSXML *xml = reinterpret_cast<JSXML *>(obj->getPrivate());
     return XMLToXMLString(cx, xml, NULL, toSourceFlag | 0);
 }
 
 static JSObject *
 ToAttributeName(JSContext *cx, jsval v)
 {
-    JSLinearString *name, *uri, *prefix;
+    JSLinearString *uri, *prefix;
     JSObject *obj;
     Class *clasp;
     JSObject *qn;
 
+    JSAtom *name;
     if (JSVAL_IS_STRING(v)) {
-        name = JSVAL_TO_STRING(v)->ensureLinear(cx);
-        if (!name)
+        if (!js_ValueToAtom(cx, Valueify(v), &name))
             return NULL;
         uri = prefix = cx->runtime->emptyString;
     } else {
         if (JSVAL_IS_PRIMITIVE(v)) {
             js_ReportValueError(cx, JSMSG_BAD_XML_ATTR_NAME,
                                 JSDVG_IGNORE_STACK, Valueify(v), NULL);
             return NULL;
         }
@@ -2790,21 +2788,17 @@ ToAttributeName(JSContext *cx, jsval v)
             qn = obj;
             uri = qn->getNameURI();
             prefix = qn->getNamePrefix();
             name = qn->getQNameLocalName();
         } else {
             if (clasp == &js_AnyNameClass) {
                 name = cx->runtime->atomState.starAtom;
             } else {
-                JSString *str = js_ValueToString(cx, Valueify(v));
-                if (!str)
-                    return NULL;
-                name = str->ensureLinear(cx);
-                if (!name)
+                if (!js_ValueToAtom(cx, Valueify(v), &name))
                     return NULL;
             }
             uri = prefix = cx->runtime->emptyString;
         }
     }
 
     qn = NewXMLAttributeName(cx, uri, prefix, name);
     if (!qn)
@@ -2816,25 +2810,24 @@ static void
 ReportBadXMLName(JSContext *cx, const Value &idval)
 {
     js_ReportValueError(cx, JSMSG_BAD_XML_NAME, JSDVG_IGNORE_STACK, idval, NULL);
 }
 
 static JSBool
 IsFunctionQName(JSContext *cx, JSObject *qn, jsid *funidp)
 {
-    JSAtom *atom;
-    JSLinearString *uri;
-
-    atom = cx->runtime->atomState.functionNamespaceURIAtom;
-    uri = qn->getNameURI();
-    if (uri && (uri == atom || EqualStrings(uri, atom)))
-        return JS_ValueToId(cx, STRING_TO_JSVAL(qn->getQNameLocalName()), funidp);
+    JSAtom *atom = cx->runtime->atomState.functionNamespaceURIAtom;
+    JSLinearString *uri = qn->getNameURI();
+    if (uri && (uri == atom || EqualStrings(uri, atom))) {
+        *funidp = ATOM_TO_JSID(qn->getQNameLocalName());
+        return true;
+    }
     *funidp = JSID_VOID;
-    return JS_TRUE;
+    return true;
 }
 
 JSBool
 js_IsFunctionQName(JSContext *cx, JSObject *obj, jsid *funidp)
 {
     if (obj->getClass() == &js_QNameClass)
         return IsFunctionQName(cx, obj, funidp);
     *funidp = JSID_VOID;
@@ -6440,39 +6433,30 @@ xml_setChildren(JSContext *cx, uintN arg
 
     *vp = OBJECT_TO_JSVAL(obj);
     return JS_TRUE;
 }
 
 static JSBool
 xml_setLocalName(JSContext *cx, uintN argc, jsval *vp)
 {
-    jsval name;
-    JSObject *nameqn;
-    JSLinearString *namestr;
-
     NON_LIST_XML_METHOD_PROLOG;
     if (!JSXML_HAS_NAME(xml))
         return JS_TRUE;
 
+    JSAtom *namestr;
     if (argc == 0) {
         namestr = cx->runtime->atomState.typeAtoms[JSTYPE_VOID];
     } else {
-        name = vp[2];
-        if (!JSVAL_IS_PRIMITIVE(name) &&
-            JSVAL_TO_OBJECT(name)->getClass() == &js_QNameClass) {
-            nameqn = JSVAL_TO_OBJECT(name);
-            namestr = nameqn->getQNameLocalName();
+        jsval name = vp[2];
+        if (!JSVAL_IS_PRIMITIVE(name) && JSVAL_TO_OBJECT(name)->isQName()) {
+            namestr = JSVAL_TO_OBJECT(name)->getQNameLocalName();
         } else {
-            if (!JS_ConvertValue(cx, name, JSTYPE_STRING, &vp[2]))
-                return JS_FALSE;
-            name = vp[2];
-            namestr = JSVAL_TO_STRING(name)->ensureLinear(cx);
-            if (!namestr)
-                return JS_FALSE;
+            if (!js_ValueToAtom(cx, Valueify(name), &namestr))
+                return false;
         }
     }
 
     xml = CHECK_COPY_ON_WRITE(cx, xml, obj);
     if (!xml)
         return JS_FALSE;
     if (namestr)
         xml->name->setQNameLocalName(namestr);
@@ -7147,17 +7131,17 @@ js_InitQNameClass(JSContext *cx, JSObjec
 {
     JS_ASSERT(obj->isNative());
 
     GlobalObject *global = obj->asGlobal();
 
     JSObject *qnameProto = global->createBlankPrototype(cx, &js_QNameClass);
     if (!qnameProto)
         return NULL;
-    JSFlatString *empty = cx->runtime->emptyString;
+    JSAtom *empty = cx->runtime->emptyString;
     if (!InitXMLQName(cx, qnameProto, empty, empty, empty))
         return NULL;
     qnameProto->syncSpecialEquality();
 
     const uintN QNAME_CTOR_LENGTH = 2;
     JSFunction *ctor = global->createConstructor(cx, QName, &js_QNameClass,
                                                  CLASS_ATOM(cx, QName), QNAME_CTOR_LENGTH);
     if (!ctor)
@@ -7777,20 +7761,20 @@ js_NewXMLSpecialObject(JSContext *cx, JS
         return js_NewXMLObject(cx, JSXML_CLASS_TEXT);
     }
 
     obj = js_NewXMLObject(cx, xml_class);
     if (!obj)
         return NULL;
     xml = (JSXML *) obj->getPrivate();
     if (name) {
-        JSLinearString *linearName = name->ensureLinear(cx);
-        if (!linearName)
+        JSAtom *atomName = js_AtomizeString(cx, name);
+        if (!atomName)
             return NULL;
-        qn = NewXMLQName(cx, cx->runtime->emptyString, NULL, linearName);
+        qn = NewXMLQName(cx, cx->runtime->emptyString, NULL, atomName);
         if (!qn)
             return NULL;
         xml->name = qn;
     }
     xml->xml_value = value;
     return obj;
 }