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

Generated by: LCOV version 1.10