Bug 1595745 - Part 11: Change TypedObject to use ClassSpec. r=mgaudet
☠☠ backed out by ec8cad689121 ☠ ☠
authorAndré Bargull <andre.bargull@gmail.com>
Fri, 15 Nov 2019 15:05:10 +0000
changeset 502205 e089ebe699d2ef3729774765db5c47a58995435f
parent 502204 a514661afdda948c4fb0917375534f06a82ff5b0
child 502206 2ce96c6187c2ad834605f4ea6cfb17688c0ebadd
push id114172
push userdluca@mozilla.com
push dateTue, 19 Nov 2019 11:31:10 +0000
treeherdermozilla-inbound@b5c5ba07d3db [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmgaudet
bugs1595745
milestone72.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 1595745 - Part 11: Change TypedObject to use ClassSpec. r=mgaudet Differential Revision: https://phabricator.services.mozilla.com/D52667
js/public/ProtoKey.h
js/src/builtin/TypedObject.cpp
js/src/builtin/TypedObject.h
js/src/vm/GlobalObject.h
--- a/js/public/ProtoKey.h
+++ b/js/public/ProtoKey.h
@@ -97,18 +97,17 @@
   REAL_IF_INTL(Collator, InitViaClassSpec, OCLASP(Collator))                 \
   REAL_IF_INTL(DateTimeFormat, InitViaClassSpec, OCLASP(DateTimeFormat))     \
   REAL_IF_INTL(Locale, InitViaClassSpec, OCLASP(Locale))                     \
   REAL_IF_INTL(ListFormat, InitViaClassSpec, OCLASP(ListFormat))             \
   REAL_IF_INTL(NumberFormat, InitViaClassSpec, OCLASP(NumberFormat))         \
   REAL_IF_INTL(PluralRules, InitViaClassSpec, OCLASP(PluralRules))           \
   REAL_IF_INTL(RelativeTimeFormat, InitViaClassSpec,                         \
                OCLASP(RelativeTimeFormat))                                   \
-  REAL_IF_BDATA(TypedObject, InitTypedObjectModuleObject,                    \
-                OCLASP(TypedObjectModule))                                   \
+  REAL_IF_BDATA(TypedObject, InitViaClassSpec, OCLASP(TypedObjectModule))    \
   REAL(Reflect, InitViaClassSpec, CLASP(Reflect))                            \
   REAL(WeakSet, InitViaClassSpec, OCLASP(WeakSet))                           \
   REAL(TypedArray, InitViaClassSpec,                                         \
        &js::TypedArrayObject::sharedTypedArrayPrototypeClass)                \
   REAL(Atomics, InitViaClassSpec, OCLASP(Atomics))                           \
   REAL(SavedFrame, InitViaClassSpec, &js::SavedFrame::class_)                \
   REAL(Promise, InitViaClassSpec, OCLASP(Promise))                           \
   REAL(AsyncFunction, InitAsyncFunction, nullptr)                            \
--- a/js/src/builtin/TypedObject.cpp
+++ b/js/src/builtin/TypedObject.cpp
@@ -35,18 +35,20 @@ using mozilla::AssertedCast;
 using mozilla::CheckedInt32;
 using mozilla::IsPowerOfTwo;
 using mozilla::PodCopy;
 using mozilla::PointerRangeSize;
 
 using namespace js;
 
 const JSClass js::TypedObjectModuleObject::class_ = {
-    "TypedObject", JSCLASS_HAS_RESERVED_SLOTS(SlotCount) |
-                       JSCLASS_HAS_CACHED_PROTO(JSProto_TypedObject)};
+    "TypedObject",
+    JSCLASS_HAS_RESERVED_SLOTS(SlotCount) |
+        JSCLASS_HAS_CACHED_PROTO(JSProto_TypedObject),
+    JS_NULL_CLASS_OPS, &classSpec_};
 
 static const JSFunctionSpec TypedObjectMethods[] = {
     JS_SELF_HOSTED_FN("objectType", "TypeOfTypedObject", 1, 0), JS_FS_END};
 
 static void ReportCannotConvertTo(JSContext* cx, HandleValue fromValue,
                                   const char* toType) {
   JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_CANT_CONVERT_TO,
                             InformalValueTypeName(fromValue), toType);
@@ -1358,41 +1360,38 @@ static JSObject* DefineMetaTypeDescr(JSC
     return nullptr;
   }
 
   module->initReservedSlot(protoSlot, ObjectValue(*proto));
 
   return ctor;
 }
 
+static JSObject* CreateTypedObjectModuleObject(JSContext* cx, JSProtoKey key) {
+  Handle<GlobalObject*> global = cx->global();
+  RootedObject objProto(cx,
+                        GlobalObject::getOrCreateObjectPrototype(cx, global));
+  if (!objProto) {
+    return nullptr;
+  }
+
+  return NewObjectWithGivenProto<TypedObjectModuleObject>(cx, objProto,
+                                                          SingletonObject);
+}
+
 /*  The initialization strategy for TypedObjects is mildly unusual
  * compared to other classes. Because all of the types are members
  * of a single global, `TypedObject`, we basically make the
  * initializer for the `TypedObject` class populate the
  * `TypedObject` global (which is referred to as "module" herein).
  */
