LCOV - code coverage report
Current view: top level - src/builtins - builtins-async-generator-gen.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 165 167 98.8 %
Date: 2017-04-26 Functions: 32 34 94.1 %

          Line data    Source code
       1             : // Copyright 2017 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-async-gen.h"
       6             : #include "src/builtins/builtins-utils-gen.h"
       7             : #include "src/builtins/builtins.h"
       8             : #include "src/code-factory.h"
       9             : #include "src/code-stub-assembler.h"
      10             : #include "src/frames-inl.h"
      11             : 
      12             : namespace v8 {
      13             : namespace internal {
      14             : 
      15             : using compiler::Node;
      16             : 
      17             : namespace {
      18             : 
      19             : // Describe fields of Context associated with AsyncGeneratorAwait resume
      20             : // closures.
      21             : class AwaitContext {
      22             :  public:
      23             :   enum Fields { kGeneratorSlot = Context::MIN_CONTEXT_SLOTS, kLength };
      24             : };
      25             : 
      26             : class AsyncGeneratorBuiltinsAssembler : public AsyncBuiltinsAssembler {
      27             :  public:
      28             :   explicit AsyncGeneratorBuiltinsAssembler(CodeAssemblerState* state)
      29             :       : AsyncBuiltinsAssembler(state) {}
      30             : 
      31             :   inline Node* LoadGeneratorState(Node* const generator) {
      32         258 :     return LoadObjectField(generator, JSGeneratorObject::kContinuationOffset);
      33             :   }
      34             : 
      35          86 :   inline Node* IsGeneratorStateClosed(Node* const state) {
      36          86 :     return SmiEqual(state, SmiConstant(JSGeneratorObject::kGeneratorClosed));
      37             :   }
      38             :   inline Node* IsGeneratorClosed(Node* const generator) {
      39             :     return IsGeneratorStateClosed(LoadGeneratorState(generator));
      40             :   }
      41             : 
      42             :   inline Node* IsGeneratorStateSuspended(Node* const state) {
      43             :     return SmiGreaterThanOrEqual(state, SmiConstant(0));
      44             :   }
      45             : 
      46             :   inline Node* IsGeneratorSuspended(Node* const generator) {
      47             :     return IsGeneratorStateSuspended(LoadGeneratorState(generator));
      48             :   }
      49             : 
      50          43 :   inline Node* IsGeneratorStateSuspendedAtStart(Node* const state) {
      51          43 :     return SmiEqual(state, SmiConstant(0));
      52             :   }
      53             : 
      54             :   inline Node* IsGeneratorStateNotExecuting(Node* const state) {
      55             :     return SmiNotEqual(state,
      56             :                        SmiConstant(JSGeneratorObject::kGeneratorExecuting));
      57             :   }
      58             :   inline Node* IsGeneratorNotExecuting(Node* const generator) {
      59             :     return IsGeneratorStateNotExecuting(LoadGeneratorState(generator));
      60             :   }
      61             : 
      62             :   inline Node* LoadGeneratorAwaitedPromise(Node* const generator) {
      63             :     return LoadObjectField(generator,
      64          43 :                            JSAsyncGeneratorObject::kAwaitedPromiseOffset);
      65             :   }
      66             : 
      67             :   inline Node* IsGeneratorNotSuspendedForAwait(Node* const generator) {
      68             :     return IsUndefined(LoadGeneratorAwaitedPromise(generator));
      69             :   }
      70             : 
      71          43 :   inline Node* IsGeneratorSuspendedForAwait(Node* const generator) {
      72             :     return HasInstanceType(LoadGeneratorAwaitedPromise(generator),
      73          43 :                            JS_PROMISE_TYPE);
      74             :   }
      75             : 
      76             :   inline void ClearAwaitedPromise(Node* const generator) {
      77             :     StoreObjectFieldRoot(generator,
      78             :                          JSAsyncGeneratorObject::kAwaitedPromiseOffset,
      79          86 :                          Heap::kUndefinedValueRootIndex);
      80             :   }
      81             : 
      82          43 :   inline void CloseGenerator(Node* const generator) {
      83             :     StoreObjectFieldNoWriteBarrier(
      84             :         generator, JSGeneratorObject::kContinuationOffset,
      85          43 :         SmiConstant(JSGeneratorObject::kGeneratorClosed));
      86          43 :   }
      87             : 
      88             :   inline Node* IsFastJSIterResult(Node* const value, Node* const context) {
      89             :     CSA_ASSERT(this, TaggedIsNotSmi(value));
      90             :     Node* const native_context = LoadNativeContext(context);
      91             :     return WordEqual(
      92             :         LoadMap(value),
      93             :         LoadContextElement(native_context, Context::ITERATOR_RESULT_MAP_INDEX));
      94             :   }
      95             : 
      96             :   inline Node* LoadFirstAsyncGeneratorRequestFromQueue(Node* const generator) {
      97         301 :     return LoadObjectField(generator, JSAsyncGeneratorObject::kQueueOffset);
      98             :   }
      99             : 
     100             :   inline Node* LoadResumeTypeFromAsyncGeneratorRequest(Node* const request) {
     101          43 :     return LoadObjectField(request, AsyncGeneratorRequest::kResumeModeOffset);
     102             :   }
     103             : 
     104             :   inline Node* LoadPromiseFromAsyncGeneratorRequest(Node* const request) {
     105          86 :     return LoadObjectField(request, AsyncGeneratorRequest::kPromiseOffset);
     106             :   }
     107             : 
     108             :   inline Node* LoadValueFromAsyncGeneratorRequest(Node* const request) {
     109         129 :     return LoadObjectField(request, AsyncGeneratorRequest::kValueOffset);
     110             :   }
     111             : 
     112          43 :   inline Node* IsAbruptResumeType(Node* const resume_type) {
     113          43 :     return SmiNotEqual(resume_type, SmiConstant(JSGeneratorObject::kNext));
     114             :   }
     115             : 
     116             :   void AsyncGeneratorEnqueue(Node* context, Node* generator, Node* value,
     117             :                              JSAsyncGeneratorObject::ResumeMode resume_mode,
     118             :                              const char* method_name);
     119             : 
     120             :   Node* TakeFirstAsyncGeneratorRequestFromQueue(Node* generator);
     121             :   Node* TakeFirstAsyncGeneratorRequestFromQueueIfPresent(Node* generator,
     122             :                                                          Label* if_not_present);
     123             :   void AddAsyncGeneratorRequestToQueue(Node* generator, Node* request);
     124             : 
     125             :   Node* AllocateAsyncGeneratorRequest(
     126             :       JSAsyncGeneratorObject::ResumeMode resume_mode, Node* resume_value,
     127             :       Node* promise);
     128             : 
     129             :   // Shared implementation of the catchable and uncatchable variations of Await
     130             :   // for AsyncGenerators.
     131             :   template <typename Descriptor>
     132             :   void AsyncGeneratorAwait(bool is_catchable);
     133             :   void AsyncGeneratorAwaitResumeClosure(
     134             :       Node* context, Node* value,
     135             :       JSAsyncGeneratorObject::ResumeMode resume_mode);
     136             : };
     137             : 
     138             : // Shared implementation for the 3 Async Iterator protocol methods of Async
     139             : // Generators.
     140         129 : void AsyncGeneratorBuiltinsAssembler::AsyncGeneratorEnqueue(
     141             :     Node* context, Node* generator, Node* value,
     142             :     JSAsyncGeneratorObject::ResumeMode resume_mode, const char* method_name) {
     143             :   // AsyncGeneratorEnqueue produces a new Promise, and appends it to the list
     144             :   // of async generator requests to be executed. If the generator is not
     145             :   // presently executing, then this method will loop through, processing each
     146             :   // request from front to back.
     147             :   // This loop resides in AsyncGeneratorResumeNext.
     148         129 :   Node* promise = AllocateAndInitJSPromise(context);
     149             : 
     150         258 :   Label enqueue(this), if_receiverisincompatible(this, Label::kDeferred);
     151             : 
     152         129 :   GotoIf(TaggedIsSmi(generator), &if_receiverisincompatible);
     153             :   Branch(HasInstanceType(generator, JS_ASYNC_GENERATOR_OBJECT_TYPE), &enqueue,
     154         129 :          &if_receiverisincompatible);
     155             : 
     156         129 :   BIND(&enqueue);
     157             :   {
     158             :     Label done(this);
     159             :     Node* const req =
     160         129 :         AllocateAsyncGeneratorRequest(resume_mode, value, promise);
     161             : 
     162         129 :     AddAsyncGeneratorRequestToQueue(generator, req);
     163             : 
     164             :     // Let state be generator.[[AsyncGeneratorState]]
     165             :     // If state is not "executing", then
     166             :     //     Perform AsyncGeneratorResumeNext(Generator)
     167             :     // Check if the {receiver} is running or already closed.
     168             :     Node* continuation = LoadGeneratorState(generator);
     169             : 
     170             :     GotoIf(SmiEqual(continuation,
     171             :                     SmiConstant(JSAsyncGeneratorObject::kGeneratorExecuting)),
     172         129 :            &done);
     173             : 
     174         129 :     CallBuiltin(Builtins::kAsyncGeneratorResumeNext, context, generator);
     175             : 
     176         129 :     Goto(&done);
     177         129 :     BIND(&done);
     178         129 :     Return(promise);
     179             :   }
     180             : 
     181         129 :   BIND(&if_receiverisincompatible);
     182             :   {
     183             :     Node* const error =
     184             :         MakeTypeError(MessageTemplate::kIncompatibleMethodReceiver, context,
     185         129 :                       CStringConstant(method_name), generator);
     186             : 
     187             :     CallBuiltin(Builtins::kRejectNativePromise, context, promise, error,
     188         129 :                 TrueConstant());
     189         129 :     Return(promise);
     190         129 :   }
     191         129 : }
     192             : 
     193         129 : Node* AsyncGeneratorBuiltinsAssembler::AllocateAsyncGeneratorRequest(
     194             :     JSAsyncGeneratorObject::ResumeMode resume_mode, Node* resume_value,
     195             :     Node* promise) {
     196             :   CSA_SLOW_ASSERT(this, HasInstanceType(promise, JS_PROMISE_TYPE));
     197         129 :   Node* request = Allocate(AsyncGeneratorRequest::kSize);
     198         129 :   StoreMapNoWriteBarrier(request, Heap::kAsyncGeneratorRequestMapRootIndex);
     199             :   StoreObjectFieldNoWriteBarrier(request, AsyncGeneratorRequest::kNextOffset,
     200         129 :                                  UndefinedConstant());
     201             :   StoreObjectFieldNoWriteBarrier(request,
     202             :                                  AsyncGeneratorRequest::kResumeModeOffset,
     203         129 :                                  SmiConstant(resume_mode));
     204             :   StoreObjectFieldNoWriteBarrier(request, AsyncGeneratorRequest::kValueOffset,
     205         129 :                                  resume_value);
     206             :   StoreObjectFieldNoWriteBarrier(request, AsyncGeneratorRequest::kPromiseOffset,
     207         129 :                                  promise);
     208             :   StoreObjectFieldRoot(request, AsyncGeneratorRequest::kNextOffset,
     209         129 :                        Heap::kUndefinedValueRootIndex);
     210         129 :   return request;
     211             : }
     212             : 
     213          86 : void AsyncGeneratorBuiltinsAssembler::AsyncGeneratorAwaitResumeClosure(
     214             :     Node* context, Node* value,
     215             :     JSAsyncGeneratorObject::ResumeMode resume_mode) {
     216             :   Node* const generator =
     217          86 :       LoadContextElement(context, AwaitContext::kGeneratorSlot);
     218             :   CSA_SLOW_ASSERT(this,
     219             :                   HasInstanceType(generator, JS_ASYNC_GENERATOR_OBJECT_TYPE));
     220             : 
     221             : #if defined(DEBUG) && defined(ENABLE_SLOW_DCHECKS)
     222             :   Node* const awaited_promise = LoadGeneratorAwaitedPromise(generator);
     223             :   CSA_SLOW_ASSERT(this, HasInstanceType(awaited_promise, JS_PROMISE_TYPE));
     224             :   CSA_SLOW_ASSERT(this, SmiNotEqual(LoadObjectField(awaited_promise,
     225             :                                                     JSPromise::kStatusOffset),
     226             :                                     SmiConstant(v8::Promise::kPending)));
     227             : #endif
     228             : 
     229             :   ClearAwaitedPromise(generator);
     230             : 
     231             :   CSA_SLOW_ASSERT(this, IsGeneratorSuspended(generator));
     232             : 
     233             :   CallStub(CodeFactory::ResumeGenerator(isolate()), context, value, generator,
     234             :            SmiConstant(resume_mode),
     235         172 :            SmiConstant(static_cast<int>(SuspendFlags::kAsyncGeneratorAwait)));
     236             : 
     237             :   TailCallStub(CodeFactory::AsyncGeneratorResumeNext(isolate()), context,
     238          86 :                generator);
     239          86 : }
     240             : 
     241             : template <typename Descriptor>
     242          86 : void AsyncGeneratorBuiltinsAssembler::AsyncGeneratorAwait(bool is_catchable) {
     243          86 :   Node* generator = Parameter(1);
     244          86 :   Node* value = Parameter(2);
     245          86 :   Node* context = Parameter(5);
     246             : 
     247             :   CSA_SLOW_ASSERT(this,
     248             :                   HasInstanceType(generator, JS_ASYNC_GENERATOR_OBJECT_TYPE));
     249             : 
     250          86 :   Node* const request = LoadFirstAsyncGeneratorRequestFromQueue(generator);
     251             :   CSA_ASSERT(this, WordNotEqual(request, UndefinedConstant()));
     252             : 
     253          86 :   NodeGenerator1 closure_context = [&](Node* native_context) -> Node* {
     254             :     Node* const context =
     255          86 :         CreatePromiseContext(native_context, AwaitContext::kLength);
     256          86 :     StoreContextElementNoWriteBarrier(context, AwaitContext::kGeneratorSlot,
     257          86 :                                       generator);
     258          86 :     return context;
     259             :   };
     260             : 
     261             :   Node* outer_promise =
     262          86 :       LoadObjectField(request, AsyncGeneratorRequest::kPromiseOffset);
     263             : 
     264             :   const int resolve_index = Context::ASYNC_GENERATOR_AWAIT_RESOLVE_SHARED_FUN;
     265             :   const int reject_index = Context::ASYNC_GENERATOR_AWAIT_REJECT_SHARED_FUN;
     266             : 
     267             :   Node* promise =
     268             :       Await(context, generator, value, outer_promise, closure_context,
     269          86 :             resolve_index, reject_index, is_catchable);
     270             : 
     271             :   CSA_SLOW_ASSERT(this, IsGeneratorNotSuspendedForAwait(generator));
     272          86 :   StoreObjectField(generator, JSAsyncGeneratorObject::kAwaitedPromiseOffset,
     273             :                    promise);
     274          86 :   Return(UndefinedConstant());
     275          86 : }
     276             : 
     277         129 : void AsyncGeneratorBuiltinsAssembler::AddAsyncGeneratorRequestToQueue(
     278             :     Node* generator, Node* request) {
     279         129 :   VARIABLE(var_current, MachineRepresentation::kTagged);
     280         129 :   Label empty(this), loop(this, &var_current), done(this);
     281             : 
     282             :   var_current.Bind(
     283         129 :       LoadObjectField(generator, JSAsyncGeneratorObject::kQueueOffset));
     284         129 :   Branch(IsUndefined(var_current.value()), &empty, &loop);
     285             : 
     286         129 :   BIND(&empty);
     287             :   {
     288         129 :     StoreObjectField(generator, JSAsyncGeneratorObject::kQueueOffset, request);
     289         129 :     Goto(&done);
     290             :   }
     291             : 
     292         129 :   BIND(&loop);
     293             :   {
     294         129 :     Label loop_next(this), next_empty(this);
     295         129 :     Node* current = var_current.value();
     296         129 :     Node* next = LoadObjectField(current, AsyncGeneratorRequest::kNextOffset);
     297             : 
     298         129 :     Branch(IsUndefined(next), &next_empty, &loop_next);
     299         129 :     BIND(&next_empty);
     300             :     {
     301         129 :       StoreObjectField(current, AsyncGeneratorRequest::kNextOffset, request);
     302         129 :       Goto(&done);
     303             :     }
     304             : 
     305         129 :     BIND(&loop_next);
     306             :     {
     307         129 :       var_current.Bind(next);
     308         129 :       Goto(&loop);
     309         129 :     }
     310             :   }
     311         258 :   BIND(&done);
     312         129 : }
     313             : 
     314          86 : Node* AsyncGeneratorBuiltinsAssembler::TakeFirstAsyncGeneratorRequestFromQueue(
     315             :     Node* generator) {
     316             :   // Removes and returns the first AsyncGeneratorRequest from a
     317             :   // JSAsyncGeneratorObject's queue. Asserts that the queue is not empty.
     318             :   CSA_ASSERT(this, HasInstanceType(generator, JS_ASYNC_GENERATOR_OBJECT_TYPE));
     319             :   Node* request =
     320          86 :       LoadObjectField(generator, JSAsyncGeneratorObject::kQueueOffset);
     321             :   CSA_ASSERT(this, WordNotEqual(request, UndefinedConstant()));
     322             : 
     323          86 :   Node* next = LoadObjectField(request, AsyncGeneratorRequest::kNextOffset);
     324             : 
     325          86 :   StoreObjectField(generator, JSAsyncGeneratorObject::kQueueOffset, next);
     326          86 :   return request;
     327             : }
     328             : }  // namespace
     329             : 
     330             : // https://tc39.github.io/proposal-async-iteration/
     331             : // Section #sec-asyncgenerator-prototype-next
     332         172 : TF_BUILTIN(AsyncGeneratorPrototypeNext, AsyncGeneratorBuiltinsAssembler) {
     333             :   Node* const generator = Parameter(Descriptor::kReceiver);
     334             :   Node* const value = Parameter(Descriptor::kValue);
     335             :   Node* const context = Parameter(Descriptor::kContext);
     336             :   AsyncGeneratorEnqueue(context, generator, value,
     337             :                         JSAsyncGeneratorObject::kNext,
     338          43 :                         "[AsyncGenerator].prototype.next");
     339          43 : }
     340             : 
     341             : // https://tc39.github.io/proposal-async-iteration/
     342             : // Section #sec-asyncgenerator-prototype-return
     343         172 : TF_BUILTIN(AsyncGeneratorPrototypeReturn, AsyncGeneratorBuiltinsAssembler) {
     344             :   Node* generator = Parameter(Descriptor::kReceiver);
     345             :   Node* value = Parameter(Descriptor::kValue);
     346             :   Node* context = Parameter(Descriptor::kContext);
     347             :   AsyncGeneratorEnqueue(context, generator, value,
     348             :                         JSAsyncGeneratorObject::kReturn,
     349          43 :                         "[AsyncGenerator].prototype.return");
     350          43 : }
     351             : 
     352             : // https://tc39.github.io/proposal-async-iteration/
     353             : // Section #sec-asyncgenerator-prototype-throw
     354         172 : TF_BUILTIN(AsyncGeneratorPrototypeThrow, AsyncGeneratorBuiltinsAssembler) {
     355             :   Node* generator = Parameter(Descriptor::kReceiver);
     356             :   Node* value = Parameter(Descriptor::kValue);
     357             :   Node* context = Parameter(Descriptor::kContext);
     358             :   AsyncGeneratorEnqueue(context, generator, value,
     359             :                         JSAsyncGeneratorObject::kThrow,
     360          43 :                         "[AsyncGenerator].prototype.throw");
     361          43 : }
     362             : 
     363         172 : TF_BUILTIN(AsyncGeneratorAwaitResolveClosure, AsyncGeneratorBuiltinsAssembler) {
     364             :   Node* value = Parameter(Descriptor::kValue);
     365             :   Node* context = Parameter(Descriptor::kContext);
     366             :   AsyncGeneratorAwaitResumeClosure(context, value,
     367          43 :                                    JSAsyncGeneratorObject::kNext);
     368          43 : }
     369             : 
     370         172 : TF_BUILTIN(AsyncGeneratorAwaitRejectClosure, AsyncGeneratorBuiltinsAssembler) {
     371             :   Node* value = Parameter(Descriptor::kValue);
     372             :   Node* context = Parameter(Descriptor::kContext);
     373             :   AsyncGeneratorAwaitResumeClosure(context, value,
     374          43 :                                    JSAsyncGeneratorObject::kThrow);
     375          43 : }
     376             : 
     377         129 : TF_BUILTIN(AsyncGeneratorAwaitUncaught, AsyncGeneratorBuiltinsAssembler) {
     378             :   const bool kIsCatchable = false;
     379          43 :   AsyncGeneratorAwait<Descriptor>(kIsCatchable);
     380           0 : }
     381             : 
     382         129 : TF_BUILTIN(AsyncGeneratorAwaitCaught, AsyncGeneratorBuiltinsAssembler) {
     383             :   const bool kIsCatchable = true;
     384          43 :   AsyncGeneratorAwait<Descriptor>(kIsCatchable);
     385           0 : }
     386             : 
     387         172 : TF_BUILTIN(AsyncGeneratorResumeNext, AsyncGeneratorBuiltinsAssembler) {
     388             :   typedef AsyncGeneratorResumeNextDescriptor Descriptor;
     389             :   Node* const generator = Parameter(Descriptor::kGenerator);
     390             :   Node* const context = Parameter(Descriptor::kContext);
     391             : 
     392             :   // The penultimate step of proposal-async-iteration/#sec-asyncgeneratorresolve
     393             :   // and proposal-async-iteration/#sec-asyncgeneratorreject both recursively
     394             :   // invoke AsyncGeneratorResumeNext() again.
     395             :   //
     396             :   // This implementation does not implement this recursively, but instead
     397             :   // performs a loop in AsyncGeneratorResumeNext, which  continues as long as
     398             :   // there is an AsyncGeneratorRequest in the queue, and as long as the
     399             :   // generator is not suspended due to an AwaitExpression.
     400          43 :   VARIABLE(var_state, MachineRepresentation::kTaggedSigned,
     401             :            LoadGeneratorState(generator));
     402          86 :   VARIABLE(var_next, MachineRepresentation::kTagged,
     403             :            LoadFirstAsyncGeneratorRequestFromQueue(generator));
     404          43 :   Variable* labels[] = {&var_state, &var_next};
     405          86 :   Label start(this, 2, labels);
     406          43 :   Goto(&start);
     407          43 :   BIND(&start);
     408             : 
     409             :   CSA_ASSERT(this, IsGeneratorNotExecuting(generator));
     410             : 
     411             :   // Stop resuming if suspended for Await.
     412          43 :   ReturnIf(IsGeneratorSuspendedForAwait(generator), UndefinedConstant());
     413             : 
     414             :   // Stop resuming if request queue is empty.
     415          43 :   ReturnIf(IsUndefined(var_next.value()), UndefinedConstant());
     416             : 
     417          43 :   Node* const next = var_next.value();
     418             :   Node* const resume_type = LoadResumeTypeFromAsyncGeneratorRequest(next);
     419             : 
     420          43 :   Label if_abrupt(this), if_normal(this), resume_generator(this);
     421          43 :   Branch(IsAbruptResumeType(resume_type), &if_abrupt, &if_normal);
     422          43 :   BIND(&if_abrupt);
     423             :   {
     424          43 :     Label settle_promise(this), fulfill_promise(this), reject_promise(this);
     425             :     GotoIfNot(IsGeneratorStateSuspendedAtStart(var_state.value()),
     426          43 :               &settle_promise);
     427          43 :     CloseGenerator(generator);
     428          43 :     var_state.Bind(SmiConstant(JSGeneratorObject::kGeneratorClosed));
     429             : 
     430          43 :     Goto(&settle_promise);
     431          43 :     BIND(&settle_promise);
     432             : 
     433          43 :     GotoIfNot(IsGeneratorStateClosed(var_state.value()), &resume_generator);
     434             : 
     435             :     Branch(SmiEqual(resume_type, SmiConstant(JSGeneratorObject::kReturn)),
     436          43 :            &fulfill_promise, &reject_promise);
     437             : 
     438          43 :     BIND(&fulfill_promise);
     439             :     CallBuiltin(Builtins::kAsyncGeneratorResolve, context, generator,
     440          86 :                 LoadValueFromAsyncGeneratorRequest(next), TrueConstant());
     441          43 :     var_next.Bind(LoadFirstAsyncGeneratorRequestFromQueue(generator));
     442          43 :     Goto(&start);
     443             : 
     444          43 :     BIND(&reject_promise);
     445             :     CallBuiltin(Builtins::kAsyncGeneratorReject, context, generator,
     446          43 :                 LoadValueFromAsyncGeneratorRequest(next));
     447          43 :     var_next.Bind(LoadFirstAsyncGeneratorRequestFromQueue(generator));
     448          86 :     Goto(&start);
     449             :   }
     450             : 
     451          43 :   BIND(&if_normal);
     452             :   {
     453          43 :     GotoIfNot(IsGeneratorStateClosed(var_state.value()), &resume_generator);
     454             :     CallBuiltin(Builtins::kAsyncGeneratorResolve, context, generator,
     455          43 :                 UndefinedConstant(), TrueConstant());
     456          43 :     var_state.Bind(LoadGeneratorState(generator));
     457          43 :     var_next.Bind(LoadFirstAsyncGeneratorRequestFromQueue(generator));
     458          43 :     Goto(&start);
     459             :   }
     460             : 
     461          43 :   BIND(&resume_generator);
     462             :   {
     463             :     CallStub(CodeFactory::ResumeGenerator(isolate()), context,
     464             :              LoadValueFromAsyncGeneratorRequest(next), generator, resume_type,
     465         129 :              SmiConstant(static_cast<int>(SuspendFlags::kAsyncGeneratorYield)));
     466          43 :     var_state.Bind(LoadGeneratorState(generator));
     467          43 :     var_next.Bind(LoadFirstAsyncGeneratorRequestFromQueue(generator));
     468          43 :     Goto(&start);
     469          43 :   }
     470          43 : }
     471             : 
     472         172 : TF_BUILTIN(AsyncGeneratorResolve, AsyncGeneratorBuiltinsAssembler) {
     473             :   Node* const generator = Parameter(Descriptor::kGenerator);
     474             :   Node* const value = Parameter(Descriptor::kValue);
     475             :   Node* const done = Parameter(Descriptor::kDone);
     476             :   Node* const context = Parameter(Descriptor::kContext);
     477             : 
     478             :   CSA_SLOW_ASSERT(this,
     479             :                   HasInstanceType(generator, JS_ASYNC_GENERATOR_OBJECT_TYPE));
     480             :   CSA_ASSERT(this, IsGeneratorNotSuspendedForAwait(generator));
     481             : 
     482          43 :   Node* const next = TakeFirstAsyncGeneratorRequestFromQueue(generator);
     483             :   Node* const promise = LoadPromiseFromAsyncGeneratorRequest(next);
     484             : 
     485          43 :   Node* const wrapper = AllocateAndInitJSPromise(context);
     486          43 :   CallBuiltin(Builtins::kResolveNativePromise, context, wrapper, value);
     487             : 
     488             :   Node* const on_fulfilled =
     489          43 :       CreateUnwrapClosure(LoadNativeContext(context), done);
     490             : 
     491             :   // Per spec, AsyncGeneratorResolve() returns undefined. However, for the
     492             :   // benefit of %TraceExit(), return the Promise.
     493             :   Return(CallBuiltin(Builtins::kPerformNativePromiseThen, context, wrapper,
     494          43 :                      on_fulfilled, UndefinedConstant(), promise));
     495          43 : }
     496             : 
     497         172 : TF_BUILTIN(AsyncGeneratorReject, AsyncGeneratorBuiltinsAssembler) {
     498             :   typedef AsyncGeneratorRejectDescriptor Descriptor;
     499             :   Node* const generator = Parameter(Descriptor::kGenerator);
     500             :   Node* const value = Parameter(Descriptor::kValue);
     501             :   Node* const context = Parameter(Descriptor::kContext);
     502             : 
     503          43 :   Node* const next = TakeFirstAsyncGeneratorRequestFromQueue(generator);
     504             :   Node* const promise = LoadPromiseFromAsyncGeneratorRequest(next);
     505             : 
     506             :   Return(CallBuiltin(Builtins::kRejectNativePromise, context, promise, value,
     507          43 :                      TrueConstant()));
     508          43 : }
     509             : 
     510             : }  // namespace internal
     511             : }  // namespace v8

Generated by: LCOV version 1.10