diff options
author | Calin Juravle <calin@google.com> | 2014-12-09 18:11:36 +0000 |
---|---|---|
committer | Calin Juravle <calin@google.com> | 2014-12-10 16:27:08 +0000 |
commit | 48c2b03965830c73cdddeae8aea8030f08430137 (patch) | |
tree | 56cf034739095c71a175fa97205ed6dc76efbe0d | |
parent | d2ec87d84057174d4884ee16f652cbcfd31362e9 (diff) | |
download | art-48c2b03965830c73cdddeae8aea8030f08430137.tar.gz art-48c2b03965830c73cdddeae8aea8030f08430137.tar.bz2 art-48c2b03965830c73cdddeae8aea8030f08430137.zip |
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
-rw-r--r-- | compiler/optimizing/builder.cc | 78 | ||||
-rw-r--r-- | compiler/optimizing/builder.h | 22 | ||||
-rw-r--r-- | compiler/optimizing/optimizing_compiler.cc | 49 | ||||
-rw-r--r-- | compiler/optimizing/optimizing_compiler.h | 2 | ||||
-rw-r--r-- | compiler/optimizing/optimizing_compiler_stats.h | 111 |
5 files changed, 199 insertions, 63 deletions
diff --git a/compiler/optimizing/builder.cc b/compiler/optimizing/builder.cc index 0a3f83024..d39f1c7d4 100644 --- a/compiler/optimizing/builder.cc +++ b/compiler/optimizing/builder.cc @@ -224,31 +224,35 @@ void HGraphBuilder::If_21t(const Instruction& instruction, uint32_t dex_pc) { 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 @@ HGraph* HGraphBuilder::BuildGraph(const DexFile::CodeItem& code_item) { 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 @@ HGraph* HGraphBuilder::BuildGraph(const DexFile::CodeItem& code_item) { // 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 @@ bool HGraphBuilder::BuildInvoke(const Instruction& instruction, 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 @@ bool HGraphBuilder::BuildInvoke(const Instruction& instruction, 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 @@ bool HGraphBuilder::BuildInstanceFieldAccess(const Instruction& instruction, 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 @@ bool HGraphBuilder::BuildStaticFieldAccess(const Instruction& instruction, &is_initialized, &field_type); if (!fast_path) { + MaybeRecordStat(MethodCompilationStat::kNotCompiledUnresolvedField); return false; } if (is_volatile) { + MaybeRecordStat(MethodCompilationStat::kNotCompiledVolatile); return false; } @@ -947,6 +954,7 @@ bool HGraphBuilder::BuildTypeCheck(const Instruction& instruction, 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 @@ bool HGraphBuilder::BuildTypeCheck(const Instruction& instruction, 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 @@ bool HGraphBuilder::BuildPackedSwitch(const Instruction& instruction, uint32_t d 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 @@ bool HGraphBuilder::BuildSparseSwitch(const Instruction& instruction, uint32_t d 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 @@ bool HGraphBuilder::AnalyzeDexInstruction(const Instruction& instruction, uint32 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 @@ bool HGraphBuilder::AnalyzeDexInstruction(const Instruction& instruction, uint32 } 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; diff --git a/compiler/optimizing/builder.h b/compiler/optimizing/builder.h index 73c2f5095..75c8634ea 100644 --- a/compiler/optimizing/builder.h +++ b/compiler/optimizing/builder.h @@ -21,6 +21,7 @@ #include "dex_file-inl.h" #include "driver/compiler_driver.h" #include "driver/dex_compilation_unit.h" +#include "optimizing_compiler_stats.h" #include "primitive.h" #include "utils/arena_object.h" #include "utils/growable_array.h" @@ -36,7 +37,8 @@ class HGraphBuilder : public ValueObject { HGraphBuilder(ArenaAllocator* arena, DexCompilationUnit* dex_compilation_unit, const DexFile* dex_file, - CompilerDriver* driver) + CompilerDriver* driver, + OptimizingCompilerStats* compiler_stats) : arena_(arena), branch_targets_(arena, 0), locals_(arena, 0), @@ -51,7 +53,8 @@ class HGraphBuilder : public ValueObject { compiler_driver_(driver), return_type_(Primitive::GetType(dex_compilation_unit_->GetShorty()[0])), code_start_(nullptr), - latest_result_(nullptr) {} + latest_result_(nullptr), + compilation_stats_(compiler_stats) {} // Only for unit testing. HGraphBuilder(ArenaAllocator* arena, Primitive::Type return_type = Primitive::kPrimInt) @@ -69,7 +72,8 @@ class HGraphBuilder : public ValueObject { compiler_driver_(nullptr), return_type_(return_type), code_start_(nullptr), - latest_result_(nullptr) {} + latest_result_(nullptr), + compilation_stats_(nullptr) {} HGraph* BuildGraph(const DexFile::CodeItem& code); @@ -205,16 +209,22 @@ class HGraphBuilder : public ValueObject { uint32_t dex_pc); // Builds an instruction sequence for a packed switch statement. - bool BuildPackedSwitch(const Instruction& instruction, uint32_t dex_pc); + void BuildPackedSwitch(const Instruction& instruction, uint32_t dex_pc); // Builds an instruction sequence for a sparse switch statement. - bool BuildSparseSwitch(const Instruction& instruction, uint32_t dex_pc); + void BuildSparseSwitch(const Instruction& instruction, uint32_t dex_pc); void BuildSwitchCaseHelper(const Instruction& instruction, size_t index, bool is_last_case, const SwitchTable& table, HInstruction* value, int32_t case_value_int, int32_t target_offset, uint32_t dex_pc); + bool SkipCompilation(size_t number_of_dex_instructions, + size_t number_of_blocks, + size_t number_of_branches); + + void MaybeRecordStat(MethodCompilationStat compilation_stat); + ArenaAllocator* const arena_; // A list of the size of the dex code holding block information for @@ -245,6 +255,8 @@ class HGraphBuilder : public ValueObject { // used by move-result instructions. HInstruction* latest_result_; + OptimizingCompilerStats* compilation_stats_; + DISALLOW_COPY_AND_ASSIGN(HGraphBuilder); }; diff --git a/compiler/optimizing/optimizing_compiler.cc b/compiler/optimizing/optimizing_compiler.cc index 11fc9bf9b..a8abb0198 100644 --- a/compiler/optimizing/optimizing_compiler.cc +++ b/compiler/optimizing/optimizing_compiler.cc @@ -121,9 +121,8 @@ class OptimizingCompiler FINAL : public Compiler { // Whether we should run any optimization or register allocation. If false, will // just run the code generation after the graph was built. const bool run_optimizations_; - mutable AtomicInteger total_compiled_methods_; - mutable AtomicInteger unoptimized_compiled_methods_; - mutable AtomicInteger optimized_compiled_methods_; + + mutable OptimizingCompilerStats compilation_stats_; std::unique_ptr<std::ostream> visualizer_output_; @@ -136,24 +135,14 @@ OptimizingCompiler::OptimizingCompiler(CompilerDriver* driver) : Compiler(driver, kMaximumCompilationTimeBeforeWarning), run_optimizations_( driver->GetCompilerOptions().GetCompilerFilter() != CompilerOptions::kTime), - total_compiled_methods_(0), - unoptimized_compiled_methods_(0), - optimized_compiled_methods_(0) { + compilation_stats_() { if (kIsVisualizerEnabled) { visualizer_output_.reset(new std::ofstream("art.cfg")); } } OptimizingCompiler::~OptimizingCompiler() { - if (total_compiled_methods_ == 0) { - LOG(INFO) << "Did not compile any method."; - } else { - size_t unoptimized_percent = (unoptimized_compiled_methods_ * 100 / total_compiled_methods_); - size_t optimized_percent = (optimized_compiled_methods_ * 100 / total_compiled_methods_); - LOG(INFO) << "Compiled " << total_compiled_methods_ << " methods: " - << unoptimized_percent << "% (" << unoptimized_compiled_methods_ << ") unoptimized, " - << optimized_percent << "% (" << optimized_compiled_methods_ << ") optimized."; - } + compilation_stats_.Log(); } bool OptimizingCompiler::CanCompileMethod(uint32_t method_idx ATTRIBUTE_UNUSED, @@ -246,7 +235,7 @@ CompiledMethod* OptimizingCompiler::Compile(const DexFile::CodeItem* code_item, jobject class_loader, const DexFile& dex_file) const { UNUSED(invoke_type); - total_compiled_methods_++; + compilation_stats_.RecordStat(MethodCompilationStat::kAttemptCompilation); InstructionSet instruction_set = GetCompilerDriver()->GetInstructionSet(); // Always use the thumb2 assembler: some runtime functionality (like implicit stack // overflow checks) assume thumb2. @@ -256,10 +245,12 @@ CompiledMethod* OptimizingCompiler::Compile(const DexFile::CodeItem* code_item, // Do not attempt to compile on architectures we do not support. if (!IsInstructionSetSupported(instruction_set)) { + compilation_stats_.RecordStat(MethodCompilationStat::kNotCompiledUnsupportedIsa); return nullptr; } if (Compiler::IsPathologicalCase(*code_item, method_idx, dex_file)) { + compilation_stats_.RecordStat(MethodCompilationStat::kNotCompiledPathological); return nullptr; } @@ -276,7 +267,10 @@ CompiledMethod* OptimizingCompiler::Compile(const DexFile::CodeItem* code_item, ArenaPool pool; ArenaAllocator arena(&pool); - HGraphBuilder builder(&arena, &dex_compilation_unit, &dex_file, GetCompilerDriver()); + HGraphBuilder builder(&arena, + &dex_compilation_unit, + &dex_file, GetCompilerDriver(), + &compilation_stats_); HGraph* graph = builder.BuildGraph(*code_item); if (graph == nullptr) { @@ -287,6 +281,7 @@ CompiledMethod* OptimizingCompiler::Compile(const DexFile::CodeItem* code_item, CodeGenerator* codegen = CodeGenerator::Create(&arena, graph, instruction_set); if (codegen == nullptr) { CHECK(!shouldCompile) << "Could not find code generator for optimizing compiler"; + compilation_stats_.RecordStat(MethodCompilationStat::kNotCompiledNoCodegen); return nullptr; } @@ -296,13 +291,13 @@ CompiledMethod* OptimizingCompiler::Compile(const DexFile::CodeItem* code_item, CodeVectorAllocator allocator; - if (run_optimizations_ - && CanOptimize(*code_item) - && RegisterAllocator::CanAllocateRegistersFor(*graph, instruction_set)) { + bool can_optimize = CanOptimize(*code_item); + bool can_allocate_registers = RegisterAllocator::CanAllocateRegistersFor(*graph, instruction_set); + if (run_optimizations_ && can_optimize && can_allocate_registers) { VLOG(compiler) << "Optimizing " << PrettyMethod(method_idx, dex_file); - optimized_compiled_methods_++; if (!TryBuildingSsa(graph, dex_compilation_unit, visualizer)) { // We could not transform the graph to SSA, bailout. + compilation_stats_.RecordStat(MethodCompilationStat::kNotCompiledCannotBuildSSA); return nullptr; } RunOptimizations(graph, visualizer); @@ -327,6 +322,7 @@ CompiledMethod* OptimizingCompiler::Compile(const DexFile::CodeItem* code_item, std::vector<uint8_t> stack_map; codegen->BuildStackMaps(&stack_map); + compilation_stats_.RecordStat(MethodCompilationStat::kCompiledOptimized); return new CompiledMethod(GetCompilerDriver(), instruction_set, allocator.GetMemory(), @@ -340,7 +336,15 @@ CompiledMethod* OptimizingCompiler::Compile(const DexFile::CodeItem* code_item, UNREACHABLE(); } else { VLOG(compiler) << "Compile baseline " << PrettyMethod(method_idx, dex_file); - unoptimized_compiled_methods_++; + + if (!run_optimizations_) { + compilation_stats_.RecordStat(MethodCompilationStat::kNotOptimizedDisabled); + } else if (!can_optimize) { + compilation_stats_.RecordStat(MethodCompilationStat::kNotOptimizedTryCatch); + } else if (!can_allocate_registers) { + compilation_stats_.RecordStat(MethodCompilationStat::kNotOptimizedRegisterAllocator); + } + codegen->CompileBaseline(&allocator); std::vector<uint8_t> mapping_table; @@ -353,6 +357,7 @@ CompiledMethod* OptimizingCompiler::Compile(const DexFile::CodeItem* code_item, std::vector<uint8_t> gc_map; codegen->BuildNativeGCMap(&gc_map, dex_compilation_unit); + compilation_stats_.RecordStat(MethodCompilationStat::kCompiledBaseline); return new CompiledMethod(GetCompilerDriver(), instruction_set, allocator.GetMemory(), diff --git a/compiler/optimizing/optimizing_compiler.h b/compiler/optimizing/optimizing_compiler.h index a415eca2d..d076fb55f 100644 --- a/compiler/optimizing/optimizing_compiler.h +++ b/compiler/optimizing/optimizing_compiler.h @@ -24,6 +24,6 @@ class CompilerDriver; Compiler* CreateOptimizingCompiler(CompilerDriver* driver); -} +} // namespace art #endif // ART_COMPILER_OPTIMIZING_OPTIMIZING_COMPILER_H_ diff --git a/compiler/optimizing/optimizing_compiler_stats.h b/compiler/optimizing/optimizing_compiler_stats.h new file mode 100644 index 000000000..829982e79 --- /dev/null +++ b/compiler/optimizing/optimizing_compiler_stats.h @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ART_COMPILER_OPTIMIZING_OPTIMIZING_COMPILER_STATS_H_ +#define ART_COMPILER_OPTIMIZING_OPTIMIZING_COMPILER_STATS_H_ + +#include <sstream> +#include <string> + +#include "atomic.h" + +namespace art { + +enum MethodCompilationStat { + kAttemptCompilation = 0, + kCompiledBaseline, + kCompiledOptimized, + kNotCompiledUnsupportedIsa, + kNotCompiledPathological, + kNotCompiledHugeMethod, + kNotCompiledLargeMethodNoBranches, + kNotCompiledCannotBuildSSA, + kNotCompiledNoCodegen, + kNotCompiledUnresolvedMethod, + kNotCompiledUnresolvedField, + kNotCompiledNonSequentialRegPair, + kNotCompiledVolatile, + kNotOptimizedTryCatch, + kNotOptimizedDisabled, + kNotCompiledCantAccesType, + kNotOptimizedRegisterAllocator, + kNotCompiledUnhandledInstruction, + kLastStat +}; + +class OptimizingCompilerStats { + public: + OptimizingCompilerStats() {} + + void RecordStat(MethodCompilationStat stat) { + compile_stats_[stat]++; + } + + void Log() const { + if (compile_stats_[kAttemptCompilation] == 0) { + LOG(INFO) << "Did not compile any method."; + } else { + size_t unoptimized_percent = + compile_stats_[kCompiledBaseline] * 100 / compile_stats_[kAttemptCompilation]; + size_t optimized_percent = + compile_stats_[kCompiledOptimized] * 100 / compile_stats_[kAttemptCompilation]; + std::ostringstream oss; + oss << "Attempted compilation of " << compile_stats_[kAttemptCompilation] << " methods: " + << unoptimized_percent << "% (" << compile_stats_[kCompiledBaseline] << ") unoptimized, " + << optimized_percent << "% (" << compile_stats_[kCompiledOptimized] << ") optimized.\n"; + for (int i = 0; i < kLastStat; i++) { + if (compile_stats_[i] != 0) { + oss << PrintMethodCompilationStat(i) << ": " << compile_stats_[i] << "\n"; + } + } + LOG(INFO) << oss.str(); + } + } + + private: + std::string PrintMethodCompilationStat(int stat) const { + switch (stat) { + case kAttemptCompilation : return "kAttemptCompilation"; + case kCompiledBaseline : return "kCompiledBaseline"; + case kCompiledOptimized : return "kCompiledOptimized"; + case kNotCompiledUnsupportedIsa : return "kNotCompiledUnsupportedIsa"; + case kNotCompiledPathological : return "kNotCompiledPathological"; + case kNotCompiledHugeMethod : return "kNotCompiledHugeMethod"; + case kNotCompiledLargeMethodNoBranches : return "kNotCompiledLargeMethodNoBranches"; + case kNotCompiledCannotBuildSSA : return "kNotCompiledCannotBuildSSA"; + case kNotCompiledNoCodegen : return "kNotCompiledNoCodegen"; + case kNotCompiledUnresolvedMethod : return "kNotCompiledUnresolvedMethod"; + case kNotCompiledUnresolvedField : return "kNotCompiledUnresolvedField"; + case kNotCompiledNonSequentialRegPair : return "kNotCompiledNonSequentialRegPair"; + case kNotCompiledVolatile : return "kNotCompiledVolatile"; + case kNotOptimizedDisabled : return "kNotOptimizedDisabled"; + case kNotOptimizedTryCatch : return "kNotOptimizedTryCatch"; + case kNotCompiledCantAccesType : return "kNotCompiledCantAccesType"; + case kNotOptimizedRegisterAllocator : return "kNotOptimizedRegisterAllocator"; + case kNotCompiledUnhandledInstruction : return "kNotCompiledUnhandledInstruction"; + default: LOG(FATAL) << "invalid stat"; + } + return ""; + } + + AtomicInteger compile_stats_[kLastStat]; + + DISALLOW_COPY_AND_ASSIGN(OptimizingCompilerStats); +}; + +} // namespace art + +#endif // ART_COMPILER_OPTIMIZING_OPTIMIZING_COMPILER_STATS_H_ |