LCOV - code coverage report
Current view: top level - src/builtins - builtins-promise-gen.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 916 924 99.1 %
Date: 2019-01-20 Functions: 98 100 98.0 %

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

Generated by: LCOV version 1.10