Skip to content

Commit 3764928

Browse files
Clement Skaucommit-bot@chromium.org
Clement Skau
authored andcommitted
[SDK] Switch to isSync to determine if async func. is running sync-async.
Bug: #39525 Change-Id: I1e23a726bf0fbff2c02891e25c714ea599330c47 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/128666 Commit-Queue: Clement Skau <[email protected]> Reviewed-by: Martin Kustermann <[email protected]>
1 parent a3ea61c commit 3764928

File tree

5 files changed

+80
-6
lines changed

5 files changed

+80
-6
lines changed

runtime/tests/vm/dart/causal_stacks/utils.dart

Lines changed: 44 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -792,12 +792,51 @@ Future<void> doTestsLazy() async {
792792
r'^#2 _AsyncAwaitCompleter.start ',
793793
r'^#3 noYields3 \(.*/utils.dart:(53|53:23)\)$',
794794
r'^#4 noYields2 \(.*/utils.dart:(50|50:9)\)$',
795-
r'^<asynchronous suspension>$',
796-
r'^$',
795+
r'^#5 _AsyncAwaitCompleter.start ',
796+
r'^#6 noYields2 \(.*/utils.dart:(49|49:23)\)$',
797+
r'^#7 noYields \(.*/utils.dart:(46|46:9)\)$',
798+
r'^#8 _AsyncAwaitCompleter.start ',
799+
r'^#9 noYields \(.*/utils.dart:(45|45:22)\)$',
797800
];
798-
await doTestAwait(noYields, noYieldsExpected);
799-
await doTestAwaitThen(noYields, noYieldsExpected);
800-
await doTestAwaitCatchError(noYields, noYieldsExpected);
801+
await doTestAwait(
802+
noYields,
803+
noYieldsExpected +
804+
const <String>[
805+
r'^#10 doTestAwait ',
806+
r'^#11 _AsyncAwaitCompleter.start ',
807+
r'^#12 doTestAwait ',
808+
r'^#13 doTestsLazy ',
809+
r'^<asynchronous suspension>$',
810+
r'^#14 main ',
811+
r'^<asynchronous suspension>$',
812+
r'^$',
813+
]);
814+
await doTestAwaitThen(
815+
noYields,
816+
noYieldsExpected +
817+
const <String>[
818+
r'^#10 doTestAwaitThen ',
819+
r'^#11 _AsyncAwaitCompleter.start ',
820+
r'^#12 doTestAwaitThen ',
821+
r'^#13 doTestsLazy ',
822+
r'^<asynchronous suspension>$',
823+
r'^#14 main ',
824+
r'^<asynchronous suspension>$',
825+
r'^$',
826+
]);
827+
await doTestAwaitCatchError(
828+
noYields,
829+
noYieldsExpected +
830+
const <String>[
831+
r'^#10 doTestAwaitCatchError ',
832+
r'^#11 _AsyncAwaitCompleter.start ',
833+
r'^#12 doTestAwaitCatchError ',
834+
r'^#13 doTestsLazy ',
835+
r'^<asynchronous suspension>$',
836+
r'^#14 main ',
837+
r'^<asynchronous suspension>$',
838+
r'^$',
839+
]);
801840

