AnyName can't have a NULL parent (bug 617485, r=brendan).
authorAndreas Gal <gal@mozilla.com>
Fri, 21 Jan 2011 10:55:39 -0800
changeset 61208 74190651d91a9744f73b6ebf0360bf3f8580f0c0
parent 61207 e63f5adc428007495c5fa32d9ccfbcfcac149317
child 61209 34359bdfcde48e5765b8806c20343174aa909da6
push id18277
push usercleary@mozilla.com
push dateTue, 25 Jan 2011 03:52:51 +0000
treeherdermozilla-central@7ee91bd90e7a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbrendan
bugs617485
milestone2.0b10pre
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
AnyName can't have a NULL parent (bug 617485, r=brendan).
js/src/jsapi.h
js/src/jscompartment.cpp
js/src/jscompartment.h
js/src/jsproto.tbl
js/src/jsxml.cpp
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -1934,20 +1934,21 @@ struct JSClass {
 #define JSCLASS_MARK_IS_TRACE           (1<<(JSCLASS_HIGH_FLAGS_SHIFT+3))
 #define JSCLASS_INTERNAL_FLAG2          (1<<(JSCLASS_HIGH_FLAGS_SHIFT+4))
 
 /* Indicate whether the proto or ctor should be frozen. */
 #define JSCLASS_FREEZE_PROTO            (1<<(JSCLASS_HIGH_FLAGS_SHIFT+5))
 #define JSCLASS_FREEZE_CTOR             (1<<(JSCLASS_HIGH_FLAGS_SHIFT+6))
 
 /* Additional global reserved slots, beyond those for standard prototypes. */
-#define JSRESERVED_GLOBAL_SLOTS_COUNT     3
+#define JSRESERVED_GLOBAL_SLOTS_COUNT     4
 #define JSRESERVED_GLOBAL_THIS            (JSProto_LIMIT * 3)
 #define JSRESERVED_GLOBAL_THROWTYPEERROR  (JSRESERVED_GLOBAL_THIS + 1)
 #define JSRESERVED_GLOBAL_REGEXP_STATICS  (JSRESERVED_GLOBAL_THROWTYPEERROR + 1)
+#define JSRESERVED_GLOBAL_FUNCTION_NS     (JSRESERVED_GLOBAL_REGEXP_STATICS + 1)
 
 /*
  * ECMA-262 requires that most constructors used internally create objects
  * with "the original Foo.prototype value" as their [[Prototype]] (__proto__)
  * member initial value.  The "original ... value" verbiage is there because
  * in ECMA-262, global properties naming class objects are read/write and
  * deleteable, for the most part.
  *
--- a/js/src/jscompartment.cpp
+++ b/js/src/jscompartment.cpp
@@ -59,18 +59,16 @@ JSCompartment::JSCompartment(JSRuntime *
     principals(NULL),
     gcBytes(0),
     gcTriggerBytes(0),
     gcLastBytes(0),
     data(NULL),
     marked(false),
     active(false),
     debugMode(rt->debugMode),
-    anynameObject(NULL),
-    functionNamespaceObject(NULL),
     mathCache(NULL)
 {
     JS_INIT_CLIST(&scripts);
 
     PodArrayZero(scriptsToGC);
 }
 
 JSCompartment::~JSCompartment()
--- a/js/src/jscompartment.h
+++ b/js/src/jscompartment.h
@@ -369,26 +369,16 @@ struct JS_FRIEND_API(JSCompartment) {
 
 #ifdef JS_METHODJIT
     js::mjit::JaegerCompartment  *jaegerCompartment;
 #endif
 
     bool                         debugMode;  // true iff debug mode on
     JSCList                      scripts;    // scripts in this compartment
 
-    /*
-     * Weak references to lazily-created, well-known XML singletons.
-     *
-     * NB: Singleton objects must be carefully disconnected from the rest of
-     * the object graph usually associated with a JSContext's global object,
-     * including the set of standard class objects.  See jsxml.c for details.
-     */
-    JSObject                     *anynameObject;
-    JSObject                     *functionNamespaceObject;
-
     JSC::ExecutableAllocator     *regExpAllocator;
 
     js::NativeIterCache          nativeIterCache;
 
     JSCompartment(JSRuntime *cx);
     ~JSCompartment();
 
     bool init();
--- a/js/src/jsproto.tbl
+++ b/js/src/jsproto.tbl
@@ -94,13 +94,14 @@ JS_PROTO(Uint8Array,            29,     
 JS_PROTO(Int16Array,            30,     js_InitTypedArrayClasses)
 JS_PROTO(Uint16Array,           31,     js_InitTypedArrayClasses)
 JS_PROTO(Int32Array,            32,     js_InitTypedArrayClasses)
 JS_PROTO(Uint32Array,           33,     js_InitTypedArrayClasses)
 JS_PROTO(Float32Array,          34,     js_InitTypedArrayClasses)
 JS_PROTO(Float64Array,          35,     js_InitTypedArrayClasses)
 JS_PROTO(Uint8ClampedArray,     36,     js_InitTypedArrayClasses)
 JS_PROTO(Proxy,                 37,     js_InitProxyClass)
+JS_PROTO(AnyName,               38,     js_InitNullClass)
 
 #undef XML_INIT
 #undef NAMESPACE_INIT
 #undef QNAME_INIT
 #undef GENERATOR_INIT
--- a/js/src/jsxml.cpp
+++ b/js/src/jsxml.cpp
@@ -135,17 +135,16 @@ static struct {
 #define METER(x)        /* nothing */
 #define UNMETER(x)      /* nothing */
 #endif
 
 /*
  * Random utilities and global functions.
  */
 const char js_AttributeName_str[] = "AttributeName";
-const char js_AnyName_str[]       = "AnyName";
 const char js_isXMLName_str[]     = "isXMLName";
 const char js_XMLList_str[]       = "XMLList";
 const char js_localName_str[]     = "localName";
 const char js_xml_parent_str[]    = "parent";
 const char js_prefix_str[]        = "prefix";
 const char js_toXMLString_str[]   = "toXMLString";
 const char js_uri_str[]           = "uri";
 
@@ -203,23 +202,16 @@ NewBuiltinClassInstanceXML(JSContext *cx
 /*
  * Namespace class and library functions.
  */
 DEFINE_GETTER(NamePrefix_getter,
               if (obj->getClass() == &js_NamespaceClass) *vp = obj->getNamePrefixVal())
 DEFINE_GETTER(NameURI_getter,
               if (obj->getClass() == &js_NamespaceClass) *vp = obj->getNameURIVal())
 
-static void
-namespace_finalize(JSContext *cx, JSObject *obj)
-{
-    if (obj->compartment()->functionNamespaceObject == obj)
-        obj->compartment()->functionNamespaceObject = NULL;
-}
-
 static JSBool
 namespace_equality(JSContext *cx, JSObject *obj, const Value *v, JSBool *bp)
 {
     JSObject *obj2;
 
     JS_ASSERT(v->isObjectOrNull());
     obj2 = v->toObjectOrNull();
     *bp = (!obj2 || obj2->getClass() != &js_NamespaceClass)
@@ -235,17 +227,17 @@ JS_FRIEND_DATA(Class) js_NamespaceClass 
     JSCLASS_MARK_IS_TRACE | JSCLASS_HAS_CACHED_PROTO(JSProto_Namespace),
     PropertyStub,   /* addProperty */
     PropertyStub,   /* delProperty */
     PropertyStub,   /* getProperty */
     PropertyStub,   /* setProperty */
     EnumerateStub,
     ResolveStub,
     ConvertStub,
-    namespace_finalize,
+    FinalizeStub,
     NULL,           /* reserved0   */
     NULL,           /* checkAccess */
     NULL,           /* call        */
     NULL,           /* construct   */
     NULL,           /* xdrObject   */
     NULL,           /* hasInstance */
     NULL,           /* mark        */
     {
@@ -309,24 +301,16 @@ NewXMLNamespace(JSContext *cx, JSLinearS
  */
 DEFINE_GETTER(QNameNameURI_getter,
               if (obj->getClass() == &js_QNameClass)
                   *vp = JSVAL_IS_VOID(obj->getNameURIVal()) ? JSVAL_NULL : obj->getNameURIVal())
 DEFINE_GETTER(QNameLocalName_getter,
               if (obj->getClass() == &js_QNameClass)
                   *vp = obj->getQNameLocalNameVal())
 
-static void
-anyname_finalize(JSContext* cx, JSObject* obj)
-{
-    /* Make sure the next call to js_GetAnyName doesn't try to use obj. */
-    if (obj->compartment()->anynameObject == obj)
-        obj->compartment()->anynameObject = NULL;
-}
-
 static JSBool
 qname_identity(JSObject *qna, JSObject *qnb)
 {
     JSLinearString *uri1 = qna->getNameURI();
     JSLinearString *uri2 = qnb->getNameURI();
 
     if (!uri1 ^ !uri2)
         return JS_FALSE;
@@ -388,32 +372,33 @@ JS_FRIEND_DATA(Class) js_AttributeNameCl
     JSCLASS_HAS_RESERVED_SLOTS(JSObject::QNAME_CLASS_RESERVED_SLOTS) |
     JSCLASS_MARK_IS_TRACE | JSCLASS_IS_ANONYMOUS,
     PropertyStub,   /* addProperty */
     PropertyStub,   /* delProperty */
     PropertyStub,   /* getProperty */
     PropertyStub,   /* setProperty */
     EnumerateStub,
     ResolveStub,
-    ConvertStub
+    ConvertStub,
+    FinalizeStub
 };
 
 JS_FRIEND_DATA(Class) js_AnyNameClass = {
     js_AnyName_str,
     JSCLASS_CONSTRUCT_PROTOTYPE |
     JSCLASS_HAS_RESERVED_SLOTS(JSObject::QNAME_CLASS_RESERVED_SLOTS) |
     JSCLASS_MARK_IS_TRACE | JSCLASS_IS_ANONYMOUS,
     PropertyStub,   /* addProperty */
     PropertyStub,   /* delProperty */
     PropertyStub,   /* getProperty */
     PropertyStub,   /* setProperty */
     EnumerateStub,
     ResolveStub,
     ConvertStub,
-    anyname_finalize
+    FinalizeStub
 };
 
 #define QNAME_ATTRS (JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT | JSPROP_SHARED)
 
 static JSPropertySpec qname_props[] = {
     {js_uri_str,       0, QNAME_ATTRS, QNameNameURI_getter,   0},
     {js_localName_str, 0, QNAME_ATTRS, QNameLocalName_getter, 0},
     {0,0,0,0,0}
@@ -7180,40 +7165,40 @@ js_InitXMLClasses(JSContext *cx, JSObjec
     if (!js_InitQNameClass(cx, obj))
         return NULL;
     return js_InitXMLClass(cx, obj);
 }
 
 JSBool
 js_GetFunctionNamespace(JSContext *cx, Value *vp)
 {
-    JSObject *obj;
-    JSLinearString *prefix, *uri;
-
-    obj = cx->compartment->functionNamespaceObject;
-    if (!obj) {
+    JSObject *global = cx->hasfp() ? cx->fp()->scopeChain().getGlobal() : cx->globalObject;
+
+    *vp = global->getReservedSlot(JSRESERVED_GLOBAL_FUNCTION_NS);
+    if (vp->isUndefined()) {
         JSRuntime *rt = cx->runtime;
-        prefix = rt->atomState.typeAtoms[JSTYPE_FUNCTION];
-        uri = rt->atomState.functionNamespaceURIAtom;
-        obj = NewXMLNamespace(cx, prefix, uri, JS_FALSE);
+        JSLinearString *prefix = rt->atomState.typeAtoms[JSTYPE_FUNCTION];
+        JSLinearString *uri = rt->atomState.functionNamespaceURIAtom;
+        JSObject *obj = NewXMLNamespace(cx, prefix, uri, JS_FALSE);
         if (!obj)
             return false;
 
         /*
          * Avoid entraining any in-scope Object.prototype.  The loss of
          * Namespace.prototype is not detectable, as there is no way to
          * refer to this instance in scripts.  When used to qualify method
          * names, its prefix and uri references are copied to the QName.
+         * The parent remains set and links back to global.
          */
         obj->clearProto();
-        obj->clearParent();
-
-        cx->compartment->functionNamespaceObject = obj;
-    }
-    vp->setObject(*obj);
+
+        vp->setObject(*obj);
+        if (!js_SetReservedSlot(cx, global, JSRESERVED_GLOBAL_FUNCTION_NS, *vp))
+            return false;
+    }
 
     return true;
 }
 
 /*
  * Note the asymmetry between js_GetDefaultXMLNamespace and js_SetDefaultXML-
  * Namespace.  Get searches fp->scopeChain for JS_DEFAULT_XML_NAMESPACE_ID,
  * while Set sets JS_DEFAULT_XML_NAMESPACE_ID in fp->varobj. There's no
@@ -7346,38 +7331,35 @@ JSString *
 js_ValueToXMLString(JSContext *cx, const Value &v)
 {
     return ToXMLString(cx, Jsvalify(v), 0);
 }
 
 JSBool
 js_GetAnyName(JSContext *cx, jsid *idp)
 {
-    JSObject *obj = cx->compartment->anynameObject;
-    if (!obj) {
-        /*
-         * Avoid entraining any Object.prototype found via cx's scope
-         * chain or global object for this internal AnyName object.
-         */
-        obj = NewNonFunction<WithProto::Given>(cx, &js_AnyNameClass, NULL, NULL);
+    JSObject *global = cx->hasfp() ? cx->fp()->scopeChain().getGlobal() : cx->globalObject;
+    Value v = global->getReservedSlot(JSProto_AnyName);
+    if (v.isUndefined()) {
+        JSObject *obj = NewNonFunction<WithProto::Given>(cx, &js_AnyNameClass, NULL, global);
         if (!obj)
             return false;
 
+        JS_ASSERT(!obj->getProto());
+
         JSRuntime *rt = cx->runtime;
         InitXMLQName(obj, rt->emptyString, rt->emptyString,
                      ATOM_TO_STRING(rt->atomState.starAtom));
         METER(xml_stats.qname);
 
-        JS_ASSERT(!obj->getProto());
-        JS_ASSERT(!obj->getParent());
-
-        cx->compartment->anynameObject = obj;
-    }
-
-    *idp = OBJECT_TO_JSID(obj);
+        v.setObject(*obj);
+        if (!js_SetReservedSlot(cx, global, JSProto_AnyName, v))
+            return false;
+    }
+    *idp = OBJECT_TO_JSID(&v.toObject());
     return true;
 }
 
 JSBool
 js_FindXMLProperty(JSContext *cx, const Value &nameval, JSObject **objp, jsid *idp)
 {
     JSObject *nameobj;
     jsval v;