Bug 1595745 - Part 3: Change String to use ClassSpec. r=mgaudet
☠☠ backed out by ec8cad689121 ☠ ☠
authorAndré Bargull <andre.bargull@gmail.com>
Fri, 15 Nov 2019 15:02:35 +0000
changeset 502197 338ad438e066e879702224ba34317d3956bb2519
parent 502196 61d25028669b165048be8775429f79b1b136e13e
child 502198 6c917c2ca4a7b1799ea159d5cc0f88ec85e11148
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 3: Change String to use ClassSpec. r=mgaudet Move String to ClassSpec using similar changes like done for Number in part 2. Differential Revision: https://phabricator.services.mozilla.com/D52659
js/public/ProtoKey.h
js/src/builtin/String.cpp
js/src/vm/StringObject.h
--- a/js/public/ProtoKey.h
+++ b/js/public/ProtoKey.h
@@ -53,17 +53,17 @@
   REAL(Object, InitViaClassSpec, OCLASP(Plain))                              \
   REAL(Function, InitViaClassSpec, &JSFunction::class_)                      \
   REAL(Array, InitViaClassSpec, OCLASP(Array))                               \
   REAL(Boolean, InitViaClassSpec, OCLASP(Boolean))                           \
   REAL(JSON, InitJSONClass, CLASP(JSON))                                     \
   REAL(Date, InitViaClassSpec, OCLASP(Date))                                 \
   REAL(Math, InitMathClass, CLASP(Math))                                     \
   REAL(Number, InitViaClassSpec, OCLASP(Number))                             \
-  REAL(String, InitStringClass, OCLASP(String))                              \
+  REAL(String, InitViaClassSpec, OCLASP(String))                             \
   REAL(RegExp, InitViaClassSpec, OCLASP(RegExp))                             \
   REAL(Error, InitViaClassSpec, ERROR_CLASP(JSEXN_ERR))                      \
   REAL(InternalError, InitViaClassSpec, ERROR_CLASP(JSEXN_INTERNALERR))      \
   REAL(EvalError, InitViaClassSpec, ERROR_CLASP(JSEXN_EVALERR))              \
   REAL(RangeError, InitViaClassSpec, ERROR_CLASP(JSEXN_RANGEERR))            \
   REAL(ReferenceError, InitViaClassSpec, ERROR_CLASP(JSEXN_REFERENCEERR))    \
   REAL(SyntaxError, InitViaClassSpec, ERROR_CLASP(JSEXN_SYNTAXERR))          \
   REAL(TypeError, InitViaClassSpec, ERROR_CLASP(JSEXN_TYPEERR))              \
