LCOV - code coverage report
Current view: top level - src/builtins - builtins-promise-gen.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 1066 1076 99.1 %
Date: 2019-02-19 Functions: 185 187 98.9 %

          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         864 : Node* PromiseBuiltinsAssembler::AllocateJSPromise(Node* context) {
      25         864 :   Node* const native_context = LoadNativeContext(context);
      26             :   Node* const promise_fun =
      27         864 :       LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX);
      28             :   CSA_ASSERT(this, IsFunctionWithPrototypeSlotMap(LoadMap(promise_fun)));
      29             :   Node* const promise_map =
      30         864 :       LoadObjectField(promise_fun, JSFunction::kPrototypeOrInitialMapOffset);
      31         864 :   Node* const promise = Allocate(JSPromise::kSizeWithEmbedderFields);
      32         864 :   StoreMapNoWriteBarrier(promise, promise_map);
      33             :   StoreObjectFieldRoot(promise, JSPromise::kPropertiesOrHashOffset,
      34         864 :                        RootIndex::kEmptyFixedArray);
      35             :   StoreObjectFieldRoot(promise, JSPromise::kElementsOffset,
      36         864 :                        RootIndex::kEmptyFixedArray);
      37         864 :   return promise;
      38             : }
      39             : 
      40        1252 : void PromiseBuiltinsAssembler::PromiseInit(Node* promise) {
      41             :   STATIC_ASSERT(v8::Promise::kPending == 0);
      42             :   StoreObjectFieldNoWriteBarrier(promise, JSPromise::kReactionsOrResultOffset,
      43        1252 :                                  SmiConstant(Smi::zero()));
      44             :   StoreObjectFieldNoWriteBarrier(promise, JSPromise::kFlagsOffset,
      45        1252 :                                  SmiConstant(Smi::zero()));
      46        1252 :   for (int offset = JSPromise::kSize;
      47             :        offset < JSPromise::kSizeWithEmbedderFields; offset += kTaggedSize) {
      48           0 :     StoreObjectFieldNoWriteBarrier(promise, offset, SmiConstant(Smi::zero()));
      49             :   }
      50        1252 : }
      51             : 
      52         620 : Node* PromiseBuiltinsAssembler::AllocateAndInitJSPromise(Node* context) {
      53         620 :   return AllocateAndInitJSPromise(context, UndefinedConstant());
      54             : }
      55             : 
      56         804 : Node* PromiseBuiltinsAssembler::AllocateAndInitJSPromise(Node* context,
      57             :                                                          Node* parent) {
      58         804 :   Node* const instance = AllocateJSPromise(context);
      59         804 :   PromiseInit(instance);
      60             : 
      61         804 :   Label out(this);
      62         804 :   GotoIfNot(IsPromiseHookEnabledOrHasAsyncEventDelegate(), &out);
      63         804 :   CallRuntime(Runtime::kPromiseHookInit, context, instance, parent);
      64         804 :   Goto(&out);
      65             : 
      66         804 :   BIND(&out);
      67         804 :   return instance;
      68             : }
      69             : 
      70          60 : Node* PromiseBuiltinsAssembler::AllocateAndSetJSPromise(
      71             :     Node* context, v8::Promise::PromiseState status, Node* result) {
      72             :   DCHECK_NE(Promise::kPending, status);
      73             : 
      74          60 :   Node* const instance = AllocateJSPromise(context);
      75             :   StoreObjectFieldNoWriteBarrier(instance, JSPromise::kReactionsOrResultOffset,
      76          60 :                                  result);
      77             :   STATIC_ASSERT(JSPromise::kStatusShift == 0);
      78             :   StoreObjectFieldNoWriteBarrier(instance, JSPromise::kFlagsOffset,
      79          60 :                                  SmiConstant(status));
      80          60 :   for (int offset = JSPromise::kSize;
      81             :        offset < JSPromise::kSizeWithEmbedderFields; offset += kTaggedSize) {
      82           0 :     StoreObjectFieldNoWriteBarrier(instance, offset, SmiConstant(0));
      83             :   }
      84             : 
      85          60 :   Label out(this);
      86          60 :   GotoIfNot(IsPromiseHookEnabledOrHasAsyncEventDelegate(), &out);
      87             :   CallRuntime(Runtime::kPromiseHookInit, context, instance,
      88          60 :               UndefinedConstant());
      89          60 :   Goto(&out);
      90             : 
      91          60 :   BIND(&out);
      92          60 :   return instance;
      93             : }
      94             : 
      95             : std::pair<Node*, Node*>
      96         172 : PromiseBuiltinsAssembler::CreatePromiseResolvingFunctions(
      97             :     Node* promise, Node* debug_event, Node* native_context) {
      98             :   Node* const promise_context = CreatePromiseResolvingFunctionsContext(
      99         172 :       promise, debug_event, native_context);
     100             :   Node* const map = LoadContextElement(
     101         172 :       native_context, Context::STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX);
     102             :   Node* const resolve_info = LoadContextElement(
     103             :       native_context,
     104         172 :       Context::PROMISE_CAPABILITY_DEFAULT_RESOLVE_SHARED_FUN_INDEX);
     105             :   Node* const resolve =
     106         172 :       AllocateFunctionWithMapAndContext(map, resolve_info, promise_context);
     107             :   Node* const reject_info = LoadContextElement(
     108             :       native_context,
     109         172 :       Context::PROMISE_CAPABILITY_DEFAULT_REJECT_SHARED_FUN_INDEX);
     110             :   Node* const reject =
     111         172 :       AllocateFunctionWithMapAndContext(map, reject_info, promise_context);
     112         172 :   return std::make_pair(resolve, reject);
     113             : }
     114             : 
     115             : // ES #sec-newpromisecapability
     116         392 : TF_BUILTIN(NewPromiseCapability, PromiseBuiltinsAssembler) {
     117          56 :   Node* const context = Parameter(Descriptor::kContext);
     118          56 :   Node* const constructor = Parameter(Descriptor::kConstructor);
     119          56 :   Node* const debug_event = Parameter(Descriptor::kDebugEvent);
     120          56 :   TNode<Context> const native_context = LoadNativeContext(context);
     121             : 
     122          56 :   Label if_not_constructor(this, Label::kDeferred),
     123         112 :       if_notcallable(this, Label::kDeferred), if_fast_promise_capability(this),
     124         112 :       if_slow_promise_capability(this, Label::kDeferred);
     125          56 :   GotoIf(TaggedIsSmi(constructor), &if_not_constructor);
     126          56 :   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          56 :         AllocateAndInitJSPromise(native_context, UndefinedConstant());
     136             : 
     137          56 :     Node* resolve = nullptr;
     138          56 :     Node* reject = nullptr;
     139         112 :     std::tie(resolve, reject) =
     140         112 :         CreatePromiseResolvingFunctions(promise, debug_event, native_context);
     141             : 
     142          56 :     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          56 :     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          56 :         native_context, Context::PROMISE_GET_CAPABILITIES_EXECUTOR_SHARED_FUN);
     168             :     Node* function_map = LoadContextElement(
     169          56 :         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          56 :     Node* promise = Construct(native_context, CAST(constructor), executor);
     174          56 :     StoreObjectField(capability, PromiseCapability::kPromiseOffset, promise);
     175             : 
     176             :     Node* resolve =
     177          56 :         LoadObjectField(capability, PromiseCapability::kResolveOffset);
     178          56 :     GotoIf(TaggedIsSmi(resolve), &if_notcallable);
     179          56 :     GotoIfNot(IsCallable(resolve), &if_notcallable);
     180             : 
     181             :     Node* reject =
     182          56 :         LoadObjectField(capability, PromiseCapability::kRejectOffset);
     183          56 :     GotoIf(TaggedIsSmi(reject), &if_notcallable);
     184          56 :     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         632 : Node* PromiseBuiltinsAssembler::CreatePromiseContext(Node* native_context,
     196             :                                                      int slots) {
     197             :   DCHECK_GE(slots, Context::MIN_CONTEXT_SLOTS);
     198             : 
     199         632 :   Node* const context = AllocateInNewSpace(FixedArray::SizeFor(slots));
     200         632 :   InitializeFunctionContext(native_context, context, slots);
     201         632 :   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          56 :       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          56 :       native_context, Context::STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX);
     238             :   Node* const resolve_info = LoadContextElement(
     239          56 :       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         180 : Node* PromiseBuiltinsAssembler::CreatePromiseResolvingFunctionsContext(
     251             :     Node* promise, Node* debug_event, Node* native_context) {
     252             :   Node* const context = CreatePromiseContext(
     253         180 :       native_context, PromiseBuiltins::kPromiseContextLength);
     254             :   StoreContextElementNoWriteBarrier(context, PromiseBuiltins::kPromiseSlot,
     255         180 :                                     promise);
     256             :   StoreContextElementNoWriteBarrier(
     257         180 :       context, PromiseBuiltins::kAlreadyResolvedSlot, FalseConstant());
     258             :   StoreContextElementNoWriteBarrier(context, PromiseBuiltins::kDebugEventSlot,
     259         180 :                                     debug_event);
     260         180 :   return context;
     261             : }
     262             : 
     263          60 : Node* PromiseBuiltinsAssembler::CreatePromiseGetCapabilitiesExecutorContext(
     264             :     Node* promise_capability, Node* native_context) {
     265          60 :   int kContextLength = PromiseBuiltins::kCapabilitiesContextLength;
     266          60 :   Node* context = CreatePromiseContext(native_context, kContextLength);
     267             :   StoreContextElementNoWriteBarrier(context, PromiseBuiltins::kCapabilitySlot,
     268          60 :                                     promise_capability);
     269          60 :   return context;
     270             : }
     271             : 
     272         228 : Node* PromiseBuiltinsAssembler::PromiseHasHandler(Node* promise) {
     273         228 :   Node* const flags = LoadObjectField(promise, JSPromise::kFlagsOffset);
     274         228 :   return IsSetWord(SmiUntag(flags), 1 << JSPromise::kHasHandlerBit);
     275             : }
     276             : 
     277         168 : void PromiseBuiltinsAssembler::PromiseSetHasHandler(Node* promise) {
     278             :   TNode<Smi> const flags =
     279         168 :       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         448 : Node* PromiseBuiltinsAssembler::IsPromiseStatus(
     286             :     Node* actual, v8::Promise::PromiseState expected) {
     287         448 :   return Word32Equal(actual, Int32Constant(expected));
     288             : }
     289             : 
     290         280 : Node* PromiseBuiltinsAssembler::PromiseStatus(Node* promise) {
     291             :   STATIC_ASSERT(JSPromise::kStatusShift == 0);
     292             :   TNode<Smi> const flags =
     293         280 :       CAST(LoadObjectField(promise, JSPromise::kFlagsOffset));
     294         280 :   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         112 :   TNode<Smi> mask = SmiConstant(status);
     304             :   TNode<Smi> const flags =
     305         112 :       CAST(LoadObjectField(promise, JSPromise::kFlagsOffset));
     306             :   StoreObjectFieldNoWriteBarrier(promise, JSPromise::kFlagsOffset,
     307         112 :                                  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         168 :          &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         168 :         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         336 :     Label if_fulfilled(this), if_rejected(this, Label::kDeferred),
     359         336 :         enqueue(this);
     360             :     Branch(IsPromiseStatus(status, v8::Promise::kFulfilled), &if_fulfilled,
     361         168 :            &if_rejected);
     362             : 
     363         168 :     BIND(&if_fulfilled);
     364             :     {
     365         168 :       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         168 :       var_map.Bind(LoadRoot(RootIndex::kPromiseRejectReactionJobTaskMap));
     374         168 :       var_handler.Bind(on_rejected);
     375         168 :       GotoIf(PromiseHasHandler(promise), &enqueue);
     376         168 :       CallRuntime(Runtime::kPromiseRevokeReject, context, promise);
     377         168 :       Goto(&enqueue);
     378             :     }
     379             : 
     380         168 :     BIND(&enqueue);
     381             :     Node* argument =
     382         168 :         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         504 : TF_BUILTIN(PerformPromiseThen, PromiseBuiltinsAssembler) {
     396          56 :   Node* const context = Parameter(Descriptor::kContext);
     397          56 :   Node* const promise = Parameter(Descriptor::kPromise);
     398          56 :   Node* const on_fulfilled = Parameter(Descriptor::kOnFulfilled);
     399          56 :   Node* const on_rejected = Parameter(Descriptor::kOnRejected);
     400          56 :   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         168 :   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         168 :   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          56 :   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         224 :     VARIABLE(var_reversed, MachineRepresentation::kTagged,
     480             :              SmiConstant(Smi::zero()));
     481             : 
     482         224 :     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         112 :       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         224 :     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         112 :       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          56 :             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         112 :   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         448 :   Label if_fast(this), if_slow(this, Label::kDeferred), done(this, &var_result);
     562         224 :   GotoIf(TaggedIsSmi(receiver), &if_slow);
     563         224 :   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         224 :         LoadContextElement(native_context, Context::PROMISE_THEN_INDEX);
     575             :     Node* const result =
     576             :         CallJS(CodeFactory::CallFunction(
     577             :                    isolate(), ConvertReceiverMode::kNotNullOrUndefined),
     578         224 :                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         448 :                                    isolate()->factory()->then_string());
     587             :     Node* const result = CallJS(
     588             :         CodeFactory::Call(isolate(), ConvertReceiverMode::kNotNullOrUndefined),
     589         224 :         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         224 :   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         112 :                                      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         224 :         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         112 :         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         168 :       LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX);
     649         168 :   GotoIfNot(WordEqual(promise_fun, constructor), if_slow);
     650         168 :   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         168 :       LoadContextElement(native_context, Context::PROMISE_PROTOTYPE_INDEX);
     668         168 :   GotoIfForceSlowPath(if_slow);
     669         336 :   GotoIfNot(WordEqual(LoadMapPrototype(promise_map), promise_prototype),
     670         168 :             if_slow);
     671         168 :   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         280 :   GotoIfNot(IsJSPromiseMap(receiver_map), if_slow);
     681             :   Node* const promise_prototype =
     682         280 :       LoadContextElement(native_context, Context::PROMISE_PROTOTYPE_INDEX);
     683         560 :   GotoIfNot(WordEqual(LoadMapPrototype(receiver_map), promise_prototype),
     684         280 :             if_slow);
     685         280 :   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         112 :   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         112 :   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          56 :     Node* executor_type = LoadInstanceType(var_executor.value());
     702          56 :     GotoIf(InstanceTypeEqual(executor_type, JS_FUNCTION_TYPE), &found_function);
     703         112 :     GotoIfNot(InstanceTypeEqual(executor_type, JS_BOUND_FUNCTION_TYPE),
     704          56 :               &call_runtime);
     705             :     var_executor.Bind(LoadObjectField(
     706          56 :         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          56 :     Node* native_function_context = LoadNativeContext(function_context);
     718         112 :     Branch(WordEqual(native_context, native_function_context), &has_access,
     719          56 :            &call_runtime);
     720             :   }
     721             : 
     722          56 :   BIND(&call_runtime);
     723             :   {
     724             :     Branch(WordEqual(CallRuntime(Runtime::kAllowDynamicFunction, context,
     725             :                                  promise_constructor),
     726         112 :                      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         224 :       CAST(context), CAST(object()),
     739         112 :       HeapConstant(factory()->promise_forwarding_handler_symbol()),
     740         448 :       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         112 :   GotoIf(TaggedIsSmi(promise), &done);
     751         112 :   GotoIfNot(HasInstanceType(promise, JS_PROMISE_TYPE), &done);
     752         224 :   SetPropertyStrict(CAST(context), CAST(promise),
     753         112 :                     HeapConstant(factory()->promise_handled_by_symbol()),
     754         448 :                     CAST(handled_by()));
     755         112 :   Goto(&done);
     756         112 :   BIND(&done);
     757         112 : }
     758             : 
     759             : // ES #sec-promise-reject-functions
     760         336 : TF_BUILTIN(PromiseCapabilityDefaultReject, PromiseBuiltinsAssembler) {
     761          56 :   Node* const reason = Parameter(Descriptor::kReason);
     762          56 :   Node* const context = Parameter(Descriptor::kContext);
     763             : 
     764             :   // 2. Let promise be F.[[Promise]].
     765             :   Node* const promise =
     766          56 :       LoadContextElement(context, PromiseBuiltins::kPromiseSlot);
     767             : 
     768             :   // 3. Let alreadyResolved be F.[[AlreadyResolved]].
     769          56 :   Label if_already_resolved(this, Label::kDeferred);
     770             :   Node* const already_resolved =
     771          56 :       LoadContextElement(context, PromiseBuiltins::kAlreadyResolvedSlot);
     772             : 
     773             :   // 4. If alreadyResolved.[[Value]] is true, return undefined.
     774          56 :   GotoIf(IsTrue(already_resolved), &if_already_resolved);
     775             : 
     776             :   // 5. Set alreadyResolved.[[Value]] to true.
     777             :   StoreContextElementNoWriteBarrier(
     778          56 :       context, PromiseBuiltins::kAlreadyResolvedSlot, TrueConstant());
     779             : 
     780             :   // 6. Return RejectPromise(promise, reason).
     781             :   Node* const debug_event =
     782          56 :       LoadContextElement(context, PromiseBuiltins::kDebugEventSlot);
     783             :   Return(CallBuiltin(Builtins::kRejectPromise, context, promise, reason,
     784          56 :                      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         336 : TF_BUILTIN(PromiseCapabilityDefaultResolve, PromiseBuiltinsAssembler) {
     795          56 :   Node* const resolution = Parameter(Descriptor::kResolution);
     796          56 :   Node* const context = Parameter(Descriptor::kContext);
     797             : 
     798             :   // 2. Let promise be F.[[Promise]].
     799             :   Node* const promise =
     800          56 :       LoadContextElement(context, PromiseBuiltins::kPromiseSlot);
     801             : 
     802             :   // 3. Let alreadyResolved be F.[[AlreadyResolved]].
     803          56 :   Label if_already_resolved(this, Label::kDeferred);
     804             :   Node* const already_resolved =
     805          56 :       LoadContextElement(context, PromiseBuiltins::kAlreadyResolvedSlot);
     806             : 
     807             :   // 4. If alreadyResolved.[[Value]] is true, return undefined.
     808          56 :   GotoIf(IsTrue(already_resolved), &if_already_resolved);
     809             : 
     810             :   // 5. Set alreadyResolved.[[Value]] to true.
     811             :   StoreContextElementNoWriteBarrier(
     812          56 :       context, PromiseBuiltins::kAlreadyResolvedSlot, TrueConstant());
     813             : 
     814             :   // The rest of the logic (and the catch prediction) is
     815             :   // encapsulated in the dedicated ResolvePromise builtin.
     816          56 :   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         448 : TF_BUILTIN(PromiseConstructorLazyDeoptContinuation, PromiseBuiltinsAssembler) {
     826          56 :   Node* promise = Parameter(Descriptor::kPromise);
     827          56 :   Node* reject = Parameter(Descriptor::kReject);
     828          56 :   Node* exception = Parameter(Descriptor::kException);
     829          56 :   Node* const context = Parameter(Descriptor::kContext);
     830             : 
     831          56 :   Label finally(this);
     832             : 
     833          56 :   GotoIf(IsTheHole(exception), &finally);
     834             :   CallJS(CodeFactory::Call(isolate(), ConvertReceiverMode::kNotNullOrUndefined),
     835          56 :          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         392 : TF_BUILTIN(PromiseConstructor, PromiseBuiltinsAssembler) {
     844          56 :   Node* const executor = Parameter(Descriptor::kExecutor);
     845          56 :   Node* const new_target = Parameter(Descriptor::kJSNewTarget);
     846          56 :   Node* const context = Parameter(Descriptor::kContext);
     847          56 :   Isolate* isolate = this->isolate();
     848             : 
     849          56 :   Label if_targetisundefined(this, Label::kDeferred);
     850             : 
     851          56 :   GotoIf(IsUndefined(new_target), &if_targetisundefined);
     852             : 
     853         112 :   Label if_notcallable(this, Label::kDeferred);
     854             : 
     855          56 :   GotoIf(TaggedIsSmi(executor), &if_notcallable);
     856             : 
     857          56 :   Node* const executor_map = LoadMap(executor);
     858          56 :   GotoIfNot(IsCallableMap(executor_map), &if_notcallable);
     859             : 
     860          56 :   Node* const native_context = LoadNativeContext(context);
     861             :   Node* const promise_fun =
     862          56 :       LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX);
     863          56 :   Node* const is_debug_active = IsDebugActive();
     864         112 :   Label if_targetisnotmodified(this),
     865         112 :       if_targetismodified(this, Label::kDeferred), run_executor(this),
     866         112 :       debug_push(this), if_noaccess(this, Label::kDeferred);
     867             : 
     868             :   BranchIfAccessCheckFailed(context, native_context, promise_fun, executor,
     869          56 :                             &if_noaccess);
     870             : 
     871         112 :   Branch(WordEqual(promise_fun, new_target), &if_targetisnotmodified,
     872          56 :          &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          56 :     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          56 :     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         112 :     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          56 :         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          56 :              context, reject, UndefinedConstant(), var_reason.value());
     925          56 :       Branch(is_debug_active, &debug_pop, &out);
     926             :     }
     927             : 
     928          56 :     BIND(&debug_pop);
     929             :     {
     930          56 :       CallRuntime(Runtime::kDebugPopPromise, context);
     931          56 :       Goto(&out);
     932             :     }
     933          56 :     BIND(&out);
     934         112 :     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          56 :         SmiConstant(v8::Isolate::kPromiseConstructorReturnedUndefined);
     950          56 :     CallRuntime(Runtime::kIncrementUseCounter, context, counter_id);
     951          56 :     Return(UndefinedConstant());
     952          56 :   }
     953          56 : }
     954             : 
     955             : // V8 Extras: v8.createPromise(parent)
     956         336 : TF_BUILTIN(PromiseInternalConstructor, PromiseBuiltinsAssembler) {
     957          56 :   Node* const parent = Parameter(Descriptor::kParent);
     958          56 :   Node* const context = Parameter(Descriptor::kContext);
     959          56 :   Return(AllocateAndInitJSPromise(context, parent));
     960          56 : }
     961             : 
     962             : // V8 Extras: v8.rejectPromise(promise, reason)
     963         392 : TF_BUILTIN(PromiseInternalReject, PromiseBuiltinsAssembler) {
     964          56 :   Node* const promise = Parameter(Descriptor::kPromise);
     965          56 :   Node* const reason = Parameter(Descriptor::kReason);
     966          56 :   Node* const context = Parameter(Descriptor::kContext);
     967             : 
     968             :   // Main V8 Extras invariant that {promise} is still "pending" at
     969             :   // this point, aka that {promise} is not resolved multiple times.
     970          56 :   Label if_promise_is_settled(this, Label::kDeferred);
     971             :   GotoIfNot(IsPromiseStatus(PromiseStatus(promise), v8::Promise::kPending),
     972          56 :             &if_promise_is_settled);
     973             : 
     974             :   // We pass true to trigger the debugger's on exception handler.
     975             :   Return(CallBuiltin(Builtins::kRejectPromise, context, promise, reason,
     976          56 :                      TrueConstant()));
     977             : 
     978          56 :   BIND(&if_promise_is_settled);
     979          56 :   Abort(AbortReason::kPromiseAlreadySettled);
     980          56 : }
     981             : 
     982             : // V8 Extras: v8.resolvePromise(promise, resolution)
     983         392 : TF_BUILTIN(PromiseInternalResolve, PromiseBuiltinsAssembler) {
     984          56 :   Node* const promise = Parameter(Descriptor::kPromise);
     985          56 :   Node* const resolution = Parameter(Descriptor::kResolution);
     986          56 :   Node* const context = Parameter(Descriptor::kContext);
     987             : 
     988             :   // Main V8 Extras invariant that {promise} is still "pending" at
     989             :   // this point, aka that {promise} is not resolved multiple times.
     990          56 :   Label if_promise_is_settled(this, Label::kDeferred);
     991             :   GotoIfNot(IsPromiseStatus(PromiseStatus(promise), v8::Promise::kPending),
     992          56 :             &if_promise_is_settled);
     993             : 
     994          56 :   Return(CallBuiltin(Builtins::kResolvePromise, context, promise, resolution));
     995             : 
     996          56 :   BIND(&if_promise_is_settled);
     997          56 :   Abort(AbortReason::kPromiseAlreadySettled);
     998          56 : }
     999             : 
    1000             : // ES#sec-promise.prototype.then
    1001             : // Promise.prototype.then ( onFulfilled, onRejected )
    1002         448 : TF_BUILTIN(PromisePrototypeThen, PromiseBuiltinsAssembler) {
    1003             :   // 1. Let promise be the this value.
    1004          56 :   Node* const promise = Parameter(Descriptor::kReceiver);
    1005          56 :   Node* const on_fulfilled = Parameter(Descriptor::kOnFulfilled);
    1006          56 :   Node* const on_rejected = Parameter(Descriptor::kOnRejected);
    1007          56 :   Node* const context = Parameter(Descriptor::kContext);
    1008             : 
    1009             :   // 2. If IsPromise(promise) is false, throw a TypeError exception.
    1010             :   ThrowIfNotInstanceType(context, promise, JS_PROMISE_TYPE,
    1011          56 :                          "Promise.prototype.then");
    1012             : 
    1013             :   // 3. Let C be ? SpeciesConstructor(promise, %Promise%).
    1014         112 :   Label fast_promise_capability(this), slow_constructor(this, Label::kDeferred),
    1015         112 :       slow_promise_capability(this, Label::kDeferred);
    1016          56 :   Node* const native_context = LoadNativeContext(context);
    1017             :   Node* const promise_fun =
    1018          56 :       LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX);
    1019          56 :   Node* const promise_map = LoadMap(promise);
    1020             :   BranchIfPromiseSpeciesLookupChainIntact(
    1021          56 :       native_context, promise_map, &fast_promise_capability, &slow_constructor);
    1022             : 
    1023          56 :   BIND(&slow_constructor);
    1024             :   Node* const constructor =
    1025          56 :       SpeciesConstructor(native_context, promise, promise_fun);
    1026         112 :   Branch(WordEqual(constructor, promise_fun), &fast_promise_capability,
    1027          56 :          &slow_promise_capability);
    1028             : 
    1029             :   // 4. Let resultCapability be ? NewPromiseCapability(C).
    1030         112 :   Label perform_promise_then(this);
    1031         112 :   VARIABLE(var_result_promise, MachineRepresentation::kTagged);
    1032         112 :   VARIABLE(var_result_promise_or_capability, MachineRepresentation::kTagged);
    1033             : 
    1034          56 :   BIND(&fast_promise_capability);
    1035             :   {
    1036          56 :     Node* const result_promise = AllocateAndInitJSPromise(context, promise);
    1037          56 :     var_result_promise_or_capability.Bind(result_promise);
    1038          56 :     var_result_promise.Bind(result_promise);
    1039          56 :     Goto(&perform_promise_then);
    1040             :   }
    1041             : 
    1042          56 :   BIND(&slow_promise_capability);
    1043             :   {
    1044          56 :     Node* const debug_event = TrueConstant();
    1045             :     Node* const capability = CallBuiltin(Builtins::kNewPromiseCapability,
    1046          56 :                                          context, constructor, debug_event);
    1047             :     var_result_promise.Bind(
    1048          56 :         LoadObjectField(capability, PromiseCapability::kPromiseOffset));
    1049          56 :     var_result_promise_or_capability.Bind(capability);
    1050          56 :     Goto(&perform_promise_then);
    1051             :   }
    1052             : 
    1053             :   // 5. Return PerformPromiseThen(promise, onFulfilled, onRejected,
    1054             :   //    resultCapability).
    1055          56 :   BIND(&perform_promise_then);
    1056             :   {
    1057             :     // We do some work of the PerformPromiseThen operation here, in that
    1058             :     // we check the handlers and turn non-callable handlers into undefined.
    1059             :     // This is because this is the one and only callsite of PerformPromiseThen
    1060             :     // that has to do this.
    1061             : 
    1062             :     // 3. If IsCallable(onFulfilled) is false, then
    1063             :     //    a. Set onFulfilled to undefined.
    1064          56 :     VARIABLE(var_on_fulfilled, MachineRepresentation::kTagged, on_fulfilled);
    1065         112 :     Label if_fulfilled_done(this), if_fulfilled_notcallable(this);
    1066          56 :     GotoIf(TaggedIsSmi(on_fulfilled), &if_fulfilled_notcallable);
    1067         112 :     Branch(IsCallable(on_fulfilled), &if_fulfilled_done,
    1068          56 :            &if_fulfilled_notcallable);
    1069          56 :     BIND(&if_fulfilled_notcallable);
    1070          56 :     var_on_fulfilled.Bind(UndefinedConstant());
    1071          56 :     Goto(&if_fulfilled_done);
    1072          56 :     BIND(&if_fulfilled_done);
    1073             : 
    1074             :     // 4. If IsCallable(onRejected) is false, then
    1075             :     //    a. Set onRejected to undefined.
    1076         112 :     VARIABLE(var_on_rejected, MachineRepresentation::kTagged, on_rejected);
    1077         112 :     Label if_rejected_done(this), if_rejected_notcallable(this);
    1078          56 :     GotoIf(TaggedIsSmi(on_rejected), &if_rejected_notcallable);
    1079         112 :     Branch(IsCallable(on_rejected), &if_rejected_done,
    1080          56 :            &if_rejected_notcallable);
    1081          56 :     BIND(&if_rejected_notcallable);
    1082          56 :     var_on_rejected.Bind(UndefinedConstant());
    1083          56 :     Goto(&if_rejected_done);
    1084          56 :     BIND(&if_rejected_done);
    1085             : 
    1086             :     PerformPromiseThen(context, promise, var_on_fulfilled.value(),
    1087             :                        var_on_rejected.value(),
    1088          56 :                        var_result_promise_or_capability.value());
    1089         112 :     Return(var_result_promise.value());
    1090          56 :   }
    1091          56 : }
    1092             : 
    1093             : // ES#sec-promise.prototype.catch
    1094             : // Promise.prototype.catch ( onRejected )
    1095         392 : TF_BUILTIN(PromisePrototypeCatch, PromiseBuiltinsAssembler) {
    1096             :   // 1. Let promise be the this value.
    1097          56 :   Node* const receiver = Parameter(Descriptor::kReceiver);
    1098          56 :   Node* const on_fulfilled = UndefinedConstant();
    1099          56 :   Node* const on_rejected = Parameter(Descriptor::kOnRejected);
    1100          56 :   Node* const context = Parameter(Descriptor::kContext);
    1101             : 
    1102             :   // 2. Return ? Invoke(promise, "then", « undefined, onRejected »).
    1103          56 :   Node* const native_context = LoadNativeContext(context);
    1104          56 :   Return(InvokeThen(native_context, receiver, on_fulfilled, on_rejected));
    1105          56 : }
    1106             : 
    1107             : // ES #sec-promiseresolvethenablejob
    1108         448 : TF_BUILTIN(PromiseResolveThenableJob, PromiseBuiltinsAssembler) {
    1109          56 :   Node* const native_context = Parameter(Descriptor::kContext);
    1110          56 :   Node* const promise_to_resolve = Parameter(Descriptor::kPromiseToResolve);
    1111          56 :   Node* const thenable = Parameter(Descriptor::kThenable);
    1112          56 :   Node* const then = Parameter(Descriptor::kThen);
    1113             : 
    1114             :   CSA_ASSERT(this, TaggedIsNotSmi(thenable));
    1115             :   CSA_ASSERT(this, IsJSReceiver(thenable));
    1116             :   CSA_ASSERT(this, IsJSPromise(promise_to_resolve));
    1117             :   CSA_ASSERT(this, IsNativeContext(native_context));
    1118             : 
    1119             :   // We can use a simple optimization here if we know that {then} is the initial
    1120             :   // Promise.prototype.then method, and {thenable} is a JSPromise whose
    1121             :   // @@species lookup chain is intact: We can connect {thenable} and
    1122             :   // {promise_to_resolve} directly in that case and avoid the allocation of a
    1123             :   // temporary JSPromise and the closures plus context.
    1124             :   //
    1125             :   // We take the generic (slow-)path if a PromiseHook is enabled or the debugger
    1126             :   // is active, to make sure we expose spec compliant behavior.
    1127         112 :   Label if_fast(this), if_slow(this, Label::kDeferred);
    1128             :   Node* const promise_then =
    1129          56 :       LoadContextElement(native_context, Context::PROMISE_THEN_INDEX);
    1130          56 :   GotoIfNot(WordEqual(then, promise_then), &if_slow);
    1131          56 :   Node* const thenable_map = LoadMap(thenable);
    1132          56 :   GotoIfNot(IsJSPromiseMap(thenable_map), &if_slow);
    1133             :   GotoIf(IsPromiseHookEnabledOrDebugIsActiveOrHasAsyncEventDelegate(),
    1134          56 :          &if_slow);
    1135             :   BranchIfPromiseSpeciesLookupChainIntact(native_context, thenable_map,
    1136          56 :                                           &if_fast, &if_slow);
    1137             : 
    1138          56 :   BIND(&if_fast);
    1139             :   {
    1140             :     // We know that the {thenable} is a JSPromise, which doesn't require
    1141             :     // any special treatment and that {then} corresponds to the initial
    1142             :     // Promise.prototype.then method. So instead of allocating a temporary
    1143             :     // JSPromise to connect the {thenable} with the {promise_to_resolve},
    1144             :     // we can directly schedule the {promise_to_resolve} with default
    1145             :     // handlers onto the {thenable} promise. This does not only save the
    1146             :     // JSPromise allocation, but also avoids the allocation of the two
    1147             :     // resolving closures and the shared context.
    1148             :     //
    1149             :     // What happens normally in this case is
    1150             :     //
    1151             :     //   resolve, reject = CreateResolvingFunctions(promise_to_resolve)
    1152             :     //   result_capability = NewPromiseCapability(%Promise%)
    1153             :     //   PerformPromiseThen(thenable, resolve, reject, result_capability)
    1154             :     //
    1155             :     // which means that PerformPromiseThen will either schedule a new
    1156             :     // PromiseReaction with resolve and reject or a PromiseReactionJob
    1157             :     // with resolve or reject based on the state of {thenable}. And
    1158             :     // resolve or reject will just invoke the default [[Resolve]] or
    1159             :     // [[Reject]] functions on the {promise_to_resolve}.
    1160             :     //
    1161             :     // This is the same as just doing
    1162             :     //
    1163             :     //   PerformPromiseThen(thenable, undefined, undefined, promise_to_resolve)
    1164             :     //
    1165             :     // which performs exactly the same (observable) steps.
    1166             :     TailCallBuiltin(Builtins::kPerformPromiseThen, native_context, thenable,
    1167             :                     UndefinedConstant(), UndefinedConstant(),
    1168          56 :                     promise_to_resolve);
    1169             :   }
    1170             : 
    1171          56 :   BIND(&if_slow);
    1172             :   {
    1173          56 :     Node* resolve = nullptr;
    1174          56 :     Node* reject = nullptr;
    1175         112 :     std::tie(resolve, reject) = CreatePromiseResolvingFunctions(
    1176         168 :         promise_to_resolve, FalseConstant(), native_context);
    1177             : 
    1178          56 :     Label if_exception(this, Label::kDeferred);
    1179         112 :     VARIABLE(var_exception, MachineRepresentation::kTagged, TheHoleConstant());
    1180             :     Node* const result = CallJS(
    1181             :         CodeFactory::Call(isolate(), ConvertReceiverMode::kNotNullOrUndefined),
    1182          56 :         native_context, then, thenable, resolve, reject);
    1183          56 :     GotoIfException(result, &if_exception, &var_exception);
    1184          56 :     Return(result);
    1185             : 
    1186          56 :     BIND(&if_exception);
    1187             :     {
    1188             :       // We need to reject the {thenable}.
    1189             :       Node* const result = CallJS(
    1190             :           CodeFactory::Call(isolate(), ConvertReceiverMode::kNullOrUndefined),
    1191          56 :           native_context, reject, UndefinedConstant(), var_exception.value());
    1192          56 :       Return(result);
    1193          56 :     }
    1194          56 :   }
    1195          56 : }
    1196             : 
    1197             : // ES #sec-promisereactionjob
    1198         112 : void PromiseBuiltinsAssembler::PromiseReactionJob(Node* context, Node* argument,
    1199             :                                                   Node* handler,
    1200             :                                                   Node* promise_or_capability,
    1201             :                                                   PromiseReaction::Type type) {
    1202             :   CSA_ASSERT(this, TaggedIsNotSmi(handler));
    1203             :   CSA_ASSERT(this, Word32Or(IsUndefined(handler), IsCallable(handler)));
    1204             :   CSA_ASSERT(this, TaggedIsNotSmi(promise_or_capability));
    1205             :   CSA_ASSERT(this,
    1206             :              Word32Or(Word32Or(IsJSPromise(promise_or_capability),
    1207             :                                IsPromiseCapability(promise_or_capability)),
    1208             :                       IsUndefined(promise_or_capability)));
    1209             : 
    1210         112 :   VARIABLE(var_handler_result, MachineRepresentation::kTagged, argument);
    1211         224 :   Label if_handler_callable(this), if_fulfill(this), if_reject(this),
    1212         224 :       if_internal(this);
    1213         224 :   Branch(IsUndefined(handler),
    1214             :          type == PromiseReaction::kFulfill ? &if_fulfill : &if_reject,
    1215         224 :          &if_handler_callable);
    1216             : 
    1217         112 :   BIND(&if_handler_callable);
    1218             :   {
    1219             :     Node* const result = CallJS(
    1220             :         CodeFactory::Call(isolate(), ConvertReceiverMode::kNullOrUndefined),
    1221         112 :         context, handler, UndefinedConstant(), argument);
    1222         112 :     GotoIfException(result, &if_reject, &var_handler_result);
    1223         112 :     var_handler_result.Bind(result);
    1224         112 :     Branch(IsUndefined(promise_or_capability), &if_internal, &if_fulfill);
    1225             :   }
    1226             : 
    1227         112 :   BIND(&if_internal);
    1228             :   {
    1229             :     // There's no [[Capability]] for this promise reaction job, which
    1230             :     // means that this is a specification-internal operation (aka await)
    1231             :     // where the result does not matter (see the specification change in
    1232             :     // https://github.com/tc39/ecma262/pull/1146 for details).
    1233         112 :     Return(UndefinedConstant());
    1234             :   }
    1235             : 
    1236         112 :   BIND(&if_fulfill);
    1237             :   {
    1238         224 :     Label if_promise(this), if_promise_capability(this, Label::kDeferred);
    1239         112 :     Node* const value = var_handler_result.value();
    1240         224 :     Branch(IsPromiseCapability(promise_or_capability), &if_promise_capability,
    1241         112 :            &if_promise);
    1242             : 
    1243         112 :     BIND(&if_promise);
    1244             :     {
    1245             :       // For fast native promises we can skip the indirection
    1246             :       // via the promiseCapability.[[Resolve]] function and
    1247             :       // run the resolve logic directly from here.
    1248             :       TailCallBuiltin(Builtins::kResolvePromise, context, promise_or_capability,
    1249         112 :                       value);
    1250             :     }
    1251             : 
    1252         112 :     BIND(&if_promise_capability);
    1253             :     {
    1254             :       // In the general case we need to call the (user provided)
    1255             :       // promiseCapability.[[Resolve]] function.
    1256             :       Node* const resolve = LoadObjectField(promise_or_capability,
    1257         112 :                                             PromiseCapability::kResolveOffset);
    1258             :       Node* const result = CallJS(
    1259             :           CodeFactory::Call(isolate(), ConvertReceiverMode::kNullOrUndefined),
    1260         112 :           context, resolve, UndefinedConstant(), value);
    1261         112 :       GotoIfException(result, &if_reject, &var_handler_result);
    1262         112 :       Return(result);
    1263         112 :     }
    1264             :   }
    1265             : 
    1266         112 :   BIND(&if_reject);
    1267         112 :   if (type == PromiseReaction::kReject) {
    1268         112 :     Label if_promise(this), if_promise_capability(this, Label::kDeferred);
    1269          56 :     Node* const reason = var_handler_result.value();
    1270         112 :     Branch(IsPromiseCapability(promise_or_capability), &if_promise_capability,
    1271          56 :            &if_promise);
    1272             : 
    1273          56 :     BIND(&if_promise);
    1274             :     {
    1275             :       // For fast native promises we can skip the indirection
    1276             :       // via the promiseCapability.[[Reject]] function and
    1277             :       // run the resolve logic directly from here.
    1278             :       TailCallBuiltin(Builtins::kRejectPromise, context, promise_or_capability,
    1279          56 :                       reason, FalseConstant());
    1280             :     }
    1281             : 
    1282          56 :     BIND(&if_promise_capability);
    1283             :     {
    1284             :       // In the general case we need to call the (user provided)
    1285             :       // promiseCapability.[[Reject]] function.
    1286          56 :       Label if_exception(this, Label::kDeferred);
    1287         112 :       VARIABLE(var_exception, MachineRepresentation::kTagged,
    1288             :                TheHoleConstant());
    1289             :       Node* const reject = LoadObjectField(promise_or_capability,
    1290          56 :                                            PromiseCapability::kRejectOffset);
    1291             :       Node* const result = CallJS(
    1292             :           CodeFactory::Call(isolate(), ConvertReceiverMode::kNullOrUndefined),
    1293          56 :           context, reject, UndefinedConstant(), reason);
    1294          56 :       GotoIfException(result, &if_exception, &var_exception);
    1295          56 :       Return(result);
    1296             : 
    1297             :       // Swallow the exception here.
    1298          56 :       BIND(&if_exception);
    1299         112 :       TailCallRuntime(Runtime::kReportMessage, context, var_exception.value());
    1300          56 :     }
    1301             :   } else {
    1302             :     // We have to call out to the dedicated PromiseRejectReactionJob builtin
    1303             :     // here, instead of just doing the work inline, as otherwise the catch
    1304             :     // predictions in the debugger will be wrong, which just walks the stack
    1305             :     // and checks for certain builtins.
    1306             :     TailCallBuiltin(Builtins::kPromiseRejectReactionJob, context,
    1307             :                     var_handler_result.value(), UndefinedConstant(),
    1308          56 :                     promise_or_capability);
    1309         112 :   }
    1310         112 : }
    1311             : 
    1312             : // ES #sec-promisereactionjob
    1313         448 : TF_BUILTIN(PromiseFulfillReactionJob, PromiseBuiltinsAssembler) {
    1314          56 :   Node* const context = Parameter(Descriptor::kContext);
    1315          56 :   Node* const value = Parameter(Descriptor::kValue);
    1316          56 :   Node* const handler = Parameter(Descriptor::kHandler);
    1317             :   Node* const promise_or_capability =
    1318          56 :       Parameter(Descriptor::kPromiseOrCapability);
    1319             : 
    1320             :   PromiseReactionJob(context, value, handler, promise_or_capability,
    1321          56 :                      PromiseReaction::kFulfill);
    1322          56 : }
    1323             : 
    1324             : // ES #sec-promisereactionjob
    1325         448 : TF_BUILTIN(PromiseRejectReactionJob, PromiseBuiltinsAssembler) {
    1326          56 :   Node* const context = Parameter(Descriptor::kContext);
    1327          56 :   Node* const reason = Parameter(Descriptor::kReason);
    1328          56 :   Node* const handler = Parameter(Descriptor::kHandler);
    1329             :   Node* const promise_or_capability =
    1330          56 :       Parameter(Descriptor::kPromiseOrCapability);
    1331             : 
    1332             :   PromiseReactionJob(context, reason, handler, promise_or_capability,
    1333          56 :                      PromiseReaction::kReject);
    1334          56 : }
    1335             : 
    1336         392 : TF_BUILTIN(PromiseResolveTrampoline, PromiseBuiltinsAssembler) {
    1337             :   //  1. Let C be the this value.
    1338          56 :   Node* receiver = Parameter(Descriptor::kReceiver);
    1339          56 :   Node* value = Parameter(Descriptor::kValue);
    1340          56 :   Node* context = Parameter(Descriptor::kContext);
    1341             : 
    1342             :   // 2. If Type(C) is not Object, throw a TypeError exception.
    1343             :   ThrowIfNotJSReceiver(context, receiver, MessageTemplate::kCalledOnNonObject,
    1344          56 :                        "PromiseResolve");
    1345             : 
    1346             :   // 3. Return ? PromiseResolve(C, x).
    1347          56 :   Return(CallBuiltin(Builtins::kPromiseResolve, context, receiver, value));
    1348          56 : }
    1349             : 
    1350         392 : TF_BUILTIN(PromiseResolve, PromiseBuiltinsAssembler) {
    1351          56 :   Node* constructor = Parameter(Descriptor::kConstructor);
    1352          56 :   Node* value = Parameter(Descriptor::kValue);
    1353          56 :   Node* context = Parameter(Descriptor::kContext);
    1354             : 
    1355             :   CSA_ASSERT(this, IsJSReceiver(constructor));
    1356             : 
    1357          56 :   Node* const native_context = LoadNativeContext(context);
    1358             :   Node* const promise_fun =
    1359          56 :       LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX);
    1360             : 
    1361         112 :   Label if_slow_constructor(this, Label::kDeferred), if_need_to_allocate(this);
    1362             : 
    1363             :   // Check if {value} is a JSPromise.
    1364          56 :   GotoIf(TaggedIsSmi(value), &if_need_to_allocate);
    1365          56 :   Node* const value_map = LoadMap(value);
    1366          56 :   GotoIfNot(IsJSPromiseMap(value_map), &if_need_to_allocate);
    1367             : 
    1368             :   // We can skip the "constructor" lookup on {value} if it's [[Prototype]]
    1369             :   // is the (initial) Promise.prototype and the @@species protector is
    1370             :   // intact, as that guards the lookup path for "constructor" on
    1371             :   // JSPromise instances which have the (initial) Promise.prototype.
    1372             :   Node* const promise_prototype =
    1373          56 :       LoadContextElement(native_context, Context::PROMISE_PROTOTYPE_INDEX);
    1374         112 :   GotoIfNot(WordEqual(LoadMapPrototype(value_map), promise_prototype),
    1375          56 :             &if_slow_constructor);
    1376          56 :   GotoIf(IsPromiseSpeciesProtectorCellInvalid(), &if_slow_constructor);
    1377             : 
    1378             :   // If the {constructor} is the Promise function, we just immediately
    1379             :   // return the {value} here and don't bother wrapping it into a
    1380             :   // native Promise.
    1381          56 :   GotoIfNot(WordEqual(promise_fun, constructor), &if_slow_constructor);
    1382          56 :   Return(value);
    1383             : 
    1384             :   // At this point, value or/and constructor are not native promises, but
    1385             :   // they could be of the same subclass.
    1386          56 :   BIND(&if_slow_constructor);
    1387             :   {
    1388             :     Node* const value_constructor =
    1389         112 :         GetProperty(context, value, isolate()->factory()->constructor_string());
    1390          56 :     GotoIfNot(WordEqual(value_constructor, constructor), &if_need_to_allocate);
    1391          56 :     Return(value);
    1392             :   }
    1393             : 
    1394          56 :   BIND(&if_need_to_allocate);
    1395             :   {
    1396         112 :     Label if_nativepromise(this), if_notnativepromise(this, Label::kDeferred);
    1397         112 :     Branch(WordEqual(promise_fun, constructor), &if_nativepromise,
    1398          56 :            &if_notnativepromise);
    1399             : 
    1400             :     // This adds a fast path for native promises that don't need to
    1401             :     // create NewPromiseCapability.
    1402          56 :     BIND(&if_nativepromise);
    1403             :     {
    1404          56 :       Node* const result = AllocateAndInitJSPromise(context);
    1405          56 :       CallBuiltin(Builtins::kResolvePromise, context, result, value);
    1406          56 :       Return(result);
    1407             :     }
    1408             : 
    1409          56 :     BIND(&if_notnativepromise);
    1410             :     {
    1411          56 :       Node* const debug_event = TrueConstant();
    1412             :       Node* const capability = CallBuiltin(Builtins::kNewPromiseCapability,
    1413          56 :                                            context, constructor, debug_event);
    1414             : 
    1415             :       Node* const resolve =
    1416          56 :           LoadObjectField(capability, PromiseCapability::kResolveOffset);
    1417             :       CallJS(
    1418             :           CodeFactory::Call(isolate(), ConvertReceiverMode::kNullOrUndefined),
    1419          56 :           context, resolve, UndefinedConstant(), value);
    1420             : 
    1421             :       Node* const result =
    1422          56 :           LoadObjectField(capability, PromiseCapability::kPromiseOffset);
    1423          56 :       Return(result);
    1424          56 :     }
    1425          56 :   }
    1426          56 : }
    1427             : 
    1428             : // ES6 #sec-getcapabilitiesexecutor-functions
    1429         392 : TF_BUILTIN(PromiseGetCapabilitiesExecutor, PromiseBuiltinsAssembler) {
    1430          56 :   Node* const resolve = Parameter(Descriptor::kResolve);
    1431          56 :   Node* const reject = Parameter(Descriptor::kReject);
    1432          56 :   Node* const context = Parameter(Descriptor::kContext);
    1433             : 
    1434             :   Node* const capability =
    1435          56 :       LoadContextElement(context, PromiseBuiltins::kCapabilitySlot);
    1436             : 
    1437          56 :   Label if_alreadyinvoked(this, Label::kDeferred);
    1438             :   GotoIfNot(IsUndefined(
    1439         112 :                 LoadObjectField(capability, PromiseCapability::kResolveOffset)),
    1440          56 :             &if_alreadyinvoked);
    1441             :   GotoIfNot(IsUndefined(
    1442         112 :                 LoadObjectField(capability, PromiseCapability::kRejectOffset)),
    1443          56 :             &if_alreadyinvoked);
    1444             : 
    1445          56 :   StoreObjectField(capability, PromiseCapability::kResolveOffset, resolve);
    1446          56 :   StoreObjectField(capability, PromiseCapability::kRejectOffset, reject);
    1447             : 
    1448          56 :   Return(UndefinedConstant());
    1449             : 
    1450          56 :   BIND(&if_alreadyinvoked);
    1451          56 :   ThrowTypeError(context, MessageTemplate::kPromiseExecutorAlreadyInvoked);
    1452          56 : }
    1453             : 
    1454         392 : TF_BUILTIN(PromiseReject, PromiseBuiltinsAssembler) {
    1455             :   // 1. Let C be the this value.
    1456          56 :   Node* const receiver = Parameter(Descriptor::kReceiver);
    1457          56 :   Node* const reason = Parameter(Descriptor::kReason);
    1458          56 :   Node* const context = Parameter(Descriptor::kContext);
    1459             : 
    1460             :   // 2. If Type(C) is not Object, throw a TypeError exception.
    1461             :   ThrowIfNotJSReceiver(context, receiver, MessageTemplate::kCalledOnNonObject,
    1462          56 :                        "PromiseReject");
    1463             : 
    1464         112 :   Label if_nativepromise(this), if_custompromise(this, Label::kDeferred);
    1465          56 :   Node* const native_context = LoadNativeContext(context);
    1466             : 
    1467             :   Node* const promise_fun =
    1468          56 :       LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX);
    1469         112 :   Branch(WordEqual(promise_fun, receiver), &if_nativepromise,
    1470          56 :          &if_custompromise);
    1471             : 
    1472          56 :   BIND(&if_nativepromise);
    1473             :   {
    1474             :     Node* const promise =
    1475          56 :         AllocateAndSetJSPromise(context, v8::Promise::kRejected, reason);
    1476             :     CallRuntime(Runtime::kPromiseRejectEventFromStack, context, promise,
    1477          56 :                 reason);
    1478          56 :     Return(promise);
    1479             :   }
    1480             : 
    1481          56 :   BIND(&if_custompromise);
    1482             :   {
    1483             :     // 3. Let promiseCapability be ? NewPromiseCapability(C).
    1484          56 :     Node* const debug_event = TrueConstant();
    1485             :     Node* const capability = CallBuiltin(Builtins::kNewPromiseCapability,
    1486          56 :                                          context, receiver, debug_event);
    1487             : 
    1488             :     // 4. Perform ? Call(promiseCapability.[[Reject]], undefined, « r »).
    1489             :     Node* const reject =
    1490          56 :         LoadObjectField(capability, PromiseCapability::kRejectOffset);
    1491             :     CallJS(CodeFactory::Call(isolate(), ConvertReceiverMode::kNullOrUndefined),
    1492          56 :            context, reject, UndefinedConstant(), reason);
    1493             : 
    1494             :     // 5. Return promiseCapability.[[Promise]].
    1495             :     Node* const promise =
    1496          56 :         LoadObjectField(capability, PromiseCapability::kPromiseOffset);
    1497          56 :     Return(promise);
    1498          56 :   }
    1499          56 : }
    1500             : 
    1501          56 : std::pair<Node*, Node*> PromiseBuiltinsAssembler::CreatePromiseFinallyFunctions(
    1502             :     Node* on_finally, Node* constructor, Node* native_context) {
    1503             :   Node* const promise_context = CreatePromiseContext(
    1504          56 :       native_context, PromiseBuiltins::kPromiseFinallyContextLength);
    1505             :   StoreContextElementNoWriteBarrier(
    1506          56 :       promise_context, PromiseBuiltins::kOnFinallySlot, on_finally);
    1507             :   StoreContextElementNoWriteBarrier(
    1508          56 :       promise_context, PromiseBuiltins::kConstructorSlot, constructor);
    1509             :   Node* const map = LoadContextElement(
    1510          56 :       native_context, Context::STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX);
    1511             :   Node* const then_finally_info = LoadContextElement(
    1512          56 :       native_context, Context::PROMISE_THEN_FINALLY_SHARED_FUN);
    1513             :   Node* const then_finally = AllocateFunctionWithMapAndContext(
    1514          56 :       map, then_finally_info, promise_context);
    1515             :   Node* const catch_finally_info = LoadContextElement(
    1516          56 :       native_context, Context::PROMISE_CATCH_FINALLY_SHARED_FUN);
    1517             :   Node* const catch_finally = AllocateFunctionWithMapAndContext(
    1518          56 :       map, catch_finally_info, promise_context);
    1519          56 :   return std::make_pair(then_finally, catch_finally);
    1520             : }
    1521             : 
    1522         280 : TF_BUILTIN(PromiseValueThunkFinally, PromiseBuiltinsAssembler) {
    1523          56 :   Node* const context = Parameter(Descriptor::kContext);
    1524             : 
    1525          56 :   Node* const value = LoadContextElement(context, PromiseBuiltins::kValueSlot);
    1526          56 :   Return(value);
    1527          56 : }
    1528             : 
    1529          56 : Node* PromiseBuiltinsAssembler::CreateValueThunkFunction(Node* value,
    1530             :                                                          Node* native_context) {
    1531             :   Node* const value_thunk_context = CreatePromiseContext(
    1532          56 :       native_context, PromiseBuiltins::kPromiseValueThunkOrReasonContextLength);
    1533             :   StoreContextElementNoWriteBarrier(value_thunk_context,
    1534          56 :                                     PromiseBuiltins::kValueSlot, value);
    1535             :   Node* const map = LoadContextElement(
    1536          56 :       native_context, Context::STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX);
    1537             :   Node* const value_thunk_info = LoadContextElement(
    1538          56 :       native_context, Context::PROMISE_VALUE_THUNK_FINALLY_SHARED_FUN);
    1539             :   Node* const value_thunk = AllocateFunctionWithMapAndContext(
    1540          56 :       map, value_thunk_info, value_thunk_context);
    1541          56 :   return value_thunk;
    1542             : }
    1543             : 
    1544         336 : TF_BUILTIN(PromiseThenFinally, PromiseBuiltinsAssembler) {
    1545             :   CSA_ASSERT_JS_ARGC_EQ(this, 1);
    1546             : 
    1547          56 :   Node* const value = Parameter(Descriptor::kValue);
    1548          56 :   Node* const context = Parameter(Descriptor::kContext);
    1549             : 
    1550             :   // 1. Let onFinally be F.[[OnFinally]].
    1551             :   Node* const on_finally =
    1552          56 :       LoadContextElement(context, PromiseBuiltins::kOnFinallySlot);
    1553             : 
    1554             :   // 2.  Assert: IsCallable(onFinally) is true.
    1555             :   CSA_ASSERT(this, IsCallable(on_finally));
    1556             : 
    1557             :   // 3. Let result be ?  Call(onFinally).
    1558             :   Node* const result = CallJS(
    1559             :       CodeFactory::Call(isolate(), ConvertReceiverMode::kNullOrUndefined),
    1560          56 :       context, on_finally, UndefinedConstant());
    1561             : 
    1562             :   // 4. Let C be F.[[Constructor]].
    1563             :   Node* const constructor =
    1564          56 :       LoadContextElement(context, PromiseBuiltins::kConstructorSlot);
    1565             : 
    1566             :   // 5. Assert: IsConstructor(C) is true.
    1567             :   CSA_ASSERT(this, IsConstructor(constructor));
    1568             : 
    1569             :   // 6. Let promise be ? PromiseResolve(C, result).
    1570             :   Node* const promise =
    1571          56 :     CallBuiltin(Builtins::kPromiseResolve, context, constructor, result);
    1572             : 
    1573             :   // 7. Let valueThunk be equivalent to a function that returns value.
    1574          56 :   Node* const native_context = LoadNativeContext(context);
    1575          56 :   Node* const value_thunk = CreateValueThunkFunction(value, native_context);
    1576             : 
    1577             :   // 8. Return ? Invoke(promise, "then", « valueThunk »).
    1578          56 :   Return(InvokeThen(native_context, promise, value_thunk));
    1579          56 : }
    1580             : 
    1581         280 : TF_BUILTIN(PromiseThrowerFinally, PromiseBuiltinsAssembler) {
    1582          56 :   Node* const context = Parameter(Descriptor::kContext);
    1583             : 
    1584          56 :   Node* const reason = LoadContextElement(context, PromiseBuiltins::kValueSlot);
    1585          56 :   CallRuntime(Runtime::kThrow, context, reason);
    1586          56 :   Unreachable();
    1587          56 : }
    1588             : 
    1589          56 : Node* PromiseBuiltinsAssembler::CreateThrowerFunction(Node* reason,
    1590             :                                                       Node* native_context) {
    1591             :   Node* const thrower_context = CreatePromiseContext(
    1592          56 :       native_context, PromiseBuiltins::kPromiseValueThunkOrReasonContextLength);
    1593             :   StoreContextElementNoWriteBarrier(thrower_context,
    1594          56 :                                     PromiseBuiltins::kValueSlot, reason);
    1595             :   Node* const map = LoadContextElement(
    1596          56 :       native_context, Context::STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX);
    1597             :   Node* const thrower_info = LoadContextElement(
    1598          56 :       native_context, Context::PROMISE_THROWER_FINALLY_SHARED_FUN);
    1599             :   Node* const thrower =
    1600          56 :       AllocateFunctionWithMapAndContext(map, thrower_info, thrower_context);
    1601          56 :   return thrower;
    1602             : }
    1603             : 
    1604         336 : TF_BUILTIN(PromiseCatchFinally, PromiseBuiltinsAssembler) {
    1605             :   CSA_ASSERT_JS_ARGC_EQ(this, 1);
    1606             : 
    1607          56 :   Node* const reason = Parameter(Descriptor::kReason);
    1608          56 :   Node* const context = Parameter(Descriptor::kContext);
    1609             : 
    1610             :   // 1. Let onFinally be F.[[OnFinally]].
    1611             :   Node* const on_finally =
    1612          56 :       LoadContextElement(context, PromiseBuiltins::kOnFinallySlot);
    1613             : 
    1614             :   // 2. Assert: IsCallable(onFinally) is true.
    1615             :   CSA_ASSERT(this, IsCallable(on_finally));
    1616             : 
    1617             :   // 3. Let result be ? Call(onFinally).
    1618             :   Node* result = CallJS(
    1619             :       CodeFactory::Call(isolate(), ConvertReceiverMode::kNullOrUndefined),
    1620          56 :       context, on_finally, UndefinedConstant());
    1621             : 
    1622             :   // 4. Let C be F.[[Constructor]].
    1623             :   Node* const constructor =
    1624          56 :       LoadContextElement(context, PromiseBuiltins::kConstructorSlot);
    1625             : 
    1626             :   // 5. Assert: IsConstructor(C) is true.
    1627             :   CSA_ASSERT(this, IsConstructor(constructor));
    1628             : 
    1629             :   // 6. Let promise be ? PromiseResolve(C, result).
    1630             :   Node* const promise =
    1631          56 :     CallBuiltin(Builtins::kPromiseResolve, context, constructor, result);
    1632             : 
    1633             :   // 7. Let thrower be equivalent to a function that throws reason.
    1634          56 :   Node* const native_context = LoadNativeContext(context);
    1635          56 :   Node* const thrower = CreateThrowerFunction(reason, native_context);
    1636             : 
    1637             :   // 8. Return ? Invoke(promise, "then", « thrower »).
    1638          56 :   Return(InvokeThen(native_context, promise, thrower));
    1639          56 : }
    1640             : 
    1641         392 : TF_BUILTIN(PromisePrototypeFinally, PromiseBuiltinsAssembler) {
    1642             :   CSA_ASSERT_JS_ARGC_EQ(this, 1);
    1643             : 
    1644             :   // 1.  Let promise be the this value.
    1645          56 :   Node* const receiver = Parameter(Descriptor::kReceiver);
    1646          56 :   Node* const on_finally = Parameter(Descriptor::kOnFinally);
    1647          56 :   Node* const context = Parameter(Descriptor::kContext);
    1648             : 
    1649             :   // 2. If Type(promise) is not Object, throw a TypeError exception.
    1650             :   ThrowIfNotJSReceiver(context, receiver, MessageTemplate::kCalledOnNonObject,
    1651          56 :                        "Promise.prototype.finally");
    1652             : 
    1653             :   // 3. Let C be ? SpeciesConstructor(promise, %Promise%).
    1654          56 :   Node* const native_context = LoadNativeContext(context);
    1655             :   Node* const promise_fun =
    1656          56 :       LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX);
    1657          56 :   VARIABLE(var_constructor, MachineRepresentation::kTagged, promise_fun);
    1658         112 :   Label slow_constructor(this, Label::kDeferred), done_constructor(this);
    1659          56 :   Node* const receiver_map = LoadMap(receiver);
    1660          56 :   GotoIfNot(IsJSPromiseMap(receiver_map), &slow_constructor);
    1661             :   BranchIfPromiseSpeciesLookupChainIntact(native_context, receiver_map,
    1662          56 :                                           &done_constructor, &slow_constructor);
    1663          56 :   BIND(&slow_constructor);
    1664             :   {
    1665             :     Node* const constructor =
    1666          56 :         SpeciesConstructor(context, receiver, promise_fun);
    1667          56 :     var_constructor.Bind(constructor);
    1668          56 :     Goto(&done_constructor);
    1669             :   }
    1670          56 :   BIND(&done_constructor);
    1671          56 :   Node* const constructor = var_constructor.value();
    1672             : 
    1673             :   // 4. Assert: IsConstructor(C) is true.
    1674             :   CSA_ASSERT(this, IsConstructor(constructor));
    1675             : 
    1676         112 :   VARIABLE(var_then_finally, MachineRepresentation::kTagged);
    1677         112 :   VARIABLE(var_catch_finally, MachineRepresentation::kTagged);
    1678             : 
    1679         112 :   Label if_notcallable(this, Label::kDeferred), perform_finally(this);
    1680             : 
    1681          56 :   GotoIf(TaggedIsSmi(on_finally), &if_notcallable);
    1682          56 :   GotoIfNot(IsCallable(on_finally), &if_notcallable);
    1683             : 
    1684             :   // 6. Else,
    1685             :   //   a. Let thenFinally be a new built-in function object as defined
    1686             :   //   in ThenFinally Function.
    1687             :   //   b. Let catchFinally be a new built-in function object as
    1688             :   //   defined in CatchFinally Function.
    1689             :   //   c. Set thenFinally and catchFinally's [[Constructor]] internal
    1690             :   //   slots to C.
    1691             :   //   d. Set thenFinally and catchFinally's [[OnFinally]] internal
    1692             :   //   slots to onFinally.
    1693          56 :   Node* then_finally = nullptr;
    1694          56 :   Node* catch_finally = nullptr;
    1695         112 :   std::tie(then_finally, catch_finally) =
    1696         112 :     CreatePromiseFinallyFunctions(on_finally, constructor, native_context);
    1697          56 :   var_then_finally.Bind(then_finally);
    1698          56 :   var_catch_finally.Bind(catch_finally);
    1699          56 :   Goto(&perform_finally);
    1700             : 
    1701             :   // 5. If IsCallable(onFinally) is not true,
    1702             :   //    a. Let thenFinally be onFinally.
    1703             :   //    b. Let catchFinally be onFinally.
    1704          56 :   BIND(&if_notcallable);
    1705             :   {
    1706          56 :     var_then_finally.Bind(on_finally);
    1707          56 :     var_catch_finally.Bind(on_finally);
    1708          56 :     Goto(&perform_finally);
    1709             :   }
    1710             : 
    1711             :   // 7. Return ? Invoke(promise, "then", « thenFinally, catchFinally »).
    1712          56 :   BIND(&perform_finally);
    1713             :   Return(InvokeThen(native_context, receiver, var_then_finally.value(),
    1714         112 :                     var_catch_finally.value()));
    1715          56 : }
    1716             : 
    1717             : // ES #sec-fulfillpromise
    1718         392 : TF_BUILTIN(FulfillPromise, PromiseBuiltinsAssembler) {
    1719          56 :   Node* const promise = Parameter(Descriptor::kPromise);
    1720          56 :   Node* const value = Parameter(Descriptor::kValue);
    1721          56 :   Node* const context = Parameter(Descriptor::kContext);
    1722             : 
    1723             :   CSA_ASSERT(this, TaggedIsNotSmi(promise));
    1724             :   CSA_ASSERT(this, IsJSPromise(promise));
    1725             : 
    1726             :   // 2. Let reactions be promise.[[PromiseFulfillReactions]].
    1727             :   Node* const reactions =
    1728          56 :       LoadObjectField(promise, JSPromise::kReactionsOrResultOffset);
    1729             : 
    1730             :   // 3. Set promise.[[PromiseResult]] to value.
    1731             :   // 4. Set promise.[[PromiseFulfillReactions]] to undefined.
    1732             :   // 5. Set promise.[[PromiseRejectReactions]] to undefined.
    1733          56 :   StoreObjectField(promise, JSPromise::kReactionsOrResultOffset, value);
    1734             : 
    1735             :   // 6. Set promise.[[PromiseState]] to "fulfilled".
    1736          56 :   PromiseSetStatus(promise, Promise::kFulfilled);
    1737             : 
    1738             :   // 7. Return TriggerPromiseReactions(reactions, value).
    1739             :   Return(TriggerPromiseReactions(context, reactions, value,
    1740          56 :                                  PromiseReaction::kFulfill));
    1741          56 : }
    1742             : 
    1743             : // ES #sec-rejectpromise
    1744         448 : TF_BUILTIN(RejectPromise, PromiseBuiltinsAssembler) {
    1745          56 :   Node* const promise = Parameter(Descriptor::kPromise);
    1746          56 :   Node* const reason = Parameter(Descriptor::kReason);
    1747          56 :   Node* const debug_event = Parameter(Descriptor::kDebugEvent);
    1748          56 :   Node* const context = Parameter(Descriptor::kContext);
    1749             : 
    1750             :   CSA_ASSERT(this, TaggedIsNotSmi(promise));
    1751             :   CSA_ASSERT(this, IsJSPromise(promise));
    1752             :   CSA_ASSERT(this, IsBoolean(debug_event));
    1753          56 :   Label if_runtime(this, Label::kDeferred);
    1754             : 
    1755             :   // If promise hook is enabled or the debugger is active, let
    1756             :   // the runtime handle this operation, which greatly reduces
    1757             :   // the complexity here and also avoids a couple of back and
    1758             :   // forth between JavaScript and C++ land.
    1759             :   GotoIf(IsPromiseHookEnabledOrDebugIsActiveOrHasAsyncEventDelegate(),
    1760          56 :          &if_runtime);
    1761             : 
    1762             :   // 7. If promise.[[PromiseIsHandled]] is false, perform
    1763             :   //    HostPromiseRejectionTracker(promise, "reject").
    1764             :   // We don't try to handle rejecting {promise} without handler
    1765             :   // here, but we let the C++ code take care of this completely.
    1766          56 :   GotoIfNot(PromiseHasHandler(promise), &if_runtime);
    1767             : 
    1768             :   // 2. Let reactions be promise.[[PromiseRejectReactions]].
    1769             :   Node* reactions =
    1770          56 :       LoadObjectField(promise, JSPromise::kReactionsOrResultOffset);
    1771             : 
    1772             :   // 3. Set promise.[[PromiseResult]] to reason.
    1773             :   // 4. Set promise.[[PromiseFulfillReactions]] to undefined.
    1774             :   // 5. Set promise.[[PromiseRejectReactions]] to undefined.
    1775          56 :   StoreObjectField(promise, JSPromise::kReactionsOrResultOffset, reason);
    1776             : 
    1777             :   // 6. Set promise.[[PromiseState]] to "rejected".
    1778          56 :   PromiseSetStatus(promise, Promise::kRejected);
    1779             : 
    1780             :   // 7. Return TriggerPromiseReactions(reactions, reason).
    1781             :   Return(TriggerPromiseReactions(context, reactions, reason,
    1782          56 :                                  PromiseReaction::kReject));
    1783             : 
    1784          56 :   BIND(&if_runtime);
    1785             :   TailCallRuntime(Runtime::kRejectPromise, context, promise, reason,
    1786          56 :                   debug_event);
    1787          56 : }
    1788             : 
    1789             : // ES #sec-promise-resolve-functions
    1790         392 : TF_BUILTIN(ResolvePromise, PromiseBuiltinsAssembler) {
    1791          56 :   Node* const promise = Parameter(Descriptor::kPromise);
    1792          56 :   Node* const resolution = Parameter(Descriptor::kResolution);
    1793          56 :   Node* const context = Parameter(Descriptor::kContext);
    1794             : 
    1795             :   CSA_ASSERT(this, TaggedIsNotSmi(promise));
    1796             :   CSA_ASSERT(this, IsJSPromise(promise));
    1797             : 
    1798         112 :   Label do_enqueue(this), if_fulfill(this), if_reject(this, Label::kDeferred),
    1799         112 :       if_runtime(this, Label::kDeferred);
    1800         112 :   VARIABLE(var_reason, MachineRepresentation::kTagged);
    1801         112 :   VARIABLE(var_then, MachineRepresentation::kTagged);
    1802             : 
    1803             :   // If promise hook is enabled or the debugger is active, let
    1804             :   // the runtime handle this operation, which greatly reduces
    1805             :   // the complexity here and also avoids a couple of back and
    1806             :   // forth between JavaScript and C++ land.
    1807             :   GotoIf(IsPromiseHookEnabledOrDebugIsActiveOrHasAsyncEventDelegate(),
    1808          56 :          &if_runtime);
    1809             : 
    1810             :   // 6. If SameValue(resolution, promise) is true, then
    1811             :   // We can use pointer comparison here, since the {promise} is guaranteed
    1812             :   // to be a JSPromise inside this function and thus is reference comparable.
    1813          56 :   GotoIf(WordEqual(promise, resolution), &if_runtime);
    1814             : 
    1815             :   // 7. If Type(resolution) is not Object, then
    1816          56 :   GotoIf(TaggedIsSmi(resolution), &if_fulfill);
    1817          56 :   Node* const resolution_map = LoadMap(resolution);
    1818          56 :   GotoIfNot(IsJSReceiverMap(resolution_map), &if_fulfill);
    1819             : 
    1820             :   // We can skip the "then" lookup on {resolution} if its [[Prototype]]
    1821             :   // is the (initial) Promise.prototype and the Promise#then protector
    1822             :   // is intact, as that guards the lookup path for the "then" property
    1823             :   // on JSPromise instances which have the (initial) %PromisePrototype%.
    1824         112 :   Label if_fast(this), if_receiver(this), if_slow(this, Label::kDeferred);
    1825          56 :   Node* const native_context = LoadNativeContext(context);
    1826          56 :   GotoIfForceSlowPath(&if_slow);
    1827          56 :   GotoIf(IsPromiseThenProtectorCellInvalid(), &if_slow);
    1828          56 :   GotoIfNot(IsJSPromiseMap(resolution_map), &if_receiver);
    1829             :   Node* const promise_prototype =
    1830          56 :       LoadContextElement(native_context, Context::PROMISE_PROTOTYPE_INDEX);
    1831         112 :   Branch(WordEqual(LoadMapPrototype(resolution_map), promise_prototype),
    1832          56 :          &if_fast, &if_slow);
    1833             : 
    1834          56 :   BIND(&if_fast);
    1835             :   {
    1836             :     // The {resolution} is a native Promise in this case.
    1837             :     Node* const then =
    1838          56 :         LoadContextElement(native_context, Context::PROMISE_THEN_INDEX);
    1839          56 :     var_then.Bind(then);
    1840          56 :     Goto(&do_enqueue);
    1841             :   }
    1842             : 
    1843          56 :   BIND(&if_receiver);
    1844             :   {
    1845             :     // We can skip the lookup of "then" if the {resolution} is a (newly
    1846             :     // created) IterResultObject, as the Promise#then() protector also
    1847             :     // ensures that the intrinsic %ObjectPrototype% doesn't contain any
    1848             :     // "then" property. This helps to avoid negative lookups on iterator
    1849             :     // results from async generators.
    1850             :     CSA_ASSERT(this, IsJSReceiverMap(resolution_map));
    1851             :     CSA_ASSERT(this, Word32BinaryNot(IsPromiseThenProtectorCellInvalid()));
    1852             :     Node* const iterator_result_map =
    1853          56 :         LoadContextElement(native_context, Context::ITERATOR_RESULT_MAP_INDEX);
    1854         112 :     Branch(WordEqual(resolution_map, iterator_result_map), &if_fulfill,
    1855          56 :            &if_slow);
    1856             :   }
    1857             : 
    1858          56 :   BIND(&if_slow);
    1859             :   {
    1860             :     // 8. Let then be Get(resolution, "then").
    1861             :     Node* const then =
    1862         112 :         GetProperty(context, resolution, isolate()->factory()->then_string());
    1863             : 
    1864             :     // 9. If then is an abrupt completion, then
    1865          56 :     GotoIfException(then, &if_reject, &var_reason);
    1866             : 
    1867             :     // 11. If IsCallable(thenAction) is false, then
    1868          56 :     GotoIf(TaggedIsSmi(then), &if_fulfill);
    1869          56 :     Node* const then_map = LoadMap(then);
    1870          56 :     GotoIfNot(IsCallableMap(then_map), &if_fulfill);
    1871          56 :     var_then.Bind(then);
    1872          56 :     Goto(&do_enqueue);
    1873             :   }
    1874             : 
    1875          56 :   BIND(&do_enqueue);
    1876             :   {
    1877             :     // 12. Perform EnqueueJob("PromiseJobs", PromiseResolveThenableJob,
    1878             :     //                        «promise, resolution, thenAction»).
    1879             :     Node* const task = AllocatePromiseResolveThenableJobTask(
    1880          56 :         promise, var_then.value(), resolution, native_context);
    1881          56 :     TailCallBuiltin(Builtins::kEnqueueMicrotask, native_context, task);
    1882             :   }
    1883             : 
    1884          56 :   BIND(&if_fulfill);
    1885             :   {
    1886             :     // 7.b Return FulfillPromise(promise, resolution).
    1887          56 :     TailCallBuiltin(Builtins::kFulfillPromise, context, promise, resolution);
    1888             :   }
    1889             : 
    1890          56 :   BIND(&if_runtime);
    1891          56 :   Return(CallRuntime(Runtime::kResolvePromise, context, promise, resolution));
    1892             : 
    1893          56 :   BIND(&if_reject);
    1894             :   {
    1895             :     // 9.a Return RejectPromise(promise, then.[[Value]]).
    1896             :     TailCallBuiltin(Builtins::kRejectPromise, context, promise,
    1897          56 :                     var_reason.value(), FalseConstant());
    1898          56 :   }
    1899          56 : }
    1900             : 
    1901          56 : Node* PromiseBuiltinsAssembler::PerformPromiseAll(
    1902             :     Node* context, Node* constructor, Node* capability,
    1903             :     const IteratorRecord& iterator, Label* if_exception,
    1904             :     Variable* var_exception) {
    1905          56 :   IteratorBuiltinsAssembler iter_assembler(state());
    1906             : 
    1907          56 :   Node* const native_context = LoadNativeContext(context);
    1908             : 
    1909             :   // For catch prediction, don't treat the .then calls as handling it;
    1910             :   // instead, recurse outwards.
    1911             :   SetForwardingHandlerIfTrue(
    1912             :       native_context, IsDebugActive(),
    1913          56 :       LoadObjectField(capability, PromiseCapability::kRejectOffset));
    1914             : 
    1915             :   Node* const resolve_element_context =
    1916          56 :       CreatePromiseAllResolveElementContext(capability, native_context);
    1917             : 
    1918         112 :   TVARIABLE(Smi, var_index, SmiConstant(1));
    1919         112 :   Label loop(this, &var_index), done_loop(this),
    1920         112 :       too_many_elements(this, Label::kDeferred),
    1921         112 :       close_iterator(this, Label::kDeferred);
    1922          56 :   Goto(&loop);
    1923          56 :   BIND(&loop);
    1924             :   {
    1925             :     // Let next be IteratorStep(iteratorRecord.[[Iterator]]).
    1926             :     // If next is an abrupt completion, set iteratorRecord.[[Done]] to true.
    1927             :     // ReturnIfAbrupt(next).
    1928             :     Node* const fast_iterator_result_map =
    1929          56 :         LoadContextElement(native_context, Context::ITERATOR_RESULT_MAP_INDEX);
    1930             :     Node* const next = iter_assembler.IteratorStep(
    1931             :         native_context, iterator, &done_loop, fast_iterator_result_map,
    1932          56 :         if_exception, var_exception);
    1933             : 
    1934             :     // Let nextValue be IteratorValue(next).
    1935             :     // If nextValue is an abrupt completion, set iteratorRecord.[[Done]] to
    1936             :     //     true.
    1937             :     // ReturnIfAbrupt(nextValue).
    1938             :     Node* const next_value = iter_assembler.IteratorValue(
    1939             :         native_context, next, fast_iterator_result_map, if_exception,
    1940          56 :         var_exception);
    1941             : 
    1942             :     // Check if we reached the limit.
    1943          56 :     TNode<Smi> const index = var_index.value();
    1944          56 :     GotoIf(SmiEqual(index, SmiConstant(PropertyArray::HashField::kMax)),
    1945          56 :            &too_many_elements);
    1946             : 
    1947             :     // Set index to index + 1.
    1948          56 :     var_index = SmiAdd(index, SmiConstant(1));
    1949             : 
    1950             :     // Set remainingElementsCount.[[Value]] to
    1951             :     //     remainingElementsCount.[[Value]] + 1.
    1952          56 :     TNode<Smi> const remaining_elements_count = CAST(LoadContextElement(
    1953             :         resolve_element_context,
    1954             :         PromiseBuiltins::kPromiseAllResolveElementRemainingSlot));
    1955             :     StoreContextElementNoWriteBarrier(
    1956             :         resolve_element_context,
    1957             :         PromiseBuiltins::kPromiseAllResolveElementRemainingSlot,
    1958          56 :         SmiAdd(remaining_elements_count, SmiConstant(1)));
    1959             : 
    1960             :     // Let resolveElement be CreateBuiltinFunction(steps,
    1961             :     //                                             « [[AlreadyCalled]],
    1962             :     //                                               [[Index]],
    1963             :     //                                               [[Values]],
    1964             :     //                                               [[Capability]],
    1965             :     //                                               [[RemainingElements]] »).
    1966             :     // Set resolveElement.[[AlreadyCalled]] to a Record { [[Value]]: false }.
    1967             :     // Set resolveElement.[[Index]] to index.
    1968             :     // Set resolveElement.[[Values]] to values.
    1969             :     // Set resolveElement.[[Capability]] to resultCapability.
    1970             :     // Set resolveElement.[[RemainingElements]] to remainingElementsCount.
    1971             :     Node* const resolve_element_fun = CreatePromiseAllResolveElementFunction(
    1972          56 :         resolve_element_context, index, native_context);
    1973             : 
    1974             :     // We can skip the "resolve" lookup on the {constructor} as well as the
    1975             :     // "then" lookup on the result of the "resolve" call, and immediately
    1976             :     // chain continuation onto the {next_value} if:
    1977             :     //
    1978             :     //   (a) The {constructor} is the intrinsic %Promise% function, and
    1979             :     //       looking up "resolve" on {constructor} yields the initial
    1980             :     //       Promise.resolve() builtin, and
    1981             :     //   (b) the promise @@species protector cell is valid, meaning that
    1982             :     //       no one messed with the Symbol.species property on any
    1983             :     //       intrinsic promise or on the Promise.prototype, and
    1984             :     //   (c) the {next_value} is a JSPromise whose [[Prototype]] field
    1985             :     //       contains the intrinsic %PromisePrototype%, and
    1986             :     //   (d) we're not running with async_hooks or DevTools enabled.
    1987             :     //
    1988             :     // In that case we also don't need to allocate a chained promise for
    1989             :     // the PromiseReaction (aka we can pass undefined to PerformPromiseThen),
    1990             :     // since this is only necessary for DevTools and PromiseHooks.
    1991         112 :     Label if_fast(this), if_slow(this);
    1992             :     GotoIfNotPromiseResolveLookupChainIntact(native_context, constructor,
    1993          56 :                                              &if_slow);
    1994             :     GotoIf(IsPromiseHookEnabledOrDebugIsActiveOrHasAsyncEventDelegate(),
    1995          56 :            &if_slow);
    1996          56 :     GotoIf(IsPromiseSpeciesProtectorCellInvalid(), &if_slow);
    1997          56 :     GotoIf(TaggedIsSmi(next_value), &if_slow);
    1998          56 :     Node* const next_value_map = LoadMap(next_value);
    1999             :     BranchIfPromiseThenLookupChainIntact(native_context, next_value_map,
    2000          56 :                                          &if_fast, &if_slow);
    2001             : 
    2002          56 :     BIND(&if_fast);
    2003             :     {
    2004             :       // Register the PromiseReaction immediately on the {next_value}, not
    2005             :       // passing any chained promise since neither async_hooks nor DevTools
    2006             :       // are enabled, so there's no use of the resulting promise.
    2007             :       PerformPromiseThen(
    2008             :           native_context, next_value, resolve_element_fun,
    2009         112 :           LoadObjectField(capability, PromiseCapability::kRejectOffset),
    2010         168 :           UndefinedConstant());
    2011          56 :       Goto(&loop);
    2012             :     }
    2013             : 
    2014          56 :     BIND(&if_slow);
    2015             :     {
    2016             :       // Let nextPromise be ? Invoke(constructor, "resolve", « nextValue »).
    2017             :       Node* const next_promise =
    2018             :           InvokeResolve(native_context, constructor, next_value,
    2019          56 :                         &close_iterator, var_exception);
    2020             : 
    2021             :       // Perform ? Invoke(nextPromise, "then", « resolveElement,
    2022             :       //                  resultCapability.[[Reject]] »).
    2023             :       Node* const then =
    2024         112 :           GetProperty(native_context, next_promise, factory()->then_string());
    2025          56 :       GotoIfException(then, &close_iterator, var_exception);
    2026             : 
    2027             :       Node* const then_call =
    2028             :           CallJS(CodeFactory::Call(isolate(),
    2029             :                                    ConvertReceiverMode::kNotNullOrUndefined),
    2030             :                  native_context, then, next_promise, resolve_element_fun,
    2031          56 :                  LoadObjectField(capability, PromiseCapability::kRejectOffset));
    2032          56 :       GotoIfException(then_call, &close_iterator, var_exception);
    2033             : 
    2034             :       // For catch prediction, mark that rejections here are semantically
    2035             :       // handled by the combined Promise.
    2036             :       SetPromiseHandledByIfTrue(
    2037          56 :           native_context, IsDebugActive(), then_call, [=]() {
    2038             :             // Load promiseCapability.[[Promise]]
    2039             :             return LoadObjectField(capability,
    2040         112 :                                    PromiseCapability::kPromiseOffset);
    2041         168 :           });
    2042             : 
    2043          56 :       Goto(&loop);
    2044          56 :     }
    2045             :   }
    2046             : 
    2047          56 :   BIND(&too_many_elements);
    2048             :   {
    2049             :     // If there are too many elements (currently more than 2**21-1), raise a
    2050             :     // RangeError here (which is caught directly and turned into a rejection)
    2051             :     // of the resulting promise. We could gracefully handle this case as well
    2052             :     // and support more than this number of elements by going to a separate
    2053             :     // function and pass the larger indices via a separate context, but it
    2054             :     // doesn't seem likely that we need this, and it's unclear how the rest
    2055             :     // of the system deals with 2**21 live Promises anyways.
    2056             :     Node* const result =
    2057             :         CallRuntime(Runtime::kThrowRangeError, native_context,
    2058          56 :                     SmiConstant(MessageTemplate::kTooManyElementsInPromiseAll));
    2059          56 :     GotoIfException(result, &close_iterator, var_exception);
    2060          56 :     Unreachable();
    2061             :   }
    2062             : 
    2063          56 :   BIND(&close_iterator);
    2064             :   {
    2065             :     // Exception must be bound to a JS value.
    2066             :     CSA_ASSERT(this, IsNotTheHole(var_exception->value()));
    2067             :     iter_assembler.IteratorCloseOnException(native_context, iterator,
    2068          56 :                                             if_exception, var_exception);
    2069             :   }
    2070             : 
    2071          56 :   BIND(&done_loop);
    2072             :   {
    2073         112 :     Label resolve_promise(this, Label::kDeferred), return_promise(this);
    2074             :     // Set iteratorRecord.[[Done]] to true.
    2075             :     // Set remainingElementsCount.[[Value]] to
    2076             :     //    remainingElementsCount.[[Value]] - 1.
    2077          56 :     TNode<Smi> remaining_elements_count = CAST(LoadContextElement(
    2078             :         resolve_element_context,
    2079             :         PromiseBuiltins::kPromiseAllResolveElementRemainingSlot));
    2080          56 :     remaining_elements_count = SmiSub(remaining_elements_count, SmiConstant(1));
    2081             :     StoreContextElementNoWriteBarrier(
    2082             :         resolve_element_context,
    2083             :         PromiseBuiltins::kPromiseAllResolveElementRemainingSlot,
    2084          56 :         remaining_elements_count);
    2085          56 :     GotoIf(SmiEqual(remaining_elements_count, SmiConstant(0)),
    2086          56 :            &resolve_promise);
    2087             : 
    2088             :     // Pre-allocate the backing store for the {values_array} to the desired
    2089             :     // capacity here. We may already have elements here in case of some
    2090             :     // fancy Thenable that calls the resolve callback immediately, so we need
    2091             :     // to handle that correctly here.
    2092             :     Node* const values_array = LoadContextElement(
    2093             :         resolve_element_context,
    2094          56 :         PromiseBuiltins::kPromiseAllResolveElementValuesArraySlot);
    2095          56 :     Node* const old_elements = LoadElements(values_array);
    2096          56 :     TNode<Smi> const old_capacity = LoadFixedArrayBaseLength(old_elements);
    2097          56 :     TNode<Smi> const new_capacity = var_index.value();
    2098          56 :     GotoIf(SmiGreaterThanOrEqual(old_capacity, new_capacity), &return_promise);
    2099             :     Node* const new_elements =
    2100             :         AllocateFixedArray(PACKED_ELEMENTS, new_capacity, SMI_PARAMETERS,
    2101          56 :                            AllocationFlag::kAllowLargeObjectAllocation);
    2102             :     CopyFixedArrayElements(PACKED_ELEMENTS, old_elements, PACKED_ELEMENTS,
    2103          56 :                            new_elements, SmiConstant(0), old_capacity,
    2104         112 :                            new_capacity, UPDATE_WRITE_BARRIER, SMI_PARAMETERS);
    2105          56 :     StoreObjectField(values_array, JSArray::kElementsOffset, new_elements);
    2106          56 :     Goto(&return_promise);
    2107             : 
    2108             :     // If remainingElementsCount.[[Value]] is 0, then
    2109             :     //     Let valuesArray be CreateArrayFromList(values).
    2110             :     //     Perform ? Call(resultCapability.[[Resolve]], undefined,
    2111             :     //                    « valuesArray »).
    2112          56 :     BIND(&resolve_promise);
    2113             :     {
    2114             :       Node* const resolve =
    2115          56 :           LoadObjectField(capability, PromiseCapability::kResolveOffset);
    2116             :       Node* const values_array = LoadContextElement(
    2117             :           resolve_element_context,
    2118          56 :           PromiseBuiltins::kPromiseAllResolveElementValuesArraySlot);
    2119             :       Node* const resolve_call = CallJS(
    2120             :           CodeFactory::Call(isolate(), ConvertReceiverMode::kNullOrUndefined),
    2121          56 :           native_context, resolve, UndefinedConstant(), values_array);
    2122          56 :       GotoIfException(resolve_call, if_exception, var_exception);
    2123          56 :       Goto(&return_promise);
    2124             :     }
    2125             : 
    2126             :     // Return resultCapability.[[Promise]].
    2127         112 :     BIND(&return_promise);
    2128             :   }
    2129             : 
    2130             :   Node* const promise =
    2131          56 :       LoadObjectField(capability, PromiseCapability::kPromiseOffset);
    2132         112 :   return promise;
    2133             : }
    2134             : 
    2135             : // ES#sec-promise.all
    2136             : // Promise.all ( iterable )
    2137         392 : TF_BUILTIN(PromiseAll, PromiseBuiltinsAssembler) {
    2138          56 :   IteratorBuiltinsAssembler iter_assembler(state());
    2139             : 
    2140             :   // Let C be the this value.
    2141             :   // If Type(C) is not Object, throw a TypeError exception.
    2142          56 :   Node* const receiver = Parameter(Descriptor::kReceiver);
    2143          56 :   Node* const context = Parameter(Descriptor::kContext);
    2144             :   ThrowIfNotJSReceiver(context, receiver, MessageTemplate::kCalledOnNonObject,
    2145          56 :                        "Promise.all");
    2146             : 
    2147             :   // Let promiseCapability be ? NewPromiseCapability(C).
    2148             :   // Don't fire debugEvent so that forwarding the rejection through all does not
    2149             :   // trigger redundant ExceptionEvents
    2150          56 :   Node* const debug_event = FalseConstant();
    2151             :   Node* const capability = CallBuiltin(Builtins::kNewPromiseCapability, context,
    2152          56 :                                        receiver, debug_event);
    2153             : 
    2154         112 :   VARIABLE(var_exception, MachineRepresentation::kTagged, TheHoleConstant());
    2155         112 :   Label reject_promise(this, &var_exception, Label::kDeferred);
    2156             : 
    2157             :   // Let iterator be GetIterator(iterable).
    2158             :   // IfAbruptRejectPromise(iterator, promiseCapability).
    2159          56 :   Node* const iterable = Parameter(Descriptor::kIterable);
    2160             :   IteratorRecord iterator = iter_assembler.GetIterator(
    2161          56 :       context, iterable, &reject_promise, &var_exception);
    2162             : 
    2163             :   // Let result be PerformPromiseAll(iteratorRecord, C, promiseCapability).
    2164             :   // If result is an abrupt completion, then
    2165             :   //   If iteratorRecord.[[Done]] is false, let result be
    2166             :   //       IteratorClose(iterator, result).
    2167             :   //    IfAbruptRejectPromise(result, promiseCapability).
    2168             :   Node* const result = PerformPromiseAll(
    2169          56 :       context, receiver, capability, iterator, &reject_promise, &var_exception);
    2170             : 
    2171          56 :   Return(result);
    2172             : 
    2173          56 :   BIND(&reject_promise);
    2174             :   {
    2175             :     // Exception must be bound to a JS value.
    2176             :     CSA_SLOW_ASSERT(this, IsNotTheHole(var_exception.value()));
    2177             :     Node* const reject =
    2178          56 :         LoadObjectField(capability, PromiseCapability::kRejectOffset);
    2179             :     CallJS(CodeFactory::Call(isolate(), ConvertReceiverMode::kNullOrUndefined),
    2180          56 :            context, reject, UndefinedConstant(), var_exception.value());
    2181             : 
    2182             :     Node* const promise =
    2183          56 :         LoadObjectField(capability, PromiseCapability::kPromiseOffset);
    2184          56 :     Return(promise);
    2185          56 :   }
    2186          56 : }
    2187             : 
    2188         392 : TF_BUILTIN(PromiseAllResolveElementClosure, PromiseBuiltinsAssembler) {
    2189          56 :   TNode<Object> value = CAST(Parameter(Descriptor::kValue));
    2190          56 :   TNode<Context> context = CAST(Parameter(Descriptor::kContext));
    2191          56 :   TNode<JSFunction> function = CAST(Parameter(Descriptor::kJSTarget));
    2192             : 
    2193         112 :   Label already_called(this, Label::kDeferred), resolve_promise(this);
    2194             : 
    2195             :   // We use the {function}s context as the marker to remember whether this
    2196             :   // resolve element closure was already called. It points to the resolve
    2197             :   // element context (which is a FunctionContext) until it was called the
    2198             :   // first time, in which case we make it point to the native context here
    2199             :   // to mark this resolve element closure as done.
    2200          56 :   GotoIf(IsNativeContext(context), &already_called);
    2201             :   CSA_ASSERT(
    2202             :       this,
    2203             :       SmiEqual(LoadObjectField<Smi>(context, Context::kLengthOffset),
    2204             :                SmiConstant(PromiseBuiltins::kPromiseAllResolveElementLength)));
    2205          56 :   TNode<Context> native_context = LoadNativeContext(context);
    2206          56 :   StoreObjectField(function, JSFunction::kContextOffset, native_context);
    2207             : 
    2208             :   // Determine the index from the {function}.
    2209         112 :   Label unreachable(this, Label::kDeferred);
    2210             :   STATIC_ASSERT(PropertyArray::kNoHashSentinel == 0);
    2211             :   TNode<IntPtrT> identity_hash =
    2212          56 :       LoadJSReceiverIdentityHash(function, &unreachable);
    2213             :   CSA_ASSERT(this, IntPtrGreaterThan(identity_hash, IntPtrConstant(0)));
    2214          56 :   TNode<IntPtrT> index = IntPtrSub(identity_hash, IntPtrConstant(1));
    2215             : 
    2216             :   // Check if we need to grow the [[ValuesArray]] to store {value} at {index}.
    2217          56 :   TNode<JSArray> values_array = CAST(LoadContextElement(
    2218             :       context, PromiseBuiltins::kPromiseAllResolveElementValuesArraySlot));
    2219          56 :   TNode<FixedArray> elements = CAST(LoadElements(values_array));
    2220             :   TNode<IntPtrT> values_length =
    2221          56 :       LoadAndUntagObjectField(values_array, JSArray::kLengthOffset);
    2222         112 :   Label if_inbounds(this), if_outofbounds(this), done(this);
    2223          56 :   Branch(IntPtrLessThan(index, values_length), &if_inbounds, &if_outofbounds);
    2224             : 
    2225          56 :   BIND(&if_outofbounds);
    2226             :   {
    2227             :     // Check if we need to grow the backing store.
    2228          56 :     TNode<IntPtrT> new_length = IntPtrAdd(index, IntPtrConstant(1));
    2229             :     TNode<IntPtrT> elements_length =
    2230          56 :         LoadAndUntagObjectField(elements, FixedArray::kLengthOffset);
    2231         112 :     Label if_grow(this, Label::kDeferred), if_nogrow(this);
    2232          56 :     Branch(IntPtrLessThan(index, elements_length), &if_nogrow, &if_grow);
    2233             : 
    2234          56 :     BIND(&if_grow);
    2235             :     {
    2236             :       // We need to grow the backing store to fit the {index} as well.
    2237             :       TNode<IntPtrT> new_elements_length =
    2238             :           IntPtrMin(CalculateNewElementsCapacity(new_length),
    2239          56 :                     IntPtrConstant(PropertyArray::HashField::kMax + 1));
    2240             :       CSA_ASSERT(this, IntPtrLessThan(index, new_elements_length));
    2241             :       CSA_ASSERT(this, IntPtrLessThan(elements_length, new_elements_length));
    2242             :       TNode<FixedArray> new_elements =
    2243          56 :           CAST(AllocateFixedArray(PACKED_ELEMENTS, new_elements_length,
    2244             :                                   AllocationFlag::kAllowLargeObjectAllocation));
    2245             :       CopyFixedArrayElements(PACKED_ELEMENTS, elements, PACKED_ELEMENTS,
    2246             :                              new_elements, elements_length,
    2247          56 :                              new_elements_length);
    2248          56 :       StoreFixedArrayElement(new_elements, index, value);
    2249             : 
    2250             :       // Update backing store and "length" on {values_array}.
    2251          56 :       StoreObjectField(values_array, JSArray::kElementsOffset, new_elements);
    2252             :       StoreObjectFieldNoWriteBarrier(values_array, JSArray::kLengthOffset,
    2253          56 :                                      SmiTag(new_length));
    2254          56 :       Goto(&done);
    2255             :     }
    2256             : 
    2257          56 :     BIND(&if_nogrow);
    2258             :     {
    2259             :       // The {index} is within bounds of the {elements} backing store, so
    2260             :       // just store the {value} and update the "length" of the {values_array}.
    2261             :       StoreObjectFieldNoWriteBarrier(values_array, JSArray::kLengthOffset,
    2262          56 :                                      SmiTag(new_length));
    2263          56 :       StoreFixedArrayElement(elements, index, value);
    2264          56 :       Goto(&done);
    2265          56 :     }
    2266             :   }
    2267             : 
    2268          56 :   BIND(&if_inbounds);
    2269             :   {
    2270             :     // The {index} is in bounds of the {values_array},
    2271             :     // just store the {value} and continue.
    2272          56 :     StoreFixedArrayElement(elements, index, value);
    2273          56 :     Goto(&done);
    2274             :   }
    2275             : 
    2276          56 :   BIND(&done);
    2277          56 :   TNode<Smi> remaining_elements_count = CAST(LoadContextElement(
    2278             :       context, PromiseBuiltins::kPromiseAllResolveElementRemainingSlot));
    2279          56 :   remaining_elements_count = SmiSub(remaining_elements_count, SmiConstant(1));
    2280             :   StoreContextElement(context,
    2281             :                       PromiseBuiltins::kPromiseAllResolveElementRemainingSlot,
    2282          56 :                       remaining_elements_count);
    2283          56 :   GotoIf(SmiEqual(remaining_elements_count, SmiConstant(0)), &resolve_promise);
    2284          56 :   Return(UndefinedConstant());
    2285             : 
    2286          56 :   BIND(&resolve_promise);
    2287          56 :   TNode<PromiseCapability> capability = CAST(LoadContextElement(
    2288             :       context, PromiseBuiltins::kPromiseAllResolveElementCapabilitySlot));
    2289             :   TNode<Object> resolve =
    2290          56 :       LoadObjectField(capability, PromiseCapability::kResolveOffset);
    2291             :   CallJS(CodeFactory::Call(isolate(), ConvertReceiverMode::kNullOrUndefined),
    2292          56 :          context, resolve, UndefinedConstant(), values_array);
    2293          56 :   Return(UndefinedConstant());
    2294             : 
    2295          56 :   BIND(&already_called);
    2296          56 :   Return(UndefinedConstant());
    2297             : 
    2298          56 :   BIND(&unreachable);
    2299         112 :   Unreachable();
    2300          56 : }
    2301             : 
    2302             : // ES#sec-promise.race
    2303             : // Promise.race ( iterable )
    2304         392 : TF_BUILTIN(PromiseRace, PromiseBuiltinsAssembler) {
    2305          56 :   IteratorBuiltinsAssembler iter_assembler(state());
    2306         112 :   VARIABLE(var_exception, MachineRepresentation::kTagged, TheHoleConstant());
    2307             : 
    2308          56 :   Node* const receiver = Parameter(Descriptor::kReceiver);
    2309          56 :   Node* const context = Parameter(Descriptor::kContext);
    2310             :   ThrowIfNotJSReceiver(context, receiver, MessageTemplate::kCalledOnNonObject,
    2311          56 :                        "Promise.race");
    2312             : 
    2313             :   // Let promiseCapability be ? NewPromiseCapability(C).
    2314             :   // Don't fire debugEvent so that forwarding the rejection through all does not
    2315             :   // trigger redundant ExceptionEvents
    2316          56 :   Node* const debug_event = FalseConstant();
    2317             :   Node* const capability = CallBuiltin(Builtins::kNewPromiseCapability, context,
    2318          56 :                                        receiver, debug_event);
    2319             : 
    2320             :   Node* const resolve =
    2321          56 :       LoadObjectField(capability, PromiseCapability::kResolveOffset);
    2322             :   Node* const reject =
    2323          56 :       LoadObjectField(capability, PromiseCapability::kRejectOffset);
    2324             : 
    2325         112 :   Label close_iterator(this, Label::kDeferred);
    2326         112 :   Label reject_promise(this, Label::kDeferred);
    2327             : 
    2328             :   // For catch prediction, don't treat the .then calls as handling it;
    2329             :   // instead, recurse outwards.
    2330          56 :   SetForwardingHandlerIfTrue(context, IsDebugActive(), reject);
    2331             : 
    2332             :   // Let iterator be GetIterator(iterable).
    2333             :   // IfAbruptRejectPromise(iterator, promiseCapability).
    2334          56 :   Node* const iterable = Parameter(Descriptor::kIterable);
    2335             :   IteratorRecord iterator = iter_assembler.GetIterator(
    2336          56 :       context, iterable, &reject_promise, &var_exception);
    2337             : 
    2338             :   // Let result be PerformPromiseRace(iteratorRecord, C, promiseCapability).
    2339             :   {
    2340         112 :     Label loop(this), break_loop(this);
    2341          56 :     Goto(&loop);
    2342          56 :     BIND(&loop);
    2343             :     {
    2344          56 :       Node* const native_context = LoadNativeContext(context);
    2345             :       Node* const fast_iterator_result_map = LoadContextElement(
    2346          56 :           native_context, Context::ITERATOR_RESULT_MAP_INDEX);
    2347             : 
    2348             :       // Let next be IteratorStep(iteratorRecord.[[Iterator]]).
    2349             :       // If next is an abrupt completion, set iteratorRecord.[[Done]] to true.
    2350             :       // ReturnIfAbrupt(next).
    2351             :       Node* const next = iter_assembler.IteratorStep(
    2352             :           context, iterator, &break_loop, fast_iterator_result_map,
    2353          56 :           &reject_promise, &var_exception);
    2354             : 
    2355             :       // Let nextValue be IteratorValue(next).
    2356             :       // If nextValue is an abrupt completion, set iteratorRecord.[[Done]] to
    2357             :       //     true.
    2358             :       // ReturnIfAbrupt(nextValue).
    2359             :       Node* const next_value =
    2360             :           iter_assembler.IteratorValue(context, next, fast_iterator_result_map,
    2361          56 :                                        &reject_promise, &var_exception);
    2362             : 
    2363             :       // Let nextPromise be ? Invoke(constructor, "resolve", « nextValue »).
    2364             :       Node* const next_promise =
    2365             :           InvokeResolve(native_context, receiver, next_value, &close_iterator,
    2366          56 :                         &var_exception);
    2367             : 
    2368             :       // Perform ? Invoke(nextPromise, "then", « resolveElement,
    2369             :       //                  resultCapability.[[Reject]] »).
    2370             :       Node* const then =
    2371         112 :           GetProperty(context, next_promise, factory()->then_string());
    2372          56 :       GotoIfException(then, &close_iterator, &var_exception);
    2373             : 
    2374             :       Node* const then_call =
    2375             :           CallJS(CodeFactory::Call(isolate(),
    2376             :                                    ConvertReceiverMode::kNotNullOrUndefined),
    2377          56 :                  context, then, next_promise, resolve, reject);
    2378          56 :       GotoIfException(then_call, &close_iterator, &var_exception);
    2379             : 
    2380             :       // For catch prediction, mark that rejections here are semantically
    2381             :       // handled by the combined Promise.
    2382          56 :       SetPromiseHandledByIfTrue(context, IsDebugActive(), then_call, [=]() {
    2383             :         // Load promiseCapability.[[Promise]]
    2384         112 :         return LoadObjectField(capability, PromiseCapability::kPromiseOffset);
    2385         168 :       });
    2386          56 :       Goto(&loop);
    2387             :     }
    2388             : 
    2389          56 :     BIND(&break_loop);
    2390         112 :     Return(LoadObjectField(capability, PromiseCapability::kPromiseOffset));
    2391             :   }
    2392             : 
    2393          56 :   BIND(&close_iterator);
    2394             :   {
    2395             :     CSA_ASSERT(this, IsNotTheHole(var_exception.value()));
    2396             :     iter_assembler.IteratorCloseOnException(context, iterator, &reject_promise,
    2397          56 :                                             &var_exception);
    2398             :   }
    2399             : 
    2400          56 :   BIND(&reject_promise);
    2401             :   {
    2402             :     Node* const reject =
    2403          56 :         LoadObjectField(capability, PromiseCapability::kRejectOffset);
    2404             :     CallJS(CodeFactory::Call(isolate(), ConvertReceiverMode::kNullOrUndefined),
    2405          56 :            context, reject, UndefinedConstant(), var_exception.value());
    2406             : 
    2407             :     Node* const promise =
    2408          56 :         LoadObjectField(capability, PromiseCapability::kPromiseOffset);
    2409          56 :     Return(promise);
    2410          56 :   }
    2411          56 : }
    2412             : 
    2413             : }  // namespace internal
    2414       86739 : }  // namespace v8

Generated by: LCOV version 1.10