11cb0ef41Sopenharmony_ci// Copyright 2017 the V8 project authors. All rights reserved. 21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be 31cb0ef41Sopenharmony_ci// found in the LICENSE file. 41cb0ef41Sopenharmony_ci 51cb0ef41Sopenharmony_ci#include "src/builtins/builtins-async-gen.h" 61cb0ef41Sopenharmony_ci#include "src/builtins/builtins-utils-gen.h" 71cb0ef41Sopenharmony_ci#include "src/builtins/builtins.h" 81cb0ef41Sopenharmony_ci#include "src/codegen/code-factory.h" 91cb0ef41Sopenharmony_ci#include "src/codegen/code-stub-assembler.h" 101cb0ef41Sopenharmony_ci#include "src/execution/frames-inl.h" 111cb0ef41Sopenharmony_ci#include "src/objects/js-generator.h" 121cb0ef41Sopenharmony_ci#include "src/objects/js-promise.h" 131cb0ef41Sopenharmony_ci 141cb0ef41Sopenharmony_cinamespace v8 { 151cb0ef41Sopenharmony_cinamespace internal { 161cb0ef41Sopenharmony_ci 171cb0ef41Sopenharmony_cinamespace { 181cb0ef41Sopenharmony_ci 191cb0ef41Sopenharmony_ciclass AsyncGeneratorBuiltinsAssembler : public AsyncBuiltinsAssembler { 201cb0ef41Sopenharmony_ci public: 211cb0ef41Sopenharmony_ci explicit AsyncGeneratorBuiltinsAssembler(CodeAssemblerState* state) 221cb0ef41Sopenharmony_ci : AsyncBuiltinsAssembler(state) {} 231cb0ef41Sopenharmony_ci 241cb0ef41Sopenharmony_ci inline TNode<Smi> LoadGeneratorState( 251cb0ef41Sopenharmony_ci const TNode<JSGeneratorObject> generator) { 261cb0ef41Sopenharmony_ci return LoadObjectField<Smi>(generator, 271cb0ef41Sopenharmony_ci JSGeneratorObject::kContinuationOffset); 281cb0ef41Sopenharmony_ci } 291cb0ef41Sopenharmony_ci 301cb0ef41Sopenharmony_ci inline TNode<BoolT> IsGeneratorStateClosed(const TNode<Smi> state) { 311cb0ef41Sopenharmony_ci return SmiEqual(state, SmiConstant(JSGeneratorObject::kGeneratorClosed)); 321cb0ef41Sopenharmony_ci } 331cb0ef41Sopenharmony_ci inline TNode<BoolT> IsGeneratorClosed( 341cb0ef41Sopenharmony_ci const TNode<JSGeneratorObject> generator) { 351cb0ef41Sopenharmony_ci return IsGeneratorStateClosed(LoadGeneratorState(generator)); 361cb0ef41Sopenharmony_ci } 371cb0ef41Sopenharmony_ci 381cb0ef41Sopenharmony_ci inline TNode<BoolT> IsGeneratorStateSuspended(const TNode<Smi> state) { 391cb0ef41Sopenharmony_ci return SmiGreaterThanOrEqual(state, SmiConstant(0)); 401cb0ef41Sopenharmony_ci } 411cb0ef41Sopenharmony_ci 421cb0ef41Sopenharmony_ci inline TNode<BoolT> IsGeneratorSuspended( 431cb0ef41Sopenharmony_ci const TNode<JSGeneratorObject> generator) { 441cb0ef41Sopenharmony_ci return IsGeneratorStateSuspended(LoadGeneratorState(generator)); 451cb0ef41Sopenharmony_ci } 461cb0ef41Sopenharmony_ci 471cb0ef41Sopenharmony_ci inline TNode<BoolT> IsGeneratorStateSuspendedAtStart(const TNode<Smi> state) { 481cb0ef41Sopenharmony_ci return SmiEqual(state, SmiConstant(0)); 491cb0ef41Sopenharmony_ci } 501cb0ef41Sopenharmony_ci 511cb0ef41Sopenharmony_ci inline TNode<BoolT> IsGeneratorStateNotExecuting(const TNode<Smi> state) { 521cb0ef41Sopenharmony_ci return SmiNotEqual(state, 531cb0ef41Sopenharmony_ci SmiConstant(JSGeneratorObject::kGeneratorExecuting)); 541cb0ef41Sopenharmony_ci } 551cb0ef41Sopenharmony_ci inline TNode<BoolT> IsGeneratorNotExecuting( 561cb0ef41Sopenharmony_ci const TNode<JSGeneratorObject> generator) { 571cb0ef41Sopenharmony_ci return IsGeneratorStateNotExecuting(LoadGeneratorState(generator)); 581cb0ef41Sopenharmony_ci } 591cb0ef41Sopenharmony_ci 601cb0ef41Sopenharmony_ci inline TNode<BoolT> IsGeneratorAwaiting( 611cb0ef41Sopenharmony_ci const TNode<JSGeneratorObject> generator) { 621cb0ef41Sopenharmony_ci TNode<Object> is_generator_awaiting = 631cb0ef41Sopenharmony_ci LoadObjectField(generator, JSAsyncGeneratorObject::kIsAwaitingOffset); 641cb0ef41Sopenharmony_ci return TaggedEqual(is_generator_awaiting, SmiConstant(1)); 651cb0ef41Sopenharmony_ci } 661cb0ef41Sopenharmony_ci 671cb0ef41Sopenharmony_ci inline void SetGeneratorAwaiting(const TNode<JSGeneratorObject> generator) { 681cb0ef41Sopenharmony_ci CSA_DCHECK(this, Word32BinaryNot(IsGeneratorAwaiting(generator))); 691cb0ef41Sopenharmony_ci StoreObjectFieldNoWriteBarrier( 701cb0ef41Sopenharmony_ci generator, JSAsyncGeneratorObject::kIsAwaitingOffset, SmiConstant(1)); 711cb0ef41Sopenharmony_ci CSA_DCHECK(this, IsGeneratorAwaiting(generator)); 721cb0ef41Sopenharmony_ci } 731cb0ef41Sopenharmony_ci 741cb0ef41Sopenharmony_ci inline void SetGeneratorNotAwaiting( 751cb0ef41Sopenharmony_ci const TNode<JSGeneratorObject> generator) { 761cb0ef41Sopenharmony_ci CSA_DCHECK(this, IsGeneratorAwaiting(generator)); 771cb0ef41Sopenharmony_ci StoreObjectFieldNoWriteBarrier( 781cb0ef41Sopenharmony_ci generator, JSAsyncGeneratorObject::kIsAwaitingOffset, SmiConstant(0)); 791cb0ef41Sopenharmony_ci CSA_DCHECK(this, Word32BinaryNot(IsGeneratorAwaiting(generator))); 801cb0ef41Sopenharmony_ci } 811cb0ef41Sopenharmony_ci 821cb0ef41Sopenharmony_ci inline void CloseGenerator(const TNode<JSGeneratorObject> generator) { 831cb0ef41Sopenharmony_ci StoreObjectFieldNoWriteBarrier( 841cb0ef41Sopenharmony_ci generator, JSGeneratorObject::kContinuationOffset, 851cb0ef41Sopenharmony_ci SmiConstant(JSGeneratorObject::kGeneratorClosed)); 861cb0ef41Sopenharmony_ci } 871cb0ef41Sopenharmony_ci 881cb0ef41Sopenharmony_ci inline TNode<HeapObject> LoadFirstAsyncGeneratorRequestFromQueue( 891cb0ef41Sopenharmony_ci const TNode<JSGeneratorObject> generator) { 901cb0ef41Sopenharmony_ci return LoadObjectField<HeapObject>(generator, 911cb0ef41Sopenharmony_ci JSAsyncGeneratorObject::kQueueOffset); 921cb0ef41Sopenharmony_ci } 931cb0ef41Sopenharmony_ci 941cb0ef41Sopenharmony_ci inline TNode<Smi> LoadResumeTypeFromAsyncGeneratorRequest( 951cb0ef41Sopenharmony_ci const TNode<AsyncGeneratorRequest> request) { 961cb0ef41Sopenharmony_ci return LoadObjectField<Smi>(request, 971cb0ef41Sopenharmony_ci AsyncGeneratorRequest::kResumeModeOffset); 981cb0ef41Sopenharmony_ci } 991cb0ef41Sopenharmony_ci 1001cb0ef41Sopenharmony_ci inline TNode<JSPromise> LoadPromiseFromAsyncGeneratorRequest( 1011cb0ef41Sopenharmony_ci const TNode<AsyncGeneratorRequest> request) { 1021cb0ef41Sopenharmony_ci return LoadObjectField<JSPromise>(request, 1031cb0ef41Sopenharmony_ci AsyncGeneratorRequest::kPromiseOffset); 1041cb0ef41Sopenharmony_ci } 1051cb0ef41Sopenharmony_ci 1061cb0ef41Sopenharmony_ci inline TNode<Object> LoadValueFromAsyncGeneratorRequest( 1071cb0ef41Sopenharmony_ci const TNode<AsyncGeneratorRequest> request) { 1081cb0ef41Sopenharmony_ci return LoadObjectField(request, AsyncGeneratorRequest::kValueOffset); 1091cb0ef41Sopenharmony_ci } 1101cb0ef41Sopenharmony_ci 1111cb0ef41Sopenharmony_ci inline TNode<BoolT> IsAbruptResumeType(const TNode<Smi> resume_type) { 1121cb0ef41Sopenharmony_ci return SmiNotEqual(resume_type, SmiConstant(JSGeneratorObject::kNext)); 1131cb0ef41Sopenharmony_ci } 1141cb0ef41Sopenharmony_ci 1151cb0ef41Sopenharmony_ci void AsyncGeneratorEnqueue(CodeStubArguments* args, TNode<Context> context, 1161cb0ef41Sopenharmony_ci TNode<Object> receiver, TNode<Object> value, 1171cb0ef41Sopenharmony_ci JSAsyncGeneratorObject::ResumeMode resume_mode, 1181cb0ef41Sopenharmony_ci const char* method_name); 1191cb0ef41Sopenharmony_ci 1201cb0ef41Sopenharmony_ci TNode<AsyncGeneratorRequest> TakeFirstAsyncGeneratorRequestFromQueue( 1211cb0ef41Sopenharmony_ci TNode<JSAsyncGeneratorObject> generator); 1221cb0ef41Sopenharmony_ci void AddAsyncGeneratorRequestToQueue(TNode<JSAsyncGeneratorObject> generator, 1231cb0ef41Sopenharmony_ci TNode<AsyncGeneratorRequest> request); 1241cb0ef41Sopenharmony_ci 1251cb0ef41Sopenharmony_ci TNode<AsyncGeneratorRequest> AllocateAsyncGeneratorRequest( 1261cb0ef41Sopenharmony_ci JSAsyncGeneratorObject::ResumeMode resume_mode, 1271cb0ef41Sopenharmony_ci TNode<Object> resume_value, TNode<JSPromise> promise); 1281cb0ef41Sopenharmony_ci 1291cb0ef41Sopenharmony_ci // Shared implementation of the catchable and uncatchable variations of Await 1301cb0ef41Sopenharmony_ci // for AsyncGenerators. 1311cb0ef41Sopenharmony_ci template <typename Descriptor> 1321cb0ef41Sopenharmony_ci void AsyncGeneratorAwait(bool is_catchable); 1331cb0ef41Sopenharmony_ci void AsyncGeneratorAwaitResumeClosure( 1341cb0ef41Sopenharmony_ci TNode<Context> context, TNode<Object> value, 1351cb0ef41Sopenharmony_ci JSAsyncGeneratorObject::ResumeMode resume_mode); 1361cb0ef41Sopenharmony_ci}; 1371cb0ef41Sopenharmony_ci 1381cb0ef41Sopenharmony_ci// Shared implementation for the 3 Async Iterator protocol methods of Async 1391cb0ef41Sopenharmony_ci// Generators. 1401cb0ef41Sopenharmony_civoid AsyncGeneratorBuiltinsAssembler::AsyncGeneratorEnqueue( 1411cb0ef41Sopenharmony_ci CodeStubArguments* args, TNode<Context> context, TNode<Object> receiver, 1421cb0ef41Sopenharmony_ci TNode<Object> value, JSAsyncGeneratorObject::ResumeMode resume_mode, 1431cb0ef41Sopenharmony_ci const char* method_name) { 1441cb0ef41Sopenharmony_ci // AsyncGeneratorEnqueue produces a new Promise, and appends it to the list 1451cb0ef41Sopenharmony_ci // of async generator requests to be executed. If the generator is not 1461cb0ef41Sopenharmony_ci // presently executing, then this method will loop through, processing each 1471cb0ef41Sopenharmony_ci // request from front to back. 1481cb0ef41Sopenharmony_ci // This loop resides in AsyncGeneratorResumeNext. 1491cb0ef41Sopenharmony_ci TNode<JSPromise> promise = NewJSPromise(context); 1501cb0ef41Sopenharmony_ci 1511cb0ef41Sopenharmony_ci Label if_receiverisincompatible(this, Label::kDeferred); 1521cb0ef41Sopenharmony_ci GotoIf(TaggedIsSmi(receiver), &if_receiverisincompatible); 1531cb0ef41Sopenharmony_ci GotoIfNot(HasInstanceType(CAST(receiver), JS_ASYNC_GENERATOR_OBJECT_TYPE), 1541cb0ef41Sopenharmony_ci &if_receiverisincompatible); 1551cb0ef41Sopenharmony_ci 1561cb0ef41Sopenharmony_ci { 1571cb0ef41Sopenharmony_ci Label done(this); 1581cb0ef41Sopenharmony_ci const TNode<JSAsyncGeneratorObject> generator = CAST(receiver); 1591cb0ef41Sopenharmony_ci const TNode<AsyncGeneratorRequest> req = 1601cb0ef41Sopenharmony_ci AllocateAsyncGeneratorRequest(resume_mode, value, promise); 1611cb0ef41Sopenharmony_ci 1621cb0ef41Sopenharmony_ci AddAsyncGeneratorRequestToQueue(generator, req); 1631cb0ef41Sopenharmony_ci 1641cb0ef41Sopenharmony_ci // Let state be generator.[[AsyncGeneratorState]] 1651cb0ef41Sopenharmony_ci // If state is not "executing", then 1661cb0ef41Sopenharmony_ci // Perform AsyncGeneratorResumeNext(Generator) 1671cb0ef41Sopenharmony_ci // Check if the {receiver} is running or already closed. 1681cb0ef41Sopenharmony_ci TNode<Smi> continuation = LoadGeneratorState(generator); 1691cb0ef41Sopenharmony_ci 1701cb0ef41Sopenharmony_ci GotoIf(SmiEqual(continuation, 1711cb0ef41Sopenharmony_ci SmiConstant(JSAsyncGeneratorObject::kGeneratorExecuting)), 1721cb0ef41Sopenharmony_ci &done); 1731cb0ef41Sopenharmony_ci 1741cb0ef41Sopenharmony_ci CallBuiltin(Builtin::kAsyncGeneratorResumeNext, context, generator); 1751cb0ef41Sopenharmony_ci 1761cb0ef41Sopenharmony_ci Goto(&done); 1771cb0ef41Sopenharmony_ci BIND(&done); 1781cb0ef41Sopenharmony_ci args->PopAndReturn(promise); 1791cb0ef41Sopenharmony_ci } 1801cb0ef41Sopenharmony_ci 1811cb0ef41Sopenharmony_ci BIND(&if_receiverisincompatible); 1821cb0ef41Sopenharmony_ci { 1831cb0ef41Sopenharmony_ci CallBuiltin(Builtin::kRejectPromise, context, promise, 1841cb0ef41Sopenharmony_ci MakeTypeError(MessageTemplate::kIncompatibleMethodReceiver, 1851cb0ef41Sopenharmony_ci context, StringConstant(method_name), receiver), 1861cb0ef41Sopenharmony_ci TrueConstant()); 1871cb0ef41Sopenharmony_ci args->PopAndReturn(promise); 1881cb0ef41Sopenharmony_ci } 1891cb0ef41Sopenharmony_ci} 1901cb0ef41Sopenharmony_ci 1911cb0ef41Sopenharmony_ciTNode<AsyncGeneratorRequest> 1921cb0ef41Sopenharmony_ciAsyncGeneratorBuiltinsAssembler::AllocateAsyncGeneratorRequest( 1931cb0ef41Sopenharmony_ci JSAsyncGeneratorObject::ResumeMode resume_mode, TNode<Object> resume_value, 1941cb0ef41Sopenharmony_ci TNode<JSPromise> promise) { 1951cb0ef41Sopenharmony_ci TNode<HeapObject> request = Allocate(AsyncGeneratorRequest::kSize); 1961cb0ef41Sopenharmony_ci StoreMapNoWriteBarrier(request, RootIndex::kAsyncGeneratorRequestMap); 1971cb0ef41Sopenharmony_ci StoreObjectFieldNoWriteBarrier(request, AsyncGeneratorRequest::kNextOffset, 1981cb0ef41Sopenharmony_ci UndefinedConstant()); 1991cb0ef41Sopenharmony_ci StoreObjectFieldNoWriteBarrier(request, 2001cb0ef41Sopenharmony_ci AsyncGeneratorRequest::kResumeModeOffset, 2011cb0ef41Sopenharmony_ci SmiConstant(resume_mode)); 2021cb0ef41Sopenharmony_ci StoreObjectFieldNoWriteBarrier(request, AsyncGeneratorRequest::kValueOffset, 2031cb0ef41Sopenharmony_ci resume_value); 2041cb0ef41Sopenharmony_ci StoreObjectFieldNoWriteBarrier(request, AsyncGeneratorRequest::kPromiseOffset, 2051cb0ef41Sopenharmony_ci promise); 2061cb0ef41Sopenharmony_ci StoreObjectFieldRoot(request, AsyncGeneratorRequest::kNextOffset, 2071cb0ef41Sopenharmony_ci RootIndex::kUndefinedValue); 2081cb0ef41Sopenharmony_ci return CAST(request); 2091cb0ef41Sopenharmony_ci} 2101cb0ef41Sopenharmony_ci 2111cb0ef41Sopenharmony_civoid AsyncGeneratorBuiltinsAssembler::AsyncGeneratorAwaitResumeClosure( 2121cb0ef41Sopenharmony_ci TNode<Context> context, TNode<Object> value, 2131cb0ef41Sopenharmony_ci JSAsyncGeneratorObject::ResumeMode resume_mode) { 2141cb0ef41Sopenharmony_ci const TNode<JSAsyncGeneratorObject> async_generator_object = 2151cb0ef41Sopenharmony_ci CAST(LoadContextElement(context, Context::EXTENSION_INDEX)); 2161cb0ef41Sopenharmony_ci 2171cb0ef41Sopenharmony_ci SetGeneratorNotAwaiting(async_generator_object); 2181cb0ef41Sopenharmony_ci 2191cb0ef41Sopenharmony_ci CSA_SLOW_DCHECK(this, IsGeneratorSuspended(async_generator_object)); 2201cb0ef41Sopenharmony_ci 2211cb0ef41Sopenharmony_ci // Remember the {resume_mode} for the {async_generator_object}. 2221cb0ef41Sopenharmony_ci StoreObjectFieldNoWriteBarrier(async_generator_object, 2231cb0ef41Sopenharmony_ci JSGeneratorObject::kResumeModeOffset, 2241cb0ef41Sopenharmony_ci SmiConstant(resume_mode)); 2251cb0ef41Sopenharmony_ci 2261cb0ef41Sopenharmony_ci // Push the promise for the {async_generator_object} back onto the catch 2271cb0ef41Sopenharmony_ci // prediction stack to handle exceptions thrown after resuming from the 2281cb0ef41Sopenharmony_ci // await properly. 2291cb0ef41Sopenharmony_ci Label if_instrumentation(this, Label::kDeferred), 2301cb0ef41Sopenharmony_ci if_instrumentation_done(this); 2311cb0ef41Sopenharmony_ci Branch(IsDebugActive(), &if_instrumentation, &if_instrumentation_done); 2321cb0ef41Sopenharmony_ci BIND(&if_instrumentation); 2331cb0ef41Sopenharmony_ci { 2341cb0ef41Sopenharmony_ci TNode<AsyncGeneratorRequest> request = 2351cb0ef41Sopenharmony_ci CAST(LoadFirstAsyncGeneratorRequestFromQueue(async_generator_object)); 2361cb0ef41Sopenharmony_ci TNode<JSPromise> promise = LoadObjectField<JSPromise>( 2371cb0ef41Sopenharmony_ci request, AsyncGeneratorRequest::kPromiseOffset); 2381cb0ef41Sopenharmony_ci CallRuntime(Runtime::kDebugPushPromise, context, promise); 2391cb0ef41Sopenharmony_ci Goto(&if_instrumentation_done); 2401cb0ef41Sopenharmony_ci } 2411cb0ef41Sopenharmony_ci BIND(&if_instrumentation_done); 2421cb0ef41Sopenharmony_ci 2431cb0ef41Sopenharmony_ci CallStub(CodeFactory::ResumeGenerator(isolate()), context, value, 2441cb0ef41Sopenharmony_ci async_generator_object); 2451cb0ef41Sopenharmony_ci 2461cb0ef41Sopenharmony_ci TailCallBuiltin(Builtin::kAsyncGeneratorResumeNext, context, 2471cb0ef41Sopenharmony_ci async_generator_object); 2481cb0ef41Sopenharmony_ci} 2491cb0ef41Sopenharmony_ci 2501cb0ef41Sopenharmony_citemplate <typename Descriptor> 2511cb0ef41Sopenharmony_civoid AsyncGeneratorBuiltinsAssembler::AsyncGeneratorAwait(bool is_catchable) { 2521cb0ef41Sopenharmony_ci auto async_generator_object = 2531cb0ef41Sopenharmony_ci Parameter<JSAsyncGeneratorObject>(Descriptor::kAsyncGeneratorObject); 2541cb0ef41Sopenharmony_ci auto value = Parameter<Object>(Descriptor::kValue); 2551cb0ef41Sopenharmony_ci auto context = Parameter<Context>(Descriptor::kContext); 2561cb0ef41Sopenharmony_ci 2571cb0ef41Sopenharmony_ci TNode<AsyncGeneratorRequest> request = 2581cb0ef41Sopenharmony_ci CAST(LoadFirstAsyncGeneratorRequestFromQueue(async_generator_object)); 2591cb0ef41Sopenharmony_ci TNode<JSPromise> outer_promise = LoadObjectField<JSPromise>( 2601cb0ef41Sopenharmony_ci request, AsyncGeneratorRequest::kPromiseOffset); 2611cb0ef41Sopenharmony_ci 2621cb0ef41Sopenharmony_ci Await(context, async_generator_object, value, outer_promise, 2631cb0ef41Sopenharmony_ci AsyncGeneratorAwaitResolveSharedFunConstant(), 2641cb0ef41Sopenharmony_ci AsyncGeneratorAwaitRejectSharedFunConstant(), is_catchable); 2651cb0ef41Sopenharmony_ci SetGeneratorAwaiting(async_generator_object); 2661cb0ef41Sopenharmony_ci Return(UndefinedConstant()); 2671cb0ef41Sopenharmony_ci} 2681cb0ef41Sopenharmony_ci 2691cb0ef41Sopenharmony_civoid AsyncGeneratorBuiltinsAssembler::AddAsyncGeneratorRequestToQueue( 2701cb0ef41Sopenharmony_ci TNode<JSAsyncGeneratorObject> generator, 2711cb0ef41Sopenharmony_ci TNode<AsyncGeneratorRequest> request) { 2721cb0ef41Sopenharmony_ci TVARIABLE(HeapObject, var_current); 2731cb0ef41Sopenharmony_ci Label empty(this), loop(this, &var_current), done(this); 2741cb0ef41Sopenharmony_ci 2751cb0ef41Sopenharmony_ci var_current = LoadObjectField<HeapObject>( 2761cb0ef41Sopenharmony_ci generator, JSAsyncGeneratorObject::kQueueOffset); 2771cb0ef41Sopenharmony_ci Branch(IsUndefined(var_current.value()), &empty, &loop); 2781cb0ef41Sopenharmony_ci 2791cb0ef41Sopenharmony_ci BIND(&empty); 2801cb0ef41Sopenharmony_ci { 2811cb0ef41Sopenharmony_ci StoreObjectField(generator, JSAsyncGeneratorObject::kQueueOffset, request); 2821cb0ef41Sopenharmony_ci Goto(&done); 2831cb0ef41Sopenharmony_ci } 2841cb0ef41Sopenharmony_ci 2851cb0ef41Sopenharmony_ci BIND(&loop); 2861cb0ef41Sopenharmony_ci { 2871cb0ef41Sopenharmony_ci Label loop_next(this), next_empty(this); 2881cb0ef41Sopenharmony_ci TNode<AsyncGeneratorRequest> current = CAST(var_current.value()); 2891cb0ef41Sopenharmony_ci TNode<HeapObject> next = LoadObjectField<HeapObject>( 2901cb0ef41Sopenharmony_ci current, AsyncGeneratorRequest::kNextOffset); 2911cb0ef41Sopenharmony_ci 2921cb0ef41Sopenharmony_ci Branch(IsUndefined(next), &next_empty, &loop_next); 2931cb0ef41Sopenharmony_ci BIND(&next_empty); 2941cb0ef41Sopenharmony_ci { 2951cb0ef41Sopenharmony_ci StoreObjectField(current, AsyncGeneratorRequest::kNextOffset, request); 2961cb0ef41Sopenharmony_ci Goto(&done); 2971cb0ef41Sopenharmony_ci } 2981cb0ef41Sopenharmony_ci 2991cb0ef41Sopenharmony_ci BIND(&loop_next); 3001cb0ef41Sopenharmony_ci { 3011cb0ef41Sopenharmony_ci var_current = next; 3021cb0ef41Sopenharmony_ci Goto(&loop); 3031cb0ef41Sopenharmony_ci } 3041cb0ef41Sopenharmony_ci } 3051cb0ef41Sopenharmony_ci BIND(&done); 3061cb0ef41Sopenharmony_ci} 3071cb0ef41Sopenharmony_ci 3081cb0ef41Sopenharmony_ciTNode<AsyncGeneratorRequest> 3091cb0ef41Sopenharmony_ciAsyncGeneratorBuiltinsAssembler::TakeFirstAsyncGeneratorRequestFromQueue( 3101cb0ef41Sopenharmony_ci TNode<JSAsyncGeneratorObject> generator) { 3111cb0ef41Sopenharmony_ci // Removes and returns the first AsyncGeneratorRequest from a 3121cb0ef41Sopenharmony_ci // JSAsyncGeneratorObject's queue. Asserts that the queue is not empty. 3131cb0ef41Sopenharmony_ci TNode<AsyncGeneratorRequest> request = LoadObjectField<AsyncGeneratorRequest>( 3141cb0ef41Sopenharmony_ci generator, JSAsyncGeneratorObject::kQueueOffset); 3151cb0ef41Sopenharmony_ci 3161cb0ef41Sopenharmony_ci TNode<Object> next = 3171cb0ef41Sopenharmony_ci LoadObjectField(request, AsyncGeneratorRequest::kNextOffset); 3181cb0ef41Sopenharmony_ci 3191cb0ef41Sopenharmony_ci StoreObjectField(generator, JSAsyncGeneratorObject::kQueueOffset, next); 3201cb0ef41Sopenharmony_ci return request; 3211cb0ef41Sopenharmony_ci} 3221cb0ef41Sopenharmony_ci} // namespace 3231cb0ef41Sopenharmony_ci 3241cb0ef41Sopenharmony_ci// https://tc39.github.io/proposal-async-iteration/ 3251cb0ef41Sopenharmony_ci// Section #sec-asyncgenerator-prototype-next 3261cb0ef41Sopenharmony_ciTF_BUILTIN(AsyncGeneratorPrototypeNext, AsyncGeneratorBuiltinsAssembler) { 3271cb0ef41Sopenharmony_ci const int kValueArg = 0; 3281cb0ef41Sopenharmony_ci 3291cb0ef41Sopenharmony_ci TNode<IntPtrT> argc = ChangeInt32ToIntPtr( 3301cb0ef41Sopenharmony_ci UncheckedParameter<Int32T>(Descriptor::kJSActualArgumentsCount)); 3311cb0ef41Sopenharmony_ci CodeStubArguments args(this, argc); 3321cb0ef41Sopenharmony_ci 3331cb0ef41Sopenharmony_ci TNode<Object> generator = args.GetReceiver(); 3341cb0ef41Sopenharmony_ci TNode<Object> value = args.GetOptionalArgumentValue(kValueArg); 3351cb0ef41Sopenharmony_ci auto context = Parameter<Context>(Descriptor::kContext); 3361cb0ef41Sopenharmony_ci 3371cb0ef41Sopenharmony_ci AsyncGeneratorEnqueue(&args, context, generator, value, 3381cb0ef41Sopenharmony_ci JSAsyncGeneratorObject::kNext, 3391cb0ef41Sopenharmony_ci "[AsyncGenerator].prototype.next"); 3401cb0ef41Sopenharmony_ci} 3411cb0ef41Sopenharmony_ci 3421cb0ef41Sopenharmony_ci// https://tc39.github.io/proposal-async-iteration/ 3431cb0ef41Sopenharmony_ci// Section #sec-asyncgenerator-prototype-return 3441cb0ef41Sopenharmony_ciTF_BUILTIN(AsyncGeneratorPrototypeReturn, AsyncGeneratorBuiltinsAssembler) { 3451cb0ef41Sopenharmony_ci const int kValueArg = 0; 3461cb0ef41Sopenharmony_ci 3471cb0ef41Sopenharmony_ci TNode<IntPtrT> argc = ChangeInt32ToIntPtr( 3481cb0ef41Sopenharmony_ci UncheckedParameter<Int32T>(Descriptor::kJSActualArgumentsCount)); 3491cb0ef41Sopenharmony_ci CodeStubArguments args(this, argc); 3501cb0ef41Sopenharmony_ci 3511cb0ef41Sopenharmony_ci TNode<Object> generator = args.GetReceiver(); 3521cb0ef41Sopenharmony_ci TNode<Object> value = args.GetOptionalArgumentValue(kValueArg); 3531cb0ef41Sopenharmony_ci auto context = Parameter<Context>(Descriptor::kContext); 3541cb0ef41Sopenharmony_ci 3551cb0ef41Sopenharmony_ci AsyncGeneratorEnqueue(&args, context, generator, value, 3561cb0ef41Sopenharmony_ci JSAsyncGeneratorObject::kReturn, 3571cb0ef41Sopenharmony_ci "[AsyncGenerator].prototype.return"); 3581cb0ef41Sopenharmony_ci} 3591cb0ef41Sopenharmony_ci 3601cb0ef41Sopenharmony_ci// https://tc39.github.io/proposal-async-iteration/ 3611cb0ef41Sopenharmony_ci// Section #sec-asyncgenerator-prototype-throw 3621cb0ef41Sopenharmony_ciTF_BUILTIN(AsyncGeneratorPrototypeThrow, AsyncGeneratorBuiltinsAssembler) { 3631cb0ef41Sopenharmony_ci const int kValueArg = 0; 3641cb0ef41Sopenharmony_ci 3651cb0ef41Sopenharmony_ci TNode<IntPtrT> argc = ChangeInt32ToIntPtr( 3661cb0ef41Sopenharmony_ci UncheckedParameter<Int32T>(Descriptor::kJSActualArgumentsCount)); 3671cb0ef41Sopenharmony_ci CodeStubArguments args(this, argc); 3681cb0ef41Sopenharmony_ci 3691cb0ef41Sopenharmony_ci TNode<Object> generator = args.GetReceiver(); 3701cb0ef41Sopenharmony_ci TNode<Object> value = args.GetOptionalArgumentValue(kValueArg); 3711cb0ef41Sopenharmony_ci auto context = Parameter<Context>(Descriptor::kContext); 3721cb0ef41Sopenharmony_ci 3731cb0ef41Sopenharmony_ci AsyncGeneratorEnqueue(&args, context, generator, value, 3741cb0ef41Sopenharmony_ci JSAsyncGeneratorObject::kThrow, 3751cb0ef41Sopenharmony_ci "[AsyncGenerator].prototype.throw"); 3761cb0ef41Sopenharmony_ci} 3771cb0ef41Sopenharmony_ci 3781cb0ef41Sopenharmony_ciTF_BUILTIN(AsyncGeneratorAwaitResolveClosure, AsyncGeneratorBuiltinsAssembler) { 3791cb0ef41Sopenharmony_ci auto value = Parameter<Object>(Descriptor::kValue); 3801cb0ef41Sopenharmony_ci auto context = Parameter<Context>(Descriptor::kContext); 3811cb0ef41Sopenharmony_ci AsyncGeneratorAwaitResumeClosure(context, value, 3821cb0ef41Sopenharmony_ci JSAsyncGeneratorObject::kNext); 3831cb0ef41Sopenharmony_ci} 3841cb0ef41Sopenharmony_ci 3851cb0ef41Sopenharmony_ciTF_BUILTIN(AsyncGeneratorAwaitRejectClosure, AsyncGeneratorBuiltinsAssembler) { 3861cb0ef41Sopenharmony_ci auto value = Parameter<Object>(Descriptor::kValue); 3871cb0ef41Sopenharmony_ci auto context = Parameter<Context>(Descriptor::kContext); 3881cb0ef41Sopenharmony_ci AsyncGeneratorAwaitResumeClosure(context, value, 3891cb0ef41Sopenharmony_ci JSAsyncGeneratorObject::kThrow); 3901cb0ef41Sopenharmony_ci} 3911cb0ef41Sopenharmony_ci 3921cb0ef41Sopenharmony_ciTF_BUILTIN(AsyncGeneratorAwaitUncaught, AsyncGeneratorBuiltinsAssembler) { 3931cb0ef41Sopenharmony_ci const bool kIsCatchable = false; 3941cb0ef41Sopenharmony_ci AsyncGeneratorAwait<Descriptor>(kIsCatchable); 3951cb0ef41Sopenharmony_ci} 3961cb0ef41Sopenharmony_ci 3971cb0ef41Sopenharmony_ciTF_BUILTIN(AsyncGeneratorAwaitCaught, AsyncGeneratorBuiltinsAssembler) { 3981cb0ef41Sopenharmony_ci const bool kIsCatchable = true; 3991cb0ef41Sopenharmony_ci AsyncGeneratorAwait<Descriptor>(kIsCatchable); 4001cb0ef41Sopenharmony_ci} 4011cb0ef41Sopenharmony_ci 4021cb0ef41Sopenharmony_ciTF_BUILTIN(AsyncGeneratorResumeNext, AsyncGeneratorBuiltinsAssembler) { 4031cb0ef41Sopenharmony_ci const auto generator = 4041cb0ef41Sopenharmony_ci Parameter<JSAsyncGeneratorObject>(Descriptor::kGenerator); 4051cb0ef41Sopenharmony_ci const auto context = Parameter<Context>(Descriptor::kContext); 4061cb0ef41Sopenharmony_ci 4071cb0ef41Sopenharmony_ci // The penultimate step of proposal-async-iteration/#sec-asyncgeneratorresolve 4081cb0ef41Sopenharmony_ci // and proposal-async-iteration/#sec-asyncgeneratorreject both recursively 4091cb0ef41Sopenharmony_ci // invoke AsyncGeneratorResumeNext() again. 4101cb0ef41Sopenharmony_ci // 4111cb0ef41Sopenharmony_ci // This implementation does not implement this recursively, but instead 4121cb0ef41Sopenharmony_ci // performs a loop in AsyncGeneratorResumeNext, which continues as long as 4131cb0ef41Sopenharmony_ci // there is an AsyncGeneratorRequest in the queue, and as long as the 4141cb0ef41Sopenharmony_ci // generator is not suspended due to an AwaitExpression. 4151cb0ef41Sopenharmony_ci TVARIABLE(Smi, var_state, LoadGeneratorState(generator)); 4161cb0ef41Sopenharmony_ci TVARIABLE(HeapObject, var_next, 4171cb0ef41Sopenharmony_ci LoadFirstAsyncGeneratorRequestFromQueue(generator)); 4181cb0ef41Sopenharmony_ci Label start(this, {&var_state, &var_next}); 4191cb0ef41Sopenharmony_ci Goto(&start); 4201cb0ef41Sopenharmony_ci BIND(&start); 4211cb0ef41Sopenharmony_ci 4221cb0ef41Sopenharmony_ci CSA_DCHECK(this, IsGeneratorNotExecuting(generator)); 4231cb0ef41Sopenharmony_ci 4241cb0ef41Sopenharmony_ci // Stop resuming if suspended for Await. 4251cb0ef41Sopenharmony_ci ReturnIf(IsGeneratorAwaiting(generator), UndefinedConstant()); 4261cb0ef41Sopenharmony_ci 4271cb0ef41Sopenharmony_ci // Stop resuming if request queue is empty. 4281cb0ef41Sopenharmony_ci ReturnIf(IsUndefined(var_next.value()), UndefinedConstant()); 4291cb0ef41Sopenharmony_ci 4301cb0ef41Sopenharmony_ci const TNode<AsyncGeneratorRequest> next = CAST(var_next.value()); 4311cb0ef41Sopenharmony_ci const TNode<Smi> resume_type = LoadResumeTypeFromAsyncGeneratorRequest(next); 4321cb0ef41Sopenharmony_ci 4331cb0ef41Sopenharmony_ci Label if_abrupt(this), if_normal(this), resume_generator(this); 4341cb0ef41Sopenharmony_ci Branch(IsAbruptResumeType(resume_type), &if_abrupt, &if_normal); 4351cb0ef41Sopenharmony_ci BIND(&if_abrupt); 4361cb0ef41Sopenharmony_ci { 4371cb0ef41Sopenharmony_ci Label settle_promise(this), if_return(this), if_throw(this); 4381cb0ef41Sopenharmony_ci GotoIfNot(IsGeneratorStateSuspendedAtStart(var_state.value()), 4391cb0ef41Sopenharmony_ci &settle_promise); 4401cb0ef41Sopenharmony_ci CloseGenerator(generator); 4411cb0ef41Sopenharmony_ci var_state = SmiConstant(JSGeneratorObject::kGeneratorClosed); 4421cb0ef41Sopenharmony_ci Goto(&settle_promise); 4431cb0ef41Sopenharmony_ci 4441cb0ef41Sopenharmony_ci BIND(&settle_promise); 4451cb0ef41Sopenharmony_ci TNode<Object> next_value = LoadValueFromAsyncGeneratorRequest(next); 4461cb0ef41Sopenharmony_ci Branch(SmiEqual(resume_type, SmiConstant(JSGeneratorObject::kReturn)), 4471cb0ef41Sopenharmony_ci &if_return, &if_throw); 4481cb0ef41Sopenharmony_ci 4491cb0ef41Sopenharmony_ci BIND(&if_return); 4501cb0ef41Sopenharmony_ci // For "return" completions, await the sent value. If the Await succeeds, 4511cb0ef41Sopenharmony_ci // and the generator is not closed, resume the generator with a "return" 4521cb0ef41Sopenharmony_ci // completion to allow `finally` blocks to be evaluated. Otherwise, perform 4531cb0ef41Sopenharmony_ci // AsyncGeneratorResolve(awaitedValue, true). If the await fails and the 4541cb0ef41Sopenharmony_ci // generator is not closed, resume the generator with a "throw" completion. 4551cb0ef41Sopenharmony_ci // If the generator was closed, perform AsyncGeneratorReject(thrownValue). 4561cb0ef41Sopenharmony_ci // In all cases, the last step is to call AsyncGeneratorResumeNext. 4571cb0ef41Sopenharmony_ci TNode<Object> is_caught = CallRuntime( 4581cb0ef41Sopenharmony_ci Runtime::kAsyncGeneratorHasCatchHandlerForPC, context, generator); 4591cb0ef41Sopenharmony_ci TailCallBuiltin(Builtin::kAsyncGeneratorReturn, context, generator, 4601cb0ef41Sopenharmony_ci next_value, is_caught); 4611cb0ef41Sopenharmony_ci 4621cb0ef41Sopenharmony_ci BIND(&if_throw); 4631cb0ef41Sopenharmony_ci GotoIfNot(IsGeneratorStateClosed(var_state.value()), &resume_generator); 4641cb0ef41Sopenharmony_ci CallBuiltin(Builtin::kAsyncGeneratorReject, context, generator, next_value); 4651cb0ef41Sopenharmony_ci var_next = LoadFirstAsyncGeneratorRequestFromQueue(generator); 4661cb0ef41Sopenharmony_ci Goto(&start); 4671cb0ef41Sopenharmony_ci } 4681cb0ef41Sopenharmony_ci 4691cb0ef41Sopenharmony_ci BIND(&if_normal); 4701cb0ef41Sopenharmony_ci { 4711cb0ef41Sopenharmony_ci GotoIfNot(IsGeneratorStateClosed(var_state.value()), &resume_generator); 4721cb0ef41Sopenharmony_ci CallBuiltin(Builtin::kAsyncGeneratorResolve, context, generator, 4731cb0ef41Sopenharmony_ci UndefinedConstant(), TrueConstant()); 4741cb0ef41Sopenharmony_ci var_state = LoadGeneratorState(generator); 4751cb0ef41Sopenharmony_ci var_next = LoadFirstAsyncGeneratorRequestFromQueue(generator); 4761cb0ef41Sopenharmony_ci Goto(&start); 4771cb0ef41Sopenharmony_ci } 4781cb0ef41Sopenharmony_ci 4791cb0ef41Sopenharmony_ci BIND(&resume_generator); 4801cb0ef41Sopenharmony_ci { 4811cb0ef41Sopenharmony_ci // Remember the {resume_type} for the {generator}. 4821cb0ef41Sopenharmony_ci StoreObjectFieldNoWriteBarrier( 4831cb0ef41Sopenharmony_ci generator, JSGeneratorObject::kResumeModeOffset, resume_type); 4841cb0ef41Sopenharmony_ci CallStub(CodeFactory::ResumeGenerator(isolate()), context, 4851cb0ef41Sopenharmony_ci LoadValueFromAsyncGeneratorRequest(next), generator); 4861cb0ef41Sopenharmony_ci var_state = LoadGeneratorState(generator); 4871cb0ef41Sopenharmony_ci var_next = LoadFirstAsyncGeneratorRequestFromQueue(generator); 4881cb0ef41Sopenharmony_ci Goto(&start); 4891cb0ef41Sopenharmony_ci } 4901cb0ef41Sopenharmony_ci} 4911cb0ef41Sopenharmony_ci 4921cb0ef41Sopenharmony_ciTF_BUILTIN(AsyncGeneratorResolve, AsyncGeneratorBuiltinsAssembler) { 4931cb0ef41Sopenharmony_ci const auto generator = 4941cb0ef41Sopenharmony_ci Parameter<JSAsyncGeneratorObject>(Descriptor::kGenerator); 4951cb0ef41Sopenharmony_ci const auto value = Parameter<Object>(Descriptor::kValue); 4961cb0ef41Sopenharmony_ci const auto done = Parameter<Object>(Descriptor::kDone); 4971cb0ef41Sopenharmony_ci const auto context = Parameter<Context>(Descriptor::kContext); 4981cb0ef41Sopenharmony_ci 4991cb0ef41Sopenharmony_ci CSA_DCHECK(this, Word32BinaryNot(IsGeneratorAwaiting(generator))); 5001cb0ef41Sopenharmony_ci 5011cb0ef41Sopenharmony_ci // This operation should be called only when the `value` parameter has been 5021cb0ef41Sopenharmony_ci // Await-ed. Typically, this means `value` is not a JSPromise value. However, 5031cb0ef41Sopenharmony_ci // it may be a JSPromise value whose "then" method has been overridden to a 5041cb0ef41Sopenharmony_ci // non-callable value. This can't be checked with assertions due to being 5051cb0ef41Sopenharmony_ci // observable, but keep it in mind. 5061cb0ef41Sopenharmony_ci 5071cb0ef41Sopenharmony_ci const TNode<AsyncGeneratorRequest> next = 5081cb0ef41Sopenharmony_ci TakeFirstAsyncGeneratorRequestFromQueue(generator); 5091cb0ef41Sopenharmony_ci const TNode<JSPromise> promise = LoadPromiseFromAsyncGeneratorRequest(next); 5101cb0ef41Sopenharmony_ci 5111cb0ef41Sopenharmony_ci // Let iteratorResult be CreateIterResultObject(value, done). 5121cb0ef41Sopenharmony_ci const TNode<HeapObject> iter_result = Allocate(JSIteratorResult::kSize); 5131cb0ef41Sopenharmony_ci { 5141cb0ef41Sopenharmony_ci TNode<Map> map = CAST(LoadContextElement( 5151cb0ef41Sopenharmony_ci LoadNativeContext(context), Context::ITERATOR_RESULT_MAP_INDEX)); 5161cb0ef41Sopenharmony_ci StoreMapNoWriteBarrier(iter_result, map); 5171cb0ef41Sopenharmony_ci StoreObjectFieldRoot(iter_result, JSIteratorResult::kPropertiesOrHashOffset, 5181cb0ef41Sopenharmony_ci RootIndex::kEmptyFixedArray); 5191cb0ef41Sopenharmony_ci StoreObjectFieldRoot(iter_result, JSIteratorResult::kElementsOffset, 5201cb0ef41Sopenharmony_ci RootIndex::kEmptyFixedArray); 5211cb0ef41Sopenharmony_ci StoreObjectFieldNoWriteBarrier(iter_result, JSIteratorResult::kValueOffset, 5221cb0ef41Sopenharmony_ci value); 5231cb0ef41Sopenharmony_ci StoreObjectFieldNoWriteBarrier(iter_result, JSIteratorResult::kDoneOffset, 5241cb0ef41Sopenharmony_ci done); 5251cb0ef41Sopenharmony_ci } 5261cb0ef41Sopenharmony_ci 5271cb0ef41Sopenharmony_ci // We know that {iter_result} itself doesn't have any "then" property (a 5281cb0ef41Sopenharmony_ci // freshly allocated IterResultObject only has "value" and "done" properties) 5291cb0ef41Sopenharmony_ci // and we also know that the [[Prototype]] of {iter_result} is the intrinsic 5301cb0ef41Sopenharmony_ci // %ObjectPrototype%. So we can skip the [[Resolve]] logic here completely 5311cb0ef41Sopenharmony_ci // and directly call into the FulfillPromise operation if we can prove 5321cb0ef41Sopenharmony_ci // that the %ObjectPrototype% also doesn't have any "then" property. This 5331cb0ef41Sopenharmony_ci // is guarded by the Promise#then() protector. 5341cb0ef41Sopenharmony_ci // If the PromiseHooks are enabled, we cannot take the shortcut here, since 5351cb0ef41Sopenharmony_ci // the "promiseResolve" hook would not be fired otherwise. 5361cb0ef41Sopenharmony_ci Label if_fast(this), if_slow(this, Label::kDeferred), return_promise(this); 5371cb0ef41Sopenharmony_ci GotoIfForceSlowPath(&if_slow); 5381cb0ef41Sopenharmony_ci GotoIf(IsIsolatePromiseHookEnabledOrHasAsyncEventDelegate(), &if_slow); 5391cb0ef41Sopenharmony_ci Branch(IsPromiseThenProtectorCellInvalid(), &if_slow, &if_fast); 5401cb0ef41Sopenharmony_ci 5411cb0ef41Sopenharmony_ci BIND(&if_fast); 5421cb0ef41Sopenharmony_ci { 5431cb0ef41Sopenharmony_ci // Skip the "then" on {iter_result} and directly fulfill the {promise} 5441cb0ef41Sopenharmony_ci // with the {iter_result}. 5451cb0ef41Sopenharmony_ci CallBuiltin(Builtin::kFulfillPromise, context, promise, iter_result); 5461cb0ef41Sopenharmony_ci Goto(&return_promise); 5471cb0ef41Sopenharmony_ci } 5481cb0ef41Sopenharmony_ci 5491cb0ef41Sopenharmony_ci BIND(&if_slow); 5501cb0ef41Sopenharmony_ci { 5511cb0ef41Sopenharmony_ci // Perform Call(promiseCapability.[[Resolve]], undefined, «iteratorResult»). 5521cb0ef41Sopenharmony_ci CallBuiltin(Builtin::kResolvePromise, context, promise, iter_result); 5531cb0ef41Sopenharmony_ci Goto(&return_promise); 5541cb0ef41Sopenharmony_ci } 5551cb0ef41Sopenharmony_ci 5561cb0ef41Sopenharmony_ci // Per spec, AsyncGeneratorResolve() returns undefined. However, for the 5571cb0ef41Sopenharmony_ci // benefit of %TraceExit(), return the Promise. 5581cb0ef41Sopenharmony_ci BIND(&return_promise); 5591cb0ef41Sopenharmony_ci Return(promise); 5601cb0ef41Sopenharmony_ci} 5611cb0ef41Sopenharmony_ci 5621cb0ef41Sopenharmony_ciTF_BUILTIN(AsyncGeneratorReject, AsyncGeneratorBuiltinsAssembler) { 5631cb0ef41Sopenharmony_ci const auto generator = 5641cb0ef41Sopenharmony_ci Parameter<JSAsyncGeneratorObject>(Descriptor::kGenerator); 5651cb0ef41Sopenharmony_ci const auto value = Parameter<Object>(Descriptor::kValue); 5661cb0ef41Sopenharmony_ci const auto context = Parameter<Context>(Descriptor::kContext); 5671cb0ef41Sopenharmony_ci 5681cb0ef41Sopenharmony_ci TNode<AsyncGeneratorRequest> next = 5691cb0ef41Sopenharmony_ci TakeFirstAsyncGeneratorRequestFromQueue(generator); 5701cb0ef41Sopenharmony_ci TNode<JSPromise> promise = LoadPromiseFromAsyncGeneratorRequest(next); 5711cb0ef41Sopenharmony_ci 5721cb0ef41Sopenharmony_ci Return(CallBuiltin(Builtin::kRejectPromise, context, promise, value, 5731cb0ef41Sopenharmony_ci TrueConstant())); 5741cb0ef41Sopenharmony_ci} 5751cb0ef41Sopenharmony_ci 5761cb0ef41Sopenharmony_ciTF_BUILTIN(AsyncGeneratorYield, AsyncGeneratorBuiltinsAssembler) { 5771cb0ef41Sopenharmony_ci const auto generator = Parameter<JSGeneratorObject>(Descriptor::kGenerator); 5781cb0ef41Sopenharmony_ci const auto value = Parameter<Object>(Descriptor::kValue); 5791cb0ef41Sopenharmony_ci const auto is_caught = Parameter<Oddball>(Descriptor::kIsCaught); 5801cb0ef41Sopenharmony_ci const auto context = Parameter<Context>(Descriptor::kContext); 5811cb0ef41Sopenharmony_ci 5821cb0ef41Sopenharmony_ci const TNode<AsyncGeneratorRequest> request = 5831cb0ef41Sopenharmony_ci CAST(LoadFirstAsyncGeneratorRequestFromQueue(generator)); 5841cb0ef41Sopenharmony_ci const TNode<JSPromise> outer_promise = 5851cb0ef41Sopenharmony_ci LoadPromiseFromAsyncGeneratorRequest(request); 5861cb0ef41Sopenharmony_ci 5871cb0ef41Sopenharmony_ci Await(context, generator, value, outer_promise, 5881cb0ef41Sopenharmony_ci AsyncGeneratorYieldResolveSharedFunConstant(), 5891cb0ef41Sopenharmony_ci AsyncGeneratorAwaitRejectSharedFunConstant(), is_caught); 5901cb0ef41Sopenharmony_ci SetGeneratorAwaiting(generator); 5911cb0ef41Sopenharmony_ci Return(UndefinedConstant()); 5921cb0ef41Sopenharmony_ci} 5931cb0ef41Sopenharmony_ci 5941cb0ef41Sopenharmony_ciTF_BUILTIN(AsyncGeneratorYieldResolveClosure, AsyncGeneratorBuiltinsAssembler) { 5951cb0ef41Sopenharmony_ci const auto context = Parameter<Context>(Descriptor::kContext); 5961cb0ef41Sopenharmony_ci const auto value = Parameter<Object>(Descriptor::kValue); 5971cb0ef41Sopenharmony_ci const TNode<JSAsyncGeneratorObject> generator = 5981cb0ef41Sopenharmony_ci CAST(LoadContextElement(context, Context::EXTENSION_INDEX)); 5991cb0ef41Sopenharmony_ci 6001cb0ef41Sopenharmony_ci SetGeneratorNotAwaiting(generator); 6011cb0ef41Sopenharmony_ci 6021cb0ef41Sopenharmony_ci // Per proposal-async-iteration/#sec-asyncgeneratoryield step 9 6031cb0ef41Sopenharmony_ci // Return ! AsyncGeneratorResolve(_F_.[[Generator]], _value_, *false*). 6041cb0ef41Sopenharmony_ci CallBuiltin(Builtin::kAsyncGeneratorResolve, context, generator, value, 6051cb0ef41Sopenharmony_ci FalseConstant()); 6061cb0ef41Sopenharmony_ci 6071cb0ef41Sopenharmony_ci TailCallBuiltin(Builtin::kAsyncGeneratorResumeNext, context, generator); 6081cb0ef41Sopenharmony_ci} 6091cb0ef41Sopenharmony_ci 6101cb0ef41Sopenharmony_ciTF_BUILTIN(AsyncGeneratorReturn, AsyncGeneratorBuiltinsAssembler) { 6111cb0ef41Sopenharmony_ci // AsyncGeneratorReturn is called when resuming requests with "return" resume 6121cb0ef41Sopenharmony_ci // modes. It is similar to AsyncGeneratorAwait(), but selects different 6131cb0ef41Sopenharmony_ci // resolve/reject closures depending on whether or not the generator is marked 6141cb0ef41Sopenharmony_ci // as closed. 6151cb0ef41Sopenharmony_ci // 6161cb0ef41Sopenharmony_ci // In particular, non-closed generators will resume the generator with either 6171cb0ef41Sopenharmony_ci // "return" or "throw" resume modes, allowing finally blocks or catch blocks 6181cb0ef41Sopenharmony_ci // to be evaluated, as if the `await` were performed within the body of the 6191cb0ef41Sopenharmony_ci // generator. (per proposal-async-iteration/#sec-asyncgeneratoryield step 8.b) 6201cb0ef41Sopenharmony_ci // 6211cb0ef41Sopenharmony_ci // Closed generators do not resume the generator in the resolve/reject 6221cb0ef41Sopenharmony_ci // closures, but instead simply perform AsyncGeneratorResolve or 6231cb0ef41Sopenharmony_ci // AsyncGeneratorReject with the awaited value 6241cb0ef41Sopenharmony_ci // (per proposal-async-iteration/#sec-asyncgeneratorresumenext step 10.b.i) 6251cb0ef41Sopenharmony_ci // 6261cb0ef41Sopenharmony_ci // In all cases, the final step is to jump back to AsyncGeneratorResumeNext. 6271cb0ef41Sopenharmony_ci const auto generator = Parameter<JSGeneratorObject>(Descriptor::kGenerator); 6281cb0ef41Sopenharmony_ci const auto value = Parameter<Object>(Descriptor::kValue); 6291cb0ef41Sopenharmony_ci const auto is_caught = Parameter<Oddball>(Descriptor::kIsCaught); 6301cb0ef41Sopenharmony_ci const TNode<AsyncGeneratorRequest> req = 6311cb0ef41Sopenharmony_ci CAST(LoadFirstAsyncGeneratorRequestFromQueue(generator)); 6321cb0ef41Sopenharmony_ci 6331cb0ef41Sopenharmony_ci Label perform_await(this); 6341cb0ef41Sopenharmony_ci TVARIABLE(SharedFunctionInfo, var_on_resolve, 6351cb0ef41Sopenharmony_ci AsyncGeneratorReturnClosedResolveSharedFunConstant()); 6361cb0ef41Sopenharmony_ci 6371cb0ef41Sopenharmony_ci TVARIABLE(SharedFunctionInfo, var_on_reject, 6381cb0ef41Sopenharmony_ci AsyncGeneratorReturnClosedRejectSharedFunConstant()); 6391cb0ef41Sopenharmony_ci 6401cb0ef41Sopenharmony_ci const TNode<Smi> state = LoadGeneratorState(generator); 6411cb0ef41Sopenharmony_ci GotoIf(IsGeneratorStateClosed(state), &perform_await); 6421cb0ef41Sopenharmony_ci var_on_resolve = AsyncGeneratorReturnResolveSharedFunConstant(); 6431cb0ef41Sopenharmony_ci var_on_reject = AsyncGeneratorAwaitRejectSharedFunConstant(); 6441cb0ef41Sopenharmony_ci 6451cb0ef41Sopenharmony_ci Goto(&perform_await); 6461cb0ef41Sopenharmony_ci 6471cb0ef41Sopenharmony_ci BIND(&perform_await); 6481cb0ef41Sopenharmony_ci 6491cb0ef41Sopenharmony_ci SetGeneratorAwaiting(generator); 6501cb0ef41Sopenharmony_ci auto context = Parameter<Context>(Descriptor::kContext); 6511cb0ef41Sopenharmony_ci const TNode<JSPromise> outer_promise = 6521cb0ef41Sopenharmony_ci LoadPromiseFromAsyncGeneratorRequest(req); 6531cb0ef41Sopenharmony_ci Await(context, generator, value, outer_promise, var_on_resolve.value(), 6541cb0ef41Sopenharmony_ci var_on_reject.value(), is_caught); 6551cb0ef41Sopenharmony_ci 6561cb0ef41Sopenharmony_ci Return(UndefinedConstant()); 6571cb0ef41Sopenharmony_ci} 6581cb0ef41Sopenharmony_ci 6591cb0ef41Sopenharmony_ci// On-resolve closure for Await in AsyncGeneratorReturn 6601cb0ef41Sopenharmony_ci// Resume the generator with "return" resume_mode, and finally perform 6611cb0ef41Sopenharmony_ci// AsyncGeneratorResumeNext. Per 6621cb0ef41Sopenharmony_ci// proposal-async-iteration/#sec-asyncgeneratoryield step 8.e 6631cb0ef41Sopenharmony_ciTF_BUILTIN(AsyncGeneratorReturnResolveClosure, 6641cb0ef41Sopenharmony_ci AsyncGeneratorBuiltinsAssembler) { 6651cb0ef41Sopenharmony_ci const auto context = Parameter<Context>(Descriptor::kContext); 6661cb0ef41Sopenharmony_ci const auto value = Parameter<Object>(Descriptor::kValue); 6671cb0ef41Sopenharmony_ci AsyncGeneratorAwaitResumeClosure(context, value, JSGeneratorObject::kReturn); 6681cb0ef41Sopenharmony_ci} 6691cb0ef41Sopenharmony_ci 6701cb0ef41Sopenharmony_ci// On-resolve closure for Await in AsyncGeneratorReturn 6711cb0ef41Sopenharmony_ci// Perform AsyncGeneratorResolve({awaited_value}, true) and finally perform 6721cb0ef41Sopenharmony_ci// AsyncGeneratorResumeNext. 6731cb0ef41Sopenharmony_ciTF_BUILTIN(AsyncGeneratorReturnClosedResolveClosure, 6741cb0ef41Sopenharmony_ci AsyncGeneratorBuiltinsAssembler) { 6751cb0ef41Sopenharmony_ci const auto context = Parameter<Context>(Descriptor::kContext); 6761cb0ef41Sopenharmony_ci const auto value = Parameter<Object>(Descriptor::kValue); 6771cb0ef41Sopenharmony_ci const TNode<JSAsyncGeneratorObject> generator = 6781cb0ef41Sopenharmony_ci CAST(LoadContextElement(context, Context::EXTENSION_INDEX)); 6791cb0ef41Sopenharmony_ci 6801cb0ef41Sopenharmony_ci SetGeneratorNotAwaiting(generator); 6811cb0ef41Sopenharmony_ci 6821cb0ef41Sopenharmony_ci // https://tc39.github.io/proposal-async-iteration/ 6831cb0ef41Sopenharmony_ci // #async-generator-resume-next-return-processor-fulfilled step 2: 6841cb0ef41Sopenharmony_ci // Return ! AsyncGeneratorResolve(_F_.[[Generator]], _value_, *true*). 6851cb0ef41Sopenharmony_ci CallBuiltin(Builtin::kAsyncGeneratorResolve, context, generator, value, 6861cb0ef41Sopenharmony_ci TrueConstant()); 6871cb0ef41Sopenharmony_ci 6881cb0ef41Sopenharmony_ci TailCallBuiltin(Builtin::kAsyncGeneratorResumeNext, context, generator); 6891cb0ef41Sopenharmony_ci} 6901cb0ef41Sopenharmony_ci 6911cb0ef41Sopenharmony_ciTF_BUILTIN(AsyncGeneratorReturnClosedRejectClosure, 6921cb0ef41Sopenharmony_ci AsyncGeneratorBuiltinsAssembler) { 6931cb0ef41Sopenharmony_ci const auto context = Parameter<Context>(Descriptor::kContext); 6941cb0ef41Sopenharmony_ci const auto value = Parameter<Object>(Descriptor::kValue); 6951cb0ef41Sopenharmony_ci const TNode<JSAsyncGeneratorObject> generator = 6961cb0ef41Sopenharmony_ci CAST(LoadContextElement(context, Context::EXTENSION_INDEX)); 6971cb0ef41Sopenharmony_ci 6981cb0ef41Sopenharmony_ci SetGeneratorNotAwaiting(generator); 6991cb0ef41Sopenharmony_ci 7001cb0ef41Sopenharmony_ci // https://tc39.github.io/proposal-async-iteration/ 7011cb0ef41Sopenharmony_ci // #async-generator-resume-next-return-processor-rejected step 2: 7021cb0ef41Sopenharmony_ci // Return ! AsyncGeneratorReject(_F_.[[Generator]], _reason_). 7031cb0ef41Sopenharmony_ci CallBuiltin(Builtin::kAsyncGeneratorReject, context, generator, value); 7041cb0ef41Sopenharmony_ci 7051cb0ef41Sopenharmony_ci TailCallBuiltin(Builtin::kAsyncGeneratorResumeNext, context, generator); 7061cb0ef41Sopenharmony_ci} 7071cb0ef41Sopenharmony_ci 7081cb0ef41Sopenharmony_ci} // namespace internal 7091cb0ef41Sopenharmony_ci} // namespace v8 710