Skip to content

Commit a4b3a85

Browse files
mralephcommit-bot@chromium.org
authored andcommitted
[vm/compiler] Use unchecked entry point when static receiver type is non-generic.
This guarantees that type checks are skipped in the code like this: class X<T> { void method(X<T> other) { } } class Y extends X<String> { } void foo(Y y, Y z) { y.method(z); // No need to check on the callee side. No variance. } Additionally ammend IL printing to print user visible type names instead of internal type names for brevity. Bug: #31798 Change-Id: I4fe16d5dc7de01bb0a8ba834569d90ee5ce7ac74 Reviewed-on: https://dart-review.googlesource.com/72001 Reviewed-by: Samir Jindel <[email protected]> Commit-Queue: Vyacheslav Egorov <[email protected]>
1 parent 0227b0f commit a4b3a85

File tree

2 files changed

+27
-13
lines changed

2 files changed

+27
-13
lines changed

runtime/vm/compiler/backend/il_printer.cc

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -149,14 +149,18 @@ void FlowGraphPrinter::PrintTypeCheck(const ParsedFunction& parsed_function,
149149
String::Handle(dst_type.Name()).ToCString(), dst_name.ToCString());
150150
}
151151

152+
static const char* TypeToUserVisibleName(const AbstractType& type) {
153+
return String::Handle(type.UserVisibleName()).ToCString();
154+
}
155+
152156
void CompileType::PrintTo(BufferFormatter* f) const {
153157
const char* type_name = "?";
154158
if ((cid_ != kIllegalCid) && (cid_ != kDynamicCid)) {
155159
const Class& cls =
156160
Class::Handle(Isolate::Current()->class_table()->At(cid_));
157161
type_name = String::Handle(cls.ScrubbedName()).ToCString();
158162
} else if (type_ != NULL && !type_->IsDynamicType()) {
159-
type_name = type_->ToCString();
163+
type_name = TypeToUserVisibleName(*type_);
160164
} else if (!is_nullable()) {
161165
type_name = "!null";
162166
}
@@ -471,7 +475,8 @@ void DropTempsInstr::PrintOperandsTo(BufferFormatter* f) const {
471475

472476
void AssertAssignableInstr::PrintOperandsTo(BufferFormatter* f) const {
473477
value()->PrintTo(f);
474-
f->Print(", %s, '%s',", dst_type().ToCString(), dst_name().ToCString());
478+
f->Print(", %s, '%s',", TypeToUserVisibleName(dst_type()),
479+
dst_name().ToCString());
475480
f->Print(" instantiator_type_args(");
476481
instantiator_type_arguments()->PrintTo(f);
477482
f->Print("), function_type_args(");
@@ -480,8 +485,8 @@ void AssertAssignableInstr::PrintOperandsTo(BufferFormatter* f) const {
480485
}
481486

482487
void AssertSubtypeInstr::PrintOperandsTo(BufferFormatter* f) const {
483-
f->Print("%s, %s, '%s',", sub_type().ToCString(), super_type().ToCString(),
484-
dst_name().ToCString());
488+
f->Print("%s, %s, '%s',", TypeToUserVisibleName(sub_type()),
489+
TypeToUserVisibleName(super_type()), dst_name().ToCString());
485490
f->Print(" instantiator_type_args(");
486491
instantiator_type_arguments()->PrintTo(f);
487492
f->Print("), function_type_args(");

runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3516,12 +3516,19 @@ Fragment StreamingFlowGraphBuilder::BuildMethodInvocation(TokenPosition* p) {
35163516
}
35173517

35183518
bool is_unchecked_closure_call = false;
3519+
bool is_unchecked_call = false;
35193520
#ifndef TARGET_ARCH_DBC
3520-
if (call_site_attributes.receiver_type != nullptr &&
3521-
call_site_attributes.receiver_type->IsFunctionType()) {
3522-
AlternativeReadingScope alt(&reader_);
3523-
SkipExpression(); // skip receiver
3524-
is_unchecked_closure_call = ReadNameAsMethodName().Equals(Symbols::Call());
3521+
if (call_site_attributes.receiver_type != nullptr) {
3522+
if (call_site_attributes.receiver_type->IsFunctionType()) {
3523+
AlternativeReadingScope alt(&reader_);
3524+
SkipExpression(); // skip receiver
3525+
is_unchecked_closure_call =
3526+
ReadNameAsMethodName().Equals(Symbols::Call());
3527+
} else if (call_site_attributes.receiver_type->HasResolvedTypeClass() &&
3528+
!Class::Handle(call_site_attributes.receiver_type->type_class())
3529+
.IsGeneric()) {
3530+
is_unchecked_call = true;
3531+
}
35253532
}
35263533
#endif
35273534

@@ -3554,7 +3561,9 @@ Fragment StreamingFlowGraphBuilder::BuildMethodInvocation(TokenPosition* p) {
35543561

35553562
// Take note of whether the invocation is against the receiver of the current
35563563
// function: in this case, we may skip some type checks in the callee.
3557-
const bool is_this_invocation = PeekTag() == kThisExpression;
3564+
if (PeekTag() == kThisExpression) {
3565+
is_unchecked_call = true;
3566+
}
35583567
instructions += BuildExpression(); // read receiver.
35593568

35603569
const String& name = ReadNameAsMethodName(); // read name.
@@ -3644,7 +3653,7 @@ Fragment StreamingFlowGraphBuilder::BuildMethodInvocation(TokenPosition* p) {
36443653
B->ClosureCall(position, type_args_len, argument_count, argument_names,
36453654
/*use_unchecked_entry=*/true);
36463655
} else if (!direct_call.target_.IsNull()) {
3647-
// TODO(#34162): Pass 'is_this_invocation' down if/when we feature multiple
3656+
// TODO(#34162): Pass 'is_unchecked_call' down if/when we feature multiple
36483657
// entry-points in AOT.
36493658
ASSERT(FLAG_precompiled_mode);
36503659
instructions += StaticCall(position, direct_call.target_, argument_count,
@@ -3665,12 +3674,12 @@ Fragment StreamingFlowGraphBuilder::BuildMethodInvocation(TokenPosition* p) {
36653674
Z, Function::CreateDynamicInvocationForwarderName(name));
36663675
}
36673676

3668-
// TODO(#34162): Pass 'is_this_invocation' down if/when we feature multiple
3677+
// TODO(#34162): Pass 'is_unchecked_call' down if/when we feature multiple
36693678
// entry-points in AOT.
36703679
instructions += InstanceCall(
36713680
position, *mangled_name, token_kind, type_args_len, argument_count,
36723681
argument_names, checked_argument_count, *interface_target, &result_type,
3673-
/*use_unchecked_entry=*/!FLAG_precompiled_mode && is_this_invocation,
3682+
/*use_unchecked_entry=*/!FLAG_precompiled_mode && is_unchecked_call,
36743683
&call_site_attributes);
36753684
}
36763685

0 commit comments

Comments
 (0)