LCOV - code coverage report
Current view: top level - src/builtins - builtins-promise-gen.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 830 833 99.6 %
Date: 2017-04-26 Functions: 78 78 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-utils-gen.h"
       9             : #include "src/builtins/builtins.h"
      10             : #include "src/code-factory.h"
      11             : #include "src/code-stub-assembler.h"
      12             : #include "src/objects-inl.h"
      13             : 
      14             : namespace v8 {
      15             : namespace internal {
      16             : 
      17             : using compiler::Node;
      18             : 
      19        1568 : Node* PromiseBuiltinsAssembler::AllocateJSPromise(Node* context) {
      20        1568 :   Node* const native_context = LoadNativeContext(context);
      21             :   Node* const promise_fun =
      22        1568 :       LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX);
      23             :   Node* const initial_map =
      24        1568 :       LoadObjectField(promise_fun, JSFunction::kPrototypeOrInitialMapOffset);
      25        1568 :   Node* const instance = AllocateJSObjectFromMap(initial_map);
      26        1568 :   return instance;
      27             : }
      28             : 
      29        1561 : void PromiseBuiltinsAssembler::PromiseInit(Node* promise) {
      30             :   StoreObjectFieldNoWriteBarrier(promise, JSPromise::kStatusOffset,
      31        1561 :                                  SmiConstant(v8::Promise::kPending));
      32             :   StoreObjectFieldNoWriteBarrier(promise, JSPromise::kFlagsOffset,
      33        1561 :                                  SmiConstant(0));
      34        1561 : }
      35             : 
      36         831 : Node* PromiseBuiltinsAssembler::AllocateAndInitJSPromise(Node* context) {
      37         831 :   return AllocateAndInitJSPromise(context, UndefinedConstant());
      38             : }
      39             : 
      40        1289 : Node* PromiseBuiltinsAssembler::AllocateAndInitJSPromise(Node* context,
      41             :                                                          Node* parent) {
      42        1289 :   Node* const instance = AllocateJSPromise(context);
      43        1289 :   PromiseInit(instance);
      44             : 
      45        1289 :   Label out(this);
      46        1289 :   GotoIfNot(IsPromiseHookEnabledOrDebugIsActive(), &out);
      47        1289 :   CallRuntime(Runtime::kPromiseHookInit, context, instance, parent);
      48        1289 :   Goto(&out);
      49             : 
      50        1289 :   BIND(&out);
      51        1289 :   return instance;
      52             : }
      53             : 
      54          50 : Node* PromiseBuiltinsAssembler::AllocateAndSetJSPromise(Node* context,
      55             :                                                         Node* status,
      56             :                                                         Node* result) {
      57             :   CSA_ASSERT(this, TaggedIsSmi(status));
      58             : 
      59          50 :   Node* const instance = AllocateJSPromise(context);
      60             : 
      61          50 :   StoreObjectFieldNoWriteBarrier(instance, JSPromise::kStatusOffset, status);
      62          50 :   StoreObjectFieldNoWriteBarrier(instance, JSPromise::kResultOffset, result);
      63             :   StoreObjectFieldNoWriteBarrier(instance, JSPromise::kFlagsOffset,
      64          50 :                                  SmiConstant(0));
      65             : 
      66             :   Label out(this);
      67          50 :   GotoIfNot(IsPromiseHookEnabledOrDebugIsActive(), &out);
      68             :   CallRuntime(Runtime::kPromiseHookInit, context, instance,
      69          50 :               UndefinedConstant());
      70          50 :   Goto(&out);
      71             : 
      72          50 :   BIND(&out);
      73          50 :   return instance;
      74             : }
      75             : 
      76             : std::pair<Node*, Node*>
      77         587 : PromiseBuiltinsAssembler::CreatePromiseResolvingFunctions(
      78             :     Node* promise, Node* debug_event, Node* native_context) {
      79             :   Node* const promise_context = CreatePromiseResolvingFunctionsContext(
      80         587 :       promise, debug_event, native_context);
      81             :   Node* const map = LoadContextElement(
      82         587 :       native_context, Context::STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX);
      83             :   Node* const resolve_info =
      84         587 :       LoadContextElement(native_context, Context::PROMISE_RESOLVE_SHARED_FUN);
      85             :   Node* const resolve =
      86         587 :       AllocateFunctionWithMapAndContext(map, resolve_info, promise_context);
      87             :   Node* const reject_info =
      88         587 :       LoadContextElement(native_context, Context::PROMISE_REJECT_SHARED_FUN);
      89             :   Node* const reject =
      90         587 :       AllocateFunctionWithMapAndContext(map, reject_info, promise_context);
      91         587 :   return std::make_pair(resolve, reject);
      92             : }
      93             : 
      94         229 : Node* PromiseBuiltinsAssembler::NewPromiseCapability(Node* context,
      95             :                                                      Node* constructor,
      96             :                                                      Node* debug_event) {
      97         229 :   if (debug_event == nullptr) {
      98         186 :     debug_event = TrueConstant();
      99             :   }
     100             : 
     101         229 :   Node* native_context = LoadNativeContext(context);
     102             : 
     103         229 :   Node* map = LoadRoot(Heap::kJSPromiseCapabilityMapRootIndex);
     104         229 :   Node* capability = AllocateJSObjectFromMap(map);
     105             : 
     106             :   StoreObjectFieldNoWriteBarrier(
     107         229 :       capability, JSPromiseCapability::kPromiseOffset, UndefinedConstant());
     108             :   StoreObjectFieldNoWriteBarrier(
     109         229 :       capability, JSPromiseCapability::kResolveOffset, UndefinedConstant());
     110             :   StoreObjectFieldNoWriteBarrier(capability, JSPromiseCapability::kRejectOffset,
     111         229 :                                  UndefinedConstant());
     112             : 
     113         229 :   VARIABLE(var_result, MachineRepresentation::kTagged);
     114         229 :   var_result.Bind(capability);
     115             : 
     116         229 :   Label if_builtin_promise(this), if_custom_promise(this, Label::kDeferred),
     117         229 :       out(this);
     118             :   Branch(WordEqual(constructor,
     119             :                    LoadContextElement(native_context,
     120             :                                       Context::PROMISE_FUNCTION_INDEX)),
     121         229 :          &if_builtin_promise, &if_custom_promise);
     122             : 
     123         229 :   BIND(&if_builtin_promise);
     124             :   {
     125         229 :     Node* promise = AllocateJSPromise(context);
     126         229 :     PromiseInit(promise);
     127         229 :     StoreObjectField(capability, JSPromiseCapability::kPromiseOffset, promise);
     128             : 
     129         229 :     Node* resolve = nullptr;
     130         229 :     Node* reject = nullptr;
     131             : 
     132         458 :     std::tie(resolve, reject) =
     133             :         CreatePromiseResolvingFunctions(promise, debug_event, native_context);
     134         229 :     StoreObjectField(capability, JSPromiseCapability::kResolveOffset, resolve);
     135         229 :     StoreObjectField(capability, JSPromiseCapability::kRejectOffset, reject);
     136             : 
     137         229 :     GotoIfNot(IsPromiseHookEnabledOrDebugIsActive(), &out);
     138             :     CallRuntime(Runtime::kPromiseHookInit, context, promise,
     139         229 :                 UndefinedConstant());
     140         229 :     Goto(&out);
     141             :   }
     142             : 
     143         229 :   BIND(&if_custom_promise);
     144             :   {
     145             :     Label if_notcallable(this, Label::kDeferred);
     146             :     Node* executor_context =
     147         229 :         CreatePromiseGetCapabilitiesExecutorContext(capability, native_context);
     148             :     Node* executor_info = LoadContextElement(
     149         229 :         native_context, Context::PROMISE_GET_CAPABILITIES_EXECUTOR_SHARED_FUN);
     150             :     Node* function_map = LoadContextElement(
     151         229 :         native_context, Context::STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX);
     152             :     Node* executor = AllocateFunctionWithMapAndContext(
     153         229 :         function_map, executor_info, executor_context);
     154             : 
     155             :     Node* promise = ConstructJS(CodeFactory::Construct(isolate()), context,
     156         229 :                                 constructor, executor);
     157             : 
     158             :     Node* resolve =
     159         229 :         LoadObjectField(capability, JSPromiseCapability::kResolveOffset);
     160         229 :     GotoIf(TaggedIsSmi(resolve), &if_notcallable);
     161         229 :     GotoIfNot(IsCallableMap(LoadMap(resolve)), &if_notcallable);
     162             : 
     163             :     Node* reject =
     164         229 :         LoadObjectField(capability, JSPromiseCapability::kRejectOffset);
     165         229 :     GotoIf(TaggedIsSmi(reject), &if_notcallable);
     166         229 :     GotoIfNot(IsCallableMap(LoadMap(reject)), &if_notcallable);
     167             : 
     168         229 :     StoreObjectField(capability, JSPromiseCapability::kPromiseOffset, promise);
     169             : 
     170         229 :     Goto(&out);
     171             : 
     172         229 :     BIND(&if_notcallable);
     173         229 :     Node* message = SmiConstant(MessageTemplate::kPromiseNonCallable);
     174             :     StoreObjectField(capability, JSPromiseCapability::kPromiseOffset,
     175         229 :                      UndefinedConstant());
     176             :     StoreObjectField(capability, JSPromiseCapability::kResolveOffset,
     177         229 :                      UndefinedConstant());
     178             :     StoreObjectField(capability, JSPromiseCapability::kRejectOffset,
     179         229 :                      UndefinedConstant());
     180         229 :     CallRuntime(Runtime::kThrowTypeError, context, message);
     181         229 :     Unreachable();
     182             :   }
     183             : 
     184         229 :   BIND(&out);
     185         458 :   return var_result.value();
     186             : }
     187             : 
     188        1310 : Node* PromiseBuiltinsAssembler::CreatePromiseContext(Node* native_context,
     189             :                                                      int slots) {
     190             :   DCHECK_GE(slots, Context::MIN_CONTEXT_SLOTS);
     191             : 
     192        1310 :   Node* const context = Allocate(FixedArray::SizeFor(slots));
     193        1310 :   StoreMapNoWriteBarrier(context, Heap::kFunctionContextMapRootIndex);
     194             :   StoreObjectFieldNoWriteBarrier(context, FixedArray::kLengthOffset,
     195        1310 :                                  SmiConstant(slots));
     196             : 
     197             :   Node* const empty_fn =
     198        1310 :       LoadContextElement(native_context, Context::CLOSURE_INDEX);
     199        1310 :   StoreContextElementNoWriteBarrier(context, Context::CLOSURE_INDEX, empty_fn);
     200             :   StoreContextElementNoWriteBarrier(context, Context::PREVIOUS_INDEX,
     201        1310 :                                     UndefinedConstant());
     202             :   StoreContextElementNoWriteBarrier(context, Context::EXTENSION_INDEX,
     203        1310 :                                     TheHoleConstant());
     204             :   StoreContextElementNoWriteBarrier(context, Context::NATIVE_CONTEXT_INDEX,
     205        1310 :                                     native_context);
     206        1310 :   return context;
     207             : }
     208             : 
     209         601 : Node* PromiseBuiltinsAssembler::CreatePromiseResolvingFunctionsContext(
     210             :     Node* promise, Node* debug_event, Node* native_context) {
     211             :   Node* const context =
     212         601 :       CreatePromiseContext(native_context, kPromiseContextLength);
     213             :   StoreContextElementNoWriteBarrier(context, kAlreadyVisitedSlot,
     214         601 :                                     SmiConstant(0));
     215         601 :   StoreContextElementNoWriteBarrier(context, kPromiseSlot, promise);
     216         601 :   StoreContextElementNoWriteBarrier(context, kDebugEventSlot, debug_event);
     217         601 :   return context;
     218             : }
     219             : 
     220         236 : Node* PromiseBuiltinsAssembler::CreatePromiseGetCapabilitiesExecutorContext(
     221             :     Node* promise_capability, Node* native_context) {
     222             :   int kContextLength = kCapabilitiesContextLength;
     223         236 :   Node* context = CreatePromiseContext(native_context, kContextLength);
     224             :   StoreContextElementNoWriteBarrier(context, kCapabilitySlot,
     225         236 :                                     promise_capability);
     226         236 :   return context;
     227             : }
     228             : 
     229         172 : Node* PromiseBuiltinsAssembler::ThrowIfNotJSReceiver(
     230             :     Node* context, Node* value, MessageTemplate::Template msg_template,
     231             :     const char* method_name) {
     232         344 :   Label out(this), throw_exception(this, Label::kDeferred);
     233         344 :   VARIABLE(var_value_map, MachineRepresentation::kTagged);
     234             : 
     235         172 :   GotoIf(TaggedIsSmi(value), &throw_exception);
     236             : 
     237             :   // Load the instance type of the {value}.
     238         172 :   var_value_map.Bind(LoadMap(value));
     239         172 :   Node* const value_instance_type = LoadMapInstanceType(var_value_map.value());
     240             : 
     241         172 :   Branch(IsJSReceiverInstanceType(value_instance_type), &out, &throw_exception);
     242             : 
     243             :   // The {value} is not a compatible receiver for this method.
     244         172 :   BIND(&throw_exception);
     245             :   {
     246             :     Node* const method =
     247             :         method_name == nullptr
     248             :             ? UndefinedConstant()
     249             :             : HeapConstant(
     250         258 :                   isolate()->factory()->NewStringFromAsciiChecked(method_name));
     251         172 :     Node* const message_id = SmiConstant(msg_template);
     252         172 :     CallRuntime(Runtime::kThrowTypeError, context, message_id, method);
     253         172 :     Unreachable();
     254             :   }
     255             : 
     256         172 :   BIND(&out);
     257         344 :   return var_value_map.value();
     258             : }
     259             : 
     260        1340 : Node* PromiseBuiltinsAssembler::PromiseHasHandler(Node* promise) {
     261        1340 :   Node* const flags = LoadObjectField(promise, JSPromise::kFlagsOffset);
     262        1340 :   return IsSetWord(SmiUntag(flags), 1 << JSPromise::kHasHandlerBit);
     263             : }
     264             : 
     265        1032 : void PromiseBuiltinsAssembler::PromiseSetHasHandler(Node* promise) {
     266        1032 :   Node* const flags = LoadObjectField(promise, JSPromise::kFlagsOffset);
     267             :   Node* const new_flags =
     268        1032 :       SmiOr(flags, SmiConstant(1 << JSPromise::kHasHandlerBit));
     269        1032 :   StoreObjectFieldNoWriteBarrier(promise, JSPromise::kFlagsOffset, new_flags);
     270        1032 : }
     271             : 
     272          86 : void PromiseBuiltinsAssembler::PromiseSetHandledHint(Node* promise) {
     273          86 :   Node* const flags = LoadObjectField(promise, JSPromise::kFlagsOffset);
     274             :   Node* const new_flags =
     275          86 :       SmiOr(flags, SmiConstant(1 << JSPromise::kHandledHintBit));
     276          86 :   StoreObjectFieldNoWriteBarrier(promise, JSPromise::kFlagsOffset, new_flags);
     277          86 : }
     278             : 
     279          86 : Node* PromiseBuiltinsAssembler::SpeciesConstructor(Node* context, Node* object,
     280             :                                                    Node* default_constructor) {
     281          86 :   Isolate* isolate = this->isolate();
     282          86 :   VARIABLE(var_result, MachineRepresentation::kTagged);
     283          86 :   var_result.Bind(default_constructor);
     284             : 
     285             :   // 2. Let C be ? Get(O, "constructor").
     286             :   Node* const constructor =
     287          86 :       GetProperty(context, object, isolate->factory()->constructor_string());
     288             : 
     289             :   // 3. If C is undefined, return defaultConstructor.
     290          86 :   Label out(this);
     291          86 :   GotoIf(IsUndefined(constructor), &out);
     292             : 
     293             :   // 4. If Type(C) is not Object, throw a TypeError exception.
     294             :   ThrowIfNotJSReceiver(context, constructor,
     295          86 :                        MessageTemplate::kConstructorNotReceiver);
     296             : 
     297             :   // 5. Let S be ? Get(C, @@species).
     298             :   Node* const species =
     299          86 :       GetProperty(context, constructor, isolate->factory()->species_symbol());
     300             : 
     301             :   // 6. If S is either undefined or null, return defaultConstructor.
     302          86 :   GotoIf(IsUndefined(species), &out);
     303          86 :   GotoIf(WordEqual(species, NullConstant()), &out);
     304             : 
     305             :   // 7. If IsConstructor(S) is true, return S.
     306          86 :   Label throw_error(this);
     307          86 :   Node* species_bitfield = LoadMapBitField(LoadMap(species));
     308             :   GotoIfNot(Word32Equal(Word32And(species_bitfield,
     309             :                                   Int32Constant((1 << Map::kIsConstructor))),
     310             :                         Int32Constant(1 << Map::kIsConstructor)),
     311          86 :             &throw_error);
     312          86 :   var_result.Bind(species);
     313          86 :   Goto(&out);
     314             : 
     315             :   // 8. Throw a TypeError exception.
     316          86 :   BIND(&throw_error);
     317             :   {
     318             :     Node* const message_id =
     319          86 :         SmiConstant(MessageTemplate::kSpeciesNotConstructor);
     320          86 :     CallRuntime(Runtime::kThrowTypeError, context, message_id);
     321          86 :     Unreachable();
     322             :   }
     323             : 
     324          86 :   BIND(&out);
     325         172 :   return var_result.value();
     326             : }
     327             : 
     328        1290 : void PromiseBuiltinsAssembler::AppendPromiseCallback(int offset, Node* promise,
     329             :                                                      Node* value) {
     330        1290 :   Node* elements = LoadObjectField(promise, offset);
     331        1290 :   Node* length = LoadFixedArrayBaseLength(elements);
     332             :   CodeStubAssembler::ParameterMode mode = OptimalParameterMode();
     333             :   length = TaggedToParameter(length, mode);
     334             : 
     335        1290 :   Node* delta = IntPtrOrSmiConstant(1, mode);
     336        1290 :   Node* new_capacity = IntPtrOrSmiAdd(length, delta, mode);
     337             : 
     338             :   const ElementsKind kind = FAST_ELEMENTS;
     339             :   const WriteBarrierMode barrier_mode = UPDATE_WRITE_BARRIER;
     340             :   const CodeStubAssembler::AllocationFlags flags =
     341             :       CodeStubAssembler::kAllowLargeObjectAllocation;
     342             :   int additional_offset = 0;
     343             : 
     344        1290 :   Node* new_elements = AllocateFixedArray(kind, new_capacity, mode, flags);
     345             : 
     346             :   CopyFixedArrayElements(kind, elements, new_elements, length, barrier_mode,
     347             :                          mode);
     348             :   StoreFixedArrayElement(new_elements, length, value, barrier_mode,
     349        1290 :                          additional_offset, mode);
     350             : 
     351        1290 :   StoreObjectField(promise, offset, new_elements);
     352        1290 : }
     353             : 
     354          86 : Node* PromiseBuiltinsAssembler::InternalPromiseThen(Node* context,
     355             :                                                     Node* promise,
     356             :                                                     Node* on_resolve,
     357             :                                                     Node* on_reject) {
     358          86 :   Isolate* isolate = this->isolate();
     359             : 
     360             :   // 2. If IsPromise(promise) is false, throw a TypeError exception.
     361             :   ThrowIfNotInstanceType(context, promise, JS_PROMISE_TYPE,
     362          86 :                          "Promise.prototype.then");
     363             : 
     364          86 :   Node* const native_context = LoadNativeContext(context);
     365             :   Node* const promise_fun =
     366          86 :       LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX);
     367             : 
     368             :   // 3. Let C be ? SpeciesConstructor(promise, %Promise%).
     369          86 :   Node* constructor = SpeciesConstructor(context, promise, promise_fun);
     370             : 
     371             :   // 4. Let resultCapability be ? NewPromiseCapability(C).
     372          86 :   Callable call_callable = CodeFactory::Call(isolate);
     373          86 :   Label fast_promise_capability(this), promise_capability(this),
     374          86 :       perform_promise_then(this);
     375         172 :   VARIABLE(var_deferred_promise, MachineRepresentation::kTagged);
     376         172 :   VARIABLE(var_deferred_on_resolve, MachineRepresentation::kTagged);
     377         172 :   VARIABLE(var_deferred_on_reject, MachineRepresentation::kTagged);
     378             : 
     379             :   Branch(WordEqual(promise_fun, constructor), &fast_promise_capability,
     380          86 :          &promise_capability);
     381             : 
     382          86 :   BIND(&fast_promise_capability);
     383             :   {
     384          86 :     Node* const deferred_promise = AllocateAndInitJSPromise(context, promise);
     385          86 :     var_deferred_promise.Bind(deferred_promise);
     386          86 :     var_deferred_on_resolve.Bind(UndefinedConstant());
     387          86 :     var_deferred_on_reject.Bind(UndefinedConstant());
     388          86 :     Goto(&perform_promise_then);
     389             :   }
     390             : 
     391          86 :   BIND(&promise_capability);
     392             :   {
     393          86 :     Node* const capability = NewPromiseCapability(context, constructor);
     394             :     var_deferred_promise.Bind(
     395          86 :         LoadObjectField(capability, JSPromiseCapability::kPromiseOffset));
     396             :     var_deferred_on_resolve.Bind(
     397          86 :         LoadObjectField(capability, JSPromiseCapability::kResolveOffset));
     398             :     var_deferred_on_reject.Bind(
     399          86 :         LoadObjectField(capability, JSPromiseCapability::kRejectOffset));
     400          86 :     Goto(&perform_promise_then);
     401             :   }
     402             : 
     403             :   // 5. Return PerformPromiseThen(promise, onFulfilled, onRejected,
     404             :   //    resultCapability).
     405          86 :   BIND(&perform_promise_then);
     406             :   Node* const result = InternalPerformPromiseThen(
     407             :       context, promise, on_resolve, on_reject, var_deferred_promise.value(),
     408          86 :       var_deferred_on_resolve.value(), var_deferred_on_reject.value());
     409          86 :   return result;
     410             : }
     411             : 
     412         258 : Node* PromiseBuiltinsAssembler::InternalPerformPromiseThen(
     413             :     Node* context, Node* promise, Node* on_resolve, Node* on_reject,
     414             :     Node* deferred_promise, Node* deferred_on_resolve,
     415             :     Node* deferred_on_reject) {
     416         258 :   VARIABLE(var_on_resolve, MachineRepresentation::kTagged);
     417         516 :   VARIABLE(var_on_reject, MachineRepresentation::kTagged);
     418             : 
     419         258 :   var_on_resolve.Bind(on_resolve);
     420         258 :   var_on_reject.Bind(on_reject);
     421             : 
     422         258 :   Label out(this), if_onresolvenotcallable(this), onrejectcheck(this),
     423         258 :       append_callbacks(this);
     424         258 :   GotoIf(TaggedIsSmi(on_resolve), &if_onresolvenotcallable);
     425             : 
     426         258 :   Isolate* isolate = this->isolate();
     427         258 :   Node* const on_resolve_map = LoadMap(on_resolve);
     428             :   Branch(IsCallableMap(on_resolve_map), &onrejectcheck,
     429         258 :          &if_onresolvenotcallable);
     430             : 
     431         258 :   BIND(&if_onresolvenotcallable);
     432             :   {
     433             :     Node* const default_resolve_handler_symbol = HeapConstant(
     434         258 :         isolate->factory()->promise_default_resolve_handler_symbol());
     435         258 :     var_on_resolve.Bind(default_resolve_handler_symbol);
     436         258 :     Goto(&onrejectcheck);
     437             :   }
     438             : 
     439         258 :   BIND(&onrejectcheck);
     440             :   {
     441             :     Label if_onrejectnotcallable(this);
     442         258 :     GotoIf(TaggedIsSmi(on_reject), &if_onrejectnotcallable);
     443             : 
     444         258 :     Node* const on_reject_map = LoadMap(on_reject);
     445             :     Branch(IsCallableMap(on_reject_map), &append_callbacks,
     446         258 :            &if_onrejectnotcallable);
     447             : 
     448         258 :     BIND(&if_onrejectnotcallable);
     449             :     {
     450             :       Node* const default_reject_handler_symbol = HeapConstant(
     451         258 :           isolate->factory()->promise_default_reject_handler_symbol());
     452         258 :       var_on_reject.Bind(default_reject_handler_symbol);
     453         258 :       Goto(&append_callbacks);
     454         258 :     }
     455             :   }
     456             : 
     457         258 :   BIND(&append_callbacks);
     458             :   {
     459             :     Label fulfilled_check(this);
     460         258 :     Node* const status = LoadObjectField(promise, JSPromise::kStatusOffset);
     461             :     GotoIfNot(SmiEqual(status, SmiConstant(v8::Promise::kPending)),
     462         258 :               &fulfilled_check);
     463             : 
     464             :     Node* const existing_deferred_promise =
     465         258 :         LoadObjectField(promise, JSPromise::kDeferredPromiseOffset);
     466             : 
     467         258 :     Label if_noexistingcallbacks(this), if_existingcallbacks(this);
     468             :     Branch(IsUndefined(existing_deferred_promise), &if_noexistingcallbacks,
     469         258 :            &if_existingcallbacks);
     470             : 
     471         258 :     BIND(&if_noexistingcallbacks);
     472             :     {
     473             :       // Store callbacks directly in the slots.
     474             :       StoreObjectField(promise, JSPromise::kDeferredPromiseOffset,
     475         258 :                        deferred_promise);
     476             :       StoreObjectField(promise, JSPromise::kDeferredOnResolveOffset,
     477         258 :                        deferred_on_resolve);
     478             :       StoreObjectField(promise, JSPromise::kDeferredOnRejectOffset,
     479         258 :                        deferred_on_reject);
     480             :       StoreObjectField(promise, JSPromise::kFulfillReactionsOffset,
     481         258 :                        var_on_resolve.value());
     482             :       StoreObjectField(promise, JSPromise::kRejectReactionsOffset,
     483         258 :                        var_on_reject.value());
     484         258 :       Goto(&out);
     485             :     }
     486             : 
     487         258 :     BIND(&if_existingcallbacks);
     488             :     {
     489         258 :       Label if_singlecallback(this), if_multiplecallbacks(this);
     490             :       BranchIfJSObject(existing_deferred_promise, &if_singlecallback,
     491         258 :                        &if_multiplecallbacks);
     492             : 
     493         258 :       BIND(&if_singlecallback);
     494             :       {
     495             :         // Create new FixedArrays to store callbacks, and migrate
     496             :         // existing callbacks.
     497             :         Node* const deferred_promise_arr =
     498         258 :             AllocateFixedArray(FAST_ELEMENTS, IntPtrConstant(2));
     499             :         StoreFixedArrayElement(deferred_promise_arr, 0,
     500         258 :                                existing_deferred_promise);
     501         258 :         StoreFixedArrayElement(deferred_promise_arr, 1, deferred_promise);
     502             : 
     503             :         Node* const deferred_on_resolve_arr =
     504         258 :             AllocateFixedArray(FAST_ELEMENTS, IntPtrConstant(2));
     505             :         StoreFixedArrayElement(
     506             :             deferred_on_resolve_arr, 0,
     507         258 :             LoadObjectField(promise, JSPromise::kDeferredOnResolveOffset));
     508         258 :         StoreFixedArrayElement(deferred_on_resolve_arr, 1, deferred_on_resolve);
     509             : 
     510             :         Node* const deferred_on_reject_arr =
     511         258 :             AllocateFixedArray(FAST_ELEMENTS, IntPtrConstant(2));
     512             :         StoreFixedArrayElement(
     513             :             deferred_on_reject_arr, 0,
     514         258 :             LoadObjectField(promise, JSPromise::kDeferredOnRejectOffset));
     515         258 :         StoreFixedArrayElement(deferred_on_reject_arr, 1, deferred_on_reject);
     516             : 
     517             :         Node* const fulfill_reactions =
     518         258 :             AllocateFixedArray(FAST_ELEMENTS, IntPtrConstant(2));
     519             :         StoreFixedArrayElement(
     520             :             fulfill_reactions, 0,
     521         258 :             LoadObjectField(promise, JSPromise::kFulfillReactionsOffset));
     522         258 :         StoreFixedArrayElement(fulfill_reactions, 1, var_on_resolve.value());
     523             : 
     524             :         Node* const reject_reactions =
     525         258 :             AllocateFixedArray(FAST_ELEMENTS, IntPtrConstant(2));
     526             :         StoreFixedArrayElement(
     527             :             reject_reactions, 0,
     528         258 :             LoadObjectField(promise, JSPromise::kRejectReactionsOffset));
     529         258 :         StoreFixedArrayElement(reject_reactions, 1, var_on_reject.value());
     530             : 
     531             :         // Store new FixedArrays in promise.
     532             :         StoreObjectField(promise, JSPromise::kDeferredPromiseOffset,
     533         258 :                          deferred_promise_arr);
     534             :         StoreObjectField(promise, JSPromise::kDeferredOnResolveOffset,
     535         258 :                          deferred_on_resolve_arr);
     536             :         StoreObjectField(promise, JSPromise::kDeferredOnRejectOffset,
     537         258 :                          deferred_on_reject_arr);
     538             :         StoreObjectField(promise, JSPromise::kFulfillReactionsOffset,
     539         258 :                          fulfill_reactions);
     540             :         StoreObjectField(promise, JSPromise::kRejectReactionsOffset,
     541         258 :                          reject_reactions);
     542         258 :         Goto(&out);
     543             :       }
     544             : 
     545         258 :       BIND(&if_multiplecallbacks);
     546             :       {
     547             :         AppendPromiseCallback(JSPromise::kDeferredPromiseOffset, promise,
     548         258 :                               deferred_promise);
     549             :         AppendPromiseCallback(JSPromise::kDeferredOnResolveOffset, promise,
     550         258 :                               deferred_on_resolve);
     551             :         AppendPromiseCallback(JSPromise::kDeferredOnRejectOffset, promise,
     552         258 :                               deferred_on_reject);
     553             :         AppendPromiseCallback(JSPromise::kFulfillReactionsOffset, promise,
     554         258 :                               var_on_resolve.value());
     555             :         AppendPromiseCallback(JSPromise::kRejectReactionsOffset, promise,
     556         258 :                               var_on_reject.value());
     557         258 :         Goto(&out);
     558         258 :       }
     559             :     }
     560             : 
     561         258 :     BIND(&fulfilled_check);
     562             :     {
     563             :       Label reject(this);
     564         258 :       Node* const result = LoadObjectField(promise, JSPromise::kResultOffset);
     565             :       GotoIfNot(WordEqual(status, SmiConstant(v8::Promise::kFulfilled)),
     566         258 :                 &reject);
     567             : 
     568             :       Node* info = AllocatePromiseReactionJobInfo(
     569             :           result, var_on_resolve.value(), deferred_promise, deferred_on_resolve,
     570         258 :           deferred_on_reject, context);
     571             :       // TODO(gsathya): Move this to TF
     572         258 :       CallRuntime(Runtime::kEnqueuePromiseReactionJob, context, info);
     573         258 :       Goto(&out);
     574             : 
     575         258 :       BIND(&reject);
     576             :       {
     577         258 :         Node* const has_handler = PromiseHasHandler(promise);
     578             :         Label enqueue(this);
     579             : 
     580             :         // TODO(gsathya): Fold these runtime calls and move to TF.
     581         258 :         GotoIf(has_handler, &enqueue);
     582         258 :         CallRuntime(Runtime::kPromiseRevokeReject, context, promise);
     583         258 :         Goto(&enqueue);
     584             : 
     585         258 :         BIND(&enqueue);
     586             :         {
     587             :           Node* info = AllocatePromiseReactionJobInfo(
     588             :               result, var_on_reject.value(), deferred_promise,
     589         258 :               deferred_on_resolve, deferred_on_reject, context);
     590             :           // TODO(gsathya): Move this to TF
     591         258 :           CallRuntime(Runtime::kEnqueuePromiseReactionJob, context, info);
     592         258 :           Goto(&out);
     593         258 :         }
     594         258 :       }
     595         258 :     }
     596             :   }
     597             : 
     598         258 :   BIND(&out);
     599         258 :   PromiseSetHasHandler(promise);
     600         258 :   return deferred_promise;
     601             : }
     602             : 
     603             : // Promise fast path implementations rely on unmodified JSPromise instances.
     604             : // We use a fairly coarse granularity for this and simply check whether both
     605             : // the promise itself is unmodified (i.e. its map has not changed) and its
     606             : // prototype is unmodified.
     607             : // TODO(gsathya): Refactor this out to prevent code dupe with builtins-regexp
     608          86 : void PromiseBuiltinsAssembler::BranchIfFastPath(Node* context, Node* promise,
     609             :                                                 Label* if_isunmodified,
     610             :                                                 Label* if_ismodified) {
     611          86 :   Node* const native_context = LoadNativeContext(context);
     612             :   Node* const promise_fun =
     613          86 :       LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX);
     614             :   BranchIfFastPath(native_context, promise_fun, promise, if_isunmodified,
     615          86 :                    if_ismodified);
     616          86 : }
     617             : 
     618         430 : void PromiseBuiltinsAssembler::BranchIfFastPath(Node* native_context,
     619             :                                                 Node* promise_fun,
     620             :                                                 Node* promise,
     621             :                                                 Label* if_isunmodified,
     622             :                                                 Label* if_ismodified) {
     623             :   CSA_ASSERT(this, IsNativeContext(native_context));
     624             :   CSA_ASSERT(this,
     625             :              WordEqual(promise_fun,
     626             :                        LoadContextElement(native_context,
     627             :                                           Context::PROMISE_FUNCTION_INDEX)));
     628             : 
     629         430 :   Node* const map = LoadMap(promise);
     630             :   Node* const initial_map =
     631         430 :       LoadObjectField(promise_fun, JSFunction::kPrototypeOrInitialMapOffset);
     632         430 :   Node* const has_initialmap = WordEqual(map, initial_map);
     633             : 
     634         430 :   GotoIfNot(has_initialmap, if_ismodified);
     635             : 
     636             :   Node* const initial_proto_initial_map =
     637         430 :       LoadContextElement(native_context, Context::PROMISE_PROTOTYPE_MAP_INDEX);
     638         430 :   Node* const proto_map = LoadMap(LoadMapPrototype(map));
     639             :   Node* const proto_has_initialmap =
     640         430 :       WordEqual(proto_map, initial_proto_initial_map);
     641             : 
     642         430 :   Branch(proto_has_initialmap, if_isunmodified, if_ismodified);
     643         430 : }
     644             : 
     645         308 : Node* PromiseBuiltinsAssembler::AllocatePromiseResolveThenableJobInfo(
     646             :     Node* thenable, Node* then, Node* resolve, Node* reject, Node* context) {
     647         308 :   Node* const info = Allocate(PromiseResolveThenableJobInfo::kSize);
     648             :   StoreMapNoWriteBarrier(info,
     649         308 :                          Heap::kPromiseResolveThenableJobInfoMapRootIndex);
     650             :   StoreObjectFieldNoWriteBarrier(
     651         308 :       info, PromiseResolveThenableJobInfo::kThenableOffset, thenable);
     652             :   StoreObjectFieldNoWriteBarrier(
     653         308 :       info, PromiseResolveThenableJobInfo::kThenOffset, then);
     654             :   StoreObjectFieldNoWriteBarrier(
     655         308 :       info, PromiseResolveThenableJobInfo::kResolveOffset, resolve);
     656             :   StoreObjectFieldNoWriteBarrier(
     657         308 :       info, PromiseResolveThenableJobInfo::kRejectOffset, reject);
     658             :   StoreObjectFieldNoWriteBarrier(
     659         308 :       info, PromiseResolveThenableJobInfo::kContextOffset, context);
     660         308 :   return info;
     661             : }
     662             : 
     663         301 : void PromiseBuiltinsAssembler::InternalResolvePromise(Node* context,
     664             :                                                       Node* promise,
     665             :                                                       Node* result) {
     666         301 :   Isolate* isolate = this->isolate();
     667             : 
     668         301 :   VARIABLE(var_reason, MachineRepresentation::kTagged);
     669         602 :   VARIABLE(var_then, MachineRepresentation::kTagged);
     670             : 
     671         301 :   Label do_enqueue(this), fulfill(this), if_cycle(this, Label::kDeferred),
     672         301 :       if_rejectpromise(this, Label::kDeferred), out(this);
     673             : 
     674         301 :   Label cycle_check(this);
     675         301 :   GotoIfNot(IsPromiseHookEnabledOrDebugIsActive(), &cycle_check);
     676         301 :   CallRuntime(Runtime::kPromiseHookResolve, context, promise);
     677         301 :   Goto(&cycle_check);
     678             : 
     679         301 :   BIND(&cycle_check);
     680             :   // 6. If SameValue(resolution, promise) is true, then
     681         301 :   GotoIf(SameValue(promise, result), &if_cycle);
     682             : 
     683             :   // 7. If Type(resolution) is not Object, then
     684         301 :   GotoIf(TaggedIsSmi(result), &fulfill);
     685         301 :   GotoIfNot(IsJSReceiver(result), &fulfill);
     686             : 
     687         301 :   Label if_nativepromise(this), if_notnativepromise(this, Label::kDeferred);
     688         301 :   Node* const native_context = LoadNativeContext(context);
     689             :   Node* const promise_fun =
     690         301 :       LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX);
     691             :   BranchIfFastPath(native_context, promise_fun, result, &if_nativepromise,
     692         301 :                    &if_notnativepromise);
     693             : 
     694             :   // Resolution is a native promise and if it's already resolved or
     695             :   // rejected, shortcircuit the resolution procedure by directly
     696             :   // reusing the value from the promise.
     697         301 :   BIND(&if_nativepromise);
     698             :   {
     699             :     Node* const thenable_status =
     700         301 :         LoadObjectField(result, JSPromise::kStatusOffset);
     701             :     Node* const thenable_value =
     702         301 :         LoadObjectField(result, JSPromise::kResultOffset);
     703             : 
     704             :     Label if_isnotpending(this);
     705             :     GotoIfNot(SmiEqual(SmiConstant(v8::Promise::kPending), thenable_status),
     706         301 :               &if_isnotpending);
     707             : 
     708             :     // TODO(gsathya): Use a marker here instead of the actual then
     709             :     // callback, and check for the marker in PromiseResolveThenableJob
     710             :     // and perform PromiseThen.
     711             :     Node* const then =
     712         301 :         LoadContextElement(native_context, Context::PROMISE_THEN_INDEX);
     713         301 :     var_then.Bind(then);
     714         301 :     Goto(&do_enqueue);
     715             : 
     716         301 :     BIND(&if_isnotpending);
     717             :     {
     718         301 :       Label if_fulfilled(this), if_rejected(this);
     719             :       Branch(SmiEqual(SmiConstant(v8::Promise::kFulfilled), thenable_status),
     720         301 :              &if_fulfilled, &if_rejected);
     721             : 
     722         301 :       BIND(&if_fulfilled);
     723             :       {
     724             :         PromiseFulfill(context, promise, thenable_value,
     725         301 :                        v8::Promise::kFulfilled);
     726         301 :         PromiseSetHasHandler(promise);
     727         301 :         Goto(&out);
     728             :       }
     729             : 
     730         301 :       BIND(&if_rejected);
     731             :       {
     732             :         Label reject(this);
     733         301 :         Node* const has_handler = PromiseHasHandler(result);
     734             : 
     735             :         // Promise has already been rejected, but had no handler.
     736             :         // Revoke previously triggered reject event.
     737         301 :         GotoIf(has_handler, &reject);
     738         301 :         CallRuntime(Runtime::kPromiseRevokeReject, context, result);
     739         301 :         Goto(&reject);
     740             : 
     741         301 :         BIND(&reject);
     742             :         // Don't cause a debug event as this case is forwarding a rejection.
     743         301 :         InternalPromiseReject(context, promise, thenable_value, false);
     744         301 :         PromiseSetHasHandler(result);
     745         301 :         Goto(&out);
     746         301 :       }
     747         301 :     }
     748             :   }
     749             : 
     750         301 :   BIND(&if_notnativepromise);
     751             :   {
     752             :     // 8. Let then be Get(resolution, "then").
     753             :     Node* const then =
     754         301 :         GetProperty(context, result, isolate->factory()->then_string());
     755             : 
     756             :     // 9. If then is an abrupt completion, then
     757         301 :     GotoIfException(then, &if_rejectpromise, &var_reason);
     758             : 
     759             :     // 11. If IsCallable(thenAction) is false, then
     760         301 :     GotoIf(TaggedIsSmi(then), &fulfill);
     761         301 :     Node* const then_map = LoadMap(then);
     762         301 :     GotoIfNot(IsCallableMap(then_map), &fulfill);
     763         301 :     var_then.Bind(then);
     764         301 :     Goto(&do_enqueue);
     765             :   }
     766             : 
     767         301 :   BIND(&do_enqueue);
     768             :   {
     769             :     // TODO(gsathya): Add fast path for native promises with unmodified
     770             :     // PromiseThen (which don't need these resolving functions, but
     771             :     // instead can just call resolve/reject directly).
     772         301 :     Node* resolve = nullptr;
     773         301 :     Node* reject = nullptr;
     774         602 :     std::tie(resolve, reject) = CreatePromiseResolvingFunctions(
     775         301 :         promise, FalseConstant(), native_context);
     776             : 
     777             :     Node* const info = AllocatePromiseResolveThenableJobInfo(
     778         301 :         result, var_then.value(), resolve, reject, context);
     779             : 
     780             :     Label enqueue(this);
     781         301 :     GotoIfNot(IsDebugActive(), &enqueue);
     782             : 
     783         301 :     GotoIf(TaggedIsSmi(result), &enqueue);
     784         301 :     GotoIfNot(HasInstanceType(result, JS_PROMISE_TYPE), &enqueue);
     785             : 
     786             :     // Mark the dependency of the new promise on the resolution
     787             :     Node* const key =
     788         301 :         HeapConstant(isolate->factory()->promise_handled_by_symbol());
     789             :     CallRuntime(Runtime::kSetProperty, context, result, key, promise,
     790         301 :                 SmiConstant(STRICT));
     791         301 :     Goto(&enqueue);
     792             : 
     793             :     // 12. Perform EnqueueJob("PromiseJobs",
     794             :     // PromiseResolveThenableJob, « promise, resolution, thenAction»).
     795         301 :     BIND(&enqueue);
     796             :     // TODO(gsathya): Move this to TF
     797         301 :     CallRuntime(Runtime::kEnqueuePromiseResolveThenableJob, context, info);
     798         301 :     Goto(&out);
     799             :   }
     800             : 
     801             :   // 7.b Return FulfillPromise(promise, resolution).
     802         301 :   BIND(&fulfill);
     803             :   {
     804         301 :     PromiseFulfill(context, promise, result, v8::Promise::kFulfilled);
     805         301 :     Goto(&out);
     806             :   }
     807             : 
     808         301 :   BIND(&if_cycle);
     809             :   {
     810             :     // 6.a Let selfResolutionError be a newly created TypeError object.
     811         301 :     Node* const message_id = SmiConstant(MessageTemplate::kPromiseCyclic);
     812             :     Node* const error =
     813         301 :         CallRuntime(Runtime::kNewTypeError, context, message_id, result);
     814         301 :     var_reason.Bind(error);
     815             : 
     816             :     // 6.b Return RejectPromise(promise, selfResolutionError).
     817         301 :     Goto(&if_rejectpromise);
     818             :   }
     819             : 
     820             :   // 9.a Return RejectPromise(promise, then.[[Value]]).
     821         301 :   BIND(&if_rejectpromise);
     822             :   {
     823             :     // Don't cause a debug event as this case is forwarding a rejection.
     824         301 :     InternalPromiseReject(context, promise, var_reason.value(), false);
     825         301 :     Goto(&out);
     826             :   }
     827             : 
     828         602 :   BIND(&out);
     829         301 : }
     830             : 
     831        1419 : void PromiseBuiltinsAssembler::PromiseFulfill(
     832             :     Node* context, Node* promise, Node* result,
     833             :     v8::Promise::PromiseState status) {
     834        2838 :   Label do_promisereset(this), debug_async_event_enqueue_recurring(this);
     835             : 
     836        1419 :   Node* const status_smi = SmiConstant(static_cast<int>(status));
     837             :   Node* const deferred_promise =
     838        1419 :       LoadObjectField(promise, JSPromise::kDeferredPromiseOffset);
     839             : 
     840        1419 :   GotoIf(IsUndefined(deferred_promise), &debug_async_event_enqueue_recurring);
     841             : 
     842             :   Node* const tasks =
     843             :       status == v8::Promise::kFulfilled
     844             :           ? LoadObjectField(promise, JSPromise::kFulfillReactionsOffset)
     845        1419 :           : LoadObjectField(promise, JSPromise::kRejectReactionsOffset);
     846             : 
     847             :   Node* const deferred_on_resolve =
     848        1419 :       LoadObjectField(promise, JSPromise::kDeferredOnResolveOffset);
     849             :   Node* const deferred_on_reject =
     850        1419 :       LoadObjectField(promise, JSPromise::kDeferredOnRejectOffset);
     851             : 
     852             :   Node* const info = AllocatePromiseReactionJobInfo(
     853             :       result, tasks, deferred_promise, deferred_on_resolve, deferred_on_reject,
     854        1419 :       context);
     855             : 
     856        1419 :   CallRuntime(Runtime::kEnqueuePromiseReactionJob, context, info);
     857        1419 :   Goto(&debug_async_event_enqueue_recurring);
     858             : 
     859        1419 :   BIND(&debug_async_event_enqueue_recurring);
     860             :   {
     861        1419 :     GotoIfNot(IsDebugActive(), &do_promisereset);
     862             :     CallRuntime(Runtime::kDebugAsyncEventEnqueueRecurring, context, promise,
     863        1419 :                 status_smi);
     864        1419 :     Goto(&do_promisereset);
     865             :   }
     866             : 
     867        1419 :   BIND(&do_promisereset);
     868             :   {
     869        1419 :     StoreObjectField(promise, JSPromise::kStatusOffset, status_smi);
     870        1419 :     StoreObjectField(promise, JSPromise::kResultOffset, result);
     871             :     StoreObjectFieldRoot(promise, JSPromise::kDeferredPromiseOffset,
     872        1419 :                          Heap::kUndefinedValueRootIndex);
     873             :     StoreObjectFieldRoot(promise, JSPromise::kDeferredOnResolveOffset,
     874        1419 :                          Heap::kUndefinedValueRootIndex);
     875             :     StoreObjectFieldRoot(promise, JSPromise::kDeferredOnRejectOffset,
     876        1419 :                          Heap::kUndefinedValueRootIndex);
     877             :     StoreObjectFieldRoot(promise, JSPromise::kFulfillReactionsOffset,
     878        1419 :                          Heap::kUndefinedValueRootIndex);
     879             :     StoreObjectFieldRoot(promise, JSPromise::kRejectReactionsOffset,
     880        1419 :                          Heap::kUndefinedValueRootIndex);
     881        1419 :   }
     882        1419 : }
     883             : 
     884          43 : void PromiseBuiltinsAssembler::BranchIfAccessCheckFailed(
     885             :     Node* context, Node* native_context, Node* promise_constructor,
     886             :     Node* executor, Label* if_noaccess) {
     887          43 :   VARIABLE(var_executor, MachineRepresentation::kTagged);
     888          43 :   var_executor.Bind(executor);
     889          43 :   Label has_access(this), call_runtime(this, Label::kDeferred);
     890             : 
     891             :   // If executor is a bound function, load the bound function until we've
     892             :   // reached an actual function.
     893          43 :   Label found_function(this), loop_over_bound_function(this, &var_executor);
     894          43 :   Goto(&loop_over_bound_function);
     895          43 :   BIND(&loop_over_bound_function);
     896             :   {
     897          43 :     Node* executor_type = LoadInstanceType(var_executor.value());
     898          43 :     GotoIf(InstanceTypeEqual(executor_type, JS_FUNCTION_TYPE), &found_function);
     899             :     GotoIfNot(InstanceTypeEqual(executor_type, JS_BOUND_FUNCTION_TYPE),
     900          43 :               &call_runtime);
     901             :     var_executor.Bind(LoadObjectField(
     902          43 :         var_executor.value(), JSBoundFunction::kBoundTargetFunctionOffset));
     903          43 :     Goto(&loop_over_bound_function);
     904             :   }
     905             : 
     906             :   // Load the context from the function and compare it to the Promise
     907             :   // constructor's context. If they match, everything is fine, otherwise, bail
     908             :   // out to the runtime.
     909          43 :   BIND(&found_function);
     910             :   {
     911             :     Node* function_context =
     912          43 :         LoadObjectField(var_executor.value(), JSFunction::kContextOffset);
     913          43 :     Node* native_function_context = LoadNativeContext(function_context);
     914             :     Branch(WordEqual(native_context, native_function_context), &has_access,
     915          43 :            &call_runtime);
     916             :   }
     917             : 
     918          43 :   BIND(&call_runtime);
     919             :   {
     920             :     Branch(WordEqual(CallRuntime(Runtime::kAllowDynamicFunction, context,
     921             :                                  promise_constructor),
     922             :                      BooleanConstant(true)),
     923          43 :            &has_access, if_noaccess);
     924             :   }
     925             : 
     926          86 :   BIND(&has_access);
     927          43 : }
     928             : 
     929         129 : void PromiseBuiltinsAssembler::InternalPromiseReject(Node* context,
     930             :                                                      Node* promise, Node* value,
     931             :                                                      Node* debug_event) {
     932         129 :   Label out(this);
     933         129 :   GotoIfNot(IsDebugActive(), &out);
     934         129 :   GotoIfNot(WordEqual(TrueConstant(), debug_event), &out);
     935         129 :   CallRuntime(Runtime::kDebugPromiseReject, context, promise, value);
     936         129 :   Goto(&out);
     937             : 
     938         129 :   BIND(&out);
     939         129 :   InternalPromiseReject(context, promise, value, false);
     940         129 : }
     941             : 
     942             : // This duplicates a lot of logic from PromiseRejectEvent in
     943             : // runtime-promise.cc
     944         774 : void PromiseBuiltinsAssembler::InternalPromiseReject(Node* context,
     945             :                                                      Node* promise, Node* value,
     946             :                                                      bool debug_event) {
     947        1548 :   Label fulfill(this), report_unhandledpromise(this), run_promise_hook(this);
     948             : 
     949         774 :   if (debug_event) {
     950           0 :     GotoIfNot(IsDebugActive(), &run_promise_hook);
     951           0 :     CallRuntime(Runtime::kDebugPromiseReject, context, promise, value);
     952           0 :     Goto(&run_promise_hook);
     953             :   } else {
     954         774 :     Goto(&run_promise_hook);
     955             :   }
     956             : 
     957         774 :   BIND(&run_promise_hook);
     958             :   {
     959         774 :     GotoIfNot(IsPromiseHookEnabledOrDebugIsActive(), &report_unhandledpromise);
     960         774 :     CallRuntime(Runtime::kPromiseHookResolve, context, promise);
     961         774 :     Goto(&report_unhandledpromise);
     962             :   }
     963             : 
     964         774 :   BIND(&report_unhandledpromise);
     965             :   {
     966         774 :     GotoIf(PromiseHasHandler(promise), &fulfill);
     967         774 :     CallRuntime(Runtime::kReportPromiseReject, context, promise, value);
     968         774 :     Goto(&fulfill);
     969             :   }
     970             : 
     971         774 :   BIND(&fulfill);
     972        1548 :   PromiseFulfill(context, promise, value, v8::Promise::kRejected);
     973         774 : }
     974             : 
     975             : // ES#sec-promise-reject-functions
     976             : // Promise Reject Functions
     977         172 : TF_BUILTIN(PromiseRejectClosure, PromiseBuiltinsAssembler) {
     978             :   Node* const value = Parameter(Descriptor::kValue);
     979             :   Node* const context = Parameter(Descriptor::kContext);
     980             : 
     981             :   Label out(this);
     982             : 
     983             :   // 3. Let alreadyResolved be F.[[AlreadyResolved]].
     984             :   int has_already_visited_slot = kAlreadyVisitedSlot;
     985             : 
     986             :   Node* const has_already_visited =
     987          43 :       LoadContextElement(context, has_already_visited_slot);
     988             : 
     989             :   // 4. If alreadyResolved.[[Value]] is true, return undefined.
     990          43 :   GotoIf(SmiEqual(has_already_visited, SmiConstant(1)), &out);
     991             : 
     992             :   // 5.Set alreadyResolved.[[Value]] to true.
     993             :   StoreContextElementNoWriteBarrier(context, has_already_visited_slot,
     994          43 :                                     SmiConstant(1));
     995             : 
     996             :   // 2. Let promise be F.[[Promise]].
     997             :   Node* const promise =
     998          43 :       LoadContextElement(context, IntPtrConstant(kPromiseSlot));
     999             :   Node* const debug_event =
    1000          43 :       LoadContextElement(context, IntPtrConstant(kDebugEventSlot));
    1001             : 
    1002          43 :   InternalPromiseReject(context, promise, value, debug_event);
    1003          43 :   Return(UndefinedConstant());
    1004             : 
    1005          43 :   BIND(&out);
    1006          43 :   Return(UndefinedConstant());
    1007          43 : }
    1008             : 
    1009             : // ES6 #sec-promise-executor
    1010         172 : TF_BUILTIN(PromiseConstructor, PromiseBuiltinsAssembler) {
    1011             :   Node* const executor = Parameter(Descriptor::kExecutor);
    1012             :   Node* const new_target = Parameter(Descriptor::kNewTarget);
    1013             :   Node* const context = Parameter(Descriptor::kContext);
    1014          43 :   Isolate* isolate = this->isolate();
    1015             : 
    1016             :   Label if_targetisundefined(this, Label::kDeferred);
    1017             : 
    1018          43 :   GotoIf(IsUndefined(new_target), &if_targetisundefined);
    1019             : 
    1020          43 :   Label if_notcallable(this, Label::kDeferred);
    1021             : 
    1022          43 :   GotoIf(TaggedIsSmi(executor), &if_notcallable);
    1023             : 
    1024          43 :   Node* const executor_map = LoadMap(executor);
    1025          43 :   GotoIfNot(IsCallableMap(executor_map), &if_notcallable);
    1026             : 
    1027          43 :   Node* const native_context = LoadNativeContext(context);
    1028             :   Node* const promise_fun =
    1029          43 :       LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX);
    1030          43 :   Node* const is_debug_active = IsDebugActive();
    1031          43 :   Label if_targetisnotmodified(this),
    1032          43 :       if_targetismodified(this, Label::kDeferred), run_executor(this),
    1033          43 :       debug_push(this), if_noaccess(this, Label::kDeferred);
    1034             : 
    1035             :   BranchIfAccessCheckFailed(context, native_context, promise_fun, executor,
    1036          43 :                             &if_noaccess);
    1037             : 
    1038             :   Branch(WordEqual(promise_fun, new_target), &if_targetisnotmodified,
    1039          43 :          &if_targetismodified);
    1040             : 
    1041          86 :   VARIABLE(var_result, MachineRepresentation::kTagged);
    1042          86 :   VARIABLE(var_reject_call, MachineRepresentation::kTagged);
    1043          86 :   VARIABLE(var_reason, MachineRepresentation::kTagged);
    1044             : 
    1045          43 :   BIND(&if_targetisnotmodified);
    1046             :   {
    1047          43 :     Node* const instance = AllocateAndInitJSPromise(context);
    1048          43 :     var_result.Bind(instance);
    1049          43 :     Goto(&debug_push);
    1050             :   }
    1051             : 
    1052          43 :   BIND(&if_targetismodified);
    1053             :   {
    1054             :     ConstructorBuiltinsAssembler constructor_assembler(this->state());
    1055             :     Node* const instance = constructor_assembler.EmitFastNewObject(
    1056          43 :         context, promise_fun, new_target);
    1057          43 :     PromiseInit(instance);
    1058          43 :     var_result.Bind(instance);
    1059             : 
    1060          43 :     GotoIfNot(IsPromiseHookEnabledOrDebugIsActive(), &debug_push);
    1061             :     CallRuntime(Runtime::kPromiseHookInit, context, instance,
    1062          43 :                 UndefinedConstant());
    1063          43 :     Goto(&debug_push);
    1064             :   }
    1065             : 
    1066          43 :   BIND(&debug_push);
    1067             :   {
    1068          43 :     GotoIfNot(is_debug_active, &run_executor);
    1069          43 :     CallRuntime(Runtime::kDebugPushPromise, context, var_result.value());
    1070          43 :     Goto(&run_executor);
    1071             :   }
    1072             : 
    1073          43 :   BIND(&run_executor);
    1074             :   {
    1075          43 :     Label out(this), if_rejectpromise(this), debug_pop(this, Label::kDeferred);
    1076             : 
    1077             :     Node *resolve, *reject;
    1078          86 :     std::tie(resolve, reject) = CreatePromiseResolvingFunctions(
    1079          43 :         var_result.value(), TrueConstant(), native_context);
    1080          43 :     Callable call_callable = CodeFactory::Call(isolate);
    1081             : 
    1082             :     Node* const maybe_exception = CallJS(call_callable, context, executor,
    1083          43 :                                          UndefinedConstant(), resolve, reject);
    1084             : 
    1085          43 :     GotoIfException(maybe_exception, &if_rejectpromise, &var_reason);
    1086          43 :     Branch(is_debug_active, &debug_pop, &out);
    1087             : 
    1088          43 :     BIND(&if_rejectpromise);
    1089             :     {
    1090          43 :       Callable call_callable = CodeFactory::Call(isolate);
    1091             :       CallJS(call_callable, context, reject, UndefinedConstant(),
    1092          43 :              var_reason.value());
    1093          43 :       Branch(is_debug_active, &debug_pop, &out);
    1094             :     }
    1095             : 
    1096          43 :     BIND(&debug_pop);
    1097             :     {
    1098          43 :       CallRuntime(Runtime::kDebugPopPromise, context);
    1099          43 :       Goto(&out);
    1100             :     }
    1101          43 :     BIND(&out);
    1102          86 :     Return(var_result.value());
    1103             :   }
    1104             : 
    1105             :   // 1. If NewTarget is undefined, throw a TypeError exception.
    1106          43 :   BIND(&if_targetisundefined);
    1107             :   {
    1108          43 :     Node* const message_id = SmiConstant(MessageTemplate::kNotAPromise);
    1109          43 :     CallRuntime(Runtime::kThrowTypeError, context, message_id, new_target);
    1110          43 :     Unreachable();
    1111             :   }
    1112             : 
    1113             :   // 2. If IsCallable(executor) is false, throw a TypeError exception.
    1114          43 :   BIND(&if_notcallable);
    1115             :   {
    1116             :     Node* const message_id =
    1117          43 :         SmiConstant(MessageTemplate::kResolverNotAFunction);
    1118          43 :     CallRuntime(Runtime::kThrowTypeError, context, message_id, executor);
    1119          43 :     Unreachable();
    1120             :   }
    1121             : 
    1122             :   // Silently fail if the stack looks fishy.
    1123          43 :   BIND(&if_noaccess);
    1124             :   {
    1125             :     Node* const counter_id =
    1126          43 :         SmiConstant(v8::Isolate::kPromiseConstructorReturnedUndefined);
    1127          43 :     CallRuntime(Runtime::kIncrementUseCounter, context, counter_id);
    1128          43 :     Return(UndefinedConstant());
    1129          43 :   }
    1130          43 : }
    1131             : 
    1132         172 : TF_BUILTIN(PromiseInternalConstructor, PromiseBuiltinsAssembler) {
    1133             :   Node* const parent = Parameter(Descriptor::kParent);
    1134             :   Node* const context = Parameter(Descriptor::kContext);
    1135          43 :   Return(AllocateAndInitJSPromise(context, parent));
    1136          43 : }
    1137             : 
    1138         172 : TF_BUILTIN(IsPromise, PromiseBuiltinsAssembler) {
    1139             :   Node* const maybe_promise = Parameter(Descriptor::kObject);
    1140             :   Label if_notpromise(this, Label::kDeferred);
    1141             : 
    1142          43 :   GotoIf(TaggedIsSmi(maybe_promise), &if_notpromise);
    1143             : 
    1144             :   Node* const result =
    1145          43 :       SelectBooleanConstant(HasInstanceType(maybe_promise, JS_PROMISE_TYPE));
    1146          43 :   Return(result);
    1147             : 
    1148          43 :   BIND(&if_notpromise);
    1149          43 :   Return(FalseConstant());
    1150          43 : }
    1151             : 
    1152             : // ES#sec-promise.prototype.then
    1153             : // Promise.prototype.catch ( onFulfilled, onRejected )
    1154         172 : TF_BUILTIN(PromiseThen, PromiseBuiltinsAssembler) {
    1155             :   // 1. Let promise be the this value.
    1156             :   Node* const promise = Parameter(Descriptor::kReceiver);
    1157             :   Node* const on_resolve = Parameter(Descriptor::kOnFullfilled);
    1158             :   Node* const on_reject = Parameter(Descriptor::kOnRejected);
    1159             :   Node* const context = Parameter(Descriptor::kContext);
    1160             : 
    1161             :   Node* const result =
    1162          43 :       InternalPromiseThen(context, promise, on_resolve, on_reject);
    1163          43 :   Return(result);
    1164          43 : }
    1165             : 
    1166             : // ES#sec-promise-resolve-functions
    1167             : // Promise Resolve Functions
    1168         172 : TF_BUILTIN(PromiseResolveClosure, PromiseBuiltinsAssembler) {
    1169             :   Node* const value = Parameter(Descriptor::kValue);
    1170             :   Node* const context = Parameter(Descriptor::kContext);
    1171             : 
    1172             :   Label out(this);
    1173             : 
    1174             :   // 3. Let alreadyResolved be F.[[AlreadyResolved]].
    1175             :   int has_already_visited_slot = kAlreadyVisitedSlot;
    1176             : 
    1177             :   Node* const has_already_visited =
    1178          43 :       LoadContextElement(context, has_already_visited_slot);
    1179             : 
    1180             :   // 4. If alreadyResolved.[[Value]] is true, return undefined.
    1181          43 :   GotoIf(SmiEqual(has_already_visited, SmiConstant(1)), &out);
    1182             : 
    1183             :   // 5.Set alreadyResolved.[[Value]] to true.
    1184             :   StoreContextElementNoWriteBarrier(context, has_already_visited_slot,
    1185          43 :                                     SmiConstant(1));
    1186             : 
    1187             :   // 2. Let promise be F.[[Promise]].
    1188             :   Node* const promise =
    1189          43 :       LoadContextElement(context, IntPtrConstant(kPromiseSlot));
    1190             : 
    1191          43 :   InternalResolvePromise(context, promise, value);
    1192          43 :   Return(UndefinedConstant());
    1193             : 
    1194          43 :   BIND(&out);
    1195          43 :   Return(UndefinedConstant());
    1196          43 : }
    1197             : 
    1198             : // ES #sec-fulfillpromise
    1199         172 : TF_BUILTIN(ResolvePromise, PromiseBuiltinsAssembler) {
    1200             :   Node* const promise = Parameter(Descriptor::kPromise);
    1201             :   Node* const result = Parameter(Descriptor::kValue);
    1202             :   Node* const context = Parameter(Descriptor::kContext);
    1203             : 
    1204          43 :   InternalResolvePromise(context, promise, result);
    1205          43 :   Return(UndefinedConstant());
    1206          43 : }
    1207             : 
    1208         172 : TF_BUILTIN(PromiseHandleReject, PromiseBuiltinsAssembler) {
    1209             :   Node* const promise = Parameter(Descriptor::kPromise);
    1210             :   Node* const on_reject = Parameter(Descriptor::kOnReject);
    1211             :   Node* const exception = Parameter(Descriptor::kException);
    1212             :   Node* const context = Parameter(Descriptor::kContext);
    1213             : 
    1214          43 :   Callable call_callable = CodeFactory::Call(isolate());
    1215          86 :   VARIABLE(var_unused, MachineRepresentation::kTagged);
    1216             : 
    1217          43 :   Label if_internalhandler(this), if_customhandler(this, Label::kDeferred);
    1218          43 :   Branch(IsUndefined(on_reject), &if_internalhandler, &if_customhandler);
    1219             : 
    1220          43 :   BIND(&if_internalhandler);
    1221             :   {
    1222          43 :     InternalPromiseReject(context, promise, exception, false);
    1223          43 :     Return(UndefinedConstant());
    1224             :   }
    1225             : 
    1226          43 :   BIND(&if_customhandler);
    1227             :   {
    1228          43 :     CallJS(call_callable, context, on_reject, UndefinedConstant(), exception);
    1229          43 :     Return(UndefinedConstant());
    1230             :   }
    1231          43 : }
    1232             : 
    1233         172 : TF_BUILTIN(PromiseHandle, PromiseBuiltinsAssembler) {
    1234             :   Node* const value = Parameter(Descriptor::kValue);
    1235             :   Node* const handler = Parameter(Descriptor::kHandler);
    1236             :   Node* const deferred_promise = Parameter(Descriptor::kDeferredPromise);
    1237             :   Node* const deferred_on_resolve = Parameter(Descriptor::kDeferredOnResolve);
    1238             :   Node* const deferred_on_reject = Parameter(Descriptor::kDeferredOnReject);
    1239             :   Node* const context = Parameter(Descriptor::kContext);
    1240          43 :   Isolate* isolate = this->isolate();
    1241             : 
    1242          43 :   VARIABLE(var_reason, MachineRepresentation::kTagged);
    1243             : 
    1244          43 :   Node* const is_debug_active = IsDebugActive();
    1245          43 :   Label run_handler(this), if_rejectpromise(this), promisehook_before(this),
    1246          43 :       promisehook_after(this), debug_pop(this);
    1247             : 
    1248          43 :   GotoIfNot(is_debug_active, &promisehook_before);
    1249          43 :   CallRuntime(Runtime::kDebugPushPromise, context, deferred_promise);
    1250          43 :   Goto(&promisehook_before);
    1251             : 
    1252          43 :   BIND(&promisehook_before);
    1253             :   {
    1254          43 :     GotoIfNot(IsPromiseHookEnabledOrDebugIsActive(), &run_handler);
    1255          43 :     CallRuntime(Runtime::kPromiseHookBefore, context, deferred_promise);
    1256          43 :     Goto(&run_handler);
    1257             :   }
    1258             : 
    1259          43 :   BIND(&run_handler);
    1260             :   {
    1261          43 :     Label if_defaulthandler(this), if_callablehandler(this),
    1262          43 :         if_internalhandler(this), if_customhandler(this, Label::kDeferred);
    1263          86 :     VARIABLE(var_result, MachineRepresentation::kTagged);
    1264             : 
    1265          43 :     Branch(IsSymbol(handler), &if_defaulthandler, &if_callablehandler);
    1266             : 
    1267          43 :     BIND(&if_defaulthandler);
    1268             :     {
    1269          43 :       Label if_resolve(this), if_reject(this);
    1270             :       Node* const default_resolve_handler_symbol = HeapConstant(
    1271          43 :           isolate->factory()->promise_default_resolve_handler_symbol());
    1272             :       Branch(WordEqual(default_resolve_handler_symbol, handler), &if_resolve,
    1273          43 :              &if_reject);
    1274             : 
    1275          43 :       BIND(&if_resolve);
    1276             :       {
    1277          43 :         var_result.Bind(value);
    1278             :         Branch(IsUndefined(deferred_on_resolve), &if_internalhandler,
    1279          43 :                &if_customhandler);
    1280             :       }
    1281             : 
    1282          43 :       BIND(&if_reject);
    1283             :       {
    1284          43 :         var_reason.Bind(value);
    1285          43 :         Goto(&if_rejectpromise);
    1286          43 :       }
    1287             :     }
    1288             : 
    1289          43 :     BIND(&if_callablehandler);
    1290             :     {
    1291          43 :       Callable call_callable = CodeFactory::Call(isolate);
    1292             :       Node* const result =
    1293          43 :           CallJS(call_callable, context, handler, UndefinedConstant(), value);
    1294          43 :       var_result.Bind(result);
    1295          43 :       GotoIfException(result, &if_rejectpromise, &var_reason);
    1296             :       Branch(IsUndefined(deferred_on_resolve), &if_internalhandler,
    1297          43 :              &if_customhandler);
    1298             :     }
    1299             : 
    1300          43 :     BIND(&if_internalhandler);
    1301          43 :     InternalResolvePromise(context, deferred_promise, var_result.value());
    1302          43 :     Goto(&promisehook_after);
    1303             : 
    1304          43 :     BIND(&if_customhandler);
    1305             :     {
    1306          43 :       Callable call_callable = CodeFactory::Call(isolate);
    1307             :       Node* const maybe_exception =
    1308             :           CallJS(call_callable, context, deferred_on_resolve,
    1309          43 :                  UndefinedConstant(), var_result.value());
    1310          43 :       GotoIfException(maybe_exception, &if_rejectpromise, &var_reason);
    1311          43 :       Goto(&promisehook_after);
    1312          43 :     }
    1313             :   }
    1314             : 
    1315          43 :   BIND(&if_rejectpromise);
    1316             :   {
    1317          43 :     Callable promise_handle_reject = CodeFactory::PromiseHandleReject(isolate);
    1318             :     CallStub(promise_handle_reject, context, deferred_promise,
    1319          43 :              deferred_on_reject, var_reason.value());
    1320          43 :     Goto(&promisehook_after);
    1321             :   }
    1322             : 
    1323          43 :   BIND(&promisehook_after);
    1324             :   {
    1325          43 :     GotoIfNot(IsPromiseHookEnabledOrDebugIsActive(), &debug_pop);
    1326          43 :     CallRuntime(Runtime::kPromiseHookAfter, context, deferred_promise);
    1327          43 :     Goto(&debug_pop);
    1328             :   }
    1329             : 
    1330          43 :   BIND(&debug_pop);
    1331             :   {
    1332             :     Label out(this);
    1333             : 
    1334          43 :     GotoIfNot(is_debug_active, &out);
    1335          43 :     CallRuntime(Runtime::kDebugPopPromise, context);
    1336          43 :     Goto(&out);
    1337             : 
    1338          43 :     BIND(&out);
    1339          43 :     Return(UndefinedConstant());
    1340          43 :   }
    1341          43 : }
    1342             : 
    1343             : // ES#sec-promise.prototype.catch
    1344             : // Promise.prototype.catch ( onRejected )
    1345         215 : TF_BUILTIN(PromiseCatch, PromiseBuiltinsAssembler) {
    1346             :   // 1. Let promise be the this value.
    1347             :   Node* const promise = Parameter(Descriptor::kReceiver);
    1348          43 :   Node* const on_resolve = UndefinedConstant();
    1349             :   Node* const on_reject = Parameter(Descriptor::kOnRejected);
    1350             :   Node* const context = Parameter(Descriptor::kContext);
    1351             : 
    1352          43 :   Label if_internalthen(this), if_customthen(this, Label::kDeferred);
    1353          43 :   GotoIf(TaggedIsSmi(promise), &if_customthen);
    1354          43 :   BranchIfFastPath(context, promise, &if_internalthen, &if_customthen);
    1355             : 
    1356          43 :   BIND(&if_internalthen);
    1357             :   {
    1358             :     Node* const result =
    1359          43 :         InternalPromiseThen(context, promise, on_resolve, on_reject);
    1360          43 :     Return(result);
    1361             :   }
    1362             : 
    1363          43 :   BIND(&if_customthen);
    1364             :   {
    1365             :     Node* const then =
    1366          86 :         GetProperty(context, promise, isolate()->factory()->then_string());
    1367          43 :     Callable call_callable = CodeFactory::Call(isolate());
    1368             :     Node* const result =
    1369          43 :         CallJS(call_callable, context, then, promise, on_resolve, on_reject);
    1370          43 :     Return(result);
    1371          43 :   }
    1372          43 : }
    1373             : 
    1374         172 : TF_BUILTIN(PromiseResolve, PromiseBuiltinsAssembler) {
    1375             :   //  1. Let C be the this value.
    1376             :   Node* receiver = Parameter(Descriptor::kReceiver);
    1377             :   Node* value = Parameter(Descriptor::kValue);
    1378             :   Node* context = Parameter(Descriptor::kContext);
    1379          43 :   Isolate* isolate = this->isolate();
    1380             : 
    1381             :   // 2. If Type(C) is not Object, throw a TypeError exception.
    1382             :   ThrowIfNotJSReceiver(context, receiver, MessageTemplate::kCalledOnNonObject,
    1383          43 :                        "PromiseResolve");
    1384             : 
    1385          43 :   Node* const native_context = LoadNativeContext(context);
    1386             :   Node* const promise_fun =
    1387          43 :       LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX);
    1388             : 
    1389          43 :   Label if_valueisnativepromise(this), if_valueisnotnativepromise(this),
    1390          43 :       if_valueisnotpromise(this);
    1391             : 
    1392             :   // 3.If IsPromise(x) is true, then
    1393          43 :   GotoIf(TaggedIsSmi(value), &if_valueisnotpromise);
    1394             : 
    1395             :   // This shortcircuits the constructor lookups.
    1396          43 :   GotoIfNot(HasInstanceType(value, JS_PROMISE_TYPE), &if_valueisnotpromise);
    1397             : 
    1398             :   // This adds a fast path as non-subclassed native promises don't have
    1399             :   // an observable constructor lookup.
    1400             :   BranchIfFastPath(native_context, promise_fun, value, &if_valueisnativepromise,
    1401          43 :                    &if_valueisnotnativepromise);
    1402             : 
    1403          43 :   BIND(&if_valueisnativepromise);
    1404             :   {
    1405          43 :     GotoIfNot(WordEqual(promise_fun, receiver), &if_valueisnotnativepromise);
    1406          43 :     Return(value);
    1407             :   }
    1408             : 
    1409             :   // At this point, value or/and receiver are not native promises, but
    1410             :   // they could be of the same subclass.
    1411          43 :   BIND(&if_valueisnotnativepromise);
    1412             :   {
    1413             :     // 3.a Let xConstructor be ? Get(x, "constructor").
    1414             :     // The constructor lookup is observable.
    1415             :     Node* const constructor =
    1416          43 :         GetProperty(context, value, isolate->factory()->constructor_string());
    1417             : 
    1418             :     // 3.b If SameValue(xConstructor, C) is true, return x.
    1419          43 :     GotoIfNot(SameValue(constructor, receiver), &if_valueisnotpromise);
    1420             : 
    1421          43 :     Return(value);
    1422             :   }
    1423             : 
    1424          43 :   BIND(&if_valueisnotpromise);
    1425             :   {
    1426          43 :     Label if_nativepromise(this), if_notnativepromise(this);
    1427             :     Branch(WordEqual(promise_fun, receiver), &if_nativepromise,
    1428          43 :            &if_notnativepromise);
    1429             : 
    1430             :     // This adds a fast path for native promises that don't need to
    1431             :     // create NewPromiseCapability.
    1432          43 :     BIND(&if_nativepromise);
    1433             :     {
    1434          43 :       Node* const result = AllocateAndInitJSPromise(context);
    1435          43 :       InternalResolvePromise(context, result, value);
    1436          43 :       Return(result);
    1437             :     }
    1438             : 
    1439          43 :     BIND(&if_notnativepromise);
    1440             :     {
    1441             :       // 4. Let promiseCapability be ? NewPromiseCapability(C).
    1442          43 :       Node* const capability = NewPromiseCapability(context, receiver);
    1443             : 
    1444             :       // 5. Perform ? Call(promiseCapability.[[Resolve]], undefined, « x »).
    1445          43 :       Callable call_callable = CodeFactory::Call(isolate);
    1446             :       Node* const resolve =
    1447          43 :           LoadObjectField(capability, JSPromiseCapability::kResolveOffset);
    1448          43 :       CallJS(call_callable, context, resolve, UndefinedConstant(), value);
    1449             : 
    1450             :       // 6. Return promiseCapability.[[Promise]].
    1451             :       Node* const result =
    1452          43 :           LoadObjectField(capability, JSPromiseCapability::kPromiseOffset);
    1453          43 :       Return(result);
    1454          43 :     }
    1455          43 :   }
    1456          43 : }
    1457             : 
    1458             : // ES6 #sec-getcapabilitiesexecutor-functions
    1459         172 : TF_BUILTIN(PromiseGetCapabilitiesExecutor, PromiseBuiltinsAssembler) {
    1460             :   Node* const resolve = Parameter(Descriptor::kResolve);
    1461             :   Node* const reject = Parameter(Descriptor::kReject);
    1462             :   Node* const context = Parameter(Descriptor::kContext);
    1463             : 
    1464          43 :   Node* const capability = LoadContextElement(context, kCapabilitySlot);
    1465             : 
    1466             :   Label if_alreadyinvoked(this, Label::kDeferred);
    1467             :   GotoIf(WordNotEqual(
    1468             :              LoadObjectField(capability, JSPromiseCapability::kResolveOffset),
    1469             :              UndefinedConstant()),
    1470          43 :          &if_alreadyinvoked);
    1471             :   GotoIf(WordNotEqual(
    1472             :              LoadObjectField(capability, JSPromiseCapability::kRejectOffset),
    1473             :              UndefinedConstant()),
    1474          43 :          &if_alreadyinvoked);
    1475             : 
    1476          43 :   StoreObjectField(capability, JSPromiseCapability::kResolveOffset, resolve);
    1477          43 :   StoreObjectField(capability, JSPromiseCapability::kRejectOffset, reject);
    1478             : 
    1479          43 :   Return(UndefinedConstant());
    1480             : 
    1481          43 :   BIND(&if_alreadyinvoked);
    1482          43 :   Node* message = SmiConstant(MessageTemplate::kPromiseExecutorAlreadyInvoked);
    1483          43 :   CallRuntime(Runtime::kThrowTypeError, context, message);
    1484          43 :   Unreachable();
    1485          43 : }
    1486             : 
    1487             : // ES6 #sec-newpromisecapability
    1488         172 : TF_BUILTIN(NewPromiseCapability, PromiseBuiltinsAssembler) {
    1489             :   Node* constructor = Parameter(Descriptor::kConstructor);
    1490             :   Node* debug_event = Parameter(Descriptor::kDebugEvent);
    1491             :   Node* context = Parameter(Descriptor::kContext);
    1492             : 
    1493             :   CSA_ASSERT_JS_ARGC_EQ(this, 2);
    1494             : 
    1495          43 :   Return(NewPromiseCapability(context, constructor, debug_event));
    1496          43 : }
    1497             : 
    1498         172 : TF_BUILTIN(PromiseReject, PromiseBuiltinsAssembler) {
    1499             :   // 1. Let C be the this value.
    1500             :   Node* const receiver = Parameter(Descriptor::kReceiver);
    1501             :   Node* const reason = Parameter(Descriptor::kReason);
    1502             :   Node* const context = Parameter(Descriptor::kContext);
    1503             : 
    1504             :   // 2. If Type(C) is not Object, throw a TypeError exception.
    1505             :   ThrowIfNotJSReceiver(context, receiver, MessageTemplate::kCalledOnNonObject,
    1506          43 :                        "PromiseReject");
    1507             : 
    1508          43 :   Label if_nativepromise(this), if_custompromise(this, Label::kDeferred);
    1509          43 :   Node* const native_context = LoadNativeContext(context);
    1510             :   Node* const promise_fun =
    1511          43 :       LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX);
    1512             :   Branch(WordEqual(promise_fun, receiver), &if_nativepromise,
    1513          43 :          &if_custompromise);
    1514             : 
    1515          43 :   BIND(&if_nativepromise);
    1516             :   {
    1517             :     Node* const promise = AllocateAndSetJSPromise(
    1518          43 :         context, SmiConstant(v8::Promise::kRejected), reason);
    1519             :     CallRuntime(Runtime::kPromiseRejectEventFromStack, context, promise,
    1520          43 :                 reason);
    1521          43 :     Return(promise);
    1522             :   }
    1523             : 
    1524          43 :   BIND(&if_custompromise);
    1525             :   {
    1526             :     // 3. Let promiseCapability be ? NewPromiseCapability(C).
    1527          43 :     Node* const capability = NewPromiseCapability(context, receiver);
    1528             : 
    1529             :     // 4. Perform ? Call(promiseCapability.[[Reject]], undefined, « r »).
    1530             :     Node* const reject =
    1531          43 :         LoadObjectField(capability, JSPromiseCapability::kRejectOffset);
    1532          43 :     Callable call_callable = CodeFactory::Call(isolate());
    1533          43 :     CallJS(call_callable, context, reject, UndefinedConstant(), reason);
    1534             : 
    1535             :     // 5. Return promiseCapability.[[Promise]].
    1536             :     Node* const promise =
    1537          43 :         LoadObjectField(capability, JSPromiseCapability::kPromiseOffset);
    1538          43 :     Return(promise);
    1539          43 :   }
    1540          43 : }
    1541             : 
    1542         172 : TF_BUILTIN(InternalPromiseReject, PromiseBuiltinsAssembler) {
    1543             :   Node* const promise = Parameter(Descriptor::kPromise);
    1544             :   Node* const reason = Parameter(Descriptor::kReason);
    1545             :   Node* const debug_event = Parameter(Descriptor::kDebugEvent);
    1546             :   Node* const context = Parameter(Descriptor::kContext);
    1547             : 
    1548          43 :   InternalPromiseReject(context, promise, reason, debug_event);
    1549          43 :   Return(UndefinedConstant());
    1550          43 : }
    1551             : 
    1552          43 : Node* PromiseBuiltinsAssembler::CreatePromiseFinallyContext(
    1553             :     Node* on_finally, Node* native_context) {
    1554             :   Node* const context =
    1555          43 :       CreatePromiseContext(native_context, kOnFinallyContextLength);
    1556          43 :   StoreContextElementNoWriteBarrier(context, kOnFinallySlot, on_finally);
    1557          43 :   return context;
    1558             : }
    1559             : 
    1560          43 : std::pair<Node*, Node*> PromiseBuiltinsAssembler::CreatePromiseFinallyFunctions(
    1561             :     Node* on_finally, Node* native_context) {
    1562             :   Node* const promise_context =
    1563          43 :       CreatePromiseFinallyContext(on_finally, native_context);
    1564             :   Node* const map = LoadContextElement(
    1565          43 :       native_context, Context::STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX);
    1566             :   Node* const then_finally_info = LoadContextElement(
    1567          43 :       native_context, Context::PROMISE_THEN_FINALLY_SHARED_FUN);
    1568             :   Node* const then_finally = AllocateFunctionWithMapAndContext(
    1569          43 :       map, then_finally_info, promise_context);
    1570             :   Node* const catch_finally_info = LoadContextElement(
    1571          43 :       native_context, Context::PROMISE_CATCH_FINALLY_SHARED_FUN);
    1572             :   Node* const catch_finally = AllocateFunctionWithMapAndContext(
    1573          43 :       map, catch_finally_info, promise_context);
    1574          43 :   return std::make_pair(then_finally, catch_finally);
    1575             : }
    1576             : 
    1577         172 : TF_BUILTIN(PromiseValueThunkFinally, PromiseBuiltinsAssembler) {
    1578             :   Node* const context = Parameter(Descriptor::kContext);
    1579             : 
    1580          43 :   Node* const value = LoadContextElement(context, kOnFinallySlot);
    1581          43 :   Return(value);
    1582          43 : }
    1583             : 
    1584          43 : Node* PromiseBuiltinsAssembler::CreateValueThunkFunctionContext(
    1585             :     Node* value, Node* native_context) {
    1586             :   Node* const context =
    1587          43 :       CreatePromiseContext(native_context, kOnFinallyContextLength);
    1588          43 :   StoreContextElementNoWriteBarrier(context, kOnFinallySlot, value);
    1589          43 :   return context;
    1590             : }
    1591             : 
    1592          43 : Node* PromiseBuiltinsAssembler::CreateValueThunkFunction(Node* value,
    1593             :                                                          Node* native_context) {
    1594             :   Node* const value_thunk_context =
    1595          43 :       CreateValueThunkFunctionContext(value, native_context);
    1596             :   Node* const map = LoadContextElement(
    1597          43 :       native_context, Context::STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX);
    1598             :   Node* const value_thunk_info = LoadContextElement(
    1599          43 :       native_context, Context::PROMISE_VALUE_THUNK_FINALLY_SHARED_FUN);
    1600             :   Node* const value_thunk = AllocateFunctionWithMapAndContext(
    1601          43 :       map, value_thunk_info, value_thunk_context);
    1602          43 :   return value_thunk;
    1603             : }
    1604             : 
    1605         172 : TF_BUILTIN(PromiseThenFinally, PromiseBuiltinsAssembler) {
    1606             :   CSA_ASSERT_JS_ARGC_EQ(this, 1);
    1607             : 
    1608             :   Node* const value = Parameter(Descriptor::kValue);
    1609             :   Node* const context = Parameter(Descriptor::kContext);
    1610             : 
    1611          43 :   Node* const on_finally = LoadContextElement(context, kOnFinallySlot);
    1612             : 
    1613             :   // 2.a Let result be ?  Call(onFinally, undefined).
    1614          43 :   Callable call_callable = CodeFactory::Call(isolate());
    1615             :   Node* result =
    1616          43 :       CallJS(call_callable, context, on_finally, UndefinedConstant());
    1617             : 
    1618             :   // 2.b Let promise be !  PromiseResolve( %Promise%, result).
    1619          43 :   Node* const promise = AllocateAndInitJSPromise(context);
    1620          43 :   InternalResolvePromise(context, promise, result);
    1621             : 
    1622             :   // 2.c Let valueThunk be equivalent to a function that returns value.
    1623          43 :   Node* native_context = LoadNativeContext(context);
    1624          43 :   Node* const value_thunk = CreateValueThunkFunction(value, native_context);
    1625             : 
    1626             :   // 2.d Let promiseCapability be !  NewPromiseCapability( %Promise%).
    1627          43 :   Node* const promise_capability = AllocateAndInitJSPromise(context, promise);
    1628             : 
    1629             :   // 2.e Return PerformPromiseThen(promise, valueThunk, undefined,
    1630             :   // promiseCapability).
    1631             :   InternalPerformPromiseThen(context, promise, value_thunk, UndefinedConstant(),
    1632             :                              promise_capability, UndefinedConstant(),
    1633          43 :                              UndefinedConstant());
    1634          43 :   Return(promise_capability);
    1635          43 : }
    1636             : 
    1637         172 : TF_BUILTIN(PromiseThrowerFinally, PromiseBuiltinsAssembler) {
    1638             :   Node* const context = Parameter(Descriptor::kContext);
    1639             : 
    1640          43 :   Node* const reason = LoadContextElement(context, kOnFinallySlot);
    1641          43 :   CallRuntime(Runtime::kThrow, context, reason);
    1642          43 :   Unreachable();
    1643          43 : }
    1644             : 
    1645          43 : Node* PromiseBuiltinsAssembler::CreateThrowerFunctionContext(
    1646             :     Node* reason, Node* native_context) {
    1647             :   Node* const context =
    1648          43 :       CreatePromiseContext(native_context, kOnFinallyContextLength);
    1649          43 :   StoreContextElementNoWriteBarrier(context, kOnFinallySlot, reason);
    1650          43 :   return context;
    1651             : }
    1652             : 
    1653          43 : Node* PromiseBuiltinsAssembler::CreateThrowerFunction(Node* reason,
    1654             :                                                       Node* native_context) {
    1655             :   Node* const thrower_context =
    1656          43 :       CreateThrowerFunctionContext(reason, native_context);
    1657             :   Node* const map = LoadContextElement(
    1658          43 :       native_context, Context::STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX);
    1659             :   Node* const thrower_info = LoadContextElement(
    1660          43 :       native_context, Context::PROMISE_THROWER_FINALLY_SHARED_FUN);
    1661             :   Node* const thrower =
    1662          43 :       AllocateFunctionWithMapAndContext(map, thrower_info, thrower_context);
    1663          43 :   return thrower;
    1664             : }
    1665             : 
    1666         172 : TF_BUILTIN(PromiseCatchFinally, PromiseBuiltinsAssembler) {
    1667             :   CSA_ASSERT_JS_ARGC_EQ(this, 1);
    1668             : 
    1669             :   Node* const reason = Parameter(Descriptor::kReason);
    1670             :   Node* const context = Parameter(Descriptor::kContext);
    1671             : 
    1672          43 :   Node* const on_finally = LoadContextElement(context, kOnFinallySlot);
    1673             : 
    1674             :   // 2.a Let result be ?  Call(onFinally, undefined).
    1675          43 :   Callable call_callable = CodeFactory::Call(isolate());
    1676             :   Node* result =
    1677          43 :       CallJS(call_callable, context, on_finally, UndefinedConstant());
    1678             : 
    1679             :   // 2.b Let promise be !  PromiseResolve( %Promise%, result).
    1680          43 :   Node* const promise = AllocateAndInitJSPromise(context);
    1681          43 :   InternalResolvePromise(context, promise, result);
    1682             : 
    1683             :   // 2.c Let thrower be equivalent to a function that throws reason.
    1684          43 :   Node* native_context = LoadNativeContext(context);
    1685          43 :   Node* const thrower = CreateThrowerFunction(reason, native_context);
    1686             : 
    1687             :   // 2.d Let promiseCapability be !  NewPromiseCapability( %Promise%).
    1688          43 :   Node* const promise_capability = AllocateAndInitJSPromise(context, promise);
    1689             : 
    1690             :   // 2.e Return PerformPromiseThen(promise, thrower, undefined,
    1691             :   // promiseCapability).
    1692             :   InternalPerformPromiseThen(context, promise, thrower, UndefinedConstant(),
    1693             :                              promise_capability, UndefinedConstant(),
    1694          43 :                              UndefinedConstant());
    1695          43 :   Return(promise_capability);
    1696          43 : }
    1697             : 
    1698         172 : TF_BUILTIN(PromiseFinally, PromiseBuiltinsAssembler) {
    1699             :   CSA_ASSERT_JS_ARGC_EQ(this, 1);
    1700             : 
    1701             :   // 1.  Let promise be the this value.
    1702             :   Node* const promise = Parameter(Descriptor::kReceiver);
    1703             :   Node* const on_finally = Parameter(Descriptor::kOnFinally);
    1704             :   Node* const context = Parameter(Descriptor::kContext);
    1705             : 
    1706             :   // 2. If IsPromise(promise) is false, throw a TypeError exception.
    1707             :   ThrowIfNotInstanceType(context, promise, JS_PROMISE_TYPE,
    1708          43 :                          "Promise.prototype.finally");
    1709             : 
    1710          43 :   VARIABLE(var_then_finally, MachineRepresentation::kTagged);
    1711          86 :   VARIABLE(var_catch_finally, MachineRepresentation::kTagged);
    1712             : 
    1713          43 :   Label if_notcallable(this, Label::kDeferred), perform_finally(this);
    1714             : 
    1715             :   // 3. Let thenFinally be !  CreateThenFinally(onFinally).
    1716             :   // 4. Let catchFinally be !  CreateCatchFinally(onFinally).
    1717          43 :   GotoIf(TaggedIsSmi(on_finally), &if_notcallable);
    1718          43 :   Node* const on_finally_map = LoadMap(on_finally);
    1719          43 :   GotoIfNot(IsCallableMap(on_finally_map), &if_notcallable);
    1720             : 
    1721          43 :   Node* const native_context = LoadNativeContext(context);
    1722          43 :   Node* then_finally = nullptr;
    1723          43 :   Node* catch_finally = nullptr;
    1724          86 :   std::tie(then_finally, catch_finally) =
    1725          43 :       CreatePromiseFinallyFunctions(on_finally, native_context);
    1726          43 :   var_then_finally.Bind(then_finally);
    1727          43 :   var_catch_finally.Bind(catch_finally);
    1728          43 :   Goto(&perform_finally);
    1729             : 
    1730          43 :   BIND(&if_notcallable);
    1731             :   {
    1732          43 :     var_then_finally.Bind(on_finally);
    1733          43 :     var_catch_finally.Bind(on_finally);
    1734          43 :     Goto(&perform_finally);
    1735             :   }
    1736             : 
    1737             :   // 5. Return PerformPromiseThen(promise, valueThunk, undefined,
    1738             :   // promiseCapability).
    1739          43 :   BIND(&perform_finally);
    1740          43 :   Label if_nativepromise(this), if_custompromise(this, Label::kDeferred);
    1741          43 :   BranchIfFastPath(context, promise, &if_nativepromise, &if_custompromise);
    1742             : 
    1743          43 :   BIND(&if_nativepromise);
    1744             :   {
    1745          43 :     Node* deferred_promise = AllocateAndInitJSPromise(context, promise);
    1746             :     InternalPerformPromiseThen(context, promise, var_then_finally.value(),
    1747             :                                var_catch_finally.value(), deferred_promise,
    1748          43 :                                UndefinedConstant(), UndefinedConstant());
    1749          43 :     Return(deferred_promise);
    1750             :   }
    1751             : 
    1752          43 :   BIND(&if_custompromise);
    1753             :   {
    1754             :     Node* const then =
    1755          86 :         GetProperty(context, promise, isolate()->factory()->then_string());
    1756          43 :     Callable call_callable = CodeFactory::Call(isolate());
    1757             :     // 5. Return ?  Invoke(promise, "then", « thenFinally, catchFinally »).
    1758             :     Node* const result =
    1759             :         CallJS(call_callable, context, then, promise, var_then_finally.value(),
    1760          43 :                var_catch_finally.value());
    1761          43 :     Return(result);
    1762          43 :   }
    1763          43 : }
    1764             : 
    1765         172 : TF_BUILTIN(ResolveNativePromise, PromiseBuiltinsAssembler) {
    1766             :   Node* const promise = Parameter(Descriptor::kPromise);
    1767             :   Node* const value = Parameter(Descriptor::kValue);
    1768             :   Node* const context = Parameter(Descriptor::kContext);
    1769             : 
    1770             :   CSA_ASSERT(this, HasInstanceType(promise, JS_PROMISE_TYPE));
    1771          43 :   InternalResolvePromise(context, promise, value);
    1772          43 :   Return(UndefinedConstant());
    1773          43 : }
    1774             : 
    1775         172 : TF_BUILTIN(RejectNativePromise, PromiseBuiltinsAssembler) {
    1776             :   Node* const promise = Parameter(Descriptor::kPromise);
    1777             :   Node* const value = Parameter(Descriptor::kValue);
    1778             :   Node* const debug_event = Parameter(Descriptor::kDebugEvent);
    1779             :   Node* const context = Parameter(Descriptor::kContext);
    1780             : 
    1781             :   CSA_ASSERT(this, HasInstanceType(promise, JS_PROMISE_TYPE));
    1782             :   CSA_ASSERT(this, IsBoolean(debug_event));
    1783          43 :   InternalPromiseReject(context, promise, value, debug_event);
    1784          43 :   Return(UndefinedConstant());
    1785          43 : }
    1786             : 
    1787         172 : TF_BUILTIN(PerformNativePromiseThen, PromiseBuiltinsAssembler) {
    1788             :   Node* const promise = Parameter(Descriptor::kPromise);
    1789             :   Node* const resolve_reaction = Parameter(Descriptor::kResolveReaction);
    1790             :   Node* const reject_reaction = Parameter(Descriptor::kRejectReaction);
    1791             :   Node* const result_promise = Parameter(Descriptor::kResultPromise);
    1792             :   Node* const context = Parameter(Descriptor::kContext);
    1793             : 
    1794             :   CSA_ASSERT(this, HasInstanceType(result_promise, JS_PROMISE_TYPE));
    1795             : 
    1796             :   InternalPerformPromiseThen(context, promise, resolve_reaction,
    1797             :                              reject_reaction, result_promise,
    1798          43 :                              UndefinedConstant(), UndefinedConstant());
    1799          43 :   Return(result_promise);
    1800          43 : }
    1801             : 
    1802             : }  // namespace internal
    1803             : }  // namespace v8

Generated by: LCOV version 1.10