Additional sanity checking for JIT thresholds
Change e3fc2d1644fd788509b834b01b83a28595721c47 reduced the frequency
of calls to JIT::AddSamples(). The elaborate choices for "default"
threshold selection may fail debug sanity checks.
Bug: 140587109
Test: art --gdb --64 --verbose -Xcompiler-option -g \
-Xjitthreshold:10000 -Xmx512M -Xusejit:true -cp \
./java-benchmarks-v3.dex benchmarks.Recurse.java.Recurse
Test: art --gdb --64 --verbose -Xcompiler-option -g \
-Xjitthreshold:10 -Xmx512M -Xusejit:true -cp \
./java-benchmarks-v3.dex benchmarks.Recurse.java.Recurse
Test: art/test/testrunner/testrunner.py --all-compiler --host -t 137-cfi
Change-Id: I13034bdc0d8f98d818ea83b57b368351388deda6
diff --git a/runtime/jit/jit.cc b/runtime/jit/jit.cc
index 3bdf243..390ea96 100644
--- a/runtime/jit/jit.cc
+++ b/runtime/jit/jit.cc
@@ -54,10 +54,24 @@
static constexpr bool kEnableOnStackReplacement = true;
+// Maximum permitted threshold value.
+static constexpr size_t kJitMaxThreshold = std::numeric_limits<uint16_t>::max();
+
// Different compilation threshold constants. These can be overridden on the command line.
-static constexpr size_t kJitDefaultCompileThreshold = 10000; // Non-debug default.
-static constexpr size_t kJitStressDefaultCompileThreshold = 100; // Fast-debug build.
-static constexpr size_t kJitSlowStressDefaultCompileThreshold = 2; // Slow-debug build.
+
+// Non-debug default
+static constexpr size_t kJitDefaultCompileThreshold = 20 * kJitSamplesBatchSize;
+// Fast-debug build.
+static constexpr size_t kJitStressDefaultCompileThreshold = 2 * kJitSamplesBatchSize;
+// Slow-debug build.
+static constexpr size_t kJitSlowStressDefaultCompileThreshold = 2;
+
+// Different warm-up threshold constants. These default to the equivalent compile thresholds divided
+// by 2, but can be overridden at the command-line.
+static constexpr size_t kJitDefaultWarmUpThreshold = kJitDefaultCompileThreshold / 2;
+static constexpr size_t kJitStressDefaultWarmUpThreshold = kJitStressDefaultCompileThreshold / 2;
+static constexpr size_t kJitSlowStressDefaultWarmUpThreshold =
+ kJitSlowStressDefaultCompileThreshold / 2;
DEFINE_RUNTIME_DEBUG_FLAG(Jit, kSlowMode);
@@ -70,7 +84,7 @@
if (!Jit::kSlowMode) {
threshold = RoundUp(threshold, kJitSamplesBatchSize);
}
- CHECK_LE(threshold, std::numeric_limits<uint16_t>::max());
+ CHECK_LE(threshold, kJitMaxThreshold);
return threshold;
}
@@ -89,32 +103,60 @@
jit_options->thread_pool_pthread_priority_ =
options.GetOrDefault(RuntimeArgumentMap::JITPoolThreadPthreadPriority);
+ // Set default compile threshold to aide with sanity checking defaults.
+ jit_options->compile_threshold_ =
+ kIsDebugBuild
+ ? (Jit::kSlowMode
+ ? kJitSlowStressDefaultCompileThreshold
+ : kJitStressDefaultCompileThreshold)
+ : kJitDefaultCompileThreshold;
+ DCHECK_EQ(RoundUpThreshold(jit_options->compile_threshold_), jit_options->compile_threshold_);
+
+ // Set default warm-up threshold to aide with sanity checking defaults.
+ jit_options->warmup_threshold_ =
+ kIsDebugBuild ? (Jit::kSlowMode
+ ? kJitSlowStressDefaultWarmUpThreshold
+ : kJitStressDefaultWarmUpThreshold)
+ : kJitDefaultWarmUpThreshold;
+ // Warmup threshold should be less than compile threshold (so long as compile threshold is not
+ // zero == JIT-on-first-use).
+ DCHECK_LT(jit_options->warmup_threshold_, jit_options->compile_threshold_);
+ DCHECK_EQ(RoundUpThreshold(jit_options->warmup_threshold_), jit_options->warmup_threshold_);
+
if (options.Exists(RuntimeArgumentMap::JITCompileThreshold)) {
jit_options->compile_threshold_ = *options.Get(RuntimeArgumentMap::JITCompileThreshold);
- } else {
- jit_options->compile_threshold_ =
- kIsDebugBuild
- ? (Jit::kSlowMode
- ? kJitSlowStressDefaultCompileThreshold
- : kJitStressDefaultCompileThreshold)
- : kJitDefaultCompileThreshold;
}
jit_options->compile_threshold_ = RoundUpThreshold(jit_options->compile_threshold_);
+ if (jit_options->compile_threshold_ > kJitMaxThreshold) {
+ LOG(FATAL) << "Compile threshold must be less than maximum ("
+ << jit_options->compile_threshold_
+ << " > "
+ << kJitMaxThreshold
+ << ").";
+ }
if (options.Exists(RuntimeArgumentMap::JITWarmupThreshold)) {
jit_options->warmup_threshold_ = *options.Get(RuntimeArgumentMap::JITWarmupThreshold);
- } else {
- jit_options->warmup_threshold_ = jit_options->compile_threshold_ / 2;
}
jit_options->warmup_threshold_ = RoundUpThreshold(jit_options->warmup_threshold_);
+ // Check compile threshold is either JIT-on-first-use (0) or greater than the warm up threshold.
+ if (jit_options->compile_threshold_ != 0 &&
+ jit_options->warmup_threshold_ >= jit_options->compile_threshold_) {
+ LOG(FATAL) << "Warm-up threshold must be less than compile threshold ("
+ << jit_options->warmup_threshold_
+ << " >= "
+ << jit_options->compile_threshold_
+ << ").";
+ }
+
if (options.Exists(RuntimeArgumentMap::JITOsrThreshold)) {
jit_options->osr_threshold_ = *options.Get(RuntimeArgumentMap::JITOsrThreshold);
} else {
jit_options->osr_threshold_ = jit_options->compile_threshold_ * 2;
- if (jit_options->osr_threshold_ > std::numeric_limits<uint16_t>::max()) {
+ if (jit_options->osr_threshold_ > kJitMaxThreshold) {
jit_options->osr_threshold_ =
- RoundDown(std::numeric_limits<uint16_t>::max(), kJitSamplesBatchSize);
+ RoundDown(kJitMaxThreshold, kJitSamplesBatchSize);
}
}
jit_options->osr_threshold_ = RoundUpThreshold(jit_options->osr_threshold_);