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