[SDK] Adds --lazy-async-stack support for async*. Bug: https://github.com/dart-lang/sdk/issues/39525 Change-Id: I53cd334243649901ea8e0f9799d9f41c126e3627 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/126729 Commit-Queue: Clement Skau <cskau@google.com> Reviewed-by: Martin Kustermann <kustermann@google.com>
diff --git a/pkg/kernel/lib/transformations/continuation.dart b/pkg/kernel/lib/transformations/continuation.dart index 367e1e7..bc07276 100644 --- a/pkg/kernel/lib/transformations/continuation.dart +++ b/pkg/kernel/lib/transformations/continuation.dart
@@ -18,6 +18,7 @@ static const asyncCompleter = ':async_completer'; static const awaitContextVar = ':await_ctx_var'; static const asyncStackTraceVar = ':async_stack_trace'; + static const controller = ':controller'; static const controllerStreamVar = ':controller_stream'; static const exceptionParam = ':exception'; static const stackTraceParam = ':stack_trace'; @@ -965,7 +966,8 @@ final elementType = elementTypeFromReturnType(helper.streamClass); // _AsyncStarStreamController<T> :controller; - controllerVariable = new VariableDeclaration(":controller", + controllerVariable = new VariableDeclaration( + ContinuationVariables.controller, type: new InterfaceType(helper.asyncStarStreamControllerClass, staticTypeContext.nullable, [elementType])); statements.add(controllerVariable);
diff --git a/pkg/vm/lib/bytecode/local_vars.dart b/pkg/vm/lib/bytecode/local_vars.dart index ad0d675..0e59577 100644 --- a/pkg/vm/lib/bytecode/local_vars.dart +++ b/pkg/vm/lib/bytecode/local_vars.dart
@@ -19,6 +19,7 @@ // Keep in sync with runtime/vm/object.h:Context::kAwaitJumpVarIndex. const int awaitJumpVarContextIndex = 0; const int asyncCompleterContextIndex = 1; +const int controllerContextIndex = 1; class LocalVariables { final _scopes = new Map<TreeNode, Scope>(); @@ -443,12 +444,17 @@ ._getVarDesc(_currentFrame .getSyntheticVar(ContinuationVariables.awaitJumpVar)) .moveToScope(_currentScope); - } - if (_currentFrame.dartAsyncMarker == AsyncMarker.Async) { - locals - ._getVarDesc(_currentFrame - .getSyntheticVar(ContinuationVariables.asyncCompleter)) - .moveToScope(_currentScope); + if (_currentFrame.dartAsyncMarker == AsyncMarker.Async) { + locals + ._getVarDesc(_currentFrame + .getSyntheticVar(ContinuationVariables.asyncCompleter)) + .moveToScope(_currentScope); + } else if (_currentFrame.dartAsyncMarker == AsyncMarker.AsyncStar) { + locals + ._getVarDesc(_currentFrame + .getSyntheticVar(ContinuationVariables.controller)) + .moveToScope(_currentScope); + } } } @@ -1110,6 +1116,12 @@ assert(locals._getVarDesc(asyncCompleter).index == asyncCompleterContextIndex); } + if (_currentFrame.dartAsyncMarker == AsyncMarker.AsyncStar) { + final controller = + _currentFrame.getSyntheticVar(ContinuationVariables.controller); + _allocateVariable(controller); + assert(locals._getVarDesc(controller).index == controllerContextIndex); + } _allocateParameters(node, function); _allocateSpecialVariables(); @@ -1172,6 +1184,8 @@ assert(locals._getVarDesc(node).index == awaitJumpVarContextIndex); } else if (node.name == ContinuationVariables.asyncCompleter) { assert(locals._getVarDesc(node).index == asyncCompleterContextIndex); + } else if (node.name == ContinuationVariables.controller) { + assert(locals._getVarDesc(node).index == controllerContextIndex); } else { _allocateVariable(node); }
diff --git a/runtime/tests/vm/dart/causal_stacks/utils.dart b/runtime/tests/vm/dart/causal_stacks/utils.dart index 3060172..6d4ccc29 100644 --- a/runtime/tests/vm/dart/causal_stacks/utils.dart +++ b/runtime/tests/vm/dart/causal_stacks/utils.dart
@@ -96,6 +96,37 @@ Future nonAsyncNoStack2() async => Future.value(0).then((_) => throwAsync()); +// ---- +// Scenario: async*: +// ---- + +Future awaitEveryAsyncStarThrowSync() async { + await for (Future v in asyncStarThrowSync()) { + await v; + } +} + +Stream<Future> asyncStarThrowSync() async* { + for (int i = 0; i < 2; i++) { + await i; + yield throwSync(); + } +} + +Future awaitEveryAsyncStarThrowAsync() async { + await for (Future v in asyncStarThrowAsync()) { + await v; + } +} + +Stream<Future> asyncStarThrowAsync() async* { + for (int i = 0; i < 2; i++) { + await i; + yield Future.value(i); + await throwAsync(); + } +} + // Helpers: void assertStack(List<String> expects, StackTrace stackTrace) { @@ -354,6 +385,93 @@ await doTestAwait(nonAsyncNoStack, nonAsyncNoStackExpected); await doTestAwaitThen(nonAsyncNoStack, nonAsyncNoStackExpected); await doTestAwaitCatchError(nonAsyncNoStack, nonAsyncNoStackExpected); + + final asyncStarThrowSyncExpected = const <String>[ + r'^#0 throwSync \(.*/utils.dart:(16|16:3)\)$', + r'^#1 asyncStarThrowSync \(.*/utils.dart:(112|112:11)\)$', + r'^<asynchronous suspension>$', + r'^#2 awaitEveryAsyncStarThrowSync \(.+\)$', + ]; + await doTestAwait( + awaitEveryAsyncStarThrowSync, + asyncStarThrowSyncExpected + + const <String>[ + r'^#3 doTestAwait \(.+\)$', + r'^#4 doTestsCausal \(.+\)$', + r'^<asynchronous suspension>$', + r'^#5 main \(.+\)$', + r'^#6 _startIsolate.<anonymous closure> \(.+\)$', + r'^#7 _RawReceivePortImpl._handleMessage \(.+\)$', + r'^$', + ]); + await doTestAwaitThen( + awaitEveryAsyncStarThrowSync, + asyncStarThrowSyncExpected + + const <String>[ + r'^#3 doTestAwaitThen \(.+\)$', + r'^#4 doTestsCausal \(.+\)$', + r'^<asynchronous suspension>$', + r'^#5 main \(.+\)$', + r'^#6 _startIsolate.<anonymous closure> \(.+\)$', + r'^#7 _RawReceivePortImpl._handleMessage \(.+\)$', + r'^$', + ]); + await doTestAwaitCatchError( + awaitEveryAsyncStarThrowSync, + asyncStarThrowSyncExpected + + const <String>[ + r'^#3 doTestAwaitCatchError \(.+\)$', + r'^#4 doTestsCausal \(.+\)$', + r'^<asynchronous suspension>$', + r'^#5 main \(.+\)$', + r'^#6 _startIsolate.<anonymous closure> \(.+\)$', + r'^#7 _RawReceivePortImpl._handleMessage \(.+\)$', + r'^$', + ]); + + final asyncStarThrowAsyncExpected = const <String>[ + r'^#0 throwAsync \(.*/utils.dart:(21|21:3)\)$', + r'^<asynchronous suspension>$', + r'^#1 asyncStarThrowAsync \(.*/utils.dart:(126|126:11)\)$', + r'^<asynchronous suspension>$', + r'^#2 awaitEveryAsyncStarThrowAsync \(.+\)$', + ]; + await doTestAwait( + awaitEveryAsyncStarThrowAsync, + asyncStarThrowAsyncExpected + + const <String>[ + r'^#3 doTestAwait \(.+\)$', + r'^#4 doTestsCausal \(.+\)$', + r'^<asynchronous suspension>$', + r'^#5 main \(.+\)$', + r'^#6 _startIsolate.<anonymous closure> \(.+\)$', + r'^#7 _RawReceivePortImpl._handleMessage \(.+\)$', + r'^$', + ]); + await doTestAwaitThen( + awaitEveryAsyncStarThrowAsync, + asyncStarThrowAsyncExpected + + const <String>[ + r'^#3 doTestAwaitThen \(.+\)$', + r'^#4 doTestsCausal \(.+\)$', + r'^<asynchronous suspension>$', + r'^#5 main \(.+\)$', + r'^#6 _startIsolate.<anonymous closure> \(.+\)$', + r'^#7 _RawReceivePortImpl._handleMessage \(.+\)$', + r'^$', + ]); + await doTestAwaitCatchError( + awaitEveryAsyncStarThrowAsync, + asyncStarThrowAsyncExpected + + const <String>[ + r'^#3 doTestAwaitCatchError \(.+\)$', + r'^#4 doTestsCausal \(.+\)$', + r'^<asynchronous suspension>$', + r'^#5 main \(.+\)$', + r'^#6 _startIsolate.<anonymous closure> \(.+\)$', + r'^#7 _RawReceivePortImpl._handleMessage \(.+\)$', + r'^$', + ]); } // For: --no-causal-async-stacks @@ -586,6 +704,47 @@ await doTestAwait(nonAsyncNoStack, nonAsyncNoStackExpected); await doTestAwaitThen(nonAsyncNoStack, nonAsyncNoStackExpected); await doTestAwaitCatchError(nonAsyncNoStack, nonAsyncNoStackExpected); + + final asyncStarThrowSyncExpected = const <String>[ + r'^#0 throwSync \(.+/utils.dart:(16|16:3)\)$', + r'^#1 asyncStarThrowSync \(.+/utils.dart:(112|112:11)\)$', + r'^#2 _RootZone.runUnary \(.+\)$', + r'^#3 _FutureListener.handleValue \(.+\)$', + r'^#4 Future._propagateToListeners.handleValueCallback \(.+\)$', + r'^#5 Future._propagateToListeners \(.+\)$', + // TODO(dart-vm): Figure out why this is inconsistent: + r'^#6 Future.(_addListener|_prependListeners).<anonymous closure> \(.+\)$', + r'^#7 _microtaskLoop \(.+\)$', + r'^#8 _startMicrotaskLoop \(.+\)$', + r'^#9 _runPendingImmediateCallback \(.+\)$', + r'^#10 _RawReceivePortImpl._handleMessage \(.+\)$', + r'^$', + ]; + await doTestAwait(awaitEveryAsyncStarThrowSync, asyncStarThrowSyncExpected); + await doTestAwaitThen( + awaitEveryAsyncStarThrowSync, asyncStarThrowSyncExpected); + await doTestAwaitCatchError( + awaitEveryAsyncStarThrowSync, asyncStarThrowSyncExpected); + + final asyncStarThrowAsyncExpected = const <String>[ + r'^#0 throwAsync \(.*/utils.dart:(21|21:3)\)$', + r'^#1 _RootZone.runUnary ', + r'^#2 _FutureListener.handleValue ', + r'^#3 Future._propagateToListeners.handleValueCallback ', + r'^#4 Future._propagateToListeners ', + // TODO(dart-vm): Figure out why this is inconsistent: + r'^#5 Future.(_addListener|_prependListeners).<anonymous closure> ', + r'^#6 _microtaskLoop ', + r'^#7 _startMicrotaskLoop ', + r'^#8 _runPendingImmediateCallback ', + r'^#9 _RawReceivePortImpl._handleMessage ', + r'^$', + ]; + await doTestAwait(awaitEveryAsyncStarThrowAsync, asyncStarThrowAsyncExpected); + await doTestAwaitThen( + awaitEveryAsyncStarThrowAsync, asyncStarThrowAsyncExpected); + await doTestAwaitCatchError( + awaitEveryAsyncStarThrowAsync, asyncStarThrowAsyncExpected); } // For: --lazy-async-stacks @@ -744,4 +903,32 @@ const <String>[ r'^$', ]); + + final asyncStarThrowSyncExpected = const <String>[ + r'^#0 throwSync \(.+/utils.dart:(16|16:3)\)$', + r'^#1 asyncStarThrowSync \(.+/utils.dart:(112|112:11)\)$', + r'^<asynchronous suspension>$', + // Non-visible _onData frame. + r'^<asynchronous suspension>$', + r'^$', + ]; + await doTestAwait(awaitEveryAsyncStarThrowSync, asyncStarThrowSyncExpected); + await doTestAwaitThen( + awaitEveryAsyncStarThrowSync, asyncStarThrowSyncExpected); + await doTestAwaitCatchError( + awaitEveryAsyncStarThrowSync, asyncStarThrowSyncExpected); + + final asyncStarThrowAsyncExpected = const <String>[ + r'^#0 throwAsync \(.*/utils.dart:(21|21:3)\)$', + r'^<asynchronous suspension>$', + r'^#1 asyncStarThrowAsync \(.*/utils.dart:(0|126|126:5)\)$', + r'^<asynchronous suspension>$', + // Non-visible _onData frame. + r'^<asynchronous suspension>$', + ]; + await doTestAwait(awaitEveryAsyncStarThrowAsync, asyncStarThrowAsyncExpected); + await doTestAwaitThen( + awaitEveryAsyncStarThrowAsync, asyncStarThrowAsyncExpected); + await doTestAwaitCatchError( + awaitEveryAsyncStarThrowAsync, asyncStarThrowAsyncExpected); }
diff --git a/runtime/vm/compiler/frontend/scope_builder.cc b/runtime/vm/compiler/frontend/scope_builder.cc index 391a04b..66348aa 100644 --- a/runtime/vm/compiler/frontend/scope_builder.cc +++ b/runtime/vm/compiler/frontend/scope_builder.cc
@@ -1280,7 +1280,8 @@ // This way we can allocate them in the outermost context at fixed indices, // allowing support for --lazy-async-stacks implementation to find awaiters. if (name.Equals(Symbols::AwaitJumpVar()) || - name.Equals(Symbols::AsyncCompleter())) { + name.Equals(Symbols::AsyncCompleter()) || + name.Equals(Symbols::Controller())) { scope_->parent()->AddVariable(variable); } else { scope_->AddVariable(variable);
diff --git a/runtime/vm/object.h b/runtime/vm/object.h index 402e025e..bc8e461 100644 --- a/runtime/vm/object.h +++ b/runtime/vm/object.h
@@ -6036,6 +6036,7 @@ static const intptr_t kAwaitJumpVarIndex = 0; static const intptr_t kAsyncCompleterIndex = 1; + static const intptr_t kControllerIndex = 1; static intptr_t variable_offset(intptr_t context_index) { return OFFSET_OF_RETURNED_VALUE(RawContext, data) +
diff --git a/runtime/vm/scopes.cc b/runtime/vm/scopes.cc index 27031de..bd68c5e 100644 --- a/runtime/vm/scopes.cc +++ b/runtime/vm/scopes.cc
@@ -210,6 +210,7 @@ LocalVariable* await_jump_var = nullptr; LocalVariable* async_completer = nullptr; + LocalVariable* controller = nullptr; for (intptr_t i = 0; i < num_variables(); i++) { LocalVariable* variable = VariableAt(i); if (variable->owner() == this) { @@ -218,6 +219,8 @@ await_jump_var = variable; } else if (variable->name().Equals(Symbols::AsyncCompleter())) { async_completer = variable; + } else if (variable->name().Equals(Symbols::Controller())) { + controller = variable; } } } @@ -234,6 +237,11 @@ *found_captured_variables = true; ASSERT(async_completer->index().value() == Context::kAsyncCompleterIndex); } + if (controller != nullptr) { + AllocateContextVariable(controller, &context_owner); + *found_captured_variables = true; + ASSERT(controller->index().value() == Context::kControllerIndex); + } while (pos < num_parameters) { LocalVariable* parameter = VariableAt(pos); @@ -263,7 +271,8 @@ if (variable->owner() == this) { if (variable->is_captured()) { // Skip the two variables already pre-allocated above. - if (variable != await_jump_var && variable != async_completer) { + if (variable != await_jump_var && variable != async_completer && + variable != controller) { AllocateContextVariable(variable, &context_owner); *found_captured_variables = true; }
diff --git a/runtime/vm/stack_trace.cc b/runtime/vm/stack_trace.cc index ed28773..9581646 100644 --- a/runtime/vm/stack_trace.cc +++ b/runtime/vm/stack_trace.cc
@@ -11,6 +11,10 @@ namespace dart { +// Keep in sync with +// sdk/lib/async/stream_controller.dart:_StreamController._STATE_SUBSCRIBED. +const intptr_t kStreamController_StateSubscribed = 1; + RawClosure* FindClosureInFrame(RawObject** last_object_in_caller, const Function& function, bool is_interpreted) { @@ -98,14 +102,27 @@ future_(Object::Handle(zone)), listener_(Object::Handle(zone)), callback_(Object::Handle(zone)), + controller_(Object::Handle(zone)), + state_(Object::Handle(zone)), + var_data_(Object::Handle(zone)), future_impl_class(Class::Handle(zone)), async_await_completer_class(Class::Handle(zone)), future_listener_class(Class::Handle(zone)), + async_start_stream_controller_class(Class::Handle(zone)), + stream_controller_class(Class::Handle(zone)), + controller_subscription_class(Class::Handle(zone)), + buffering_stream_subscription_class(Class::Handle(zone)), + async_stream_controller_class(Class::Handle(zone)), completer_future_field(Field::Handle(zone)), future_result_or_listeners_field(Field::Handle(zone)), - callback_field(Field::Handle(zone)) { + callback_field(Field::Handle(zone)), + controller_controller_field(Field::Handle(zone)), + var_data_field(Field::Handle(zone)), + state_field(Field::Handle(zone)), + on_data_field(Field::Handle(zone)) { const auto& async_lib = Library::Handle(zone, Library::AsyncLibrary()); - // Look up classes. + // Look up classes: + // - async: future_impl_class = async_lib.LookupClassAllowPrivate(Symbols::FutureImpl()); ASSERT(!future_impl_class.IsNull()); @@ -115,7 +132,25 @@ future_listener_class = async_lib.LookupClassAllowPrivate(Symbols::_FutureListener()); ASSERT(!future_listener_class.IsNull()); - // Look up fields. + // - async*: + async_start_stream_controller_class = async_lib.LookupClassAllowPrivate( + Symbols::_AsyncStarStreamController()); + ASSERT(!async_start_stream_controller_class.IsNull()); + stream_controller_class = + async_lib.LookupClassAllowPrivate(Symbols::_StreamController()); + ASSERT(!stream_controller_class.IsNull()); + async_stream_controller_class = + async_lib.LookupClassAllowPrivate(Symbols::_AsyncStreamController()); + ASSERT(!async_stream_controller_class.IsNull()); + controller_subscription_class = + async_lib.LookupClassAllowPrivate(Symbols::_ControllerSubscription()); + ASSERT(!controller_subscription_class.IsNull()); + buffering_stream_subscription_class = async_lib.LookupClassAllowPrivate( + Symbols::_BufferingStreamSubscription()); + ASSERT(!buffering_stream_subscription_class.IsNull()); + + // Look up fields: + // - async: completer_future_field = async_await_completer_class.LookupFieldAllowPrivate(Symbols::_future()); ASSERT(!completer_future_field.IsNull()); @@ -126,18 +161,24 @@ callback_field = future_listener_class.LookupFieldAllowPrivate(Symbols::callback()); ASSERT(!callback_field.IsNull()); + // - async*: + controller_controller_field = + async_start_stream_controller_class.LookupFieldAllowPrivate( + Symbols::controller()); + ASSERT(!controller_controller_field.IsNull()); + state_field = + stream_controller_class.LookupFieldAllowPrivate(Symbols::_state()); + ASSERT(!state_field.IsNull()); + var_data_field = + stream_controller_class.LookupFieldAllowPrivate(Symbols::_varData()); + ASSERT(!var_data_field.IsNull()); + on_data_field = buffering_stream_subscription_class.LookupFieldAllowPrivate( + Symbols::_onData()); + ASSERT(!on_data_field.IsNull()); } - RawClosure* FindCaller(const Closure& receiver_closure) { - receiver_function_ = receiver_closure.function(); - if (!receiver_function_.IsAsyncClosure() && - !receiver_function_.IsAsyncGenClosure()) { - return Closure::null(); - } - - receiver_context_ = receiver_closure.context(); - context_entry_ = receiver_context_.At(Context::kAsyncCompleterIndex); - + RawClosure* FindCallerInAsyncClosure(const Context& receiver_context) { + context_entry_ = receiver_context.At(Context::kAsyncCompleterIndex); ASSERT(context_entry_.IsInstance()); ASSERT(context_entry_.GetClassId() == async_await_completer_class.id()); @@ -162,20 +203,73 @@ return Closure::Cast(callback_).raw(); } + RawClosure* FindCallerInAsyncGenClosure(const Context& receiver_context) { + context_entry_ = receiver_context.At(Context::kControllerIndex); + ASSERT(context_entry_.IsInstance()); + ASSERT(context_entry_.GetClassId() == + async_start_stream_controller_class.id()); + + const Instance& controller = Instance::Cast(context_entry_); + controller_ = controller.GetField(controller_controller_field); + ASSERT(!controller_.IsNull()); + ASSERT(controller_.GetClassId() == async_stream_controller_class.id()); + + state_ = Instance::Cast(controller_).GetField(state_field); + ASSERT(state_.IsSmi()); + if (Smi::Cast(state_).Value() != kStreamController_StateSubscribed) { + return Closure::null(); + } + + var_data_ = Instance::Cast(controller_).GetField(var_data_field); + ASSERT(var_data_.GetClassId() == controller_subscription_class.id()); + + callback_ = Instance::Cast(var_data_).GetField(on_data_field); + ASSERT(callback_.IsClosure()); + + return Closure::Cast(callback_).raw(); + } + + RawClosure* FindCaller(const Closure& receiver_closure) { + receiver_function_ = receiver_closure.function(); + receiver_context_ = receiver_closure.context(); + + if (receiver_function_.IsAsyncClosure()) { + return FindCallerInAsyncClosure(receiver_context_); + } else if (receiver_function_.IsAsyncGenClosure()) { + return FindCallerInAsyncGenClosure(receiver_context_); + } + + return Closure::null(); + } + private: Context& receiver_context_; Function& receiver_function_; + Object& context_entry_; Object& future_; Object& listener_; Object& callback_; + Object& controller_; + Object& state_; + Object& var_data_; Class& future_impl_class; Class& async_await_completer_class; Class& future_listener_class; + Class& async_start_stream_controller_class; + Class& stream_controller_class; + Class& controller_subscription_class; + Class& buffering_stream_subscription_class; + Class& async_stream_controller_class; + Field& completer_future_field; Field& future_result_or_listeners_field; Field& callback_field; + Field& controller_controller_field; + Field& var_data_field; + Field& state_field; + Field& on_data_field; }; void StackTraceUtils::CollectFramesLazy(
diff --git a/runtime/vm/symbols.h b/runtime/vm/symbols.h index ff63c44..3f47d8f 100644 --- a/runtime/vm/symbols.h +++ b/runtime/vm/symbols.h
@@ -61,6 +61,7 @@ V(ConstructorStacktracePrefix, "new ") \ V(Context, "Context") \ V(ContextScope, "ContextScope") \ + V(Controller, ":controller") \ V(ControllerStream, ":controller_stream") \ V(Current, "current") \ V(CurrentContextVar, ":current_context_var") \ @@ -252,6 +253,7 @@ V(StackTraceParameter, ":stack_trace") \ V(StackTraceVar, ":stack_trace_var") \ V(Stream, "stream") \ + V(StreamController, "StreamController") \ V(StreamIterator, "StreamIterator") \ V(StreamIteratorConstructor, "StreamIterator.") \ V(StringBase, "_StringBase") \ @@ -300,7 +302,9 @@ V(_AsyncStarListenHelper, "_asyncStarListenHelper") \ V(_AsyncStarStreamController, "_AsyncStarStreamController") \ V(_AsyncStarStreamControllerConstructor, "_AsyncStarStreamController.") \ + V(_AsyncStreamController, "_AsyncStreamController") \ V(_Awaiter, "_awaiter") \ + V(_BufferingStreamSubscription, "_BufferingStreamSubscription") \ V(_ByteBuffer, "_ByteBuffer") \ V(_ByteBufferDot_New, "_ByteBuffer._New") \ V(_ByteDataView, "_ByteDataView") \ @@ -311,6 +315,7 @@ V(_CombinatorMirror, "_CombinatorMirror") \ V(_CompileTimeError, "_CompileTimeError") \ V(_CompleteOnAsyncReturn, "_completeOnAsyncReturn") \ + V(_ControllerSubscription, "_ControllerSubscription") \ V(_DeletedEnumPrefix, "Deleted enum value from ") \ V(_DeletedEnumSentinel, "_deleted_enum_sentinel") \ V(_Double, "_Double") \ @@ -386,6 +391,7 @@ V(_SourceLocation, "_SourceLocation") \ V(_SpecialTypeMirror, "_SpecialTypeMirror") \ V(_StackTrace, "_StackTrace") \ + V(_StreamController, "_StreamController") \ V(_StreamImpl, "_StreamImpl") \ V(_String, "String") \ V(_SyncIterable, "_SyncIterable") \ @@ -424,6 +430,7 @@ V(_instanceOf, "_instanceOf") \ V(_lookupHandler, "_lookupHandler") \ V(_name, "_name") \ + V(_onData, "_onData") \ V(_rehashObjects, "_rehashObjects") \ V(_resultOrListeners, "_resultOrListeners") \ V(_runExtension, "_runExtension") \ @@ -434,6 +441,7 @@ V(_simpleInstanceOfTrue, "_simpleInstanceOfTrue") \ V(_stackTrace, "_stackTrace") \ V(_state, "_state") \ + V(_varData, "_varData") \ V(_wordCharacterMap, "_wordCharacterMap") \ V(add, "add") \ V(callback, "callback") \ @@ -442,6 +450,7 @@ V(char_in_capture, ":char_in_capture") \ V(char_in_match, ":char_in_match") \ V(clear, "clear") \ + V(controller, "controller") \ V(current_character, ":current_character") \ V(current_position, ":current_position") \ V(getID, "getID") \
diff --git a/sdk/lib/_internal/vm/lib/async_patch.dart b/sdk/lib/_internal/vm/lib/async_patch.dart index 374947d..c4266f4 100644 --- a/sdk/lib/_internal/vm/lib/async_patch.dart +++ b/sdk/lib/_internal/vm/lib/async_patch.dart
@@ -134,6 +134,7 @@ // async* generator functions. @pragma("vm:entry-point") class _AsyncStarStreamController<T> { + @pragma("vm:entry-point") StreamController<T> controller; Function asyncStarBody; bool isAdding = false;
diff --git a/sdk/lib/async/stream_controller.dart b/sdk/lib/async/stream_controller.dart index f2854a9..50e9aa3 100644 --- a/sdk/lib/async/stream_controller.dart +++ b/sdk/lib/async/stream_controller.dart
@@ -409,7 +409,12 @@ /** The controller is in its initial state with no subscription. */ static const int _STATE_INITIAL = 0; - /** The controller has a subscription, but hasn't been closed or canceled. */ + /** + * The controller has a subscription, but hasn't been closed or canceled. + * + * Keep in sync with + * runtime/vm/stack_trace.cc:kStreamController_StateSubscribed. + */ static const int _STATE_SUBSCRIBED = 1; /** The subscription is canceled. */ static const int _STATE_CANCELED = 2; @@ -447,9 +452,11 @@ * * When [_state] is [_STATE_CANCELED] the field is currently not used. */ + @pragma("vm:entry-point") var _varData; /** Current state of the controller. */ + @pragma("vm:entry-point") int _state = _STATE_INITIAL; /**
diff --git a/sdk/lib/async/stream_impl.dart b/sdk/lib/async/stream_impl.dart index b3969fc..0b7cc5a 100644 --- a/sdk/lib/async/stream_impl.dart +++ b/sdk/lib/async/stream_impl.dart
@@ -89,6 +89,7 @@ static const int _STATE_PAUSE_COUNT = 128; /* Event handlers provided in constructor. */ + @pragma("vm:entry-point") _DataHandler<T> _onData; Function _onError; _DoneHandler _onDone;
diff --git a/sdk_nnbd/lib/_internal/vm/lib/async_patch.dart b/sdk_nnbd/lib/_internal/vm/lib/async_patch.dart index 2edf7c2..fa10ad4 100644 --- a/sdk_nnbd/lib/_internal/vm/lib/async_patch.dart +++ b/sdk_nnbd/lib/_internal/vm/lib/async_patch.dart
@@ -134,6 +134,7 @@ // async* generator functions. @pragma("vm:entry-point") class _AsyncStarStreamController<T> { + @pragma("vm:entry-point") StreamController<T> controller; Function asyncStarBody; bool isAdding = false;
diff --git a/sdk_nnbd/lib/async/stream_controller.dart b/sdk_nnbd/lib/async/stream_controller.dart index 9303b86..6f09d5d 100644 --- a/sdk_nnbd/lib/async/stream_controller.dart +++ b/sdk_nnbd/lib/async/stream_controller.dart
@@ -407,7 +407,12 @@ /** The controller is in its initial state with no subscription. */ static const int _STATE_INITIAL = 0; - /** The controller has a subscription, but hasn't been closed or canceled. */ + /** + * The controller has a subscription, but hasn't been closed or canceled. + * + * Keep in sync with + * runtime/vm/stack_trace.cc:kStreamController_StateSubscribed. + */ static const int _STATE_SUBSCRIBED = 1; /** The subscription is canceled. */ static const int _STATE_CANCELED = 2; @@ -446,9 +451,11 @@ * When [_state] is [_STATE_CANCELED] the field is currently not used, * and will contain `null`. */ + @pragma("vm:entry-point") Object? _varData; /** Current state of the controller. */ + @pragma("vm:entry-point") int _state = _STATE_INITIAL; /**
diff --git a/sdk_nnbd/lib/async/stream_impl.dart b/sdk_nnbd/lib/async/stream_impl.dart index 5011a82..f8a4437 100644 --- a/sdk_nnbd/lib/async/stream_impl.dart +++ b/sdk_nnbd/lib/async/stream_impl.dart
@@ -87,6 +87,7 @@ static const int _STATE_PAUSE_COUNT = 128; /* Event handlers provided in constructor. */ + @pragma("vm:entry-point") _DataHandler<T> _onData; Function _onError; _DoneHandler _onDone;