Skip to content

Commit

Permalink
[vm/aot] Attach unboxing info to unreachable members
Browse files Browse the repository at this point in the history
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 #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>
  • Loading branch information
alexmarkov authored and commit-bot@chromium.org committed Jan 6, 2021
1 parent e5ed69d commit 3bef6cf
Show file tree
Hide file tree
Showing 3 changed files with 91 additions and 31 deletions.
60 changes: 29 additions & 31 deletions pkg/vm/lib/transformations/type_flow/transformer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -313,13 +313,6 @@ class AnnotateKernel extends RecursiveVisitor<Null> {
if (_typeFlowAnalysis.isMemberUsed(member)) {
if (member is Field) {
_setInferredType(member, _typeFlowAnalysis.fieldType(member));

final unboxingInfoMetadata =
_unboxingInfo.getUnboxingInfoOfMember(member);
if (unboxingInfoMetadata != null &&
!unboxingInfoMetadata.isFullyBoxed) {
_unboxingInfoMetadata.mapping[member] = unboxingInfoMetadata;
}
} else {
Args<Type> argTypes = _typeFlowAnalysis.argumentTypes(member);
final uncheckedParameters =
Expand Down Expand Up @@ -350,36 +343,41 @@ class AnnotateKernel extends RecursiveVisitor<Null> {
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.
}
} else if (!member.isAbstract &&
!fieldMorpher.isExtraMemberWithReachableBody(member)) {
_setUnreachable(member);
} else 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.returnInfo = UnboxingInfoMetadata.kBoxed;
}
for (int i = 0; i < unboxingInfoMetadata.unboxedArgsInfo.length; i++) {
if (unboxingInfoMetadata.unboxedArgsInfo[i] ==
if (unboxingInfoMetadata != null && !unboxingInfoMetadata.isFullyBoxed) {
_unboxingInfoMetadata.mapping[member] = unboxingInfoMetadata;
}
} else {
if (!member.isAbstract &&
!fieldMorpher.isExtraMemberWithReachableBody(member)) {
_setUnreachable(member);
}

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.unboxedArgsInfo[i] =
UnboxingInfoMetadata.kBoxed;
unboxingInfoMetadata.returnInfo = 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;
}
}
}
Expand Down
31 changes: 31 additions & 0 deletions runtime/tests/vm/dart/regress_44563_test.dart
Original file line number Diff line number Diff line change
@@ -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 changes: 31 additions & 0 deletions runtime/tests/vm/dart_2/regress_44563_test.dart
Original file line number Diff line number Diff line change
@@ -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);
}

0 comments on commit 3bef6cf

Please sign in to comment.