LCOV - code coverage report
Current view: top level - src/builtins - builtins-promise-gen.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 1136 1144 99.3 %
Date: 2019-04-19 Functions: 108 110 98.2 %

          Line data    Source code
       1             : // Copyright 2016 the V8 project authors. All rights reserved.
       2             : // Use of this source code is governed by a BSD-style license that can be
       3             : // found in the LICENSE file.
       4             : 
       5             : #include "src/builtins/builtins-promise-gen.h"
       6             : 
       7             : #include "src/builtins/builtins-constructor-gen.h"
       8             : #include "src/builtins/builtins-iterator-gen.h"
       9             : #include "src/builtins/builtins-promise.h"
      10             : #include "src/builtins/builtins-utils-gen.h"
      11             : #include "src/builtins/builtins.h"
      12             : #include "src/code-factory.h"
      13             : #include "src/code-stub-assembler.h"
      14             : #include "src/objects-inl.h"
      15             : #include "src/objects/js-promise.h"
      16             : #include "src/objects/smi.h"
      17             : 
      18             : namespace v8 {
      19             : namespace internal {
      20             : 
      21             : typedef compiler::Node Node;
      22             : template <class T>
      23             : using TNode = CodeStubAssembler::TNode<T>;
      24             : using IteratorRecord = IteratorBuiltinsAssembler::IteratorRecord;
      25             : 
      26         696 : Node* PromiseBuiltinsAssembler::AllocateJSPromise(Node* context) {
      27        1392 :   Node* const native_context = LoadNativeContext(context);
      28             :   Node* const promise_fun =
      29        1392 :       LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX);
      30             :   CSA_ASSERT(this, IsFunctionWithPrototypeSlotMap(LoadMap(promise_fun)));
      31             :   Node* const promise_map =
      32             :       LoadObjectField(promise_fun, JSFunction::kPrototypeOrInitialMapOffset);
      33        1392 :   Node* const promise = Allocate(JSPromise::kSizeWithEmbedderFields);
      34         696 :   StoreMapNoWriteBarrier(promise, promise_map);
      35             :   StoreObjectFieldRoot(promise, JSPromise::kPropertiesOrHashOffset,
      36         696 :                        RootIndex::kEmptyFixedArray);
      37             :   StoreObjectFieldRoot(promise, JSPromise::kElementsOffset,
      38         696 :                        RootIndex::kEmptyFixedArray);
      39         696 :   return promise;
      40             : }
      41             : 
      42        1084 : void PromiseBuiltinsAssembler::PromiseInit(Node* promise) {
      43             :   STATIC_ASSERT(v8::Promise::kPending == 0);
      44        1084 :   StoreObjectFieldNoWriteBarrier(promise, JSPromise::kReactionsOrResultOffset,
      45        2168 :                                  SmiConstant(Smi::zero()));
      46             :   StoreObjectFieldNoWriteBarrier(promise, JSPromise::kFlagsOffset,
      47        2168 :                                  SmiConstant(Smi::zero()));
      48             :   for (int offset = JSPromise::kSize;
      49             :        offset < JSPromise::kSizeWithEmbedderFields; offset += kTaggedSize) {
      50             :     StoreObjectFieldNoWriteBarrier(promise, offset, SmiConstant(Smi::zero()));
      51             :   }
      52        1084 : }
      53             : 
      54         452 : Node* PromiseBuiltinsAssembler::AllocateAndInitJSPromise(Node* context) {
      55         904 :   return AllocateAndInitJSPromise(context, UndefinedConstant());
      56             : }
      57             : 
      58         636 : Node* PromiseBuiltinsAssembler::AllocateAndInitJSPromise(Node* context,
      59             :                                                          Node* parent) {
      60         636 :   Node* const instance = AllocateJSPromise(context);
      61         636 :   PromiseInit(instance);
      62             : 
      63        1272 :   Label out(this);
      64        1272 :   GotoIfNot(IsPromiseHookEnabledOrHasAsyncEventDelegate(), &out);
      65             :   CallRuntime(Runtime::kPromiseHookInit, context, instance, parent);
      66         636 :   Goto(&out);
      67             : 
      68         636 :   BIND(&out);
      69         636 :   return instance;
      70             : }
      71             : 
      72          60 : Node* PromiseBuiltinsAssembler::AllocateAndSetJSPromise(
      73             :     Node* context, v8::Promise::PromiseState status, Node* result) {
      74             :   DCHECK_NE(Promise::kPending, status);
      75             : 
      76          60 :   Node* const instance = AllocateJSPromise(context);
      77          60 :   StoreObjectFieldNoWriteBarrier(instance, JSPromise::kReactionsOrResultOffset,
      78          60 :                                  result);
      79             :   STATIC_ASSERT(JSPromise::kStatusShift == 0);
      80             :   StoreObjectFieldNoWriteBarrier(instance, JSPromise::kFlagsOffset,
      81         120 :                                  SmiConstant(status));
      82             :   for (int offset = JSPromise::kSize;
      83             :        offset < JSPromise::kSizeWithEmbedderFields; offset += kTaggedSize) {
      84             :     StoreObjectFieldNoWriteBarrier(instance, offset, SmiConstant(0));
      85             :   }
      86             : 
      87          60 :   Label out(this);
      88         120 :   GotoIfNot(IsPromiseHookEnabledOrHasAsyncEventDelegate(), &out);
      89             :   CallRuntime(Runtime::kPromiseHookInit, context, instance,
      90          60 :               UndefinedConstant());
      91          60 :   Goto(&out);
      92             : 
      93          60 :   BIND(&out);
      94          60 :   return instance;
      95             : }
      96             : 
      97             : std::pair<Node*, Node*>
      98         172 : PromiseBuiltinsAssembler::CreatePromiseResolvingFunctions(
      99             :     Node* promise, Node* debug_event, Node* native_context) {
     100             :   Node* const promise_context = CreatePromiseResolvingFunctionsContext(
     101         172 :       promise, debug_event, native_context);
     102         344 :   Node* const map = LoadContextElement(
     103         344 :       native_context, Context::STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX);
     104         344 :   Node* const resolve_info = LoadContextElement(
     105             :       native_context,
     106         172 :       Context::PROMISE_CAPABILITY_DEFAULT_RESOLVE_SHARED_FUN_INDEX);
     107             :   Node* const resolve =
     108         172 :       AllocateFunctionWithMapAndContext(map, resolve_info, promise_context);
     109         344 :   Node* const reject_info = LoadContextElement(
     110             :       native_context,
     111         172 :       Context::PROMISE_CAPABILITY_DEFAULT_REJECT_SHARED_FUN_INDEX);
     112             :   Node* const reject =
     113         172 :       AllocateFunctionWithMapAndContext(map, reject_info, promise_context);
     114         172 :   return std::make_pair(resolve, reject);
     115             : }
     116             : 
     117        1120 : void PromiseBuiltinsAssembler::ExtractHandlerContext(Node* handler,
     118             :                                                      Variable* var_context) {
     119        2240 :   VARIABLE(var_handler, MachineRepresentation::kTagged, handler);
     120        1120 :   Label loop(this, &var_handler), done(this, Label::kDeferred);
     121        1120 :   Goto(&loop);
     122        1120 :   BIND(&loop);
     123             :   {
     124        1120 :     Label if_function(this), if_bound_function(this, Label::kDeferred),
     125        1120 :         if_proxy(this, Label::kDeferred);
     126        3360 :     GotoIf(TaggedIsSmi(var_handler.value()), &done);
     127             : 
     128             :     int32_t case_values[] = {
     129             :         JS_FUNCTION_TYPE,
     130             :         JS_BOUND_FUNCTION_TYPE,
     131             :         JS_PROXY_TYPE,
     132        1120 :     };
     133             :     Label* case_labels[] = {
     134             :         &if_function,
     135             :         &if_bound_function,
     136             :         &if_proxy,
     137        1120 :     };
     138             :     static_assert(arraysize(case_values) == arraysize(case_labels), "");
     139        2240 :     TNode<Map> handler_map = LoadMap(var_handler.value());
     140        1120 :     TNode<Int32T> handler_type = LoadMapInstanceType(handler_map);
     141             :     Switch(handler_type, &done, case_values, case_labels,
     142        1120 :            arraysize(case_labels));
     143             : 
     144        1120 :     BIND(&if_bound_function);
     145             :     {
     146             :       // Use the target function's context for JSBoundFunction.
     147             :       var_handler.Bind(LoadObjectField(
     148        2240 :           var_handler.value(), JSBoundFunction::kBoundTargetFunctionOffset));
     149        1120 :       Goto(&loop);
     150             :     }
     151             : 
     152        1120 :     BIND(&if_proxy);
     153             :     {
     154             :       // Use the target function's context for JSProxy.
     155             :       // If the proxy is revoked, |var_handler| will be undefined and this
     156             :       // function will return with unchanged |var_context|.
     157             :       var_handler.Bind(
     158        2240 :           LoadObjectField(var_handler.value(), JSProxy::kTargetOffset));
     159        1120 :       Goto(&loop);
     160             :     }
     161             : 
     162        1120 :     BIND(&if_function);
     163             :     {
     164             :       // Use the function's context.
     165             :       Node* handler_context =
     166        1120 :           LoadObjectField(var_handler.value(), JSFunction::kContextOffset);
     167        2240 :       var_context->Bind(LoadNativeContext(CAST(handler_context)));
     168        1120 :       Goto(&done);
     169             :     }
     170             :   }
     171             : 
     172             :   // If no valid context is available, |var_context| is unchanged and the caller
     173             :   // will use a fallback context.
     174        1120 :   BIND(&done);
     175        1120 : }
     176             : 
     177             : // ES #sec-newpromisecapability
     178         224 : TF_BUILTIN(NewPromiseCapability, PromiseBuiltinsAssembler) {
     179             :   Node* const context = Parameter(Descriptor::kContext);
     180             :   Node* const constructor = Parameter(Descriptor::kConstructor);
     181             :   Node* const debug_event = Parameter(Descriptor::kDebugEvent);
     182          56 :   TNode<Context> const native_context = LoadNativeContext(context);
     183             : 
     184          56 :   Label if_not_constructor(this, Label::kDeferred),
     185          56 :       if_notcallable(this, Label::kDeferred), if_fast_promise_capability(this),
     186          56 :       if_slow_promise_capability(this, Label::kDeferred);
     187         112 :   GotoIf(TaggedIsSmi(constructor), &if_not_constructor);
     188         168 :   GotoIfNot(IsConstructorMap(LoadMap(constructor)), &if_not_constructor);
     189          56 :   Branch(WordEqual(constructor,
     190             :                    LoadContextElement(native_context,
     191         112 :                                       Context::PROMISE_FUNCTION_INDEX)),
     192          56 :          &if_fast_promise_capability, &if_slow_promise_capability);
     193             : 
     194          56 :   BIND(&if_fast_promise_capability);
     195             :   {
     196             :     Node* promise =
     197         112 :         AllocateAndInitJSPromise(native_context, UndefinedConstant());
     198             : 
     199          56 :     Node* resolve = nullptr;
     200          56 :     Node* reject = nullptr;
     201             :     std::tie(resolve, reject) =
     202         112 :         CreatePromiseResolvingFunctions(promise, debug_event, native_context);
     203             : 
     204         112 :     Node* capability = Allocate(PromiseCapability::kSize);
     205          56 :     StoreMapNoWriteBarrier(capability, RootIndex::kPromiseCapabilityMap);
     206             :     StoreObjectFieldNoWriteBarrier(capability,
     207          56 :                                    PromiseCapability::kPromiseOffset, promise);
     208             :     StoreObjectFieldNoWriteBarrier(capability,
     209          56 :                                    PromiseCapability::kResolveOffset, resolve);
     210             :     StoreObjectFieldNoWriteBarrier(capability, PromiseCapability::kRejectOffset,
     211          56 :                                    reject);
     212          56 :     Return(capability);
     213             :   }
     214             : 
     215          56 :   BIND(&if_slow_promise_capability);
     216             :   {
     217         112 :     Node* capability = Allocate(PromiseCapability::kSize);
     218          56 :     StoreMapNoWriteBarrier(capability, RootIndex::kPromiseCapabilityMap);
     219             :     StoreObjectFieldRoot(capability, PromiseCapability::kPromiseOffset,
     220          56 :                          RootIndex::kUndefinedValue);
     221             :     StoreObjectFieldRoot(capability, PromiseCapability::kResolveOffset,
     222          56 :                          RootIndex::kUndefinedValue);
     223             :     StoreObjectFieldRoot(capability, PromiseCapability::kRejectOffset,
     224          56 :                          RootIndex::kUndefinedValue);
     225             : 
     226             :     Node* executor_context =
     227          56 :         CreatePromiseGetCapabilitiesExecutorContext(capability, native_context);
     228         112 :     Node* executor_info = LoadContextElement(
     229          56 :         native_context, Context::PROMISE_GET_CAPABILITIES_EXECUTOR_SHARED_FUN);
     230         112 :     Node* function_map = LoadContextElement(
     231          56 :         native_context, Context::STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX);
     232          56 :     TNode<JSFunction> executor = CAST(AllocateFunctionWithMapAndContext(
     233             :         function_map, executor_info, executor_context));
     234             : 
     235             :     Node* promise = Construct(native_context, CAST(constructor), executor);
     236          56 :     StoreObjectField(capability, PromiseCapability::kPromiseOffset, promise);
     237             : 
     238             :     Node* resolve =
     239             :         LoadObjectField(capability, PromiseCapability::kResolveOffset);
     240         112 :     GotoIf(TaggedIsSmi(resolve), &if_notcallable);
     241         112 :     GotoIfNot(IsCallable(resolve), &if_notcallable);
     242             : 
     243             :     Node* reject =
     244             :         LoadObjectField(capability, PromiseCapability::kRejectOffset);
     245         112 :     GotoIf(TaggedIsSmi(reject), &if_notcallable);
     246         112 :     GotoIfNot(IsCallable(reject), &if_notcallable);
     247          56 :     Return(capability);
     248             :   }
     249             : 
     250          56 :   BIND(&if_not_constructor);
     251          56 :   ThrowTypeError(context, MessageTemplate::kNotConstructor, constructor);
     252             : 
     253          56 :   BIND(&if_notcallable);
     254          56 :   ThrowTypeError(context, MessageTemplate::kPromiseNonCallable);
     255          56 : }
     256             : 
     257         688 : Node* PromiseBuiltinsAssembler::CreatePromiseContext(Node* native_context,
     258             :                                                      int slots) {
     259             :   DCHECK_GE(slots, Context::MIN_CONTEXT_SLOTS);
     260             : 
     261        1376 :   Node* const context = AllocateInNewSpace(FixedArray::SizeFor(slots));
     262         688 :   InitializeFunctionContext(native_context, context, slots);
     263         688 :   return context;
     264             : }
     265             : 
     266         112 : Node* PromiseBuiltinsAssembler::CreatePromiseAllResolveElementContext(
     267             :     Node* promise_capability, Node* native_context) {
     268             :   CSA_ASSERT(this, IsNativeContext(native_context));
     269             : 
     270             :   // TODO(bmeurer): Manually fold this into a single allocation.
     271         112 :   TNode<Map> array_map = CAST(LoadContextElement(
     272             :       native_context, Context::JS_ARRAY_PACKED_ELEMENTS_MAP_INDEX));
     273             :   TNode<JSArray> values_array = AllocateJSArray(
     274         112 :       PACKED_ELEMENTS, array_map, IntPtrConstant(0), SmiConstant(0));
     275             : 
     276             :   Node* const context = CreatePromiseContext(
     277         112 :       native_context, PromiseBuiltins::kPromiseAllResolveElementLength);
     278         112 :   StoreContextElementNoWriteBarrier(
     279             :       context, PromiseBuiltins::kPromiseAllResolveElementRemainingSlot,
     280         336 :       SmiConstant(1));
     281         112 :   StoreContextElementNoWriteBarrier(
     282             :       context, PromiseBuiltins::kPromiseAllResolveElementCapabilitySlot,
     283         112 :       promise_capability);
     284         112 :   StoreContextElementNoWriteBarrier(
     285             :       context, PromiseBuiltins::kPromiseAllResolveElementValuesArraySlot,
     286         112 :       values_array);
     287             : 
     288         112 :   return context;
     289             : }
     290             : 
     291             : TNode<JSFunction>
     292         168 : PromiseBuiltinsAssembler::CreatePromiseAllResolveElementFunction(
     293             :     Node* context, TNode<Smi> index, Node* native_context, int slot_index) {
     294             :   CSA_ASSERT(this, SmiGreaterThan(index, SmiConstant(0)));
     295             :   CSA_ASSERT(this, SmiLessThanOrEqual(
     296             :                        index, SmiConstant(PropertyArray::HashField::kMax)));
     297             :   CSA_ASSERT(this, IsNativeContext(native_context));
     298             : 
     299         336 :   Node* const map = LoadContextElement(
     300         336 :       native_context, Context::STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX);
     301         336 :   Node* const resolve_info = LoadContextElement(native_context, slot_index);
     302             :   TNode<JSFunction> resolve =
     303         168 :       Cast(AllocateFunctionWithMapAndContext(map, resolve_info, context));
     304             : 
     305             :   STATIC_ASSERT(PropertyArray::kNoHashSentinel == 0);
     306             :   StoreObjectFieldNoWriteBarrier(resolve, JSFunction::kPropertiesOrHashOffset,
     307             :                                  index);
     308             : 
     309         168 :   return resolve;
     310             : }
     311             : 
     312         180 : Node* PromiseBuiltinsAssembler::CreatePromiseResolvingFunctionsContext(
     313             :     Node* promise, Node* debug_event, Node* native_context) {
     314             :   Node* const context = CreatePromiseContext(
     315         180 :       native_context, PromiseBuiltins::kPromiseContextLength);
     316         360 :   StoreContextElementNoWriteBarrier(context, PromiseBuiltins::kPromiseSlot,
     317         180 :                                     promise);
     318         180 :   StoreContextElementNoWriteBarrier(
     319         540 :       context, PromiseBuiltins::kAlreadyResolvedSlot, FalseConstant());
     320         180 :   StoreContextElementNoWriteBarrier(context, PromiseBuiltins::kDebugEventSlot,
     321         180 :                                     debug_event);
     322         180 :   return context;
     323             : }
     324             : 
     325          60 : Node* PromiseBuiltinsAssembler::CreatePromiseGetCapabilitiesExecutorContext(
     326             :     Node* promise_capability, Node* native_context) {
     327             :   int kContextLength = PromiseBuiltins::kCapabilitiesContextLength;
     328          60 :   Node* context = CreatePromiseContext(native_context, kContextLength);
     329         120 :   StoreContextElementNoWriteBarrier(context, PromiseBuiltins::kCapabilitySlot,
     330          60 :                                     promise_capability);
     331          60 :   return context;
     332             : }
     333             : 
     334         284 : Node* PromiseBuiltinsAssembler::PromiseHasHandler(Node* promise) {
     335         284 :   Node* const flags = LoadObjectField(promise, JSPromise::kFlagsOffset);
     336         852 :   return IsSetWord(SmiUntag(flags), 1 << JSPromise::kHasHandlerBit);
     337             : }
     338             : 
     339         224 : void PromiseBuiltinsAssembler::PromiseSetHasHandler(Node* promise) {
     340             :   TNode<Smi> const flags =
     341         448 :       CAST(LoadObjectField(promise, JSPromise::kFlagsOffset));
     342             :   TNode<Smi> const new_flags =
     343         224 :       SmiOr(flags, SmiConstant(1 << JSPromise::kHasHandlerBit));
     344         224 :   StoreObjectFieldNoWriteBarrier(promise, JSPromise::kFlagsOffset, new_flags);
     345         224 : }
     346             : 
     347         560 : Node* PromiseBuiltinsAssembler::IsPromiseStatus(
     348             :     Node* actual, v8::Promise::PromiseState expected) {
     349        1680 :   return Word32Equal(actual, Int32Constant(expected));
     350             : }
     351             : 
     352         336 : Node* PromiseBuiltinsAssembler::PromiseStatus(Node* promise) {
     353             :   STATIC_ASSERT(JSPromise::kStatusShift == 0);
     354             :   TNode<Smi> const flags =
     355         336 :       CAST(LoadObjectField(promise, JSPromise::kFlagsOffset));
     356        1344 :   return Word32And(SmiToInt32(flags), Int32Constant(JSPromise::kStatusMask));
     357             : }
     358             : 
     359         112 : void PromiseBuiltinsAssembler::PromiseSetStatus(
     360             :     Node* promise, v8::Promise::PromiseState const status) {
     361             :   CSA_ASSERT(this,
     362             :              IsPromiseStatus(PromiseStatus(promise), v8::Promise::kPending));
     363         112 :   CHECK_NE(status, v8::Promise::kPending);
     364             : 
     365         224 :   TNode<Smi> mask = SmiConstant(status);
     366             :   TNode<Smi> const flags =
     367         224 :       CAST(LoadObjectField(promise, JSPromise::kFlagsOffset));
     368             :   StoreObjectFieldNoWriteBarrier(promise, JSPromise::kFlagsOffset,
     369         224 :                                  SmiOr(flags, mask));
     370         112 : }
     371             : 
     372           0 : void PromiseBuiltinsAssembler::PromiseSetHandledHint(Node* promise) {
     373             :   TNode<Smi> const flags =
     374           0 :       CAST(LoadObjectField(promise, JSPromise::kFlagsOffset));
     375             :   TNode<Smi> const new_flags =
     376           0 :       SmiOr(flags, SmiConstant(1 << JSPromise::kHandledHintBit));
     377           0 :   StoreObjectFieldNoWriteBarrier(promise, JSPromise::kFlagsOffset, new_flags);
     378           0 : }
     379             : 
     380             : // ES #sec-performpromisethen
     381         224 : void PromiseBuiltinsAssembler::PerformPromiseThen(
     382             :     Node* context, Node* promise, Node* on_fulfilled, Node* on_rejected,
     383             :     Node* result_promise_or_capability) {
     384             :   CSA_ASSERT(this, TaggedIsNotSmi(promise));
     385             :   CSA_ASSERT(this, IsJSPromise(promise));
     386             :   CSA_ASSERT(this,
     387             :              Word32Or(IsCallable(on_fulfilled), IsUndefined(on_fulfilled)));
     388             :   CSA_ASSERT(this, Word32Or(IsCallable(on_rejected), IsUndefined(on_rejected)));
     389             :   CSA_ASSERT(this, TaggedIsNotSmi(result_promise_or_capability));
     390             :   CSA_ASSERT(
     391             :       this,
     392             :       Word32Or(Word32Or(IsJSPromise(result_promise_or_capability),
     393             :                         IsPromiseCapability(result_promise_or_capability)),
     394             :                IsUndefined(result_promise_or_capability)));
     395             : 
     396         448 :   Label if_pending(this), if_notpending(this), done(this);
     397         224 :   Node* const status = PromiseStatus(promise);
     398         448 :   Branch(IsPromiseStatus(status, v8::Promise::kPending), &if_pending,
     399         224 :          &if_notpending);
     400             : 
     401         224 :   BIND(&if_pending);
     402             :   {
     403             :     // The {promise} is still in "Pending" state, so we just record a new
     404             :     // PromiseReaction holding both the onFulfilled and onRejected callbacks.
     405             :     // Once the {promise} is resolved we decide on the concrete handler to
     406             :     // push onto the microtask queue.
     407             :     Node* const promise_reactions =
     408             :         LoadObjectField(promise, JSPromise::kReactionsOrResultOffset);
     409             :     Node* const reaction =
     410             :         AllocatePromiseReaction(promise_reactions, result_promise_or_capability,
     411         224 :                                 on_fulfilled, on_rejected);
     412         224 :     StoreObjectField(promise, JSPromise::kReactionsOrResultOffset, reaction);
     413         224 :     Goto(&done);
     414             :   }
     415             : 
     416         224 :   BIND(&if_notpending);
     417             :   {
     418         448 :     VARIABLE(var_map, MachineRepresentation::kTagged);
     419         448 :     VARIABLE(var_handler, MachineRepresentation::kTagged);
     420         672 :     VARIABLE(var_handler_context, MachineRepresentation::kTagged,
     421             :              UndefinedConstant());
     422         224 :     Label if_fulfilled(this), if_rejected(this, Label::kDeferred),
     423         224 :         enqueue(this);
     424         448 :     Branch(IsPromiseStatus(status, v8::Promise::kFulfilled), &if_fulfilled,
     425         224 :            &if_rejected);
     426             : 
     427         224 :     BIND(&if_fulfilled);
     428             :     {
     429         448 :       var_map.Bind(LoadRoot(RootIndex::kPromiseFulfillReactionJobTaskMap));
     430         224 :       var_handler.Bind(on_fulfilled);
     431             : 
     432         224 :       Label use_fallback(this, Label::kDeferred), done(this);
     433         224 :       ExtractHandlerContext(on_fulfilled, &var_handler_context);
     434         672 :       Branch(IsUndefined(var_handler_context.value()), &use_fallback, &done);
     435             : 
     436         224 :       BIND(&use_fallback);
     437         224 :       var_handler_context.Bind(context);
     438         224 :       ExtractHandlerContext(on_rejected, &var_handler_context);
     439         224 :       Goto(&done);
     440             : 
     441         224 :       BIND(&done);
     442         224 :       Goto(&enqueue);
     443             :     }
     444             : 
     445         224 :     BIND(&if_rejected);
     446             :     {
     447             :       CSA_ASSERT(this, IsPromiseStatus(status, v8::Promise::kRejected));
     448         448 :       var_map.Bind(LoadRoot(RootIndex::kPromiseRejectReactionJobTaskMap));
     449         224 :       var_handler.Bind(on_rejected);
     450             : 
     451         224 :       Label use_fallback(this, Label::kDeferred), done(this);
     452         224 :       ExtractHandlerContext(on_rejected, &var_handler_context);
     453         672 :       Branch(IsUndefined(var_handler_context.value()), &use_fallback, &done);
     454             : 
     455         224 :       BIND(&use_fallback);
     456         224 :       var_handler_context.Bind(context);
     457         224 :       ExtractHandlerContext(on_fulfilled, &var_handler_context);
     458         224 :       Goto(&done);
     459         224 :       BIND(&done);
     460             : 
     461         448 :       GotoIf(PromiseHasHandler(promise), &enqueue);
     462             :       CallRuntime(Runtime::kPromiseRevokeReject, context, promise);
     463         224 :       Goto(&enqueue);
     464             :     }
     465             : 
     466         224 :     BIND(&enqueue);
     467             :     {
     468             :       Node* argument =
     469             :           LoadObjectField(promise, JSPromise::kReactionsOrResultOffset);
     470         224 :       Node* microtask = AllocatePromiseReactionJobTask(
     471             :           var_map.value(), var_handler_context.value(), argument,
     472         224 :           var_handler.value(), result_promise_or_capability);
     473             :       CallBuiltin(Builtins::kEnqueueMicrotask, var_handler_context.value(),
     474         448 :                   microtask);
     475         224 :       Goto(&done);
     476             :     }
     477             :   }
     478             : 
     479         224 :   BIND(&done);
     480         224 :   PromiseSetHasHandler(promise);
     481         224 : }
     482             : 
     483             : // ES #sec-performpromisethen
     484         224 : TF_BUILTIN(PerformPromiseThen, PromiseBuiltinsAssembler) {
     485             :   Node* const context = Parameter(Descriptor::kContext);
     486             :   Node* const promise = Parameter(Descriptor::kPromise);
     487             :   Node* const on_fulfilled = Parameter(Descriptor::kOnFulfilled);
     488             :   Node* const on_rejected = Parameter(Descriptor::kOnRejected);
     489             :   Node* const result_promise = Parameter(Descriptor::kResultPromise);
     490             : 
     491             :   CSA_ASSERT(this, TaggedIsNotSmi(result_promise));
     492             :   CSA_ASSERT(
     493             :       this, Word32Or(IsJSPromise(result_promise), IsUndefined(result_promise)));
     494             : 
     495          56 :   PerformPromiseThen(context, promise, on_fulfilled, on_rejected,
     496          56 :                      result_promise);
     497          56 :   Return(result_promise);
     498          56 : }
     499             : 
     500         224 : Node* PromiseBuiltinsAssembler::AllocatePromiseReaction(
     501             :     Node* next, Node* promise_or_capability, Node* fulfill_handler,
     502             :     Node* reject_handler) {
     503         448 :   Node* const reaction = Allocate(PromiseReaction::kSize);
     504         224 :   StoreMapNoWriteBarrier(reaction, RootIndex::kPromiseReactionMap);
     505         224 :   StoreObjectFieldNoWriteBarrier(reaction, PromiseReaction::kNextOffset, next);
     506             :   StoreObjectFieldNoWriteBarrier(reaction,
     507             :                                  PromiseReaction::kPromiseOrCapabilityOffset,
     508         224 :                                  promise_or_capability);
     509             :   StoreObjectFieldNoWriteBarrier(
     510         224 :       reaction, PromiseReaction::kFulfillHandlerOffset, fulfill_handler);
     511             :   StoreObjectFieldNoWriteBarrier(
     512         224 :       reaction, PromiseReaction::kRejectHandlerOffset, reject_handler);
     513         224 :   return reaction;
     514             : }
     515             : 
     516         224 : Node* PromiseBuiltinsAssembler::AllocatePromiseReactionJobTask(
     517             :     Node* map, Node* context, Node* argument, Node* handler,
     518             :     Node* promise_or_capability) {
     519         448 :   Node* const microtask = Allocate(PromiseReactionJobTask::kSize);
     520         224 :   StoreMapNoWriteBarrier(microtask, map);
     521             :   StoreObjectFieldNoWriteBarrier(
     522         224 :       microtask, PromiseReactionJobTask::kArgumentOffset, argument);
     523             :   StoreObjectFieldNoWriteBarrier(
     524         224 :       microtask, PromiseReactionJobTask::kContextOffset, context);
     525             :   StoreObjectFieldNoWriteBarrier(
     526         224 :       microtask, PromiseReactionJobTask::kHandlerOffset, handler);
     527             :   StoreObjectFieldNoWriteBarrier(
     528             :       microtask, PromiseReactionJobTask::kPromiseOrCapabilityOffset,
     529         224 :       promise_or_capability);
     530         224 :   return microtask;
     531             : }
     532             : 
     533           0 : Node* PromiseBuiltinsAssembler::AllocatePromiseReactionJobTask(
     534             :     RootIndex map_root_index, Node* context, Node* argument, Node* handler,
     535             :     Node* promise_or_capability) {
     536             :   DCHECK(map_root_index == RootIndex::kPromiseFulfillReactionJobTaskMap ||
     537             :          map_root_index == RootIndex::kPromiseRejectReactionJobTaskMap);
     538           0 :   Node* const map = LoadRoot(map_root_index);
     539             :   return AllocatePromiseReactionJobTask(map, context, argument, handler,
     540           0 :                                         promise_or_capability);
     541             : }
     542             : 
     543          56 : Node* PromiseBuiltinsAssembler::AllocatePromiseResolveThenableJobTask(
     544             :     Node* promise_to_resolve, Node* then, Node* thenable, Node* context) {
     545         112 :   Node* const microtask = Allocate(PromiseResolveThenableJobTask::kSize);
     546             :   StoreMapNoWriteBarrier(microtask,
     547          56 :                          RootIndex::kPromiseResolveThenableJobTaskMap);
     548             :   StoreObjectFieldNoWriteBarrier(
     549          56 :       microtask, PromiseResolveThenableJobTask::kContextOffset, context);
     550             :   StoreObjectFieldNoWriteBarrier(
     551             :       microtask, PromiseResolveThenableJobTask::kPromiseToResolveOffset,
     552          56 :       promise_to_resolve);
     553             :   StoreObjectFieldNoWriteBarrier(
     554          56 :       microtask, PromiseResolveThenableJobTask::kThenOffset, then);
     555             :   StoreObjectFieldNoWriteBarrier(
     556          56 :       microtask, PromiseResolveThenableJobTask::kThenableOffset, thenable);
     557          56 :   return microtask;
     558             : }
     559             : 
     560             : // ES #sec-triggerpromisereactions
     561         112 : Node* PromiseBuiltinsAssembler::TriggerPromiseReactions(
     562             :     Node* context, Node* reactions, Node* argument,
     563             :     PromiseReaction::Type type) {
     564             :   // We need to reverse the {reactions} here, since we record them on the
     565             :   // JSPromise in the reverse order.
     566             :   {
     567         224 :     VARIABLE(var_current, MachineRepresentation::kTagged, reactions);
     568         336 :     VARIABLE(var_reversed, MachineRepresentation::kTagged,
     569             :              SmiConstant(Smi::zero()));
     570             : 
     571             :     // As an additional safety net against misuse of the V8 Extras API, we
     572             :     // sanity check the {reactions} to make sure that they are actually
     573             :     // PromiseReaction instances and not actual JavaScript values (which
     574             :     // would indicate that we're rejecting or resolving an already settled
     575             :     // promise), see https://crbug.com/931640 for details on this.
     576             :     TNode<Map> promise_reaction_map =
     577         112 :         CAST(LoadRoot(RootIndex::kPromiseReactionMap));
     578             : 
     579         336 :     Label loop(this, {&var_current, &var_reversed}), done_loop(this);
     580         112 :     Goto(&loop);
     581         112 :     BIND(&loop);
     582             :     {
     583         112 :       Node* current = var_current.value();
     584         224 :       GotoIf(TaggedIsSmi(current), &done_loop);
     585         224 :       CSA_CHECK(this, WordEqual(LoadMap(CAST(current)), promise_reaction_map));
     586         112 :       var_current.Bind(LoadObjectField(current, PromiseReaction::kNextOffset));
     587         112 :       StoreObjectField(current, PromiseReaction::kNextOffset,
     588         112 :                        var_reversed.value());
     589         112 :       var_reversed.Bind(current);
     590         112 :       Goto(&loop);
     591             :     }
     592         112 :     BIND(&done_loop);
     593         112 :     reactions = var_reversed.value();
     594             :   }
     595             : 
     596             :   // Morph the {reactions} into PromiseReactionJobTasks and push them
     597             :   // onto the microtask queue.
     598             :   {
     599         224 :     VARIABLE(var_current, MachineRepresentation::kTagged, reactions);
     600             : 
     601         336 :     Label loop(this, {&var_current}), done_loop(this);
     602         112 :     Goto(&loop);
     603         112 :     BIND(&loop);
     604             :     {
     605         112 :       Node* current = var_current.value();
     606         224 :       GotoIf(TaggedIsSmi(current), &done_loop);
     607         112 :       var_current.Bind(LoadObjectField(current, PromiseReaction::kNextOffset));
     608             : 
     609         336 :       VARIABLE(var_context, MachineRepresentation::kTagged,
     610             :                UndefinedConstant());
     611             : 
     612             :       Node* primary_handler;
     613             :       Node* secondary_handler;
     614         112 :       if (type == PromiseReaction::kFulfill) {
     615             :         primary_handler =
     616             :             LoadObjectField(current, PromiseReaction::kFulfillHandlerOffset);
     617             :         secondary_handler =
     618             :             LoadObjectField(current, PromiseReaction::kRejectHandlerOffset);
     619             :       } else {
     620             :         primary_handler =
     621             :             LoadObjectField(current, PromiseReaction::kRejectHandlerOffset);
     622             :         secondary_handler =
     623             :             LoadObjectField(current, PromiseReaction::kFulfillHandlerOffset);
     624             :       }
     625             : 
     626             :       {
     627         112 :         Label use_fallback(this, Label::kDeferred), done(this);
     628         112 :         ExtractHandlerContext(primary_handler, &var_context);
     629         336 :         Branch(IsUndefined(var_context.value()), &use_fallback, &done);
     630             : 
     631         112 :         BIND(&use_fallback);
     632         112 :         var_context.Bind(context);
     633         112 :         ExtractHandlerContext(secondary_handler, &var_context);
     634             :         CSA_ASSERT(this, IsNotUndefined(var_context.value()));
     635         112 :         Goto(&done);
     636             : 
     637         112 :         BIND(&done);
     638             :       }
     639             : 
     640             :       // Morph {current} from a PromiseReaction into a PromiseReactionJobTask
     641             :       // and schedule that on the microtask queue. We try to minimize the number
     642             :       // of stores here to avoid screwing up the store buffer.
     643             :       STATIC_ASSERT(static_cast<int>(PromiseReaction::kSize) ==
     644             :                     static_cast<int>(PromiseReactionJobTask::kSize));
     645         112 :       if (type == PromiseReaction::kFulfill) {
     646             :         StoreMapNoWriteBarrier(current,
     647          56 :                                RootIndex::kPromiseFulfillReactionJobTaskMap);
     648             :         StoreObjectField(current, PromiseReactionJobTask::kArgumentOffset,
     649          56 :                          argument);
     650          56 :         StoreObjectField(current, PromiseReactionJobTask::kContextOffset,
     651          56 :                          var_context.value());
     652             :         STATIC_ASSERT(
     653             :             static_cast<int>(PromiseReaction::kFulfillHandlerOffset) ==
     654             :             static_cast<int>(PromiseReactionJobTask::kHandlerOffset));
     655             :         STATIC_ASSERT(
     656             :             static_cast<int>(PromiseReaction::kPromiseOrCapabilityOffset) ==
     657             :             static_cast<int>(
     658             :                 PromiseReactionJobTask::kPromiseOrCapabilityOffset));
     659             :       } else {
     660             :         StoreMapNoWriteBarrier(current,
     661          56 :                                RootIndex::kPromiseRejectReactionJobTaskMap);
     662             :         StoreObjectField(current, PromiseReactionJobTask::kArgumentOffset,
     663          56 :                          argument);
     664          56 :         StoreObjectField(current, PromiseReactionJobTask::kContextOffset,
     665          56 :                          var_context.value());
     666             :         StoreObjectField(current, PromiseReactionJobTask::kHandlerOffset,
     667          56 :                          primary_handler);
     668             :         STATIC_ASSERT(
     669             :             static_cast<int>(PromiseReaction::kPromiseOrCapabilityOffset) ==
     670             :             static_cast<int>(
     671             :                 PromiseReactionJobTask::kPromiseOrCapabilityOffset));
     672             :       }
     673         224 :       CallBuiltin(Builtins::kEnqueueMicrotask, var_context.value(), current);
     674         112 :       Goto(&loop);
     675             :     }
     676         112 :     BIND(&done_loop);
     677             :   }
     678             : 
     679         224 :   return UndefinedConstant();
     680             : }
     681             : 
     682             : template <typename... TArgs>
     683         224 : Node* PromiseBuiltinsAssembler::InvokeThen(Node* native_context, Node* receiver,
     684             :                                            TArgs... args) {
     685             :   CSA_ASSERT(this, IsNativeContext(native_context));
     686             : 
     687         448 :   VARIABLE(var_result, MachineRepresentation::kTagged);
     688         224 :   Label if_fast(this), if_slow(this, Label::kDeferred), done(this, &var_result);
     689         448 :   GotoIf(TaggedIsSmi(receiver), &if_slow);
     690         448 :   Node* const receiver_map = LoadMap(receiver);
     691             :   // We can skip the "then" lookup on {receiver} if it's [[Prototype]]
     692             :   // is the (initial) Promise.prototype and the Promise#then protector
     693             :   // is intact, as that guards the lookup path for the "then" property
     694             :   // on JSPromise instances which have the (initial) %PromisePrototype%.
     695         224 :   BranchIfPromiseThenLookupChainIntact(native_context, receiver_map, &if_fast,
     696             :                                        &if_slow);
     697             : 
     698         224 :   BIND(&if_fast);
     699             :   {
     700             :     Node* const then =
     701         448 :         LoadContextElement(native_context, Context::PROMISE_THEN_INDEX);
     702             :     Node* const result =
     703             :         CallJS(CodeFactory::CallFunction(
     704             :                    isolate(), ConvertReceiverMode::kNotNullOrUndefined),
     705         448 :                native_context, then, receiver, args...);
     706         224 :     var_result.Bind(result);
     707         224 :     Goto(&done);
     708             :   }
     709             : 
     710         224 :   BIND(&if_slow);
     711             :   {
     712         448 :     Node* const then = GetProperty(native_context, receiver,
     713         448 :                                    isolate()->factory()->then_string());
     714             :     Node* const result = CallJS(
     715             :         CodeFactory::Call(isolate(), ConvertReceiverMode::kNotNullOrUndefined),
     716         448 :         native_context, then, receiver, args...);
     717         224 :     var_result.Bind(result);
     718         224 :     Goto(&done);
     719             :   }
     720             : 
     721         224 :   BIND(&done);
     722         448 :   return var_result.value();
     723             : }
     724             : 
     725         168 : Node* PromiseBuiltinsAssembler::InvokeResolve(Node* native_context,
     726             :                                               Node* constructor, Node* value,
     727             :                                               Label* if_exception,
     728             :                                               Variable* var_exception) {
     729             :   CSA_ASSERT(this, IsNativeContext(native_context));
     730             : 
     731         336 :   VARIABLE(var_result, MachineRepresentation::kTagged);
     732         168 :   Label if_fast(this), if_slow(this, Label::kDeferred), done(this, &var_result);
     733             :   // We can skip the "resolve" lookup on {constructor} if it's the
     734             :   // Promise constructor and the Promise.resolve protector is intact,
     735             :   // as that guards the lookup path for the "resolve" property on the
     736             :   // Promise constructor.
     737             :   BranchIfPromiseResolveLookupChainIntact(native_context, constructor, &if_fast,
     738         168 :                                           &if_slow);
     739             : 
     740         168 :   BIND(&if_fast);
     741             :   {
     742         336 :     Node* const result = CallBuiltin(Builtins::kPromiseResolve, native_context,
     743         168 :                                      constructor, value);
     744         168 :     GotoIfException(result, if_exception, var_exception);
     745             : 
     746         168 :     var_result.Bind(result);
     747         168 :     Goto(&done);
     748             :   }
     749             : 
     750         168 :   BIND(&if_slow);
     751             :   {
     752             :     Node* const resolve =
     753         504 :         GetProperty(native_context, constructor, factory()->resolve_string());
     754         168 :     GotoIfException(resolve, if_exception, var_exception);
     755             : 
     756             :     Node* const result = CallJS(
     757         336 :         CodeFactory::Call(isolate(), ConvertReceiverMode::kNotNullOrUndefined),
     758         168 :         native_context, resolve, constructor, value);
     759         168 :     GotoIfException(result, if_exception, var_exception);
     760             : 
     761         168 :     var_result.Bind(result);
     762         168 :     Goto(&done);
     763             :   }
     764             : 
     765         168 :   BIND(&done);
     766         336 :   return var_result.value();
     767             : }
     768             : 
     769         280 : void PromiseBuiltinsAssembler::BranchIfPromiseResolveLookupChainIntact(
     770             :     Node* native_context, Node* constructor, Label* if_fast, Label* if_slow) {
     771             :   CSA_ASSERT(this, IsNativeContext(native_context));
     772             : 
     773         280 :   GotoIfForceSlowPath(if_slow);
     774             :   Node* const promise_fun =
     775         560 :       LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX);
     776         560 :   GotoIfNot(WordEqual(promise_fun, constructor), if_slow);
     777         560 :   Branch(IsPromiseResolveProtectorCellInvalid(), if_slow, if_fast);
     778         280 : }
     779             : 
     780         112 : void PromiseBuiltinsAssembler::GotoIfNotPromiseResolveLookupChainIntact(
     781             :     Node* native_context, Node* constructor, Label* if_slow) {
     782         224 :   Label if_fast(this);
     783             :   BranchIfPromiseResolveLookupChainIntact(native_context, constructor, &if_fast,
     784         112 :                                           if_slow);
     785         112 :   BIND(&if_fast);
     786         112 : }
     787             : 
     788         168 : void PromiseBuiltinsAssembler::BranchIfPromiseSpeciesLookupChainIntact(
     789             :     Node* native_context, Node* promise_map, Label* if_fast, Label* if_slow) {
     790             :   CSA_ASSERT(this, IsNativeContext(native_context));
     791             :   CSA_ASSERT(this, IsJSPromiseMap(promise_map));
     792             : 
     793             :   Node* const promise_prototype =
     794         336 :       LoadContextElement(native_context, Context::PROMISE_PROTOTYPE_INDEX);
     795         168 :   GotoIfForceSlowPath(if_slow);
     796         504 :   GotoIfNot(WordEqual(LoadMapPrototype(promise_map), promise_prototype),
     797         168 :             if_slow);
     798         336 :   Branch(IsPromiseSpeciesProtectorCellInvalid(), if_slow, if_fast);
     799         168 : }
     800             : 
     801         336 : void PromiseBuiltinsAssembler::BranchIfPromiseThenLookupChainIntact(
     802             :     Node* native_context, Node* receiver_map, Label* if_fast, Label* if_slow) {
     803             :   CSA_ASSERT(this, IsMap(receiver_map));
     804             :   CSA_ASSERT(this, IsNativeContext(native_context));
     805             : 
     806         336 :   GotoIfForceSlowPath(if_slow);
     807         672 :   GotoIfNot(IsJSPromiseMap(receiver_map), if_slow);
     808             :   Node* const promise_prototype =
     809         672 :       LoadContextElement(native_context, Context::PROMISE_PROTOTYPE_INDEX);
     810         672 :   GotoIfNot(WordEqual(LoadMapPrototype(receiver_map), promise_prototype),
     811         336 :             if_slow);
     812         672 :   Branch(IsPromiseThenProtectorCellInvalid(), if_slow, if_fast);
     813         336 : }
     814             : 
     815          56 : void PromiseBuiltinsAssembler::BranchIfAccessCheckFailed(
     816             :     Node* context, Node* native_context, Node* promise_constructor,
     817             :     Node* executor, Label* if_noaccess) {
     818         112 :   VARIABLE(var_executor, MachineRepresentation::kTagged);
     819          56 :   var_executor.Bind(executor);
     820          56 :   Label has_access(this), call_runtime(this, Label::kDeferred);
     821             : 
     822             :   // If executor is a bound function, load the bound function until we've
     823             :   // reached an actual function.
     824          56 :   Label found_function(this), loop_over_bound_function(this, &var_executor);
     825          56 :   Goto(&loop_over_bound_function);
     826          56 :   BIND(&loop_over_bound_function);
     827             :   {
     828         168 :     Node* executor_type = LoadInstanceType(var_executor.value());
     829         112 :     GotoIf(InstanceTypeEqual(executor_type, JS_FUNCTION_TYPE), &found_function);
     830         112 :     GotoIfNot(InstanceTypeEqual(executor_type, JS_BOUND_FUNCTION_TYPE),
     831          56 :               &call_runtime);
     832             :     var_executor.Bind(LoadObjectField(
     833         112 :         var_executor.value(), JSBoundFunction::kBoundTargetFunctionOffset));
     834          56 :     Goto(&loop_over_bound_function);
     835             :   }
     836             : 
     837             :   // Load the context from the function and compare it to the Promise
     838             :   // constructor's context. If they match, everything is fine, otherwise, bail
     839             :   // out to the runtime.
     840          56 :   BIND(&found_function);
     841             :   {
     842             :     Node* function_context =
     843          56 :         LoadObjectField(var_executor.value(), JSFunction::kContextOffset);
     844         112 :     Node* native_function_context = LoadNativeContext(function_context);
     845         112 :     Branch(WordEqual(native_context, native_function_context), &has_access,
     846          56 :            &call_runtime);
     847             :   }
     848             : 
     849          56 :   BIND(&call_runtime);
     850             :   {
     851          56 :     Branch(WordEqual(CallRuntime(Runtime::kAllowDynamicFunction, context,
     852             :                                  promise_constructor),
     853          56 :                      TrueConstant()),
     854          56 :            &has_access, if_noaccess);
     855             :   }
     856             : 
     857          56 :   BIND(&has_access);
     858          56 : }
     859             : 
     860         168 : void PromiseBuiltinsAssembler::SetForwardingHandlerIfTrue(
     861             :     Node* context, Node* condition, const NodeGenerator& object) {
     862         336 :   Label done(this);
     863         168 :   GotoIfNot(condition, &done);
     864             :   SetPropertyStrict(
     865             :       CAST(context), CAST(object()),
     866         168 :       HeapConstant(factory()->promise_forwarding_handler_symbol()),
     867         336 :       TrueConstant());
     868         168 :   Goto(&done);
     869         168 :   BIND(&done);
     870         168 : }
     871             : 
     872         168 : void PromiseBuiltinsAssembler::SetPromiseHandledByIfTrue(
     873             :     Node* context, Node* condition, Node* promise,
     874             :     const NodeGenerator& handled_by) {
     875         336 :   Label done(this);
     876         168 :   GotoIfNot(condition, &done);
     877         336 :   GotoIf(TaggedIsSmi(promise), &done);
     878         336 :   GotoIfNot(HasInstanceType(promise, JS_PROMISE_TYPE), &done);
     879             :   SetPropertyStrict(CAST(context), CAST(promise),
     880         168 :                     HeapConstant(factory()->promise_handled_by_symbol()),
     881             :                     CAST(handled_by()));
     882         168 :   Goto(&done);
     883         168 :   BIND(&done);
     884         168 : }
     885             : 
     886             : // ES #sec-promise-reject-functions
     887         224 : TF_BUILTIN(PromiseCapabilityDefaultReject, PromiseBuiltinsAssembler) {
     888             :   Node* const reason = Parameter(Descriptor::kReason);
     889             :   Node* const context = Parameter(Descriptor::kContext);
     890             : 
     891             :   // 2. Let promise be F.[[Promise]].
     892             :   Node* const promise =
     893         112 :       LoadContextElement(context, PromiseBuiltins::kPromiseSlot);
     894             : 
     895             :   // 3. Let alreadyResolved be F.[[AlreadyResolved]].
     896          56 :   Label if_already_resolved(this, Label::kDeferred);
     897             :   Node* const already_resolved =
     898         112 :       LoadContextElement(context, PromiseBuiltins::kAlreadyResolvedSlot);
     899             : 
     900             :   // 4. If alreadyResolved.[[Value]] is true, return undefined.
     901         112 :   GotoIf(IsTrue(already_resolved), &if_already_resolved);
     902             : 
     903             :   // 5. Set alreadyResolved.[[Value]] to true.
     904          56 :   StoreContextElementNoWriteBarrier(
     905         168 :       context, PromiseBuiltins::kAlreadyResolvedSlot, TrueConstant());
     906             : 
     907             :   // 6. Return RejectPromise(promise, reason).
     908             :   Node* const debug_event =
     909         112 :       LoadContextElement(context, PromiseBuiltins::kDebugEventSlot);
     910         112 :   Return(CallBuiltin(Builtins::kRejectPromise, context, promise, reason,
     911         112 :                      debug_event));
     912             : 
     913          56 :   BIND(&if_already_resolved);
     914             :   {
     915          56 :     Return(CallRuntime(Runtime::kPromiseRejectAfterResolved, context, promise,
     916          56 :                        reason));
     917             :   }
     918          56 : }
     919             : 
     920             : // ES #sec-promise-resolve-functions
     921         224 : TF_BUILTIN(PromiseCapabilityDefaultResolve, PromiseBuiltinsAssembler) {
     922             :   Node* const resolution = Parameter(Descriptor::kResolution);
     923             :   Node* const context = Parameter(Descriptor::kContext);
     924             : 
     925             :   // 2. Let promise be F.[[Promise]].
     926             :   Node* const promise =
     927         112 :       LoadContextElement(context, PromiseBuiltins::kPromiseSlot);
     928             : 
     929             :   // 3. Let alreadyResolved be F.[[AlreadyResolved]].
     930          56 :   Label if_already_resolved(this, Label::kDeferred);
     931             :   Node* const already_resolved =
     932         112 :       LoadContextElement(context, PromiseBuiltins::kAlreadyResolvedSlot);
     933             : 
     934             :   // 4. If alreadyResolved.[[Value]] is true, return undefined.
     935         112 :   GotoIf(IsTrue(already_resolved), &if_already_resolved);
     936             : 
     937             :   // 5. Set alreadyResolved.[[Value]] to true.
     938          56 :   StoreContextElementNoWriteBarrier(
     939         168 :       context, PromiseBuiltins::kAlreadyResolvedSlot, TrueConstant());
     940             : 
     941             :   // The rest of the logic (and the catch prediction) is
     942             :   // encapsulated in the dedicated ResolvePromise builtin.
     943         112 :   Return(CallBuiltin(Builtins::kResolvePromise, context, promise, resolution));
     944             : 
     945          56 :   BIND(&if_already_resolved);
     946             :   {
     947          56 :     Return(CallRuntime(Runtime::kPromiseResolveAfterResolved, context, promise,
     948          56 :                        resolution));
     949             :   }
     950          56 : }
     951             : 
     952         224 : TF_BUILTIN(PromiseConstructorLazyDeoptContinuation, PromiseBuiltinsAssembler) {
     953             :   Node* promise = Parameter(Descriptor::kPromise);
     954             :   Node* reject = Parameter(Descriptor::kReject);
     955             :   Node* exception = Parameter(Descriptor::kException);
     956             :   Node* const context = Parameter(Descriptor::kContext);
     957             : 
     958          56 :   Label finally(this);
     959             : 
     960         112 :   GotoIf(IsTheHole(exception), &finally);
     961         112 :   CallJS(CodeFactory::Call(isolate(), ConvertReceiverMode::kNotNullOrUndefined),
     962         168 :          context, reject, UndefinedConstant(), exception);
     963          56 :   Goto(&finally);
     964             : 
     965          56 :   BIND(&finally);
     966          56 :   Return(promise);
     967          56 : }
     968             : 
     969             : // ES6 #sec-promise-executor
     970         224 : TF_BUILTIN(PromiseConstructor, PromiseBuiltinsAssembler) {
     971             :   Node* const executor = Parameter(Descriptor::kExecutor);
     972             :   Node* const new_target = Parameter(Descriptor::kJSNewTarget);
     973             :   Node* const context = Parameter(Descriptor::kContext);
     974          56 :   Isolate* isolate = this->isolate();
     975             : 
     976          56 :   Label if_targetisundefined(this, Label::kDeferred);
     977             : 
     978         112 :   GotoIf(IsUndefined(new_target), &if_targetisundefined);
     979             : 
     980          56 :   Label if_notcallable(this, Label::kDeferred);
     981             : 
     982         112 :   GotoIf(TaggedIsSmi(executor), &if_notcallable);
     983             : 
     984         112 :   Node* const executor_map = LoadMap(executor);
     985         112 :   GotoIfNot(IsCallableMap(executor_map), &if_notcallable);
     986             : 
     987         112 :   Node* const native_context = LoadNativeContext(context);
     988             :   Node* const promise_fun =
     989         112 :       LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX);
     990          56 :   Node* const is_debug_active = IsDebugActive();
     991          56 :   Label if_targetisnotmodified(this),
     992          56 :       if_targetismodified(this, Label::kDeferred), run_executor(this),
     993          56 :       debug_push(this), if_noaccess(this, Label::kDeferred);
     994             : 
     995          56 :   BranchIfAccessCheckFailed(context, native_context, promise_fun, executor,
     996          56 :                             &if_noaccess);
     997             : 
     998         112 :   Branch(WordEqual(promise_fun, new_target), &if_targetisnotmodified,
     999          56 :          &if_targetismodified);
    1000             : 
    1001         112 :   VARIABLE(var_result, MachineRepresentation::kTagged);
    1002         112 :   VARIABLE(var_reject_call, MachineRepresentation::kTagged);
    1003         112 :   VARIABLE(var_reason, MachineRepresentation::kTagged);
    1004             : 
    1005          56 :   BIND(&if_targetisnotmodified);
    1006             :   {
    1007          56 :     Node* const instance = AllocateAndInitJSPromise(context);
    1008          56 :     var_result.Bind(instance);
    1009          56 :     Goto(&debug_push);
    1010             :   }
    1011             : 
    1012          56 :   BIND(&if_targetismodified);
    1013             :   {
    1014             :     ConstructorBuiltinsAssembler constructor_assembler(this->state());
    1015             :     Node* const instance = constructor_assembler.EmitFastNewObject(
    1016          56 :         context, promise_fun, new_target);
    1017          56 :     PromiseInit(instance);
    1018          56 :     var_result.Bind(instance);
    1019             : 
    1020         112 :     GotoIfNot(IsPromiseHookEnabledOrHasAsyncEventDelegate(), &debug_push);
    1021             :     CallRuntime(Runtime::kPromiseHookInit, context, instance,
    1022          56 :                 UndefinedConstant());
    1023          56 :     Goto(&debug_push);
    1024             :   }
    1025             : 
    1026          56 :   BIND(&debug_push);
    1027             :   {
    1028          56 :     GotoIfNot(is_debug_active, &run_executor);
    1029          56 :     CallRuntime(Runtime::kDebugPushPromise, context, var_result.value());
    1030          56 :     Goto(&run_executor);
    1031             :   }
    1032             : 
    1033          56 :   BIND(&run_executor);
    1034             :   {
    1035          56 :     Label out(this), if_rejectpromise(this), debug_pop(this, Label::kDeferred);
    1036             : 
    1037             :     Node *resolve, *reject;
    1038         112 :     std::tie(resolve, reject) = CreatePromiseResolvingFunctions(
    1039         168 :         var_result.value(), TrueConstant(), native_context);
    1040             : 
    1041             :     Node* const maybe_exception = CallJS(
    1042         112 :         CodeFactory::Call(isolate, ConvertReceiverMode::kNullOrUndefined),
    1043         168 :         context, executor, UndefinedConstant(), resolve, reject);
    1044             : 
    1045          56 :     GotoIfException(maybe_exception, &if_rejectpromise, &var_reason);
    1046          56 :     Branch(is_debug_active, &debug_pop, &out);
    1047             : 
    1048          56 :     BIND(&if_rejectpromise);
    1049             :     {
    1050         168 :       CallJS(CodeFactory::Call(isolate, ConvertReceiverMode::kNullOrUndefined),
    1051         168 :              context, reject, UndefinedConstant(), var_reason.value());
    1052          56 :       Branch(is_debug_active, &debug_pop, &out);
    1053             :     }
    1054             : 
    1055          56 :     BIND(&debug_pop);
    1056             :     {
    1057             :       CallRuntime(Runtime::kDebugPopPromise, context);
    1058          56 :       Goto(&out);
    1059             :     }
    1060          56 :     BIND(&out);
    1061         112 :     Return(var_result.value());
    1062             :   }
    1063             : 
    1064             :   // 1. If NewTarget is undefined, throw a TypeError exception.
    1065          56 :   BIND(&if_targetisundefined);
    1066          56 :   ThrowTypeError(context, MessageTemplate::kNotAPromise, new_target);
    1067             : 
    1068             :   // 2. If IsCallable(executor) is false, throw a TypeError exception.
    1069          56 :   BIND(&if_notcallable);
    1070          56 :   ThrowTypeError(context, MessageTemplate::kResolverNotAFunction, executor);
    1071             : 
    1072             :   // Silently fail if the stack looks fishy.
    1073          56 :   BIND(&if_noaccess);
    1074             :   {
    1075             :     Node* const counter_id =
    1076             :         SmiConstant(v8::Isolate::kPromiseConstructorReturnedUndefined);
    1077             :     CallRuntime(Runtime::kIncrementUseCounter, context, counter_id);
    1078         112 :     Return(UndefinedConstant());
    1079             :   }
    1080          56 : }
    1081             : 
    1082             : // V8 Extras: v8.createPromise(parent)
    1083         224 : TF_BUILTIN(PromiseInternalConstructor, PromiseBuiltinsAssembler) {
    1084             :   Node* const parent = Parameter(Descriptor::kParent);
    1085             :   Node* const context = Parameter(Descriptor::kContext);
    1086         112 :   Return(AllocateAndInitJSPromise(context, parent));
    1087          56 : }
    1088             : 
    1089             : // V8 Extras: v8.rejectPromise(promise, reason)
    1090         224 : TF_BUILTIN(PromiseInternalReject, PromiseBuiltinsAssembler) {
    1091             :   Node* const promise = Parameter(Descriptor::kPromise);
    1092             :   Node* const reason = Parameter(Descriptor::kReason);
    1093             :   Node* const context = Parameter(Descriptor::kContext);
    1094             : 
    1095             :   // Main V8 Extras invariant that {promise} is still "pending" at
    1096             :   // this point, aka that {promise} is not resolved multiple times.
    1097          56 :   Label if_promise_is_settled(this, Label::kDeferred);
    1098         112 :   GotoIfNot(IsPromiseStatus(PromiseStatus(promise), v8::Promise::kPending),
    1099          56 :             &if_promise_is_settled);
    1100             : 
    1101             :   // We pass true to trigger the debugger's on exception handler.
    1102         112 :   Return(CallBuiltin(Builtins::kRejectPromise, context, promise, reason,
    1103         168 :                      TrueConstant()));
    1104             : 
    1105          56 :   BIND(&if_promise_is_settled);
    1106          56 :   Abort(AbortReason::kPromiseAlreadySettled);
    1107          56 : }
    1108             : 
    1109             : // V8 Extras: v8.resolvePromise(promise, resolution)
    1110         224 : TF_BUILTIN(PromiseInternalResolve, PromiseBuiltinsAssembler) {
    1111             :   Node* const promise = Parameter(Descriptor::kPromise);
    1112             :   Node* const resolution = Parameter(Descriptor::kResolution);
    1113             :   Node* const context = Parameter(Descriptor::kContext);
    1114             : 
    1115             :   // Main V8 Extras invariant that {promise} is still "pending" at
    1116             :   // this point, aka that {promise} is not resolved multiple times.
    1117          56 :   Label if_promise_is_settled(this, Label::kDeferred);
    1118         112 :   GotoIfNot(IsPromiseStatus(PromiseStatus(promise), v8::Promise::kPending),
    1119          56 :             &if_promise_is_settled);
    1120             : 
    1121         112 :   Return(CallBuiltin(Builtins::kResolvePromise, context, promise, resolution));
    1122             : 
    1123          56 :   BIND(&if_promise_is_settled);
    1124          56 :   Abort(AbortReason::kPromiseAlreadySettled);
    1125          56 : }
    1126             : 
    1127             : // ES#sec-promise.prototype.then
    1128             : // Promise.prototype.then ( onFulfilled, onRejected )
    1129         224 : TF_BUILTIN(PromisePrototypeThen, PromiseBuiltinsAssembler) {
    1130             :   // 1. Let promise be the this value.
    1131             :   Node* const promise = Parameter(Descriptor::kReceiver);
    1132             :   Node* const on_fulfilled = Parameter(Descriptor::kOnFulfilled);
    1133             :   Node* const on_rejected = Parameter(Descriptor::kOnRejected);
    1134             :   Node* const context = Parameter(Descriptor::kContext);
    1135             : 
    1136             :   // 2. If IsPromise(promise) is false, throw a TypeError exception.
    1137          56 :   ThrowIfNotInstanceType(context, promise, JS_PROMISE_TYPE,
    1138          56 :                          "Promise.prototype.then");
    1139             : 
    1140             :   // 3. Let C be ? SpeciesConstructor(promise, %Promise%).
    1141          56 :   Label fast_promise_capability(this), slow_constructor(this, Label::kDeferred),
    1142          56 :       slow_promise_capability(this, Label::kDeferred);
    1143         112 :   Node* const native_context = LoadNativeContext(context);
    1144             :   Node* const promise_fun =
    1145         112 :       LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX);
    1146         112 :   Node* const promise_map = LoadMap(promise);
    1147          56 :   BranchIfPromiseSpeciesLookupChainIntact(
    1148          56 :       native_context, promise_map, &fast_promise_capability, &slow_constructor);
    1149             : 
    1150          56 :   BIND(&slow_constructor);
    1151             :   Node* const constructor =
    1152         112 :       SpeciesConstructor(native_context, promise, promise_fun);
    1153         112 :   Branch(WordEqual(constructor, promise_fun), &fast_promise_capability,
    1154          56 :          &slow_promise_capability);
    1155             : 
    1156             :   // 4. Let resultCapability be ? NewPromiseCapability(C).
    1157          56 :   Label perform_promise_then(this);
    1158         112 :   VARIABLE(var_result_promise, MachineRepresentation::kTagged);
    1159         112 :   VARIABLE(var_result_promise_or_capability, MachineRepresentation::kTagged);
    1160             : 
    1161          56 :   BIND(&fast_promise_capability);
    1162             :   {
    1163          56 :     Node* const result_promise = AllocateAndInitJSPromise(context, promise);
    1164          56 :     var_result_promise_or_capability.Bind(result_promise);
    1165          56 :     var_result_promise.Bind(result_promise);
    1166          56 :     Goto(&perform_promise_then);
    1167             :   }
    1168             : 
    1169          56 :   BIND(&slow_promise_capability);
    1170             :   {
    1171         112 :     Node* const debug_event = TrueConstant();
    1172         112 :     Node* const capability = CallBuiltin(Builtins::kNewPromiseCapability,
    1173          56 :                                          context, constructor, debug_event);
    1174             :     var_result_promise.Bind(
    1175          56 :         LoadObjectField(capability, PromiseCapability::kPromiseOffset));
    1176          56 :     var_result_promise_or_capability.Bind(capability);
    1177          56 :     Goto(&perform_promise_then);
    1178             :   }
    1179             : 
    1180             :   // 5. Return PerformPromiseThen(promise, onFulfilled, onRejected,
    1181             :   //    resultCapability).
    1182          56 :   BIND(&perform_promise_then);
    1183             :   {
    1184             :     // We do some work of the PerformPromiseThen operation here, in that
    1185             :     // we check the handlers and turn non-callable handlers into undefined.
    1186             :     // This is because this is the one and only callsite of PerformPromiseThen
    1187             :     // that has to do this.
    1188             : 
    1189             :     // 3. If IsCallable(onFulfilled) is false, then
    1190             :     //    a. Set onFulfilled to undefined.
    1191         112 :     VARIABLE(var_on_fulfilled, MachineRepresentation::kTagged, on_fulfilled);
    1192          56 :     Label if_fulfilled_done(this), if_fulfilled_notcallable(this);
    1193         112 :     GotoIf(TaggedIsSmi(on_fulfilled), &if_fulfilled_notcallable);
    1194         112 :     Branch(IsCallable(on_fulfilled), &if_fulfilled_done,
    1195          56 :            &if_fulfilled_notcallable);
    1196          56 :     BIND(&if_fulfilled_notcallable);
    1197         112 :     var_on_fulfilled.Bind(UndefinedConstant());
    1198          56 :     Goto(&if_fulfilled_done);
    1199          56 :     BIND(&if_fulfilled_done);
    1200             : 
    1201             :     // 4. If IsCallable(onRejected) is false, then
    1202             :     //    a. Set onRejected to undefined.
    1203         112 :     VARIABLE(var_on_rejected, MachineRepresentation::kTagged, on_rejected);
    1204          56 :     Label if_rejected_done(this), if_rejected_notcallable(this);
    1205         112 :     GotoIf(TaggedIsSmi(on_rejected), &if_rejected_notcallable);
    1206         112 :     Branch(IsCallable(on_rejected), &if_rejected_done,
    1207          56 :            &if_rejected_notcallable);
    1208          56 :     BIND(&if_rejected_notcallable);
    1209         112 :     var_on_rejected.Bind(UndefinedConstant());
    1210          56 :     Goto(&if_rejected_done);
    1211          56 :     BIND(&if_rejected_done);
    1212             : 
    1213          56 :     PerformPromiseThen(context, promise, var_on_fulfilled.value(),
    1214             :                        var_on_rejected.value(),
    1215          56 :                        var_result_promise_or_capability.value());
    1216         112 :     Return(var_result_promise.value());
    1217             :   }
    1218          56 : }
    1219             : 
    1220             : // ES#sec-promise.prototype.catch
    1221             : // Promise.prototype.catch ( onRejected )
    1222         280 : TF_BUILTIN(PromisePrototypeCatch, PromiseBuiltinsAssembler) {
    1223             :   // 1. Let promise be the this value.
    1224             :   Node* const receiver = Parameter(Descriptor::kReceiver);
    1225         112 :   Node* const on_fulfilled = UndefinedConstant();
    1226             :   Node* const on_rejected = Parameter(Descriptor::kOnRejected);
    1227             :   Node* const context = Parameter(Descriptor::kContext);
    1228             : 
    1229             :   // 2. Return ? Invoke(promise, "then", « undefined, onRejected »).
    1230         112 :   Node* const native_context = LoadNativeContext(context);
    1231         112 :   Return(InvokeThen(native_context, receiver, on_fulfilled, on_rejected));
    1232          56 : }
    1233             : 
    1234             : // ES #sec-promiseresolvethenablejob
    1235         224 : TF_BUILTIN(PromiseResolveThenableJob, PromiseBuiltinsAssembler) {
    1236             :   Node* const native_context = Parameter(Descriptor::kContext);
    1237             :   Node* const promise_to_resolve = Parameter(Descriptor::kPromiseToResolve);
    1238             :   Node* const thenable = Parameter(Descriptor::kThenable);
    1239             :   Node* const then = Parameter(Descriptor::kThen);
    1240             : 
    1241             :   CSA_ASSERT(this, TaggedIsNotSmi(thenable));
    1242             :   CSA_ASSERT(this, IsJSReceiver(thenable));
    1243             :   CSA_ASSERT(this, IsJSPromise(promise_to_resolve));
    1244             :   CSA_ASSERT(this, IsNativeContext(native_context));
    1245             : 
    1246             :   // We can use a simple optimization here if we know that {then} is the initial
    1247             :   // Promise.prototype.then method, and {thenable} is a JSPromise whose
    1248             :   // @@species lookup chain is intact: We can connect {thenable} and
    1249             :   // {promise_to_resolve} directly in that case and avoid the allocation of a
    1250             :   // temporary JSPromise and the closures plus context.
    1251             :   //
    1252             :   // We take the generic (slow-)path if a PromiseHook is enabled or the debugger
    1253             :   // is active, to make sure we expose spec compliant behavior.
    1254          56 :   Label if_fast(this), if_slow(this, Label::kDeferred);
    1255             :   Node* const promise_then =
    1256         112 :       LoadContextElement(native_context, Context::PROMISE_THEN_INDEX);
    1257         112 :   GotoIfNot(WordEqual(then, promise_then), &if_slow);
    1258         112 :   Node* const thenable_map = LoadMap(thenable);
    1259         112 :   GotoIfNot(IsJSPromiseMap(thenable_map), &if_slow);
    1260         112 :   GotoIf(IsPromiseHookEnabledOrDebugIsActiveOrHasAsyncEventDelegate(),
    1261          56 :          &if_slow);
    1262          56 :   BranchIfPromiseSpeciesLookupChainIntact(native_context, thenable_map,
    1263          56 :                                           &if_fast, &if_slow);
    1264             : 
    1265          56 :   BIND(&if_fast);
    1266             :   {
    1267             :     // We know that the {thenable} is a JSPromise, which doesn't require
    1268             :     // any special treatment and that {then} corresponds to the initial
    1269             :     // Promise.prototype.then method. So instead of allocating a temporary
    1270             :     // JSPromise to connect the {thenable} with the {promise_to_resolve},
    1271             :     // we can directly schedule the {promise_to_resolve} with default
    1272             :     // handlers onto the {thenable} promise. This does not only save the
    1273             :     // JSPromise allocation, but also avoids the allocation of the two
    1274             :     // resolving closures and the shared context.
    1275             :     //
    1276             :     // What happens normally in this case is
    1277             :     //
    1278             :     //   resolve, reject = CreateResolvingFunctions(promise_to_resolve)
    1279             :     //   result_capability = NewPromiseCapability(%Promise%)
    1280             :     //   PerformPromiseThen(thenable, resolve, reject, result_capability)
    1281             :     //
    1282             :     // which means that PerformPromiseThen will either schedule a new
    1283             :     // PromiseReaction with resolve and reject or a PromiseReactionJob
    1284             :     // with resolve or reject based on the state of {thenable}. And
    1285             :     // resolve or reject will just invoke the default [[Resolve]] or
    1286             :     // [[Reject]] functions on the {promise_to_resolve}.
    1287             :     //
    1288             :     // This is the same as just doing
    1289             :     //
    1290             :     //   PerformPromiseThen(thenable, undefined, undefined, promise_to_resolve)
    1291             :     //
    1292             :     // which performs exactly the same (observable) steps.
    1293         112 :     TailCallBuiltin(Builtins::kPerformPromiseThen, native_context, thenable,
    1294             :                     UndefinedConstant(), UndefinedConstant(),
    1295          56 :                     promise_to_resolve);
    1296             :   }
    1297             : 
    1298          56 :   BIND(&if_slow);
    1299             :   {
    1300          56 :     Node* resolve = nullptr;
    1301          56 :     Node* reject = nullptr;
    1302         112 :     std::tie(resolve, reject) = CreatePromiseResolvingFunctions(
    1303         112 :         promise_to_resolve, FalseConstant(), native_context);
    1304             : 
    1305          56 :     Label if_exception(this, Label::kDeferred);
    1306         168 :     VARIABLE(var_exception, MachineRepresentation::kTagged, TheHoleConstant());
    1307             :     Node* const result = CallJS(
    1308         112 :         CodeFactory::Call(isolate(), ConvertReceiverMode::kNotNullOrUndefined),
    1309          56 :         native_context, then, thenable, resolve, reject);
    1310          56 :     GotoIfException(result, &if_exception, &var_exception);
    1311          56 :     Return(result);
    1312             : 
    1313          56 :     BIND(&if_exception);
    1314             :     {
    1315             :       // We need to reject the {thenable}.
    1316          56 :       Node* const result = CallJS(
    1317         112 :           CodeFactory::Call(isolate(), ConvertReceiverMode::kNullOrUndefined),
    1318         168 :           native_context, reject, UndefinedConstant(), var_exception.value());
    1319          56 :       Return(result);
    1320             :     }
    1321             :   }
    1322          56 : }
    1323             : 
    1324             : // ES #sec-promisereactionjob
    1325         112 : void PromiseBuiltinsAssembler::PromiseReactionJob(Node* context, Node* argument,
    1326             :                                                   Node* handler,
    1327             :                                                   Node* promise_or_capability,
    1328             :                                                   PromiseReaction::Type type) {
    1329             :   CSA_ASSERT(this, TaggedIsNotSmi(handler));
    1330             :   CSA_ASSERT(this, Word32Or(IsUndefined(handler), IsCallable(handler)));
    1331             :   CSA_ASSERT(this, TaggedIsNotSmi(promise_or_capability));
    1332             :   CSA_ASSERT(this,
    1333             :              Word32Or(Word32Or(IsJSPromise(promise_or_capability),
    1334             :                                IsPromiseCapability(promise_or_capability)),
    1335             :                       IsUndefined(promise_or_capability)));
    1336             : 
    1337         224 :   VARIABLE(var_handler_result, MachineRepresentation::kTagged, argument);
    1338         112 :   Label if_handler_callable(this), if_fulfill(this), if_reject(this),
    1339         112 :       if_internal(this);
    1340         336 :   Branch(IsUndefined(handler),
    1341             :          type == PromiseReaction::kFulfill ? &if_fulfill : &if_reject,
    1342         112 :          &if_handler_callable);
    1343             : 
    1344         112 :   BIND(&if_handler_callable);
    1345             :   {
    1346             :     Node* const result = CallJS(
    1347         224 :         CodeFactory::Call(isolate(), ConvertReceiverMode::kNullOrUndefined),
    1348         336 :         context, handler, UndefinedConstant(), argument);
    1349         112 :     GotoIfException(result, &if_reject, &var_handler_result);
    1350         112 :     var_handler_result.Bind(result);
    1351         224 :     Branch(IsUndefined(promise_or_capability), &if_internal, &if_fulfill);
    1352             :   }
    1353             : 
    1354         112 :   BIND(&if_internal);
    1355             :   {
    1356             :     // There's no [[Capability]] for this promise reaction job, which
    1357             :     // means that this is a specification-internal operation (aka await)
    1358             :     // where the result does not matter (see the specification change in
    1359             :     // https://github.com/tc39/ecma262/pull/1146 for details).
    1360         224 :     Return(UndefinedConstant());
    1361             :   }
    1362             : 
    1363         112 :   BIND(&if_fulfill);
    1364             :   {
    1365         112 :     Label if_promise(this), if_promise_capability(this, Label::kDeferred);
    1366         112 :     Node* const value = var_handler_result.value();
    1367         224 :     Branch(IsPromiseCapability(promise_or_capability), &if_promise_capability,
    1368         112 :            &if_promise);
    1369             : 
    1370         112 :     BIND(&if_promise);
    1371             :     {
    1372             :       // For fast native promises we can skip the indirection
    1373             :       // via the promiseCapability.[[Resolve]] function and
    1374             :       // run the resolve logic directly from here.
    1375         112 :       TailCallBuiltin(Builtins::kResolvePromise, context, promise_or_capability,
    1376         112 :                       value);
    1377             :     }
    1378             : 
    1379         112 :     BIND(&if_promise_capability);
    1380             :     {
    1381             :       // In the general case we need to call the (user provided)
    1382             :       // promiseCapability.[[Resolve]] function.
    1383             :       Node* const resolve = LoadObjectField(promise_or_capability,
    1384             :                                             PromiseCapability::kResolveOffset);
    1385             :       Node* const result = CallJS(
    1386         224 :           CodeFactory::Call(isolate(), ConvertReceiverMode::kNullOrUndefined),
    1387         336 :           context, resolve, UndefinedConstant(), value);
    1388         112 :       GotoIfException(result, &if_reject, &var_handler_result);
    1389         112 :       Return(result);
    1390             :     }
    1391             :   }
    1392             : 
    1393         112 :   BIND(&if_reject);
    1394         112 :   if (type == PromiseReaction::kReject) {
    1395          56 :     Label if_promise(this), if_promise_capability(this, Label::kDeferred);
    1396          56 :     Node* const reason = var_handler_result.value();
    1397         112 :     Branch(IsPromiseCapability(promise_or_capability), &if_promise_capability,
    1398          56 :            &if_promise);
    1399             : 
    1400          56 :     BIND(&if_promise);
    1401             :     {
    1402             :       // For fast native promises we can skip the indirection
    1403             :       // via the promiseCapability.[[Reject]] function and
    1404             :       // run the resolve logic directly from here.
    1405         112 :       TailCallBuiltin(Builtins::kRejectPromise, context, promise_or_capability,
    1406          56 :                       reason, FalseConstant());
    1407             :     }
    1408             : 
    1409          56 :     BIND(&if_promise_capability);
    1410             :     {
    1411             :       // In the general case we need to call the (user provided)
    1412             :       // promiseCapability.[[Reject]] function.
    1413          56 :       Label if_exception(this, Label::kDeferred);
    1414         168 :       VARIABLE(var_exception, MachineRepresentation::kTagged,
    1415             :                TheHoleConstant());
    1416             :       Node* const reject = LoadObjectField(promise_or_capability,
    1417             :                                            PromiseCapability::kRejectOffset);
    1418             :       Node* const result = CallJS(
    1419         112 :           CodeFactory::Call(isolate(), ConvertReceiverMode::kNullOrUndefined),
    1420         168 :           context, reject, UndefinedConstant(), reason);
    1421          56 :       GotoIfException(result, &if_exception, &var_exception);
    1422          56 :       Return(result);
    1423             : 
    1424             :       // Swallow the exception here.
    1425          56 :       BIND(&if_exception);
    1426         112 :       TailCallRuntime(Runtime::kReportMessage, context, var_exception.value());
    1427             :     }
    1428             :   } else {
    1429             :     // We have to call out to the dedicated PromiseRejectReactionJob builtin
    1430             :     // here, instead of just doing the work inline, as otherwise the catch
    1431             :     // predictions in the debugger will be wrong, which just walks the stack
    1432             :     // and checks for certain builtins.
    1433         112 :     TailCallBuiltin(Builtins::kPromiseRejectReactionJob, context,
    1434             :                     var_handler_result.value(), UndefinedConstant(),
    1435          56 :                     promise_or_capability);
    1436             :   }
    1437         112 : }
    1438             : 
    1439             : // ES #sec-promisereactionjob
    1440         224 : TF_BUILTIN(PromiseFulfillReactionJob, PromiseBuiltinsAssembler) {
    1441             :   Node* const context = Parameter(Descriptor::kContext);
    1442             :   Node* const value = Parameter(Descriptor::kValue);
    1443             :   Node* const handler = Parameter(Descriptor::kHandler);
    1444             :   Node* const promise_or_capability =
    1445             :       Parameter(Descriptor::kPromiseOrCapability);
    1446             : 
    1447          56 :   PromiseReactionJob(context, value, handler, promise_or_capability,
    1448          56 :                      PromiseReaction::kFulfill);
    1449          56 : }
    1450             : 
    1451             : // ES #sec-promisereactionjob
    1452         224 : TF_BUILTIN(PromiseRejectReactionJob, PromiseBuiltinsAssembler) {
    1453             :   Node* const context = Parameter(Descriptor::kContext);
    1454             :   Node* const reason = Parameter(Descriptor::kReason);
    1455             :   Node* const handler = Parameter(Descriptor::kHandler);
    1456             :   Node* const promise_or_capability =
    1457             :       Parameter(Descriptor::kPromiseOrCapability);
    1458             : 
    1459          56 :   PromiseReactionJob(context, reason, handler, promise_or_capability,
    1460          56 :                      PromiseReaction::kReject);
    1461          56 : }
    1462             : 
    1463         224 : TF_BUILTIN(PromiseResolveTrampoline, PromiseBuiltinsAssembler) {
    1464             :   //  1. Let C be the this value.
    1465             :   Node* receiver = Parameter(Descriptor::kReceiver);
    1466             :   Node* value = Parameter(Descriptor::kValue);
    1467             :   Node* context = Parameter(Descriptor::kContext);
    1468             : 
    1469             :   // 2. If Type(C) is not Object, throw a TypeError exception.
    1470          56 :   ThrowIfNotJSReceiver(context, receiver, MessageTemplate::kCalledOnNonObject,
    1471          56 :                        "PromiseResolve");
    1472             : 
    1473             :   // 3. Return ? PromiseResolve(C, x).
    1474         112 :   Return(CallBuiltin(Builtins::kPromiseResolve, context, receiver, value));
    1475          56 : }
    1476             : 
    1477         224 : TF_BUILTIN(PromiseResolve, PromiseBuiltinsAssembler) {
    1478             :   Node* constructor = Parameter(Descriptor::kConstructor);
    1479             :   Node* value = Parameter(Descriptor::kValue);
    1480             :   Node* context = Parameter(Descriptor::kContext);
    1481             : 
    1482             :   CSA_ASSERT(this, IsJSReceiver(constructor));
    1483             : 
    1484         112 :   Node* const native_context = LoadNativeContext(context);
    1485             :   Node* const promise_fun =
    1486         112 :       LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX);
    1487             : 
    1488          56 :   Label if_slow_constructor(this, Label::kDeferred), if_need_to_allocate(this);
    1489             : 
    1490             :   // Check if {value} is a JSPromise.
    1491         112 :   GotoIf(TaggedIsSmi(value), &if_need_to_allocate);
    1492         112 :   Node* const value_map = LoadMap(value);
    1493         112 :   GotoIfNot(IsJSPromiseMap(value_map), &if_need_to_allocate);
    1494             : 
    1495             :   // We can skip the "constructor" lookup on {value} if it's [[Prototype]]
    1496             :   // is the (initial) Promise.prototype and the @@species protector is
    1497             :   // intact, as that guards the lookup path for "constructor" on
    1498             :   // JSPromise instances which have the (initial) Promise.prototype.
    1499             :   Node* const promise_prototype =
    1500         112 :       LoadContextElement(native_context, Context::PROMISE_PROTOTYPE_INDEX);
    1501         112 :   GotoIfNot(WordEqual(LoadMapPrototype(value_map), promise_prototype),
    1502          56 :             &if_slow_constructor);
    1503         112 :   GotoIf(IsPromiseSpeciesProtectorCellInvalid(), &if_slow_constructor);
    1504             : 
    1505             :   // If the {constructor} is the Promise function, we just immediately
    1506             :   // return the {value} here and don't bother wrapping it into a
    1507             :   // native Promise.
    1508         112 :   GotoIfNot(WordEqual(promise_fun, constructor), &if_slow_constructor);
    1509          56 :   Return(value);
    1510             : 
    1511             :   // At this point, value or/and constructor are not native promises, but
    1512             :   // they could be of the same subclass.
    1513          56 :   BIND(&if_slow_constructor);
    1514             :   {
    1515             :     Node* const value_constructor =
    1516         168 :         GetProperty(context, value, isolate()->factory()->constructor_string());
    1517         112 :     GotoIfNot(WordEqual(value_constructor, constructor), &if_need_to_allocate);
    1518          56 :     Return(value);
    1519             :   }
    1520             : 
    1521          56 :   BIND(&if_need_to_allocate);
    1522             :   {
    1523          56 :     Label if_nativepromise(this), if_notnativepromise(this, Label::kDeferred);
    1524         112 :     Branch(WordEqual(promise_fun, constructor), &if_nativepromise,
    1525          56 :            &if_notnativepromise);
    1526             : 
    1527             :     // This adds a fast path for native promises that don't need to
    1528             :     // create NewPromiseCapability.
    1529          56 :     BIND(&if_nativepromise);
    1530             :     {
    1531          56 :       Node* const result = AllocateAndInitJSPromise(context);
    1532          56 :       CallBuiltin(Builtins::kResolvePromise, context, result, value);
    1533          56 :       Return(result);
    1534             :     }
    1535             : 
    1536          56 :     BIND(&if_notnativepromise);
    1537             :     {
    1538         112 :       Node* const debug_event = TrueConstant();
    1539         112 :       Node* const capability = CallBuiltin(Builtins::kNewPromiseCapability,
    1540          56 :                                            context, constructor, debug_event);
    1541             : 
    1542             :       Node* const resolve =
    1543             :           LoadObjectField(capability, PromiseCapability::kResolveOffset);
    1544             :       CallJS(
    1545         112 :           CodeFactory::Call(isolate(), ConvertReceiverMode::kNullOrUndefined),
    1546         168 :           context, resolve, UndefinedConstant(), value);
    1547             : 
    1548             :       Node* const result =
    1549             :           LoadObjectField(capability, PromiseCapability::kPromiseOffset);
    1550          56 :       Return(result);
    1551             :     }
    1552             :   }
    1553          56 : }
    1554             : 
    1555             : // ES6 #sec-getcapabilitiesexecutor-functions
    1556         224 : TF_BUILTIN(PromiseGetCapabilitiesExecutor, PromiseBuiltinsAssembler) {
    1557             :   Node* const resolve = Parameter(Descriptor::kResolve);
    1558             :   Node* const reject = Parameter(Descriptor::kReject);
    1559             :   Node* const context = Parameter(Descriptor::kContext);
    1560             : 
    1561             :   Node* const capability =
    1562         112 :       LoadContextElement(context, PromiseBuiltins::kCapabilitySlot);
    1563             : 
    1564          56 :   Label if_alreadyinvoked(this, Label::kDeferred);
    1565         112 :   GotoIfNot(IsUndefined(
    1566          56 :                 LoadObjectField(capability, PromiseCapability::kResolveOffset)),
    1567          56 :             &if_alreadyinvoked);
    1568         112 :   GotoIfNot(IsUndefined(
    1569          56 :                 LoadObjectField(capability, PromiseCapability::kRejectOffset)),
    1570          56 :             &if_alreadyinvoked);
    1571             : 
    1572          56 :   StoreObjectField(capability, PromiseCapability::kResolveOffset, resolve);
    1573          56 :   StoreObjectField(capability, PromiseCapability::kRejectOffset, reject);
    1574             : 
    1575         112 :   Return(UndefinedConstant());
    1576             : 
    1577          56 :   BIND(&if_alreadyinvoked);
    1578          56 :   ThrowTypeError(context, MessageTemplate::kPromiseExecutorAlreadyInvoked);
    1579          56 : }
    1580             : 
    1581         224 : TF_BUILTIN(PromiseReject, PromiseBuiltinsAssembler) {
    1582             :   // 1. Let C be the this value.
    1583             :   Node* const receiver = Parameter(Descriptor::kReceiver);
    1584             :   Node* const reason = Parameter(Descriptor::kReason);
    1585             :   Node* const context = Parameter(Descriptor::kContext);
    1586             : 
    1587             :   // 2. If Type(C) is not Object, throw a TypeError exception.
    1588          56 :   ThrowIfNotJSReceiver(context, receiver, MessageTemplate::kCalledOnNonObject,
    1589          56 :                        "PromiseReject");
    1590             : 
    1591          56 :   Label if_nativepromise(this), if_custompromise(this, Label::kDeferred);
    1592         112 :   Node* const native_context = LoadNativeContext(context);
    1593             : 
    1594             :   Node* const promise_fun =
    1595         112 :       LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX);
    1596         112 :   Branch(WordEqual(promise_fun, receiver), &if_nativepromise,
    1597          56 :          &if_custompromise);
    1598             : 
    1599          56 :   BIND(&if_nativepromise);
    1600             :   {
    1601             :     Node* const promise =
    1602          56 :         AllocateAndSetJSPromise(context, v8::Promise::kRejected, reason);
    1603             :     CallRuntime(Runtime::kPromiseRejectEventFromStack, context, promise,
    1604             :                 reason);
    1605          56 :     Return(promise);
    1606             :   }
    1607             : 
    1608          56 :   BIND(&if_custompromise);
    1609             :   {
    1610             :     // 3. Let promiseCapability be ? NewPromiseCapability(C).
    1611         112 :     Node* const debug_event = TrueConstant();
    1612         112 :     Node* const capability = CallBuiltin(Builtins::kNewPromiseCapability,
    1613          56 :                                          context, receiver, debug_event);
    1614             : 
    1615             :     // 4. Perform ? Call(promiseCapability.[[Reject]], undefined, « r »).
    1616             :     Node* const reject =
    1617             :         LoadObjectField(capability, PromiseCapability::kRejectOffset);
    1618         112 :     CallJS(CodeFactory::Call(isolate(), ConvertReceiverMode::kNullOrUndefined),
    1619         168 :            context, reject, UndefinedConstant(), reason);
    1620             : 
    1621             :     // 5. Return promiseCapability.[[Promise]].
    1622             :     Node* const promise =
    1623             :         LoadObjectField(capability, PromiseCapability::kPromiseOffset);
    1624          56 :     Return(promise);
    1625             :   }
    1626          56 : }
    1627             : 
    1628          56 : std::pair<Node*, Node*> PromiseBuiltinsAssembler::CreatePromiseFinallyFunctions(
    1629             :     Node* on_finally, Node* constructor, Node* native_context) {
    1630             :   Node* const promise_context = CreatePromiseContext(
    1631          56 :       native_context, PromiseBuiltins::kPromiseFinallyContextLength);
    1632         112 :   StoreContextElementNoWriteBarrier(
    1633          56 :       promise_context, PromiseBuiltins::kOnFinallySlot, on_finally);
    1634          56 :   StoreContextElementNoWriteBarrier(
    1635          56 :       promise_context, PromiseBuiltins::kConstructorSlot, constructor);
    1636         112 :   Node* const map = LoadContextElement(
    1637          56 :       native_context, Context::STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX);
    1638         112 :   Node* const then_finally_info = LoadContextElement(
    1639          56 :       native_context, Context::PROMISE_THEN_FINALLY_SHARED_FUN);
    1640          56 :   Node* const then_finally = AllocateFunctionWithMapAndContext(
    1641             :       map, then_finally_info, promise_context);
    1642         112 :   Node* const catch_finally_info = LoadContextElement(
    1643          56 :       native_context, Context::PROMISE_CATCH_FINALLY_SHARED_FUN);
    1644          56 :   Node* const catch_finally = AllocateFunctionWithMapAndContext(
    1645             :       map, catch_finally_info, promise_context);
    1646          56 :   return std::make_pair(then_finally, catch_finally);
    1647             : }
    1648             : 
    1649         224 : TF_BUILTIN(PromiseValueThunkFinally, PromiseBuiltinsAssembler) {
    1650             :   Node* const context = Parameter(Descriptor::kContext);
    1651             : 
    1652         112 :   Node* const value = LoadContextElement(context, PromiseBuiltins::kValueSlot);
    1653          56 :   Return(value);
    1654          56 : }
    1655             : 
    1656          56 : Node* PromiseBuiltinsAssembler::CreateValueThunkFunction(Node* value,
    1657             :                                                          Node* native_context) {
    1658             :   Node* const value_thunk_context = CreatePromiseContext(
    1659          56 :       native_context, PromiseBuiltins::kPromiseValueThunkOrReasonContextLength);
    1660         112 :   StoreContextElementNoWriteBarrier(value_thunk_context,
    1661          56 :                                     PromiseBuiltins::kValueSlot, value);
    1662         112 :   Node* const map = LoadContextElement(
    1663          56 :       native_context, Context::STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX);
    1664         112 :   Node* const value_thunk_info = LoadContextElement(
    1665          56 :       native_context, Context::PROMISE_VALUE_THUNK_FINALLY_SHARED_FUN);
    1666             :   Node* const value_thunk = AllocateFunctionWithMapAndContext(
    1667          56 :       map, value_thunk_info, value_thunk_context);
    1668          56 :   return value_thunk;
    1669             : }
    1670             : 
    1671         224 : TF_BUILTIN(PromiseThenFinally, PromiseBuiltinsAssembler) {
    1672             :   CSA_ASSERT_JS_ARGC_EQ(this, 1);
    1673             : 
    1674             :   Node* const value = Parameter(Descriptor::kValue);
    1675             :   Node* const context = Parameter(Descriptor::kContext);
    1676             : 
    1677             :   // 1. Let onFinally be F.[[OnFinally]].
    1678             :   Node* const on_finally =
    1679         112 :       LoadContextElement(context, PromiseBuiltins::kOnFinallySlot);
    1680             : 
    1681             :   // 2.  Assert: IsCallable(onFinally) is true.
    1682             :   CSA_ASSERT(this, IsCallable(on_finally));
    1683             : 
    1684             :   // 3. Let result be ?  Call(onFinally).
    1685             :   Node* const result = CallJS(
    1686         112 :       CodeFactory::Call(isolate(), ConvertReceiverMode::kNullOrUndefined),
    1687         168 :       context, on_finally, UndefinedConstant());
    1688             : 
    1689             :   // 4. Let C be F.[[Constructor]].
    1690             :   Node* const constructor =
    1691         112 :       LoadContextElement(context, PromiseBuiltins::kConstructorSlot);
    1692             : 
    1693             :   // 5. Assert: IsConstructor(C) is true.
    1694             :   CSA_ASSERT(this, IsConstructor(constructor));
    1695             : 
    1696             :   // 6. Let promise be ? PromiseResolve(C, result).
    1697             :   Node* const promise =
    1698         112 :     CallBuiltin(Builtins::kPromiseResolve, context, constructor, result);
    1699             : 
    1700             :   // 7. Let valueThunk be equivalent to a function that returns value.
    1701         112 :   Node* const native_context = LoadNativeContext(context);
    1702          56 :   Node* const value_thunk = CreateValueThunkFunction(value, native_context);
    1703             : 
    1704             :   // 8. Return ? Invoke(promise, "then", « valueThunk »).
    1705         112 :   Return(InvokeThen(native_context, promise, value_thunk));
    1706          56 : }
    1707             : 
    1708         224 : TF_BUILTIN(PromiseThrowerFinally, PromiseBuiltinsAssembler) {
    1709             :   Node* const context = Parameter(Descriptor::kContext);
    1710             : 
    1711         112 :   Node* const reason = LoadContextElement(context, PromiseBuiltins::kValueSlot);
    1712             :   CallRuntime(Runtime::kThrow, context, reason);
    1713          56 :   Unreachable();
    1714          56 : }
    1715             : 
    1716          56 : Node* PromiseBuiltinsAssembler::CreateThrowerFunction(Node* reason,
    1717             :                                                       Node* native_context) {
    1718             :   Node* const thrower_context = CreatePromiseContext(
    1719          56 :       native_context, PromiseBuiltins::kPromiseValueThunkOrReasonContextLength);
    1720         112 :   StoreContextElementNoWriteBarrier(thrower_context,
    1721          56 :                                     PromiseBuiltins::kValueSlot, reason);
    1722         112 :   Node* const map = LoadContextElement(
    1723          56 :       native_context, Context::STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX);
    1724         112 :   Node* const thrower_info = LoadContextElement(
    1725          56 :       native_context, Context::PROMISE_THROWER_FINALLY_SHARED_FUN);
    1726             :   Node* const thrower =
    1727          56 :       AllocateFunctionWithMapAndContext(map, thrower_info, thrower_context);
    1728          56 :   return thrower;
    1729             : }
    1730             : 
    1731         224 : TF_BUILTIN(PromiseCatchFinally, PromiseBuiltinsAssembler) {
    1732             :   CSA_ASSERT_JS_ARGC_EQ(this, 1);
    1733             : 
    1734             :   Node* const reason = Parameter(Descriptor::kReason);
    1735             :   Node* const context = Parameter(Descriptor::kContext);
    1736             : 
    1737             :   // 1. Let onFinally be F.[[OnFinally]].
    1738             :   Node* const on_finally =
    1739         112 :       LoadContextElement(context, PromiseBuiltins::kOnFinallySlot);
    1740             : 
    1741             :   // 2. Assert: IsCallable(onFinally) is true.
    1742             :   CSA_ASSERT(this, IsCallable(on_finally));
    1743             : 
    1744             :   // 3. Let result be ? Call(onFinally).
    1745             :   Node* result = CallJS(
    1746         112 :       CodeFactory::Call(isolate(), ConvertReceiverMode::kNullOrUndefined),
    1747         168 :       context, on_finally, UndefinedConstant());
    1748             : 
    1749             :   // 4. Let C be F.[[Constructor]].
    1750             :   Node* const constructor =
    1751         112 :       LoadContextElement(context, PromiseBuiltins::kConstructorSlot);
    1752             : 
    1753             :   // 5. Assert: IsConstructor(C) is true.
    1754             :   CSA_ASSERT(this, IsConstructor(constructor));
    1755             : 
    1756             :   // 6. Let promise be ? PromiseResolve(C, result).
    1757             :   Node* const promise =
    1758         112 :     CallBuiltin(Builtins::kPromiseResolve, context, constructor, result);
    1759             : 
    1760             :   // 7. Let thrower be equivalent to a function that throws reason.
    1761         112 :   Node* const native_context = LoadNativeContext(context);
    1762          56 :   Node* const thrower = CreateThrowerFunction(reason, native_context);
    1763             : 
    1764             :   // 8. Return ? Invoke(promise, "then", « thrower »).
    1765         112 :   Return(InvokeThen(native_context, promise, thrower));
    1766          56 : }
    1767             : 
    1768         224 : TF_BUILTIN(PromisePrototypeFinally, PromiseBuiltinsAssembler) {
    1769             :   CSA_ASSERT_JS_ARGC_EQ(this, 1);
    1770             : 
    1771             :   // 1.  Let promise be the this value.
    1772             :   Node* const receiver = Parameter(Descriptor::kReceiver);
    1773             :   Node* const on_finally = Parameter(Descriptor::kOnFinally);
    1774             :   Node* const context = Parameter(Descriptor::kContext);
    1775             : 
    1776             :   // 2. If Type(promise) is not Object, throw a TypeError exception.
    1777          56 :   ThrowIfNotJSReceiver(context, receiver, MessageTemplate::kCalledOnNonObject,
    1778          56 :                        "Promise.prototype.finally");
    1779             : 
    1780             :   // 3. Let C be ? SpeciesConstructor(promise, %Promise%).
    1781         112 :   Node* const native_context = LoadNativeContext(context);
    1782             :   Node* const promise_fun =
    1783         112 :       LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX);
    1784         112 :   VARIABLE(var_constructor, MachineRepresentation::kTagged, promise_fun);
    1785          56 :   Label slow_constructor(this, Label::kDeferred), done_constructor(this);
    1786         112 :   Node* const receiver_map = LoadMap(receiver);
    1787         112 :   GotoIfNot(IsJSPromiseMap(receiver_map), &slow_constructor);
    1788          56 :   BranchIfPromiseSpeciesLookupChainIntact(native_context, receiver_map,
    1789          56 :                                           &done_constructor, &slow_constructor);
    1790          56 :   BIND(&slow_constructor);
    1791             :   {
    1792             :     Node* const constructor =
    1793         112 :         SpeciesConstructor(context, receiver, promise_fun);
    1794          56 :     var_constructor.Bind(constructor);
    1795          56 :     Goto(&done_constructor);
    1796             :   }
    1797          56 :   BIND(&done_constructor);
    1798          56 :   Node* const constructor = var_constructor.value();
    1799             : 
    1800             :   // 4. Assert: IsConstructor(C) is true.
    1801             :   CSA_ASSERT(this, IsConstructor(constructor));
    1802             : 
    1803         112 :   VARIABLE(var_then_finally, MachineRepresentation::kTagged);
    1804         112 :   VARIABLE(var_catch_finally, MachineRepresentation::kTagged);
    1805             : 
    1806          56 :   Label if_notcallable(this, Label::kDeferred), perform_finally(this);
    1807             : 
    1808         112 :   GotoIf(TaggedIsSmi(on_finally), &if_notcallable);
    1809         112 :   GotoIfNot(IsCallable(on_finally), &if_notcallable);
    1810             : 
    1811             :   // 6. Else,
    1812             :   //   a. Let thenFinally be a new built-in function object as defined
    1813             :   //   in ThenFinally Function.
    1814             :   //   b. Let catchFinally be a new built-in function object as
    1815             :   //   defined in CatchFinally Function.
    1816             :   //   c. Set thenFinally and catchFinally's [[Constructor]] internal
    1817             :   //   slots to C.
    1818             :   //   d. Set thenFinally and catchFinally's [[OnFinally]] internal
    1819             :   //   slots to onFinally.
    1820          56 :   Node* then_finally = nullptr;
    1821          56 :   Node* catch_finally = nullptr;
    1822             :   std::tie(then_finally, catch_finally) =
    1823         112 :     CreatePromiseFinallyFunctions(on_finally, constructor, native_context);
    1824          56 :   var_then_finally.Bind(then_finally);
    1825          56 :   var_catch_finally.Bind(catch_finally);
    1826          56 :   Goto(&perform_finally);
    1827             : 
    1828             :   // 5. If IsCallable(onFinally) is not true,
    1829             :   //    a. Let thenFinally be onFinally.
    1830             :   //    b. Let catchFinally be onFinally.
    1831          56 :   BIND(&if_notcallable);
    1832             :   {
    1833          56 :     var_then_finally.Bind(on_finally);
    1834          56 :     var_catch_finally.Bind(on_finally);
    1835          56 :     Goto(&perform_finally);
    1836             :   }
    1837             : 
    1838             :   // 7. Return ? Invoke(promise, "then", « thenFinally, catchFinally »).
    1839          56 :   BIND(&perform_finally);
    1840         112 :   Return(InvokeThen(native_context, receiver, var_then_finally.value(),
    1841          56 :                     var_catch_finally.value()));
    1842          56 : }
    1843             : 
    1844             : // ES #sec-fulfillpromise
    1845         224 : TF_BUILTIN(FulfillPromise, PromiseBuiltinsAssembler) {
    1846             :   Node* const promise = Parameter(Descriptor::kPromise);
    1847             :   Node* const value = Parameter(Descriptor::kValue);
    1848             :   Node* const context = Parameter(Descriptor::kContext);
    1849             : 
    1850             :   CSA_ASSERT(this, TaggedIsNotSmi(promise));
    1851             :   CSA_ASSERT(this, IsJSPromise(promise));
    1852             : 
    1853             :   // 2. Let reactions be promise.[[PromiseFulfillReactions]].
    1854             :   Node* const reactions =
    1855          56 :       LoadObjectField(promise, JSPromise::kReactionsOrResultOffset);
    1856             : 
    1857             :   // 3. Set promise.[[PromiseResult]] to value.
    1858             :   // 4. Set promise.[[PromiseFulfillReactions]] to undefined.
    1859             :   // 5. Set promise.[[PromiseRejectReactions]] to undefined.
    1860          56 :   StoreObjectField(promise, JSPromise::kReactionsOrResultOffset, value);
    1861             : 
    1862             :   // 6. Set promise.[[PromiseState]] to "fulfilled".
    1863          56 :   PromiseSetStatus(promise, Promise::kFulfilled);
    1864             : 
    1865             :   // 7. Return TriggerPromiseReactions(reactions, value).
    1866         112 :   Return(TriggerPromiseReactions(context, reactions, value,
    1867          56 :                                  PromiseReaction::kFulfill));
    1868          56 : }
    1869             : 
    1870             : // ES #sec-rejectpromise
    1871         224 : TF_BUILTIN(RejectPromise, PromiseBuiltinsAssembler) {
    1872             :   Node* const promise = Parameter(Descriptor::kPromise);
    1873             :   Node* const reason = Parameter(Descriptor::kReason);
    1874             :   Node* const debug_event = Parameter(Descriptor::kDebugEvent);
    1875             :   Node* const context = Parameter(Descriptor::kContext);
    1876             : 
    1877             :   CSA_ASSERT(this, TaggedIsNotSmi(promise));
    1878             :   CSA_ASSERT(this, IsJSPromise(promise));
    1879             :   CSA_ASSERT(this, IsBoolean(debug_event));
    1880          56 :   Label if_runtime(this, Label::kDeferred);
    1881             : 
    1882             :   // If promise hook is enabled or the debugger is active, let
    1883             :   // the runtime handle this operation, which greatly reduces
    1884             :   // the complexity here and also avoids a couple of back and
    1885             :   // forth between JavaScript and C++ land.
    1886         112 :   GotoIf(IsPromiseHookEnabledOrDebugIsActiveOrHasAsyncEventDelegate(),
    1887          56 :          &if_runtime);
    1888             : 
    1889             :   // 7. If promise.[[PromiseIsHandled]] is false, perform
    1890             :   //    HostPromiseRejectionTracker(promise, "reject").
    1891             :   // We don't try to handle rejecting {promise} without handler
    1892             :   // here, but we let the C++ code take care of this completely.
    1893         112 :   GotoIfNot(PromiseHasHandler(promise), &if_runtime);
    1894             : 
    1895             :   // 2. Let reactions be promise.[[PromiseRejectReactions]].
    1896             :   Node* reactions =
    1897             :       LoadObjectField(promise, JSPromise::kReactionsOrResultOffset);
    1898             : 
    1899             :   // 3. Set promise.[[PromiseResult]] to reason.
    1900             :   // 4. Set promise.[[PromiseFulfillReactions]] to undefined.
    1901             :   // 5. Set promise.[[PromiseRejectReactions]] to undefined.
    1902          56 :   StoreObjectField(promise, JSPromise::kReactionsOrResultOffset, reason);
    1903             : 
    1904             :   // 6. Set promise.[[PromiseState]] to "rejected".
    1905          56 :   PromiseSetStatus(promise, Promise::kRejected);
    1906             : 
    1907             :   // 7. Return TriggerPromiseReactions(reactions, reason).
    1908         112 :   Return(TriggerPromiseReactions(context, reactions, reason,
    1909          56 :                                  PromiseReaction::kReject));
    1910             : 
    1911          56 :   BIND(&if_runtime);
    1912          56 :   TailCallRuntime(Runtime::kRejectPromise, context, promise, reason,
    1913          56 :                   debug_event);
    1914          56 : }
    1915             : 
    1916             : // ES #sec-promise-resolve-functions
    1917         224 : TF_BUILTIN(ResolvePromise, PromiseBuiltinsAssembler) {
    1918             :   Node* const promise = Parameter(Descriptor::kPromise);
    1919             :   Node* const resolution = Parameter(Descriptor::kResolution);
    1920             :   Node* const context = Parameter(Descriptor::kContext);
    1921             : 
    1922             :   CSA_ASSERT(this, TaggedIsNotSmi(promise));
    1923             :   CSA_ASSERT(this, IsJSPromise(promise));
    1924             : 
    1925          56 :   Label do_enqueue(this), if_fulfill(this), if_reject(this, Label::kDeferred),
    1926          56 :       if_runtime(this, Label::kDeferred);
    1927         112 :   VARIABLE(var_reason, MachineRepresentation::kTagged);
    1928         112 :   VARIABLE(var_then, MachineRepresentation::kTagged);
    1929             : 
    1930             :   // If promise hook is enabled or the debugger is active, let
    1931             :   // the runtime handle this operation, which greatly reduces
    1932             :   // the complexity here and also avoids a couple of back and
    1933             :   // forth between JavaScript and C++ land.
    1934         112 :   GotoIf(IsPromiseHookEnabledOrDebugIsActiveOrHasAsyncEventDelegate(),
    1935          56 :          &if_runtime);
    1936             : 
    1937             :   // 6. If SameValue(resolution, promise) is true, then
    1938             :   // We can use pointer comparison here, since the {promise} is guaranteed
    1939             :   // to be a JSPromise inside this function and thus is reference comparable.
    1940         112 :   GotoIf(WordEqual(promise, resolution), &if_runtime);
    1941             : 
    1942             :   // 7. If Type(resolution) is not Object, then
    1943         112 :   GotoIf(TaggedIsSmi(resolution), &if_fulfill);
    1944         112 :   Node* const resolution_map = LoadMap(resolution);
    1945         112 :   GotoIfNot(IsJSReceiverMap(resolution_map), &if_fulfill);
    1946             : 
    1947             :   // We can skip the "then" lookup on {resolution} if its [[Prototype]]
    1948             :   // is the (initial) Promise.prototype and the Promise#then protector
    1949             :   // is intact, as that guards the lookup path for the "then" property
    1950             :   // on JSPromise instances which have the (initial) %PromisePrototype%.
    1951          56 :   Label if_fast(this), if_receiver(this), if_slow(this, Label::kDeferred);
    1952         112 :   Node* const native_context = LoadNativeContext(context);
    1953          56 :   GotoIfForceSlowPath(&if_slow);
    1954         112 :   GotoIf(IsPromiseThenProtectorCellInvalid(), &if_slow);
    1955         112 :   GotoIfNot(IsJSPromiseMap(resolution_map), &if_receiver);
    1956             :   Node* const promise_prototype =
    1957         112 :       LoadContextElement(native_context, Context::PROMISE_PROTOTYPE_INDEX);
    1958         112 :   Branch(WordEqual(LoadMapPrototype(resolution_map), promise_prototype),
    1959          56 :          &if_fast, &if_slow);
    1960             : 
    1961          56 :   BIND(&if_fast);
    1962             :   {
    1963             :     // The {resolution} is a native Promise in this case.
    1964             :     Node* const then =
    1965         112 :         LoadContextElement(native_context, Context::PROMISE_THEN_INDEX);
    1966          56 :     var_then.Bind(then);
    1967          56 :     Goto(&do_enqueue);
    1968             :   }
    1969             : 
    1970          56 :   BIND(&if_receiver);
    1971             :   {
    1972             :     // We can skip the lookup of "then" if the {resolution} is a (newly
    1973             :     // created) IterResultObject, as the Promise#then() protector also
    1974             :     // ensures that the intrinsic %ObjectPrototype% doesn't contain any
    1975             :     // "then" property. This helps to avoid negative lookups on iterator
    1976             :     // results from async generators.
    1977             :     CSA_ASSERT(this, IsJSReceiverMap(resolution_map));
    1978             :     CSA_ASSERT(this, Word32BinaryNot(IsPromiseThenProtectorCellInvalid()));
    1979             :     Node* const iterator_result_map =
    1980         112 :         LoadContextElement(native_context, Context::ITERATOR_RESULT_MAP_INDEX);
    1981         112 :     Branch(WordEqual(resolution_map, iterator_result_map), &if_fulfill,
    1982          56 :            &if_slow);
    1983             :   }
    1984             : 
    1985          56 :   BIND(&if_slow);
    1986             :   {
    1987             :     // 8. Let then be Get(resolution, "then").
    1988             :     Node* const then =
    1989         168 :         GetProperty(context, resolution, isolate()->factory()->then_string());
    1990             : 
    1991             :     // 9. If then is an abrupt completion, then
    1992          56 :     GotoIfException(then, &if_reject, &var_reason);
    1993             : 
    1994             :     // 11. If IsCallable(thenAction) is false, then
    1995         112 :     GotoIf(TaggedIsSmi(then), &if_fulfill);
    1996         112 :     Node* const then_map = LoadMap(then);
    1997         112 :     GotoIfNot(IsCallableMap(then_map), &if_fulfill);
    1998          56 :     var_then.Bind(then);
    1999          56 :     Goto(&do_enqueue);
    2000             :   }
    2001             : 
    2002          56 :   BIND(&do_enqueue);
    2003             :   {
    2004             :     // 12. Perform EnqueueJob("PromiseJobs", PromiseResolveThenableJob,
    2005             :     //                        «promise, resolution, thenAction»).
    2006          56 :     Node* const task = AllocatePromiseResolveThenableJobTask(
    2007          56 :         promise, var_then.value(), resolution, native_context);
    2008          56 :     TailCallBuiltin(Builtins::kEnqueueMicrotask, native_context, task);
    2009             :   }
    2010             : 
    2011          56 :   BIND(&if_fulfill);
    2012             :   {
    2013             :     // 7.b Return FulfillPromise(promise, resolution).
    2014          56 :     TailCallBuiltin(Builtins::kFulfillPromise, context, promise, resolution);
    2015             :   }
    2016             : 
    2017          56 :   BIND(&if_runtime);
    2018          56 :   Return(CallRuntime(Runtime::kResolvePromise, context, promise, resolution));
    2019             : 
    2020          56 :   BIND(&if_reject);
    2021             :   {
    2022             :     // 9.a Return RejectPromise(promise, then.[[Value]]).
    2023         112 :     TailCallBuiltin(Builtins::kRejectPromise, context, promise,
    2024          56 :                     var_reason.value(), FalseConstant());
    2025             :   }
    2026          56 : }
    2027             : 
    2028         112 : Node* PromiseBuiltinsAssembler::PerformPromiseAll(
    2029             :     Node* context, Node* constructor, Node* capability,
    2030             :     const IteratorRecord& iterator,
    2031             :     const PromiseAllResolvingElementFunction& create_resolve_element_function,
    2032             :     const PromiseAllResolvingElementFunction& create_reject_element_function,
    2033             :     Label* if_exception, Variable* var_exception) {
    2034         112 :   IteratorBuiltinsAssembler iter_assembler(state());
    2035             : 
    2036         112 :   TNode<NativeContext> native_context = Cast(LoadNativeContext(context));
    2037             : 
    2038             :   // For catch prediction, don't treat the .then calls as handling it;
    2039             :   // instead, recurse outwards.
    2040         112 :   SetForwardingHandlerIfTrue(
    2041             :       native_context, IsDebugActive(),
    2042         112 :       LoadObjectField(capability, PromiseCapability::kRejectOffset));
    2043             : 
    2044             :   TNode<Context> resolve_element_context =
    2045         112 :       Cast(CreatePromiseAllResolveElementContext(capability, native_context));
    2046             : 
    2047         112 :   TVARIABLE(Smi, var_index, SmiConstant(1));
    2048         112 :   Label loop(this, &var_index), done_loop(this),
    2049         112 :       too_many_elements(this, Label::kDeferred),
    2050         112 :       close_iterator(this, Label::kDeferred);
    2051         112 :   Goto(&loop);
    2052         112 :   BIND(&loop);
    2053             :   {
    2054             :     // Let next be IteratorStep(iteratorRecord.[[Iterator]]).
    2055             :     // If next is an abrupt completion, set iteratorRecord.[[Done]] to true.
    2056             :     // ReturnIfAbrupt(next).
    2057             :     Node* const fast_iterator_result_map =
    2058         224 :         LoadContextElement(native_context, Context::ITERATOR_RESULT_MAP_INDEX);
    2059         224 :     Node* const next = iter_assembler.IteratorStep(
    2060             :         native_context, iterator, &done_loop, fast_iterator_result_map,
    2061             :         if_exception, var_exception);
    2062             : 
    2063             :     // Let nextValue be IteratorValue(next).
    2064             :     // If nextValue is an abrupt completion, set iteratorRecord.[[Done]] to
    2065             :     //     true.
    2066             :     // ReturnIfAbrupt(nextValue).
    2067             :     Node* const next_value = iter_assembler.IteratorValue(
    2068             :         native_context, next, fast_iterator_result_map, if_exception,
    2069         112 :         var_exception);
    2070             : 
    2071             :     // Check if we reached the limit.
    2072             :     TNode<Smi> const index = var_index.value();
    2073         224 :     GotoIf(SmiEqual(index, SmiConstant(PropertyArray::HashField::kMax)),
    2074         112 :            &too_many_elements);
    2075             : 
    2076             :     // Set index to index + 1.
    2077         112 :     var_index = SmiAdd(index, SmiConstant(1));
    2078             : 
    2079             :     // Set remainingElementsCount.[[Value]] to
    2080             :     //     remainingElementsCount.[[Value]] + 1.
    2081         112 :     TNode<Smi> const remaining_elements_count = CAST(LoadContextElement(
    2082             :         resolve_element_context,
    2083             :         PromiseBuiltins::kPromiseAllResolveElementRemainingSlot));
    2084         112 :     StoreContextElementNoWriteBarrier(
    2085             :         resolve_element_context,
    2086             :         PromiseBuiltins::kPromiseAllResolveElementRemainingSlot,
    2087         336 :         SmiAdd(remaining_elements_count, SmiConstant(1)));
    2088             : 
    2089             :     // Let resolveElement be CreateBuiltinFunction(steps,
    2090             :     //                                             « [[AlreadyCalled]],
    2091             :     //                                               [[Index]],
    2092             :     //                                               [[Values]],
    2093             :     //                                               [[Capability]],
    2094             :     //                                               [[RemainingElements]] »).
    2095             :     // Set resolveElement.[[AlreadyCalled]] to a Record { [[Value]]: false }.
    2096             :     // Set resolveElement.[[Index]] to index.
    2097             :     // Set resolveElement.[[Values]] to values.
    2098             :     // Set resolveElement.[[Capability]] to resultCapability.
    2099             :     // Set resolveElement.[[RemainingElements]] to remainingElementsCount.
    2100             :     Node* const resolve_element_fun = create_resolve_element_function(
    2101             :         resolve_element_context, index, native_context, Cast(capability));
    2102             :     Node* const reject_element_fun = create_reject_element_function(
    2103             :         resolve_element_context, index, native_context, Cast(capability));
    2104             : 
    2105             :     // We can skip the "resolve" lookup on the {constructor} as well as the
    2106             :     // "then" lookup on the result of the "resolve" call, and immediately
    2107             :     // chain continuation onto the {next_value} if:
    2108             :     //
    2109             :     //   (a) The {constructor} is the intrinsic %Promise% function, and
    2110             :     //       looking up "resolve" on {constructor} yields the initial
    2111             :     //       Promise.resolve() builtin, and
    2112             :     //   (b) the promise @@species protector cell is valid, meaning that
    2113             :     //       no one messed with the Symbol.species property on any
    2114             :     //       intrinsic promise or on the Promise.prototype, and
    2115             :     //   (c) the {next_value} is a JSPromise whose [[Prototype]] field
    2116             :     //       contains the intrinsic %PromisePrototype%, and
    2117             :     //   (d) we're not running with async_hooks or DevTools enabled.
    2118             :     //
    2119             :     // In that case we also don't need to allocate a chained promise for
    2120             :     // the PromiseReaction (aka we can pass undefined to PerformPromiseThen),
    2121             :     // since this is only necessary for DevTools and PromiseHooks.
    2122         112 :     Label if_fast(this), if_slow(this);
    2123             :     GotoIfNotPromiseResolveLookupChainIntact(native_context, constructor,
    2124         112 :                                              &if_slow);
    2125         224 :     GotoIf(IsPromiseHookEnabledOrDebugIsActiveOrHasAsyncEventDelegate(),
    2126         112 :            &if_slow);
    2127         224 :     GotoIf(IsPromiseSpeciesProtectorCellInvalid(), &if_slow);
    2128         224 :     GotoIf(TaggedIsSmi(next_value), &if_slow);
    2129         224 :     Node* const next_value_map = LoadMap(next_value);
    2130             :     BranchIfPromiseThenLookupChainIntact(native_context, next_value_map,
    2131         112 :                                          &if_fast, &if_slow);
    2132             : 
    2133         112 :     BIND(&if_fast);
    2134             :     {
    2135             :       // Register the PromiseReaction immediately on the {next_value}, not
    2136             :       // passing any chained promise since neither async_hooks nor DevTools
    2137             :       // are enabled, so there's no use of the resulting promise.
    2138             :       PerformPromiseThen(native_context, next_value, resolve_element_fun,
    2139         224 :                          reject_element_fun, UndefinedConstant());
    2140         112 :       Goto(&loop);
    2141             :     }
    2142             : 
    2143         112 :     BIND(&if_slow);
    2144             :     {
    2145             :       // Let nextPromise be ? Invoke(constructor, "resolve", « nextValue »).
    2146             :       Node* const next_promise =
    2147             :           InvokeResolve(native_context, constructor, next_value,
    2148         112 :                         &close_iterator, var_exception);
    2149             : 
    2150             :       // Perform ? Invoke(nextPromise, "then", « resolveElement,
    2151             :       //                  resultCapability.[[Reject]] »).
    2152             :       Node* const then =
    2153         336 :           GetProperty(native_context, next_promise, factory()->then_string());
    2154         112 :       GotoIfException(then, &close_iterator, var_exception);
    2155             : 
    2156             :       Node* const then_call =
    2157         224 :           CallJS(CodeFactory::Call(isolate(),
    2158             :                                    ConvertReceiverMode::kNotNullOrUndefined),
    2159             :                  native_context, then, next_promise, resolve_element_fun,
    2160         112 :                  reject_element_fun);
    2161         112 :       GotoIfException(then_call, &close_iterator, var_exception);
    2162             : 
    2163             :       // For catch prediction, mark that rejections here are semantically
    2164             :       // handled by the combined Promise.
    2165         224 :       SetPromiseHandledByIfTrue(
    2166         112 :           native_context, IsDebugActive(), then_call, [=]() {
    2167             :             // Load promiseCapability.[[Promise]]
    2168         112 :             return LoadObjectField(capability,
    2169         112 :                                    PromiseCapability::kPromiseOffset);
    2170         224 :           });
    2171             : 
    2172         112 :       Goto(&loop);
    2173             :     }
    2174             :   }
    2175             : 
    2176         112 :   BIND(&too_many_elements);
    2177             :   {
    2178             :     // If there are too many elements (currently more than 2**21-1), raise a
    2179             :     // RangeError here (which is caught directly and turned into a rejection)
    2180             :     // of the resulting promise. We could gracefully handle this case as well
    2181             :     // and support more than this number of elements by going to a separate
    2182             :     // function and pass the larger indices via a separate context, but it
    2183             :     // doesn't seem likely that we need this, and it's unclear how the rest
    2184             :     // of the system deals with 2**21 live Promises anyways.
    2185             :     Node* const result =
    2186             :         CallRuntime(Runtime::kThrowRangeError, native_context,
    2187             :                     SmiConstant(MessageTemplate::kTooManyElementsInPromiseAll));
    2188         112 :     GotoIfException(result, &close_iterator, var_exception);
    2189         112 :     Unreachable();
    2190             :   }
    2191             : 
    2192         112 :   BIND(&close_iterator);
    2193             :   {
    2194             :     // Exception must be bound to a JS value.
    2195             :     CSA_ASSERT(this, IsNotTheHole(var_exception->value()));
    2196             :     iter_assembler.IteratorCloseOnException(native_context, iterator,
    2197         112 :                                             if_exception, var_exception);
    2198             :   }
    2199             : 
    2200         112 :   BIND(&done_loop);
    2201             :   {
    2202         112 :     Label resolve_promise(this, Label::kDeferred), return_promise(this);
    2203             :     // Set iteratorRecord.[[Done]] to true.
    2204             :     // Set remainingElementsCount.[[Value]] to
    2205             :     //    remainingElementsCount.[[Value]] - 1.
    2206         112 :     TNode<Smi> remaining_elements_count = CAST(LoadContextElement(
    2207             :         resolve_element_context,
    2208             :         PromiseBuiltins::kPromiseAllResolveElementRemainingSlot));
    2209         112 :     remaining_elements_count = SmiSub(remaining_elements_count, SmiConstant(1));
    2210         112 :     StoreContextElementNoWriteBarrier(
    2211             :         resolve_element_context,
    2212             :         PromiseBuiltins::kPromiseAllResolveElementRemainingSlot,
    2213         112 :         remaining_elements_count);
    2214         224 :     GotoIf(SmiEqual(remaining_elements_count, SmiConstant(0)),
    2215         112 :            &resolve_promise);
    2216             : 
    2217             :     // Pre-allocate the backing store for the {values_array} to the desired
    2218             :     // capacity here. We may already have elements here in case of some
    2219             :     // fancy Thenable that calls the resolve callback immediately, so we need
    2220             :     // to handle that correctly here.
    2221         224 :     Node* const values_array = LoadContextElement(
    2222             :         resolve_element_context,
    2223         112 :         PromiseBuiltins::kPromiseAllResolveElementValuesArraySlot);
    2224             :     Node* const old_elements = LoadElements(values_array);
    2225         112 :     TNode<Smi> const old_capacity = LoadFixedArrayBaseLength(old_elements);
    2226             :     TNode<Smi> const new_capacity = var_index.value();
    2227         224 :     GotoIf(SmiGreaterThanOrEqual(old_capacity, new_capacity), &return_promise);
    2228             :     Node* const new_elements =
    2229         224 :         AllocateFixedArray(PACKED_ELEMENTS, new_capacity, SMI_PARAMETERS,
    2230         112 :                            AllocationFlag::kAllowLargeObjectAllocation);
    2231             :     CopyFixedArrayElements(PACKED_ELEMENTS, old_elements, PACKED_ELEMENTS,
    2232         224 :                            new_elements, SmiConstant(0), old_capacity,
    2233         112 :                            new_capacity, UPDATE_WRITE_BARRIER, SMI_PARAMETERS);
    2234         112 :     StoreObjectField(values_array, JSArray::kElementsOffset, new_elements);
    2235         112 :     Goto(&return_promise);
    2236             : 
    2237             :     // If remainingElementsCount.[[Value]] is 0, then
    2238             :     //     Let valuesArray be CreateArrayFromList(values).
    2239             :     //     Perform ? Call(resultCapability.[[Resolve]], undefined,
    2240             :     //                    « valuesArray »).
    2241         112 :     BIND(&resolve_promise);
    2242             :     {
    2243             :       Node* const resolve =
    2244             :           LoadObjectField(capability, PromiseCapability::kResolveOffset);
    2245         224 :       Node* const values_array = LoadContextElement(
    2246             :           resolve_element_context,
    2247         112 :           PromiseBuiltins::kPromiseAllResolveElementValuesArraySlot);
    2248             :       Node* const resolve_call = CallJS(
    2249         224 :           CodeFactory::Call(isolate(), ConvertReceiverMode::kNullOrUndefined),
    2250         336 :           native_context, resolve, UndefinedConstant(), values_array);
    2251         112 :       GotoIfException(resolve_call, if_exception, var_exception);
    2252         112 :       Goto(&return_promise);
    2253             :     }
    2254             : 
    2255             :     // Return resultCapability.[[Promise]].
    2256         112 :     BIND(&return_promise);
    2257             :   }
    2258             : 
    2259             :   Node* const promise =
    2260             :       LoadObjectField(capability, PromiseCapability::kPromiseOffset);
    2261         112 :   return promise;
    2262             : }
    2263             : 
    2264         112 : void PromiseBuiltinsAssembler::Generate_PromiseAll(
    2265             :     TNode<Context> context, TNode<Object> receiver, TNode<Object> iterable,
    2266             :     const PromiseAllResolvingElementFunction& create_resolve_element_function,
    2267             :     const PromiseAllResolvingElementFunction& create_reject_element_function) {
    2268         112 :   IteratorBuiltinsAssembler iter_assembler(state());
    2269             : 
    2270             :   // Let C be the this value.
    2271             :   // If Type(C) is not Object, throw a TypeError exception.
    2272         112 :   ThrowIfNotJSReceiver(context, receiver, MessageTemplate::kCalledOnNonObject,
    2273         112 :                        "Promise.all");
    2274             : 
    2275             :   // Let promiseCapability be ? NewPromiseCapability(C).
    2276             :   // Don't fire debugEvent so that forwarding the rejection through all does not
    2277             :   // trigger redundant ExceptionEvents
    2278         224 :   Node* const debug_event = FalseConstant();
    2279         224 :   Node* const capability = CallBuiltin(Builtins::kNewPromiseCapability, context,
    2280         112 :                                        receiver, debug_event);
    2281             : 
    2282         336 :   VARIABLE(var_exception, MachineRepresentation::kTagged, TheHoleConstant());
    2283         112 :   Label reject_promise(this, &var_exception, Label::kDeferred);
    2284             : 
    2285             :   // Let iterator be GetIterator(iterable).
    2286             :   // IfAbruptRejectPromise(iterator, promiseCapability).
    2287             :   IteratorRecord iterator = iter_assembler.GetIterator(
    2288         112 :       context, iterable, &reject_promise, &var_exception);
    2289             : 
    2290             :   // Let result be PerformPromiseAll(iteratorRecord, C, promiseCapability).
    2291             :   // If result is an abrupt completion, then
    2292             :   //   If iteratorRecord.[[Done]] is false, let result be
    2293             :   //       IteratorClose(iterator, result).
    2294             :   //    IfAbruptRejectPromise(result, promiseCapability).
    2295             :   Node* const result = PerformPromiseAll(
    2296             :       context, receiver, capability, iterator, create_resolve_element_function,
    2297         112 :       create_reject_element_function, &reject_promise, &var_exception);
    2298             : 
    2299         112 :   Return(result);
    2300             : 
    2301         112 :   BIND(&reject_promise);
    2302             :   {
    2303             :     // Exception must be bound to a JS value.
    2304             :     CSA_SLOW_ASSERT(this, IsNotTheHole(var_exception.value()));
    2305             :     Node* const reject =
    2306             :         LoadObjectField(capability, PromiseCapability::kRejectOffset);
    2307         336 :     CallJS(CodeFactory::Call(isolate(), ConvertReceiverMode::kNullOrUndefined),
    2308         336 :            context, reject, UndefinedConstant(), var_exception.value());
    2309             : 
    2310             :     Node* const promise =
    2311             :         LoadObjectField(capability, PromiseCapability::kPromiseOffset);
    2312         112 :     Return(promise);
    2313             :   }
    2314         112 : }
    2315             : 
    2316             : // ES#sec-promise.all
    2317             : // Promise.all ( iterable )
    2318         336 : TF_BUILTIN(PromiseAll, PromiseBuiltinsAssembler) {
    2319          56 :   TNode<Object> receiver = Cast(Parameter(Descriptor::kReceiver));
    2320          56 :   TNode<Context> context = Cast(Parameter(Descriptor::kContext));
    2321          56 :   TNode<Object> iterable = Cast(Parameter(Descriptor::kIterable));
    2322         168 :   Generate_PromiseAll(
    2323             :       context, receiver, iterable,
    2324             :       [this](TNode<Context> context, TNode<Smi> index,
    2325             :              TNode<NativeContext> native_context,
    2326          56 :              TNode<PromiseCapability> capability) {
    2327             :         return CreatePromiseAllResolveElementFunction(
    2328             :             context, index, native_context,
    2329          56 :             Context::PROMISE_ALL_RESOLVE_ELEMENT_SHARED_FUN);
    2330          56 :       },
    2331             :       [this](TNode<Context> context, TNode<Smi> index,
    2332             :              TNode<NativeContext> native_context,
    2333          56 :              TNode<PromiseCapability> capability) {
    2334          56 :         return LoadObjectField(capability, PromiseCapability::kRejectOffset);
    2335          56 :       });
    2336          56 : }
    2337             : 
    2338             : // ES#sec-promise.allsettled
    2339             : // Promise.allSettled ( iterable )
    2340         336 : TF_BUILTIN(PromiseAllSettled, PromiseBuiltinsAssembler) {
    2341          56 :   TNode<Object> receiver = Cast(Parameter(Descriptor::kReceiver));
    2342          56 :   TNode<Context> context = Cast(Parameter(Descriptor::kContext));
    2343          56 :   TNode<Object> iterable = Cast(Parameter(Descriptor::kIterable));
    2344         168 :   Generate_PromiseAll(
    2345             :       context, receiver, iterable,
    2346             :       [this](TNode<Context> context, TNode<Smi> index,
    2347             :              TNode<NativeContext> native_context,
    2348          56 :              TNode<PromiseCapability> capability) {
    2349             :         return CreatePromiseAllResolveElementFunction(
    2350             :             context, index, native_context,
    2351          56 :             Context::PROMISE_ALL_SETTLED_RESOLVE_ELEMENT_SHARED_FUN);
    2352          56 :       },
    2353             :       [this](TNode<Context> context, TNode<Smi> index,
    2354             :              TNode<NativeContext> native_context,
    2355          56 :              TNode<PromiseCapability> capability) {
    2356             :         return CreatePromiseAllResolveElementFunction(
    2357             :             context, index, native_context,
    2358          56 :             Context::PROMISE_ALL_SETTLED_REJECT_ELEMENT_SHARED_FUN);
    2359         112 :       });
    2360          56 : }
    2361             : 
    2362         168 : void PromiseBuiltinsAssembler::Generate_PromiseAllResolveElementClosure(
    2363             :     TNode<Context> context, TNode<Object> value, TNode<JSFunction> function,
    2364             :     const CreatePromiseAllResolveElementFunctionValue& callback) {
    2365         336 :   Label already_called(this, Label::kDeferred), resolve_promise(this);
    2366             : 
    2367             :   // We use the {function}s context as the marker to remember whether this
    2368             :   // resolve element closure was already called. It points to the resolve
    2369             :   // element context (which is a FunctionContext) until it was called the
    2370             :   // first time, in which case we make it point to the native context here
    2371             :   // to mark this resolve element closure as done.
    2372         336 :   GotoIf(IsNativeContext(context), &already_called);
    2373             :   CSA_ASSERT(
    2374             :       this,
    2375             :       SmiEqual(LoadObjectField<Smi>(context, Context::kLengthOffset),
    2376             :                SmiConstant(PromiseBuiltins::kPromiseAllResolveElementLength)));
    2377         168 :   TNode<NativeContext> native_context = Cast(LoadNativeContext(context));
    2378         168 :   StoreObjectField(function, JSFunction::kContextOffset, native_context);
    2379             : 
    2380             :   // Update the value depending on whether Promise.all or
    2381             :   // Promise.allSettled is called.
    2382             :   value = callback(context, native_context, value);
    2383             : 
    2384             :   // Determine the index from the {function}.
    2385         168 :   Label unreachable(this, Label::kDeferred);
    2386             :   STATIC_ASSERT(PropertyArray::kNoHashSentinel == 0);
    2387             :   TNode<IntPtrT> identity_hash =
    2388         168 :       LoadJSReceiverIdentityHash(function, &unreachable);
    2389             :   CSA_ASSERT(this, IntPtrGreaterThan(identity_hash, IntPtrConstant(0)));
    2390         168 :   TNode<IntPtrT> index = IntPtrSub(identity_hash, IntPtrConstant(1));
    2391             : 
    2392             :   // Check if we need to grow the [[ValuesArray]] to store {value} at {index}.
    2393         168 :   TNode<JSArray> values_array = CAST(LoadContextElement(
    2394             :       context, PromiseBuiltins::kPromiseAllResolveElementValuesArraySlot));
    2395             :   TNode<FixedArray> elements = CAST(LoadElements(values_array));
    2396             :   TNode<IntPtrT> values_length =
    2397         168 :       LoadAndUntagObjectField(values_array, JSArray::kLengthOffset);
    2398         168 :   Label if_inbounds(this), if_outofbounds(this), done(this);
    2399         336 :   Branch(IntPtrLessThan(index, values_length), &if_inbounds, &if_outofbounds);
    2400             : 
    2401         168 :   BIND(&if_outofbounds);
    2402             :   {
    2403             :     // Check if we need to grow the backing store.
    2404         168 :     TNode<IntPtrT> new_length = IntPtrAdd(index, IntPtrConstant(1));
    2405             :     TNode<IntPtrT> elements_length =
    2406         168 :         LoadAndUntagObjectField(elements, FixedArray::kLengthOffset);
    2407         168 :     Label if_grow(this, Label::kDeferred), if_nogrow(this);
    2408         336 :     Branch(IntPtrLessThan(index, elements_length), &if_nogrow, &if_grow);
    2409             : 
    2410         168 :     BIND(&if_grow);
    2411             :     {
    2412             :       // We need to grow the backing store to fit the {index} as well.
    2413             :       TNode<IntPtrT> new_elements_length =
    2414             :           IntPtrMin(CalculateNewElementsCapacity(new_length),
    2415         504 :                     IntPtrConstant(PropertyArray::HashField::kMax + 1));
    2416             :       CSA_ASSERT(this, IntPtrLessThan(index, new_elements_length));
    2417             :       CSA_ASSERT(this, IntPtrLessThan(elements_length, new_elements_length));
    2418             :       TNode<FixedArray> new_elements =
    2419             :           CAST(AllocateFixedArray(PACKED_ELEMENTS, new_elements_length,
    2420             :                                   AllocationFlag::kAllowLargeObjectAllocation));
    2421             :       CopyFixedArrayElements(PACKED_ELEMENTS, elements, PACKED_ELEMENTS,
    2422             :                              new_elements, elements_length,
    2423         168 :                              new_elements_length);
    2424         168 :       StoreFixedArrayElement(new_elements, index, value);
    2425             : 
    2426             :       // Update backing store and "length" on {values_array}.
    2427         168 :       StoreObjectField(values_array, JSArray::kElementsOffset, new_elements);
    2428         336 :       StoreObjectFieldNoWriteBarrier(values_array, JSArray::kLengthOffset,
    2429             :                                      SmiTag(new_length));
    2430         168 :       Goto(&done);
    2431             :     }
    2432             : 
    2433         168 :     BIND(&if_nogrow);
    2434             :     {
    2435             :       // The {index} is within bounds of the {elements} backing store, so
    2436             :       // just store the {value} and update the "length" of the {values_array}.
    2437         336 :       StoreObjectFieldNoWriteBarrier(values_array, JSArray::kLengthOffset,
    2438             :                                      SmiTag(new_length));
    2439         168 :       StoreFixedArrayElement(elements, index, value);
    2440         168 :       Goto(&done);
    2441             :     }
    2442             :   }
    2443             : 
    2444         168 :   BIND(&if_inbounds);
    2445             :   {
    2446             :     // The {index} is in bounds of the {values_array},
    2447             :     // just store the {value} and continue.
    2448         168 :     StoreFixedArrayElement(elements, index, value);
    2449         168 :     Goto(&done);
    2450             :   }
    2451             : 
    2452         168 :   BIND(&done);
    2453         168 :   TNode<Smi> remaining_elements_count = CAST(LoadContextElement(
    2454             :       context, PromiseBuiltins::kPromiseAllResolveElementRemainingSlot));
    2455         168 :   remaining_elements_count = SmiSub(remaining_elements_count, SmiConstant(1));
    2456         168 :   StoreContextElement(context,
    2457             :                       PromiseBuiltins::kPromiseAllResolveElementRemainingSlot,
    2458         168 :                       remaining_elements_count);
    2459         336 :   GotoIf(SmiEqual(remaining_elements_count, SmiConstant(0)), &resolve_promise);
    2460         336 :   Return(UndefinedConstant());
    2461             : 
    2462         168 :   BIND(&resolve_promise);
    2463         168 :   TNode<PromiseCapability> capability = CAST(LoadContextElement(
    2464             :       context, PromiseBuiltins::kPromiseAllResolveElementCapabilitySlot));
    2465             :   TNode<Object> resolve =
    2466             :       LoadObjectField(capability, PromiseCapability::kResolveOffset);
    2467         336 :   CallJS(CodeFactory::Call(isolate(), ConvertReceiverMode::kNullOrUndefined),
    2468         504 :          context, resolve, UndefinedConstant(), values_array);
    2469         336 :   Return(UndefinedConstant());
    2470             : 
    2471         168 :   BIND(&already_called);
    2472         336 :   Return(UndefinedConstant());
    2473             : 
    2474         168 :   BIND(&unreachable);
    2475         168 :   Unreachable();
    2476         168 : }
    2477             : 
    2478         336 : TF_BUILTIN(PromiseAllResolveElementClosure, PromiseBuiltinsAssembler) {
    2479          56 :   TNode<Object> value = CAST(Parameter(Descriptor::kValue));
    2480          56 :   TNode<Context> context = CAST(Parameter(Descriptor::kContext));
    2481          56 :   TNode<JSFunction> function = CAST(Parameter(Descriptor::kJSTarget));
    2482             : 
    2483         112 :   Generate_PromiseAllResolveElementClosure(
    2484             :       context, value, function,
    2485             :       [](TNode<Object>, TNode<NativeContext>, TNode<Object> value) {
    2486             :         return value;
    2487          56 :       });
    2488          56 : }
    2489             : 
    2490         336 : TF_BUILTIN(PromiseAllSettledResolveElementClosure, PromiseBuiltinsAssembler) {
    2491          56 :   TNode<Object> value = CAST(Parameter(Descriptor::kValue));
    2492          56 :   TNode<Context> context = CAST(Parameter(Descriptor::kContext));
    2493          56 :   TNode<JSFunction> function = CAST(Parameter(Descriptor::kJSTarget));
    2494             : 
    2495         112 :   Generate_PromiseAllResolveElementClosure(
    2496             :       context, value, function,
    2497             :       [this](TNode<Context> context, TNode<NativeContext> native_context,
    2498         504 :              TNode<Object> value) {
    2499             :         // TODO(gsathya): Optimize the creation using a cached map to
    2500             :         // prevent transitions here.
    2501             :         // 9. Let obj be ! ObjectCreate(%ObjectPrototype%).
    2502             :         TNode<HeapObject> object_function = Cast(
    2503         112 :             LoadContextElement(native_context, Context::OBJECT_FUNCTION_INDEX));
    2504             :         TNode<Map> object_function_map = Cast(LoadObjectField(
    2505          56 :             object_function, JSFunction::kPrototypeOrInitialMapOffset));
    2506             :         TNode<JSObject> obj =
    2507         112 :             Cast(AllocateJSObjectFromMap(object_function_map));
    2508             : 
    2509             :         // 10. Perform ! CreateDataProperty(obj, "status", "fulfilled").
    2510             :         CallBuiltin(Builtins::kFastCreateDataProperty, context, obj,
    2511         168 :                     StringConstant("status"), StringConstant("fulfilled"));
    2512             : 
    2513             :         // 11. Perform ! CreateDataProperty(obj, "value", x).
    2514             :         CallBuiltin(Builtins::kFastCreateDataProperty, context, obj,
    2515         112 :                     StringConstant("value"), value);
    2516             : 
    2517          56 :         return obj;
    2518          56 :       });
    2519          56 : }
    2520             : 
    2521         336 : TF_BUILTIN(PromiseAllSettledRejectElementClosure, PromiseBuiltinsAssembler) {
    2522          56 :   TNode<Object> value = CAST(Parameter(Descriptor::kValue));
    2523          56 :   TNode<Context> context = CAST(Parameter(Descriptor::kContext));
    2524          56 :   TNode<JSFunction> function = CAST(Parameter(Descriptor::kJSTarget));
    2525             : 
    2526         112 :   Generate_PromiseAllResolveElementClosure(
    2527             :       context, value, function,
    2528             :       [this](TNode<Context> context, TNode<NativeContext> native_context,
    2529         504 :              TNode<Object> value) {
    2530             :         // TODO(gsathya): Optimize the creation using a cached map to
    2531             :         // prevent transitions here.
    2532             :         // 9. Let obj be ! ObjectCreate(%ObjectPrototype%).
    2533             :         TNode<HeapObject> object_function = Cast(
    2534         112 :             LoadContextElement(native_context, Context::OBJECT_FUNCTION_INDEX));
    2535             :         TNode<Map> object_function_map = Cast(LoadObjectField(
    2536          56 :             object_function, JSFunction::kPrototypeOrInitialMapOffset));
    2537             :         TNode<JSObject> obj =
    2538         112 :             Cast(AllocateJSObjectFromMap(object_function_map));
    2539             : 
    2540             :         // 10. Perform ! CreateDataProperty(obj, "status", "rejected").
    2541             :         CallBuiltin(Builtins::kFastCreateDataProperty, context, obj,
    2542         168 :                     StringConstant("status"), StringConstant("rejected"));
    2543             : 
    2544             :         // 11. Perform ! CreateDataProperty(obj, "reason", x).
    2545             :         CallBuiltin(Builtins::kFastCreateDataProperty, context, obj,
    2546         112 :                     StringConstant("reason"), value);
    2547             : 
    2548          56 :         return obj;
    2549          56 :       });
    2550          56 : }
    2551             : 
    2552             : // ES#sec-promise.race
    2553             : // Promise.race ( iterable )
    2554         336 : TF_BUILTIN(PromiseRace, PromiseBuiltinsAssembler) {
    2555          56 :   IteratorBuiltinsAssembler iter_assembler(state());
    2556         168 :   VARIABLE(var_exception, MachineRepresentation::kTagged, TheHoleConstant());
    2557             : 
    2558             :   Node* const receiver = Parameter(Descriptor::kReceiver);
    2559             :   Node* const context = Parameter(Descriptor::kContext);
    2560             :   ThrowIfNotJSReceiver(context, receiver, MessageTemplate::kCalledOnNonObject,
    2561          56 :                        "Promise.race");
    2562             : 
    2563             :   // Let promiseCapability be ? NewPromiseCapability(C).
    2564             :   // Don't fire debugEvent so that forwarding the rejection through all does not
    2565             :   // trigger redundant ExceptionEvents
    2566         112 :   Node* const debug_event = FalseConstant();
    2567         112 :   Node* const capability = CallBuiltin(Builtins::kNewPromiseCapability, context,
    2568          56 :                                        receiver, debug_event);
    2569             : 
    2570             :   Node* const resolve =
    2571             :       LoadObjectField(capability, PromiseCapability::kResolveOffset);
    2572             :   Node* const reject =
    2573             :       LoadObjectField(capability, PromiseCapability::kRejectOffset);
    2574             : 
    2575          56 :   Label close_iterator(this, Label::kDeferred);
    2576          56 :   Label reject_promise(this, Label::kDeferred);
    2577             : 
    2578             :   // For catch prediction, don't treat the .then calls as handling it;
    2579             :   // instead, recurse outwards.
    2580          56 :   SetForwardingHandlerIfTrue(context, IsDebugActive(), reject);
    2581             : 
    2582             :   // Let iterator be GetIterator(iterable).
    2583             :   // IfAbruptRejectPromise(iterator, promiseCapability).
    2584             :   Node* const iterable = Parameter(Descriptor::kIterable);
    2585             :   IteratorRecord iterator = iter_assembler.GetIterator(
    2586          56 :       context, iterable, &reject_promise, &var_exception);
    2587             : 
    2588             :   // Let result be PerformPromiseRace(iteratorRecord, C, promiseCapability).
    2589             :   {
    2590          56 :     Label loop(this), break_loop(this);
    2591          56 :     Goto(&loop);
    2592          56 :     BIND(&loop);
    2593             :     {
    2594         112 :       Node* const native_context = LoadNativeContext(context);
    2595         112 :       Node* const fast_iterator_result_map = LoadContextElement(
    2596          56 :           native_context, Context::ITERATOR_RESULT_MAP_INDEX);
    2597             : 
    2598             :       // Let next be IteratorStep(iteratorRecord.[[Iterator]]).
    2599             :       // If next is an abrupt completion, set iteratorRecord.[[Done]] to true.
    2600             :       // ReturnIfAbrupt(next).
    2601         112 :       Node* const next = iter_assembler.IteratorStep(
    2602             :           context, iterator, &break_loop, fast_iterator_result_map,
    2603             :           &reject_promise, &var_exception);
    2604             : 
    2605             :       // Let nextValue be IteratorValue(next).
    2606             :       // If nextValue is an abrupt completion, set iteratorRecord.[[Done]] to
    2607             :       //     true.
    2608             :       // ReturnIfAbrupt(nextValue).
    2609             :       Node* const next_value =
    2610             :           iter_assembler.IteratorValue(context, next, fast_iterator_result_map,
    2611          56 :                                        &reject_promise, &var_exception);
    2612             : 
    2613             :       // Let nextPromise be ? Invoke(constructor, "resolve", « nextValue »).
    2614             :       Node* const next_promise =
    2615             :           InvokeResolve(native_context, receiver, next_value, &close_iterator,
    2616          56 :                         &var_exception);
    2617             : 
    2618             :       // Perform ? Invoke(nextPromise, "then", « resolveElement,
    2619             :       //                  resultCapability.[[Reject]] »).
    2620             :       Node* const then =
    2621         168 :           GetProperty(context, next_promise, factory()->then_string());
    2622          56 :       GotoIfException(then, &close_iterator, &var_exception);
    2623             : 
    2624             :       Node* const then_call =
    2625         112 :           CallJS(CodeFactory::Call(isolate(),
    2626             :                                    ConvertReceiverMode::kNotNullOrUndefined),
    2627          56 :                  context, then, next_promise, resolve, reject);
    2628          56 :       GotoIfException(then_call, &close_iterator, &var_exception);
    2629             : 
    2630             :       // For catch prediction, mark that rejections here are semantically
    2631             :       // handled by the combined Promise.
    2632         168 :       SetPromiseHandledByIfTrue(context, IsDebugActive(), then_call, [=]() {
    2633             :         // Load promiseCapability.[[Promise]]
    2634          56 :         return LoadObjectField(capability, PromiseCapability::kPromiseOffset);
    2635         112 :       });
    2636          56 :       Goto(&loop);
    2637             :     }
    2638             : 
    2639          56 :     BIND(&break_loop);
    2640          56 :     Return(LoadObjectField(capability, PromiseCapability::kPromiseOffset));
    2641             :   }
    2642             : 
    2643          56 :   BIND(&close_iterator);
    2644             :   {
    2645             :     CSA_ASSERT(this, IsNotTheHole(var_exception.value()));
    2646             :     iter_assembler.IteratorCloseOnException(context, iterator, &reject_promise,
    2647          56 :                                             &var_exception);
    2648             :   }
    2649             : 
    2650          56 :   BIND(&reject_promise);
    2651             :   {
    2652             :     Node* const reject =
    2653             :         LoadObjectField(capability, PromiseCapability::kRejectOffset);
    2654         168 :     CallJS(CodeFactory::Call(isolate(), ConvertReceiverMode::kNullOrUndefined),
    2655         168 :            context, reject, UndefinedConstant(), var_exception.value());
    2656             : 
    2657             :     Node* const promise =
    2658             :         LoadObjectField(capability, PromiseCapability::kPromiseOffset);
    2659          56 :     Return(promise);
    2660             :   }
    2661          56 : }
    2662             : 
    2663             : }  // namespace internal
    2664       59480 : }  // namespace v8

Generated by: LCOV version 1.10