Bug 975589, part 1 - Rename js::DefineConstructorAndPrototype -> GlobalObject::initBuiltinConstructor and refactor it a bit. r=jwalden.
authorJason Orendorff <jorendorff@mozilla.com>
Mon, 10 Mar 2014 16:29:40 -0500
changeset 191072 6635d1edc7497a5fa346d0921013d0fde248c0bb
parent 191071 236e257bf505324d68fe3552677c981672001848
child 191073 a4be3456ea82fdac258cd53c00a89a09b7232745
push id474
push userasasaki@mozilla.com
push dateMon, 02 Jun 2014 21:01:02 +0000
treeherdermozilla-release@967f4cf1b31c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjwalden
bugs975589
milestone30.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 975589, part 1 - Rename js::DefineConstructorAndPrototype -> GlobalObject::initBuiltinConstructor and refactor it a bit. r=jwalden.
js/src/builtin/MapObject.cpp
js/src/builtin/RegExp.cpp
js/src/jsarray.cpp
js/src/jsbool.cpp
js/src/jsexn.cpp
js/src/jsiter.cpp
js/src/jsnum.cpp
js/src/jsobj.cpp
js/src/jsobjinlines.h
js/src/jsstr.cpp
js/src/jsweakmap.cpp
js/src/vm/GlobalObject.cpp
js/src/vm/GlobalObject.h
js/src/vm/SharedArrayObject.cpp
js/src/vm/TypedArrayObject.cpp
--- a/js/src/builtin/MapObject.cpp
+++ b/js/src/builtin/MapObject.cpp
@@ -1047,17 +1047,17 @@ InitClass(JSContext *cx, Handle<GlobalOb
     if (!proto)
         return nullptr;
     proto->setPrivate(nullptr);
 
     Rooted<JSFunction*> ctor(cx, global->createConstructor(cx, construct, ClassName(key, cx), 0));
     if (!ctor ||
         !LinkConstructorAndPrototype(cx, ctor, proto) ||
         !DefinePropertiesAndBrand(cx, proto, properties, methods) ||
-        !DefineConstructorAndPrototype(cx, global, key, ctor, proto))
+        !GlobalObject::initBuiltinConstructor(cx, global, key, ctor, proto))
     {
         return nullptr;
     }
     return proto;
 }
 
 JSObject *
 MapObject::initClass(JSContext *cx, JSObject *obj)
--- a/js/src/builtin/RegExp.cpp
+++ b/js/src/builtin/RegExp.cpp
@@ -497,17 +497,17 @@ js_InitRegExpClass(JSContext *cx, Handle
 
     if (!LinkConstructorAndPrototype(cx, ctor, proto))
         return nullptr;
 
     /* Add static properties to the RegExp constructor. */
     if (!JS_DefineProperties(cx, ctor, regexp_static_props))
         return nullptr;
 
-    if (!DefineConstructorAndPrototype(cx, global, JSProto_RegExp, ctor, proto))
+    if (!GlobalObject::initBuiltinConstructor(cx, global, JSProto_RegExp, ctor, proto))
         return nullptr;
 
     return proto;
 }
 
 RegExpRunStatus
 js::ExecuteRegExp(JSContext *cx, HandleObject regexp, HandleString string,
                   MatchConduit &matches, RegExpStaticsUpdate staticsUpdate)
--- a/js/src/jsarray.cpp
+++ b/js/src/jsarray.cpp
@@ -3109,17 +3109,17 @@ js_InitArrayClass(JSContext *cx, HandleO
         return nullptr;
 
     if (!DefinePropertiesAndBrand(cx, arrayProto, nullptr, array_methods) ||
         !DefinePropertiesAndBrand(cx, ctor, nullptr, array_static_methods))
     {
         return nullptr;
     }
 
-    if (!DefineConstructorAndPrototype(cx, global, JSProto_Array, ctor, arrayProto))
+    if (!GlobalObject::initBuiltinConstructor(cx, global, JSProto_Array, ctor, arrayProto))
         return nullptr;
 
     return arrayProto;
 }
 
 /*
  * Array allocation functions.
  */
