From 4b939b99c378a674aec0ada9a98cd9998cf7c8c9 Mon Sep 17 00:00:00 2001 From: Bobby Holley Date: Fri, 22 Nov 2013 10:55:41 -0800 Subject: [PATCH] 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 | 2 +- js/src/jsiter.cpp | 2 +- js/src/jsmath.cpp | 2 +- js/src/json.cpp | 2 +- js/src/jsproxy.cpp | 2 +- js/src/vm/GlobalObject.h | 23 ++++++++--------------- 6 files changed, 13 insertions(+), 20 deletions(-) diff --git a/js/src/builtin/Intl.cpp b/js/src/builtin/Intl.cpp index 572cc291f35..da65a0eba83 100644 --- a/js/src/builtin/Intl.cpp +++ b/js/src/builtin/Intl.cpp @@ -2042,7 +2042,7 @@ js_InitIntlClass(JSContext *cx, HandleObject obj) return nullptr; } - global->markStandardClassInitializedNoProto(&IntlClass); + global->setConstructor(JSProto_Intl, ObjectValue(*Intl)); return Intl; } diff --git a/js/src/jsiter.cpp b/js/src/jsiter.cpp index edbc660c074..06015d66220 100644 --- a/js/src/jsiter.cpp +++ b/js/src/jsiter.cpp @@ -1945,7 +1945,7 @@ GlobalObject::initIteratorClasses(JSContext *cx, Handle global) if (!DefineConstructorAndPrototype(cx, global, JSProto_StopIteration, proto, proto)) return false; - global->markStandardClassInitializedNoProto(&StopIterationObject::class_); + global->setConstructor(JSProto_StopIteration, ObjectValue(*proto)); } return true; diff --git a/js/src/jsmath.cpp b/js/src/jsmath.cpp index 682501f2725..6d82f735e9f 100644 --- a/js/src/jsmath.cpp +++ b/js/src/jsmath.cpp @@ -1489,7 +1489,7 @@ js_InitMathClass(JSContext *cx, HandleObject obj) if (!JS_DefineConstDoubles(cx, Math, math_constants)) return nullptr; - obj->as().markStandardClassInitializedNoProto(&MathClass); + obj->as().setConstructor(JSProto_Math, ObjectValue(*Math)); return Math; } diff --git a/js/src/json.cpp b/js/src/json.cpp index 9f80d8dc39f..36771241151 100644 --- a/js/src/json.cpp +++ b/js/src/json.cpp @@ -885,7 +885,7 @@ js_InitJSONClass(JSContext *cx, HandleObject obj) if (!JS_DefineFunctions(cx, JSON, json_static_methods)) return nullptr; - global->markStandardClassInitializedNoProto(&JSONClass); + global->setConstructor(JSProto_JSON, ObjectValue(*JSON)); return JSON; } diff --git a/js/src/jsproxy.cpp b/js/src/jsproxy.cpp index 7877514911a..04abff3f221 100644 --- a/js/src/jsproxy.cpp +++ b/js/src/jsproxy.cpp @@ -3367,6 +3367,6 @@ js_InitProxyClass(JSContext *cx, HandleObject obj) return nullptr; } - global->markStandardClassInitializedNoProto(&ProxyObject::uncallableClass_); + global->setConstructor(JSProto_Proxy, ObjectValue(*ctor)); return ctor; } diff --git a/js/src/vm/GlobalObject.h b/js/src/vm/GlobalObject.h index bd14c84503b..1aad7bbcd04 100644 --- a/js/src/vm/GlobalObject.h +++ b/js/src/vm/GlobalObject.h @@ -200,29 +200,22 @@ class GlobalObject : public JSObject /* * 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());