diff options
author | buzbee <buzbee@google.com> | 2013-08-21 22:14:23 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2013-08-21 22:14:24 +0000 |
commit | dd3413f4a1a4fcf9fd62b4660805a4ce64b22bd6 (patch) | |
tree | 6fd61b2f41f7282d140d347b3bd93eea97f7bf30 | |
parent | b8a0b94735f188bc739e4c55479c37699006b881 (diff) | |
parent | fe9ca4028f379688ecba6132ac3738171176b3e4 (diff) | |
download | art-dd3413f4a1a4fcf9fd62b4660805a4ce64b22bd6.zip art-dd3413f4a1a4fcf9fd62b4660805a4ce64b22bd6.tar.gz art-dd3413f4a1a4fcf9fd62b4660805a4ce64b22bd6.tar.bz2 |
Merge "Compiler filter update" into dalvik-dev
-rw-r--r-- | compiler/dex/mir_analysis.cc | 80 | ||||
-rw-r--r-- | compiler/dex/mir_graph.h | 4 | ||||
-rw-r--r-- | dex2oat/dex2oat.cc | 7 | ||||
-rw-r--r-- | runtime/class_linker.cc | 6 | ||||
-rw-r--r-- | runtime/runtime.cc | 4 | ||||
-rw-r--r-- | runtime/runtime.h | 12 |
6 files changed, 66 insertions, 47 deletions
diff --git a/compiler/dex/mir_analysis.cc b/compiler/dex/mir_analysis.cc index 8321ff6..d7a4136 100644 --- a/compiler/dex/mir_analysis.cc +++ b/compiler/dex/mir_analysis.cc @@ -151,10 +151,10 @@ const uint32_t MIRGraph::analysis_attributes_[kMirOpLast] = { AN_BRANCH, // 2B PACKED_SWITCH vAA, +BBBBBBBB - AN_NONE, + AN_SWITCH, // 2C SPARSE_SWITCH vAA, +BBBBBBBB - AN_NONE, + AN_SWITCH, // 2D CMPL_FLOAT vAA, vBB, vCC AN_MATH | AN_FP | AN_SINGLE, @@ -841,6 +841,7 @@ struct MethodStats { int branch_ops; int heavyweight_ops; bool has_computational_loop; + bool has_switch; float math_ratio; float fp_ratio; float array_ratio; @@ -914,6 +915,9 @@ void MIRGraph::AnalyzeBlock(BasicBlock* bb, MethodStats* stats) { if ((flags & AN_HEAVYWEIGHT) != 0) { stats->heavyweight_ops += loop_scale_factor; } + if ((flags & AN_SWITCH) != 0) { + stats->has_switch = true; + } } if (tbb == ending_bb) { done = true; @@ -939,7 +943,7 @@ bool MIRGraph::ComputeSkipCompilation(MethodStats* stats, bool skip_default) { << stats->math_ratio << ", fp:" << stats->fp_ratio << ", br:" << stats->branch_ratio << ", hw:" - << stats-> heavyweight_ratio << ", arr:" + << stats->heavyweight_ratio << ", arr:" << stats->array_ratio << ", hot:" << stats->has_computational_loop << ", " << PrettyMethod(cu_->method_idx, *cu_->dex_file); @@ -971,8 +975,14 @@ bool MIRGraph::ComputeSkipCompilation(MethodStats* stats, bool skip_default) { return false; } - // If high proportion of expensive operations, skip. - if (stats->heavyweight_ratio > 0.3) { + // Switch operations benefit greatly from compilation, so go ahead and spend the cycles. + if (stats->has_switch) { + return false; + } + + // If significant in size and high proportion of expensive operations, skip. + if ((GetNumDalvikInsns() > Runtime::Current()->GetSmallMethodThreshold()) && + (stats->heavyweight_ratio > 0.3)) { return true; } @@ -984,8 +994,7 @@ bool MIRGraph::ComputeSkipCompilation(MethodStats* stats, bool skip_default) { * Ultimate goal is to drive with profile data. */ bool MIRGraph::SkipCompilation(Runtime::CompilerFilter compiler_filter) { - if (compiler_filter == Runtime::kSpeed) { - // If going for speed, compile everything. + if (compiler_filter == Runtime::kEverything) { return false; } @@ -994,10 +1003,38 @@ bool MIRGraph::SkipCompilation(Runtime::CompilerFilter compiler_filter) { return true; } - // Filter 1: Skip huge methods (generally machine-generated initialization methods). + // Set up compilation cutoffs based on current filter mode. + size_t small_cutoff = 0; + size_t default_cutoff = 0; + switch (compiler_filter) { + case Runtime::kBalanced: + small_cutoff = Runtime::Current()->GetSmallMethodThreshold(); + default_cutoff = Runtime::Current()->GetLargeMethodThreshold(); + break; + case Runtime::kSpace: + small_cutoff = Runtime::Current()->GetTinyMethodThreshold(); + default_cutoff = Runtime::Current()->GetSmallMethodThreshold(); + break; + case Runtime::kSpeed: + small_cutoff = Runtime::Current()->GetHugeMethodThreshold(); + default_cutoff = Runtime::Current()->GetHugeMethodThreshold(); + break; + default: + LOG(FATAL) << "Unexpected compiler_filter_: " << compiler_filter; + } + + // If size < cutoff, assume we'll compile - but allow removal. + bool skip_compilation = (GetNumDalvikInsns() >= default_cutoff); + + /* + * Filter 1: Huge methods are likely to be machine generated, but some aren't. + * If huge, assume we won't compile, but allow futher analysis to turn it back on. + */ if (GetNumDalvikInsns() > Runtime::Current()->GetHugeMethodThreshold()) { - // Ain't nobody got time for that. - return true; + skip_compilation = true; + } else if (compiler_filter == Runtime::kSpeed) { + // If not huge, compile. + return false; } // Filter 2: Skip class initializers. @@ -1010,28 +1047,7 @@ bool MIRGraph::SkipCompilation(Runtime::CompilerFilter compiler_filter) { return false; } - /* In balanced mode, we generally assume that we'll be compiling, and then detect - * methods that won't benefit and remove them. In space or deferred mode, we do the - * opposite: assume no compilation and then add back presumed hot methods. - */ - bool skip_compilation = (compiler_filter == Runtime::kBalanced) ? false : true; - - - // Filter 4: go ahead and compile the small ones. - size_t small_cutoff = 0; - switch (compiler_filter) { - case Runtime::kBalanced: - small_cutoff = Runtime::Current()->GetSmallMethodThreshold(); - break; - case Runtime::kSpace: - small_cutoff = Runtime::Current()->GetTinyMethodThreshold(); - break; - case Runtime::kDeferCompilation: - small_cutoff = 0; - break; - default: - LOG(FATAL) << "Unexpected compiler_filter_: " << compiler_filter; - } + // Filter 4: if small, just compile. if (GetNumDalvikInsns() < small_cutoff) { return false; } diff --git a/compiler/dex/mir_graph.h b/compiler/dex/mir_graph.h index af1ae44..c02deab 100644 --- a/compiler/dex/mir_graph.h +++ b/compiler/dex/mir_graph.h @@ -38,7 +38,8 @@ enum InstructionAnalysisAttributePos { kArrayOp, kHeavyweightOp, kSimpleConstOp, - kMoveOp + kMoveOp, + kSwitch }; #define AN_NONE (1 << kUninterestingOp) @@ -55,6 +56,7 @@ enum InstructionAnalysisAttributePos { #define AN_HEAVYWEIGHT (1 << kHeavyweightOp) #define AN_SIMPLECONST (1 << kSimpleConstOp) #define AN_MOVE (1 << kMoveOp) +#define AN_SWITCH (1 << kSwitch) #define AN_COMPUTATIONAL (AN_MATH | AN_ARRAYOP | AN_MOVE | AN_SIMPLECONST) enum DataFlowAttributePos { diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc index 511788b..1d7f68d 100644 --- a/dex2oat/dex2oat.cc +++ b/dex2oat/dex2oat.cc @@ -867,9 +867,10 @@ static int dex2oat(int argc, char** argv) { // give it away now and then switch to a more managable ScopedObjectAccess. Thread::Current()->TransitionFromRunnableToSuspended(kNative); // If we're doing the image, override the compiler filter to force full compilation. Must be - // done ahead of WellKnownClasses::Init that causes verification. - if (image && Runtime::Current()->GetCompilerFilter() == Runtime::kInterpretOnly) { - Runtime::Current()->SetCompilerFilter(Runtime::kSpeed); + // done ahead of WellKnownClasses::Init that causes verification. Note: doesn't force + // compilation of class initializers. + if (image) { + Runtime::Current()->SetCompilerFilter(Runtime::kEverything); } // Whilst we're in native take the opportunity to initialize well known classes. WellKnownClasses::Init(Thread::Current()->GetJniEnv()); diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc index 0110b36..69f004d 100644 --- a/runtime/class_linker.cc +++ b/runtime/class_linker.cc @@ -575,9 +575,6 @@ bool ClassLinker::GenerateOatFile(const std::string& dex_filename, case Runtime::kInterpretOnly: oat_compiler_filter_string += "interpret-only"; break; - case Runtime::kDeferCompilation: - oat_compiler_filter_string += "defer-compilation"; - break; case Runtime::kSpace: oat_compiler_filter_string += "space"; break; @@ -587,6 +584,9 @@ bool ClassLinker::GenerateOatFile(const std::string& dex_filename, case Runtime::kSpeed: oat_compiler_filter_string += "speed"; break; + case Runtime::kEverything: + oat_compiler_filter_string += "everything"; + break; default: LOG(FATAL) << "Unexpected case."; } diff --git a/runtime/runtime.cc b/runtime/runtime.cc index c4a9503..65bd495 100644 --- a/runtime/runtime.cc +++ b/runtime/runtime.cc @@ -583,14 +583,14 @@ Runtime::ParsedOptions* Runtime::ParsedOptions::Create(const Options& options, b Trace::SetDefaultClockSource(kProfilerClockSourceDual); } else if (option == "-compiler-filter:interpret-only") { parsed->compiler_filter_ = kInterpretOnly; - } else if (option == "-compiler-filter:defer-compilation") { - parsed->compiler_filter_ = kDeferCompilation; } else if (option == "-compiler-filter:space") { parsed->compiler_filter_ = kSpace; } else if (option == "-compiler-filter:balanced") { parsed->compiler_filter_ = kBalanced; } else if (option == "-compiler-filter:speed") { parsed->compiler_filter_ = kSpeed; + } else if (option == "-compiler-filter:everything") { + parsed->compiler_filter_ = kEverything; } else if (option == "-sea_ir") { parsed->sea_ir_mode_ = true; } else if (StartsWith(option, "-huge-method-max:")) { diff --git a/runtime/runtime.h b/runtime/runtime.h index 8aba762..be29a86 100644 --- a/runtime/runtime.h +++ b/runtime/runtime.h @@ -65,10 +65,10 @@ class Runtime { enum CompilerFilter { kInterpretOnly, // Compile nothing. - kDeferCompilation, // Temporary minimal compilation, will redo during device idle time. kSpace, // Maximize space savings. kBalanced, // Try to get the best performance return on compilation investment. - kSpeed // Compile all methods. + kSpeed, // Maximize runtime performance. + kEverything // Force compilation (Note: excludes compilaton of class initializers). }; // Guide heuristics to determine whether to compile method if profile data not available. @@ -77,10 +77,10 @@ class Runtime { #else static const CompilerFilter kDefaultCompilerFilter = kSpeed; #endif - static const size_t kDefaultHugeMethodThreshold = 6000; - static const size_t kDefaultLargeMethodThreshold = 1000; - static const size_t kDefaultSmallMethodThreshold = 200; - static const size_t kDefaultTinyMethodThreshold = 10; + static const size_t kDefaultHugeMethodThreshold = 10000; + static const size_t kDefaultLargeMethodThreshold = 600; + static const size_t kDefaultSmallMethodThreshold = 60; + static const size_t kDefaultTinyMethodThreshold = 20; static const size_t kDefaultNumDexMethodsThreshold = 900; class ParsedOptions { |