| # Suspendable Functions (`async`, `async*` and `sync*`) | 
 |  | 
 | This document describes the implementation of _suspendable_ functions (functions with `async`, | 
 | `async*` or `sync*` modifier) in Dart VM. The execution of such functions can be suspended in | 
 | the middle at `await`/`yield`/`yield*` and resumed afterwards. | 
 |  | 
 | When suspending a function, its local execution state (local variables and temporaries) is saved | 
 | and the control is returned to the caller of the suspended function. | 
 | When resuming a function, its local execution state is restored and execution continues within | 
 | the suspendable function from the point where it was suspended. | 
 |  | 
 | In order to minimize code size, the implementation is built using a variety of _stubs_ - reusable | 
 | snippets of machine code generated by the VM/AOT. | 
 | The high-level Dart logic used to implement suspendable functions (such as managing | 
 | Futures/Streams/Iterators) is factored into helper Dart methods in core library. | 
 |  | 
 | The rest of the document is organized as follows: first, general mechanisms for implementation of | 
 | suspendable functions are described. | 
 | After that, `async`, `async*` and `sync*` implementations are outlined using the general | 
 | mechanisms introduced before. | 
 |  | 
 | # Building blocks common to all suspendable functions | 
 |  | 
 | ## SuspendState objects | 
 |  | 
 | SuspendState objects are allocated on the heap and encapsulate the saved state of a suspended | 
 | function. When suspending a function, its local frame (including local variables, spill slots | 
 | and expression stack) is copied from the stack to a SuspendState object on the heap. | 
 | When resuming a function, the frame is recreated and copied back from the SuspendState object | 
 | into the stack. | 
 |  | 
 | SuspendState objects have variable size and keep frame in the "payload" following a few fixed | 
 | fields. | 
 |  | 
 | In addition to a stack frame, SuspendState records a PC in the code of the suspended function | 
 | where execution was suspended and can be resumed. | 
 | The PC is also used by GC to find a stack map and scan through the pointers in the copied frame. | 
 |  | 
 | SuspendState object also holds data and callbacks specific to a particular kind of suspendable | 
 | function. | 
 |  | 
 | SuspendState object is allocated during the first suspension and can be reused for the subsequent | 
 | suspensions of the same function. | 
 |  | 
 | For the declaration of SuspendState see [object.h](https://github.com/dart-lang/sdk/blob/main/runtime/vm/object.h#:~:text=class%20SuspendState), | 
 | UntaggedSuspendState is declared in [raw_object.h](https://github.com/dart-lang/sdk/blob/main/runtime/vm/raw_object.h#:~:text=class%20UntaggedSuspendState). | 
 |  | 
 | There is also a corresponding Dart class `_SuspendState`, declared in [async_patch.dart](https://github.com/dart-lang/sdk/blob/main/sdk/lib/_internal/vm/lib/async_patch.dart#:~:text=class%20_SuspendState). | 
 | It contains Dart methods which are used to customize implementation for a particular kind of | 
 | suspendable function. | 
 |  | 
 | ## Frame of a suspendable function | 
 |  | 
 | Suspendable functions are never inlined into other functions, so their local state is not mixed | 
 | with the state of their callers (but other functions may be inlined into them). | 
 |  | 
 | In order to have a single contiguous region of memory to copy during suspend/resume, parameters of | 
 | suspendable functions are always copied into the local frame in the function prologue (see uses of | 
 | `Function::MakesCopyOfParameters()` predicate). | 
 |  | 
 | In order to keep and reuse SuspendState object, each suspendable function has an artificial local | 
 | variable `:suspend_state` (see uses of `ParsedFunction::suspend_state_var()`), which is always | 
 | allocated at the fixed offset in frame. It occupies the first local variable slot | 
 | (`SuspendState::kSuspendStateVarIndex`) in case of unoptimized code or the first spill slot | 
 | in case of optimized code (see `FlowGraphAllocator::AllocateSpillSlotForSuspendState`). | 
 | The fixed location helps to find this variable in various stubs and runtime. | 
 |  | 
 | ## Prologue and InitSuspendableFunction stub | 
 |  | 
 | At the very beginning of a suspendable function `null` is stored into `:suspend_state` variable. | 
 | This guarantees that `:suspend_state` variable can be accessed any time by GC and exception | 
 | handling. | 
 |  | 
 | After checking bounds of type arguments and types of arguments, suspendable functions call | 
 | InitSuspendableFunction stub. | 
 |  | 
 | InitSuspendableFunction stub does the following: | 
 |  | 
 | - It calls a static generic Dart method specific to a particular kind of suspendable function. | 
 |   The argument of the stub is passed as type arguments to that method. | 
 |   Dart method performs initialization specific to a particular kind of suspendable function | 
 |   (for example, it creates `_Future<T>()` for async functions). | 
 |   It returns the instance which is used as a function-specific data. | 
 |  | 
 | - Stub puts the function-specific data to `:suspend_state` variable, where it can be found by | 
 |   Suspend or Return stubs later. | 
 |  | 
 | ## Suspend stub | 
 |  | 
 | Suspend stub is called from a suspendable function when its execution should be suspended. | 
 |  | 
 | Suspend stub does the following: | 
 |  | 
 | - It inspects `:suspend_state` variable and checks if it contains an instance of SuspendState. | 
 |   If it doesn't, then stub allocates a new instance with a payload sufficient to hold a frame of | 
 |   the suspendable function. The newly allocated SuspendState is stored into `:suspend_state` | 
 |   variable, and previous value of `:suspend_state` (coming from InitSuspendableFunction stub) is | 
 |   saved to `SuspendState.function_data`. | 
 |  | 
 | - In JIT mode, size of the frame may vary over time - expression stack depth varies during | 
 |   execution of unoptimized code and frame size may change during deoptimization and OSR. | 
 |   In AOT mode size of the stack frame stays the same. | 
 |   So, if stub finds an existing SuspendState object in JIT mode, it also checks if its frame | 
 |   payload has a sufficient size to hold a frame of the suspendable function. If it is not | 
 |   large enough, suspend stub calls `AllocateSuspendState` runtime entry to allocate a larger | 
 |   SuspendState object. The same runtime entry is called for slow path when allocating | 
 |   SuspendState for the first time. | 
 |  | 
 | - The return address from Suspend stub to the suspendable function is saved to `SuspendState.pc`. | 
 |   It will be used to resume execution later. | 
 |  | 
 | - The contents of the stack frame of the suspendable function between FP and SP is copied into | 
 |   SuspendState. | 
 |  | 
 | - Write barrier: if SuspendState object resides in the old generation, then | 
 |   EnsureRememberedAndMarkingDeferred runtime entry is called. | 
 |  | 
 | - If implementation of particular kind of suspendable function uses a customized Dart method | 
 |   for the suspension, then that method is called. | 
 |   Suspend stub supports passing one argument to the customization method. | 
 |   The result of the method is returned back to the caller of the suspendable function - it's | 
 |   the result of the suspendable function. | 
 |   If such method is not used, then Suspend stub returns its argument (so suspendable function | 
 |   could customize its return value). | 
 |  | 
 | - On architectures other than x64/ia32, the frame of the suspendable function is removed and | 
 |   stub returns directly to the caller of the suspendable function. | 
 |   On x64/ia32, in order to maintain call/return balance and avoid performance penalty, | 
 |   Suspend stub returns to the suspendable function which immediately returns to its caller. | 
 |  | 
 | For more details see `StubCodeCompiler::GenerateSuspendStub` in [stub_code_compiler.cc](https://github.com/dart-lang/sdk/blob/main/runtime/vm/compiler/stub_code_compiler.cc#:~:text=StubCodeCompiler::GenerateSuspendStub). | 
 |  | 
 | ## Resume stub | 
 |  | 
 | Resume stub is tail-called from `_SuspendState._resume` recognized method (which is called | 
 | from Dart helpers). It is used to resume execution of the previously suspended function. | 
 |  | 
 | Resume stub does the following: | 
 |  | 
 | - Allocates Dart frame on the stack, using `SuspendState.frame_size` to calculate its size. | 
 |  | 
 | - Copies frame contents from SuspendState to the stack. | 
 |  | 
 | - In JIT mode restores pool pointer (PP). | 
 |  | 
 | - Checks for the following cases and calls ResumeFrame runtime entry if any of this is true: | 
 |   + If resuming with an exception. | 
 |   + In JIT mode, if Code of the suspendable function is disabled (deoptimized). | 
 |   + In JIT mode, if there is a resumption breakpoint set by debugger. | 
 |  | 
 | - Otherwise, jumps to `SuspendState.pc` to resume execution of the suspended function. | 
 |   On x64/ia32 the continuation PC is adjusted by adding `SuspendStubABI::kResumePcDistance` | 
 |   to skip over the epilogue which immediately follows the Suspend stub call to maintain | 
 |   call/return balance. | 
 |  | 
 | ResumeFrame runtime entry is called as if it was called from suspended function at continuation PC. | 
 | It handles all corner cases by throwing an exception, lazy deoptimizing or calling into | 
 | the debugger. | 
 |  | 
 | For more details see `StubCodeCompiler::GenerateResumeStub` in [stub_code_compiler.cc](https://github.com/dart-lang/sdk/blob/main/runtime/vm/compiler/stub_code_compiler.cc#:~:text=StubCodeCompiler::GenerateResumeStub) | 
 | and `ResumeFrame` in [runtime_entry.cc](https://github.com/dart-lang/sdk/blob/main/runtime/vm/runtime_entry.cc#:~:text=ResumeFrame). | 
 |  | 
 | ## Return stub | 
 |  | 
 | Suspendable functions can use Return stub if they need to do something when execution of | 
 | a function ends (for example, complete a Future or close a Stream). In such a case, | 
 | suspendable function jumps to the Return stub instead of returning. | 
 |  | 
 | Return stub does the following: | 
 |  | 
 | - Removes the frame of the suspendable function (as if function epilogue was executed). | 
 |  | 
 | - Calls a Dart method specific to a particular kind of suspendable function. | 
 |   The customization method takes a value of `:suspend_state` variable and a return value | 
 |   passed from the body of the suspendable function to the stub. | 
 |  | 
 | - The value returned from the customization method is used as the result of | 
 |   the suspendable function. | 
 |  | 
 | For more details see `StubCodeCompiler::GenerateReturnStub` in [stub_code_compiler.cc](https://github.com/dart-lang/sdk/blob/main/runtime/vm/compiler/stub_code_compiler.cc#:~:text=StubCodeCompiler::GenerateReturnStub). | 
 |  | 
 | ## Exception handling and AsyncExceptionHandler stub | 
 |  | 
 | Certain kinds of suspendable functions (async and async*) may need to catch all thrown exceptions | 
 | which are not caught within the function body, and perform certain actions (such as completing | 
 | the Future with an error). | 
 |  | 
 | This is implemented by setting `has_async_handler` bit on `ExceptionHandlers` object. | 
 | When looking for an exception handler, runtime checks if this bit is set and uses | 
 | AsyncExceptionHandler stub as a handler (see `StackFrame::FindExceptionHandler`). | 
 |  | 
 | AsyncExceptionHandler stub does the following: | 
 |  | 
 | - It inspects the value of `:suspend_state` variable. If it is `null` (meaning the prologue has not | 
 |   finished yet), the exception should not be handled and it is rethrown. | 
 |   This makes it possible for argument type checks to throw an exception  synchronously | 
 |   instead of completing a Future with an error. | 
 |  | 
 | - Otherwise, stub removes the frame of the suspendable function (as if function epilogue was | 
 |   executed) and calls `_SuspendState._handleException` Dart method. AsyncExceptionHandler stub | 
 |   does not use separate Dart helper methods for async and async* functions as exception handling is | 
 |   not performance sensitive and currently uses only one bit in `ExceptionHandlers` to select | 
 |   a stub handler for simplicity. | 
 |  | 
 | - The value returned from `_SuspendState._handleException` is used as the result of the | 
 |   suspendable function. | 
 |  | 
 | For more details see `StubCodeCompiler::GenerateAsyncExceptionHandlerStub` in [stub_code_compiler.cc](https://github.com/dart-lang/sdk/blob/main/runtime/vm/compiler/stub_code_compiler.cc#:~:text=StubCodeCompiler::GenerateAsyncExceptionHandlerStub). | 
 |  | 
 | ## IL instructions | 
 |  | 
 | When compiling suspendable functions, the following IL instructions are used: | 
 |  | 
 | - `Call1ArgStub` instruction is used to call one-argument stubs such as InitSuspendableFunction. | 
 |  | 
 | - `Suspend` instruction is used to call Suspend stub. After calling Suspend stub, | 
 |   on x64/ia32 it also generates an epilogue right after the stub, in order to | 
 |   return to the caller after suspending without disrupting call/return balance. | 
 |   Due to this extra epilogue following the Suspend stub call, the resumption PC is | 
 |   not the same as the return address of the Suspend stub. So `Suspend` instruction | 
 |   uses 2 distinct deopt ids for the Suspend stub call and resumption PC. | 
 |  | 
 | - `Return` instruction jumps to a Return stub instead of returning for certain kinds | 
 |   of suspendable functions (async and async*). | 
 |  | 
 | # Combining all pieces together | 
 |  | 
 | ## Async functions | 
 |  | 
 | See [async_patch.dart](https://github.com/dart-lang/sdk/blob/main/sdk/lib/_internal/vm/lib/async_patch.dart) for the corresponding Dart source code. | 
 |  | 
 | Async functions use the following customized stubs: | 
 |  | 
 | ### InitAsync stub | 
 |  | 
 | InitAsync = InitSuspendableFunction stub which calls `_SuspendState._initAsync`. | 
 |  | 
 | `_SuspendState._initAsync` creates a `_Future<T>` instance which is used as the result of | 
 | the async function. This `_Future<T>` instance is kept in `:suspend_state` variable until | 
 | `_SuspendState` instance is created during the first `await`, and then kept in | 
 | `_SuspendState._functionData`. This instance is returned from `_SuspendState._await`, | 
 | `_SuspendState._returnAsync`, `_SuspendState._returnAsyncNotFuture` and | 
 | `_SuspendState._handleException` methods to serve as the result of the async function. | 
 |  | 
 | ### Await stub | 
 |  | 
 | Await = Suspend stub which calls `_SuspendState._await`. It implements the `await` expression. | 
 |  | 
 | `_SuspendState._await` allocates 'then' and 'error' callback closures when called for | 
 | the first time. These callback closures resume execution of the async function via Resume stub. | 
 | It is possible to create callbacks eagerly in the InitAsync stub, but there is a significant | 
 | fraction of async functions which don't have `await` at all, so creating callbacks lazily during | 
 | the first `await` makes those functions more efficient. | 
 | If an argument of `await` is a Future, then `_SuspendState._await` attaches 'then' and 'error' | 
 | callbacks to that Future. Otherwise it schedules a micro-task to continue execution of | 
 | the suspended function later. | 
 |  | 
 | ### AwaitWithTypeCheck stub | 
 |  | 
 | AwaitWithTypeCheck is a variant of Await stub which additionally passes type argument `T` | 
 | and calls `_SuspendState._awaitWithTypeCheck` in order to test if the value has a | 
 | correct `Future<T>` type before awaiting. | 
 |  | 
 | This runtime check is needed to maintain soundness in case value is a Future of an | 
 | incompatible type, for example: | 
 |  | 
 | ``` | 
 | final FutureOr<Object> f = Future<Object?>.value(null); | 
 | Object x = await f; // x == f, not null. | 
 | ``` | 
 |  | 
 | ### ReturnAsync stub | 
 |  | 
 | ReturnAsync stub = Return stub which calls `_SuspendState._returnAsync`. | 
 | It is used to implement `return` statement (either explicit or implicit when reaching | 
 | the end of function). | 
 |  | 
 | `_SuspendState._returnAsync` completes `_Future<T>` which is used as the result of | 
 | the async function. | 
 |  | 
 | ### ReturnAsyncNotFuture stub | 
 |  | 
 | ReturnAsyncNotFuture stub = Return stub which calls `_SuspendState._returnAsyncNotFuture`. | 
 |  | 
 | ReturnAsyncNotFuture is similar to ReturnAsync, but used when compiler can prove that | 
 | return value is not a Future. It bypasses the expensive `is Future` test. | 
 |  | 
 | ### Execution flow in async functions | 
 |  | 
 | The following diagram depicts how the control is passed in a typical async function: | 
 |  | 
 | ``` | 
 | Caller          Future<T> foo() async           Stubs        Dart _SuspendState methods | 
 |   | | 
 |   *-------------------> | | 
 |                     (prologue) -------------> InitAsync | 
 |                                                   | | 
 |                                                   *----------> _initAsync | 
 |                                                               (creates _Future<T>) | 
 |                                                   | <--------- | 
 |                         | <-----------------------* | 
 |                         | | 
 |                         | | 
 |                       (await) ----------------> AwaitAsync | 
 |                                                   | | 
 |                                                   *----------> _await | 
 |                                                               (setups resumption) | 
 |                                                               (returns _Future<T>) | 
 |                                                   | <--------- | 
 |   | <---------------------------------------------* | 
 |  | 
 | Awaited Future is completed | 
 |   | | 
 |   *------------------------------------------> Resume | 
 |                                                   | | 
 |                     (after await) <---------------* | 
 |                         | | 
 |                         | | 
 |                       (return) ---------------> ReturnAsync/ReturnAsyncNotFuture | 
 |                                                   | | 
 |                                                   *----------> _returnAsync/_returnAsyncNotFuture | 
 |                                                               (completes _Future<T>) | 
 |                                                               (returns _Future<T>) | 
 |                                                   | <--------- | 
 |   | <---------------------------------------------* | 
 | ``` | 
 |  | 
 | ## Async* functions | 
 |  | 
 | See [async_patch.dart](https://github.com/dart-lang/sdk/blob/main/sdk/lib/_internal/vm/lib/async_patch.dart) | 
 | for the corresponding Dart source code. | 
 |  | 
 | Async* functions use the following customized stubs: | 
 |  | 
 | ### InitAsyncStar stub | 
 |  | 
 | InitAsyncStar = InitSuspendableFunction stub which calls `_SuspendState._initAsyncStar`. | 
 |  | 
 | `_SuspendState._initAsyncStar` creates `_AsyncStarStreamController<T>` instance which is used | 
 | to control the Stream returned from the async* function. `_AsyncStarStreamController<T>` is kept | 
 | in `_SuspendState._functionData` (after the first suspension at the beginning of async* function). | 
 |  | 
 | ## YieldAsyncStar stub and `yield`/`yield*` | 
 |  | 
 | YieldAsyncStar = Suspend stub which calls `_SuspendState._yieldAsyncStar`. | 
 |  | 
 | This stub is used to suspend async* function at the beginning (until listener is attached to | 
 | the Stream returned from async* function), and at `yield` / `yield*` statements. | 
 |  | 
 | When `_SuspendState._yieldAsyncStar` is called at the beginning of async* function it creates | 
 | a callback closure to resume body of the async* function (via Resume stub), creates and | 
 | returns `Stream`. | 
 |  | 
 | `yield` / `yield*` statements are implemented in the following way: | 
 |  | 
 | ``` | 
 | _AsyncStarStreamController controller = :suspend_state._functionData; | 
 | if (controller.add/addStream(<expr>)) { | 
 |   return; | 
 | } | 
 | if (YieldAsyncStar()) { | 
 |   return; | 
 | } | 
 | ``` | 
 |  | 
 | `_AsyncStarStreamController.add`, `_AsyncStarStreamController.addStream` and YieldAsyncStar stub | 
 | can return `true` to indicate that Stream doesn't have a listener anymore and execution of | 
 | async* function should end. | 
 |  | 
 | Note that YieldAsyncStar stub returns a value passed to a Resume stub when resuming async* | 
 | function, so the 2nd hasListeners check happens right before the async* function is resumed. | 
 |  | 
 | See `StreamingFlowGraphBuilder::BuildYieldStatement` for more details about `yield` / `yield*`. | 
 |  | 
 | ### Await stub | 
 |  | 
 | Async* functions use the same Await stub which is used by async functions. | 
 |  | 
 | ### ReturnAsyncStar stub | 
 |  | 
 | ReturnAsyncStar stub = Return stub which calls `_SuspendState._returnAsyncStar`. | 
 |  | 
 | `_SuspendState._returnAsyncStar` closes the Stream. | 
 |  | 
 | ### Execution flow in async* functions | 
 |  | 
 | The following diagram depicts how the control is passed in a typical async* function: | 
 |  | 
 | ``` | 
 | Caller          Stream<T> foo() async*          Stubs        Dart helper methods | 
 |   | | 
 |   *-------------------> | | 
 |                     (prologue) -------------> InitAsyncStar | 
 |                                                   | | 
 |                                                   *----------> _SuspendState._initAsyncStar | 
 |                                                               (creates _AsyncStarStreamController<T>) | 
 |                                                   | <--------- | 
 |                         | <-----------------------* | 
 |                         * ------------------> YieldAsyncStar | 
 |                                                   | | 
 |                                                   *----------> _SuspendState._yieldAsyncStar | 
 |                                                               (setups resumption) | 
 |                                                               (returns _AsyncStarStreamController.stream) | 
 |                                                   | <--------- | 
 |   | <---------------------------------------------* | 
 |  | 
 | Stream is listened | 
 |   | | 
 |   *------------------------------------------> Resume | 
 |                                                   | | 
 |                   (after prologue) <--------------* | 
 |                         | | 
 |                         | | 
 |                       (yield) --------------------------------> _AsyncStarStreamController.add | 
 |                                                               (adds value to Stream) | 
 |                                                               (checks if there are listeners) | 
 |                         | <----------------------------------- | 
 |                         * ------------------> YieldAsyncStar | 
 |                                                   | | 
 |                                                   *----------> _SuspendState._yieldAsyncStar | 
 |                                                   | <--------- | 
 |   | <---------------------------------------------* | 
 |  | 
 | Micro-task to run async* body | 
 |   | | 
 |   *----------------------------------------------------------> _AsyncStarStreamController.runBody | 
 |                                                               (checks if there are listeners) | 
 |                                                 Resume <------- | 
 |                                                   | | 
 |                     (after yield) <---------------* | 
 |                         | | 
 |                         | | 
 |                       (return) ---------------> ReturnAsyncStar | 
 |                                                   | | 
 |                                                   *----------> _SuspendState._returnAsyncStar | 
 |                                                               (closes _AsyncStarStreamController) | 
 |                                                   | <--------- | 
 |   | <---------------------------------------------* | 
 | ``` | 
 |  | 
 | ## Sync* functions | 
 |  | 
 | See [async_patch.dart](https://github.com/dart-lang/sdk/blob/main/sdk/lib/_internal/vm/lib/async_patch.dart) | 
 | for the corresponding Dart source code. | 
 |  | 
 | Sync* functions use the following customized stubs: | 
 |  | 
 | ### InitSyncStar stub | 
 |  | 
 | InitSyncStar = InitSuspendableFunction stub which calls `_SuspendState._initSyncStar`. | 
 |  | 
 | `_SuspendState._initSyncStar` creates a `_SyncStarIterable<T>` instance which is returned | 
 | from sync* function. | 
 |  | 
 | ### SuspendSyncStarAtStart stub | 
 |  | 
 | SuspendSyncStarAtStart = Suspend stub which calls `_SuspendState._suspendSyncStarAtStart`. | 
 |  | 
 | This stub is used to suspend execution of sync* at the beginning. It is called after | 
 | InitSyncStar in the sync* function prologue. The body of sync* function doesn't run | 
 | until Iterator is not obtained from Iterable (`_SyncStarIterable<T>`) which is returned from | 
 | the sync* function. | 
 |  | 
 | ### CloneSuspendState stub | 
 |  | 
 | This stub creates a copy of SuspendState object. It is used to clone state of sync* | 
 | function (suspended at the beginning) for each Iterator instance obtained from | 
 | Iterable. | 
 |  | 
 | See `StubCodeCompiler::GenerateCloneSuspendStateStub`. | 
 |  | 
 | ### SuspendSyncStarAtYield stub and `yield`/`yield*` | 
 |  | 
 | SuspendSyncStarAtYield = Suspend stub which doesn't call helper Dart methods. | 
 |  | 
 | SuspendSyncStarAtYield is used to implement `yield` / `yield*` statements in sync* functions. | 
 |  | 
 | `yield` / `yield*` statements are implemented in the following way: | 
 |  | 
 | ``` | 
 | _SyncStarIterator iterator = :suspend_state._functionData; | 
 |  | 
 | iterator._current = <expr>;             // yield <expr> | 
 |   OR | 
 | iterator._yieldStarIterable = <expr>;   // yield* <expr> | 
 |  | 
 | SuspendSyncStarAtYield(true); | 
 | ``` | 
 |  | 
 | See `StreamingFlowGraphBuilder::BuildYieldStatement` for more details about `yield` / `yield*`. | 
 |  | 
 | The value passed to SuspendSyncStarAtYield is returned back from the invocation of | 
 | Resume stub. `true` indicates that iteration can continue. | 
 |  | 
 | ### Returning from sync* functions. | 
 |  | 
 | Sync* function do not use Return stubs. Instead, return statements are rewritten to return `false` | 
 | in order to indicate that iteration is finished. | 
 |  | 
 | ### Execution flow in sync* functions | 
 |  | 
 | The following diagram depicts how the control is passed in a typical sync* function: | 
 |  | 
 | ``` | 
 | Caller          Iterable<T> foo() sync*          Stubs        Dart helpers | 
 |   | | 
 |   *-------------------> | | 
 |                     (prologue) -------------> InitSyncStar | 
 |                                                   | | 
 |                                                   *----------> _SuspendState._initSyncStar | 
 |                                                               (creates _SyncStarIterable<T>) | 
 |                                                   | <--------- | 
 |                         | <-----------------------* | 
 |                         * ------------------> SuspendSyncStarAtStart | 
 |                                                   | | 
 |                                                   *----------> _SuspendState._suspendSyncStarAtStart | 
 |                                                               (remembers _SuspendState at start) | 
 |                                                               (returns _SyncStarIterable<T>) | 
 |                                                   | <--------- | 
 |   | <---------------------------------------------* | 
 |  | 
 | Iterable.iterator is called | 
 |   | | 
 |   *----------------------------------------------------------> _SyncStarIterable<T>.iterator | 
 |                                                               (creates _SyncStarIterator<T>) | 
 |                                                                 | | 
 |                                       CloneSuspendState <-------* | 
 |                                       (makes a copy of _SuspendState at start) | 
 |                                                   | | 
 |                                                   *-----------> | | 
 |   | <------------------------------------------------------- (returns _SyncStarIterator<T>) | 
 |  | 
 | Iterator.moveNext is called | 
 |   | | 
 |   *----------------------------------------------------------> _SyncStarIterator<T>.moveNext | 
 |                                                               (iterates over the cached yield* iterator, if any) | 
 |                                                               (resumes sync* body to get the next element) | 
 |                                                 Resume <------- | 
 |                                                   | | 
 |                   (after prologue) <--------------* | 
 |                         | | 
 |                         | | 
 |                       (yield) ---------------> SuspendSyncStarAtYield(true) | 
 |                                                   | | 
 |                                                   *----------> | 
 |                                                               (the next element is cached in _SyncStarIterator<T>._current) | 
 |                                                               (returns true indicating that the next element is available) | 
 |   | <---------------------------------------------------------- | 
 |  | 
 | Iterator.moveNext is called | 
 |   | | 
 |   *----------------------------------------------------------> _SyncStarIterator<T>.moveNext | 
 |                                                               (iterates over the cached yield* iterator, if any) | 
 |                                                               (resumes sync* body to get the next element) | 
 |                                                 Resume <------- | 
 |                                                   | | 
 |                   (after yield) <-----------------* | 
 |                         | | 
 |                         | | 
 |                   (return false) -----------------------------> | 
 |                                                               (returns false indicating that iteration is finished) | 
 |   | <---------------------------------------------------------- | 
 | ``` |