Bug 1447442 - Part 6: Pass Handle<GlobalObject*> in ClassInitializerOp. r=jorendorff
authorAndré Bargull <andre.bargull@gmail.com>
Fri, 13 Apr 2018 02:26:00 -0700
changeset 466867 7a03a7e15320ca43339f40866a1ac982f87e5c5e
parent 466866 a5cdb5568e441dc8bd676ee93a94293b5c55493f
child 466868 20546b86221e433170746889fad17450c5d6d3e0
push id9165
push userasasaki@mozilla.com
push dateThu, 26 Apr 2018 21:04:54 +0000
treeherdermozilla-beta@064c3804de2e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjorendorff
bugs1447442
milestone61.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 1447442 - Part 6: Pass Handle<GlobalObject*> in ClassInitializerOp. r=jorendorff
js/public/Proxy.h
js/src/builtin/AtomicsObject.cpp
js/src/builtin/AtomicsObject.h
js/src/builtin/Boolean.cpp
js/src/builtin/Boolean.h
js/src/builtin/JSON.cpp
js/src/builtin/JSON.h
js/src/builtin/Reflect.cpp
js/src/builtin/Reflect.h
js/src/builtin/SIMD.cpp
js/src/builtin/SIMD.h
js/src/builtin/String.cpp
js/src/builtin/String.h
js/src/builtin/Symbol.cpp
js/src/builtin/Symbol.h
js/src/builtin/TypedObject.cpp
js/src/builtin/TypedObject.h
js/src/builtin/WeakMapObject.cpp
js/src/builtin/WeakMapObject.h
js/src/builtin/WeakSetObject.cpp
js/src/builtin/WeakSetObject.h
js/src/builtin/intl/IntlObject.cpp
js/src/builtin/intl/IntlObject.h
js/src/jsmath.cpp
js/src/jsmath.h
js/src/jsnum.cpp
js/src/jsnum.h
js/src/proxy/Proxy.cpp
js/src/proxy/Proxy.h
js/src/vm/BooleanObject.h
js/src/vm/GlobalObject.cpp
js/src/vm/JSObject.h
js/src/vm/NumberObject.h
js/src/vm/StringObject.h
js/src/wasm/WasmJS.cpp
js/src/wasm/WasmJS.h
--- a/js/public/Proxy.h
+++ b/js/public/Proxy.h
@@ -674,19 +674,16 @@ extern JS_FRIEND_API(void)
 assertEnteredPolicy(JSContext* cx, JSObject* obj, jsid id,
                     BaseProxyHandler::Action act);
 #else
 inline void assertEnteredPolicy(JSContext* cx, JSObject* obj, jsid id,
                                 BaseProxyHandler::Action act)
 {}
 #endif
 
-extern JS_FRIEND_API(JSObject*)
-InitProxyClass(JSContext* cx, JS::HandleObject obj);
-
 extern JS_FRIEND_DATA(const js::ClassOps) ProxyClassOps;
 extern JS_FRIEND_DATA(const js::ClassExtension) ProxyClassExtension;
 extern JS_FRIEND_DATA(const js::ObjectOps) ProxyObjectOps;
 
 template <unsigned Flags>
 constexpr unsigned
 CheckProxyFlags()
 {
--- a/js/src/builtin/AtomicsObject.cpp
+++ b/js/src/builtin/AtomicsObject.cpp
@@ -1008,17 +1008,15 @@ AtomicsObject::initClass(JSContext* cx, 
     if (!DefineDataProperty(cx, global, cx->names().Atomics, AtomicsValue, JSPROP_RESOLVING))
         return nullptr;
 
     global->setConstructor(JSProto_Atomics, AtomicsValue);
     return Atomics;
 }
 
 JSObject*
-js::InitAtomicsClass(JSContext* cx, HandleObject obj)
+js::InitAtomicsClass(JSContext* cx, Handle<GlobalObject*> global)
 {
-    MOZ_ASSERT(obj->is<GlobalObject>());
-    Rooted<GlobalObject*> global(cx, &obj->as<GlobalObject>());
     return AtomicsObject::initClass(cx, global);
 }
 
 #undef CXX11_ATOMICS
 #undef GNU_ATOMICS
--- a/js/src/builtin/AtomicsObject.h
+++ b/js/src/builtin/AtomicsObject.h
@@ -12,16 +12,18 @@
 
 #include "threading/ConditionVariable.h"
 #include "vm/JSObject.h"
 #include "vm/MutexIDs.h"
 #include "vm/NativeObject.h"
 
 namespace js {
 
+class GlobalObject;
+
 class AtomicsObject : public NativeObject
 {
   public:
     static const Class class_;
     static JSObject* initClass(JSContext* cx, Handle<GlobalObject*> global);
     static MOZ_MUST_USE bool toString(JSContext* cx, unsigned int argc, Value* vp);
 };
 
@@ -136,17 +138,17 @@ public:
     // or coarser.
     static mozilla::Atomic<js::Mutex*> lock_;
 
     // A flag that controls whether waiting is allowed.
     ThreadLocalData<bool> canWait_;
 };
 
 JSObject*
-InitAtomicsClass(JSContext* cx, HandleObject obj);
+InitAtomicsClass(JSContext* cx, Handle<GlobalObject*> global);
 
 // Go to sleep if the int32_t value at the given address equals `value`.
 MOZ_MUST_USE FutexThread::WaitResult
 atomics_wait_impl(JSContext* cx, SharedArrayRawBuffer* sarb, uint32_t byteOffset, int32_t value,
                   const mozilla::Maybe<mozilla::TimeDuration>& timeout);
 
 // Go to sleep if the int64_t value at the given address equals `value`.
 MOZ_MUST_USE FutexThread::WaitResult
--- a/js/src/builtin/Boolean.cpp
+++ b/js/src/builtin/Boolean.cpp
@@ -123,22 +123,18 @@ Boolean(JSContext* cx, unsigned argc, Va
         args.rval().setObject(*obj);
     } else {
         args.rval().setBoolean(b);
     }
     return true;
 }
 
 JSObject*
