Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit b681bfd

Browse files
Clement Skaucommit-bot@chromium.org
authored andcommitted
[VM] Fixes bad reuse/typing of temps in async transform invocations.
For a method invocation temps might get allocated for both the receiver and argument(s) so that: A().foo(await null) becomes: Future<void> tmp0 ... tmp0 = A() // <- Type mismatch. yield ... tmp0 = tmp0.foo(:result) // <- Correct type. This happens because the liveness analysis finds that the (previously dynamic) temps can be reused. Unfortunately 121988 added typing information to these temps, which means they can't be simply reused in all cases. This fix makes the temps dynamic again (by removing the type) but adds unsafecasts to all VariableGets to propagate the know type. Bug: flutter/flutter#51828 Change-Id: I89c82763e0d4f8b102bb55dec3b694d017345517 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/138500 Reviewed-by: Johnni Winther <[email protected]> Commit-Queue: Clement Skau <[email protected]>
1 parent c1ed25d commit b681bfd

10 files changed

+200
-178
lines changed

pkg/front_end/testcases/general/async_nested.dart.strong.transformed.expect

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,9 @@ static method main() → void /* originally async */ {
2727
core::int* :await_jump_var = 0;
2828
dynamic :await_ctx_var;
2929
dynamic :saved_try_context_var0;
30-
self::Node* :async_temporary_0;
31-
self::Node* :async_temporary_1;
32-
self::Node* :async_temporary_2;
30+
dynamic :async_temporary_0;
31+
dynamic :async_temporary_1;
32+
dynamic :async_temporary_2;
3333
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
3434
try {
3535
#L1:
@@ -42,11 +42,11 @@ static method main() → void /* originally async */ {
4242
[yield] let dynamic #t6 = asy::_awaitHelper(asy::Future::value<self::Node*>(new self::Node::•("8", <self::Node*>[])), :async_op_then, :async_op_error, :async_op) in null;
4343
:async_temporary_0 = _in::unsafeCast<self::Node*>(:result);
4444
[yield] let dynamic #t7 = asy::_awaitHelper(asy::Future::value<self::Node*>(new self::Node::•("9", <self::Node*>[])), :async_op_then, :async_op_error, :async_op) in null;
45-
[yield] let dynamic #t8 = asy::_awaitHelper(asy::Future::value<self::Node*>(new self::Node::•("4", <self::Node*>[new self::Node::•("5", <self::Node*>[:async_temporary_1, :async_temporary_0, _in::unsafeCast<self::Node*>(:result)])])), :async_op_then, :async_op_error, :async_op) in null;
45+
[yield] let dynamic #t8 = asy::_awaitHelper(asy::Future::value<self::Node*>(new self::Node::•("4", <self::Node*>[new self::Node::•("5", <self::Node*>[_in::unsafeCast<self::Node*>(:async_temporary_1), _in::unsafeCast<self::Node*>(:async_temporary_0), _in::unsafeCast<self::Node*>(:result)])])), :async_op_then, :async_op_error, :async_op) in null;
4646
[yield] let dynamic #t9 = asy::_awaitHelper(asy::Future::value<self::Node*>(new self::Node::•("3", <self::Node*>[_in::unsafeCast<self::Node*>(:result)])), :async_op_then, :async_op_error, :async_op) in null;
4747
:async_temporary_0 = _in::unsafeCast<self::Node*>(:result);
4848
[yield] let dynamic #t10 = asy::_awaitHelper(asy::Future::value<self::Node*>(new self::Node::•("10", <self::Node*>[])), :async_op_then, :async_op_error, :async_op) in null;
49-
self::Node* node = new self::Node::•("1", <self::Node*>[:async_temporary_2, :async_temporary_0, _in::unsafeCast<self::Node*>(:result)]);
49+
self::Node* node = new self::Node::•("1", <self::Node*>[_in::unsafeCast<self::Node*>(:async_temporary_2), _in::unsafeCast<self::Node*>(:async_temporary_0), _in::unsafeCast<self::Node*>(:result)]);
5050
core::String* actual = node.{self::Node::toSimpleString}() as{TypeError,ForDynamic} core::String*;
5151
core::print(actual);
5252
if(!actual.{core::String::==}(expected)) {

pkg/front_end/testcases/general/await_complex.dart.strong.transformed.expect

Lines changed: 46 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -55,39 +55,39 @@ static method staticMembers() → dynamic /* originally async */ {
5555
core::int* :await_jump_var = 0;
5656
dynamic :await_ctx_var;
5757
dynamic :saved_try_context_var0;
58-
core::int* :async_temporary_0;
59-
core::int* :async_temporary_1;
60-
core::int* :async_temporary_2;
61-
core::int* :async_temporary_3;
62-
core::int* :async_temporary_4;
63-
core::int* :async_temporary_5;
58+
dynamic :async_temporary_0;
59+
dynamic :async_temporary_1;
60+
dynamic :async_temporary_2;
61+
dynamic :async_temporary_3;
62+
dynamic :async_temporary_4;
63+
dynamic :async_temporary_5;
6464
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
6565
try {
6666
#L1:
6767
{
6868
:async_temporary_0 = self::C::staticField;
6969
[yield] let dynamic #t1 = asy::_awaitHelper(self::dummy(), :async_op_then, :async_op_error, :async_op) in null;
70-
core::num* a = :async_temporary_0.{core::num::+}(:result as{TypeError,ForDynamic} core::num*);
70+
core::num* a = _in::unsafeCast<core::int*>(:async_temporary_0).{core::num::+}(:result as{TypeError,ForDynamic} core::num*);
7171
self::expect(2, a);
7272
:async_temporary_1 = self::C::staticField = 1;
7373
[yield] let dynamic #t2 = asy::_awaitHelper(self::dummy(), :async_op_then, :async_op_error, :async_op) in null;
74-
core::num* f = :async_temporary_1.{core::num::+}(:result as{TypeError,ForDynamic} core::num*);
74+
core::num* f = _in::unsafeCast<core::int*>(:async_temporary_1).{core::num::+}(:result as{TypeError,ForDynamic} core::num*);
7575
self::expect(2, f);
7676
:async_temporary_2 = self::C::staticGetter;
7777
[yield] let dynamic #t3 = asy::_awaitHelper(self::dummy(), :async_op_then, :async_op_error, :async_op) in null;
78-
core::num* b = :async_temporary_2.{core::num::+}(:result as{TypeError,ForDynamic} core::num*);
78+
core::num* b = _in::unsafeCast<core::int*>(:async_temporary_2).{core::num::+}(:result as{TypeError,ForDynamic} core::num*);
7979
self::expect(2, b);
8080
:async_temporary_3 = self::C::staticSetter = 1;
8181
[yield] let dynamic #t4 = asy::_awaitHelper(self::dummy(), :async_op_then, :async_op_error, :async_op) in null;
82-
core::num* c = :async_temporary_3.{core::num::+}(:result as{TypeError,ForDynamic} core::num*);
82+
core::num* c = _in::unsafeCast<core::int*>(:async_temporary_3).{core::num::+}(:result as{TypeError,ForDynamic} core::num*);
8383
self::expect(2, c);
8484
:async_temporary_4 = self::C::staticFoo(2);
8585
[yield] let dynamic #t5 = asy::_awaitHelper(self::dummy(), :async_op_then, :async_op_error, :async_op) in null;
86-
core::num* d = :async_temporary_4.{core::num::+}(:result as{TypeError,ForDynamic} core::num*);
86+
core::num* d = _in::unsafeCast<core::int*>(:async_temporary_4).{core::num::+}(:result as{TypeError,ForDynamic} core::num*);
8787
self::expect(3, d);
8888
:async_temporary_5 = self::C::staticField.{core::num::+}(self::C::staticGetter).{core::num::+}(self::C::staticSetter = 1).{core::num::+}(self::C::staticFoo(1));
8989
[yield] let dynamic #t6 = asy::_awaitHelper(self::dummy(), :async_op_then, :async_op_error, :async_op) in null;
90-
core::num* e = :async_temporary_5.{core::num::+}(:result as{TypeError,ForDynamic} core::num*);
90+
core::num* e = _in::unsafeCast<core::int*>(:async_temporary_5).{core::num::+}(:result as{TypeError,ForDynamic} core::num*);
9191
self::expect(5, e);
9292
}
9393
asy::_completeOnAsyncReturn(:async_completer, :return_value);
@@ -111,34 +111,34 @@ static method topLevelMembers() → dynamic /* originally async */ {
111111
core::int* :await_jump_var = 0;
112112
dynamic :await_ctx_var;
113113
dynamic :saved_try_context_var0;
114-
core::int* :async_temporary_0;
115-
core::int* :async_temporary_1;
116-
core::int* :async_temporary_2;
117-
core::int* :async_temporary_3;
118-
core::int* :async_temporary_4;
114+
dynamic :async_temporary_0;
115+
dynamic :async_temporary_1;
116+
dynamic :async_temporary_2;
117+
dynamic :async_temporary_3;
118+
dynamic :async_temporary_4;
119119
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
120120
try {
121121
#L2:
122122
{
123123
:async_temporary_0 = self::globalVariable;
124124
[yield] let dynamic #t7 = asy::_awaitHelper(self::dummy(), :async_op_then, :async_op_error, :async_op) in null;
125-
core::num* a = :async_temporary_0.{core::num::+}(:result as{TypeError,ForDynamic} core::num*);
125+
core::num* a = _in::unsafeCast<core::int*>(:async_temporary_0).{core::num::+}(:result as{TypeError,ForDynamic} core::num*);
126126
self::expect(2, a);
127127
:async_temporary_1 = self::topLevelGetter;
128128
[yield] let dynamic #t8 = asy::_awaitHelper(self::dummy(), :async_op_then, :async_op_error, :async_op) in null;
129-
core::num* b = :async_temporary_1.{core::num::+}(:result as{TypeError,ForDynamic} core::num*);
129+
core::num* b = _in::unsafeCast<core::int*>(:async_temporary_1).{core::num::+}(:result as{TypeError,ForDynamic} core::num*);
130130
self::expect(2, b);
131131
:async_temporary_2 = self::topLevelSetter = 1;
132132
[yield] let dynamic #t9 = asy::_awaitHelper(self::dummy(), :async_op_then, :async_op_error, :async_op) in null;
133-
core::num* c = :async_temporary_2.{core::num::+}(:result as{TypeError,ForDynamic} core::num*);
133+
core::num* c = _in::unsafeCast<core::int*>(:async_temporary_2).{core::num::+}(:result as{TypeError,ForDynamic} core::num*);
134134
self::expect(2, c);
135135
:async_temporary_3 = self::topLevelFoo(1);
136136
[yield] let dynamic #t10 = asy::_awaitHelper(self::dummy(), :async_op_then, :async_op_error, :async_op) in null;
137-
core::num* d = :async_temporary_3.{core::num::+}(:result as{TypeError,ForDynamic} core::num*);
137+
core::num* d = _in::unsafeCast<core::int*>(:async_temporary_3).{core::num::+}(:result as{TypeError,ForDynamic} core::num*);
138138
self::expect(2, d);
139139
:async_temporary_4 = self::globalVariable.{core::num::+}(self::topLevelGetter).{core::num::+}(self::topLevelSetter = 1).{core::num::+}(self::topLevelFoo(1));
140140
[yield] let dynamic #t11 = asy::_awaitHelper(self::dummy(), :async_op_then, :async_op_error, :async_op) in null;
141-
core::num* e = :async_temporary_4.{core::num::+}(:result as{TypeError,ForDynamic} core::num*);
141+
core::num* e = _in::unsafeCast<core::int*>(:async_temporary_4).{core::num::+}(:result as{TypeError,ForDynamic} core::num*);
142142
self::expect(5, e);
143143
}
144144
asy::_completeOnAsyncReturn(:async_completer, :return_value);
@@ -162,35 +162,35 @@ static method instanceMembers() → dynamic /* originally async */ {
162162
core::int* :await_jump_var = 0;
163163
dynamic :await_ctx_var;
164164
dynamic :saved_try_context_var0;
165-
core::int* :async_temporary_0;
166-
core::int* :async_temporary_1;
167-
core::int* :async_temporary_2;
168-
core::int* :async_temporary_3;
169-
core::int* :async_temporary_4;
165+
dynamic :async_temporary_0;
166+
dynamic :async_temporary_1;
167+
dynamic :async_temporary_2;
168+
dynamic :async_temporary_3;
169+
dynamic :async_temporary_4;
170170
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
171171
try {
172172
#L3:
173173
{
174174
self::C* inst = new self::C::•();
175175
:async_temporary_0 = inst.{self::C::field};
176176
[yield] let dynamic #t12 = asy::_awaitHelper(self::dummy(), :async_op_then, :async_op_error, :async_op) in null;
177-
core::num* a = :async_temporary_0.{core::num::+}(:result as{TypeError,ForDynamic} core::num*);
177+
core::num* a = _in::unsafeCast<core::int*>(:async_temporary_0).{core::num::+}(:result as{TypeError,ForDynamic} core::num*);
178178
self::expect(2, a);
179179
:async_temporary_1 = inst.{self::C::getter};
180180
[yield] let dynamic #t13 = asy::_awaitHelper(self::dummy(), :async_op_then, :async_op_error, :async_op) in null;
181-
core::num* b = :async_temporary_1.{core::num::+}(:result as{TypeError,ForDynamic} core::num*);
181+
core::num* b = _in::unsafeCast<core::int*>(:async_temporary_1).{core::num::+}(:result as{TypeError,ForDynamic} core::num*);
182182
self::expect(2, b);
183183
:async_temporary_2 = inst.{self::C::setter} = 1;
184184
[yield] let dynamic #t14 = asy::_awaitHelper(self::dummy(), :async_op_then, :async_op_error, :async_op) in null;
185-
core::num* c = :async_temporary_2.{core::num::+}(:result as{TypeError,ForDynamic} core::num*);
185+
core::num* c = _in::unsafeCast<core::int*>(:async_temporary_2).{core::num::+}(:result as{TypeError,ForDynamic} core::num*);
186186
self::expect(2, c);
187187
:async_temporary_3 = inst.{self::C::foo}(1);
188188
[yield] let dynamic #t15 = asy::_awaitHelper(self::dummy(), :async_op_then, :async_op_error, :async_op) in null;
189-
core::num* d = :async_temporary_3.{core::num::+}(:result as{TypeError,ForDynamic} core::num*);
189+
core::num* d = _in::unsafeCast<core::int*>(:async_temporary_3).{core::num::+}(:result as{TypeError,ForDynamic} core::num*);
190190
self::expect(2, d);
191191
:async_temporary_4 = inst.{self::C::field}.{core::num::+}(inst.{self::C::getter}).{core::num::+}(inst.{self::C::setter} = 1).{core::num::+}(inst.{self::C::foo}(1));
192192
[yield] let dynamic #t16 = asy::_awaitHelper(self::dummy(), :async_op_then, :async_op_error, :async_op) in null;
193-
core::num* e = :async_temporary_4.{core::num::+}(:result as{TypeError,ForDynamic} core::num*);
193+
core::num* e = _in::unsafeCast<core::int*>(:async_temporary_4).{core::num::+}(:result as{TypeError,ForDynamic} core::num*);
194194
self::expect(5, e);
195195
}
196196
asy::_completeOnAsyncReturn(:async_completer, :return_value);
@@ -214,35 +214,35 @@ static method others() → dynamic /* originally async */ {
214214
core::int* :await_jump_var = 0;
215215
dynamic :await_ctx_var;
216216
dynamic :saved_try_context_var0;
217-
core::String* :async_temporary_0;
218-
core::int* :async_temporary_1;
219-
core::int* :async_temporary_2;
220-
core::List<core::int*>* :async_temporary_3;
221-
core::int* :async_temporary_4;
217+
dynamic :async_temporary_0;
218+
dynamic :async_temporary_1;
219+
dynamic :async_temporary_2;
220+
dynamic :async_temporary_3;
221+
dynamic :async_temporary_4;
222222
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
223223
try {
224224
#L4:
225225
{
226226
:async_temporary_0 = self::globalVariable;
227227
[yield] let dynamic #t17 = asy::_awaitHelper(self::dummy(), :async_op_then, :async_op_error, :async_op) in null;
228-
:async_temporary_0 = "${:async_temporary_0} ${:result} ";
228+
:async_temporary_0 = "${_in::unsafeCast<core::int*>(:async_temporary_0)} ${:result} ";
229229
[yield] let dynamic #t18 = asy::_awaitHelper("someString", :async_op_then, :async_op_error, :async_op) in null;
230-
core::String* a = :async_temporary_0.{core::String::+}(_in::unsafeCast<core::String*>(:result));
230+
core::String* a = _in::unsafeCast<core::String*>(:async_temporary_0).{core::String::+}(_in::unsafeCast<core::String*>(:result));
231231
self::expect("1 1 someString", a);
232232
self::C* c = new self::C::•();
233233
:async_temporary_1 = c.{self::C::field};
234234
[yield] let dynamic #t19 = asy::_awaitHelper(self::dummy(), :async_op_then, :async_op_error, :async_op) in null;
235-
core::num* d = :async_temporary_1.{core::num::+}(:result as{TypeError,ForDynamic} core::num*);
235+
core::num* d = _in::unsafeCast<core::int*>(:async_temporary_1).{core::num::+}(:result as{TypeError,ForDynamic} core::num*);
236236
core::int* cnt = 2;
237237
core::List<core::int*>* b = <core::int*>[1, 2, 3];
238238
:async_temporary_3 = b;
239239
:async_temporary_2 = cnt;
240240
[yield] let dynamic #t20 = asy::_awaitHelper(self::dummy(), :async_op_then, :async_op_error, :async_op) in null;
241-
:async_temporary_3.{core::List::[]=}(:async_temporary_2, :result as{TypeError,ForDynamic} core::int*);
241+
_in::unsafeCast<core::List<core::int*>*>(:async_temporary_3).{core::List::[]=}(_in::unsafeCast<core::int*>(:async_temporary_2), :result as{TypeError,ForDynamic} core::int*);
242242
self::expect(1, b.{core::List::[]}(cnt));
243243
:async_temporary_4 = b.{core::List::[]}(0);
244244
[yield] let dynamic #t21 = asy::_awaitHelper(self::dummy(), :async_op_then, :async_op_error, :async_op) in null;
245-
core::num* e = :async_temporary_4.{core::num::+}(:result as{TypeError,ForDynamic} core::num*);
245+
core::num* e = _in::unsafeCast<core::int*>(:async_temporary_4).{core::num::+}(:result as{TypeError,ForDynamic} core::num*);
246246
self::expect(2, e);
247247
}
248248
asy::_completeOnAsyncReturn(:async_completer, :return_value);
@@ -416,8 +416,8 @@ static method controlFlow() → dynamic /* originally async */ {
416416
dynamic :saved_try_context_var3;
417417
dynamic :exception0;
418418
dynamic :stack_trace0;
419-
core::List<dynamic>* :async_temporary_0;
420-
core::List<dynamic>* :async_temporary_1;
419+
dynamic :async_temporary_0;
420+
dynamic :async_temporary_1;
421421
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
422422
try {
423423
#L7:
@@ -631,7 +631,7 @@ static method controlFlow() → dynamic /* originally async */ {
631631
}
632632
:async_temporary_0 = <dynamic>[42];
633633
[yield] let dynamic #t55 = asy::_awaitHelper(testStream1.call().{asy::Stream::toList}(), :async_op_then, :async_op_error, :async_op) in null;
634-
self::expectList(:async_temporary_0, _in::unsafeCast<core::List<core::int*>*>(:result));
634+
self::expectList(_in::unsafeCast<core::List<dynamic>*>(:async_temporary_0), _in::unsafeCast<core::List<core::int*>*>(:result));
635635
function testStream2() → asy::Stream<core::int*>* /* originally async* */ {
636636
asy::_AsyncStarStreamController<core::int*>* :controller;
637637
dynamic :controller_stream;
@@ -670,7 +670,7 @@ static method controlFlow() → dynamic /* originally async */ {
670670
}
671671
:async_temporary_1 = <dynamic>[42];
672672
[yield] let dynamic #t57 = asy::_awaitHelper(testStream2.call().{asy::Stream::toList}(), :async_op_then, :async_op_error, :async_op) in null;
673-
self::expectList(:async_temporary_1, _in::unsafeCast<core::List<core::int*>*>(:result));
673+
self::expectList(_in::unsafeCast<core::List<dynamic>*>(:async_temporary_1), _in::unsafeCast<core::List<core::int*>*>(:result));
674674
}
675675
}
676676
}

pkg/front_end/testcases/general/issue40662.dart.strong.transformed.expect

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,10 @@ static method foo(core::int* x) → dynamic /* originally async */ {
1717
core::int* :await_jump_var = 0;
1818
dynamic :await_ctx_var;
1919
dynamic :saved_try_context_var0;
20-
core::int* :async_temporary_0;
21-
core::int* :async_temporary_1;
20+
dynamic :async_temporary_0;
21+
dynamic :async_temporary_1;
2222
core::List<core::int*>* :async_temporary_2;
23-
core::int* :async_temporary_3;
23+
dynamic :async_temporary_3;
2424
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
2525
try {
2626
#L1:
@@ -30,12 +30,12 @@ static method foo(core::int* x) → dynamic /* originally async */ {
3030
:async_temporary_1 = x.{core::num::+}(1);
3131
:async_temporary_0 = x.{core::num::+}(2);
3232
[yield] let dynamic #t1 = asy::_awaitHelper(null, :async_op_then, :async_op_error, :async_op) in null;
33-
:async_temporary_2 = <core::int*>[:async_temporary_1, :async_temporary_0, _in::unsafeCast<core::Null?>(:result)];
33+
:async_temporary_2 = <core::int*>[_in::unsafeCast<core::int*>(:async_temporary_1), _in::unsafeCast<core::int*>(:async_temporary_0), _in::unsafeCast<core::Null?>(:result)];
3434
}
3535
else {
3636
:async_temporary_2 = null;
3737
}
38-
:return_value = self::bar(:async_temporary_3, :async_temporary_2);
38+
:return_value = self::bar(_in::unsafeCast<core::int*>(:async_temporary_3), :async_temporary_2);
3939
break #L1;
4040
}
4141
asy::_completeOnAsyncReturn(:async_completer, :return_value);

0 commit comments

Comments
 (0)