Bug 1568903 - Part 6: Add helper to create Promise combinator element functions. r=jorendorff
☠☠ backed out by cfe990fab350 ☠ ☠
authorAndré Bargull <andre.bargull@gmail.com>
Tue, 12 Nov 2019 11:13:51 +0000
changeset 502142 595accbef95e27f253a0c4539a31c6858f1cae7c
parent 502141 567d497a39f42a347f0cdddb720cfc68256167a2
child 502143 3f4aee7f2893f625f0e88dbd623ac9cb41824e97
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)
reviewersjorendorff
bugs1568903
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 1568903 - Part 6: Add helper to create Promise combinator element functions. r=jorendorff Moves the `NewNativeFunction` and the two `setExtendedSlot` calls into a helper function to reduce code duplication. Differential Revision: https://phabricator.services.mozilla.com/D51655
js/src/builtin/Promise.cpp
--- a/js/src/builtin/Promise.cpp
+++ b/js/src/builtin/Promise.cpp
@@ -87,24 +87,19 @@ enum ResolveFunctionSlots {
   ResolveFunctionSlot_RejectFunction,
 };
 
 enum RejectFunctionSlots {
   RejectFunctionSlot_Promise = 0,
   RejectFunctionSlot_ResolveFunction,
 };
 
-enum PromiseAllResolveElementFunctionSlots {
-  PromiseAllResolveElementFunctionSlot_Data = 0,
-  PromiseAllResolveElementFunctionSlot_ElementIndex,
-};
-
-enum PromiseAllSettledElementFunctionSlots {
-  PromiseAllSettledElementFunctionSlot_Data = 0,
-  PromiseAllSettledElementFunctionSlot_ElementIndex,
+enum PromiseCombinatorElementFunctionSlots {
+  PromiseCombinatorElementFunctionSlot_Data = 0,
+  PromiseCombinatorElementFunctionSlot_ElementIndex,
 };
 
 enum ReactionJobSlots {
   ReactionJobSlot_ReactionRecord = 0,
 };
 
 enum ThenableJobSlots {
   // The handler to use as the Promise reaction. It is a callable object
@@ -2385,16 +2380,20 @@ static MOZ_MUST_USE bool PerformPromiseT
     JSContext* cx, Handle<PromiseObject*> promise, HandleValue onFulfilled_,
     HandleValue onRejected_, Handle<PromiseCapability> resultCapability);
 
 static MOZ_MUST_USE bool PerformPromiseThenWithoutSettleHandlers(
     JSContext* cx, Handle<PromiseObject*> promise,
     Handle<PromiseObject*> promiseToResolve,
     Handle<PromiseCapability> resultCapability);
 
+static JSFunction* NewPromiseCombinatorElementFunction(
+    JSContext* cx, Native native,
+    Handle<PromiseCombinatorDataHolder*> dataHolder, uint32_t index);
+
 static bool PromiseAllResolveElementFunction(JSContext* cx, unsigned argc,
                                              Value* vp);
 
 // Unforgeable version of ES2016, 25.4.4.1.
 MOZ_MUST_USE JSObject* js::GetWaitForAllPromise(
     JSContext* cx, JS::HandleObjectVector promises) {
 #ifdef DEBUG
   for (size_t i = 0, len = promises.length(); i < len; i++) {
@@ -2464,31 +2463,23 @@ MOZ_MUST_USE JSObject* js::GetWaitForAll
       // Steps e-g (omitted).
 
       // Step h.
       valuesArray->setDenseElement(index, UndefinedHandleValue);
 
       // Step i, vastly simplified.
       RootedObject nextPromiseObj(cx, promises[index]);
 
-      // Step j.
-      RootedFunction resolveFunc(
-          cx,
-          NewNativeFunction(cx, PromiseAllResolveElementFunction, 1, nullptr,
-                            gc::AllocKind::FUNCTION_EXTENDED, GenericObject));
+      // Steps j-o.
+      JSFunction* resolveFunc = NewPromiseCombinatorElementFunction(
+          cx, PromiseAllResolveElementFunction, dataHolder, index);
       if (!resolveFunc) {
         return nullptr;
       }
 
-      // Steps k-o.
-      resolveFunc->setExtendedSlot(PromiseAllResolveElementFunctionSlot_Data,
-                                   ObjectValue(*dataHolder));
-      resolveFunc->setExtendedSlot(
-          PromiseAllResolveElementFunctionSlot_ElementIndex, Int32Value(index));
-
       // Step p.
       dataHolder->increaseRemainingCount();
 
       // Step q, very roughly.
       RootedValue resolveFunVal(cx, ObjectValue(*resolveFunc));
       RootedValue rejectFunVal(cx, ObjectValue(*resultCapability.reject()));
       Rooted<PromiseObject*> nextPromise(cx);
 
@@ -2893,16 +2884,32 @@ static MOZ_MUST_USE bool CommonPerformPr
         if (!AddDummyPromiseReactionForDebugger(cx, promise, blockedPromise)) {
           return false;
         }
       }
     }
   }
 }
 
