summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbuzbee <buzbee@google.com>2013-08-21 22:14:23 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2013-08-21 22:14:24 +0000
commitdd3413f4a1a4fcf9fd62b4660805a4ce64b22bd6 (patch)
tree6fd61b2f41f7282d140d347b3bd93eea97f7bf30
parentb8a0b94735f188bc739e4c55479c37699006b881 (diff)
parentfe9ca4028f379688ecba6132ac3738171176b3e4 (diff)
downloadart-dd3413f4a1a4fcf9fd62b4660805a4ce64b22bd6.zip
art-dd3413f4a1a4fcf9fd62b4660805a4ce64b22bd6.tar.gz
art-dd3413f4a1a4fcf9fd62b4660805a4ce64b22bd6.tar.bz2
Merge "Compiler filter update" into dalvik-dev
-rw-r--r--compiler/dex/mir_analysis.cc80
-rw-r--r--compiler/dex/mir_graph.h4
-rw-r--r--dex2oat/dex2oat.cc7
-rw-r--r--runtime/class_linker.cc6
-rw-r--r--runtime/runtime.cc4
-rw-r--r--runtime/runtime.h12
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 {