Skip to content

Commit 68fd2a9

Browse files
askeksacommit-bot@chromium.org
authored andcommitted
[vm/jit] Pessimize type assumption in LoadLocal of covariant parameter.
This avoids unsound optimizations that could arise from loading a parameter before its type had been checked. Affects only unoptimized code. Fixes dart-lang#43464 Some considerations for a cleaner fix are described in dart-lang#43654 Change-Id: I05872e46495313e82e9c516e5f283e1bc4612300 Cq-Do-Not-Cancel-Tryjobs: true Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/164500 Commit-Queue: Aske Simon Christensen <askesc@google.com> Reviewed-by: Martin Kustermann <kustermann@google.com>
1 parent 7d79d21 commit 68fd2a9

File tree

6 files changed

+72
-5
lines changed

6 files changed

+72
-5
lines changed
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
import 'package:expect/expect.dart';
6+
7+
class A {}
8+
9+
abstract class B<T> {
10+
dynamic foo(T a);
11+
}
12+
13+
class C extends B<A> {
14+
dynamic foo(A a) {
15+
return () => a;
16+
}
17+
}
18+
19+
main() {
20+
Expect.throws(() => (C().foo as dynamic)(1));
21+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
import 'package:expect/expect.dart';
6+
7+
class A {}
8+
9+
abstract class B<T> {
10+
dynamic foo(T a);
11+
}
12+
13+
class C extends B<A> {
14+
dynamic foo(A a) {
15+
return () => a;
16+
}
17+
}
18+
19+
main() {
20+
Expect.throws(() => (C().foo as dynamic)(1));
21+
}

runtime/vm/compiler/backend/type_propagator.cc

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1405,6 +1405,12 @@ CompileType StaticCallInstr::ComputeType() const {
14051405
}
14061406

14071407
CompileType LoadLocalInstr::ComputeType() const {
1408+
if (local().needs_covariant_check_in_method()) {
1409+
// We may not yet have checked the actual type of the parameter value.
1410+
// Assuming that the value has the required type can lead to unsound
1411+
// optimizations. See dartbug.com/43464.
1412+
return CompileType::FromCid(kDynamicCid);
1413+
}
14081414
const AbstractType& local_type = local().type();
14091415
TraceStrongModeType(this, local_type);
14101416
return CompileType::FromAbstractType(local_type);

runtime/vm/compiler/frontend/scope_builder.cc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1601,6 +1601,9 @@ void ScopeBuilder::AddVariableDeclarationParameter(
16011601
helper.IsCovariant() ||
16021602
(helper.IsGenericCovariantImpl() &&
16031603
(attrs.has_non_this_uses || attrs.has_tearoff_uses));
1604+
if (needs_covariant_check_in_method) {
1605+
variable->set_needs_covariant_check_in_method();
1606+
}
16041607

16051608
switch (type_check_mode) {
16061609
case kTypeCheckAllParameters:

runtime/vm/parser.cc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,9 @@ void ParsedFunction::AllocateVariables() {
211211
if (variable->is_explicit_covariant_parameter()) {
212212
raw_parameter->set_is_explicit_covariant_parameter();
213213
}
214+
if (variable->needs_covariant_check_in_method()) {
215+
raw_parameter->set_needs_covariant_check_in_method();
216+
}
214217
raw_parameter->set_type_check_mode(variable->type_check_mode());
215218
if (function().HasOptionalParameters()) {
216219
bool ok = scope->AddVariable(raw_parameter);

runtime/vm/scopes.h

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ class LocalVariable : public ZoneAllocated {
9191
is_invisible_(false),
9292
is_captured_parameter_(false),
9393
is_forced_stack_(false),
94-
is_explicit_covariant_parameter_(false),
94+
covariance_mode_(kNotCovariant),
9595
is_late_(false),
9696
is_chained_future_(false),
9797
expected_context_index_(-1),
@@ -147,10 +147,17 @@ class LocalVariable : public ZoneAllocated {
147147
}
148148

149149
bool is_explicit_covariant_parameter() const {
150-
return is_explicit_covariant_parameter_;
150+
return covariance_mode_ == kExplicit;
151151
}
152-
void set_is_explicit_covariant_parameter() {
153-
is_explicit_covariant_parameter_ = true;
152+
void set_is_explicit_covariant_parameter() { covariance_mode_ = kExplicit; }
153+
154+
bool needs_covariant_check_in_method() const {
155+
return covariance_mode_ != kNotCovariant;
156+
}
157+
void set_needs_covariant_check_in_method() {
158+
if (covariance_mode_ == kNotCovariant) {
159+
covariance_mode_ = kImplicit;
160+
}
154161
}
155162

156163
enum TypeCheckMode {
@@ -208,6 +215,12 @@ class LocalVariable : public ZoneAllocated {
208215
bool Equals(const LocalVariable& other) const;
209216

210217
private:
218+
enum CovarianceMode {
219+
kNotCovariant,
220+
kImplicit,
221+
kExplicit,
222+
};
223+
211224
static const int kUninitializedIndex = INT_MIN;
212225

213226
const TokenPosition declaration_pos_;
@@ -228,7 +241,7 @@ class LocalVariable : public ZoneAllocated {
228241
bool is_invisible_;
229242
bool is_captured_parameter_;
230243
bool is_forced_stack_;
231-
bool is_explicit_covariant_parameter_;
244+
CovarianceMode covariance_mode_;
232245
bool is_late_;
233246
bool is_chained_future_;
234247
intptr_t expected_context_index_;

0 commit comments

Comments
 (0)