+static JSFunction* NewPromiseCombinatorElementFunction(
+    JSContext* cx, Native native,
+    Handle<PromiseCombinatorDataHolder*> dataHolder, uint32_t index) {
+  JSFunction* fn = NewNativeFunction(
+      cx, native, 1, nullptr, gc::AllocKind::FUNCTION_EXTENDED, GenericObject);
+  if (!fn) {
+    return nullptr;
+  }
+
+  fn->setExtendedSlot(PromiseCombinatorElementFunctionSlot_Data,
+                      ObjectValue(*dataHolder));
+  fn->setExtendedSlot(PromiseCombinatorElementFunctionSlot_ElementIndex,
+                      Int32Value(index));
+  return fn;
+}
+
 // ES2020 draft rev dc1e21c454bd316810be1c0e7af0131a2d7f38e9
 // 25.6.4.1.1 PerformPromiseAll (iteratorRecord, constructor, resultCapability)
 static MOZ_MUST_USE bool PerformPromiseAll(
     JSContext* cx, PromiseForOfIterator& iterator, HandleObject C,
     Handle<PromiseCapability> resultCapability, bool* done) {
   *done = false;
 
   // Step 1.
@@ -2983,32 +2990,23 @@ static MOZ_MUST_USE bool PerformPromiseA
       // a cross-compartment proxy instead...
       AutoRealm ar(cx, valuesArray);
 
       if (!NewbornArrayPush(cx, valuesArray, UndefinedValue())) {
         return false;
       }
     }
 
-    // Steps 8.j-k.
-    JSFunction* resolveFunc =
-        NewNativeFunction(cx, PromiseAllResolveElementFunction, 1, nullptr,
-                          gc::AllocKind::FUNCTION_EXTENDED, GenericObject);
+    // Steps 8.j-p.
+    JSFunction* resolveFunc = NewPromiseCombinatorElementFunction(
+        cx, PromiseAllResolveElementFunction, dataHolder, index);
     if (!resolveFunc) {
       return false;
     }
 
-    // Steps 8.l, 8.n-p.
-    resolveFunc->setExtendedSlot(PromiseAllResolveElementFunctionSlot_Data,
-                                 ObjectValue(*dataHolder));
-
-    // Step 8.m.
-    resolveFunc->setExtendedSlot(
-        PromiseAllResolveElementFunctionSlot_ElementIndex, Int32Value(index));
-
     // Step 8.q.
     dataHolder->increaseRemainingCount();
 
     // Step 8.s.
     index++;
     MOZ_ASSERT(index > 0);
 
     resolveFunVal.setObject(*resolveFunc);
