From f57c99fc31a76642d34941ec844da9de570334b3 Mon Sep 17 00:00:00 2001 From: Alexander Markov Date: Fri, 29 May 2020 16:34:45 +0000 Subject: [PATCH] [vm/compiler] Fix crash in inliner when receiver is dead Fixes https://github.com/dart-lang/sdk/issues/42065 Change-Id: Ib66163a41a13f02cfa9df9bcb1cf505e934fea93 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/149370 Reviewed-by: Martin Kustermann Commit-Queue: Alexander Markov --- runtime/tests/vm/dart/regress_42065_test.dart | 22 +++++++++++++++++++ runtime/vm/compiler/backend/inliner.cc | 7 ++++++ .../compiler/frontend/flow_graph_builder.cc | 6 ++--- 3 files changed, 32 insertions(+), 3 deletions(-) create mode 100644 runtime/tests/vm/dart/regress_42065_test.dart diff --git a/runtime/tests/vm/dart/regress_42065_test.dart b/runtime/tests/vm/dart/regress_42065_test.dart new file mode 100644 index 00000000000..28079af1da4 --- /dev/null +++ b/runtime/tests/vm/dart/regress_42065_test.dart @@ -0,0 +1,22 @@ +// 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. + +// Verifies that compiler doesn't crash while inlining recognized method +// when receiver is a dead code. +// Regression test for https://github.com/dart-lang/sdk/issues/42065. + +import "package:expect/expect.dart"; + +List foo0(int par1) { + if (par1 >= 39) { + return []; + } + throw 'hi'; +} + +main() { + Expect.throws(() { + (foo0(0)).add(42); + }, (e) => e == 'hi'); +} diff --git a/runtime/vm/compiler/backend/inliner.cc b/runtime/vm/compiler/backend/inliner.cc index 58c4c88b96d..25c3e446866 100644 --- a/runtime/vm/compiler/backend/inliner.cc +++ b/runtime/vm/compiler/backend/inliner.cc @@ -3658,6 +3658,13 @@ bool FlowGraphInliner::TryInlineRecognizedMethod( Definition** result, SpeculativeInliningPolicy* policy, FlowGraphInliner::ExactnessInfo* exactness) { + if (receiver_cid == kNeverCid) { + // Receiver was defined in dead code and was replaced by the sentinel. + // Original receiver cid is lost, so don't try to inline recognized + // methods. + return false; + } + const bool can_speculate = policy->IsAllowedForInlining(call->deopt_id()); const MethodRecognizer::Kind kind = target.recognized_kind(); diff --git a/runtime/vm/compiler/frontend/flow_graph_builder.cc b/runtime/vm/compiler/frontend/flow_graph_builder.cc index 4a13620512e..95fc85457a3 100644 --- a/runtime/vm/compiler/frontend/flow_graph_builder.cc +++ b/runtime/vm/compiler/frontend/flow_graph_builder.cc @@ -273,9 +273,9 @@ void InlineExitCollector::ReplaceCall(BlockEntryInstr* callee_entry) { call_->previous()->AppendInstruction(branch); call_block->set_last_instruction(branch); - // Replace uses of the return value with null to maintain valid - // SSA form - even though the rest of the caller is unreachable. - call_->ReplaceUsesWith(caller_graph_->constant_null()); + // Replace uses of the return value with sentinel constant to maintain + // valid SSA form - even though the rest of the caller is unreachable. + call_->ReplaceUsesWith(caller_graph_->GetConstant(Object::sentinel())); // Update dominator tree. for (intptr_t i = 0, n = callee_entry->dominated_blocks().length(); i < n;