Dump the graph before/after every pass
We will now dump a partial CFG when encountering an error while
compiling which is useful for debugging a crash.
Also, force the number of threads to 1 if the --dump-cfg option is
passed. This makes the visualizer_dump_mutex_ obsolete since there's no
possibility of a race.
Bug: 203755436
Test: ART tests, dumped cfg with an added CHECK(false) to verify the
partial .cfg
Change-Id: I55bc9ceafef9e9eb4a43e891fb88d10e619bf64c
diff --git a/compiler/optimizing/optimizing_compiler.cc b/compiler/optimizing/optimizing_compiler.cc
index 6d7a953..c4dd31d 100644
--- a/compiler/optimizing/optimizing_compiler.cc
+++ b/compiler/optimizing/optimizing_compiler.cc
@@ -103,8 +103,7 @@
PassObserver(HGraph* graph,
CodeGenerator* codegen,
std::ostream* visualizer_output,
- const CompilerOptions& compiler_options,
- Mutex& dump_mutex)
+ const CompilerOptions& compiler_options)
: graph_(graph),
last_seen_graph_size_(0),
cached_method_name_(),
@@ -116,7 +115,6 @@
visualizer_enabled_(!compiler_options.GetDumpCfgFileName().empty()),
visualizer_(&visualizer_oss_, graph, codegen),
codegen_(codegen),
- visualizer_dump_mutex_(dump_mutex),
graph_in_bad_state_(false) {
if (timing_logger_enabled_ || visualizer_enabled_) {
if (!IsVerboseMethod(compiler_options, GetMethodName())) {
@@ -143,6 +141,7 @@
void DumpDisassembly() {
if (visualizer_enabled_) {
visualizer_.DumpGraphWithDisassembly();
+ FlushVisualizer();
}
}
@@ -162,14 +161,14 @@
// Dump graph first, then start timer.
if (visualizer_enabled_) {
visualizer_.DumpGraph(pass_name, /* is_after_pass= */ false, graph_in_bad_state_);
+ FlushVisualizer();
}
if (timing_logger_enabled_) {
timing_logger_.StartTiming(pass_name);
}
}
- void FlushVisualizer() REQUIRES(!visualizer_dump_mutex_) {
- MutexLock mu(Thread::Current(), visualizer_dump_mutex_);
+ void FlushVisualizer() {
*visualizer_output_ << visualizer_oss_.str();
visualizer_output_->flush();
visualizer_oss_.str("");
@@ -183,6 +182,7 @@
}
if (visualizer_enabled_) {
visualizer_.DumpGraph(pass_name, /* is_after_pass= */ true, graph_in_bad_state_);
+ FlushVisualizer();
}
// Validate the HGraph if running in debug mode.
@@ -231,7 +231,6 @@
bool visualizer_enabled_;
HGraphVisualizer visualizer_;
CodeGenerator* codegen_;
- Mutex& visualizer_dump_mutex_;
// Flag to be set by the compiler if the pass failed and the graph is not
// expected to validate.
@@ -406,8 +405,6 @@
std::unique_ptr<std::ostream> visualizer_output_;
- mutable Mutex dump_mutex_; // To synchronize visualizer writing.
-
DISALLOW_COPY_AND_ASSIGN(OptimizingCompiler);
};
@@ -415,8 +412,7 @@
OptimizingCompiler::OptimizingCompiler(const CompilerOptions& compiler_options,
CompiledMethodStorage* storage)
- : Compiler(compiler_options, storage, kMaximumCompilationTimeBeforeWarning),
- dump_mutex_("Visualizer dump lock") {
+ : Compiler(compiler_options, storage, kMaximumCompilationTimeBeforeWarning) {
// Enable C1visualizer output.
const std::string& cfg_file_name = compiler_options.GetDumpCfgFileName();
if (!cfg_file_name.empty()) {
@@ -829,8 +825,7 @@
PassObserver pass_observer(graph,
codegen.get(),
visualizer_output_.get(),
- compiler_options,
- dump_mutex_);
+ compiler_options);
{
VLOG(compiler) << "Building " << pass_observer.GetMethodName();
@@ -953,8 +948,7 @@
PassObserver pass_observer(graph,
codegen.get(),
visualizer_output_.get(),
- compiler_options,
- dump_mutex_);
+ compiler_options);
{
VLOG(compiler) << "Building intrinsic graph " << pass_observer.GetMethodName();
diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc
index 217afa9..22ac036 100644
--- a/dex2oat/dex2oat.cc
+++ b/dex2oat/dex2oat.cc
@@ -1189,6 +1189,13 @@
Usage(error_msg.c_str());
}
+ if (!compiler_options_->GetDumpCfgFileName().empty() && thread_count_ != 1) {
+ LOG(INFO) << "Since we are dumping the CFG to " << compiler_options_->GetDumpCfgFileName()
+ << ", we override thread number to 1 to have determinism. It was " << thread_count_
+ << ".";
+ thread_count_ = 1;
+ }
+
ProcessOptions(parser_options.get());
}