mirror of
https://github.com/dart-lang/sdk
synced 2024-09-18 20:31:21 +00:00
[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:
parent
76f531e742
commit
010a12330e
36
runtime/tests/vm/dart/regress_35887_test.dart
Normal file
36
runtime/tests/vm/dart/regress_35887_test.dart
Normal 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) {});
|
||||
}
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in a new issue