mirror of
https://github.com/dart-lang/sdk
synced 2024-11-02 06:20:13 +00:00
[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:
parent
e5ed69d04d
commit
3bef6cf639
3 changed files with 91 additions and 31 deletions
|
@ -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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
31
runtime/tests/vm/dart/regress_44563_test.dart
Normal file
31
runtime/tests/vm/dart/regress_44563_test.dart
Normal 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);
|
||||||
|
}
|
31
runtime/tests/vm/dart_2/regress_44563_test.dart
Normal file
31
runtime/tests/vm/dart_2/regress_44563_test.dart
Normal 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);
|
||||||
|
}
|
Loading…
Reference in a new issue