Bug 1288457 - Part 14: Add JSProtoKey for GeneratorFunction. r=mgaudet
authorAndré Bargull <andre.bargull@gmail.com>
Wed, 16 Oct 2019 12:35:08 +0000
changeset 559207 e6325a3232790e98eaed09565fcab43506623359
parent 559206 2b3fe913292a06469799979c912be5109dfda27f
child 559208 000d2a8cc400889945e93e8aa6c4a78c0e4bbe6c
push id12175
push userccoroiu@mozilla.com
push dateThu, 17 Oct 2019 19:29:09 +0000
treeherdermozilla-beta@d333b6ef1fd3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmgaudet
bugs1288457
milestone71.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 1288457 - Part 14: Add JSProtoKey for GeneratorFunction. r=mgaudet Differential Revision: https://phabricator.services.mozilla.com/D42884
js/public/Class.h
js/public/ProtoKey.h
js/src/jsapi.cpp
js/src/vm/CommonPropertyNames.h
js/src/vm/GeneratorObject.cpp
js/src/vm/GeneratorObject.h
js/src/vm/GlobalObject.cpp
js/src/vm/GlobalObject.h
js/src/vm/HelperThreads.cpp
js/src/vm/JSFunction.cpp
--- a/js/public/Class.h
+++ b/js/public/Class.h
@@ -741,17 +741,17 @@ static const uint32_t JSCLASS_FOREGROUND
 // with the following flags. Failure to use JSCLASS_GLOBAL_FLAGS was
 // previously allowed, but is now an ES5 violation and thus unsupported.
 //
 // JSCLASS_GLOBAL_APPLICATION_SLOTS is the number of slots reserved at
 // the beginning of every global object's slots for use by the
 // application.
 static const uint32_t JSCLASS_GLOBAL_APPLICATION_SLOTS = 5;
 static const uint32_t JSCLASS_GLOBAL_SLOT_COUNT =
-    JSCLASS_GLOBAL_APPLICATION_SLOTS + JSProto_LIMIT * 2 + 30;
+    JSCLASS_GLOBAL_APPLICATION_SLOTS + JSProto_LIMIT * 2 + 28;
 
 static constexpr uint32_t JSCLASS_GLOBAL_FLAGS_WITH_SLOTS(uint32_t n) {
   return JSCLASS_IS_GLOBAL |
          JSCLASS_HAS_RESERVED_SLOTS(JSCLASS_GLOBAL_SLOT_COUNT + n);
 }
 
 static constexpr uint32_t JSCLASS_GLOBAL_FLAGS =
     JSCLASS_GLOBAL_FLAGS_WITH_SLOTS(0);
--- a/js/public/ProtoKey.h
+++ b/js/public/ProtoKey.h
@@ -113,16 +113,17 @@
   REAL(Reflect, InitReflect, nullptr)                                        \
   REAL(WeakSet, InitViaClassSpec, OCLASP(WeakSet))                           \
   REAL(TypedArray, InitViaClassSpec,                                         \
        &js::TypedArrayObject::sharedTypedArrayPrototypeClass)                \
   REAL(Atomics, InitAtomicsClass, OCLASP(Atomics))                           \
   REAL(SavedFrame, InitViaClassSpec, &js::SavedFrame::class_)                \
   REAL(Promise, InitViaClassSpec, OCLASP(Promise))                           \
   REAL(AsyncFunction, InitAsyncFunction, nullptr)                            \
+  REAL(GeneratorFunction, InitGeneratorFunction, nullptr)                    \
   REAL(ReadableStream, InitViaClassSpec, &js::ReadableStream::class_)        \
   REAL(ReadableStreamDefaultReader, InitViaClassSpec,                        \
        &js::ReadableStreamDefaultReader::class_)                             \
   REAL(ReadableStreamDefaultController, InitViaClassSpec,                    \
        &js::ReadableStreamDefaultController::class_)                         \
   REAL(ReadableByteStreamController, InitViaClassSpec,                       \
        &js::ReadableByteStreamController::class_)                            \
   REAL(WritableStream, InitViaClassSpec, &js::WritableStream::class_)        \
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -906,17 +906,18 @@ JS_PUBLIC_API bool JS_ResolveStandardCla
 
   if (stdnm && GlobalObject::skipDeselectedConstructor(cx, stdnm->key)) {
     stdnm = nullptr;
   }
 
   // If this class is anonymous, then it doesn't exist as a global
   // property, so we won't resolve anything.
   JSProtoKey key = stdnm ? stdnm->key : JSProto_Null;
