Bug 933681 - Always stash resolved constructors in global slots, and kill markStandardClassInitializedNoProto. r=jorendorff
authorBobby Holley <bobbyholley@gmail.com>
Fri, 22 Nov 2013 10:55:41 -0800
changeset 157061 b5ad39d10f98b3519e9e01dab3f8cb865c26c061
parent 157060 36be4254baba102453faa38b124f313fd589541d
child 157062 30bbe45c775e205462b9dee6cfe4aae68591ec5f
push id36628
push userbobbyholley@gmail.com
push dateFri, 22 Nov 2013 18:55:55 +0000
treeherdermozilla-inbound@061c63d261e5 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjorendorff
bugs933681
milestone28.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 933681 - Always stash resolved constructors in global slots, and kill markStandardClassInitializedNoProto. r=jorendorff This is necessary to see this stuff over Xrays.
js/src/builtin/Intl.cpp
js/src/jsiter.cpp
js/src/jsmath.cpp
js/src/json.cpp
js/src/jsproxy.cpp
js/src/vm/GlobalObject.h
--- a/js/src/builtin/Intl.cpp
+++ b/js/src/builtin/Intl.cpp
@@ -2037,17 +2037,17 @@ js_InitIntlClass(JSContext *cx, HandleOb
         if (!InitCollatorClass(cx, Intl, global))
             return nullptr;
         if (!InitNumberFormatClass(cx, Intl, global))
             return nullptr;
         if (!InitDateTimeFormatClass(cx, Intl, global))
             return nullptr;
     }
 
-    global->markStandardClassInitializedNoProto(&IntlClass);
+    global->setConstructor(JSProto_Intl, ObjectValue(*Intl));
 
     return Intl;
 }
 
 bool
 GlobalObject::initIntlObject(JSContext *cx, Handle<GlobalObject*> global)
 {
     RootedObject Intl(cx);
--- a/js/src/jsiter.cpp
+++ b/js/src/jsiter.cpp
@@ -1940,17 +1940,17 @@ GlobalObject::initIteratorClasses(JSCont
         proto = global->createBlankPrototype(cx, &StopIterationObject::class_);
         if (!proto || !JSObject::freeze(cx, proto))
             return false;
 
         /* This should use a non-JSProtoKey'd slot, but this is easier for now. */
         if (!DefineConstructorAndPrototype(cx, global, JSProto_StopIteration, proto, proto))
             return false;
 
-        global->markStandardClassInitializedNoProto(&StopIterationObject::class_);
+        global->setConstructor(JSProto_StopIteration, ObjectValue(*proto));
     }
 
     return true;
 }
 
 JSObject *
 js_InitIteratorClasses(JSContext *cx, HandleObject obj)
 {
--- a/js/src/jsmath.cpp
+++ b/js/src/jsmath.cpp
@@ -1484,12 +1484,12 @@ js_InitMathClass(JSContext *cx, HandleOb
         return nullptr;
     }
 
     if (!JS_DefineFunctions(cx, Math, math_static_methods))
         return nullptr;
     if (!JS_DefineConstDoubles(cx, Math, math_constants))
         return nullptr;
 
-    obj->as<GlobalObject>().markStandardClassInitializedNoProto(&MathClass);
+    obj->as<GlobalObject>().setConstructor(JSProto_Math, ObjectValue(*Math));
 
     return Math;
 }
--- a/js/src/json.cpp
+++ b/js/src/json.cpp
@@ -880,12 +880,12 @@ js_InitJSONClass(JSContext *cx, HandleOb
 
     if (!JS_DefineProperty(cx, global, js_JSON_str, OBJECT_TO_JSVAL(JSON),
                            JS_PropertyStub, JS_StrictPropertyStub, 0))
         return nullptr;
 
     if (!JS_DefineFunctions(cx, JSON, json_static_methods))
         return nullptr;
 
-    global->markStandardClassInitializedNoProto(&JSONClass);
+    global->setConstructor(JSProto_JSON, ObjectValue(*JSON));
 
     return JSON;
 }
--- a/js/src/jsproxy.cpp
+++ b/js/src/jsproxy.cpp
@@ -3362,11 +3362,11 @@ js_InitProxyClass(JSContext *cx, HandleO
 
     if (!JS_DefineFunctions(cx, ctor, static_methods))
         return nullptr;
     if (!JS_DefineProperty(cx, obj, "Proxy", OBJECT_TO_JSVAL(ctor),
                            JS_PropertyStub, JS_StrictPropertyStub, 0)) {
         return nullptr;
     }
 
-    global->markStandardClassInitializedNoProto(&ProxyObject::uncallableClass_);
+    global->setConstructor(JSProto_Proxy, ObjectValue(*ctor));
     return ctor;
 }
--- a/js/src/vm/GlobalObject.h
+++ b/js/src/vm/GlobalObject.h
@@ -195,39 +195,32 @@ class GlobalObject : public JSObject
         bool inited = classIsInitialized(JSProto_Function);
         JS_ASSERT(inited == classIsInitialized(JSProto_Object));
         return inited;
     }
 
     /*
      * Lazy standard classes need a way to indicate they have been initialized.
      * Otherwise, when we delete them, we might accidentally recreate them via
-     * a lazy initialization. We use the presence of a ctor or proto in the
-     * global object's slot to indicate that they've been constructed, but this
-     * only works for classes which have a proto and ctor. Classes which don't
-     * have one can call markStandardClassInitializedNoProto(), and we can
-     * always check whether a class is initialized by calling
-     * isStandardClassResolved().
+     * a lazy initialization. We use the presence of an object in the
+     * getConstructor(key) reserved slot to indicate that they've been
+     * initialized.
+     *
+     * Note: A few builtin objects, like JSON and Math, are not constructors,
+     * so getConstructor is a bit of a misnomer.
      */
     bool isStandardClassResolved(const js::Class *clasp) const {
         JSProtoKey key = JSCLASS_CACHED_PROTO_KEY(clasp);
 
         // If the constructor is undefined, then it hasn't been initialized.
+        MOZ_ASSERT(getConstructor(key).isUndefined() ||
+                   getConstructor(key).isObject());
         return !getConstructor(key).isUndefined();
     }
 
-    void markStandardClassInitializedNoProto(const js::Class *clasp) {
-        JSProtoKey key = JSCLASS_CACHED_PROTO_KEY(clasp);
-
-        // We use true so that it's obvious what we're doing (instead of, say,
-        // null, which might be miscontrued as an error in setting Undefined).
-        if (getConstructor(key).isUndefined())
-            setConstructor(key, BooleanValue(true));
-    }
-
   private:
     void setDetailsForKey(JSProtoKey key, JSObject *ctor, JSObject *proto) {
         JS_ASSERT(getConstructor(key).isUndefined());
         JS_ASSERT(getPrototype(key).isUndefined());
         JS_ASSERT(getConstructorPropertySlot(key).isUndefined());
         setConstructor(key, ObjectValue(*ctor));
         setPrototype(key, ObjectValue(*proto));
         setConstructorPropertySlot(key, ObjectValue(*ctor));