LCOV - code coverage report
Current view: top level - src/builtins - builtins-promise-gen.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 945 945 100.0 %
Date: 2017-10-20 Functions: 91 91 100.0 %

          Line data    Source code
       1             : // Copyright 2016 the V8 project authors. All rights reserved.
       2             : // Use of this source code is governed by a BSD-style license that can be
       3             : // found in the LICENSE file.
       4             : 
       5             : #include "src/builtins/builtins-promise-gen.h"
       6             : 
       7             : #include "src/builtins/builtins-constructor-gen.h"
       8             : #include "src/builtins/builtins-iterator-gen.h"
       9             : #include "src/builtins/builtins-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             : 
      15             : namespace v8 {
      16             : namespace internal {
      17             : 
      18             : using compiler::Node;
      19             : 
      20         767 : Node* PromiseBuiltinsAssembler::AllocateJSPromise(Node* context) {
      21        1534 :   Node* const native_context = LoadNativeContext(context);
      22             :   Node* const promise_fun =
      23        1534 :       LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX);
      24             :   CSA_ASSERT(this, IsFunctionWithPrototypeSlotMap(LoadMap(promise_fun)));
      25             :   Node* const initial_map =
      26             :       LoadObjectField(promise_fun, JSFunction::kPrototypeOrInitialMapOffset);
      27         767 :   Node* const instance = AllocateJSObjectFromMap(initial_map);
      28         767 :   return instance;
      29             : }
      30             : 
      31        1133 : void PromiseBuiltinsAssembler::PromiseInit(Node* promise) {
      32             :   STATIC_ASSERT(v8::Promise::kPending == 0);
      33             :   StoreObjectFieldNoWriteBarrier(promise, JSPromise::kFlagsOffset,
      34        2266 :                                  SmiConstant(0));
      35             :   for (int i = 0; i < v8::Promise::kEmbedderFieldCount; i++) {
      36             :     int offset = JSPromise::kSize + i * kPointerSize;
      37             :     StoreObjectFieldNoWriteBarrier(promise, offset, SmiConstant(0));
      38             :   }
      39        1133 : }
      40             : 
      41         384 : Node* PromiseBuiltinsAssembler::AllocateAndInitJSPromise(Node* context) {
      42         768 :   return AllocateAndInitJSPromise(context, UndefinedConstant());
      43             : }
      44             : 
      45         501 : Node* PromiseBuiltinsAssembler::AllocateAndInitJSPromise(Node* context,
      46             :                                                          Node* parent) {
      47         501 :   Node* const instance = AllocateJSPromise(context);
      48         501 :   PromiseInit(instance);
      49             : 
      50         501 :   Label out(this);
      51        1002 :   GotoIfNot(IsPromiseHookEnabledOrDebugIsActive(), &out);
      52             :   CallRuntime(Runtime::kPromiseHookInit, context, instance, parent);
      53         501 :   Goto(&out);
      54             : 
      55         501 :   BIND(&out);
      56         501 :   return instance;
      57             : }
      58             : 
      59          37 : Node* PromiseBuiltinsAssembler::AllocateAndSetJSPromise(
      60             :     Node* context, v8::Promise::PromiseState status, Node* result) {
      61          37 :   Node* const instance = AllocateJSPromise(context);
      62             : 
      63          37 :   StoreObjectFieldNoWriteBarrier(instance, JSPromise::kResultOffset, result);
      64             :   STATIC_ASSERT(JSPromise::kStatusShift == 0);
      65             :   StoreObjectFieldNoWriteBarrier(instance, JSPromise::kFlagsOffset,
      66          74 :                                  SmiConstant(status));
      67             :   for (int i = 0; i < v8::Promise::kEmbedderFieldCount; i++) {
      68             :     int offset = JSPromise::kSize + i * kPointerSize;
      69             :     StoreObjectFieldNoWriteBarrier(instance, offset, SmiConstant(0));
      70             :   }
      71             : 
      72             :   Label out(this);
      73          74 :   GotoIfNot(IsPromiseHookEnabledOrDebugIsActive(), &out);
      74             :   CallRuntime(Runtime::kPromiseHookInit, context, instance,
      75          37 :               UndefinedConstant());
      76          37 :   Goto(&out);
      77             : 
      78          37 :   BIND(&out);
      79          37 :   return instance;
      80             : }
      81             : 
      82             : std::pair<Node*, Node*>
      83         427 : PromiseBuiltinsAssembler::CreatePromiseResolvingFunctions(
      84             :     Node* promise, Node* debug_event, Node* native_context) {
      85             :   Node* const promise_context = CreatePromiseResolvingFunctionsContext(
      86         427 :       promise, debug_event, native_context);
      87             :   Node* const map = LoadContextElement(
      88         854 :       native_context, Context::STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX);
      89             :   Node* const resolve_info =
      90         854 :       LoadContextElement(native_context, Context::PROMISE_RESOLVE_SHARED_FUN);
      91             :   Node* const resolve =
      92         427 :       AllocateFunctionWithMapAndContext(map, resolve_info, promise_context);
      93             :   Node* const reject_info =
      94         854 :       LoadContextElement(native_context, Context::PROMISE_REJECT_SHARED_FUN);
      95             :   Node* const reject =
      96         427 :       AllocateFunctionWithMapAndContext(map, reject_info, promise_context);
      97         427 :   return std::make_pair(resolve, reject);
      98             : }
      99             : 
     100         229 : Node* PromiseBuiltinsAssembler::NewPromiseCapability(Node* context,
     101             :                                                      Node* constructor,
     102             :                                                      Node* debug_event) {
     103         229 :   if (debug_event == nullptr) {
     104         272 :     debug_event = TrueConstant();
     105             :   }
     106             : 
     107         229 :   Label if_not_constructor(this, Label::kDeferred);
     108         458 :   GotoIf(TaggedIsSmi(constructor), &if_not_constructor);
     109         687 :   GotoIfNot(IsConstructorMap(LoadMap(constructor)), &if_not_constructor);
     110             : 
     111         458 :   Node* native_context = LoadNativeContext(context);
     112             : 
     113         458 :   Node* map = LoadRoot(Heap::kPromiseCapabilityMapRootIndex);
     114         229 :   Node* capability = AllocateStruct(map);
     115             : 
     116         458 :   VARIABLE(var_result, MachineRepresentation::kTagged);
     117         229 :   var_result.Bind(capability);
     118             : 
     119         229 :   Label if_builtin_promise(this), if_custom_promise(this, Label::kDeferred),
     120         229 :       out(this);
     121             :   Branch(WordEqual(constructor,
     122             :                    LoadContextElement(native_context,
     123         458 :                                       Context::PROMISE_FUNCTION_INDEX)),
     124         229 :          &if_builtin_promise, &if_custom_promise);
     125             : 
     126         229 :   BIND(&if_builtin_promise);
     127             :   {
     128         229 :     Node* promise = AllocateJSPromise(context);
     129         229 :     PromiseInit(promise);
     130         229 :     StoreObjectField(capability, PromiseCapability::kPromiseOffset, promise);
     131             : 
     132         229 :     Node* resolve = nullptr;
     133         229 :     Node* reject = nullptr;
     134             : 
     135         458 :     std::tie(resolve, reject) =
     136             :         CreatePromiseResolvingFunctions(promise, debug_event, native_context);
     137         229 :     StoreObjectField(capability, PromiseCapability::kResolveOffset, resolve);
     138         229 :     StoreObjectField(capability, PromiseCapability::kRejectOffset, reject);
     139             : 
     140         458 :     GotoIfNot(IsPromiseHookEnabledOrDebugIsActive(), &out);
     141             :     CallRuntime(Runtime::kPromiseHookInit, context, promise,
     142         229 :                 UndefinedConstant());
     143         229 :     Goto(&out);
     144             :   }
     145             : 
     146         229 :   BIND(&if_custom_promise);
     147             :   {
     148             :     Label if_notcallable(this, Label::kDeferred);
     149             :     Node* executor_context =
     150         229 :         CreatePromiseGetCapabilitiesExecutorContext(capability, native_context);
     151             :     Node* executor_info = LoadContextElement(
     152         458 :         native_context, Context::PROMISE_GET_CAPABILITIES_EXECUTOR_SHARED_FUN);
     153             :     Node* function_map = LoadContextElement(
     154         458 :         native_context, Context::STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX);
     155             :     Node* executor = AllocateFunctionWithMapAndContext(
     156         229 :         function_map, executor_info, executor_context);
     157             : 
     158             :     Node* promise = ConstructJS(CodeFactory::Construct(isolate()), context,
     159         458 :                                 constructor, executor);
     160             : 
     161             :     Node* resolve =
     162             :         LoadObjectField(capability, PromiseCapability::kResolveOffset);
     163         458 :     GotoIf(TaggedIsSmi(resolve), &if_notcallable);
     164         687 :     GotoIfNot(IsCallableMap(LoadMap(resolve)), &if_notcallable);
     165             : 
     166             :     Node* reject =
     167             :         LoadObjectField(capability, PromiseCapability::kRejectOffset);
     168         458 :     GotoIf(TaggedIsSmi(reject), &if_notcallable);
     169         687 :     GotoIfNot(IsCallableMap(LoadMap(reject)), &if_notcallable);
     170             : 
     171         229 :     StoreObjectField(capability, PromiseCapability::kPromiseOffset, promise);
     172             : 
     173         229 :     Goto(&out);
     174             : 
     175         229 :     BIND(&if_notcallable);
     176             :     StoreObjectField(capability, PromiseCapability::kPromiseOffset,
     177         458 :                      UndefinedConstant());
     178             :     StoreObjectField(capability, PromiseCapability::kResolveOffset,
     179         458 :                      UndefinedConstant());
     180             :     StoreObjectField(capability, PromiseCapability::kRejectOffset,
     181         458 :                      UndefinedConstant());
     182         229 :     ThrowTypeError(context, MessageTemplate::kPromiseNonCallable);
     183             :   }
     184             : 
     185         229 :   BIND(&if_not_constructor);
     186         229 :   ThrowTypeError(context, MessageTemplate::kNotConstructor, constructor);
     187             : 
     188         229 :   BIND(&out);
     189         458 :   return var_result.value();
     190             : }
     191             : 
     192        1077 : void PromiseBuiltinsAssembler::InitializeFunctionContext(Node* native_context,
     193             :                                                          Node* context,
     194             :                                                          int slots) {
     195             :   DCHECK_GE(slots, Context::MIN_CONTEXT_SLOTS);
     196        1077 :   StoreMapNoWriteBarrier(context, Heap::kFunctionContextMapRootIndex);
     197             :   StoreObjectFieldNoWriteBarrier(context, FixedArray::kLengthOffset,
     198        2154 :                                  SmiConstant(slots));
     199             : 
     200             :   Node* const empty_fn =
     201        2154 :       LoadContextElement(native_context, Context::CLOSURE_INDEX);
     202        1077 :   StoreContextElementNoWriteBarrier(context, Context::CLOSURE_INDEX, empty_fn);
     203             :   StoreContextElementNoWriteBarrier(context, Context::PREVIOUS_INDEX,
     204        2154 :                                     UndefinedConstant());
     205             :   StoreContextElementNoWriteBarrier(context, Context::EXTENSION_INDEX,
     206        2154 :                                     TheHoleConstant());
     207             :   StoreContextElementNoWriteBarrier(context, Context::NATIVE_CONTEXT_INDEX,
     208        1077 :                                     native_context);
     209        1077 : }
     210             : 
     211         891 : Node* PromiseBuiltinsAssembler::CreatePromiseContext(Node* native_context,
     212             :                                                      int slots) {
     213             :   DCHECK_GE(slots, Context::MIN_CONTEXT_SLOTS);
     214             : 
     215         891 :   Node* const context = AllocateInNewSpace(FixedArray::SizeFor(slots));
     216         891 :   InitializeFunctionContext(native_context, context, slots);
     217         891 :   return context;
     218             : }
     219             : 
     220         439 : Node* PromiseBuiltinsAssembler::CreatePromiseResolvingFunctionsContext(
     221             :     Node* promise, Node* debug_event, Node* native_context) {
     222             :   Node* const context =
     223         439 :       CreatePromiseContext(native_context, kPromiseContextLength);
     224             :   StoreContextElementNoWriteBarrier(context, kAlreadyVisitedSlot,
     225         878 :                                     SmiConstant(0));
     226         439 :   StoreContextElementNoWriteBarrier(context, kPromiseSlot, promise);
     227         439 :   StoreContextElementNoWriteBarrier(context, kDebugEventSlot, debug_event);
     228         439 :   return context;
     229             : }
     230             : 
     231         235 : Node* PromiseBuiltinsAssembler::CreatePromiseGetCapabilitiesExecutorContext(
     232             :     Node* promise_capability, Node* native_context) {
     233             :   int kContextLength = kCapabilitiesContextLength;
     234         235 :   Node* context = CreatePromiseContext(native_context, kContextLength);
     235             :   StoreContextElementNoWriteBarrier(context, kCapabilitySlot,
     236         235 :                                     promise_capability);
     237         235 :   return context;
     238             : }
     239             : 
     240         688 : Node* PromiseBuiltinsAssembler::PromiseHasHandler(Node* promise) {
     241         688 :   Node* const flags = LoadObjectField(promise, JSPromise::kFlagsOffset);
     242        1376 :   return IsSetWord(SmiUntag(flags), 1 << JSPromise::kHasHandlerBit);
     243             : }
     244             : 
     245         589 : void PromiseBuiltinsAssembler::PromiseSetHasHandler(Node* promise) {
     246         589 :   Node* const flags = LoadObjectField(promise, JSPromise::kFlagsOffset);
     247             :   Node* const new_flags =
     248        1767 :       SmiOr(flags, SmiConstant(1 << JSPromise::kHasHandlerBit));
     249         589 :   StoreObjectFieldNoWriteBarrier(promise, JSPromise::kFlagsOffset, new_flags);
     250         589 : }
     251             : 
     252         496 : Node* PromiseBuiltinsAssembler::IsPromiseStatus(
     253             :     Node* actual, v8::Promise::PromiseState expected) {
     254        1488 :   return Word32Equal(actual, Int32Constant(expected));
     255             : }
     256             : 
     257         248 : Node* PromiseBuiltinsAssembler::PromiseStatus(Node* promise) {
     258             :   STATIC_ASSERT(JSPromise::kStatusShift == 0);
     259         248 :   Node* const flags = LoadObjectField(promise, JSPromise::kFlagsOffset);
     260         992 :   return Word32And(SmiToWord32(flags), Int32Constant(JSPromise::kStatusMask));
     261             : }
     262             : 
     263         775 : void PromiseBuiltinsAssembler::PromiseSetStatus(
     264             :     Node* promise, v8::Promise::PromiseState const status) {
     265             :   CSA_ASSERT(this,
     266             :              IsPromiseStatus(PromiseStatus(promise), v8::Promise::kPending));
     267         775 :   CHECK_NE(status, v8::Promise::kPending);
     268             : 
     269        1550 :   Node* mask = SmiConstant(status);
     270         775 :   Node* const flags = LoadObjectField(promise, JSPromise::kFlagsOffset);
     271             :   StoreObjectFieldNoWriteBarrier(promise, JSPromise::kFlagsOffset,
     272        1550 :                                  SmiOr(flags, mask));
     273         775 : }
     274             : 
     275         186 : void PromiseBuiltinsAssembler::PromiseSetHandledHint(Node* promise) {
     276         186 :   Node* const flags = LoadObjectField(promise, JSPromise::kFlagsOffset);
     277             :   Node* const new_flags =
     278         558 :       SmiOr(flags, SmiConstant(1 << JSPromise::kHandledHintBit));
     279         186 :   StoreObjectFieldNoWriteBarrier(promise, JSPromise::kFlagsOffset, new_flags);
     280         186 : }
     281             : 
     282          93 : Node* PromiseBuiltinsAssembler::SpeciesConstructor(Node* context, Node* object,
     283             :                                                    Node* default_constructor) {
     284          93 :   Isolate* isolate = this->isolate();
     285          93 :   VARIABLE(var_result, MachineRepresentation::kTagged);
     286          93 :   var_result.Bind(default_constructor);
     287             : 
     288             :   // 2. Let C be ? Get(O, "constructor").
     289             :   Node* const constructor =
     290          93 :       GetProperty(context, object, isolate->factory()->constructor_string());
     291             : 
     292             :   // 3. If C is undefined, return defaultConstructor.
     293          93 :   Label out(this);
     294         186 :   GotoIf(IsUndefined(constructor), &out);
     295             : 
     296             :   // 4. If Type(C) is not Object, throw a TypeError exception.
     297             :   ThrowIfNotJSReceiver(context, constructor,
     298          93 :                        MessageTemplate::kConstructorNotReceiver);
     299             : 
     300             :   // 5. Let S be ? Get(C, @@species).
     301             :   Node* const species =
     302          93 :       GetProperty(context, constructor, isolate->factory()->species_symbol());
     303             : 
     304             :   // 6. If S is either undefined or null, return defaultConstructor.
     305         186 :   GotoIf(IsUndefined(species), &out);
     306         186 :   GotoIf(WordEqual(species, NullConstant()), &out);
     307             : 
     308             :   // 7. If IsConstructor(S) is true, return S.
     309          93 :   Label throw_error(this);
     310         186 :   GotoIf(TaggedIsSmi(species), &throw_error);
     311         279 :   GotoIfNot(IsConstructorMap(LoadMap(species)), &throw_error);
     312          93 :   var_result.Bind(species);
     313          93 :   Goto(&out);
     314             : 
     315             :   // 8. Throw a TypeError exception.
     316          93 :   BIND(&throw_error);
     317          93 :   ThrowTypeError(context, MessageTemplate::kSpeciesNotConstructor);
     318             : 
     319          93 :   BIND(&out);
     320         186 :   return var_result.value();
     321             : }
     322             : 
     323         465 : void PromiseBuiltinsAssembler::AppendPromiseCallback(int offset, Node* promise,
     324             :                                                      Node* value) {
     325         465 :   Node* elements = LoadObjectField(promise, offset);
     326         930 :   Node* length = LoadFixedArrayBaseLength(elements);
     327             :   CodeStubAssembler::ParameterMode mode = OptimalParameterMode();
     328             :   length = TaggedToParameter(length, mode);
     329             : 
     330         465 :   Node* delta = IntPtrOrSmiConstant(1, mode);
     331         465 :   Node* new_capacity = IntPtrOrSmiAdd(length, delta, mode);
     332             : 
     333             :   const WriteBarrierMode barrier_mode = UPDATE_WRITE_BARRIER;
     334             :   int additional_offset = 0;
     335             : 
     336             :   ExtractFixedArrayFlags flags;
     337             :   flags |= ExtractFixedArrayFlag::kFixedArrays;
     338             :   Node* new_elements =
     339         465 :       ExtractFixedArray(elements, nullptr, length, new_capacity, flags, mode);
     340             : 
     341             :   StoreFixedArrayElement(new_elements, length, value, barrier_mode,
     342         465 :                          additional_offset, mode);
     343             : 
     344         465 :   StoreObjectField(promise, offset, new_elements);
     345         465 : }
     346             : 
     347          62 : Node* PromiseBuiltinsAssembler::InternalPromiseThen(Node* context,
     348             :                                                     Node* promise,
     349             :                                                     Node* on_resolve,
     350             :                                                     Node* on_reject) {
     351          62 :   Isolate* isolate = this->isolate();
     352             : 
     353             :   // 2. If IsPromise(promise) is false, throw a TypeError exception.
     354             :   ThrowIfNotInstanceType(context, promise, JS_PROMISE_TYPE,
     355          62 :                          "Promise.prototype.then");
     356             : 
     357         124 :   Node* const native_context = LoadNativeContext(context);
     358             :   Node* const promise_fun =
     359         124 :       LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX);
     360             : 
     361             :   // 3. Let C be ? SpeciesConstructor(promise, %Promise%).
     362          62 :   Node* constructor = SpeciesConstructor(context, promise, promise_fun);
     363             : 
     364             :   // 4. Let resultCapability be ? NewPromiseCapability(C).
     365          62 :   Callable call_callable = CodeFactory::Call(isolate);
     366          62 :   Label fast_promise_capability(this), promise_capability(this),
     367          62 :       perform_promise_then(this);
     368         124 :   VARIABLE(var_deferred_promise, MachineRepresentation::kTagged);
     369         124 :   VARIABLE(var_deferred_on_resolve, MachineRepresentation::kTagged);
     370         124 :   VARIABLE(var_deferred_on_reject, MachineRepresentation::kTagged);
     371             : 
     372          62 :   Branch(WordEqual(promise_fun, constructor), &fast_promise_capability,
     373         124 :          &promise_capability);
     374             : 
     375          62 :   BIND(&fast_promise_capability);
     376             :   {
     377          62 :     Node* const deferred_promise = AllocateAndInitJSPromise(context, promise);
     378          62 :     var_deferred_promise.Bind(deferred_promise);
     379         124 :     var_deferred_on_resolve.Bind(UndefinedConstant());
     380         124 :     var_deferred_on_reject.Bind(UndefinedConstant());
     381          62 :     Goto(&perform_promise_then);
     382             :   }
     383             : 
     384          62 :   BIND(&promise_capability);
     385             :   {
     386          62 :     Node* const capability = NewPromiseCapability(context, constructor);
     387             :     var_deferred_promise.Bind(
     388          62 :         LoadObjectField(capability, PromiseCapability::kPromiseOffset));
     389             :     var_deferred_on_resolve.Bind(
     390          62 :         LoadObjectField(capability, PromiseCapability::kResolveOffset));
     391             :     var_deferred_on_reject.Bind(
     392          62 :         LoadObjectField(capability, PromiseCapability::kRejectOffset));
     393          62 :     Goto(&perform_promise_then);
     394             :   }
     395             : 
     396             :   // 5. Return PerformPromiseThen(promise, onFulfilled, onRejected,
     397             :   //    resultCapability).
     398          62 :   BIND(&perform_promise_then);
     399             :   Node* const result = InternalPerformPromiseThen(
     400             :       context, promise, on_resolve, on_reject, var_deferred_promise.value(),
     401          62 :       var_deferred_on_resolve.value(), var_deferred_on_reject.value());
     402          62 :   return result;
     403             : }
     404             : 
     405          93 : Node* PromiseBuiltinsAssembler::InternalPerformPromiseThen(
     406             :     Node* context, Node* promise, Node* on_resolve, Node* on_reject,
     407             :     Node* deferred_promise, Node* deferred_on_resolve,
     408             :     Node* deferred_on_reject) {
     409          93 :   VARIABLE(var_on_resolve, MachineRepresentation::kTagged);
     410         186 :   VARIABLE(var_on_reject, MachineRepresentation::kTagged);
     411             : 
     412          93 :   var_on_resolve.Bind(on_resolve);
     413          93 :   var_on_reject.Bind(on_reject);
     414             : 
     415          93 :   Label out(this), if_onresolvenotcallable(this), onrejectcheck(this),
     416          93 :       append_callbacks(this);
     417         186 :   GotoIf(TaggedIsSmi(on_resolve), &if_onresolvenotcallable);
     418             : 
     419          93 :   Isolate* isolate = this->isolate();
     420         186 :   Node* const on_resolve_map = LoadMap(on_resolve);
     421             :   Branch(IsCallableMap(on_resolve_map), &onrejectcheck,
     422         186 :          &if_onresolvenotcallable);
     423             : 
     424          93 :   BIND(&if_onresolvenotcallable);
     425             :   {
     426             :     Node* const default_resolve_handler_symbol = HeapConstant(
     427             :         isolate->factory()->promise_default_resolve_handler_symbol());
     428          93 :     var_on_resolve.Bind(default_resolve_handler_symbol);
     429          93 :     Goto(&onrejectcheck);
     430             :   }
     431             : 
     432          93 :   BIND(&onrejectcheck);
     433             :   {
     434             :     Label if_onrejectnotcallable(this);
     435         186 :     GotoIf(TaggedIsSmi(on_reject), &if_onrejectnotcallable);
     436             : 
     437         186 :     Node* const on_reject_map = LoadMap(on_reject);
     438             :     Branch(IsCallableMap(on_reject_map), &append_callbacks,
     439         186 :            &if_onrejectnotcallable);
     440             : 
     441          93 :     BIND(&if_onrejectnotcallable);
     442             :     {
     443             :       Node* const default_reject_handler_symbol = HeapConstant(
     444             :           isolate->factory()->promise_default_reject_handler_symbol());
     445          93 :       var_on_reject.Bind(default_reject_handler_symbol);
     446          93 :       Goto(&append_callbacks);
     447          93 :     }
     448             :   }
     449             : 
     450          93 :   BIND(&append_callbacks);
     451             :   {
     452             :     Label fulfilled_check(this);
     453          93 :     Node* const status = PromiseStatus(promise);
     454         186 :     GotoIfNot(IsPromiseStatus(status, v8::Promise::kPending), &fulfilled_check);
     455             : 
     456             :     Node* const existing_deferred_promise =
     457             :         LoadObjectField(promise, JSPromise::kDeferredPromiseOffset);
     458             : 
     459          93 :     Label if_noexistingcallbacks(this), if_existingcallbacks(this);
     460          93 :     Branch(IsUndefined(existing_deferred_promise), &if_noexistingcallbacks,
     461         186 :            &if_existingcallbacks);
     462             : 
     463          93 :     BIND(&if_noexistingcallbacks);
     464             :     {
     465             :       // Store callbacks directly in the slots.
     466             :       StoreObjectField(promise, JSPromise::kDeferredPromiseOffset,
     467          93 :                        deferred_promise);
     468             :       StoreObjectField(promise, JSPromise::kDeferredOnResolveOffset,
     469          93 :                        deferred_on_resolve);
     470             :       StoreObjectField(promise, JSPromise::kDeferredOnRejectOffset,
     471          93 :                        deferred_on_reject);
     472             :       StoreObjectField(promise, JSPromise::kFulfillReactionsOffset,
     473          93 :                        var_on_resolve.value());
     474             :       StoreObjectField(promise, JSPromise::kRejectReactionsOffset,
     475          93 :                        var_on_reject.value());
     476          93 :       Goto(&out);
     477             :     }
     478             : 
     479          93 :     BIND(&if_existingcallbacks);
     480             :     {
     481          93 :       Label if_singlecallback(this), if_multiplecallbacks(this);
     482             :       BranchIfJSObject(existing_deferred_promise, &if_singlecallback,
     483          93 :                        &if_multiplecallbacks);
     484             : 
     485          93 :       BIND(&if_singlecallback);
     486             :       {
     487             :         // Create new FixedArrays to store callbacks, and migrate
     488             :         // existing callbacks.
     489             :         Node* const deferred_promise_arr =
     490         186 :             AllocateFixedArray(PACKED_ELEMENTS, IntPtrConstant(2));
     491             :         StoreFixedArrayElement(deferred_promise_arr, 0,
     492          93 :                                existing_deferred_promise);
     493          93 :         StoreFixedArrayElement(deferred_promise_arr, 1, deferred_promise);
     494             : 
     495             :         Node* const deferred_on_resolve_arr =
     496         186 :             AllocateFixedArray(PACKED_ELEMENTS, IntPtrConstant(2));
     497             :         StoreFixedArrayElement(
     498             :             deferred_on_resolve_arr, 0,
     499          93 :             LoadObjectField(promise, JSPromise::kDeferredOnResolveOffset));
     500          93 :         StoreFixedArrayElement(deferred_on_resolve_arr, 1, deferred_on_resolve);
     501             : 
     502             :         Node* const deferred_on_reject_arr =
     503         186 :             AllocateFixedArray(PACKED_ELEMENTS, IntPtrConstant(2));
     504             :         StoreFixedArrayElement(
     505             :             deferred_on_reject_arr, 0,
     506          93 :             LoadObjectField(promise, JSPromise::kDeferredOnRejectOffset));
     507          93 :         StoreFixedArrayElement(deferred_on_reject_arr, 1, deferred_on_reject);
     508             : 
     509             :         Node* const fulfill_reactions =
     510         186 :             AllocateFixedArray(PACKED_ELEMENTS, IntPtrConstant(2));
     511             :         StoreFixedArrayElement(
     512             :             fulfill_reactions, 0,
     513          93 :             LoadObjectField(promise, JSPromise::kFulfillReactionsOffset));
     514          93 :         StoreFixedArrayElement(fulfill_reactions, 1, var_on_resolve.value());
     515             : 
     516             :         Node* const reject_reactions =
     517         186 :             AllocateFixedArray(PACKED_ELEMENTS, IntPtrConstant(2));
     518             :         StoreFixedArrayElement(
     519             :             reject_reactions, 0,
     520          93 :             LoadObjectField(promise, JSPromise::kRejectReactionsOffset));
     521          93 :         StoreFixedArrayElement(reject_reactions, 1, var_on_reject.value());
     522             : 
     523             :         // Store new FixedArrays in promise.
     524             :         StoreObjectField(promise, JSPromise::kDeferredPromiseOffset,
     525          93 :                          deferred_promise_arr);
     526             :         StoreObjectField(promise, JSPromise::kDeferredOnResolveOffset,
     527          93 :                          deferred_on_resolve_arr);
     528             :         StoreObjectField(promise, JSPromise::kDeferredOnRejectOffset,
     529          93 :                          deferred_on_reject_arr);
     530             :         StoreObjectField(promise, JSPromise::kFulfillReactionsOffset,
     531          93 :                          fulfill_reactions);
     532             :         StoreObjectField(promise, JSPromise::kRejectReactionsOffset,
     533          93 :                          reject_reactions);
     534          93 :         Goto(&out);
     535             :       }
     536             : 
     537          93 :       BIND(&if_multiplecallbacks);
     538             :       {
     539             :         AppendPromiseCallback(JSPromise::kDeferredPromiseOffset, promise,
     540          93 :                               deferred_promise);
     541             :         AppendPromiseCallback(JSPromise::kDeferredOnResolveOffset, promise,
     542          93 :                               deferred_on_resolve);
     543             :         AppendPromiseCallback(JSPromise::kDeferredOnRejectOffset, promise,
     544          93 :                               deferred_on_reject);
     545             :         AppendPromiseCallback(JSPromise::kFulfillReactionsOffset, promise,
     546          93 :                               var_on_resolve.value());
     547             :         AppendPromiseCallback(JSPromise::kRejectReactionsOffset, promise,
     548          93 :                               var_on_reject.value());
     549          93 :         Goto(&out);
     550          93 :       }
     551             :     }
     552             : 
     553          93 :     BIND(&fulfilled_check);
     554             :     {
     555             :       Label reject(this);
     556             :       Node* const result = LoadObjectField(promise, JSPromise::kResultOffset);
     557         186 :       GotoIfNot(IsPromiseStatus(status, v8::Promise::kFulfilled), &reject);
     558             : 
     559             :       Node* info = AllocatePromiseReactionJobInfo(
     560             :           result, var_on_resolve.value(), deferred_promise, deferred_on_resolve,
     561          93 :           deferred_on_reject, context);
     562             :       // TODO(gsathya): Move this to TF
     563             :       CallRuntime(Runtime::kEnqueuePromiseReactionJob, context, info);
     564          93 :       Goto(&out);
     565             : 
     566          93 :       BIND(&reject);
     567             :       {
     568             :         CSA_ASSERT(this, IsPromiseStatus(status, v8::Promise::kRejected));
     569          93 :         Node* const has_handler = PromiseHasHandler(promise);
     570             :         Label enqueue(this);
     571             : 
     572             :         // TODO(gsathya): Fold these runtime calls and move to TF.
     573          93 :         GotoIf(has_handler, &enqueue);
     574             :         CallRuntime(Runtime::kPromiseRevokeReject, context, promise);
     575          93 :         Goto(&enqueue);
     576             : 
     577          93 :         BIND(&enqueue);
     578             :         {
     579             :           Node* info = AllocatePromiseReactionJobInfo(
     580             :               result, var_on_reject.value(), deferred_promise,
     581          93 :               deferred_on_resolve, deferred_on_reject, context);
     582             :           // TODO(gsathya): Move this to TF
     583             :           CallRuntime(Runtime::kEnqueuePromiseReactionJob, context, info);
     584          93 :           Goto(&out);
     585          93 :         }
     586          93 :       }
     587          93 :     }
     588             :   }
     589             : 
     590          93 :   BIND(&out);
     591          93 :   PromiseSetHasHandler(promise);
     592          93 :   return deferred_promise;
     593             : }
     594             : 
     595             : // Promise fast path implementations rely on unmodified JSPromise instances.
     596             : // We use a fairly coarse granularity for this and simply check whether both
     597             : // the promise itself is unmodified (i.e. its map has not changed) and its
     598             : // prototype is unmodified.
     599             : // TODO(gsathya): Refactor this out to prevent code dupe with builtins-regexp
     600          31 : void PromiseBuiltinsAssembler::BranchIfFastPath(Node* context, Node* promise,
     601             :                                                 Label* if_isunmodified,
     602             :                                                 Label* if_ismodified) {
     603          62 :   Node* const native_context = LoadNativeContext(context);
     604             :   Node* const promise_fun =
     605          62 :       LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX);
     606             :   BranchIfFastPath(native_context, promise_fun, promise, if_isunmodified,
     607          31 :                    if_ismodified);
     608          31 : }
     609             : 
     610         217 : void PromiseBuiltinsAssembler::BranchIfFastPath(Node* native_context,
     611             :                                                 Node* promise_fun,
     612             :                                                 Node* promise,
     613             :                                                 Label* if_isunmodified,
     614             :                                                 Label* if_ismodified) {
     615             :   CSA_ASSERT(this, IsNativeContext(native_context));
     616             :   CSA_ASSERT(this,
     617             :              WordEqual(promise_fun,
     618             :                        LoadContextElement(native_context,
     619             :                                           Context::PROMISE_FUNCTION_INDEX)));
     620             : 
     621         434 :   Node* const map = LoadMap(promise);
     622             :   Node* const initial_map =
     623             :       LoadObjectField(promise_fun, JSFunction::kPrototypeOrInitialMapOffset);
     624         434 :   Node* const has_initialmap = WordEqual(map, initial_map);
     625             : 
     626         217 :   GotoIfNot(has_initialmap, if_ismodified);
     627             : 
     628             :   Node* const initial_proto_initial_map =
     629         434 :       LoadContextElement(native_context, Context::PROMISE_PROTOTYPE_MAP_INDEX);
     630         434 :   Node* const proto_map = LoadMap(CAST(LoadMapPrototype(map)));
     631             :   Node* const proto_has_initialmap =
     632         434 :       WordEqual(proto_map, initial_proto_initial_map);
     633             : 
     634         217 :   Branch(proto_has_initialmap, if_isunmodified, if_ismodified);
     635         217 : }
     636             : 
     637         161 : Node* PromiseBuiltinsAssembler::AllocatePromiseResolveThenableJobInfo(
     638             :     Node* thenable, Node* then, Node* resolve, Node* reject, Node* context) {
     639         161 :   Node* const info = Allocate(PromiseResolveThenableJobInfo::kSize);
     640             :   StoreMapNoWriteBarrier(info,
     641         161 :                          Heap::kPromiseResolveThenableJobInfoMapRootIndex);
     642             :   StoreObjectFieldNoWriteBarrier(
     643         161 :       info, PromiseResolveThenableJobInfo::kThenableOffset, thenable);
     644             :   StoreObjectFieldNoWriteBarrier(
     645         161 :       info, PromiseResolveThenableJobInfo::kThenOffset, then);
     646             :   StoreObjectFieldNoWriteBarrier(
     647         161 :       info, PromiseResolveThenableJobInfo::kResolveOffset, resolve);
     648             :   StoreObjectFieldNoWriteBarrier(
     649         161 :       info, PromiseResolveThenableJobInfo::kRejectOffset, reject);
     650             :   StoreObjectFieldNoWriteBarrier(
     651         161 :       info, PromiseResolveThenableJobInfo::kContextOffset, context);
     652         161 :   return info;
     653             : }
     654             : 
     655         155 : void PromiseBuiltinsAssembler::InternalResolvePromise(Node* context,
     656             :                                                       Node* promise,
     657             :                                                       Node* result) {
     658         155 :   Isolate* isolate = this->isolate();
     659             : 
     660         155 :   VARIABLE(var_reason, MachineRepresentation::kTagged);
     661         310 :   VARIABLE(var_then, MachineRepresentation::kTagged);
     662             : 
     663         155 :   Label do_enqueue(this), fulfill(this), if_nocycle(this),
     664         155 :       if_cycle(this, Label::kDeferred),
     665         155 :       if_rejectpromise(this, Label::kDeferred), out(this);
     666             : 
     667         155 :   Label cycle_check(this);
     668         310 :   GotoIfNot(IsPromiseHookEnabledOrDebugIsActive(), &cycle_check);
     669             :   CallRuntime(Runtime::kPromiseHookResolve, context, promise);
     670         155 :   Goto(&cycle_check);
     671             : 
     672         155 :   BIND(&cycle_check);
     673             :   // 6. If SameValue(resolution, promise) is true, then
     674         155 :   BranchIfSameValue(promise, result, &if_cycle, &if_nocycle);
     675         155 :   BIND(&if_nocycle);
     676             : 
     677             :   // 7. If Type(resolution) is not Object, then
     678         310 :   GotoIf(TaggedIsSmi(result), &fulfill);
     679         310 :   GotoIfNot(IsJSReceiver(result), &fulfill);
     680             : 
     681         155 :   Label if_nativepromise(this), if_notnativepromise(this, Label::kDeferred);
     682         310 :   Node* const native_context = LoadNativeContext(context);
     683             :   Node* const promise_fun =
     684         310 :       LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX);
     685             :   BranchIfFastPath(native_context, promise_fun, result, &if_nativepromise,
     686         155 :                    &if_notnativepromise);
     687             : 
     688             :   // Resolution is a native promise and if it's already resolved or
     689             :   // rejected, shortcircuit the resolution procedure by directly
     690             :   // reusing the value from the promise.
     691         155 :   BIND(&if_nativepromise);
     692             :   {
     693         155 :     Node* const thenable_status = PromiseStatus(result);
     694             :     Node* const thenable_value =
     695             :         LoadObjectField(result, JSPromise::kResultOffset);
     696             : 
     697             :     Label if_isnotpending(this);
     698             :     GotoIfNot(IsPromiseStatus(thenable_status, v8::Promise::kPending),
     699         310 :               &if_isnotpending);
     700             : 
     701             :     // TODO(gsathya): Use a marker here instead of the actual then
     702             :     // callback, and check for the marker in PromiseResolveThenableJob
     703             :     // and perform PromiseThen.
     704             :     Node* const then =
     705         310 :         LoadContextElement(native_context, Context::PROMISE_THEN_INDEX);
     706         155 :     var_then.Bind(then);
     707         155 :     Goto(&do_enqueue);
     708             : 
     709         155 :     BIND(&if_isnotpending);
     710             :     {
     711         155 :       Label if_fulfilled(this), if_rejected(this);
     712             :       Branch(IsPromiseStatus(thenable_status, v8::Promise::kFulfilled),
     713         310 :              &if_fulfilled, &if_rejected);
     714             : 
     715         155 :       BIND(&if_fulfilled);
     716             :       {
     717             :         PromiseFulfill(context, promise, thenable_value,
     718         155 :                        v8::Promise::kFulfilled);
     719         155 :         PromiseSetHasHandler(promise);
     720         155 :         Goto(&out);
     721             :       }
     722             : 
     723         155 :       BIND(&if_rejected);
     724             :       {
     725             :         Label reject(this);
     726         155 :         Node* const has_handler = PromiseHasHandler(result);
     727             : 
     728             :         // Promise has already been rejected, but had no handler.
     729             :         // Revoke previously triggered reject event.
     730         155 :         GotoIf(has_handler, &reject);
     731             :         CallRuntime(Runtime::kPromiseRevokeReject, context, result);
     732         155 :         Goto(&reject);
     733             : 
     734         155 :         BIND(&reject);
     735             :         // Don't cause a debug event as this case is forwarding a rejection.
     736         155 :         InternalPromiseReject(context, promise, thenable_value, false);
     737         155 :         PromiseSetHasHandler(result);
     738         155 :         Goto(&out);
     739         155 :       }
     740         155 :     }
     741             :   }
     742             : 
     743         155 :   BIND(&if_notnativepromise);
     744             :   {
     745             :     // 8. Let then be Get(resolution, "then").
     746             :     Node* const then =
     747         155 :         GetProperty(context, result, isolate->factory()->then_string());
     748             : 
     749             :     // 9. If then is an abrupt completion, then
     750         155 :     GotoIfException(then, &if_rejectpromise, &var_reason);
     751             : 
     752             :     // 11. If IsCallable(thenAction) is false, then
     753         310 :     GotoIf(TaggedIsSmi(then), &fulfill);
     754         310 :     Node* const then_map = LoadMap(then);
     755         310 :     GotoIfNot(IsCallableMap(then_map), &fulfill);
     756         155 :     var_then.Bind(then);
     757         155 :     Goto(&do_enqueue);
     758             :   }
     759             : 
     760         155 :   BIND(&do_enqueue);
     761             :   {
     762             :     // TODO(gsathya): Add fast path for native promises with unmodified
     763             :     // PromiseThen (which don't need these resolving functions, but
     764             :     // instead can just call resolve/reject directly).
     765         155 :     Node* resolve = nullptr;
     766         155 :     Node* reject = nullptr;
     767         310 :     std::tie(resolve, reject) = CreatePromiseResolvingFunctions(
     768         310 :         promise, FalseConstant(), native_context);
     769             : 
     770             :     Node* const info = AllocatePromiseResolveThenableJobInfo(
     771         155 :         result, var_then.value(), resolve, reject, context);
     772             : 
     773             :     Label enqueue(this);
     774         310 :     GotoIfNot(IsDebugActive(), &enqueue);
     775             : 
     776         310 :     GotoIf(TaggedIsSmi(result), &enqueue);
     777         310 :     GotoIfNot(HasInstanceType(result, JS_PROMISE_TYPE), &enqueue);
     778             : 
     779             :     // Mark the dependency of the new promise on the resolution
     780             :     Node* const key =
     781             :         HeapConstant(isolate->factory()->promise_handled_by_symbol());
     782             :     CallRuntime(Runtime::kSetProperty, context, result, key, promise,
     783         155 :                 SmiConstant(Smi::FromEnum(LanguageMode::kStrict)));
     784         155 :     Goto(&enqueue);
     785             : 
     786             :     // 12. Perform EnqueueJob("PromiseJobs",
     787             :     // PromiseResolveThenableJob, « promise, resolution, thenAction»).
     788         155 :     BIND(&enqueue);
     789             :     // TODO(gsathya): Move this to TF
     790             :     CallRuntime(Runtime::kEnqueuePromiseResolveThenableJob, context, info);
     791         155 :     Goto(&out);
     792             :   }
     793             : 
     794             :   // 7.b Return FulfillPromise(promise, resolution).
     795         155 :   BIND(&fulfill);
     796             :   {
     797         155 :     PromiseFulfill(context, promise, result, v8::Promise::kFulfilled);
     798         155 :     Goto(&out);
     799             :   }
     800             : 
     801         155 :   BIND(&if_cycle);
     802             :   {
     803             :     // 6.a Let selfResolutionError be a newly created TypeError object.
     804         310 :     Node* const message_id = SmiConstant(MessageTemplate::kPromiseCyclic);
     805             :     Node* const error =
     806             :         CallRuntime(Runtime::kNewTypeError, context, message_id, result);
     807         155 :     var_reason.Bind(error);
     808             : 
     809             :     // 6.b Return RejectPromise(promise, selfResolutionError).
     810         155 :     Goto(&if_rejectpromise);
     811             :   }
     812             : 
     813             :   // 9.a Return RejectPromise(promise, then.[[Value]]).
     814         155 :   BIND(&if_rejectpromise);
     815             :   {
     816             :     // Don't cause a debug event as this case is forwarding a rejection.
     817         155 :     InternalPromiseReject(context, promise, var_reason.value(), false);
     818         155 :     Goto(&out);
     819             :   }
     820             : 
     821         310 :   BIND(&out);
     822         155 : }
     823             : 
     824         775 : void PromiseBuiltinsAssembler::PromiseFulfill(
     825             :     Node* context, Node* promise, Node* result,
     826             :     v8::Promise::PromiseState status) {
     827        1550 :   Label do_promisereset(this), debug_async_event_enqueue_recurring(this);
     828             : 
     829             :   Node* const deferred_promise =
     830         775 :       LoadObjectField(promise, JSPromise::kDeferredPromiseOffset);
     831             : 
     832        1550 :   GotoIf(IsUndefined(deferred_promise), &debug_async_event_enqueue_recurring);
     833             : 
     834             :   Node* const tasks =
     835             :       status == v8::Promise::kFulfilled
     836             :           ? LoadObjectField(promise, JSPromise::kFulfillReactionsOffset)
     837         775 :           : LoadObjectField(promise, JSPromise::kRejectReactionsOffset);
     838             : 
     839             :   Node* const deferred_on_resolve =
     840             :       LoadObjectField(promise, JSPromise::kDeferredOnResolveOffset);
     841             :   Node* const deferred_on_reject =
     842             :       LoadObjectField(promise, JSPromise::kDeferredOnRejectOffset);
     843             : 
     844             :   Node* const info = AllocatePromiseReactionJobInfo(
     845             :       result, tasks, deferred_promise, deferred_on_resolve, deferred_on_reject,
     846         775 :       context);
     847             : 
     848             :   CallRuntime(Runtime::kEnqueuePromiseReactionJob, context, info);
     849         775 :   Goto(&debug_async_event_enqueue_recurring);
     850             : 
     851         775 :   BIND(&debug_async_event_enqueue_recurring);
     852             :   {
     853        1550 :     GotoIfNot(IsDebugActive(), &do_promisereset);
     854             :     CallRuntime(Runtime::kDebugAsyncEventEnqueueRecurring, context, promise,
     855         775 :                 SmiConstant(status));
     856         775 :     Goto(&do_promisereset);
     857             :   }
     858             : 
     859         775 :   BIND(&do_promisereset);
     860             :   {
     861         775 :     PromiseSetStatus(promise, status);
     862         775 :     StoreObjectField(promise, JSPromise::kResultOffset, result);
     863             :     StoreObjectFieldRoot(promise, JSPromise::kDeferredPromiseOffset,
     864         775 :                          Heap::kUndefinedValueRootIndex);
     865             :     StoreObjectFieldRoot(promise, JSPromise::kDeferredOnResolveOffset,
     866         775 :                          Heap::kUndefinedValueRootIndex);
     867             :     StoreObjectFieldRoot(promise, JSPromise::kDeferredOnRejectOffset,
     868         775 :                          Heap::kUndefinedValueRootIndex);
     869             :     StoreObjectFieldRoot(promise, JSPromise::kFulfillReactionsOffset,
     870         775 :                          Heap::kUndefinedValueRootIndex);
     871             :     StoreObjectFieldRoot(promise, JSPromise::kRejectReactionsOffset,
     872         775 :                          Heap::kUndefinedValueRootIndex);
     873         775 :   }
     874         775 : }
     875             : 
     876          31 : void PromiseBuiltinsAssembler::BranchIfAccessCheckFailed(
     877             :     Node* context, Node* native_context, Node* promise_constructor,
     878             :     Node* executor, Label* if_noaccess) {
     879          31 :   VARIABLE(var_executor, MachineRepresentation::kTagged);
     880          31 :   var_executor.Bind(executor);
     881          31 :   Label has_access(this), call_runtime(this, Label::kDeferred);
     882             : 
     883             :   // If executor is a bound function, load the bound function until we've
     884             :   // reached an actual function.
     885          31 :   Label found_function(this), loop_over_bound_function(this, &var_executor);
     886          31 :   Goto(&loop_over_bound_function);
     887          31 :   BIND(&loop_over_bound_function);
     888             :   {
     889          93 :     Node* executor_type = LoadInstanceType(var_executor.value());
     890          62 :     GotoIf(InstanceTypeEqual(executor_type, JS_FUNCTION_TYPE), &found_function);
     891             :     GotoIfNot(InstanceTypeEqual(executor_type, JS_BOUND_FUNCTION_TYPE),
     892          62 :               &call_runtime);
     893             :     var_executor.Bind(LoadObjectField(
     894          62 :         var_executor.value(), JSBoundFunction::kBoundTargetFunctionOffset));
     895          31 :     Goto(&loop_over_bound_function);
     896             :   }
     897             : 
     898             :   // Load the context from the function and compare it to the Promise
     899             :   // constructor's context. If they match, everything is fine, otherwise, bail
     900             :   // out to the runtime.
     901          31 :   BIND(&found_function);
     902             :   {
     903             :     Node* function_context =
     904          31 :         LoadObjectField(var_executor.value(), JSFunction::kContextOffset);
     905          62 :     Node* native_function_context = LoadNativeContext(function_context);
     906          31 :     Branch(WordEqual(native_context, native_function_context), &has_access,
     907          62 :            &call_runtime);
     908             :   }
     909             : 
     910          31 :   BIND(&call_runtime);
     911             :   {
     912             :     Branch(WordEqual(CallRuntime(Runtime::kAllowDynamicFunction, context,
     913             :                                  promise_constructor),
     914          31 :                      BooleanConstant(true)),
     915          31 :            &has_access, if_noaccess);
     916             :   }
     917             : 
     918          62 :   BIND(&has_access);
     919          31 : }
     920             : 
     921          93 : void PromiseBuiltinsAssembler::InternalPromiseReject(Node* context,
     922             :                                                      Node* promise, Node* value,
     923             :                                                      Node* debug_event) {
     924          93 :   Label out(this);
     925         186 :   GotoIfNot(IsDebugActive(), &out);
     926         186 :   GotoIfNot(WordEqual(TrueConstant(), debug_event), &out);
     927             :   CallRuntime(Runtime::kDebugPromiseReject, context, promise, value);
     928          93 :   Goto(&out);
     929             : 
     930          93 :   BIND(&out);
     931          93 :   InternalPromiseReject(context, promise, value, false);
     932          93 : }
     933             : 
     934             : // This duplicates a lot of logic from PromiseRejectEvent in
     935             : // runtime-promise.cc
     936         434 : void PromiseBuiltinsAssembler::InternalPromiseReject(Node* context,
     937             :                                                      Node* promise, Node* value,
     938             :                                                      bool debug_event) {
     939         868 :   Label fulfill(this), exit(this);
     940             : 
     941         868 :   GotoIfNot(IsPromiseHookEnabledOrDebugIsActive(), &fulfill);
     942         434 :   if (debug_event) {
     943             :     CallRuntime(Runtime::kDebugPromiseReject, context, promise, value);
     944             :   }
     945             :   CallRuntime(Runtime::kPromiseHookResolve, context, promise);
     946         434 :   Goto(&fulfill);
     947             : 
     948         434 :   BIND(&fulfill);
     949         434 :   PromiseFulfill(context, promise, value, v8::Promise::kRejected);
     950             : 
     951         868 :   GotoIf(PromiseHasHandler(promise), &exit);
     952             :   CallRuntime(Runtime::kReportPromiseReject, context, promise, value);
     953         434 :   Goto(&exit);
     954             : 
     955         868 :   BIND(&exit);
     956         434 : }
     957             : 
     958          62 : void PromiseBuiltinsAssembler::SetForwardingHandlerIfTrue(
     959             :     Node* context, Node* condition, const NodeGenerator& object) {
     960          62 :   Label done(this);
     961          62 :   GotoIfNot(condition, &done);
     962             :   CallRuntime(Runtime::kSetProperty, context, object(),
     963             :               HeapConstant(factory()->promise_forwarding_handler_symbol()),
     964             :               TrueConstant(),
     965         124 :               SmiConstant(Smi::FromEnum(LanguageMode::kStrict)));
     966          62 :   Goto(&done);
     967          62 :   BIND(&done);
     968          62 : }
     969             : 
     970          62 : void PromiseBuiltinsAssembler::SetPromiseHandledByIfTrue(
     971             :     Node* context, Node* condition, Node* promise,
     972             :     const NodeGenerator& handled_by) {
     973          62 :   Label done(this);
     974          62 :   GotoIfNot(condition, &done);
     975         124 :   GotoIf(TaggedIsSmi(promise), &done);
     976         124 :   GotoIfNot(HasInstanceType(promise, JS_PROMISE_TYPE), &done);
     977             :   CallRuntime(Runtime::kSetProperty, context, promise,
     978             :               HeapConstant(factory()->promise_handled_by_symbol()),
     979          62 :               handled_by(), SmiConstant(Smi::FromEnum(LanguageMode::kStrict)));
     980          62 :   Goto(&done);
     981          62 :   BIND(&done);
     982          62 : }
     983             : 
     984             : // ES#sec-promise-reject-functions
     985             : // Promise Reject Functions
     986         124 : TF_BUILTIN(PromiseRejectClosure, PromiseBuiltinsAssembler) {
     987             :   Node* const value = Parameter(Descriptor::kValue);
     988             :   Node* const context = Parameter(Descriptor::kContext);
     989             : 
     990             :   Label out(this);
     991             : 
     992             :   // 3. Let alreadyResolved be F.[[AlreadyResolved]].
     993             :   int has_already_visited_slot = kAlreadyVisitedSlot;
     994             : 
     995             :   Node* const has_already_visited =
     996          62 :       LoadContextElement(context, has_already_visited_slot);
     997             : 
     998             :   // 4. If alreadyResolved.[[Value]] is true, return undefined.
     999          93 :   GotoIf(SmiEqual(has_already_visited, SmiConstant(1)), &out);
    1000             : 
    1001             :   // 5.Set alreadyResolved.[[Value]] to true.
    1002             :   StoreContextElementNoWriteBarrier(context, has_already_visited_slot,
    1003          62 :                                     SmiConstant(1));
    1004             : 
    1005             :   // 2. Let promise be F.[[Promise]].
    1006             :   Node* const promise =
    1007          93 :       LoadContextElement(context, IntPtrConstant(kPromiseSlot));
    1008             :   Node* const debug_event =
    1009          93 :       LoadContextElement(context, IntPtrConstant(kDebugEventSlot));
    1010             : 
    1011          31 :   InternalPromiseReject(context, promise, value, debug_event);
    1012          62 :   Return(UndefinedConstant());
    1013             : 
    1014          31 :   BIND(&out);
    1015          62 :   Return(UndefinedConstant());
    1016          31 : }
    1017             : 
    1018             : // ES6 #sec-promise-executor
    1019         124 : TF_BUILTIN(PromiseConstructor, PromiseBuiltinsAssembler) {
    1020             :   Node* const executor = Parameter(Descriptor::kExecutor);
    1021             :   Node* const new_target = Parameter(Descriptor::kNewTarget);
    1022             :   Node* const context = Parameter(Descriptor::kContext);
    1023          31 :   Isolate* isolate = this->isolate();
    1024             : 
    1025             :   Label if_targetisundefined(this, Label::kDeferred);
    1026             : 
    1027          62 :   GotoIf(IsUndefined(new_target), &if_targetisundefined);
    1028             : 
    1029          31 :   Label if_notcallable(this, Label::kDeferred);
    1030             : 
    1031          62 :   GotoIf(TaggedIsSmi(executor), &if_notcallable);
    1032             : 
    1033          62 :   Node* const executor_map = LoadMap(executor);
    1034          62 :   GotoIfNot(IsCallableMap(executor_map), &if_notcallable);
    1035             : 
    1036          62 :   Node* const native_context = LoadNativeContext(context);
    1037             :   Node* const promise_fun =
    1038          62 :       LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX);
    1039          31 :   Node* const is_debug_active = IsDebugActive();
    1040          31 :   Label if_targetisnotmodified(this),
    1041          31 :       if_targetismodified(this, Label::kDeferred), run_executor(this),
    1042          31 :       debug_push(this), if_noaccess(this, Label::kDeferred);
    1043             : 
    1044             :   BranchIfAccessCheckFailed(context, native_context, promise_fun, executor,
    1045          31 :                             &if_noaccess);
    1046             : 
    1047          31 :   Branch(WordEqual(promise_fun, new_target), &if_targetisnotmodified,
    1048          62 :          &if_targetismodified);
    1049             : 
    1050          62 :   VARIABLE(var_result, MachineRepresentation::kTagged);
    1051          62 :   VARIABLE(var_reject_call, MachineRepresentation::kTagged);
    1052          62 :   VARIABLE(var_reason, MachineRepresentation::kTagged);
    1053             : 
    1054          31 :   BIND(&if_targetisnotmodified);
    1055             :   {
    1056          31 :     Node* const instance = AllocateAndInitJSPromise(context);
    1057          31 :     var_result.Bind(instance);
    1058          31 :     Goto(&debug_push);
    1059             :   }
    1060             : 
    1061          31 :   BIND(&if_targetismodified);
    1062             :   {
    1063             :     ConstructorBuiltinsAssembler constructor_assembler(this->state());
    1064             :     Node* const instance = constructor_assembler.EmitFastNewObject(
    1065          31 :         context, promise_fun, new_target);
    1066          31 :     PromiseInit(instance);
    1067          31 :     var_result.Bind(instance);
    1068             : 
    1069          62 :     GotoIfNot(IsPromiseHookEnabledOrDebugIsActive(), &debug_push);
    1070             :     CallRuntime(Runtime::kPromiseHookInit, context, instance,
    1071          31 :                 UndefinedConstant());
    1072          31 :     Goto(&debug_push);
    1073             :   }
    1074             : 
    1075          31 :   BIND(&debug_push);
    1076             :   {
    1077          31 :     GotoIfNot(is_debug_active, &run_executor);
    1078          31 :     CallRuntime(Runtime::kDebugPushPromise, context, var_result.value());
    1079          31 :     Goto(&run_executor);
    1080             :   }
    1081             : 
    1082          31 :   BIND(&run_executor);
    1083             :   {
    1084          31 :     Label out(this), if_rejectpromise(this), debug_pop(this, Label::kDeferred);
    1085             : 
    1086             :     Node *resolve, *reject;
    1087          62 :     std::tie(resolve, reject) = CreatePromiseResolvingFunctions(
    1088          93 :         var_result.value(), TrueConstant(), native_context);
    1089          31 :     Callable call_callable = CodeFactory::Call(isolate);
    1090             : 
    1091             :     Node* const maybe_exception = CallJS(call_callable, context, executor,
    1092          62 :                                          UndefinedConstant(), resolve, reject);
    1093             : 
    1094          31 :     GotoIfException(maybe_exception, &if_rejectpromise, &var_reason);
    1095          31 :     Branch(is_debug_active, &debug_pop, &out);
    1096             : 
    1097          31 :     BIND(&if_rejectpromise);
    1098             :     {
    1099          31 :       Callable call_callable = CodeFactory::Call(isolate);
    1100             :       CallJS(call_callable, context, reject, UndefinedConstant(),
    1101          62 :              var_reason.value());
    1102          31 :       Branch(is_debug_active, &debug_pop, &out);
    1103             :     }
    1104             : 
    1105          31 :     BIND(&debug_pop);
    1106             :     {
    1107             :       CallRuntime(Runtime::kDebugPopPromise, context);
    1108          31 :       Goto(&out);
    1109             :     }
    1110          31 :     BIND(&out);
    1111          93 :     Return(var_result.value());
    1112             :   }
    1113             : 
    1114             :   // 1. If NewTarget is undefined, throw a TypeError exception.
    1115          31 :   BIND(&if_targetisundefined);
    1116          31 :   ThrowTypeError(context, MessageTemplate::kNotAPromise, new_target);
    1117             : 
    1118             :   // 2. If IsCallable(executor) is false, throw a TypeError exception.
    1119          31 :   BIND(&if_notcallable);
    1120          31 :   ThrowTypeError(context, MessageTemplate::kResolverNotAFunction, executor);
    1121             : 
    1122             :   // Silently fail if the stack looks fishy.
    1123          31 :   BIND(&if_noaccess);
    1124             :   {
    1125             :     Node* const counter_id =
    1126          62 :         SmiConstant(v8::Isolate::kPromiseConstructorReturnedUndefined);
    1127             :     CallRuntime(Runtime::kIncrementUseCounter, context, counter_id);
    1128          62 :     Return(UndefinedConstant());
    1129          31 :   }
    1130          31 : }
    1131             : 
    1132         124 : TF_BUILTIN(PromiseInternalConstructor, PromiseBuiltinsAssembler) {
    1133             :   Node* const parent = Parameter(Descriptor::kParent);
    1134             :   Node* const context = Parameter(Descriptor::kContext);
    1135          62 :   Return(AllocateAndInitJSPromise(context, parent));
    1136          31 : }
    1137             : 
    1138             : // ES#sec-promise.prototype.then
    1139             : // Promise.prototype.catch ( onFulfilled, onRejected )
    1140         124 : TF_BUILTIN(PromiseThen, PromiseBuiltinsAssembler) {
    1141             :   // 1. Let promise be the this value.
    1142             :   Node* const promise = Parameter(Descriptor::kReceiver);
    1143             :   Node* const on_resolve = Parameter(Descriptor::kOnFullfilled);
    1144             :   Node* const on_reject = Parameter(Descriptor::kOnRejected);
    1145             :   Node* const context = Parameter(Descriptor::kContext);
    1146             : 
    1147             :   Node* const result =
    1148          31 :       InternalPromiseThen(context, promise, on_resolve, on_reject);
    1149          31 :   Return(result);
    1150          31 : }
    1151             : 
    1152             : // ES#sec-promise-resolve-functions
    1153             : // Promise Resolve Functions
    1154         124 : TF_BUILTIN(PromiseResolveClosure, PromiseBuiltinsAssembler) {
    1155             :   Node* const value = Parameter(Descriptor::kValue);
    1156             :   Node* const context = Parameter(Descriptor::kContext);
    1157             : 
    1158             :   Label out(this);
    1159             : 
    1160             :   // 3. Let alreadyResolved be F.[[AlreadyResolved]].
    1161             :   int has_already_visited_slot = kAlreadyVisitedSlot;
    1162             : 
    1163             :   Node* const has_already_visited =
    1164          62 :       LoadContextElement(context, has_already_visited_slot);
    1165             : 
    1166             :   // 4. If alreadyResolved.[[Value]] is true, return undefined.
    1167          93 :   GotoIf(SmiEqual(has_already_visited, SmiConstant(1)), &out);
    1168             : 
    1169             :   // 5.Set alreadyResolved.[[Value]] to true.
    1170             :   StoreContextElementNoWriteBarrier(context, has_already_visited_slot,
    1171          62 :                                     SmiConstant(1));
    1172             : 
    1173             :   // 2. Let promise be F.[[Promise]].
    1174             :   Node* const promise =
    1175          93 :       LoadContextElement(context, IntPtrConstant(kPromiseSlot));
    1176             : 
    1177          31 :   InternalResolvePromise(context, promise, value);
    1178          62 :   Return(UndefinedConstant());
    1179             : 
    1180          31 :   BIND(&out);
    1181          62 :   Return(UndefinedConstant());
    1182          31 : }
    1183             : 
    1184             : // ES #sec-fulfillpromise
    1185         124 : TF_BUILTIN(ResolvePromise, PromiseBuiltinsAssembler) {
    1186             :   Node* const promise = Parameter(Descriptor::kPromise);
    1187             :   Node* const result = Parameter(Descriptor::kValue);
    1188             :   Node* const context = Parameter(Descriptor::kContext);
    1189             : 
    1190          31 :   InternalResolvePromise(context, promise, result);
    1191          62 :   Return(UndefinedConstant());
    1192          31 : }
    1193             : 
    1194         124 : TF_BUILTIN(PromiseHandleReject, PromiseBuiltinsAssembler) {
    1195             :   Node* const promise = Parameter(Descriptor::kPromise);
    1196             :   Node* const on_reject = Parameter(Descriptor::kOnReject);
    1197             :   Node* const exception = Parameter(Descriptor::kException);
    1198             :   Node* const context = Parameter(Descriptor::kContext);
    1199             : 
    1200          31 :   Callable call_callable = CodeFactory::Call(isolate());
    1201          62 :   VARIABLE(var_unused, MachineRepresentation::kTagged);
    1202             : 
    1203          31 :   Label if_internalhandler(this), if_customhandler(this, Label::kDeferred);
    1204          62 :   Branch(IsUndefined(on_reject), &if_internalhandler, &if_customhandler);
    1205             : 
    1206          31 :   BIND(&if_internalhandler);
    1207             :   {
    1208          31 :     InternalPromiseReject(context, promise, exception, false);
    1209          62 :     Return(UndefinedConstant());
    1210             :   }
    1211             : 
    1212          31 :   BIND(&if_customhandler);
    1213             :   {
    1214          62 :     CallJS(call_callable, context, on_reject, UndefinedConstant(), exception);
    1215          62 :     Return(UndefinedConstant());
    1216             :   }
    1217          31 : }
    1218             : 
    1219         124 : TF_BUILTIN(PromiseHandle, PromiseBuiltinsAssembler) {
    1220             :   Node* const value = Parameter(Descriptor::kValue);
    1221             :   Node* const handler = Parameter(Descriptor::kHandler);
    1222             :   Node* const deferred_promise = Parameter(Descriptor::kDeferredPromise);
    1223             :   Node* const deferred_on_resolve = Parameter(Descriptor::kDeferredOnResolve);
    1224             :   Node* const deferred_on_reject = Parameter(Descriptor::kDeferredOnReject);
    1225             :   Node* const context = Parameter(Descriptor::kContext);
    1226          31 :   Isolate* isolate = this->isolate();
    1227             : 
    1228          31 :   VARIABLE(var_reason, MachineRepresentation::kTagged);
    1229             : 
    1230          31 :   Node* const is_debug_active = IsDebugActive();
    1231          31 :   Label run_handler(this), if_rejectpromise(this), promisehook_before(this),
    1232          31 :       promisehook_after(this), debug_pop(this);
    1233             : 
    1234          31 :   GotoIfNot(is_debug_active, &promisehook_before);
    1235             :   CallRuntime(Runtime::kDebugPushPromise, context, deferred_promise);
    1236          31 :   Goto(&promisehook_before);
    1237             : 
    1238          31 :   BIND(&promisehook_before);
    1239             :   {
    1240          62 :     GotoIfNot(IsPromiseHookEnabledOrDebugIsActive(), &run_handler);
    1241             :     CallRuntime(Runtime::kPromiseHookBefore, context, deferred_promise);
    1242          31 :     Goto(&run_handler);
    1243             :   }
    1244             : 
    1245          31 :   BIND(&run_handler);
    1246             :   {
    1247          31 :     Label if_defaulthandler(this), if_callablehandler(this),
    1248          31 :         if_internalhandler(this), if_customhandler(this, Label::kDeferred);
    1249          62 :     VARIABLE(var_result, MachineRepresentation::kTagged);
    1250             : 
    1251          62 :     Branch(IsSymbol(handler), &if_defaulthandler, &if_callablehandler);
    1252             : 
    1253          31 :     BIND(&if_defaulthandler);
    1254             :     {
    1255          31 :       Label if_resolve(this), if_reject(this);
    1256             :       Node* const default_resolve_handler_symbol = HeapConstant(
    1257             :           isolate->factory()->promise_default_resolve_handler_symbol());
    1258          31 :       Branch(WordEqual(default_resolve_handler_symbol, handler), &if_resolve,
    1259          62 :              &if_reject);
    1260             : 
    1261          31 :       BIND(&if_resolve);
    1262             :       {
    1263          31 :         var_result.Bind(value);
    1264          31 :         Branch(IsUndefined(deferred_on_resolve), &if_internalhandler,
    1265          62 :                &if_customhandler);
    1266             :       }
    1267             : 
    1268          31 :       BIND(&if_reject);
    1269             :       {
    1270          31 :         var_reason.Bind(value);
    1271          31 :         Goto(&if_rejectpromise);
    1272          31 :       }
    1273             :     }
    1274             : 
    1275          31 :     BIND(&if_callablehandler);
    1276             :     {
    1277          31 :       Callable call_callable = CodeFactory::Call(isolate);
    1278             :       Node* const result =
    1279          62 :           CallJS(call_callable, context, handler, UndefinedConstant(), value);
    1280          31 :       var_result.Bind(result);
    1281          31 :       GotoIfException(result, &if_rejectpromise, &var_reason);
    1282          31 :       Branch(IsUndefined(deferred_on_resolve), &if_internalhandler,
    1283          62 :              &if_customhandler);
    1284             :     }
    1285             : 
    1286          31 :     BIND(&if_internalhandler);
    1287          31 :     InternalResolvePromise(context, deferred_promise, var_result.value());
    1288          31 :     Goto(&promisehook_after);
    1289             : 
    1290          31 :     BIND(&if_customhandler);
    1291             :     {
    1292          31 :       Callable call_callable = CodeFactory::Call(isolate);
    1293             :       Node* const maybe_exception =
    1294             :           CallJS(call_callable, context, deferred_on_resolve,
    1295          62 :                  UndefinedConstant(), var_result.value());
    1296          31 :       GotoIfException(maybe_exception, &if_rejectpromise, &var_reason);
    1297          31 :       Goto(&promisehook_after);
    1298          31 :     }
    1299             :   }
    1300             : 
    1301          31 :   BIND(&if_rejectpromise);
    1302             :   {
    1303             :     CallBuiltin(Builtins::kPromiseHandleReject, context, deferred_promise,
    1304          31 :                 deferred_on_reject, var_reason.value());
    1305          31 :     Goto(&promisehook_after);
    1306             :   }
    1307             : 
    1308          31 :   BIND(&promisehook_after);
    1309             :   {
    1310          62 :     GotoIfNot(IsPromiseHookEnabledOrDebugIsActive(), &debug_pop);
    1311             :     CallRuntime(Runtime::kPromiseHookAfter, context, deferred_promise);
    1312          31 :     Goto(&debug_pop);
    1313             :   }
    1314             : 
    1315          31 :   BIND(&debug_pop);
    1316             :   {
    1317             :     Label out(this);
    1318             : 
    1319          31 :     GotoIfNot(is_debug_active, &out);
    1320             :     CallRuntime(Runtime::kDebugPopPromise, context);
    1321          31 :     Goto(&out);
    1322             : 
    1323          31 :     BIND(&out);
    1324          62 :     Return(UndefinedConstant());
    1325          31 :   }
    1326          31 : }
    1327             : 
    1328             : // ES#sec-promise.prototype.catch
    1329             : // Promise.prototype.catch ( onRejected )
    1330         155 : TF_BUILTIN(PromiseCatch, PromiseBuiltinsAssembler) {
    1331             :   // 1. Let promise be the this value.
    1332             :   Node* const promise = Parameter(Descriptor::kReceiver);
    1333          62 :   Node* const on_resolve = UndefinedConstant();
    1334             :   Node* const on_reject = Parameter(Descriptor::kOnRejected);
    1335             :   Node* const context = Parameter(Descriptor::kContext);
    1336             : 
    1337          31 :   Label if_internalthen(this), if_customthen(this, Label::kDeferred);
    1338          62 :   GotoIf(TaggedIsSmi(promise), &if_customthen);
    1339          31 :   BranchIfFastPath(context, promise, &if_internalthen, &if_customthen);
    1340             : 
    1341          31 :   BIND(&if_internalthen);
    1342             :   {
    1343             :     Node* const result =
    1344          31 :         InternalPromiseThen(context, promise, on_resolve, on_reject);
    1345          31 :     Return(result);
    1346             :   }
    1347             : 
    1348          31 :   BIND(&if_customthen);
    1349             :   {
    1350             :     Node* const then =
    1351          62 :         GetProperty(context, promise, isolate()->factory()->then_string());
    1352          31 :     Callable call_callable = CodeFactory::Call(isolate());
    1353             :     Node* const result =
    1354          31 :         CallJS(call_callable, context, then, promise, on_resolve, on_reject);
    1355          31 :     Return(result);
    1356          31 :   }
    1357          31 : }
    1358             : 
    1359         124 : TF_BUILTIN(PromiseResolveWrapper, PromiseBuiltinsAssembler) {
    1360             :   //  1. Let C be the this value.
    1361             :   Node* receiver = Parameter(Descriptor::kReceiver);
    1362             :   Node* value = Parameter(Descriptor::kValue);
    1363             :   Node* context = Parameter(Descriptor::kContext);
    1364             : 
    1365             :   // 2. If Type(C) is not Object, throw a TypeError exception.
    1366             :   ThrowIfNotJSReceiver(context, receiver, MessageTemplate::kCalledOnNonObject,
    1367          31 :                        "PromiseResolve");
    1368             : 
    1369             :   // 3. Return ? PromiseResolve(C, x).
    1370          62 :   Return(CallBuiltin(Builtins::kPromiseResolve, context, receiver, value));
    1371          31 : }
    1372             : 
    1373         124 : TF_BUILTIN(PromiseResolve, PromiseBuiltinsAssembler) {
    1374             :   Node* constructor = Parameter(Descriptor::kConstructor);
    1375             :   Node* value = Parameter(Descriptor::kValue);
    1376             :   Node* context = Parameter(Descriptor::kContext);
    1377          31 :   Isolate* isolate = this->isolate();
    1378             : 
    1379          62 :   Node* const native_context = LoadNativeContext(context);
    1380             :   Node* const promise_fun =
    1381          62 :       LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX);
    1382             : 
    1383             :   Label if_value_is_native_promise(this),
    1384          31 :       if_value_or_constructor_are_not_native_promise(this),
    1385          31 :       if_need_to_allocate(this);
    1386             : 
    1387          62 :   GotoIf(TaggedIsSmi(value), &if_need_to_allocate);
    1388             : 
    1389             :   // This shortcircuits the constructor lookups.
    1390          62 :   GotoIfNot(HasInstanceType(value, JS_PROMISE_TYPE), &if_need_to_allocate);
    1391             : 
    1392             :   // This adds a fast path as non-subclassed native promises don't have
    1393             :   // an observable constructor lookup.
    1394             :   BranchIfFastPath(native_context, promise_fun, value,
    1395             :                    &if_value_is_native_promise,
    1396          31 :                    &if_value_or_constructor_are_not_native_promise);
    1397             : 
    1398          31 :   BIND(&if_value_is_native_promise);
    1399             :   {
    1400          31 :     GotoIfNot(WordEqual(promise_fun, constructor),
    1401          62 :               &if_value_or_constructor_are_not_native_promise);
    1402          31 :     Return(value);
    1403             :   }
    1404             : 
    1405             :   // At this point, value or/and constructor are not native promises, but
    1406             :   // they could be of the same subclass.
    1407          31 :   BIND(&if_value_or_constructor_are_not_native_promise);
    1408             :   {
    1409             :     Label if_return(this);
    1410             :     Node* const xConstructor =
    1411          31 :         GetProperty(context, value, isolate->factory()->constructor_string());
    1412             :     BranchIfSameValue(xConstructor, constructor, &if_return,
    1413          31 :                       &if_need_to_allocate);
    1414             : 
    1415          31 :     BIND(&if_return);
    1416          31 :     Return(value);
    1417             :   }
    1418             : 
    1419          31 :   BIND(&if_need_to_allocate);
    1420             :   {
    1421          31 :     Label if_nativepromise(this), if_notnativepromise(this);
    1422          31 :     Branch(WordEqual(promise_fun, constructor), &if_nativepromise,
    1423          62 :            &if_notnativepromise);
    1424             : 
    1425             :     // This adds a fast path for native promises that don't need to
    1426             :     // create NewPromiseCapability.
    1427          31 :     BIND(&if_nativepromise);
    1428             :     {
    1429          31 :       Node* const result = AllocateAndInitJSPromise(context);
    1430          31 :       InternalResolvePromise(context, result, value);
    1431          31 :       Return(result);
    1432             :     }
    1433             : 
    1434          31 :     BIND(&if_notnativepromise);
    1435             :     {
    1436          31 :       Node* const capability = NewPromiseCapability(context, constructor);
    1437             : 
    1438          31 :       Callable call_callable = CodeFactory::Call(isolate);
    1439             :       Node* const resolve =
    1440             :           LoadObjectField(capability, PromiseCapability::kResolveOffset);
    1441          62 :       CallJS(call_callable, context, resolve, UndefinedConstant(), value);
    1442             : 
    1443             :       Node* const result =
    1444             :           LoadObjectField(capability, PromiseCapability::kPromiseOffset);
    1445          31 :       Return(result);
    1446          31 :     }
    1447          31 :   }
    1448          31 : }
    1449             : 
    1450             : // ES6 #sec-getcapabilitiesexecutor-functions
    1451         124 : TF_BUILTIN(PromiseGetCapabilitiesExecutor, PromiseBuiltinsAssembler) {
    1452             :   Node* const resolve = Parameter(Descriptor::kResolve);
    1453             :   Node* const reject = Parameter(Descriptor::kReject);
    1454             :   Node* const context = Parameter(Descriptor::kContext);
    1455             : 
    1456          62 :   Node* const capability = LoadContextElement(context, kCapabilitySlot);
    1457             : 
    1458             :   Label if_alreadyinvoked(this, Label::kDeferred);
    1459             :   GotoIf(WordNotEqual(
    1460             :              LoadObjectField(capability, PromiseCapability::kResolveOffset),
    1461          31 :              UndefinedConstant()),
    1462          31 :          &if_alreadyinvoked);
    1463             :   GotoIf(WordNotEqual(
    1464             :              LoadObjectField(capability, PromiseCapability::kRejectOffset),
    1465          31 :              UndefinedConstant()),
    1466          31 :          &if_alreadyinvoked);
    1467             : 
    1468          31 :   StoreObjectField(capability, PromiseCapability::kResolveOffset, resolve);
    1469          31 :   StoreObjectField(capability, PromiseCapability::kRejectOffset, reject);
    1470             : 
    1471          62 :   Return(UndefinedConstant());
    1472             : 
    1473          31 :   BIND(&if_alreadyinvoked);
    1474          31 :   ThrowTypeError(context, MessageTemplate::kPromiseExecutorAlreadyInvoked);
    1475          31 : }
    1476             : 
    1477             : // ES6 #sec-newpromisecapability
    1478         124 : TF_BUILTIN(NewPromiseCapability, PromiseBuiltinsAssembler) {
    1479             :   Node* constructor = Parameter(Descriptor::kConstructor);
    1480             :   Node* debug_event = Parameter(Descriptor::kDebugEvent);
    1481             :   Node* context = Parameter(Descriptor::kContext);
    1482             : 
    1483             :   CSA_ASSERT_JS_ARGC_EQ(this, 2);
    1484             : 
    1485          62 :   Return(NewPromiseCapability(context, constructor, debug_event));
    1486          31 : }
    1487             : 
    1488         124 : TF_BUILTIN(PromiseReject, PromiseBuiltinsAssembler) {
    1489             :   // 1. Let C be the this value.
    1490             :   Node* const receiver = Parameter(Descriptor::kReceiver);
    1491             :   Node* const reason = Parameter(Descriptor::kReason);
    1492             :   Node* const context = Parameter(Descriptor::kContext);
    1493             : 
    1494             :   // 2. If Type(C) is not Object, throw a TypeError exception.
    1495             :   ThrowIfNotJSReceiver(context, receiver, MessageTemplate::kCalledOnNonObject,
    1496          31 :                        "PromiseReject");
    1497             : 
    1498          31 :   Label if_nativepromise(this), if_custompromise(this, Label::kDeferred);
    1499          62 :   Node* const native_context = LoadNativeContext(context);
    1500             :   Node* const promise_fun =
    1501          62 :       LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX);
    1502          31 :   Branch(WordEqual(promise_fun, receiver), &if_nativepromise,
    1503          62 :          &if_custompromise);
    1504             : 
    1505          31 :   BIND(&if_nativepromise);
    1506             :   {
    1507             :     Node* const promise =
    1508          31 :         AllocateAndSetJSPromise(context, v8::Promise::kRejected, reason);
    1509             :     CallRuntime(Runtime::kPromiseRejectEventFromStack, context, promise,
    1510             :                 reason);
    1511          31 :     Return(promise);
    1512             :   }
    1513             : 
    1514          31 :   BIND(&if_custompromise);
    1515             :   {
    1516             :     // 3. Let promiseCapability be ? NewPromiseCapability(C).
    1517          31 :     Node* const capability = NewPromiseCapability(context, receiver);
    1518             : 
    1519             :     // 4. Perform ? Call(promiseCapability.[[Reject]], undefined, « r »).
    1520             :     Node* const reject =
    1521             :         LoadObjectField(capability, PromiseCapability::kRejectOffset);
    1522          31 :     Callable call_callable = CodeFactory::Call(isolate());
    1523          62 :     CallJS(call_callable, context, reject, UndefinedConstant(), reason);
    1524             : 
    1525             :     // 5. Return promiseCapability.[[Promise]].
    1526             :     Node* const promise =
    1527             :         LoadObjectField(capability, PromiseCapability::kPromiseOffset);
    1528          31 :     Return(promise);
    1529          31 :   }
    1530          31 : }
    1531             : 
    1532         124 : TF_BUILTIN(InternalPromiseReject, PromiseBuiltinsAssembler) {
    1533             :   Node* const promise = Parameter(Descriptor::kPromise);
    1534             :   Node* const reason = Parameter(Descriptor::kReason);
    1535             :   Node* const debug_event = Parameter(Descriptor::kDebugEvent);
    1536             :   Node* const context = Parameter(Descriptor::kContext);
    1537             : 
    1538          31 :   InternalPromiseReject(context, promise, reason, debug_event);
    1539          62 :   Return(UndefinedConstant());
    1540          31 : }
    1541             : 
    1542          31 : std::pair<Node*, Node*> PromiseBuiltinsAssembler::CreatePromiseFinallyFunctions(
    1543             :     Node* on_finally, Node* constructor, Node* native_context) {
    1544             :   Node* const promise_context =
    1545          31 :       CreatePromiseContext(native_context, kPromiseFinallyContextLength);
    1546             :   StoreContextElementNoWriteBarrier(promise_context, kOnFinallySlot,
    1547          31 :                                     on_finally);
    1548             :   StoreContextElementNoWriteBarrier(promise_context, kConstructorSlot,
    1549          31 :                                     constructor);
    1550             :   Node* const map = LoadContextElement(
    1551          62 :       native_context, Context::STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX);
    1552             :   Node* const then_finally_info = LoadContextElement(
    1553          62 :       native_context, Context::PROMISE_THEN_FINALLY_SHARED_FUN);
    1554             :   Node* const then_finally = AllocateFunctionWithMapAndContext(
    1555          31 :       map, then_finally_info, promise_context);
    1556             :   Node* const catch_finally_info = LoadContextElement(
    1557          62 :       native_context, Context::PROMISE_CATCH_FINALLY_SHARED_FUN);
    1558             :   Node* const catch_finally = AllocateFunctionWithMapAndContext(
    1559          31 :       map, catch_finally_info, promise_context);
    1560          31 :   return std::make_pair(then_finally, catch_finally);
    1561             : }
    1562             : 
    1563         124 : TF_BUILTIN(PromiseValueThunkFinally, PromiseBuiltinsAssembler) {
    1564             :   Node* const context = Parameter(Descriptor::kContext);
    1565             : 
    1566          62 :   Node* const value = LoadContextElement(context, kValueSlot);
    1567          31 :   Return(value);
    1568          31 : }
    1569             : 
    1570          31 : Node* PromiseBuiltinsAssembler::CreateValueThunkFunction(Node* value,
    1571             :                                                          Node* native_context) {
    1572             :   Node* const value_thunk_context = CreatePromiseContext(
    1573          31 :       native_context, kPromiseValueThunkOrReasonContextLength);
    1574          31 :   StoreContextElementNoWriteBarrier(value_thunk_context, kValueSlot, value);
    1575             :   Node* const map = LoadContextElement(
    1576          62 :       native_context, Context::STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX);
    1577             :   Node* const value_thunk_info = LoadContextElement(
    1578          62 :       native_context, Context::PROMISE_VALUE_THUNK_FINALLY_SHARED_FUN);
    1579             :   Node* const value_thunk = AllocateFunctionWithMapAndContext(
    1580          31 :       map, value_thunk_info, value_thunk_context);
    1581          31 :   return value_thunk;
    1582             : }
    1583             : 
    1584         124 : TF_BUILTIN(PromiseThenFinally, PromiseBuiltinsAssembler) {
    1585             :   CSA_ASSERT_JS_ARGC_EQ(this, 1);
    1586             : 
    1587             :   Node* const value = Parameter(Descriptor::kValue);
    1588             :   Node* const context = Parameter(Descriptor::kContext);
    1589             : 
    1590             :   // 1. Let onFinally be F.[[OnFinally]].
    1591          62 :   Node* const on_finally = LoadContextElement(context, kOnFinallySlot);
    1592             : 
    1593             :   // 2.  Assert: IsCallable(onFinally) is true.
    1594             :   CSA_ASSERT(this, IsCallable(on_finally));
    1595             : 
    1596             :   // 3. Let result be ?  Call(onFinally).
    1597          31 :   Callable call_callable = CodeFactory::Call(isolate());
    1598             :   Node* const result =
    1599          62 :       CallJS(call_callable, context, on_finally, UndefinedConstant());
    1600             : 
    1601             :   // 4. Let C be F.[[Constructor]].
    1602          62 :   Node* const constructor = LoadContextElement(context, kConstructorSlot);
    1603             : 
    1604             :   // 5. Assert: IsConstructor(C) is true.
    1605             :   CSA_ASSERT(this, IsConstructor(constructor));
    1606             : 
    1607             :   // 6. Let promise be ? PromiseResolve(C, result).
    1608             :   Node* const promise =
    1609          31 :     CallBuiltin(Builtins::kPromiseResolve, context, constructor, result);
    1610             : 
    1611             :   // 7. Let valueThunk be equivalent to a function that returns value.
    1612          62 :   Node* native_context = LoadNativeContext(context);
    1613          31 :   Node* const value_thunk = CreateValueThunkFunction(value, native_context);
    1614             : 
    1615             :   // 8. Return ? Invoke(promise, "then", « valueThunk »).
    1616             :   Node* const promise_then =
    1617          62 :     GetProperty(context, promise, factory()->then_string());
    1618             :   Node* const result_promise = CallJS(call_callable, context,
    1619          31 :                                       promise_then, promise, value_thunk);
    1620          31 :   Return(result_promise);
    1621          31 : }
    1622             : 
    1623         124 : TF_BUILTIN(PromiseThrowerFinally, PromiseBuiltinsAssembler) {
    1624             :   Node* const context = Parameter(Descriptor::kContext);
    1625             : 
    1626          62 :   Node* const reason = LoadContextElement(context, kValueSlot);
    1627             :   CallRuntime(Runtime::kThrow, context, reason);
    1628          31 :   Unreachable();
    1629          31 : }
    1630             : 
    1631          31 : Node* PromiseBuiltinsAssembler::CreateThrowerFunction(Node* reason,
    1632             :                                                       Node* native_context) {
    1633             :   Node* const thrower_context = CreatePromiseContext(
    1634          31 :       native_context, kPromiseValueThunkOrReasonContextLength);
    1635          31 :   StoreContextElementNoWriteBarrier(thrower_context, kValueSlot, reason);
    1636             :   Node* const map = LoadContextElement(
    1637          62 :       native_context, Context::STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX);
    1638             :   Node* const thrower_info = LoadContextElement(
    1639          62 :       native_context, Context::PROMISE_THROWER_FINALLY_SHARED_FUN);
    1640             :   Node* const thrower =
    1641          31 :       AllocateFunctionWithMapAndContext(map, thrower_info, thrower_context);
    1642          31 :   return thrower;
    1643             : }
    1644             : 
    1645         124 : TF_BUILTIN(PromiseCatchFinally, PromiseBuiltinsAssembler) {
    1646             :   CSA_ASSERT_JS_ARGC_EQ(this, 1);
    1647             : 
    1648             :   Node* const reason = Parameter(Descriptor::kReason);
    1649             :   Node* const context = Parameter(Descriptor::kContext);
    1650             : 
    1651             :   // 1. Let onFinally be F.[[OnFinally]].
    1652          62 :   Node* const on_finally = LoadContextElement(context, kOnFinallySlot);
    1653             : 
    1654             :   // 2. Assert: IsCallable(onFinally) is true.
    1655             :   CSA_ASSERT(this, IsCallable(on_finally));
    1656             : 
    1657             :   // 3. Let result be ? Call(onFinally).
    1658          31 :   Callable call_callable = CodeFactory::Call(isolate());
    1659             :   Node* result =
    1660          62 :     CallJS(call_callable, context, on_finally, UndefinedConstant());
    1661             : 
    1662             :   // 4. Let C be F.[[Constructor]].
    1663          62 :   Node* const constructor = LoadContextElement(context, kConstructorSlot);
    1664             : 
    1665             :   // 5. Assert: IsConstructor(C) is true.
    1666             :   CSA_ASSERT(this, IsConstructor(constructor));
    1667             : 
    1668             :   // 6. Let promise be ? PromiseResolve(C, result).
    1669             :   Node* const promise =
    1670          31 :     CallBuiltin(Builtins::kPromiseResolve, context, constructor, result);
    1671             : 
    1672             :   // 7. Let thrower be equivalent to a function that throws reason.
    1673          62 :   Node* native_context = LoadNativeContext(context);
    1674          31 :   Node* const thrower = CreateThrowerFunction(reason, native_context);
    1675             : 
    1676             :   // 8. Return ? Invoke(promise, "then", « thrower »).
    1677             :   Node* const promise_then =
    1678          62 :     GetProperty(context, promise, factory()->then_string());
    1679             :   Node* const result_promise = CallJS(call_callable, context,
    1680          31 :                                       promise_then, promise, thrower);
    1681          31 :   Return(result_promise);
    1682          31 : }
    1683             : 
    1684         124 : TF_BUILTIN(PromiseFinally, PromiseBuiltinsAssembler) {
    1685             :   CSA_ASSERT_JS_ARGC_EQ(this, 1);
    1686             : 
    1687             :   // 1.  Let promise be the this value.
    1688             :   Node* const promise = Parameter(Descriptor::kReceiver);
    1689             :   Node* const on_finally = Parameter(Descriptor::kOnFinally);
    1690             :   Node* const context = Parameter(Descriptor::kContext);
    1691             : 
    1692             :   // 2. If IsPromise(promise) is false, throw a TypeError exception.
    1693             :   ThrowIfNotInstanceType(context, promise, JS_PROMISE_TYPE,
    1694          31 :                          "Promise.prototype.finally");
    1695             : 
    1696             :   // 3. Let C be ? SpeciesConstructor(promise, %Promise%).
    1697          62 :   Node* const native_context = LoadNativeContext(context);
    1698             :   Node* const promise_fun =
    1699          62 :       LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX);
    1700          31 :   Node* const constructor = SpeciesConstructor(context, promise, promise_fun);
    1701             : 
    1702             :   // 4. Assert: IsConstructor(C) is true.
    1703             :   CSA_ASSERT(this, IsConstructor(constructor));
    1704             : 
    1705          31 :   VARIABLE(var_then_finally, MachineRepresentation::kTagged);
    1706          62 :   VARIABLE(var_catch_finally, MachineRepresentation::kTagged);
    1707             : 
    1708          31 :   Label if_notcallable(this, Label::kDeferred), perform_finally(this);
    1709             : 
    1710          62 :   GotoIf(TaggedIsSmi(on_finally), &if_notcallable);
    1711          62 :   GotoIfNot(IsCallable(on_finally), &if_notcallable);
    1712             : 
    1713             :   // 6. Else,
    1714             :   //   a. Let thenFinally be a new built-in function object as defined
    1715             :   //   in ThenFinally Function.
    1716             :   //   b. Let catchFinally be a new built-in function object as
    1717             :   //   defined in CatchFinally Function.
    1718             :   //   c. Set thenFinally and catchFinally's [[Constructor]] internal
    1719             :   //   slots to C.
    1720             :   //   d. Set thenFinally and catchFinally's [[OnFinally]] internal
    1721             :   //   slots to onFinally.
    1722          31 :   Node* then_finally = nullptr;
    1723          31 :   Node* catch_finally = nullptr;
    1724          62 :   std::tie(then_finally, catch_finally) =
    1725             :     CreatePromiseFinallyFunctions(on_finally, constructor, native_context);
    1726          31 :   var_then_finally.Bind(then_finally);
    1727          31 :   var_catch_finally.Bind(catch_finally);
    1728          31 :   Goto(&perform_finally);
    1729             : 
    1730             :   // 5. If IsCallable(onFinally) is not true,
    1731             :   //    a. Let thenFinally be onFinally.
    1732             :   //    b. Let catchFinally be onFinally.
    1733          31 :   BIND(&if_notcallable);
    1734             :   {
    1735          31 :     var_then_finally.Bind(on_finally);
    1736          31 :     var_catch_finally.Bind(on_finally);
    1737          31 :     Goto(&perform_finally);
    1738             :   }
    1739             : 
    1740             :   // 7. Return ? Invoke(promise, "then", « thenFinally, catchFinally »).
    1741          31 :   BIND(&perform_finally);
    1742             :   Node* const promise_then =
    1743          62 :     GetProperty(context, promise, factory()->then_string());
    1744             :   Node* const result_promise =
    1745             :     CallJS(CodeFactory::Call(isolate()), context, promise_then, promise,
    1746          62 :            var_then_finally.value(), var_catch_finally.value());
    1747          62 :   Return(result_promise);
    1748          31 : }
    1749             : 
    1750         124 : TF_BUILTIN(ResolveNativePromise, PromiseBuiltinsAssembler) {
    1751             :   Node* const promise = Parameter(Descriptor::kPromise);
    1752             :   Node* const value = Parameter(Descriptor::kValue);
    1753             :   Node* const context = Parameter(Descriptor::kContext);
    1754             : 
    1755             :   CSA_ASSERT(this, HasInstanceType(promise, JS_PROMISE_TYPE));
    1756          31 :   InternalResolvePromise(context, promise, value);
    1757          62 :   Return(UndefinedConstant());
    1758          31 : }
    1759             : 
    1760         124 : TF_BUILTIN(RejectNativePromise, PromiseBuiltinsAssembler) {
    1761             :   Node* const promise = Parameter(Descriptor::kPromise);
    1762             :   Node* const value = Parameter(Descriptor::kValue);
    1763             :   Node* const debug_event = Parameter(Descriptor::kDebugEvent);
    1764             :   Node* const context = Parameter(Descriptor::kContext);
    1765             : 
    1766             :   CSA_ASSERT(this, HasInstanceType(promise, JS_PROMISE_TYPE));
    1767             :   CSA_ASSERT(this, IsBoolean(debug_event));
    1768          31 :   InternalPromiseReject(context, promise, value, debug_event);
    1769          62 :   Return(UndefinedConstant());
    1770          31 : }
    1771             : 
    1772         124 : TF_BUILTIN(PerformNativePromiseThen, PromiseBuiltinsAssembler) {
    1773             :   Node* const promise = Parameter(Descriptor::kPromise);
    1774             :   Node* const resolve_reaction = Parameter(Descriptor::kResolveReaction);
    1775             :   Node* const reject_reaction = Parameter(Descriptor::kRejectReaction);
    1776             :   Node* const result_promise = Parameter(Descriptor::kResultPromise);
    1777             :   Node* const context = Parameter(Descriptor::kContext);
    1778             : 
    1779             :   CSA_ASSERT(this, HasInstanceType(result_promise, JS_PROMISE_TYPE));
    1780             : 
    1781             :   InternalPerformPromiseThen(context, promise, resolve_reaction,
    1782             :                              reject_reaction, result_promise,
    1783          93 :                              UndefinedConstant(), UndefinedConstant());
    1784          31 :   Return(result_promise);
    1785          31 : }
    1786             : 
    1787          31 : Node* PromiseBuiltinsAssembler::PerformPromiseAll(
    1788             :     Node* context, Node* constructor, Node* capability, Node* iterator,
    1789             :     Label* if_exception, Variable* var_exception) {
    1790             :   IteratorBuiltinsAssembler iter_assembler(state());
    1791          62 :   Label close_iterator(this);
    1792             : 
    1793          31 :   Node* const instrumenting = IsDebugActive();
    1794             : 
    1795             :   // For catch prediction, don't treat the .then calls as handling it;
    1796             :   // instead, recurse outwards.
    1797             :   SetForwardingHandlerIfTrue(
    1798             :       context, instrumenting,
    1799          31 :       LoadObjectField(capability, PromiseCapability::kRejectOffset));
    1800             : 
    1801          62 :   Node* const native_context = LoadNativeContext(context);
    1802             :   Node* const array_map = LoadContextElement(
    1803          62 :       native_context, Context::JS_ARRAY_PACKED_ELEMENTS_MAP_INDEX);
    1804             :   Node* const values_array = AllocateJSArray(PACKED_ELEMENTS, array_map,
    1805          93 :                                              IntPtrConstant(0), SmiConstant(0));
    1806          31 :   Node* const remaining_elements = AllocateSmiCell(1);
    1807             : 
    1808          93 :   VARIABLE(var_index, MachineRepresentation::kTagged, SmiConstant(0));
    1809             : 
    1810          31 :   Label loop(this, &var_index), break_loop(this);
    1811          31 :   Goto(&loop);
    1812          31 :   BIND(&loop);
    1813             :   {
    1814             :     // Let next be IteratorStep(iteratorRecord.[[Iterator]]).
    1815             :     // If next is an abrupt completion, set iteratorRecord.[[Done]] to true.
    1816             :     // ReturnIfAbrupt(next).
    1817             :     Node* const fast_iterator_result_map =
    1818          62 :         LoadContextElement(native_context, Context::ITERATOR_RESULT_MAP_INDEX);
    1819             :     Node* const next = iter_assembler.IteratorStep(
    1820             :         context, iterator, &break_loop, fast_iterator_result_map, if_exception,
    1821          31 :         var_exception);
    1822             : 
    1823             :     // Let nextValue be IteratorValue(next).
    1824             :     // If nextValue is an abrupt completion, set iteratorRecord.[[Done]] to
    1825             :     //     true.
    1826             :     // ReturnIfAbrupt(nextValue).
    1827             :     Node* const next_value = iter_assembler.IteratorValue(
    1828          31 :         context, next, fast_iterator_result_map, if_exception, var_exception);
    1829             : 
    1830             :     // Let nextPromise be ? Invoke(constructor, "resolve", « nextValue »).
    1831             :     Node* const promise_resolve =
    1832          62 :         GetProperty(context, constructor, factory()->resolve_string());
    1833          31 :     GotoIfException(promise_resolve, &close_iterator, var_exception);
    1834             : 
    1835             :     Node* const next_promise = CallJS(CodeFactory::Call(isolate()), context,
    1836          62 :                                       promise_resolve, constructor, next_value);
    1837          31 :     GotoIfException(next_promise, &close_iterator, var_exception);
    1838             : 
    1839             :     // Let resolveElement be a new built-in function object as defined in
    1840             :     // Promise.all Resolve Element Functions.
    1841             :     Node* const resolve_context =
    1842          31 :         CreatePromiseContext(native_context, kPromiseAllResolveElementLength);
    1843             :     StoreContextElementNoWriteBarrier(
    1844             :         resolve_context, kPromiseAllResolveElementAlreadyVisitedSlot,
    1845          62 :         SmiConstant(0));
    1846             :     StoreContextElementNoWriteBarrier(
    1847          62 :         resolve_context, kPromiseAllResolveElementIndexSlot, var_index.value());
    1848             :     StoreContextElementNoWriteBarrier(
    1849             :         resolve_context, kPromiseAllResolveElementRemainingElementsSlot,
    1850          31 :         remaining_elements);
    1851             :     StoreContextElementNoWriteBarrier(
    1852          31 :         resolve_context, kPromiseAllResolveElementCapabilitySlot, capability);
    1853             :     StoreContextElementNoWriteBarrier(resolve_context,
    1854             :                                       kPromiseAllResolveElementValuesArraySlot,
    1855          31 :                                       values_array);
    1856             : 
    1857             :     Node* const map = LoadContextElement(
    1858          62 :         native_context, Context::STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX);
    1859             :     Node* const resolve_info = LoadContextElement(
    1860          62 :         native_context, Context::PROMISE_ALL_RESOLVE_ELEMENT_SHARED_FUN);
    1861             :     Node* const resolve =
    1862          31 :         AllocateFunctionWithMapAndContext(map, resolve_info, resolve_context);
    1863             : 
    1864             :     // Set remainingElementsCount.[[Value]] to
    1865             :     //     remainingElementsCount.[[Value]] + 1.
    1866             :     {
    1867          31 :       Label if_outofrange(this, Label::kDeferred), done(this);
    1868          31 :       IncrementSmiCell(remaining_elements, &if_outofrange);
    1869          31 :       Goto(&done);
    1870             : 
    1871          31 :       BIND(&if_outofrange);
    1872             :       {
    1873             :         // If the incremented value is out of Smi range, crash.
    1874          31 :         Abort(kOffsetOutOfRange);
    1875             :       }
    1876             : 
    1877          62 :       BIND(&done);
    1878             :     }
    1879             : 
    1880             :     // Perform ? Invoke(nextPromise, "then", « resolveElement,
    1881             :     //                  resultCapability.[[Reject]] »).
    1882             :     Node* const then =
    1883          62 :         GetProperty(context, next_promise, factory()->then_string());
    1884          31 :     GotoIfException(then, &close_iterator, var_exception);
    1885             : 
    1886             :     Node* const then_call = CallJS(
    1887             :         CodeFactory::Call(isolate()), context, then, next_promise, resolve,
    1888          62 :         LoadObjectField(capability, PromiseCapability::kRejectOffset));
    1889          31 :     GotoIfException(then_call, &close_iterator, var_exception);
    1890             : 
    1891             :     // For catch prediction, mark that rejections here are semantically
    1892             :     // handled by the combined Promise.
    1893          31 :     SetPromiseHandledByIfTrue(context, instrumenting, then_call, [=]() {
    1894             :       // Load promiseCapability.[[Promise]]
    1895          31 :       return LoadObjectField(capability, PromiseCapability::kPromiseOffset);
    1896          93 :     });
    1897             : 
    1898             :     // Set index to index + 1
    1899          31 :     var_index.Bind(NumberInc(var_index.value()));
    1900          31 :     Goto(&loop);
    1901             :   }
    1902             : 
    1903          31 :   BIND(&close_iterator);
    1904             :   {
    1905             :     // Exception must be bound to a JS value.
    1906             :     CSA_ASSERT(this, IsNotTheHole(var_exception->value()));
    1907             :     iter_assembler.IteratorCloseOnException(context, iterator, if_exception,
    1908          31 :                                             var_exception);
    1909             :   }
    1910             : 
    1911          31 :   BIND(&break_loop);
    1912             :   {
    1913          31 :     Label resolve_promise(this), return_promise(this);
    1914             :     // Set iteratorRecord.[[Done]] to true.
    1915             :     // Set remainingElementsCount.[[Value]] to
    1916             :     //    remainingElementsCount.[[Value]] - 1.
    1917          31 :     Node* const remaining = DecrementSmiCell(remaining_elements);
    1918             :     Branch(SmiEqual(remaining, SmiConstant(0)), &resolve_promise,
    1919          93 :            &return_promise);
    1920             : 
    1921             :     // If remainingElementsCount.[[Value]] is 0, then
    1922             :     //     Let valuesArray be CreateArrayFromList(values).
    1923             :     //     Perform ? Call(resultCapability.[[Resolve]], undefined,
    1924             :     //                    « valuesArray »).
    1925          31 :     BIND(&resolve_promise);
    1926             : 
    1927             :     Node* const resolve =
    1928             :         LoadObjectField(capability, PromiseCapability::kResolveOffset);
    1929             :     Node* const resolve_call =
    1930             :         CallJS(CodeFactory::Call(isolate()), context, resolve,
    1931          93 :                UndefinedConstant(), values_array);
    1932          31 :     GotoIfException(resolve_call, if_exception, var_exception);
    1933          31 :     Goto(&return_promise);
    1934             : 
    1935             :     // Return resultCapability.[[Promise]].
    1936          62 :     BIND(&return_promise);
    1937             :   }
    1938             : 
    1939             :   Node* const promise =
    1940             :       LoadObjectField(capability, PromiseCapability::kPromiseOffset);
    1941          31 :   return promise;
    1942             : }
    1943             : 
    1944          31 : Node* PromiseBuiltinsAssembler::IncrementSmiCell(Node* cell,
    1945             :                                                  Label* if_overflow) {
    1946             :   CSA_SLOW_ASSERT(this, HasInstanceType(cell, CELL_TYPE));
    1947          31 :   Node* value = LoadCellValue(cell);
    1948             :   CSA_SLOW_ASSERT(this, TaggedIsSmi(value));
    1949             : 
    1950          31 :   if (if_overflow != nullptr) {
    1951          93 :     GotoIf(SmiEqual(value, SmiConstant(Smi::kMaxValue)), if_overflow);
    1952             :   }
    1953             : 
    1954          93 :   Node* result = SmiAdd(value, SmiConstant(1));
    1955          31 :   StoreCellValue(cell, result, SKIP_WRITE_BARRIER);
    1956          31 :   return result;
    1957             : }
    1958             : 
    1959          62 : Node* PromiseBuiltinsAssembler::DecrementSmiCell(Node* cell) {
    1960             :   CSA_SLOW_ASSERT(this, HasInstanceType(cell, CELL_TYPE));
    1961          62 :   Node* value = LoadCellValue(cell);
    1962             :   CSA_SLOW_ASSERT(this, TaggedIsSmi(value));
    1963             : 
    1964         186 :   Node* result = SmiSub(value, SmiConstant(1));
    1965          62 :   StoreCellValue(cell, result, SKIP_WRITE_BARRIER);
    1966          62 :   return result;
    1967             : }
    1968             : 
    1969             : // ES#sec-promise.all
    1970             : // Promise.all ( iterable )
    1971         186 : TF_BUILTIN(PromiseAll, PromiseBuiltinsAssembler) {
    1972             :   IteratorBuiltinsAssembler iter_assembler(state());
    1973             : 
    1974             :   // Let C be the this value.
    1975             :   // If Type(C) is not Object, throw a TypeError exception.
    1976             :   Node* const receiver = Parameter(Descriptor::kReceiver);
    1977             :   Node* const context = Parameter(Descriptor::kContext);
    1978             :   ThrowIfNotJSReceiver(context, receiver, MessageTemplate::kCalledOnNonObject,
    1979          31 :                        "Promise.all");
    1980             : 
    1981             :   // Let promiseCapability be ? NewPromiseCapability(C).
    1982             :   // Don't fire debugEvent so that forwarding the rejection through all does not
    1983             :   // trigger redundant ExceptionEvents
    1984          62 :   Node* const debug_event = FalseConstant();
    1985          31 :   Node* const capability = NewPromiseCapability(context, receiver, debug_event);
    1986             : 
    1987          93 :   VARIABLE(var_exception, MachineRepresentation::kTagged, TheHoleConstant());
    1988          31 :   Label reject_promise(this, &var_exception, Label::kDeferred);
    1989             : 
    1990             :   // Let iterator be GetIterator(iterable).
    1991             :   // IfAbruptRejectPromise(iterator, promiseCapability).
    1992             :   Node* const iterable = Parameter(Descriptor::kIterable);
    1993             :   Node* const iterator = iter_assembler.GetIterator(
    1994          31 :       context, iterable, &reject_promise, &var_exception);
    1995             : 
    1996             :   // Let result be PerformPromiseAll(iteratorRecord, C, promiseCapability).
    1997             :   // If result is an abrupt completion, then
    1998             :   //   If iteratorRecord.[[Done]] is false, let result be
    1999             :   //       IteratorClose(iterator, result).
    2000             :   //    IfAbruptRejectPromise(result, promiseCapability).
    2001             :   Node* const result = PerformPromiseAll(
    2002          31 :       context, receiver, capability, iterator, &reject_promise, &var_exception);
    2003             : 
    2004          31 :   Return(result);
    2005             : 
    2006          31 :   BIND(&reject_promise);
    2007             :   {
    2008             :     // Exception must be bound to a JS value.
    2009             :     CSA_SLOW_ASSERT(this, IsNotTheHole(var_exception.value()));
    2010             :     Node* const reject =
    2011             :         LoadObjectField(capability, PromiseCapability::kRejectOffset);
    2012          31 :     Callable callable = CodeFactory::Call(isolate());
    2013             :     CallJS(callable, context, reject, UndefinedConstant(),
    2014          62 :            var_exception.value());
    2015             : 
    2016             :     Node* const promise =
    2017             :         LoadObjectField(capability, PromiseCapability::kPromiseOffset);
    2018          31 :     Return(promise);
    2019             :   }
    2020          31 : }
    2021             : 
    2022         124 : TF_BUILTIN(PromiseAllResolveElementClosure, PromiseBuiltinsAssembler) {
    2023             :   Node* const value = Parameter(Descriptor::kValue);
    2024             :   Node* const context = Parameter(Descriptor::kContext);
    2025             : 
    2026             :   CSA_ASSERT(this, SmiEqual(LoadFixedArrayBaseLength(context),
    2027             :                             SmiConstant(kPromiseAllResolveElementLength)));
    2028             : 
    2029          31 :   Label already_called(this), resolve_promise(this);
    2030             :   GotoIf(SmiEqual(LoadContextElement(
    2031          62 :                       context, kPromiseAllResolveElementAlreadyVisitedSlot),
    2032             :                   SmiConstant(1)),
    2033         155 :          &already_called);
    2034             :   StoreContextElementNoWriteBarrier(
    2035          62 :       context, kPromiseAllResolveElementAlreadyVisitedSlot, SmiConstant(1));
    2036             : 
    2037             :   Node* const index =
    2038          62 :       LoadContextElement(context, kPromiseAllResolveElementIndexSlot);
    2039             :   Node* const values_array =
    2040          62 :       LoadContextElement(context, kPromiseAllResolveElementValuesArraySlot);
    2041             : 
    2042             :   // Set element in FixedArray
    2043          31 :   Label runtime_set_element(this), did_set_element(this);
    2044          62 :   GotoIfNot(TaggedIsPositiveSmi(index), &runtime_set_element);
    2045             :   {
    2046          62 :     VARIABLE(var_elements, MachineRepresentation::kTagged,
    2047             :              LoadElements(values_array));
    2048             :     PossiblyGrowElementsCapacity(SMI_PARAMETERS, PACKED_ELEMENTS, values_array,
    2049             :                                  index, &var_elements, SmiConstant(1),
    2050          62 :                                  &runtime_set_element);
    2051             :     StoreFixedArrayElement(var_elements.value(), index, value,
    2052          31 :                            UPDATE_WRITE_BARRIER, 0, SMI_PARAMETERS);
    2053             : 
    2054             :     // Update array length
    2055          31 :     Label did_set_length(this);
    2056          62 :     Node* const length = LoadJSArrayLength(values_array);
    2057          62 :     GotoIfNot(TaggedIsPositiveSmi(length), &did_set_length);
    2058          93 :     Node* const new_length = SmiAdd(index, SmiConstant(1));
    2059          62 :     GotoIfNot(SmiLessThan(length, new_length), &did_set_length);
    2060             :     StoreObjectFieldNoWriteBarrier(values_array, JSArray::kLengthOffset,
    2061          31 :                                    new_length);
    2062             :     // Assert that valuesArray.[[Length]] is less than or equal to the
    2063             :     // elements backing-store length.e
    2064             :     CSA_SLOW_ASSERT(
    2065             :         this, SmiAboveOrEqual(LoadFixedArrayBaseLength(var_elements.value()),
    2066             :                               new_length));
    2067          31 :     Goto(&did_set_length);
    2068          62 :     BIND(&did_set_length);
    2069             :   }
    2070          31 :   Goto(&did_set_element);
    2071          31 :   BIND(&runtime_set_element);
    2072             :   // New-space filled up or index too large, set element via runtime
    2073             :   CallRuntime(Runtime::kCreateDataProperty, context, values_array, index,
    2074             :               value);
    2075          31 :   Goto(&did_set_element);
    2076          31 :   BIND(&did_set_element);
    2077             : 
    2078             :   Node* const remaining_elements = LoadContextElement(
    2079          62 :       context, kPromiseAllResolveElementRemainingElementsSlot);
    2080          31 :   Node* const result = DecrementSmiCell(remaining_elements);
    2081          93 :   GotoIf(SmiEqual(result, SmiConstant(0)), &resolve_promise);
    2082          62 :   Return(UndefinedConstant());
    2083             : 
    2084          31 :   BIND(&resolve_promise);
    2085             :   Node* const capability =
    2086          62 :       LoadContextElement(context, kPromiseAllResolveElementCapabilitySlot);
    2087             :   Node* const resolve =
    2088             :       LoadObjectField(capability, PromiseCapability::kResolveOffset);
    2089             :   CallJS(CodeFactory::Call(isolate()), context, resolve, UndefinedConstant(),
    2090          93 :          values_array);
    2091          62 :   Return(UndefinedConstant());
    2092             : 
    2093          31 :   BIND(&already_called);
    2094          93 :   Return(UndefinedConstant());
    2095          31 : }
    2096             : 
    2097             : // ES#sec-promise.race
    2098             : // Promise.race ( iterable )
    2099         186 : TF_BUILTIN(PromiseRace, PromiseBuiltinsAssembler) {
    2100             :   IteratorBuiltinsAssembler iter_assembler(state());
    2101          93 :   VARIABLE(var_exception, MachineRepresentation::kTagged, TheHoleConstant());
    2102             : 
    2103             :   Node* const receiver = Parameter(Descriptor::kReceiver);
    2104             :   Node* const context = Parameter(Descriptor::kContext);
    2105             :   ThrowIfNotJSReceiver(context, receiver, MessageTemplate::kCalledOnNonObject,
    2106          31 :                        "Promise.race");
    2107             : 
    2108             :   // Let promiseCapability be ? NewPromiseCapability(C).
    2109             :   // Don't fire debugEvent so that forwarding the rejection through all does not
    2110             :   // trigger redundant ExceptionEvents
    2111          62 :   Node* const debug_event = FalseConstant();
    2112          31 :   Node* const capability = NewPromiseCapability(context, receiver, debug_event);
    2113             : 
    2114             :   Node* const resolve =
    2115             :       LoadObjectField(capability, PromiseCapability::kResolveOffset);
    2116             :   Node* const reject =
    2117             :       LoadObjectField(capability, PromiseCapability::kRejectOffset);
    2118             : 
    2119          31 :   Node* const instrumenting = IsDebugActive();
    2120             : 
    2121          31 :   Label close_iterator(this, Label::kDeferred);
    2122          31 :   Label reject_promise(this, Label::kDeferred);
    2123             : 
    2124             :   // For catch prediction, don't treat the .then calls as handling it;
    2125             :   // instead, recurse outwards.
    2126          31 :   SetForwardingHandlerIfTrue(context, instrumenting, reject);
    2127             : 
    2128             :   // Let iterator be GetIterator(iterable).
    2129             :   // IfAbruptRejectPromise(iterator, promiseCapability).
    2130             :   Node* const iterable = Parameter(Descriptor::kIterable);
    2131             :   Node* const iterator = iter_assembler.GetIterator(
    2132          31 :       context, iterable, &reject_promise, &var_exception);
    2133             : 
    2134             :   // Let result be PerformPromiseRace(iteratorRecord, C, promiseCapability).
    2135             :   {
    2136          31 :     Label loop(this), break_loop(this);
    2137          31 :     Goto(&loop);
    2138          31 :     BIND(&loop);
    2139             :     {
    2140          62 :       Node* const native_context = LoadNativeContext(context);
    2141             :       Node* const fast_iterator_result_map = LoadContextElement(
    2142          62 :           native_context, Context::ITERATOR_RESULT_MAP_INDEX);
    2143             : 
    2144             :       // Let next be IteratorStep(iteratorRecord.[[Iterator]]).
    2145             :       // If next is an abrupt completion, set iteratorRecord.[[Done]] to true.
    2146             :       // ReturnIfAbrupt(next).
    2147             :       Node* const next = iter_assembler.IteratorStep(
    2148             :           context, iterator, &break_loop, fast_iterator_result_map,
    2149          31 :           &reject_promise, &var_exception);
    2150             : 
    2151             :       // Let nextValue be IteratorValue(next).
    2152             :       // If nextValue is an abrupt completion, set iteratorRecord.[[Done]] to
    2153             :       //     true.
    2154             :       // ReturnIfAbrupt(nextValue).
    2155             :       Node* const next_value =
    2156             :           iter_assembler.IteratorValue(context, next, fast_iterator_result_map,
    2157          31 :                                        &reject_promise, &var_exception);
    2158             : 
    2159             :       // Let nextPromise be ? Invoke(constructor, "resolve", « nextValue »).
    2160             :       Node* const promise_resolve =
    2161          62 :           GetProperty(context, receiver, factory()->resolve_string());
    2162          31 :       GotoIfException(promise_resolve, &close_iterator, &var_exception);
    2163             : 
    2164             :       Node* const next_promise = CallJS(CodeFactory::Call(isolate()), context,
    2165          62 :                                         promise_resolve, receiver, next_value);
    2166          31 :       GotoIfException(next_promise, &close_iterator, &var_exception);
    2167             : 
    2168             :       // Perform ? Invoke(nextPromise, "then", « resolveElement,
    2169             :       //                  resultCapability.[[Reject]] »).
    2170             :       Node* const then =
    2171          62 :           GetProperty(context, next_promise, factory()->then_string());
    2172          31 :       GotoIfException(then, &close_iterator, &var_exception);
    2173             : 
    2174             :       Node* const then_call = CallJS(CodeFactory::Call(isolate()), context,
    2175          62 :                                      then, next_promise, resolve, reject);
    2176          31 :       GotoIfException(then_call, &close_iterator, &var_exception);
    2177             : 
    2178             :       // For catch prediction, mark that rejections here are semantically
    2179             :       // handled by the combined Promise.
    2180          31 :       SetPromiseHandledByIfTrue(context, instrumenting, then_call, [=]() {
    2181             :         // Load promiseCapability.[[Promise]]
    2182          31 :         return LoadObjectField(capability, PromiseCapability::kPromiseOffset);
    2183          93 :       });
    2184          31 :       Goto(&loop);
    2185             :     }
    2186             : 
    2187          31 :     BIND(&break_loop);
    2188          62 :     Return(LoadObjectField(capability, PromiseCapability::kPromiseOffset));
    2189             :   }
    2190             : 
    2191          31 :   BIND(&close_iterator);
    2192             :   {
    2193             :     CSA_ASSERT(this, IsNotTheHole(var_exception.value()));
    2194             :     iter_assembler.IteratorCloseOnException(context, iterator, &reject_promise,
    2195          31 :                                             &var_exception);
    2196             :   }
    2197             : 
    2198          31 :   BIND(&reject_promise);
    2199             :   {
    2200             :     Node* const reject =
    2201             :         LoadObjectField(capability, PromiseCapability::kRejectOffset);
    2202          31 :     Callable callable = CodeFactory::Call(isolate());
    2203             :     CallJS(callable, context, reject, UndefinedConstant(),
    2204          62 :            var_exception.value());
    2205             : 
    2206             :     Node* const promise =
    2207             :         LoadObjectField(capability, PromiseCapability::kPromiseOffset);
    2208          31 :     Return(promise);
    2209             :   }
    2210          31 : }
    2211             : 
    2212             : }  // namespace internal
    2213             : }  // namespace v8

Generated by: LCOV version 1.10