[vm/compiler] Elide DebugStepCheck instructions in PRODUCT mode
This improves https://dart-review.googlesource.com/c/sdk/+/99287
by removing DebugStepCheck instructions from unoptimized IL
entirely in PRODUCT mode.
Crash mentioned in https://dart-review.googlesource.com/c/sdk/+/99287/1/runtime/vm/compiler/backend/il_arm.cc#7045
is fixed. Also, this CL adds checks which helped me to debug the crash.
Change-Id: I5452877355876b21d2ce21890626db9e5a59f170
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/99421
Reviewed-by: Martin Kustermann <kustermann@google.com>
Commit-Queue: Alexander Markov <alexmarkov@google.com>
diff --git a/runtime/vm/compiler/backend/flow_graph_checker.cc b/runtime/vm/compiler/backend/flow_graph_checker.cc
index a07ed6d..3b9481f 100644
--- a/runtime/vm/compiler/backend/flow_graph_checker.cc
+++ b/runtime/vm/compiler/backend/flow_graph_checker.cc
@@ -119,6 +119,7 @@
}
// Visit regular instructions.
Instruction* last = block->last_instruction();
+ ASSERT((last == block) == block->IsGraphEntry());
Instruction* prev = block;
ASSERT(prev->previous() == nullptr);
for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) {
diff --git a/runtime/vm/compiler/backend/il_arm.cc b/runtime/vm/compiler/backend/il_arm.cc
index 7ac25ef..d7dc61d 100644
--- a/runtime/vm/compiler/backend/il_arm.cc
+++ b/runtime/vm/compiler/backend/il_arm.cc
@@ -7042,7 +7042,9 @@
}
void DebugStepCheckInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-#ifndef PRODUCT
+#ifdef PRODUCT
+ UNREACHABLE();
+#else
ASSERT(!compiler->is_optimizing());
__ BranchLinkPatchable(StubCode::DebugStepCheck());
compiler->AddCurrentDescriptor(stub_kind_, deopt_id_, token_pos());
diff --git a/runtime/vm/compiler/backend/il_arm64.cc b/runtime/vm/compiler/backend/il_arm64.cc
index 11779d4..5ba37ca 100644
--- a/runtime/vm/compiler/backend/il_arm64.cc
+++ b/runtime/vm/compiler/backend/il_arm64.cc
@@ -6185,7 +6185,9 @@
}
void DebugStepCheckInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-#ifndef PRODUCT
+#ifdef PRODUCT
+ UNREACHABLE();
+#else
ASSERT(!compiler->is_optimizing());
__ BranchLinkPatchable(StubCode::DebugStepCheck());
compiler->AddCurrentDescriptor(stub_kind_, deopt_id_, token_pos());
diff --git a/runtime/vm/compiler/backend/il_dbc.cc b/runtime/vm/compiler/backend/il_dbc.cc
index 8c7b83b..e75bfef 100644
--- a/runtime/vm/compiler/backend/il_dbc.cc
+++ b/runtime/vm/compiler/backend/il_dbc.cc
@@ -1317,7 +1317,9 @@
}
void DebugStepCheckInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-#ifndef PRODUCT
+#ifdef PRODUCT
+ UNREACHABLE();
+#else
__ DebugStep();
compiler->AddCurrentDescriptor(stub_kind_, deopt_id_, token_pos());
#endif
diff --git a/runtime/vm/compiler/backend/il_ia32.cc b/runtime/vm/compiler/backend/il_ia32.cc
index 19daf1e..88ce5ba 100644
--- a/runtime/vm/compiler/backend/il_ia32.cc
+++ b/runtime/vm/compiler/backend/il_ia32.cc
@@ -6384,7 +6384,9 @@
}
void DebugStepCheckInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-#ifndef PRODUCT
+#ifdef PRODUCT
+ UNREACHABLE();
+#else
ASSERT(!compiler->is_optimizing());
__ Call(StubCode::DebugStepCheck());
compiler->AddCurrentDescriptor(stub_kind_, deopt_id_, token_pos());
diff --git a/runtime/vm/compiler/backend/il_x64.cc b/runtime/vm/compiler/backend/il_x64.cc
index be9b9b6..af182c4 100644
--- a/runtime/vm/compiler/backend/il_x64.cc
+++ b/runtime/vm/compiler/backend/il_x64.cc
@@ -6481,7 +6481,9 @@
}
void DebugStepCheckInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-#ifndef PRODUCT
+#ifdef PRODUCT
+ UNREACHABLE();
+#else
ASSERT(!compiler->is_optimizing());
__ CallPatchable(StubCode::DebugStepCheck());
compiler->AddCurrentDescriptor(stub_kind_, deopt_id_, token_pos());
diff --git a/runtime/vm/compiler/backend/inliner.cc b/runtime/vm/compiler/backend/inliner.cc
index 8d34ae8..8a7550f 100644
--- a/runtime/vm/compiler/backend/inliner.cc
+++ b/runtime/vm/compiler/backend/inliner.cc
@@ -10,6 +10,7 @@
#include "vm/compiler/aot/precompiler.h"
#include "vm/compiler/backend/block_scheduler.h"
#include "vm/compiler/backend/branch_optimizer.h"
+#include "vm/compiler/backend/flow_graph_checker.h"
#include "vm/compiler/backend/flow_graph_compiler.h"
#include "vm/compiler/backend/il_printer.h"
#include "vm/compiler/backend/type_propagator.h"
@@ -1062,6 +1063,10 @@
{
callee_graph = builder.BuildGraph();
+#if defined(DEBUG)
+ FlowGraphChecker(callee_graph).Check();
+#endif
+
CalleeGraphValidator::Validate(callee_graph);
}
#if defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_DBC) && \
diff --git a/runtime/vm/compiler/frontend/kernel_to_il.cc b/runtime/vm/compiler/frontend/kernel_to_il.cc
index 8268034..ba7ab1b 100644
--- a/runtime/vm/compiler/frontend/kernel_to_il.cc
+++ b/runtime/vm/compiler/frontend/kernel_to_il.cc
@@ -1142,8 +1142,12 @@
}
Fragment FlowGraphBuilder::DebugStepCheck(TokenPosition position) {
+#ifdef PRODUCT
+ return Fragment();
+#else
return Fragment(new (Z) DebugStepCheckInstr(
position, RawPcDescriptors::kRuntimeCall, GetNextDeoptId()));
+#endif
}
Fragment FlowGraphBuilder::EvaluateAssertion() {
@@ -2011,7 +2015,12 @@
extra_entry += Drop();
extra_entry += Goto(join_entry);
- join_entry->LinkTo(prologue_start);
+ if (prologue_start != nullptr) {
+ join_entry->LinkTo(prologue_start);
+ } else {
+ // Prologue is empty.
+ shared_prologue_linked_in.current = join_entry;
+ }
TargetEntryInstr *do_checks, *skip_checks;
shared_prologue_linked_in +=
diff --git a/runtime/vm/compiler/frontend/prologue_builder.cc b/runtime/vm/compiler/frontend/prologue_builder.cc
index deb29dc..f0cb2cf 100644
--- a/runtime/vm/compiler/frontend/prologue_builder.cc
+++ b/runtime/vm/compiler/frontend/prologue_builder.cc
@@ -81,12 +81,13 @@
// Always do this to preserve deoptid numbering.
JoinEntryInstr* normal_code = BuildJoinEntry();
- prologue += Goto(normal_code);
+ Fragment jump_to_normal_code = Goto(normal_code);
if (is_empty_prologue) {
*prologue_info = PrologueInfo(-1, -1);
return entry;
} else {
+ prologue += jump_to_normal_code;
*prologue_info =
PrologueInfo(previous_block_id, normal_code->block_id() - 1);
return normal_code;