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 75328 c6a3b64dcac076dbca8ad87ff165be85d6fd3da2
parent 75327 36ddaaab6e57b212a8dc21d184d592c61796e1fc
child 75329 c36563ee6447afd04561b1ba9f30e740c43261b8
push id2
push userbsmedberg@mozilla.com
push dateFri, 19 Aug 2011 14:38:13 +0000
reviewersluke
bugs678998
milestone8.0a1
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;
 }