--- a/js/src/jsbool.cpp
+++ b/js/src/jsbool.cpp
@@ -164,17 +164,17 @@ js_InitBooleanClass(JSContext *cx, Handl
 
     RootedValue value(cx, ObjectValue(*valueOf));
     if (!JSObject::defineProperty(cx, booleanProto, valueOfName, value,
                                   JS_PropertyStub, JS_StrictPropertyStub, 0))
     {
         return nullptr;
     }
 
-    if (!DefineConstructorAndPrototype(cx, global, JSProto_Boolean, ctor, booleanProto))
+    if (!GlobalObject::initBuiltinConstructor(cx, global, JSProto_Boolean, ctor, booleanProto))
         return nullptr;
 
     return booleanProto;
 }
 
 JSString *
 js_BooleanToString(ExclusiveContext *cx, bool b)
 {
--- a/js/src/jsexn.cpp
+++ b/js/src/jsexn.cpp
@@ -554,17 +554,17 @@ ErrorObject::createProto(JSContext *cx, 
                                                       JSFunction::ExtendedFinalizeKind));
     if (!ctor)
         return nullptr;
     ctor->setExtendedSlot(0, Int32Value(int32_t(type)));
 
     if (!LinkConstructorAndPrototype(cx, ctor, err))
         return nullptr;
 
-    if (!DefineConstructorAndPrototype(cx, global, key, ctor, err))
+    if (!GlobalObject::initBuiltinConstructor(cx, global, key, ctor, err))
         return nullptr;
 
     return err;
 }
 
 JSObject *
 js_InitExceptionClasses(JSContext *cx, HandleObject obj)
 {
--- a/js/src/jsiter.cpp
+++ b/js/src/jsiter.cpp
@@ -2000,18 +2000,21 @@ GlobalObject::initIteratorClasses(JSCont
         Rooted<JSFunction*> ctor(cx);
         ctor = global->createConstructor(cx, IteratorConstructor, cx->names().Iterator, 2);
         if (!ctor)
             return false;
         if (!LinkConstructorAndPrototype(cx, ctor, iteratorProto))
             return false;
         if (!DefinePropertiesAndBrand(cx, iteratorProto, nullptr, iterator_methods))
             return false;
-        if (!DefineConstructorAndPrototype(cx, global, JSProto_Iterator, ctor, iteratorProto))
+        if (!GlobalObject::initBuiltinConstructor(cx, global, JSProto_Iterator,
+                                                  ctor, iteratorProto))
+        {
             return false;
+        }
     }
 
     RootedObject proto(cx);
     if (global->getSlot(ARRAY_ITERATOR_PROTO).isUndefined()) {
         const Class *cls = &ArrayIteratorObject::class_;
         proto = global->createBlankPrototypeInheriting(cx, cls, *iteratorProto);
         if (!proto || !DefinePropertiesAndBrand(cx, proto, nullptr, array_iterator_methods))
             return false;
@@ -2063,18 +2066,18 @@ GlobalObject::initIteratorClasses(JSCont
         global->setPrototype(JSProto_GeneratorFunction, ObjectValue(*genFunctionProto));
     }
 
     if (global->getPrototype(JSProto_StopIteration).isUndefined()) {
         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))
+        // This should use a non-JSProtoKey'd slot, but this is easier for now.
+        if (!GlobalObject::initBuiltinConstructor(cx, global, JSProto_StopIteration, proto, proto))
             return false;
 
         global->setConstructor(JSProto_StopIteration, ObjectValue(*proto));
     }
 
     return true;
 }
 
--- a/js/src/jsnum.cpp
+++ b/js/src/jsnum.cpp
@@ -1246,17 +1246,17 @@ js_InitNumberClass(JSContext *cx, Handle
                               JSPROP_PERMANENT | JSPROP_READONLY, 0) ||
         !DefineNativeProperty(cx, global, cx->names().Infinity, valueInfinity,
                               JS_PropertyStub, JS_StrictPropertyStub,
                               JSPROP_PERMANENT | JSPROP_READONLY, 0))
     {
         return nullptr;
     }
 