802841
final mixedYieldsExpected = const <String>[
803842
r'^#0 throwAsync \(.*/utils.dart:(21|21:3)\)$',

runtime/vm/stack_trace.cc

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ class CallerClosureFinder {
9999
: receiver_context_(Context::Handle(zone)),
100100
receiver_function_(Function::Handle(zone)),
101101
context_entry_(Object::Handle(zone)),
102+
is_sync(Object::Handle(zone)),
102103
future_(Object::Handle(zone)),
103104
listener_(Object::Handle(zone)),
104105
callback_(Object::Handle(zone)),
@@ -113,6 +114,7 @@ class CallerClosureFinder {
113114
controller_subscription_class(Class::Handle(zone)),
114115
buffering_stream_subscription_class(Class::Handle(zone)),
115116
async_stream_controller_class(Class::Handle(zone)),
117+
completer_is_sync_field(Field::Handle(zone)),
116118
completer_future_field(Field::Handle(zone)),
117119
future_result_or_listeners_field(Field::Handle(zone)),
118120
callback_field(Field::Handle(zone)),
@@ -151,6 +153,9 @@ class CallerClosureFinder {
151153

152154
// Look up fields:
153155
// - async:
156+
completer_is_sync_field =
157+
async_await_completer_class.LookupFieldAllowPrivate(Symbols::isSync());
158+
ASSERT(!completer_is_sync_field.IsNull());
154159
completer_future_field =
155160
async_await_completer_class.LookupFieldAllowPrivate(Symbols::_future());
156161
ASSERT(!completer_future_field.IsNull());
@@ -242,11 +247,37 @@ class CallerClosureFinder {
242247
return Closure::null();
243248
}
244249

250+
bool IsRunningAsync(const Closure& receiver_closure) {
251+
receiver_function_ = receiver_closure.function();
252+
receiver_context_ = receiver_closure.context();
253+
254+
// The async* functions are never started synchronously, they start running
255+
// after the first `listen()` call to its returned `Stream`.
256+
if (receiver_function_.IsAsyncGenClosure()) {
257+
return true;
258+
}
259+
ASSERT(receiver_function_.IsAsyncClosure());
260+
261+
context_entry_ = receiver_context_.At(Context::kAsyncCompleterIndex);
262+
ASSERT(context_entry_.IsInstance());
263+
ASSERT(context_entry_.GetClassId() == async_await_completer_class.id());
264+
265+
const Instance& completer = Instance::Cast(context_entry_);
266+
is_sync = completer.GetField(completer_is_sync_field);
267+
ASSERT(!is_sync.IsNull());
268+
ASSERT(is_sync.IsBool());
269+
// _AsyncAwaitCompleter.isSync indicates whether the future should be
270+
// completed async. or sync., based on whether it has yielded yet.
271+
// isSync is true when the :async_op is running async.
272+
return Bool::Cast(is_sync).value();
273+
}
274+
245275
private:
246276
Context& receiver_context_;
247277
Function& receiver_function_;
248278

249279
Object& context_entry_;
280+
Object& is_sync;
250281
Object& future_;
251282
Object& listener_;
252283
Object& callback_;
@@ -263,6 +294,7 @@ class CallerClosureFinder {
263294
Class& buffering_stream_subscription_class;
264295
Class& async_stream_controller_class;
265296

297+
Field& completer_is_sync_field;
266298
Field& completer_future_field;
267299
Field& future_result_or_listeners_field;
268300
Field& callback_field;
@@ -326,7 +358,7 @@ void StackTraceUtils::CollectFramesLazy(
326358

327359
// If this async function hasn't yielded yet, we're still dealing with a
328360
// normal stack. Continue to next frame as usual.
329-
if (GetYieldIndex(closure) <= 0) {
361+
if (!caller_closure_finder.IsRunningAsync(closure)) {
330362
// Don't advance frame since we already did so just above.
331363
continue;
332364
}

runtime/vm/symbols.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -458,6 +458,7 @@ class ObjectPointerVisitor;
458458
V(identityHashCode, "identityHashCode") \
459459
V(index_temp, ":index_temp") \
460460
V(isPaused, "isPaused") \
461+
V(isSync, "isSync") \
461462
V(last, "last") \
462463
V(match_end_index, ":match_end_index") \
463464
V(match_start_index, ":match_start_index") \

sdk/lib/_internal/vm/lib/async_patch.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ _fatal(msg) native "DartAsync_fatal";
2222
class _AsyncAwaitCompleter<T> implements Completer<T> {
2323
@pragma("vm:entry-point")
2424
final _future = new _Future<T>();
25+
@pragma("vm:entry-point")
2526
bool isSync;
2627

2728
_AsyncAwaitCompleter() : isSync = false;

sdk_nnbd/lib/_internal/vm/lib/async_patch.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ _fatal(msg) native "DartAsync_fatal";
2222
class _AsyncAwaitCompleter<T> implements Completer<T> {
2323
@pragma("vm:entry-point")
2424
final _future = new _Future<T>();
25+
@pragma("vm:entry-point")
2526
bool isSync;
2627

2728
_AsyncAwaitCompleter() : isSync = false;

0 commit comments

Comments
 (0)