-  if (key != JSProto_Null && key != JSProto_AsyncFunction) {
+  if (key != JSProto_Null && key != JSProto_AsyncFunction &&
+      key != JSProto_GeneratorFunction) {
     const JSClass* clasp = ProtoKeyToClass(key);
     if (!clasp || clasp->specShouldDefineConstructor()) {
       if (!GlobalObject::ensureConstructor(cx, global, key)) {
         return false;
       }
 
       *resolved = true;
       return true;
@@ -982,18 +983,18 @@ static bool EnumerateStandardClassesInTa
     if (!includeResolved && global->isStandardClassResolved(key)) {
       continue;
     }
 
     if (GlobalObject::skipDeselectedConstructor(cx, key)) {
       continue;
     }
 
-    // AsyncFunction doesn't yet use ClassSpec.
-    if (key == JSProto_AsyncFunction) {
+    // AsyncFunction and Generator don't yet use ClassSpec.
+    if (key == JSProto_AsyncFunction || key == JSProto_GeneratorFunction) {
       continue;
     }
 
     if (const JSClass* clasp = ProtoKeyToClass(key)) {
       if (!clasp->specShouldDefineConstructor()) {
         continue;
       }
     }
--- a/js/src/vm/CommonPropertyNames.h
+++ b/js/src/vm/CommonPropertyNames.h
@@ -176,17 +176,16 @@
   MACRO(frame, frame, "frame")                                                 \
   MACRO(from, from, "from")                                                    \
   MACRO(fulfilled, fulfilled, "fulfilled")                                     \
   MACRO(futexNotEqual, futexNotEqual, "not-equal")                             \
   MACRO(futexOK, futexOK, "ok")                                                \
   MACRO(futexTimedOut, futexTimedOut, "timed-out")                             \
   MACRO(gcCycleNumber, gcCycleNumber, "gcCycleNumber")                         \
   MACRO(Generator, Generator, "Generator")                                     \
-  MACRO(GeneratorFunction, GeneratorFunction, "GeneratorFunction")             \
   MACRO(GeneratorNext, GeneratorNext, "GeneratorNext")                         \
   MACRO(GeneratorReturn, GeneratorReturn, "GeneratorReturn")                   \
   MACRO(GeneratorThrow, GeneratorThrow, "GeneratorThrow")                      \
   MACRO(get, get, "get")                                                       \
   MACRO(GetInternalError, GetInternalError, "GetInternalError")                \
   MACRO(getBigInt64, getBigInt64, "getBigInt64")                               \
   MACRO(getBigUint64, getBigUint64, "getBigUint64")                            \
   MACRO(getInternals, getInternals, "getInternals")                            \
--- a/js/src/vm/GeneratorObject.cpp
+++ b/js/src/vm/GeneratorObject.cpp
@@ -235,74 +235,70 @@ JSObject* js::NewSingletonObjectWithFunc
     return nullptr;
   }
   if (!JSObject::setDelegate(cx, obj)) {
     return nullptr;
   }
   return obj;
 }
 
-/* static */
-bool GlobalObject::initGenerators(JSContext* cx, Handle<GlobalObject*> global) {
-  if (global->getReservedSlot(GENERATOR_OBJECT_PROTO).isObject()) {
-    return true;
-  }
-
+JSObject* js::InitGeneratorFunction(JSContext* cx,
+                                    Handle<GlobalObject*> global) {
   RootedObject iteratorProto(
       cx, GlobalObject::getOrCreateIteratorPrototype(cx, global));
   if (!iteratorProto) {
-    return false;
+    return nullptr;
   }
 
   RootedObject genObjectProto(cx, GlobalObject::createBlankPrototypeInheriting(
                                       cx, &PlainObject::class_, iteratorProto));
   if (!genObjectProto) {
-    return false;
+    return nullptr;
   }
   if (!DefinePropertiesAndFunctions(cx, genObjectProto, nullptr,
                                     generator_methods) ||
       !DefineToStringTag(cx, genObjectProto, cx->names().Generator)) {
-    return false;
+    return nullptr;
   }
 
   RootedObject genFunctionProto(
       cx, NewSingletonObjectWithFunctionPrototype(cx, global));
   if (!genFunctionProto) {
-    return false;
+    return nullptr;
   }
   if (!LinkConstructorAndPrototype(cx, genFunctionProto, genObjectProto,
                                    JSPROP_READONLY, JSPROP_READONLY) ||
       !DefineToStringTag(cx, genFunctionProto, cx->names().GeneratorFunction)) {
-    return false;
+    return nullptr;
   }
 
   RootedObject proto(
       cx, GlobalObject::getOrCreateFunctionConstructor(cx, cx->global()));
   if (!proto) {
-    return false;
+    return nullptr;
   }
   HandlePropertyName name = cx->names().GeneratorFunction;
   RootedObject genFunction(
       cx, NewFunctionWithProto(cx, Generator, 1, FunctionFlags::NATIVE_CTOR,
                                nullptr, name, proto, gc::AllocKind::FUNCTION,
                                SingletonObject));
   if (!genFunction) {
-    return false;
+    return nullptr;
   }
   if (!LinkConstructorAndPrototype(cx, genFunction, genFunctionProto,
                                    JSPROP_PERMANENT | JSPROP_READONLY,
                                    JSPROP_READONLY)) {
-    return false;
+    return nullptr;
   }
 
-  global->setReservedSlot(GENERATOR_OBJECT_PROTO, ObjectValue(*genObjectProto));
-  global->setReservedSlot(GENERATOR_FUNCTION, ObjectValue(*genFunction));
-  global->setReservedSlot(GENERATOR_FUNCTION_PROTO,
-                          ObjectValue(*genFunctionProto));
-  return true;
+  global->setGeneratorObjectPrototype(genObjectProto);
+  global->setConstructor(JSProto_GeneratorFunction, ObjectValue(*genFunction));
+  global->setPrototype(JSProto_GeneratorFunction,
+                       ObjectValue(*genFunctionProto));
+  return genFunction;
 }
 
 bool AbstractGeneratorObject::isAfterYield() {
   return isAfterYieldOrAwait(JSOP_YIELD);
 }
 
 bool AbstractGeneratorObject::isAfterAwait() {
   return isAfterYieldOrAwait(JSOP_AWAIT);
--- a/js/src/vm/GeneratorObject.h
+++ b/js/src/vm/GeneratorObject.h
@@ -11,16 +11,18 @@
 #include "vm/ArgumentsObject.h"
 #include "vm/ArrayObject.h"
 #include "vm/JSContext.h"
 #include "vm/JSObject.h"
 #include "vm/Stack.h"
 
 namespace js {
 
+class GlobalObject;
+
 enum class GeneratorResumeKind { Next, Throw, Return };
 
 class AbstractGeneratorObject : public NativeObject {
  public:
   // Magic value stored in the resumeIndex slot when the generator is
   // running or closing. See the resumeIndex comment below.
   static const int32_t RESUME_INDEX_RUNNING = INT32_MAX;
 
@@ -218,14 +220,17 @@ bool GeneratorThrowOrReturn(JSContext* c
  *   only on the stack, and not the `.generator` pseudo-variable this function
  *   consults.
  */
 AbstractGeneratorObject* GetGeneratorObjectForFrame(JSContext* cx,
                                                     AbstractFramePtr frame);
 
 void SetGeneratorClosed(JSContext* cx, AbstractFramePtr frame);
 
+extern JSObject* InitGeneratorFunction(JSContext* cx,
+                                       js::Handle<GlobalObject*> global);
+
 }  // namespace js
 
 template <>
 bool JSObject::is<js::AbstractGeneratorObject>() const;
 
 #endif /* vm_GeneratorObject_h */
--- a/js/src/vm/GlobalObject.cpp
+++ b/js/src/vm/GlobalObject.cpp
@@ -39,16 +39,17 @@
 #include "builtin/WeakMapObject.h"
 #include "builtin/WeakSetObject.h"
 #include "debugger/DebugAPI.h"
 #include "gc/FreeOp.h"
 #include "js/ProtoKey.h"
 #include "vm/AsyncFunction.h"
 #include "vm/DateObject.h"
 #include "vm/EnvironmentObject.h"
+#include "vm/GeneratorObject.h"
 #include "vm/HelperThreads.h"
 #include "vm/JSContext.h"
 #include "vm/PIC.h"
 #include "vm/RegExpStatics.h"
 #include "vm/RegExpStaticsObject.h"
 
 #include "gc/FreeOp-inl.h"
 #include "vm/JSObject-inl.h"
@@ -396,17 +397,17 @@ bool GlobalObject::resolveOffThreadConst
   // Don't resolve constructors for off-thread parse globals. Instead create a
   // placeholder object for the prototype which we can use to find the real
   // prototype when the off-thread compartment is merged back into the target
   // compartment.
 
   MOZ_ASSERT(global->zone()->createdForHelperThread());
   MOZ_ASSERT(key == JSProto_Object || key == JSProto_Function ||
              key == JSProto_Array || key == JSProto_RegExp ||
-             key == JSProto_AsyncFunction);
+             key == JSProto_AsyncFunction || key == JSProto_GeneratorFunction);
 
   Rooted<OffThreadPlaceholderObject*> placeholder(cx);
   placeholder = OffThreadPlaceholderObject::New(cx, prototypeSlot(key));
   if (!placeholder) {
     return false;
   }
 
   if (key == JSProto_Object &&
@@ -433,19 +434,19 @@ JSObject* GlobalObject::createOffThreadO
                                               Handle<GlobalObject*> global,
                                               unsigned slot) {
   // Don't create prototype objects for off-thread parse globals. Instead
   // create a placeholder object which we can use to find the real prototype
   // when the off-thread compartment is merged back into the target
   // compartment.
 
   MOZ_ASSERT(global->zone()->createdForHelperThread());
-  MOZ_ASSERT(slot == GENERATOR_FUNCTION_PROTO || slot == ASYNC_GENERATOR ||
-             slot == MODULE_PROTO || slot == IMPORT_ENTRY_PROTO ||
-             slot == EXPORT_ENTRY_PROTO || slot == REQUESTED_MODULE_PROTO);
+  MOZ_ASSERT(slot == ASYNC_GENERATOR || slot == MODULE_PROTO ||
+             slot == IMPORT_ENTRY_PROTO || slot == EXPORT_ENTRY_PROTO ||
+             slot == REQUESTED_MODULE_PROTO);
 
   auto placeholder = OffThreadPlaceholderObject::New(cx, slot);
   if (!placeholder) {
     return nullptr;
   }
 
   global->setSlot(slot, ObjectValue(*placeholder));
   return placeholder;
--- a/js/src/vm/GlobalObject.h
+++ b/js/src/vm/GlobalObject.h
@@ -72,18 +72,16 @@ class GlobalObject : public NativeObject
 
     /* One-off properties stored after slots for built-ins. */
     EMPTY_GLOBAL_SCOPE,
     ITERATOR_PROTO,
     ARRAY_ITERATOR_PROTO,
     STRING_ITERATOR_PROTO,
     REGEXP_STRING_ITERATOR_PROTO,
     GENERATOR_OBJECT_PROTO,
-    GENERATOR_FUNCTION_PROTO,
-    GENERATOR_FUNCTION,
     ASYNC_ITERATOR_PROTO,
     ASYNC_FROM_SYNC_ITERATOR_PROTO,
     ASYNC_GENERATOR,
     ASYNC_GENERATOR_FUNCTION,
     ASYNC_GENERATOR_PROTO,
     MAP_ITERATOR_PROTO,
     SET_ITERATOR_PROTO,
     MODULE_PROTO,
@@ -573,31 +571,44 @@ class GlobalObject : public NativeObject
 
   static NativeObject* getOrCreateRegExpStringIteratorPrototype(
       JSContext* cx, Handle<GlobalObject*> global) {
     return MaybeNativeObject(getOrCreateObject(cx, global,
                                                REGEXP_STRING_ITERATOR_PROTO,
                                                initRegExpStringIteratorProto));
   }
 
+  void setGeneratorObjectPrototype(JSObject* obj) {
+    setSlot(GENERATOR_OBJECT_PROTO, ObjectValue(*obj));
+  }
+
   static NativeObject* getOrCreateGeneratorObjectPrototype(
       JSContext* cx, Handle<GlobalObject*> global) {
-    return MaybeNativeObject(
-        getOrCreateObject(cx, global, GENERATOR_OBJECT_PROTO, initGenerators));
+    if (!ensureConstructor(cx, global, JSProto_GeneratorFunction)) {
+      return nullptr;
+    }
+    return &global->getSlot(GENERATOR_OBJECT_PROTO)
+                .toObject()
+                .as<NativeObject>();
   }
 
   static JSObject* getOrCreateGeneratorFunctionPrototype(
       JSContext* cx, Handle<GlobalObject*> global) {
-    return getOrCreateObject(cx, global, GENERATOR_FUNCTION_PROTO,
-                             initGenerators);
+    if (!ensureConstructor(cx, global, JSProto_GeneratorFunction)) {
+      return nullptr;
+    }
+    return &global->getPrototype(JSProto_GeneratorFunction).toObject();
   }
 
   static JSObject* getOrCreateGeneratorFunction(JSContext* cx,
                                                 Handle<GlobalObject*> global) {
-    return getOrCreateObject(cx, global, GENERATOR_FUNCTION, initGenerators);
+    if (!ensureConstructor(cx, global, JSProto_GeneratorFunction)) {
+      return nullptr;
+    }
+    return &global->getConstructor(JSProto_GeneratorFunction).toObject();
   }
 
   static NativeObject* getOrCreateAsyncFunctionPrototype(
       JSContext* cx, Handle<GlobalObject*> global) {
     if (!ensureConstructor(cx, global, JSProto_AsyncFunction)) {
       return nullptr;
     }
     return &global->getPrototype(JSProto_AsyncFunction)
@@ -773,19 +784,16 @@ class GlobalObject : public NativeObject
   static bool initIteratorProto(JSContext* cx, Handle<GlobalObject*> global);
   static bool initArrayIteratorProto(JSContext* cx,
                                      Handle<GlobalObject*> global);
   static bool initStringIteratorProto(JSContext* cx,
                                       Handle<GlobalObject*> global);
   static bool initRegExpStringIteratorProto(JSContext* cx,
                                             Handle<GlobalObject*> global);
 
-  // Implemented in vm/GeneratorObject.cpp.
-  static bool initGenerators(JSContext* cx, Handle<GlobalObject*> global);
-
   static bool initAsyncGenerators(JSContext* cx, Handle<GlobalObject*> global);
 
   // Implemented in builtin/MapObject.cpp.
   static bool initMapIteratorProto(JSContext* cx, Handle<GlobalObject*> global);
   static bool initSetIteratorProto(JSContext* cx, Handle<GlobalObject*> global);
 
   // Implemented in builtin/ModuleObject.cpp
   static bool initModuleProto(JSContext* cx, Handle<GlobalObject*> global);
--- a/js/src/vm/HelperThreads.cpp
+++ b/js/src/vm/HelperThreads.cpp
@@ -837,17 +837,17 @@ static bool EnsureParserCreatedClasses(J
   if (!EnsureConstructor(cx, global, JSProto_Array)) {
     return false;  // needed by array literals
   }
 
   if (!EnsureConstructor(cx, global, JSProto_RegExp)) {
     return false;  // needed by regular expression literals
   }
 
-  if (!GlobalObject::initGenerators(cx, global)) {
+  if (!EnsureConstructor(cx, global, JSProto_GeneratorFunction)) {
     return false;  // needed by function*() {}
   }
 
   if (!EnsureConstructor(cx, global, JSProto_AsyncFunction)) {
     return false;  // needed by async function() {}
   }
 
   if (!GlobalObject::initAsyncGenerators(cx, global)) {
--- a/js/src/vm/JSFunction.cpp
+++ b/js/src/vm/JSFunction.cpp
@@ -1956,16 +1956,17 @@ static bool CreateDynamicFunction(JSCont
       protoKey = JSProto_AsyncFunction;
     }
   } else {
     if (isGenerator) {
       if (!CompileStandaloneGenerator(cx, &fun, options, srcBuf,
                                       parameterListEnd)) {
         return false;
       }
+      protoKey = JSProto_GeneratorFunction;
     } else {
       if (!CompileStandaloneFunction(cx, &fun, options, srcBuf,
                                      parameterListEnd)) {
         return false;
       }
       protoKey = JSProto_Function;
     }
   }