Add more compilation stats to optimizing
Optimizing is getting closer to have full coverage and this provides a
nice overview on why certain methods are not compiled/optimized.
Also, clean up some of the builder methods.
Change-Id: Id2f31441a788b797b0efea7ec78bee27bb654186
diff --git a/compiler/optimizing/builder.cc b/compiler/optimizing/builder.cc
index 0a3f830..d39f1c7 100644
--- a/compiler/optimizing/builder.cc
+++ b/compiler/optimizing/builder.cc
@@ -224,31 +224,35 @@
current_block_ = nullptr;
}
-static bool ShouldSkipCompilation(const CompilerDriver& compiler_driver,
- const DexCompilationUnit& dex_compilation_unit,
- size_t number_of_dex_instructions,
- size_t number_of_blocks ATTRIBUTE_UNUSED,
- size_t number_of_branches) {
- const CompilerOptions& compiler_options = compiler_driver.GetCompilerOptions();
+void HGraphBuilder::MaybeRecordStat(MethodCompilationStat compilation_stat) {
+ if (compilation_stats_ != nullptr) {
+ compilation_stats_->RecordStat(compilation_stat);
+ }
+}
+
+bool HGraphBuilder::SkipCompilation(size_t number_of_dex_instructions,
+ size_t number_of_blocks ATTRIBUTE_UNUSED,
+ size_t number_of_branches) {
+ const CompilerOptions& compiler_options = compiler_driver_->GetCompilerOptions();
CompilerOptions::CompilerFilter compiler_filter = compiler_options.GetCompilerFilter();
if (compiler_filter == CompilerOptions::kEverything) {
return false;
}
if (compiler_options.IsHugeMethod(number_of_dex_instructions)) {
- LOG(INFO) << "Skip compilation of huge method "
- << PrettyMethod(dex_compilation_unit.GetDexMethodIndex(),
- *dex_compilation_unit.GetDexFile())
- << ": " << number_of_dex_instructions << " dex instructions";
+ VLOG(compiler) << "Skip compilation of huge method "
+ << PrettyMethod(dex_compilation_unit_->GetDexMethodIndex(), *dex_file_)
+ << ": " << number_of_dex_instructions << " dex instructions";
+ MaybeRecordStat(MethodCompilationStat::kNotCompiledHugeMethod);
return true;
}
// If it's large and contains no branches, it's likely to be machine generated initialization.
if (compiler_options.IsLargeMethod(number_of_dex_instructions) && (number_of_branches == 0)) {
- LOG(INFO) << "Skip compilation of large method with no branch "
- << PrettyMethod(dex_compilation_unit.GetDexMethodIndex(),
- *dex_compilation_unit.GetDexFile())
- << ": " << number_of_dex_instructions << " dex instructions";
+ VLOG(compiler) << "Skip compilation of large method with no branch "
+ << PrettyMethod(dex_compilation_unit_->GetDexMethodIndex(), *dex_file_)
+ << ": " << number_of_dex_instructions << " dex instructions";
+ MaybeRecordStat(MethodCompilationStat::kNotCompiledLargeMethodNoBranches);
return true;
}
@@ -283,14 +287,9 @@
code_ptr, code_end, &number_of_dex_instructions, &number_of_blocks, &number_of_branches);
// Note that the compiler driver is null when unit testing.
- if (compiler_driver_ != nullptr) {
- if (ShouldSkipCompilation(*compiler_driver_,
- *dex_compilation_unit_,
- number_of_dex_instructions,
- number_of_blocks,
- number_of_branches)) {
- return nullptr;
- }
+ if ((compiler_driver_ != nullptr)
+ && SkipCompilation(number_of_dex_instructions, number_of_blocks, number_of_branches)) {
+ return nullptr;
}
// Also create blocks for catch handlers.
@@ -319,7 +318,9 @@
// Update the current block if dex_pc starts a new block.
MaybeUpdateCurrentBlock(dex_pc);
const Instruction& instruction = *Instruction::At(code_ptr);
- if (!AnalyzeDexInstruction(instruction, dex_pc)) return nullptr;
+ if (!AnalyzeDexInstruction(instruction, dex_pc)) {
+ return nullptr;
+ }
dex_pc += instruction.SizeInCodeUnits();
code_ptr += instruction.SizeInCodeUnits();
}
@@ -593,8 +594,9 @@
if (!compiler_driver_->ComputeInvokeInfo(dex_compilation_unit_, dex_pc, true, true,
&optimized_invoke_type, &target_method, &table_index,
&direct_code, &direct_method)) {
- LOG(INFO) << "Did not compile " << PrettyMethod(method_idx, *dex_file_)
- << " because a method call could not be resolved";
+ VLOG(compiler) << "Did not compile " << PrettyMethod(method_idx, *dex_file_)
+ << " because a method call could not be resolved";
+ MaybeRecordStat(MethodCompilationStat::kNotCompiledUnresolvedMethod);
return false;
}
DCHECK(optimized_invoke_type != kSuper);
@@ -636,6 +638,7 @@
LOG(WARNING) << "Non sequential register pair in " << dex_compilation_unit_->GetSymbol()
<< " at " << dex_pc;
// We do not implement non sequential register pair.
+ MaybeRecordStat(MethodCompilationStat::kNotCompiledNonSequentialRegPair);
return false;
}
HInstruction* arg = LoadLocal(is_range ? register_index + i : args[i], type);
@@ -664,9 +667,11 @@
compiler_driver_->ComputeInstanceFieldInfo(field_index, dex_compilation_unit_, is_put, soa)));
if (resolved_field.Get() == nullptr) {
+ MaybeRecordStat(MethodCompilationStat::kNotCompiledUnresolvedField);
return false;
}
if (resolved_field->IsVolatile()) {
+ MaybeRecordStat(MethodCompilationStat::kNotCompiledVolatile);
return false;
}
@@ -721,10 +726,12 @@
&is_initialized,
&field_type);
if (!fast_path) {
+ MaybeRecordStat(MethodCompilationStat::kNotCompiledUnresolvedField);
return false;
}
if (is_volatile) {
+ MaybeRecordStat(MethodCompilationStat::kNotCompiledVolatile);
return false;
}
@@ -947,6 +954,7 @@
dex_compilation_unit_->GetDexMethodIndex(), *dex_file_, type_index,
&type_known_final, &type_known_abstract, &is_referrers_class);
if (!can_access) {
+ MaybeRecordStat(MethodCompilationStat::kNotCompiledCantAccesType);
return false;
}
HInstruction* object = LoadLocal(reference, Primitive::kPrimNot);
@@ -967,7 +975,7 @@
return true;
}
-bool HGraphBuilder::BuildPackedSwitch(const Instruction& instruction, uint32_t dex_pc) {
+void HGraphBuilder::BuildPackedSwitch(const Instruction& instruction, uint32_t dex_pc) {
SwitchTable table(instruction, dex_pc, false);
// Value to test against.
@@ -984,10 +992,9 @@
BuildSwitchCaseHelper(instruction, i, i == num_entries, table, value, starting_key + i - 1,
table.GetEntryAt(i), dex_pc);
}
- return true;
}
-bool HGraphBuilder::BuildSparseSwitch(const Instruction& instruction, uint32_t dex_pc) {
+void HGraphBuilder::BuildSparseSwitch(const Instruction& instruction, uint32_t dex_pc) {
SwitchTable table(instruction, dex_pc, true);
// Value to test against.
@@ -1001,7 +1008,6 @@
BuildSwitchCaseHelper(instruction, i, i == static_cast<size_t>(num_entries) - 1, table, value,
table.GetEntryAt(i), table.GetEntryAt(i + num_entries), dex_pc);
}
- return true;
}
void HGraphBuilder::BuildSwitchCaseHelper(const Instruction& instruction, size_t index,
@@ -1928,6 +1934,7 @@
dex_compilation_unit_->GetDexMethodIndex(), *dex_file_, type_index,
&type_known_final, &type_known_abstract, &is_referrers_class);
if (!can_access) {
+ MaybeRecordStat(MethodCompilationStat::kNotCompiledCantAccesType);
return false;
}
current_block_->AddInstruction(
@@ -1989,20 +1996,21 @@
}
case Instruction::PACKED_SWITCH: {
- if (!BuildPackedSwitch(instruction, dex_pc)) {
- return false;
- }
+ BuildPackedSwitch(instruction, dex_pc);
break;
}
case Instruction::SPARSE_SWITCH: {
- if (!BuildSparseSwitch(instruction, dex_pc)) {
- return false;
- }
+ BuildSparseSwitch(instruction, dex_pc);
break;
}
default:
+ VLOG(compiler) << "Did not compile "
+ << PrettyMethod(dex_compilation_unit_->GetDexMethodIndex(), *dex_file_)
+ << " because of unhandled instruction "
+ << instruction.Name();
+ MaybeRecordStat(MethodCompilationStat::kNotCompiledUnhandledInstruction);
return false;
}
return true;