[vm/aot] Attach unboxing info to unreachable members

Unreachable members could be used as interface targets of dispatch
table calls, so they should have correct unboxing metadata.
This change fixes attaching unboxing info to such members.

TEST=runtime/tests/vm/dart/regress_44563_test.dart

Fixes https://github.com/dart-lang/sdk/issues/44563

Change-Id: I5da6a8d07048904eb94b05bfba11bdf72d655e12
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/177621
Reviewed-by: Aske Simon Christensen <askesc@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
Commit-Queue: Alexander Markov <alexmarkov@google.com>
This commit is contained in:
Alexander Markov 2021-01-06 18:12:51 +00:00 committed by commit-bot@chromium.org
parent e5ed69d04d
commit 3bef6cf639
3 changed files with 91 additions and 31 deletions

View file

@ -313,13 +313,6 @@ class AnnotateKernel extends RecursiveVisitor<Null> {
if (_typeFlowAnalysis.isMemberUsed(member)) { if (_typeFlowAnalysis.isMemberUsed(member)) {
if (member is Field) { if (member is Field) {
_setInferredType(member, _typeFlowAnalysis.fieldType(member)); _setInferredType(member, _typeFlowAnalysis.fieldType(member));
final unboxingInfoMetadata =
_unboxingInfo.getUnboxingInfoOfMember(member);
if (unboxingInfoMetadata != null &&
!unboxingInfoMetadata.isFullyBoxed) {
_unboxingInfoMetadata.mapping[member] = unboxingInfoMetadata;
}
} else { } else {
Args<Type> argTypes = _typeFlowAnalysis.argumentTypes(member); Args<Type> argTypes = _typeFlowAnalysis.argumentTypes(member);
final uncheckedParameters = final uncheckedParameters =
@ -350,36 +343,41 @@ class AnnotateKernel extends RecursiveVisitor<Null> {
skipCheck: uncheckedParameters.contains(param)); skipCheck: uncheckedParameters.contains(param));
} }
final unboxingInfoMetadata =
_unboxingInfo.getUnboxingInfoOfMember(member);
if (unboxingInfoMetadata != null &&
!unboxingInfoMetadata.isFullyBoxed) {
_unboxingInfoMetadata.mapping[member] = unboxingInfoMetadata;
}
// TODO(alexmarkov): figure out how to pass receiver type. // TODO(alexmarkov): figure out how to pass receiver type.
} }
} else if (!member.isAbstract &&
!fieldMorpher.isExtraMemberWithReachableBody(member)) {
_setUnreachable(member);
} else if (member is! Field) {
final unboxingInfoMetadata = final unboxingInfoMetadata =
_unboxingInfo.getUnboxingInfoOfMember(member); _unboxingInfo.getUnboxingInfoOfMember(member);
if (unboxingInfoMetadata != null) { if (unboxingInfoMetadata != null && !unboxingInfoMetadata.isFullyBoxed) {
// Check for partitions that only have abstract methods should be marked as boxed. _unboxingInfoMetadata.mapping[member] = unboxingInfoMetadata;
if (unboxingInfoMetadata.returnInfo == }
UnboxingInfoMetadata.kUnboxingCandidate) { } else {
unboxingInfoMetadata.returnInfo = UnboxingInfoMetadata.kBoxed; if (!member.isAbstract &&
} !fieldMorpher.isExtraMemberWithReachableBody(member)) {
for (int i = 0; i < unboxingInfoMetadata.unboxedArgsInfo.length; i++) { _setUnreachable(member);
if (unboxingInfoMetadata.unboxedArgsInfo[i] == }
if (member is! Field) {
final unboxingInfoMetadata =
_unboxingInfo.getUnboxingInfoOfMember(member);
if (unboxingInfoMetadata != null) {
// Check for partitions that only have abstract methods should be marked as boxed.
if (unboxingInfoMetadata.returnInfo ==
UnboxingInfoMetadata.kUnboxingCandidate) { UnboxingInfoMetadata.kUnboxingCandidate) {
unboxingInfoMetadata.unboxedArgsInfo[i] = unboxingInfoMetadata.returnInfo = UnboxingInfoMetadata.kBoxed;
UnboxingInfoMetadata.kBoxed; }
for (int i = 0;
i < unboxingInfoMetadata.unboxedArgsInfo.length;
i++) {
if (unboxingInfoMetadata.unboxedArgsInfo[i] ==
UnboxingInfoMetadata.kUnboxingCandidate) {
unboxingInfoMetadata.unboxedArgsInfo[i] =
UnboxingInfoMetadata.kBoxed;
}
}
if (!unboxingInfoMetadata.isFullyBoxed) {
_unboxingInfoMetadata.mapping[member] = unboxingInfoMetadata;
} }
}
if (!unboxingInfoMetadata.isFullyBoxed) {
_unboxingInfoMetadata.mapping[member] = unboxingInfoMetadata;
} }
} }
} }

View file

@ -0,0 +1,31 @@
// Copyright (c) 2021, 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.
// Verifies that unboxing info is attached to a member with unreachable body,
// which is still used as an interface target.
// Regression test for https://github.com/dart-lang/sdk/issues/44563.
import 'package:expect/expect.dart';
class BaseClass {
int get value => 0;
}
class Class1 extends BaseClass {
@pragma('vm:never-inline')
int get value => 1;
}
class Class2 extends BaseClass {
@pragma('vm:never-inline')
int get value => 2;
}
bool nonConstantCondition = int.parse("1") == 1;
void main() {
BaseClass obj = BaseClass();
obj = nonConstantCondition ? Class1() : Class2();
Expect.equals(1, obj.value);
}

View file

@ -0,0 +1,31 @@
// Copyright (c) 2021, 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.
// Verifies that unboxing info is attached to a member with unreachable body,
// which is still used as an interface target.
// Regression test for https://github.com/dart-lang/sdk/issues/44563.
import 'package:expect/expect.dart';
class BaseClass {
int get value => 0;
}
class Class1 extends BaseClass {
@pragma('vm:never-inline')
int get value => 1;
}
class Class2 extends BaseClass {
@pragma('vm:never-inline')
int get value => 2;
}
bool nonConstantCondition = int.parse("1") == 1;
void main() {
BaseClass obj = BaseClass();
obj = nonConstantCondition ? Class1() : Class2();
Expect.equals(1, obj.value);
}