#include "driver/compiler_options.h"
#include "driver/dex_compilation_unit.h"
#include "elf_writer_quick.h"
+#include "graph_checker.h"
#include "graph_visualizer.h"
#include "gvn.h"
#include "inliner.h"
*/
static const char* kStringFilter = "";
-class PassInfo;
+class PassScope;
-class PassInfoPrinter : public ValueObject {
+class PassObserver : public ValueObject {
public:
- PassInfoPrinter(HGraph* graph,
- const char* method_name,
- CodeGenerator* codegen,
- std::ostream* visualizer_output,
- CompilerDriver* compiler_driver)
- : method_name_(method_name),
+ PassObserver(HGraph* graph,
+ const char* method_name,
+ CodeGenerator* codegen,
+ std::ostream* visualizer_output,
+ CompilerDriver* compiler_driver)
+ : graph_(graph),
+ method_name_(method_name),
timing_logger_enabled_(compiler_driver->GetDumpPasses()),
timing_logger_(method_name, true, true),
disasm_info_(graph->GetArena()),
visualizer_enabled_(!compiler_driver->GetDumpCfgFileName().empty()),
- visualizer_(visualizer_output, graph, *codegen) {
+ visualizer_(visualizer_output, graph, *codegen),
+ graph_in_bad_state_(false) {
if (strstr(method_name, kStringFilter) == nullptr) {
timing_logger_enabled_ = visualizer_enabled_ = false;
}
}
}
- ~PassInfoPrinter() {
+ ~PassObserver() {
if (timing_logger_enabled_) {
LOG(INFO) << "TIMINGS " << method_name_;
LOG(INFO) << Dumpable<TimingLogger>(timing_logger_);
}
}
+ void SetGraphInBadState() { graph_in_bad_state_ = true; }
+
private:
void StartPass(const char* pass_name) {
// Dump graph first, then start timer.
if (visualizer_enabled_) {
visualizer_.DumpGraph(pass_name, /* is_after_pass */ true);
}
+
+ // Validate the HGraph if running in debug mode.
+ if (kIsDebugBuild) {
+ if (!graph_in_bad_state_) {
+ if (graph_->IsInSsaForm()) {
+ SSAChecker checker(graph_->GetArena(), graph_);
+ checker.Run();
+ if (!checker.IsValid()) {
+ LOG(FATAL) << "Error after " << pass_name << ": " << Dumpable<SSAChecker>(checker);
+ }
+ } else {
+ GraphChecker checker(graph_->GetArena(), graph_);
+ checker.Run();
+ if (!checker.IsValid()) {
+ LOG(FATAL) << "Error after " << pass_name << ": " << Dumpable<GraphChecker>(checker);
+ }
+ }
+ }
+ }
}
+ HGraph* const graph_;
const char* method_name_;
bool timing_logger_enabled_;
bool visualizer_enabled_;
HGraphVisualizer visualizer_;
- friend PassInfo;
+ // Flag to be set by the compiler if the pass failed and the graph is not
+ // expected to validate.
+ bool graph_in_bad_state_;
- DISALLOW_COPY_AND_ASSIGN(PassInfoPrinter);
+ friend PassScope;
+
+ DISALLOW_COPY_AND_ASSIGN(PassObserver);
};
-class PassInfo : public ValueObject {
+class PassScope : public ValueObject {
public:
- PassInfo(const char *pass_name, PassInfoPrinter* pass_info_printer)
+ PassScope(const char *pass_name, PassObserver* pass_observer)
: pass_name_(pass_name),
- pass_info_printer_(pass_info_printer) {
- pass_info_printer_->StartPass(pass_name_);
+ pass_observer_(pass_observer) {
+ pass_observer_->StartPass(pass_name_);
}
- ~PassInfo() {
- pass_info_printer_->EndPass(pass_name_);
+ ~PassScope() {
+ pass_observer_->EndPass(pass_name_);
}
private:
const char* const pass_name_;
- PassInfoPrinter* const pass_info_printer_;
+ PassObserver* const pass_observer_;
};
class OptimizingCompiler FINAL : public Compiler {
CodeGenerator* codegen,
CompilerDriver* driver,
const DexCompilationUnit& dex_compilation_unit,
- PassInfoPrinter* pass_info_printer) const;
+ PassObserver* pass_observer) const;
// Just compile without doing optimizations.
CompiledMethod* CompileBaseline(CodeGenerator* codegen,
CompilerDriver* driver,
const DexCompilationUnit& dex_compilation_unit,
- PassInfoPrinter* pass_info_printer) const;
+ PassObserver* pass_observer) const;
std::unique_ptr<OptimizingCompilerStats> compilation_stats_;
static void RunOptimizations(HOptimization* optimizations[],
size_t length,
- PassInfoPrinter* pass_info_printer) {
+ PassObserver* pass_observer) {
for (size_t i = 0; i < length; ++i) {
- HOptimization* optimization = optimizations[i];
- {
- PassInfo pass_info(optimization->GetPassName(), pass_info_printer);
- optimization->Run();
- }
- optimization->Check();
+ PassScope scope(optimizations[i]->GetPassName(), pass_observer);
+ optimizations[i]->Run();
}
}
CompilerDriver* driver,
OptimizingCompilerStats* stats,
const DexCompilationUnit& dex_compilation_unit,
- PassInfoPrinter* pass_info_printer,
+ PassObserver* pass_observer,
StackHandleScopeCollection* handles) {
ArenaAllocator* arena = graph->GetArena();
HDeadCodeElimination* dce1 = new (arena) HDeadCodeElimination(
simplify4,
};
- RunOptimizations(optimizations, arraysize(optimizations), pass_info_printer);
+ RunOptimizations(optimizations, arraysize(optimizations), pass_observer);
}
// The stack map we generate must be 4-byte aligned on ARM. Since existing
static void AllocateRegisters(HGraph* graph,
CodeGenerator* codegen,
- PassInfoPrinter* pass_info_printer) {
+ PassObserver* pass_observer) {
PrepareForRegisterAllocation(graph).Run();
SsaLivenessAnalysis liveness(graph, codegen);
{
- PassInfo pass_info(SsaLivenessAnalysis::kLivenessPassName, pass_info_printer);
+ PassScope scope(SsaLivenessAnalysis::kLivenessPassName, pass_observer);
liveness.Analyze();
}
{
- PassInfo pass_info(RegisterAllocator::kRegisterAllocatorPassName, pass_info_printer);
+ PassScope scope(RegisterAllocator::kRegisterAllocatorPassName, pass_observer);
RegisterAllocator(graph->GetArena(), codegen, liveness).AllocateRegisters();
}
}
CodeGenerator* codegen,
CompilerDriver* compiler_driver,
const DexCompilationUnit& dex_compilation_unit,
- PassInfoPrinter* pass_info_printer) const {
+ PassObserver* pass_observer) const {
StackHandleScopeCollection handles(Thread::Current());
RunOptimizations(graph, compiler_driver, compilation_stats_.get(),
- dex_compilation_unit, pass_info_printer, &handles);
+ dex_compilation_unit, pass_observer, &handles);
- AllocateRegisters(graph, codegen, pass_info_printer);
+ AllocateRegisters(graph, codegen, pass_observer);
CodeVectorAllocator allocator;
codegen->CompileOptimized(&allocator);
ArrayRef<const uint8_t>(), // native_gc_map.
ArrayRef<const uint8_t>(*codegen->GetAssembler()->cfi().data()),
ArrayRef<const LinkerPatch>());
- pass_info_printer->DumpDisassembly();
+ pass_observer->DumpDisassembly();
return compiled_method;
}
CodeGenerator* codegen,
CompilerDriver* compiler_driver,
const DexCompilationUnit& dex_compilation_unit,
- PassInfoPrinter* pass_info_printer) const {
+ PassObserver* pass_observer) const {
CodeVectorAllocator allocator;
codegen->CompileBaseline(&allocator);
AlignVectorSize(gc_map),
ArrayRef<const uint8_t>(*codegen->GetAssembler()->cfi().data()),
ArrayRef<const LinkerPatch>());
- pass_info_printer->DumpDisassembly();
+ pass_observer->DumpDisassembly();
return compiled_method;
}
codegen->GetAssembler()->cfi().SetEnabled(
compiler_driver->GetCompilerOptions().GetGenerateDebugInfo());
- PassInfoPrinter pass_info_printer(graph,
- method_name.c_str(),
- codegen.get(),
- visualizer_output_.get(),
- compiler_driver);
+ PassObserver pass_observer(graph,
+ method_name.c_str(),
+ codegen.get(),
+ visualizer_output_.get(),
+ compiler_driver);
HGraphBuilder builder(graph,
&dex_compilation_unit,
VLOG(compiler) << "Building " << method_name;
{
- PassInfo pass_info(HGraphBuilder::kBuilderPassName, &pass_info_printer);
+ PassScope scope(HGraphBuilder::kBuilderPassName, &pass_observer);
if (!builder.BuildGraph(*code_item)) {
CHECK(!shouldCompile) << "Could not build graph in optimizing compiler";
+ pass_observer.SetGraphInBadState();
return nullptr;
}
}
VLOG(compiler) << "Optimizing " << method_name;
{
- PassInfo pass_info(SsaBuilder::kSsaBuilderPassName, &pass_info_printer);
+ PassScope scope(SsaBuilder::kSsaBuilderPassName, &pass_observer);
if (!graph->TryBuildingSsa()) {
// We could not transform the graph to SSA, bailout.
LOG(INFO) << "Skipping compilation of " << method_name << ": it contains a non natural loop";
codegen.get(),
compiler_driver,
dex_compilation_unit,
- &pass_info_printer);
+ &pass_observer);
} else if (shouldOptimize && can_allocate_registers) {
LOG(FATAL) << "Could not allocate registers in optimizing compiler";
UNREACHABLE();
return CompileBaseline(codegen.get(),
compiler_driver,
dex_compilation_unit,
- &pass_info_printer);
+ &pass_observer);
} else {
return nullptr;
}