-/* static */
-bool GlobalObject::initTypedObjectModule(JSContext* cx,
-                                         Handle<GlobalObject*> global) {
-  RootedObject objProto(cx,
-                        GlobalObject::getOrCreateObjectPrototype(cx, global));
-  if (!objProto) {
-    return false;
-  }
-
-  Rooted<TypedObjectModuleObject*> module(cx);
-  module = NewObjectWithGivenProto<TypedObjectModuleObject>(cx, objProto,
-                                                            SingletonObject);
-  if (!module) {
-    return false;
-  }
-
-  if (!JS_DefineFunctions(cx, module, TypedObjectMethods)) {
-    return false;
-  }
+static bool TypedObjectModuleObjectClassFinish(JSContext* cx, HandleObject ctor,
+                                               HandleObject proto) {
+  Handle<TypedObjectModuleObject*> module = ctor.as<TypedObjectModuleObject>();
+  Handle<GlobalObject*> global = cx->global();
 
   // uint8, uint16, any, etc
 
 #define BINARYDATA_SCALAR_DEFINE(constant_, type_, name_)                    \
   if (!DefineSimpleTypeDescr<ScalarTypeDescr>(cx, global, module, constant_, \
                                               cx->names().name_))            \
     return false;
   JS_FOR_EACH_SCALAR_TYPE_REPR(BINARYDATA_SCALAR_DEFINE)
@@ -1470,32 +1469,27 @@ bool GlobalObject::initTypedObjectModule
   }
 
   RootedValue structTypeValue(cx, ObjectValue(*structType));
   if (!DefineDataProperty(cx, module, cx->names().StructType, structTypeValue,
                           JSPROP_READONLY | JSPROP_PERMANENT)) {
     return false;
   }
 
-  // Everything is setup, install module on the global object:
-  RootedValue moduleValue(cx, ObjectValue(*module));
-  if (!DefineDataProperty(cx, global, cx->names().TypedObject, moduleValue,
-                          JSPROP_RESOLVING)) {
-    return false;
-  }
-
-  global->setConstructor(JSProto_TypedObject, moduleValue);
-
-  return module;
+  return true;
 }
 
-JSObject* js::InitTypedObjectModuleObject(JSContext* cx,
-                                          Handle<GlobalObject*> global) {
-  return GlobalObject::getOrCreateTypedObjectModule(cx, global);
-}
+const ClassSpec TypedObjectModuleObject::classSpec_ = {
+    CreateTypedObjectModuleObject,
+    nullptr,
+    TypedObjectMethods,
+    nullptr,
+    nullptr,
+    nullptr,
+    TypedObjectModuleObjectClassFinish};
 
 /******************************************************************************
  * Typed objects
  */
 
 uint32_t TypedObject::offset() const {
   if (is<InlineTypedObject>()) {
     return 0;
--- a/js/src/builtin/TypedObject.h
+++ b/js/src/builtin/TypedObject.h
@@ -89,18 +89,16 @@
  * 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) {
@@ -530,16 +528,19 @@ class TypedObjectModuleObject : public N
     Float32Desc,
     Float64Desc,
     ObjectDesc,
     WasmAnyRefDesc,
     SlotCount
   };
 
   static const JSClass class_;
+
+ private:
+  static const ClassSpec classSpec_;
 };
 
 /* Base type for transparent and opaque typed objects. */
 class TypedObject : public JSObject {
   static const bool IsTypedObjectClass = true;
 
   static MOZ_MUST_USE bool obj_getArrayElement(JSContext* cx,
                                                Handle<TypedObject*> typedObj,
@@ -1046,19 +1047,16 @@ inline bool IsComplexTypeDescrClass(cons
 inline bool IsTypeDescrClass(const JSClass* clasp) {
   return IsSimpleTypeDescrClass(clasp) || IsComplexTypeDescrClass(clasp);
 }
 
 inline bool TypedObject::opaque() const {
   return IsOpaqueTypedObjectClass(getClass());
 }
 
-JSObject* InitTypedObjectModuleObject(JSContext* cx,
-                                      JS::Handle<GlobalObject*> global);
-
 }  // namespace js
 
 template <>
 inline bool JSObject::is<js::SimpleTypeDescr>() const {
   return js::IsSimpleTypeDescrClass(getClass());
 }
 
 template <>
--- a/js/src/vm/GlobalObject.h
+++ b/js/src/vm/GlobalObject.h
@@ -450,19 +450,17 @@ class GlobalObject : public NativeObject
     if (!ensureConstructor(cx, global, JSProto_WeakSet)) {
       return nullptr;
     }
     return &global->getPrototype(JSProto_WeakSet).toObject().as<NativeObject>();
   }
 
   static JSObject* getOrCreateTypedObjectModule(JSContext* cx,
                                                 Handle<GlobalObject*> global) {
-    return getOrCreateObject(cx, global,
-                             APPLICATION_SLOTS + JSProto_TypedObject,
-                             initTypedObjectModule);
+    return getOrCreateConstructor(cx, JSProto_TypedObject);
   }
 
   static TypeDescr* getOrCreateScalarTypeDescr(JSContext* cx,
                                                Handle<GlobalObject*> global,
                                                Scalar::Type scalarType);
 
   static TypeDescr* getOrCreateReferenceTypeDescr(JSContext* cx,
                                                   Handle<GlobalObject*> global,