--- a/js/src/builtin/String.cpp
+++ b/js/src/builtin/String.cpp
@@ -448,17 +448,17 @@ static const JSClassOps StringObjectClas
     nullptr,                /* delProperty */
     str_enumerate, nullptr, /* newEnumerate */
     str_resolve,   str_mayResolve};
 
 const JSClass StringObject::class_ = {
     js_String_str,
     JSCLASS_HAS_RESERVED_SLOTS(StringObject::RESERVED_SLOTS) |
         JSCLASS_HAS_CACHED_PROTO(JSProto_String),
-    &StringObjectClassOps};
+    &StringObjectClassOps, &StringObject::classSpec_};
 
 /*
  * Perform the initial |RequireObjectCoercible(thisv)| and |ToString(thisv)|
  * from nearly all String.prototype.* functions.
  */
 static MOZ_ALWAYS_INLINE JSString* ToStringForStringFunction(
     JSContext* cx, HandleValue thisv) {
   if (!CheckRecursionLimit(cx)) {
@@ -3937,78 +3937,71 @@ static const JSFunctionSpec string_stati
 Shape* StringObject::assignInitialShape(JSContext* cx,
                                         Handle<StringObject*> obj) {
   MOZ_ASSERT(obj->empty());
 
   return NativeObject::addDataProperty(cx, obj, cx->names().length, LENGTH_SLOT,
                                        JSPROP_PERMANENT | JSPROP_READONLY);
 }
 
-JSObject* js::InitStringClass(JSContext* cx, Handle<GlobalObject*> global) {
+JSObject* StringObject::createPrototype(JSContext* cx, JSProtoKey key) {
   Rooted<JSString*> empty(cx, cx->runtime()->emptyString);
   Rooted<StringObject*> proto(
-      cx, GlobalObject::createBlankPrototype<StringObject>(cx, global));
+      cx, GlobalObject::createBlankPrototype<StringObject>(cx, cx->global()));
   if (!proto) {
     return nullptr;
   }
   if (!StringObject::init(cx, proto, empty)) {
     return nullptr;
   }
-
-  /* Now create the String function. */
-  RootedFunction ctor(cx);
-  ctor = GlobalObject::createConstructor(
-      cx, StringConstructor, cx->names().String, 1, gc::AllocKind::FUNCTION,
-      &jit::JitInfo_String);
-  if (!ctor) {
-    return nullptr;
-  }
-
-  if (!LinkConstructorAndPrototype(cx, ctor, proto)) {
-    return nullptr;
-  }
-
-  if (!DefinePropertiesAndFunctions(cx, proto, nullptr, string_methods) ||
-      !DefinePropertiesAndFunctions(cx, ctor, nullptr, string_static_methods)) {
-    return nullptr;
-  }
+  return proto;
+}
+
+static bool StringClassFinish(JSContext* cx, HandleObject ctor,
+                              HandleObject proto) {
+  HandleNativeObject nativeProto = proto.as<NativeObject>();
 
   // Create "trimLeft" as an alias for "trimStart".
   RootedValue trimFn(cx);
   RootedId trimId(cx, NameToId(cx->names().trimStart));
   RootedId trimAliasId(cx, NameToId(cx->names().trimLeft));
-  if (!NativeGetProperty(cx, proto, trimId, &trimFn) ||
-      !NativeDefineDataProperty(cx, proto, trimAliasId, trimFn, 0)) {
-    return nullptr;
+  if (!NativeGetProperty(cx, nativeProto, trimId, &trimFn) ||
+      !NativeDefineDataProperty(cx, nativeProto, trimAliasId, trimFn, 0)) {
+    return false;
   }
 
   // Create "trimRight" as an alias for "trimEnd".
   trimId = NameToId(cx->names().trimEnd);
   trimAliasId = NameToId(cx->names().trimRight);
-  if (!NativeGetProperty(cx, proto, trimId, &trimFn) ||
-      !NativeDefineDataProperty(cx, proto, trimAliasId, trimFn, 0)) {
-    return nullptr;
+  if (!NativeGetProperty(cx, nativeProto, trimId, &trimFn) ||
+      !NativeDefineDataProperty(cx, nativeProto, trimAliasId, trimFn, 0)) {
+    return false;
   }
 
   /*
    * Define escape/unescape, the URI encode/decode functions, and maybe
    * uneval on the global object.
    */
-  if (!JS_DefineFunctions(cx, global, string_functions)) {
-    return nullptr;
-  }
-
-  if (!GlobalObject::initBuiltinConstructor(cx, global, JSProto_String, ctor,
-                                            proto)) {
-    return nullptr;
-  }
-
-  return proto;
+  if (!JS_DefineFunctions(cx, cx->global(), string_functions)) {
+    return false;
+  }
+
+  return true;
 }
 
+const ClassSpec StringObject::classSpec_ = {
+    GenericCreateConstructor<StringConstructor, 1, gc::AllocKind::FUNCTION,
+                             &jit::JitInfo_String>,
+    StringObject::createPrototype,
+    string_static_methods,
+    nullptr,
+    string_methods,
+    nullptr,
+    StringClassFinish};
+
 #define ____ false
 
 /*
  * Uri reserved chars + #:
  * - 35: #
  * - 36: $
  * - 38: &
  * - 43: +
--- a/js/src/vm/StringObject.h
+++ b/js/src/vm/StringObject.h
@@ -7,24 +7,22 @@
 #ifndef vm_StringObject_h
 #define vm_StringObject_h
 
 #include "vm/JSObject.h"
 #include "vm/Shape.h"
 
 namespace js {
 
-class GlobalObject;
-
-JSObject* InitStringClass(JSContext* cx, Handle<GlobalObject*> global);
-
 class StringObject : public NativeObject {
   static const unsigned PRIMITIVE_VALUE_SLOT = 0;
   static const unsigned LENGTH_SLOT = 1;
 
+  static const ClassSpec classSpec_;
+
  public:
   static const unsigned RESERVED_SLOTS = 2;
 
   static const JSClass class_;
 
   /*
    * Creates a new String object boxing the given string.  The object's
    * [[Prototype]] is determined from context.
@@ -52,22 +50,20 @@ class StringObject : public NativeObject
     return getFixedSlotOffset(PRIMITIVE_VALUE_SLOT);
   }
   static size_t offsetOfLength() { return getFixedSlotOffset(LENGTH_SLOT); }
 
  private:
   static inline bool init(JSContext* cx, Handle<StringObject*> obj,
                           HandleString str);
 
+  static JSObject* createPrototype(JSContext* cx, JSProtoKey key);
+
   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,
-                                       Handle<GlobalObject*> global);
 };
 
 }  // namespace js
 
 #endif /* vm_StringObject_h */