-    if (!DefineConstructorAndPrototype(cx, global, JSProto_Number, ctor, numberProto))
+    if (!GlobalObject::initBuiltinConstructor(cx, global, JSProto_Number, ctor, numberProto))
         return nullptr;
 
     return numberProto;
 }
 
 static char *
 FracNumberToCString(ThreadSafeContext *cx, ToCStringBuf *cbuf, double d, int base = 10)
 {
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -2476,23 +2476,23 @@ ClearClassObject(JSObject *obj, JSProtoK
     JS_ASSERT(!obj->getParent());
     if (!obj->is<GlobalObject>())
         return;
 
     obj->as<GlobalObject>().setConstructor(key, UndefinedValue());
     obj->as<GlobalObject>().setPrototype(key, UndefinedValue());
 }
 
-JSObject *
-js::DefineConstructorAndPrototype(JSContext *cx, HandleObject obj, JSProtoKey key, HandleAtom atom,
-                                  JSObject *protoProto, const Class *clasp,
-                                  Native constructor, unsigned nargs,
-                                  const JSPropertySpec *ps, const JSFunctionSpec *fs,
-                                  const JSPropertySpec *static_ps, const JSFunctionSpec *static_fs,
-                                  JSObject **ctorp, AllocKind ctorKind)
+static JSObject *
+DefineConstructorAndPrototype(JSContext *cx, HandleObject obj, JSProtoKey key, HandleAtom atom,
+                              JSObject *protoProto, const Class *clasp,
+                              Native constructor, unsigned nargs,
+                              const JSPropertySpec *ps, const JSFunctionSpec *fs,
+                              const JSPropertySpec *static_ps, const JSFunctionSpec *static_fs,
+                              JSObject **ctorp, AllocKind ctorKind)
 {
     /*
      * Create a prototype object for this class.
      *
      * FIXME: lazy standard (built-in) class initialization and even older
      * eager boostrapping code rely on all of these properties:
      *
      * 1. NewObject attempting to compute a default prototype object when
--- a/js/src/jsobjinlines.h
+++ b/js/src/jsobjinlines.h
@@ -1018,43 +1018,16 @@ static inline gc::AllocKind
 GuessArrayGCKind(size_t numSlots)
 {
     if (numSlots)
         return gc::GetGCArrayKind(numSlots);
     return gc::FINALIZE_OBJECT8;
 }
 
 inline bool
-DefineConstructorAndPrototype(JSContext *cx, Handle<GlobalObject*> global,
-                              JSProtoKey key, HandleObject ctor, HandleObject proto)
-{
-    JS_ASSERT(!global->nativeEmpty()); /* reserved slots already allocated */
-    JS_ASSERT(ctor);
-    JS_ASSERT(proto);
-
-    RootedId id(cx, NameToId(ClassName(key, cx)));
-    JS_ASSERT(!global->nativeLookup(cx, id));
-
-    /* Set these first in case AddTypePropertyId looks for this class. */
-    global->setConstructor(key, ObjectValue(*ctor));
-    global->setPrototype(key, ObjectValue(*proto));
-    global->setConstructorPropertySlot(key, ObjectValue(*ctor));
-
-    if (!global->addDataProperty(cx, id, GlobalObject::constructorPropertySlot(key), 0)) {
-        global->setConstructor(key, UndefinedValue());
-        global->setPrototype(key, UndefinedValue());
-        global->setConstructorPropertySlot(key, UndefinedValue());
-        return false;
-    }
-
-    types::AddTypePropertyId(cx, global, id, ObjectValue(*ctor));
-    return true;
-}
-
-inline bool
 ObjectClassIs(HandleObject obj, ESClassValue classValue, JSContext *cx)
 {
     if (MOZ_UNLIKELY(obj->is<ProxyObject>()))
         return Proxy::objectClassIs(obj, classValue, cx);
 
     switch (classValue) {
       case ESClass_Array: return obj->is<ArrayObject>();
       case ESClass_Number: return obj->is<NumberObject>();
@@ -1085,25 +1058,16 @@ ValueMightBeSpecial(const Value &propval
 
 static MOZ_ALWAYS_INLINE bool
 ValueIsSpecial(JSObject *obj, MutableHandleValue propval, MutableHandle<SpecialId> sidp,
                JSContext *cx)
 {
     return false;
 }
 
-JSObject *
-DefineConstructorAndPrototype(JSContext *cx, HandleObject obj, JSProtoKey key, HandleAtom atom,
-                              JSObject *protoProto, const Class *clasp,
-                              Native constructor, unsigned nargs,
-                              const JSPropertySpec *ps, const JSFunctionSpec *fs,
-                              const JSPropertySpec *static_ps, const JSFunctionSpec *static_fs,
-                              JSObject **ctorp = nullptr,
-                              gc::AllocKind ctorKind = JSFunction::FinalizeKind);
-
 static MOZ_ALWAYS_INLINE bool
 NewObjectMetadata(ExclusiveContext *cxArg, JSObject **pmetadata)
 {
     // The metadata callback is invoked before each created object, except when
     // analysis/compilation is active, to avoid recursion.
     JS_ASSERT(!*pmetadata);
     if (JSContext *cx = cxArg->maybeJSContext()) {
         if (MOZ_UNLIKELY((size_t)cx->compartment()->hasObjectMetadataCallback()) &&
--- a/js/src/jsstr.cpp
+++ b/js/src/jsstr.cpp
@@ -3934,17 +3934,17 @@ js_InitStringClass(JSContext *cx, Handle
         return nullptr;
 
     if (!DefinePropertiesAndBrand(cx, proto, nullptr, string_methods) ||
         !DefinePropertiesAndBrand(cx, ctor, nullptr, string_static_methods))
     {
         return nullptr;
     }
 
-    if (!DefineConstructorAndPrototype(cx, global, JSProto_String, ctor, proto))
+    if (!GlobalObject::initBuiltinConstructor(cx, global, JSProto_String, ctor, proto))
         return nullptr;
 
     /*
      * Define escape/unescape, the URI encode/decode functions, and maybe
      * uneval on the global object.
      */
     if (!JS_DefineFunctions(cx, global, string_functions))
         return nullptr;
--- a/js/src/jsweakmap.cpp
+++ b/js/src/jsweakmap.cpp
@@ -454,13 +454,13 @@ js_InitWeakMapClass(JSContext *cx, Handl
         return nullptr;
 
     if (!LinkConstructorAndPrototype(cx, ctor, weakMapProto))
         return nullptr;
 
     if (!DefinePropertiesAndBrand(cx, weakMapProto, nullptr, weak_map_methods))
         return nullptr;
 
-    if (!DefineConstructorAndPrototype(cx, global, JSProto_WeakMap, ctor, weakMapProto))
+    if (!GlobalObject::initBuiltinConstructor(cx, global, JSProto_WeakMap, ctor, weakMapProto))
         return nullptr;
     return weakMapProto;
 }
 
--- a/js/src/vm/GlobalObject.cpp
+++ b/js/src/vm/GlobalObject.cpp
@@ -443,37 +443,37 @@ GlobalObject::initFunctionAndObjectClass
     return functionProto;
 }
 
 /* static */ bool
 GlobalObject::ensureConstructor(JSContext *cx, Handle<GlobalObject*> global, JSProtoKey key)
 {
     if (global->getConstructor(key).isObject())
         return true;
-    return initConstructor(cx, global, key);
+    return resolveConstructor(cx, global, key);
 }
 
 /* static*/ bool
-GlobalObject::initConstructor(JSContext *cx, Handle<GlobalObject*> global, JSProtoKey key)
+GlobalObject::resolveConstructor(JSContext *cx, Handle<GlobalObject*> global, JSProtoKey key)
 {
     MOZ_ASSERT(global->getConstructor(key).isUndefined());
 
     // There are two different kinds of initialization hooks. One of them is
     // the class js_InitFoo hook, defined in a JSProtoKey-keyed table at the
     // top of this file. The other lives in the ClassSpec for classes that
     // define it. Classes may use one or the other, but not both.
     ClassInitializerOp init = protoTable[key].init;
     if (init == js_InitViaClassSpec)
         init = nullptr;
 
     const Class *clasp = ProtoKeyToClass(key);
 
     // Some classes have no init routine, which means that they're disabled at
     // compile-time. We could try to enforce that callers never pass such keys
-    // to initConstructor, but that would cramp the style of consumers like
+    // to resolveConstructor, but that would cramp the style of consumers like
     // GlobalObject::initStandardClasses that want to just carpet-bomb-call
     // ensureConstructor with every JSProtoKey. So it's easier to just handle
     // it here.
     bool haveSpec = clasp && clasp->spec.defined();
     if (!init && !haveSpec)
         return true;
 
     // See if there's an old-style initialization hook.
@@ -514,17 +514,40 @@ GlobalObject::initConstructor(JSContext 
     if (proto && !LinkConstructorAndPrototype(cx, ctor, proto))
         return false;
 
     // Call the post-initialization hook, if provided.
     if (clasp->spec.finishInit && !clasp->spec.finishInit(cx, ctor, proto))
         return false;
 
     // Stash things in the right slots and define the constructor on the global.
-    return DefineConstructorAndPrototype(cx, global, key, ctor, proto);
+    return initBuiltinConstructor(cx, global, key, ctor, proto);
+}
+
+/* static */ bool
+GlobalObject::initBuiltinConstructor(JSContext *cx, Handle<GlobalObject*> global,
+                                     JSProtoKey key, HandleObject ctor, HandleObject proto)
+{
+    JS_ASSERT(!global->nativeEmpty()); // reserved slots already allocated
+    JS_ASSERT(key != JSProto_Null);
+    JS_ASSERT(ctor);
+    JS_ASSERT(proto);
+
+    RootedId id(cx, NameToId(ClassName(key, cx)));
+    JS_ASSERT(!global->nativeLookup(cx, id));
+
+    if (!global->addDataProperty(cx, id, constructorPropertySlot(key), 0))
+        return false;
+
+    global->setConstructor(key, ObjectValue(*ctor));
+    global->setPrototype(key, ObjectValue(*proto));
+    global->setConstructorPropertySlot(key, ObjectValue(*ctor));
+
+    types::AddTypePropertyId(cx, global, id, ObjectValue(*ctor));
+    return true;
 }
 
 GlobalObject *
 GlobalObject::create(JSContext *cx, const Class *clasp)
 {
     JS_ASSERT(clasp->flags & JSCLASS_IS_GLOBAL);
 
     JSObject *obj = NewObjectWithGivenProto(cx, clasp, nullptr, nullptr, SingletonObject);
--- a/js/src/vm/GlobalObject.h
+++ b/js/src/vm/GlobalObject.h
@@ -160,17 +160,19 @@ class GlobalObject : public JSObject
     warnOnceAbout(JSContext *cx, HandleObject obj, uint32_t slot, unsigned errorNumber);
 
   public:
     Value getConstructor(JSProtoKey key) const {
         JS_ASSERT(key <= JSProto_LIMIT);
         return getSlot(APPLICATION_SLOTS + key);
     }
     static bool ensureConstructor(JSContext *cx, Handle<GlobalObject*> global, JSProtoKey key);
-    static bool initConstructor(JSContext *cx, Handle<GlobalObject*> global, JSProtoKey key);
+    static bool resolveConstructor(JSContext *cx, Handle<GlobalObject*> global, JSProtoKey key);
+    static bool initBuiltinConstructor(JSContext *cx, Handle<GlobalObject*> global,
+                                       JSProtoKey key, HandleObject ctor, HandleObject proto);
 
     void setConstructor(JSProtoKey key, const Value &v) {
         JS_ASSERT(key <= JSProto_LIMIT);
         setSlot(APPLICATION_SLOTS + key, v);
     }
 
     Value getPrototype(JSProtoKey key) const {
         JS_ASSERT(key <= JSProto_LIMIT);
--- a/js/src/vm/SharedArrayObject.cpp
+++ b/js/src/vm/SharedArrayObject.cpp
@@ -371,12 +371,12 @@ js_InitSharedArrayBufferClass(JSContext 
 
     RootedValue value(cx, UndefinedValue());
     if (!DefineNativeProperty(cx, proto, byteLengthId, value,
                               JS_DATA_TO_FUNC_PTR(PropertyOp, getter), nullptr, flags, 0, 0))
     {
         return nullptr;
     }
 
-    if (!DefineConstructorAndPrototype(cx, global, JSProto_SharedArrayBuffer, ctor, proto))
+    if (!GlobalObject::initBuiltinConstructor(cx, global, JSProto_SharedArrayBuffer, ctor, proto))
         return nullptr;
     return proto;
 }
--- a/js/src/vm/TypedArrayObject.cpp
+++ b/js/src/vm/TypedArrayObject.cpp
@@ -2180,17 +2180,17 @@ InitTypedArrayClass(JSContext *cx)
     RootedFunction fun(cx);
     fun =
         NewFunction(cx, NullPtr(),
                     ArrayBufferObject::createTypedArrayFromBuffer<typename ArrayType::ThisType>,
                     0, JSFunction::NATIVE_FUN, global, NullPtr());
     if (!fun)
         return nullptr;
 
-    if (!DefineConstructorAndPrototype(cx, global, ArrayType::key, ctor, proto))
+    if (!GlobalObject::initBuiltinConstructor(cx, global, ArrayType::key, ctor, proto))
         return nullptr;
 
     global->setCreateArrayFromBuffer<typename ArrayType::ThisType>(fun);
 
     return proto;
 }
 
 IMPL_TYPED_ARRAY_STATICS(Int8Array);
@@ -2272,18 +2272,21 @@ InitArrayBufferClass(JSContext *cx)
         return nullptr;
 
     if (!JS_DefineFunctions(cx, ctor, ArrayBufferObject::jsstaticfuncs))
         return nullptr;
 
     if (!JS_DefineFunctions(cx, arrayBufferProto, ArrayBufferObject::jsfuncs))
         return nullptr;
 
-    if (!DefineConstructorAndPrototype(cx, global, JSProto_ArrayBuffer, ctor, arrayBufferProto))
+    if (!GlobalObject::initBuiltinConstructor(cx, global, JSProto_ArrayBuffer,
+                                              ctor, arrayBufferProto))
+    {
         return nullptr;
+    }
 
     return arrayBufferProto;
 }
 
 const Class DataViewObject::protoClass = {
     "DataViewPrototype",
     JSCLASS_HAS_PRIVATE |
     JSCLASS_HAS_RESERVED_SLOTS(DataViewObject::RESERVED_SLOTS) |
@@ -2404,17 +2407,17 @@ DataViewObject::initClass(JSContext *cx)
      * |new DataView(new otherWindow.ArrayBuffer())|, and install it in the
      * global for use by the DataViewObject constructor.
      */
     RootedFunction fun(cx, NewFunction(cx, NullPtr(), ArrayBufferObject::createDataViewForThis,
                                        0, JSFunction::NATIVE_FUN, global, NullPtr()));
     if (!fun)
         return nullptr;
 
-    if (!DefineConstructorAndPrototype(cx, global, JSProto_DataView, ctor, proto))
+    if (!GlobalObject::initBuiltinConstructor(cx, global, JSProto_DataView, ctor, proto))
         return nullptr;
 
     global->setCreateDataViewForThis(fun);
 
     return proto;
 }
 
 void