@@ -3040,38 +3038,38 @@ static bool PromiseAllResolveElementFunc
                                              Value* vp) {
   CallArgs args = CallArgsFromVp(argc, vp);
 
   JSFunction* resolve = &args.callee().as<JSFunction>();
   RootedValue xVal(cx, args.get(0));
 
   // Step 1.
   const Value& dataVal =
-      resolve->getExtendedSlot(PromiseAllResolveElementFunctionSlot_Data);
+      resolve->getExtendedSlot(PromiseCombinatorElementFunctionSlot_Data);
 
   // Step 2.
   // We use the existence of the data holder as a signal for whether the
   // Promise was already resolved. Upon resolution, it's reset to
   // `undefined`.
   if (dataVal.isUndefined()) {
     args.rval().setUndefined();
     return true;
   }
 
   Rooted<PromiseCombinatorDataHolder*> data(
       cx, &dataVal.toObject().as<PromiseCombinatorDataHolder>());
 
   // Step 3.
-  resolve->setExtendedSlot(PromiseAllResolveElementFunctionSlot_Data,
+  resolve->setExtendedSlot(PromiseCombinatorElementFunctionSlot_Data,
                            UndefinedValue());
 
   // Step 4.
   int32_t index =
       resolve
-          ->getExtendedSlot(PromiseAllResolveElementFunctionSlot_ElementIndex)
+          ->getExtendedSlot(PromiseCombinatorElementFunctionSlot_ElementIndex)
           .toInt32();
 
   // Step 5.
   RootedValue valuesVal(cx, data->valuesArray());
   RootedObject valuesObj(cx, &valuesVal.toObject());
   if (IsProxy(valuesObj)) {
     // See comment for PerformPromiseAll, step 3 for why we unwrap here.
     valuesObj = UncheckedUnwrap(valuesObj);
@@ -3255,50 +3253,32 @@ static MOZ_MUST_USE bool PerformPromiseA
 
     auto PromiseAllSettledResolveElementFunction =
         PromiseAllSettledElementFunction<
             PromiseAllSettledElementFunctionKind::Resolve>;
     auto PromiseAllSettledRejectElementFunction =
         PromiseAllSettledElementFunction<
             PromiseAllSettledElementFunctionKind::Reject>;
 
-    // Steps 8.j-m.
-    JSFunction* resolveFunc = NewNativeFunction(
-        cx, PromiseAllSettledResolveElementFunction, 1, nullptr,
-        gc::AllocKind::FUNCTION_EXTENDED, GenericObject);
+    // Steps 8.j-q.
+    JSFunction* resolveFunc = NewPromiseCombinatorElementFunction(
+        cx, PromiseAllSettledResolveElementFunction, dataHolder, index);
     if (!resolveFunc) {
       return false;
     }
     resolveFunVal.setObject(*resolveFunc);
 
-    // Steps 8.o-q.
-    resolveFunc->setExtendedSlot(PromiseAllSettledElementFunctionSlot_Data,
-                                 ObjectValue(*dataHolder));
-
-    // Step 8.n.
-    resolveFunc->setExtendedSlot(
-        PromiseAllSettledElementFunctionSlot_ElementIndex, Int32Value(index));
-
-    // Steps 8.r-t.
-    JSFunction* rejectFunc = NewNativeFunction(
-        cx, PromiseAllSettledRejectElementFunction, 1, nullptr,
-        gc::AllocKind::FUNCTION_EXTENDED, GenericObject);
+    // Steps 8.r-x.
+    JSFunction* rejectFunc = NewPromiseCombinatorElementFunction(
+        cx, PromiseAllSettledRejectElementFunction, dataHolder, index);
     if (!rejectFunc) {
       return false;
     }
     rejectFunVal.setObject(*rejectFunc);
 
-    // Steps 8.v-x.
-    rejectFunc->setExtendedSlot(PromiseAllSettledElementFunctionSlot_Data,
-                                ObjectValue(*dataHolder));
-
-    // Step 8.u.
-    rejectFunc->setExtendedSlot(
-        PromiseAllSettledElementFunctionSlot_ElementIndex, Int32Value(index));
-
     // Step 8.y.
     dataHolder->increaseRemainingCount();
 
     // Step 8.aa.
     index++;
     MOZ_ASSERT(index > 0);
 
     return true;
@@ -3332,26 +3312,26 @@ template <PromiseAllSettledElementFuncti
 static bool PromiseAllSettledElementFunction(JSContext* cx, unsigned argc,
                                              Value* vp) {
   CallArgs args = CallArgsFromVp(argc, vp);
   HandleValue valueOrReason = args.get(0);
 
   // Step 1.
   JSFunction* resolve = &args.callee().as<JSFunction>();
   Rooted<PromiseCombinatorDataHolder*> data(
-      cx, &resolve->getExtendedSlot(PromiseAllSettledElementFunctionSlot_Data)
+      cx, &resolve->getExtendedSlot(PromiseCombinatorElementFunctionSlot_Data)
                .toObject()
                .as<PromiseCombinatorDataHolder>());
 
   // Steps 2-4 (moved below).
 
   // Step 5.
   int32_t index =
       resolve
-          ->getExtendedSlot(PromiseAllSettledElementFunctionSlot_ElementIndex)
+          ->getExtendedSlot(PromiseCombinatorElementFunctionSlot_ElementIndex)
           .toInt32();
 
   // Step 6.
   RootedValue valuesVal(cx, data->valuesArray());
   RootedObject valuesObj(cx, &valuesVal.toObject());
   bool needsWrapping = false;
   if (IsProxy(valuesObj)) {
     // See comment for PerformPromiseAllSettled, step 3 for why we unwrap here.