[vm] Fix ThrowErrorSlowPath-derived instructions (e.g. CheckNull) in JIT mode.

Previously these instructions were not safe to use on JIT, because they
crated catch-entry moves which are not used in JIT.

Now we assign deopt-infos to these slow paths so they can handle exceptions
correctly in JIT.

I considered removing uses of CheckNull in JIT mode, but I did not find a simple
replacement for all the existing uses.

Fixes #35887.

Change-Id: I05dfb46200679934d0ff6114cae8723f4908af8e
Reviewed-on: https://dart-review.googlesource.com/c/92783
Reviewed-by: Alexander Markov <alexmarkov@google.com>
Commit-Queue: Samir Jindel <sjindel@google.com>
Auto-Submit: Samir Jindel <sjindel@google.com>
This commit is contained in:
Samir Jindel 2019-02-13 16:39:55 +00:00 committed by commit-bot@chromium.org
parent 76f531e742
commit 010a12330e
3 changed files with 54 additions and 4 deletions

View file

@ -0,0 +1,36 @@
// Copyright (c) 2019, 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.
//
// Regression test for dartbug.com/35887.
//
// The call specializer inserts a "CheckNull" into main() here, but CheckNull
// was broken in JIT because it didn't create a deopt-info to hold the
// environment in case the it was inside a try/catch block.
//
// VMOptions=--optimization_counter_threshold=10 --no-background-compilation
import 'package:expect/expect.dart';
class Value {
const Value(this.val);
final int val;
}
const int limit = 50;
Value maybeWrap(int i) => i < limit ? new Value(i) : null;
Future<void> test() async {
for (int i = 0; i < 60; ++i) {
if (maybeWrap(i).val == -1) {
// never mind we just do something with it
print(i);
}
}
}
void main() {
test().catchError((e) {});
}

View file

@ -756,6 +756,16 @@ CompilerDeoptInfo* FlowGraphCompiler::AddDeoptIndexAtCall(intptr_t deopt_id) {
return info;
}
CompilerDeoptInfo* FlowGraphCompiler::AddSlowPathDeoptInfo(intptr_t deopt_id,
Environment* env) {
ASSERT(deopt_id != DeoptId::kNone);
CompilerDeoptInfo* info =
new (zone()) CompilerDeoptInfo(deopt_id, ICData::kDeoptUnknown, 0, env);
info->set_pc_offset(assembler()->CodeSize());
deopt_infos_.Add(info);
return info;
}
// This function must be in sync with FlowGraphCompiler::SaveLiveRegisters
// and FlowGraphCompiler::SlowPathEnvironmentFor.
// See StackFrame::VisitObjectPointers for the details of how stack map is
@ -1053,7 +1063,7 @@ void FlowGraphCompiler::FinalizeStackMaps(const Code& code) {
void FlowGraphCompiler::FinalizeVarDescriptors(const Code& code) {
#if defined(PRODUCT)
// No debugger: no var descriptors.
// No debugger: no var descriptors.
#else
// TODO(alexmarkov): revise local vars descriptors when compiling bytecode
if (code.is_optimized() || flow_graph().function().HasBytecode()) {
@ -1418,8 +1428,7 @@ static Register AllocateFreeRegister(bool* blocked_registers) {
void FlowGraphCompiler::AllocateRegistersLocally(Instruction* instr) {
ASSERT(!is_optimizing());
instr->InitializeLocationSummary(zone(),
false); // Not optimizing.
instr->InitializeLocationSummary(zone(), false); // Not optimizing.
// No need to allocate registers based on LocationSummary on DBC as in
// unoptimized mode it's a stack based bytecode just like IR itself.
@ -2302,7 +2311,11 @@ void ThrowErrorSlowPathCode::EmitNativeCode(FlowGraphCompiler* compiler) {
(compiler->CurrentTryIndex() != kInvalidTryIndex)) {
Environment* env =
compiler->SlowPathEnvironmentFor(instruction(), num_args_);
compiler->RecordCatchEntryMoves(env, try_index_);
if (FLAG_precompiled_mode) {
compiler->RecordCatchEntryMoves(env, try_index_);
} else if (env != nullptr) {
compiler->AddSlowPathDeoptInfo(deopt_id, env);
}
}
if (!use_shared_stub) {
__ Breakpoint();

View file

@ -693,6 +693,7 @@ class FlowGraphCompiler : public ValueObject {
#endif // defined(TARGET_ARCH_DBC)
CompilerDeoptInfo* AddDeoptIndexAtCall(intptr_t deopt_id);
CompilerDeoptInfo* AddSlowPathDeoptInfo(intptr_t deopt_id, Environment* env);
void AddSlowPathCode(SlowPathCode* slow_path);