[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 https://github.com/dart-lang/sdk/issues/43464

Some considerations for a cleaner fix are described in
https://github.com/dart-lang/sdk/issues/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>
This commit is contained in:
Aske Simon Christensen
2020-10-02 16:17:58 +00:00
committed by commit-bot@chromium.org
parent 7d79d215db
commit 68fd2a9d52
6 changed files with 72 additions and 5 deletions
@@ -0,0 +1,21 @@
// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'package:expect/expect.dart';
class A {}
abstract class B<T> {
dynamic foo(T a);
}
class C extends B<A> {
dynamic foo(A a) {
return () => a;
}
}
main() {
Expect.throws(() => (C().foo as dynamic)(1));
}
@@ -0,0 +1,21 @@
// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'package:expect/expect.dart';
class A {}
abstract class B<T> {
dynamic foo(T a);
}
class C extends B<A> {
dynamic foo(A a) {
return () => a;
}
}
main() {
Expect.throws(() => (C().foo as dynamic)(1));
}
@@ -1405,6 +1405,12 @@ CompileType StaticCallInstr::ComputeType() const {
}
CompileType LoadLocalInstr::ComputeType() const {
if (local().needs_covariant_check_in_method()) {
// We may not yet have checked the actual type of the parameter value.
// Assuming that the value has the required type can lead to unsound
// optimizations. See dartbug.com/43464.
return CompileType::FromCid(kDynamicCid);
}
const AbstractType& local_type = local().type();
TraceStrongModeType(this, local_type);
return CompileType::FromAbstractType(local_type);
@@ -1601,6 +1601,9 @@ void ScopeBuilder::AddVariableDeclarationParameter(
helper.IsCovariant() ||
(helper.IsGenericCovariantImpl() &&
(attrs.has_non_this_uses || attrs.has_tearoff_uses));
if (needs_covariant_check_in_method) {
variable->set_needs_covariant_check_in_method();
}
switch (type_check_mode) {
case kTypeCheckAllParameters:
+3
View File
@@ -211,6 +211,9 @@ void ParsedFunction::AllocateVariables() {
if (variable->is_explicit_covariant_parameter()) {
raw_parameter->set_is_explicit_covariant_parameter();
}
if (variable->needs_covariant_check_in_method()) {
raw_parameter->set_needs_covariant_check_in_method();
}
raw_parameter->set_type_check_mode(variable->type_check_mode());
if (function().HasOptionalParameters()) {
bool ok = scope->AddVariable(raw_parameter);
+18 -5
View File
@@ -91,7 +91,7 @@ class LocalVariable : public ZoneAllocated {
is_invisible_(false),
is_captured_parameter_(false),
is_forced_stack_(false),
is_explicit_covariant_parameter_(false),
covariance_mode_(kNotCovariant),
is_late_(false),
is_chained_future_(false),
expected_context_index_(-1),
@@ -147,10 +147,17 @@ class LocalVariable : public ZoneAllocated {
}
bool is_explicit_covariant_parameter() const {
return is_explicit_covariant_parameter_;
return covariance_mode_ == kExplicit;
}
void set_is_explicit_covariant_parameter() {
is_explicit_covariant_parameter_ = true;
void set_is_explicit_covariant_parameter() { covariance_mode_ = kExplicit; }
bool needs_covariant_check_in_method() const {
return covariance_mode_ != kNotCovariant;
}
void set_needs_covariant_check_in_method() {
if (covariance_mode_ == kNotCovariant) {
covariance_mode_ = kImplicit;
}
}
enum TypeCheckMode {
@@ -208,6 +215,12 @@ class LocalVariable : public ZoneAllocated {
bool Equals(const LocalVariable& other) const;
private:
enum CovarianceMode {
kNotCovariant,
kImplicit,
kExplicit,
};
static const int kUninitializedIndex = INT_MIN;
const TokenPosition declaration_pos_;
@@ -228,7 +241,7 @@ class LocalVariable : public ZoneAllocated {
bool is_invisible_;
bool is_captured_parameter_;
bool is_forced_stack_;
bool is_explicit_covariant_parameter_;
CovarianceMode covariance_mode_;
bool is_late_;
bool is_chained_future_;
intptr_t expected_context_index_;