-js::InitBooleanClass(JSContext* cx, HandleObject obj)
+js::InitBooleanClass(JSContext* cx, Handle<GlobalObject*> global)
 {
-    MOZ_ASSERT(obj->isNative());
-
-    Handle<GlobalObject*> global = obj.as<GlobalObject>();
-
     Rooted<BooleanObject*> booleanProto(cx, GlobalObject::createBlankPrototype<BooleanObject>(cx, global));
     if (!booleanProto)
         return nullptr;
     booleanProto->setFixedSlot(BooleanObject::PRIMITIVE_VALUE_SLOT, BooleanValue(false));
 
     RootedFunction ctor(cx, GlobalObject::createConstructor(cx, Boolean, cx->names().Boolean, 1,
                                                             gc::AllocKind::FUNCTION,
                                                             &jit::JitInfo_Boolean));
--- a/js/src/builtin/Boolean.h
+++ b/js/src/builtin/Boolean.h
@@ -10,17 +10,19 @@
 /*
  * JS boolean interface.
  */
 
 #include "NamespaceImports.h"
 
 namespace js {
 
+class GlobalObject;
+
 extern JSObject*
-InitBooleanClass(JSContext* cx, js::HandleObject obj);
+InitBooleanClass(JSContext* cx, js::Handle<GlobalObject*> global);
 
 extern JSString*
 BooleanToString(JSContext* cx, bool b);
 
 } // namespace js
 
 #endif /* builtin_Boolean_h */
--- a/js/src/builtin/JSON.cpp
+++ b/js/src/builtin/JSON.cpp
@@ -979,20 +979,18 @@ json_stringify(JSContext* cx, unsigned a
 static const JSFunctionSpec json_static_methods[] = {
     JS_FN(js_toSource_str,  json_toSource,      0, 0),
     JS_FN("parse",          json_parse,         2, 0),
     JS_FN("stringify",      json_stringify,     3, 0),
     JS_FS_END
 };
 
 JSObject*
-js::InitJSONClass(JSContext* cx, HandleObject obj)
+js::InitJSONClass(JSContext* cx, Handle<GlobalObject*> global)
 {
-    Handle<GlobalObject*> global = obj.as<GlobalObject>();
-
     RootedObject proto(cx, GlobalObject::getOrCreateObjectPrototype(cx, global));
     if (!proto)
         return nullptr;
     RootedObject JSON(cx, NewObjectWithGivenProto(cx, &JSONClass, proto, SingletonObject));
     if (!JSON)
         return nullptr;
 
     if (!JS_DefineProperty(cx, global, js_JSON_str, JSON, JSPROP_RESOLVING))
--- a/js/src/builtin/JSON.h
+++ b/js/src/builtin/JSON.h
@@ -11,22 +11,23 @@
 
 #include "NamespaceImports.h"
 
 #include "js/RootingAPI.h"
 
 namespace js {
 
 struct Class;
+class GlobalObject;
 class StringBuffer;
 
 extern const Class JSONClass;
 
 extern JSObject*
-InitJSONClass(JSContext* cx, HandleObject obj);
+InitJSONClass(JSContext* cx, Handle<GlobalObject*> obj);
 
 enum class StringifyBehavior {
     Normal,
     RestrictedSafe
 };
 
 /**
  * If maybeSafely is true, Stringify will attempt to assert the API requirements
--- a/js/src/builtin/Reflect.cpp
+++ b/js/src/builtin/Reflect.cpp
@@ -200,29 +200,28 @@ static const JSFunctionSpec methods[] = 
     JS_FN("setPrototypeOf", Reflect_setPrototypeOf, 2, 0),
     JS_FS_END
 };
 
 
 /*** Setup **************************************************************************************/
 
 JSObject*
-js::InitReflect(JSContext* cx, HandleObject obj)
+js::InitReflect(JSContext* cx, Handle<GlobalObject*> global)
 {
-    Handle<GlobalObject*> global = obj.as<GlobalObject>();
     RootedObject proto(cx, GlobalObject::getOrCreateObjectPrototype(cx, global));
     if (!proto)
         return nullptr;
 
     RootedObject reflect(cx, NewObjectWithGivenProto<PlainObject>(cx, proto, SingletonObject));
     if (!reflect)
         return nullptr;
     if (!JS_DefineFunctions(cx, reflect, methods))
         return nullptr;
 
     RootedValue value(cx, ObjectValue(*reflect));
-    if (!DefineDataProperty(cx, obj, cx->names().Reflect, value, JSPROP_RESOLVING))
+    if (!DefineDataProperty(cx, global, cx->names().Reflect, value, JSPROP_RESOLVING))
         return nullptr;
 
-    obj->as<GlobalObject>().setConstructor(JSProto_Reflect, value);
+    global->setConstructor(JSProto_Reflect, value);
 
     return reflect;
 }
--- a/js/src/builtin/Reflect.h
+++ b/js/src/builtin/Reflect.h
@@ -6,18 +6,20 @@
 
 #ifndef builtin_Reflect_h
 #define builtin_Reflect_h
 
 #include "vm/JSObject.h"
 
 namespace js {
 
+class GlobalObject;
+
 extern JSObject*
-InitReflect(JSContext* cx, js::HandleObject obj);
+InitReflect(JSContext* cx, js::Handle<GlobalObject*> global);
 
 }
 
 namespace js {
 
 extern MOZ_MUST_USE bool
 Reflect_getPrototypeOf(JSContext* cx, unsigned argc, Value* vp);
 
--- a/js/src/builtin/SIMD.cpp
+++ b/js/src/builtin/SIMD.cpp
@@ -683,19 +683,18 @@ SimdObject::resolve(JSContext* cx, JS::H
         return *resolved;                                                     \
     }
     FOR_EACH_SIMD(TRY_RESOLVE_)
 #undef TRY_RESOLVE_
     return true;
 }
 
 JSObject*
-js::InitSimdClass(JSContext* cx, HandleObject obj)
+js::InitSimdClass(JSContext* cx, Handle<GlobalObject*> global)
 {
-    Handle<GlobalObject*> global = obj.as<GlobalObject>();
     return GlobalObject::getOrCreateSimdGlobalObject(cx, global);
 }
 
 template<typename V>
 JSObject*
 js::CreateSimd(JSContext* cx, const typename V::Elem* data)
 {
     typedef typename V::Elem Elem;
--- a/js/src/builtin/SIMD.h
+++ b/js/src/builtin/SIMD.h
@@ -779,16 +779,18 @@
     _(fromInt8x16Bits)                \
     _(fromInt16x8Bits)                \
     _(fromInt32x4Bits)                \
     _(fromInt32x4)                    \
     _(fromUint32x4)
 
 namespace js {
 
+class GlobalObject;
+
 // Complete set of SIMD types.
 // It must be kept in sync with the enumeration of values in
 // TypedObjectConstants.h; in particular we need to ensure that Count is
 // appropriately set with respect to the number of actual types.
 enum class SimdType {
     Int8x16   = JS_SIMDTYPEREPR_INT8X16,
     Int16x8   = JS_SIMDTYPEREPR_INT16X8,
     Int32x4   = JS_SIMDTYPEREPR_INT32X4,
@@ -1128,17 +1130,17 @@ JSObject* CreateSimd(JSContext* cx, cons
 
 template<typename V>
 bool IsVectorObject(HandleValue v);
 
 template<typename V>
 MOZ_MUST_USE bool ToSimdConstant(JSContext* cx, HandleValue v, jit::SimdConstant* out);
 
 JSObject*
-InitSimdClass(JSContext* cx, HandleObject obj);
+InitSimdClass(JSContext* cx, Handle<GlobalObject*> global);
 
 namespace jit {
 
 extern const JSJitInfo JitInfo_SimdInt32x4_extractLane;
 extern const JSJitInfo JitInfo_SimdFloat32x4_extractLane;
 
 } // namespace jit
 
--- a/js/src/builtin/String.cpp
+++ b/js/src/builtin/String.cpp
@@ -3617,22 +3617,18 @@ StringObject::assignInitialShape(JSConte
 {
     MOZ_ASSERT(obj->empty());
 
     return NativeObject::addDataProperty(cx, obj, cx->names().length, LENGTH_SLOT,
                                          JSPROP_PERMANENT | JSPROP_READONLY);
 }
 
 JSObject*
-js::InitStringClass(JSContext* cx, HandleObject obj)
+js::InitStringClass(JSContext* cx, Handle<GlobalObject*> global)
 {
-    MOZ_ASSERT(obj->isNative());
-
-    Handle<GlobalObject*> global = obj.as<GlobalObject>();
-
     Rooted<JSString*> empty(cx, cx->runtime()->emptyString);
     Rooted<StringObject*> proto(cx, GlobalObject::createBlankPrototype<StringObject>(cx, global));
     if (!proto)
         return nullptr;
     if (!StringObject::init(cx, proto, empty))
         return nullptr;
 
     /* Now create the String function. */
--- a/js/src/builtin/String.h
+++ b/js/src/builtin/String.h
@@ -19,19 +19,21 @@
 #include "gc/Rooting.h"
 #include "js/RootingAPI.h"
 #include "js/UniquePtr.h"
 #include "util/Unicode.h"
 #include "vm/Printer.h"
 
 namespace js {
 
+class GlobalObject;
+
 /* Initialize the String class, returning its prototype object. */
 extern JSObject*
-InitStringClass(JSContext* cx, HandleObject obj);
+InitStringClass(JSContext* cx, Handle<GlobalObject*> global);
 
 extern bool
 str_fromCharCode(JSContext* cx, unsigned argc, Value* vp);
 
 extern bool
 str_fromCharCode_one_arg(JSContext* cx, HandleValue code, MutableHandleValue rval);
 
 extern bool
--- a/js/src/builtin/Symbol.cpp
+++ b/js/src/builtin/Symbol.cpp
@@ -43,20 +43,18 @@ const JSFunctionSpec SymbolObject::metho
 
 const JSFunctionSpec SymbolObject::staticMethods[] = {
     JS_FN("for", for_, 1, 0),
     JS_FN("keyFor", keyFor, 1, 0),
     JS_FS_END
 };
 
 JSObject*
-SymbolObject::initClass(JSContext* cx, HandleObject obj, bool defineMembers)
+SymbolObject::initClass(JSContext* cx, Handle<GlobalObject*> global, bool defineMembers)
 {
-    Handle<GlobalObject*> global = obj.as<GlobalObject>();
-
     // This uses &JSObject::class_ because: "The Symbol prototype object is an
     // ordinary object. It is not a Symbol instance and does not have a
     // [[SymbolData]] internal slot." (ES6 rev 24, 19.4.3)
     RootedObject proto(cx, GlobalObject::createBlankPrototype<PlainObject>(cx, global));
     if (!proto)
         return nullptr;
 
     RootedFunction ctor(cx, GlobalObject::createConstructor(cx, construct,
@@ -229,18 +227,18 @@ SymbolObject::toPrimitive(JSContext* cx,
     CallArgs args = CallArgsFromVp(argc, vp);
 
     // The specification gives exactly the same algorithm for @@toPrimitive as
     // for valueOf, so reuse the valueOf implementation.
     return CallNonGenericMethod<IsSymbol, valueOf_impl>(cx, args);
 }
 
 JSObject*
-js::InitSymbolClass(JSContext* cx, HandleObject obj)
+js::InitSymbolClass(JSContext* cx, Handle<GlobalObject*> global)
 {
-    return SymbolObject::initClass(cx, obj, true);
+    return SymbolObject::initClass(cx, global, true);
 }
 
 JSObject*
-js::InitBareSymbolCtor(JSContext* cx, HandleObject obj)
+js::InitBareSymbolCtor(JSContext* cx, Handle<GlobalObject*> global)
 {
-    return SymbolObject::initClass(cx, obj, false);
+    return SymbolObject::initClass(cx, global, false);
 }
--- a/js/src/builtin/Symbol.h
+++ b/js/src/builtin/Symbol.h
@@ -7,27 +7,29 @@
 #ifndef builtin_Symbol_h
 #define builtin_Symbol_h
 
 #include "vm/NativeObject.h"
 #include "vm/SymbolType.h"
 
 namespace js {
 
+class GlobalObject;
+
 class SymbolObject : public NativeObject
 {
     /* Stores this Symbol object's [[PrimitiveValue]]. */
     static const unsigned PRIMITIVE_VALUE_SLOT = 0;
 
   public:
     static const unsigned RESERVED_SLOTS = 1;
 
     static const Class class_;
 
-    static JSObject* initClass(JSContext* cx, js::HandleObject obj, bool defineMembers);
+    static JSObject* initClass(JSContext* cx, Handle<GlobalObject*> global, bool defineMembers);
 
     /*
      * Creates a new Symbol object boxing the given primitive Symbol.  The
      * object's [[Prototype]] is determined from context.
      */
     static SymbolObject* create(JSContext* cx, JS::HandleSymbol symbol);
 
     JS::Symbol* unbox() const {
@@ -53,16 +55,16 @@ class SymbolObject : public NativeObject
     static MOZ_MUST_USE bool toPrimitive(JSContext* cx, unsigned argc, Value* vp);
 
     static const JSPropertySpec properties[];
     static const JSFunctionSpec methods[];
     static const JSFunctionSpec staticMethods[];
 };
 
 extern JSObject*
-InitSymbolClass(JSContext* cx, HandleObject obj);
+InitSymbolClass(JSContext* cx, Handle<GlobalObject*> global);
 
 extern JSObject*
-InitBareSymbolCtor(JSContext* cx, HandleObject obj);
+InitBareSymbolCtor(JSContext* cx, Handle<GlobalObject*> global);
 
 } /* namespace js */
 
 #endif /* builtin_Symbol_h */
--- a/js/src/builtin/TypedObject.cpp
+++ b/js/src/builtin/TypedObject.cpp
@@ -1305,19 +1305,18 @@ GlobalObject::initTypedObjectModule(JSCo
     }
 
     global->setConstructor(JSProto_TypedObject, moduleValue);
 
     return module;
 }
 
 JSObject*
-js::InitTypedObjectModuleObject(JSContext* cx, HandleObject obj)
+js::InitTypedObjectModuleObject(JSContext* cx, Handle<GlobalObject*> global)
 {
-    Handle<GlobalObject*> global = obj.as<GlobalObject>();
     return GlobalObject::getOrCreateTypedObjectModule(cx, global);
 }
 
 /******************************************************************************
  * Typed objects
  */
 
 uint32_t
--- a/js/src/builtin/TypedObject.h
+++ b/js/src/builtin/TypedObject.h
@@ -88,16 +88,18 @@
  * Typed objects (no matter their class) are non-native objects that
  * fully override the property accessors etc. The overridden accessor
  * methods are the same in each and are defined in methods of
  * TypedObject.
  */
 
 namespace js {
 
+class GlobalObject;
+
 /*
  * Helper method for converting a double into other scalar
  * types in the same way that JavaScript would. In particular,
  * simple C casting from double to int32_t gets things wrong
  * for values like 0xF0000000.
  */
 template <typename T>
 static T ConvertScalar(double d)
@@ -1016,17 +1018,17 @@ IsTypeDescrClass(const Class* clasp)
 
 inline bool
 TypedObject::opaque() const
 {
     return IsOpaqueTypedObjectClass(getClass());
 }
 
 JSObject*
-InitTypedObjectModuleObject(JSContext* cx, JS::HandleObject obj);
+InitTypedObjectModuleObject(JSContext* cx, JS::Handle<GlobalObject*> global);
 
 } // namespace js
 
 template <>
 inline bool
 JSObject::is<js::SimpleTypeDescr>() const
 {
     return IsSimpleTypeDescrClass(getClass());
--- a/js/src/builtin/WeakMapObject.cpp
+++ b/js/src/builtin/WeakMapObject.cpp
@@ -285,22 +285,18 @@ static const JSFunctionSpec weak_map_met
     JS_FN("has",    WeakMap_has, 1, 0),
     JS_FN("get",    WeakMap_get, 1, 0),
     JS_FN("delete", WeakMap_delete, 1, 0),
     JS_FN("set",    WeakMap_set, 2, 0),
     JS_FS_END
 };
 
 JSObject*
-js::InitWeakMapClass(JSContext* cx, HandleObject obj)
+js::InitWeakMapClass(JSContext* cx, Handle<GlobalObject*> global)
 {
-    MOZ_ASSERT(obj->isNative());
-
-    Handle<GlobalObject*> global = obj.as<GlobalObject>();
-
     RootedPlainObject proto(cx, NewBuiltinClassInstance<PlainObject>(cx));
     if (!proto)
         return nullptr;
 
     RootedFunction ctor(cx, GlobalObject::createConstructor(cx, WeakMap_construct,
                                                             cx->names().WeakMap, 0));
     if (!ctor)
         return nullptr;
--- a/js/src/builtin/WeakMapObject.h
+++ b/js/src/builtin/WeakMapObject.h
@@ -7,16 +7,18 @@
 #ifndef builtin_WeakMapObject_h
 #define builtin_WeakMapObject_h
 
 #include "gc/WeakMap.h"
 #include "vm/JSObject.h"
 
 namespace js {
 
+class GlobalObject;
+
 // Abstract base class for WeakMapObject and WeakSetObject.
 class WeakCollectionObject : public NativeObject
 {
   public:
     ObjectValueMap* getMap() { return static_cast<ObjectValueMap*>(getPrivate()); }
 
     static MOZ_MUST_USE bool nondeterministicGetKeys(JSContext* cx,
                                                      Handle<WeakCollectionObject*> obj,
@@ -28,13 +30,13 @@ class WeakCollectionObject : public Nati
 
 class WeakMapObject : public WeakCollectionObject
 {
   public:
     static const Class class_;
 };
 
 extern JSObject*
-InitWeakMapClass(JSContext* cx, HandleObject obj);
+InitWeakMapClass(JSContext* cx, Handle<GlobalObject*> global);
 
 } // namespace js
 
 #endif /* builtin_WeakMapObject_h */
--- a/js/src/builtin/WeakSetObject.cpp
+++ b/js/src/builtin/WeakSetObject.cpp
@@ -145,19 +145,18 @@ const JSPropertySpec WeakSetObject::prop
 const JSFunctionSpec WeakSetObject::methods[] = {
     JS_FN("add",    WeakSet_add,    1, 0),
     JS_FN("delete", WeakSet_delete, 1, 0),
     JS_FN("has",    WeakSet_has,    1, 0),
     JS_FS_END
 };
 
 JSObject*
-WeakSetObject::initClass(JSContext* cx, HandleObject obj)
+WeakSetObject::initClass(JSContext* cx, Handle<GlobalObject*> global)
 {
-    Handle<GlobalObject*> global = obj.as<GlobalObject>();
     RootedPlainObject proto(cx, NewBuiltinClassInstance<PlainObject>(cx));
     if (!proto)
         return nullptr;
 
     Rooted<JSFunction*> ctor(cx, GlobalObject::createConstructor(cx, construct,
                                                                  ClassName(JSProto_WeakSet, cx), 0));
     if (!ctor ||
         !LinkConstructorAndPrototype(cx, ctor, proto) ||
@@ -233,19 +232,19 @@ WeakSetObject::construct(JSContext* cx, 
     }
 
     args.rval().setObject(*obj);
     return true;
 }
 
 
 JSObject*
-js::InitWeakSetClass(JSContext* cx, HandleObject obj)
+js::InitWeakSetClass(JSContext* cx, Handle<GlobalObject*> global)
 {
-    return WeakSetObject::initClass(cx, obj);
+    return WeakSetObject::initClass(cx, global);
 }
 
 JS_FRIEND_API(bool)
 JS_NondeterministicGetWeakSetKeys(JSContext* cx, HandleObject objArg, MutableHandleObject ret)
 {
     RootedObject obj(cx, UncheckedUnwrap(objArg));
     if (!obj || !obj->is<WeakSetObject>()) {
         ret.set(nullptr);
--- a/js/src/builtin/WeakSetObject.h
+++ b/js/src/builtin/WeakSetObject.h
@@ -6,34 +6,36 @@
 
 #ifndef builtin_WeakSetObject_h
 #define builtin_WeakSetObject_h
 
 #include "builtin/WeakMapObject.h"
 
 namespace js {
 
+class GlobalObject;
+
 class WeakSetObject : public WeakCollectionObject
 {
   public:
-    static JSObject* initClass(JSContext* cx, HandleObject obj);
+    static JSObject* initClass(JSContext* cx, Handle<GlobalObject*> global);
     static const Class class_;
 
   private:
     static const JSPropertySpec properties[];
     static const JSFunctionSpec methods[];
 
     static WeakSetObject* create(JSContext* cx, HandleObject proto = nullptr);
     static MOZ_MUST_USE bool construct(JSContext* cx, unsigned argc, Value* vp);
 
     static bool isBuiltinAdd(HandleValue add);
 };
 
 extern JSObject*
-InitWeakSetClass(JSContext* cx, HandleObject obj);
+InitWeakSetClass(JSContext* cx, Handle<GlobalObject*> global);
 
 } // namespace js
 
 template<>
 inline bool
 JSObject::is<js::WeakCollectionObject>() const
 {
     return is<js::WeakMapObject>() || is<js::WeakSetObject>();
--- a/js/src/builtin/intl/IntlObject.cpp
+++ b/js/src/builtin/intl/IntlObject.cpp
@@ -563,16 +563,15 @@ GlobalObject::initIntlObject(JSContext* 
     // Use |setConstructor| to correspond with |JSProto_Intl|.
     //
     // XXX We should possibly do a one-off reserved slot like above.
     global->setConstructor(JSProto_Intl, ObjectValue(*intl));
     return true;
 }
 
 JSObject*
-js::InitIntlClass(JSContext* cx, HandleObject obj)
+js::InitIntlClass(JSContext* cx, Handle<GlobalObject*> global)
 {
-    Handle<GlobalObject*> global = obj.as<GlobalObject>();
     if (!GlobalObject::initIntlObject(cx, global))
         return nullptr;
 
     return &global->getConstructor(JSProto_Intl).toObject();
 }
--- a/js/src/builtin/intl/IntlObject.h
+++ b/js/src/builtin/intl/IntlObject.h
@@ -10,25 +10,26 @@
 #include "mozilla/Attributes.h"
 
 #include "js/RootingAPI.h"
 #include "js/TypeDecls.h"
 
 namespace js {
 
 struct Class;
+class GlobalObject;
 
 extern const Class IntlClass;
 
 /**
  * Initializes the Intl Object and its standard built-in properties.
  * Spec: ECMAScript Internationalization API Specification, 8.0, 8.1
  */
 extern JSObject*
-InitIntlClass(JSContext* cx, JS::Handle<JSObject*> obj);
+InitIntlClass(JSContext* cx, JS::Handle<GlobalObject*> global);
 
 /**
  * Returns a plain object with calendar information for a single valid locale
  * (callers must perform this validation).  The object will have these
  * properties:
  *
  *   firstDayOfWeek
  *     an integer in the range 1=Sunday to 7=Saturday indicating the day
--- a/js/src/jsmath.cpp
+++ b/js/src/jsmath.cpp
@@ -1471,31 +1471,30 @@ static const JSFunctionSpec math_static_
     JS_INLINABLE_FN("hypot",  math_hypot,           2, 0, MathHypot),
     JS_INLINABLE_FN("trunc",  math_trunc,           1, 0, MathTrunc),
     JS_INLINABLE_FN("sign",   math_sign,            1, 0, MathSign),
     JS_INLINABLE_FN("cbrt",   math_cbrt,            1, 0, MathCbrt),
     JS_FS_END
 };
 
 JSObject*
-js::InitMathClass(JSContext* cx, HandleObject obj)
+js::InitMathClass(JSContext* cx, Handle<GlobalObject*> global)
 {
-    Handle<GlobalObject*> global = obj.as<GlobalObject>();
     RootedObject proto(cx, GlobalObject::getOrCreateObjectPrototype(cx, global));
     if (!proto)
         return nullptr;
     RootedObject Math(cx, NewObjectWithGivenProto(cx, &MathClass, proto, SingletonObject));
     if (!Math)
         return nullptr;
 
-    if (!JS_DefineProperty(cx, obj, js_Math_str, Math, JSPROP_RESOLVING))
+    if (!JS_DefineProperty(cx, global, js_Math_str, Math, JSPROP_RESOLVING))
         return nullptr;
     if (!JS_DefineFunctions(cx, Math, math_static_methods))
         return nullptr;
     if (!JS_DefineConstDoubles(cx, Math, math_constants))
         return nullptr;
     if (!DefineToStringTag(cx, Math, cx->names().Math))
         return nullptr;
 
-    obj->as<GlobalObject>().setConstructor(JSProto_Math, ObjectValue(*Math));
+    global->setConstructor(JSProto_Math, ObjectValue(*Math));
 
     return Math;
 }
--- a/js/src/jsmath.h
+++ b/js/src/jsmath.h
@@ -12,16 +12,17 @@
 #include <cmath>
 #include <stdint.h>
 
 #include "NamespaceImports.h"
 
 namespace js {
 
 struct Class;
+class GlobalObject;
 
 typedef double (*UnaryFunType)(double);
 
 class MathCache
 {
   public:
     enum MathFuncId {
         Zero,
@@ -84,17 +85,17 @@ class MathCache
 
 /*
  * JS math functions.
  */
 
 extern const Class MathClass;
 
 extern JSObject*
-InitMathClass(JSContext* cx, HandleObject obj);
+InitMathClass(JSContext* cx, Handle<GlobalObject*> global);
 
 extern uint64_t
 GenerateRandomSeed();
 
 // Fill |seed[0]| and |seed[1]| with random bits, suitable for
 // seeding a XorShift128+ random number generator.
 extern void
 GenerateXorShift128PlusSeed(mozilla::Array<uint64_t, 2>& seed);
--- a/js/src/jsnum.cpp
+++ b/js/src/jsnum.cpp
@@ -1189,22 +1189,18 @@ js::FinishRuntimeNumberState(JSRuntime* 
      * strings.
      */
     char* storage = const_cast<char*>(rt->thousandsSeparator.ref());
     js_free(storage);
 }
 #endif
 
 JSObject*
-js::InitNumberClass(JSContext* cx, HandleObject obj)
+js::InitNumberClass(JSContext* cx, Handle<GlobalObject*> global)
 {
-    MOZ_ASSERT(obj->isNative());
-
-    Handle<GlobalObject*> global = obj.as<GlobalObject>();
-
     Rooted<NumberObject*> numberProto(cx);
     numberProto = GlobalObject::createBlankPrototype<NumberObject>(cx, global);
     if (!numberProto)
         return nullptr;
     numberProto->setPrimitiveValue(0);
 
     RootedFunction ctor(cx);
     ctor = GlobalObject::createConstructor(cx, Number, cx->names().Number, 1);
--- a/js/src/jsnum.h
+++ b/js/src/jsnum.h
@@ -29,29 +29,30 @@
     #endif
 #endif
 #ifndef BUILTIN_CHECKED_ARITHMETIC_SUPPORTED
     #define BUILTIN_CHECKED_ARITHMETIC_SUPPORTED(x) 0
 #endif
 
 namespace js {
 
+class GlobalObject;
 class StringBuffer;
 
 extern MOZ_MUST_USE bool
 InitRuntimeNumberState(JSRuntime* rt);
 
 #if !EXPOSE_INTL_API
 extern void
 FinishRuntimeNumberState(JSRuntime* rt);
 #endif
 
 /* Initialize the Number class, returning its prototype object. */
 extern JSObject*
-InitNumberClass(JSContext* cx, HandleObject obj);
+InitNumberClass(JSContext* cx, Handle<GlobalObject*> global);
 
 /*
  * When base == 10, this function implements ToString() as specified by
  * ECMA-262-5 section 9.8.1; but note that it handles integers specially for
  * performance.  See also js::NumberToCString().
  */
 template <AllowGC allowGC>
 extern JSString*
--- a/js/src/proxy/Proxy.cpp
+++ b/js/src/proxy/Proxy.cpp
@@ -838,30 +838,29 @@ ProxyObject::renew(const BaseProxyHandle
     MOZ_ASSERT(hasDynamicPrototype());
 
     setHandler(handler);
     setCrossCompartmentPrivate(priv);
     for (size_t i = 0; i < numReservedSlots(); i++)
         setReservedSlot(i, UndefinedValue());
 }
 
-JS_FRIEND_API(JSObject*)
-js::InitProxyClass(JSContext* cx, HandleObject obj)
+JSObject*
+js::InitProxyClass(JSContext* cx, Handle<GlobalObject*> global)
 {
     static const JSFunctionSpec static_methods[] = {
         JS_FN("revocable",      proxy_revocable,       2, 0),
         JS_FS_END
     };
 
-    Handle<GlobalObject*> global = obj.as<GlobalObject>();
     RootedFunction ctor(cx);
     ctor = GlobalObject::createConstructor(cx, proxy, cx->names().Proxy, 2);
     if (!ctor)
         return nullptr;
 
     if (!JS_DefineFunctions(cx, ctor, static_methods))
         return nullptr;
-    if (!JS_DefineProperty(cx, obj, "Proxy", ctor, JSPROP_RESOLVING))
+    if (!JS_DefineProperty(cx, global, "Proxy", ctor, JSPROP_RESOLVING))
         return nullptr;
 
     global->setConstructor(JSProto_Proxy, ObjectValue(*ctor));
     return ctor;
 }
--- a/js/src/proxy/Proxy.h
+++ b/js/src/proxy/Proxy.h
@@ -8,16 +8,18 @@
 #define proxy_Proxy_h
 
 #include "NamespaceImports.h"
 
 #include "js/Class.h"
 
 namespace js {
 
+class GlobalObject;
+
 /*
  * Dispatch point for handlers that executes the appropriate C++ or scripted traps.
  *
  * Important: All proxy methods need either (a) an AutoEnterPolicy in their
  * Proxy::foo entry point below or (b) an override in SecurityWrapper. See bug
  * 945826 comment 0.
  */
 class Proxy
@@ -97,11 +99,14 @@ ProxyGetPropertyByValue(JSContext* cx, H
 
 bool
 ProxySetProperty(JSContext* cx, HandleObject proxy, HandleId id, HandleValue val, bool strict);
 
 bool
 ProxySetPropertyByValue(JSContext* cx, HandleObject proxy, HandleValue idVal, HandleValue val,
                         bool strict);
 
+extern JSObject*
+InitProxyClass(JSContext* cx, Handle<GlobalObject*> global);
+
 } /* namespace js */
 
 #endif /* proxy_Proxy_h */
--- a/js/src/vm/BooleanObject.h
+++ b/js/src/vm/BooleanObject.h
@@ -8,16 +8,18 @@
 #define vm_BooleanObject_h
 
 #include "builtin/Boolean.h"
 
 #include "vm/NativeObject.h"
 
 namespace js {
 
+class GlobalObject;
+
 class BooleanObject : public NativeObject
 {
     /* Stores this Boolean object's [[PrimitiveValue]]. */
     static const unsigned PRIMITIVE_VALUE_SLOT = 0;
 
   public:
     static const unsigned RESERVED_SLOTS = 1;
 
@@ -36,14 +38,14 @@ class BooleanObject : public NativeObjec
 
   private:
     inline void setPrimitiveValue(bool b) {
         setFixedSlot(PRIMITIVE_VALUE_SLOT, BooleanValue(b));
     }
 
     /* For access to init, as Boolean.prototype is special. */
     friend JSObject*
-    js::InitBooleanClass(JSContext* cx, js::HandleObject global);
+    js::InitBooleanClass(JSContext* cx, js::Handle<GlobalObject*> global);
 };
 
 } // namespace js
 
 #endif /* vm_BooleanObject_h */
--- a/js/src/vm/GlobalObject.cpp
+++ b/js/src/vm/GlobalObject.cpp
@@ -49,24 +49,24 @@ struct ProtoTableEntry {
 namespace js {
 
 extern const Class IntlClass;
 extern const Class JSONClass;
 extern const Class MathClass;
 extern const Class WebAssemblyClass;
 
 #define DECLARE_PROTOTYPE_CLASS_INIT(name,init,clasp) \
-    extern JSObject* init(JSContext* cx, Handle<JSObject*> obj);
+    extern JSObject* init(JSContext* cx, Handle<GlobalObject*> global);
 JS_FOR_EACH_PROTOTYPE(DECLARE_PROTOTYPE_CLASS_INIT)
 #undef DECLARE_PROTOTYPE_CLASS_INIT
 
 } // namespace js
 
 JSObject*
-js::InitViaClassSpec(JSContext* cx, Handle<JSObject*> obj)
+js::InitViaClassSpec(JSContext* cx, Handle<GlobalObject*> global)
 {
     MOZ_CRASH("InitViaClassSpec() should not be called.");
 }
 
 static const ProtoTableEntry protoTable[JSProto_LIMIT] = {
 #define INIT_FUNC(name,init,clasp) { clasp, init },
 #define INIT_FUNC_DUMMY(name,init,clasp) { nullptr, nullptr },
     JS_FOR_PROTOTYPES(INIT_FUNC, INIT_FUNC_DUMMY)
--- a/js/src/vm/JSObject.h
+++ b/js/src/vm/JSObject.h
@@ -1020,17 +1020,17 @@ GetThisValue(JSObject* obj);
 Value
 GetThisValueOfLexical(JSObject* env);
 
 Value
 GetThisValueOfWith(JSObject* env);
 
 /* * */
 
-typedef JSObject* (*ClassInitializerOp)(JSContext* cx, JS::HandleObject obj);
+using ClassInitializerOp = JSObject* (*)(JSContext* cx, Handle<GlobalObject*> global);
 
 } /* namespace js */
 
 namespace js {
 
 inline gc::InitialHeap
 GetInitialHeap(NewObjectKind newKind, const Class* clasp)
 {
--- a/js/src/vm/NumberObject.h
+++ b/js/src/vm/NumberObject.h
@@ -6,16 +6,18 @@
 
 #ifndef vm_NumberObject_h
 #define vm_NumberObject_h
 
 #include "jsnum.h"
 
 namespace js {
 
+class GlobalObject;
+
 class NumberObject : public NativeObject
 {
     /* Stores this Number object's [[PrimitiveValue]]. */
     static const unsigned PRIMITIVE_VALUE_SLOT = 0;
 
   public:
     static const unsigned RESERVED_SLOTS = 1;
 
@@ -34,14 +36,14 @@ class NumberObject : public NativeObject
 
   private:
     inline void setPrimitiveValue(double d) {
         setFixedSlot(PRIMITIVE_VALUE_SLOT, NumberValue(d));
     }
 
     /* For access to init, as Number.prototype is special. */
     friend JSObject*
-    js::InitNumberClass(JSContext* cx, HandleObject global);
+    js::InitNumberClass(JSContext* cx, Handle<GlobalObject*> global);
 };
 
 } // namespace js
 
 #endif /* vm_NumberObject_h */
--- a/js/src/vm/StringObject.h
+++ b/js/src/vm/StringObject.h
@@ -9,16 +9,18 @@
 
 #include "builtin/String.h"
 
 #include "vm/JSObject.h"
 #include "vm/Shape.h"
 
 namespace js {
 
+class GlobalObject;
+
 class StringObject : public NativeObject
 {
     static const unsigned PRIMITIVE_VALUE_SLOT = 0;
     static const unsigned LENGTH_SLOT = 1;
 
   public:
     static const unsigned RESERVED_SLOTS = 2;
 
@@ -61,14 +63,14 @@ class StringObject : public NativeObject
     void setStringThis(JSString* str) {
         MOZ_ASSERT(getReservedSlot(PRIMITIVE_VALUE_SLOT).isUndefined());
         setFixedSlot(PRIMITIVE_VALUE_SLOT, StringValue(str));
         setFixedSlot(LENGTH_SLOT, Int32Value(int32_t(str->length())));
     }
 
     /* For access to init, as String.prototype is special. */
     friend JSObject*
-    js::InitStringClass(JSContext* cx, HandleObject global);
+    js::InitStringClass(JSContext* cx, Handle<GlobalObject*> global);
 };
 
 } // namespace js
 
 #endif /* vm_StringObject_h */
--- a/js/src/wasm/WasmJS.cpp
+++ b/js/src/wasm/WasmJS.cpp
@@ -3123,21 +3123,20 @@ InitErrorClass(JSContext* cx, HandleObje
         return false;
 
     RootedId id(cx, AtomToId(className));
     RootedValue ctorValue(cx, global->getConstructor(GetExceptionProtoKey(exn)));
     return DefineDataProperty(cx, wasm, id, ctorValue, 0);
 }
 
 JSObject*
-js::InitWebAssemblyClass(JSContext* cx, HandleObject obj)
+js::InitWebAssemblyClass(JSContext* cx, Handle<GlobalObject*> global)
 {
     MOZ_RELEASE_ASSERT(HasSupport(cx));
 
-    Handle<GlobalObject*> global = obj.as<GlobalObject>();
     MOZ_ASSERT(!global->isStandardClassResolved(JSProto_WebAssembly));
 
     RootedObject proto(cx, GlobalObject::getOrCreateObjectPrototype(cx, global));
     if (!proto)
         return nullptr;
 
     RootedObject wasm(cx, NewObjectWithGivenProto(cx, &WebAssemblyClass, proto, SingletonObject));
     if (!wasm)
--- a/js/src/wasm/WasmJS.h
+++ b/js/src/wasm/WasmJS.h
@@ -20,16 +20,17 @@
 #define wasm_js_h
 
 #include "gc/Policy.h"
 #include "vm/NativeObject.h"
 #include "wasm/WasmTypes.h"
 
 namespace js {
 
+class GlobalObject;
 class TypedArrayObject;
 class WasmFunctionScope;
 class WasmInstanceScope;
 
 namespace wasm {
 
 // Return whether WebAssembly can be compiled on this platform.
 // This must be checked and must be true to call any of the top-level wasm
@@ -85,17 +86,17 @@ IsSharedWasmMemoryObject(JSObject* obj);
 
 } // namespace wasm
 
 // The class of the WebAssembly global namespace object.
 
 extern const Class WebAssemblyClass;
 
 JSObject*
-InitWebAssemblyClass(JSContext* cx, HandleObject global);
+InitWebAssemblyClass(JSContext* cx, Handle<GlobalObject*> global);
 
 // The class of WebAssembly.Module. Each WasmModuleObject owns a
 // wasm::Module. These objects are used both as content-facing JS objects and as
 // internal implementation details of asm.js.
 
 class WasmModuleObject : public NativeObject
 {
     static const unsigned MODULE_SLOT = 0;