Compile filter for small applications and methods
Adds a filter per method and program size (in method count). Right now, options are treated
as runtime options...but we might want to change this and separate options for compilers and
runtime.
Change-Id: I8c3e925116119af8ffa95ff09f77bcfdd173767b
diff --git a/build/Android.common.mk b/build/Android.common.mk
index c8212ef..2453fa9 100644
--- a/build/Android.common.mk
+++ b/build/Android.common.mk
@@ -14,10 +14,10 @@
# limitations under the License.
#
-ART_LIGHT_MODE := false
-ifneq ($(wildcard art/LIGHT_ART),)
-$(info Enabling ART_LIGHT_MODE because of existence of art/LIGHT_ART)
-ART_LIGHT_MODE := true
+ART_SMALL_MODE := false
+ifneq ($(wildcard art/SMALL_ART),)
+$(info Enabling ART_SMALL_MODE because of existence of art/SMALL_ART)
+ART_SMALL_MODE := true
endif
ART_USE_PORTABLE_COMPILER := false
diff --git a/src/common_test.h b/src/common_test.h
index 6876274..cc68f44 100644
--- a/src/common_test.h
+++ b/src/common_test.h
@@ -364,7 +364,7 @@
}
class_linker_->FixupDexCaches(runtime_->GetResolutionMethod());
image_classes_.reset(new std::set<std::string>);
- compiler_driver_.reset(new CompilerDriver(compiler_backend, instruction_set, true, 2, false, false,
+ compiler_driver_.reset(new CompilerDriver(compiler_backend, instruction_set, true, 2, false,
image_classes_.get(), true, true));
// Create the heap thread pool so that the GC runs in parallel for tests. Normally, the thread
diff --git a/src/compiler/driver/compiler_driver.cc b/src/compiler/driver/compiler_driver.cc
index 1660914..3075a54 100644
--- a/src/compiler/driver/compiler_driver.cc
+++ b/src/compiler/driver/compiler_driver.cc
@@ -283,7 +283,7 @@
}
CompilerDriver::CompilerDriver(CompilerBackend compiler_backend, InstructionSet instruction_set,
- bool image, size_t thread_count, bool support_debugging, bool light_mode,
+ bool image, size_t thread_count, bool support_debugging,
const std::set<std::string>* image_classes,
bool dump_stats, bool dump_timings)
: compiler_backend_(compiler_backend),
@@ -294,7 +294,6 @@
image_(image),
thread_count_(thread_count),
support_debugging_(support_debugging),
- light_mode_(light_mode),
start_ns_(0),
stats_(new AOTCompilationStats),
dump_stats_(dump_stats),
@@ -1566,12 +1565,15 @@
CHECK(compiled_method != NULL);
} else if ((access_flags & kAccAbstract) != 0) {
} else {
- // In light mode we only compile image classes.
- bool dont_compile = light_mode_ && ((image_classes_ == NULL) || (image_classes_->size() == 0));
+ // In small mode we only compile image classes.
+ bool dont_compile = Runtime::Current()->IsSmallMode() && ((image_classes_ == NULL) || (image_classes_->size() == 0));
// Don't compile class initializers, ever.
if (((access_flags & kAccConstructor) != 0) && ((access_flags & kAccStatic) != 0)) {
dont_compile = true;
+ } else if (code_item->insns_size_in_code_units_ < Runtime::Current()->GetSmallModeMethodDexSizeLimit()) {
+ // Do compile small methods.
+ dont_compile = false;
}
if (!dont_compile) {
diff --git a/src/compiler/driver/compiler_driver.h b/src/compiler/driver/compiler_driver.h
index a20e5ef..7c37c6a 100644
--- a/src/compiler/driver/compiler_driver.h
+++ b/src/compiler/driver/compiler_driver.h
@@ -67,7 +67,7 @@
// can assume will be in the image, with NULL implying all available
// classes.
explicit CompilerDriver(CompilerBackend compiler_backend, InstructionSet instruction_set, bool image,
- size_t thread_count, bool support_debugging, bool light_mode,
+ size_t thread_count, bool support_debugging,
const std::set<std::string>* image_classes,
bool dump_stats, bool dump_timings);
@@ -84,10 +84,6 @@
return support_debugging_;
}
- bool IsLightMode() const {
- return light_mode_;
- }
-
InstructionSet GetInstructionSet() const {
return instruction_set_;
}
@@ -331,7 +327,6 @@
bool image_;
size_t thread_count_;
bool support_debugging_;
- const bool light_mode_;
uint64_t start_ns_;
UniquePtr<AOTCompilationStats> stats_;
diff --git a/src/dex2oat.cc b/src/dex2oat.cc
index e41e537..37d2996 100644
--- a/src/dex2oat.cc
+++ b/src/dex2oat.cc
@@ -137,8 +137,6 @@
UsageError(" Use a separate --runtime-arg switch for each argument.");
UsageError(" Example: --runtime-arg -Xms256m");
UsageError("");
- UsageError(" --light-mode: compile only if generating image file");
- UsageError("");
std::cerr << "See log for usage error information\n";
exit(EXIT_FAILURE);
}
@@ -146,15 +144,14 @@
class Dex2Oat {
public:
static bool Create(Dex2Oat** p_dex2oat, Runtime::Options& options, CompilerBackend compiler_backend,
- InstructionSet instruction_set, size_t thread_count, bool support_debugging,
- bool light_mode)
+ InstructionSet instruction_set, size_t thread_count, bool support_debugging)
SHARED_TRYLOCK_FUNCTION(true, Locks::mutator_lock_) {
if (!CreateRuntime(options, instruction_set)) {
*p_dex2oat = NULL;
return false;
}
*p_dex2oat = new Dex2Oat(Runtime::Current(), compiler_backend, instruction_set, thread_count,
- support_debugging, light_mode);
+ support_debugging);
return true;
}
@@ -265,7 +262,6 @@
image,
thread_count_,
support_debugging_,
- light_mode_,
image_classes,
dump_stats,
dump_timings));
@@ -274,6 +270,7 @@
driver->SetBitcodeFileName(bitcode_filename);
}
+
Thread::Current()->TransitionFromRunnableToSuspended(kNative);
driver->CompileAll(class_loader, dex_files);
@@ -344,23 +341,14 @@
return true;
}
- void SetLightMode(bool light_mode) {
- light_mode_ = light_mode;
- }
-
- bool GetLightMode() {
- return light_mode_;
- }
-
private:
explicit Dex2Oat(Runtime* runtime, CompilerBackend compiler_backend, InstructionSet instruction_set,
- size_t thread_count, bool support_debugging, bool light_mode)
+ size_t thread_count, bool support_debugging)
: compiler_backend_(compiler_backend),
instruction_set_(instruction_set),
runtime_(runtime),
thread_count_(thread_count),
support_debugging_(support_debugging),
- light_mode_(light_mode),
start_ns_(NanoTime()) {
}
@@ -486,7 +474,6 @@
Runtime* runtime_;
size_t thread_count_;
bool support_debugging_;
- bool light_mode_;
uint64_t start_ns_;
DISALLOW_IMPLICIT_CONSTRUCTORS(Dex2Oat);
@@ -674,7 +661,6 @@
std::vector<const char*> runtime_args;
int thread_count = sysconf(_SC_NPROCESSORS_CONF);
bool support_debugging = false;
- bool light_mode = false;
#if defined(ART_USE_PORTABLE_COMPILER)
CompilerBackend compiler_backend = kPortable;
#else
@@ -694,9 +680,6 @@
bool dump_timings = kIsDebugBuild;
bool watch_dog_enabled = !kIsTargetBuild;
-#if ART_LIGHT_MODE
- light_mode = true;
-#endif // ART_LIGHT_MODE
for (int i = 0; i < argc; i++) {
const StringPiece option(argv[i]);
@@ -726,8 +709,6 @@
}
} else if (option == "-g") {
support_debugging = true;
- } else if (option == "--light-mode") {
- light_mode = true;
} else if (option == "--watch-dog") {
watch_dog_enabled = true;
} else if (option == "--no-watch-dog") {
@@ -932,8 +913,13 @@
options.push_back(std::make_pair(runtime_args[i], reinterpret_cast<void*>(NULL)));
}
+#if ART_SMALL_MODE
+ options.push_back(std::make_pair("-small", reinterpret_cast<void*>(NULL)));
+#endif // ART_SMALL_MODE
+
Dex2Oat* p_dex2oat;
- if (!Dex2Oat::Create(&p_dex2oat, options, compiler_backend, instruction_set, thread_count, support_debugging, light_mode)) {
+ if (!Dex2Oat::Create(&p_dex2oat, options, compiler_backend, instruction_set, thread_count,
+ support_debugging)) {
LOG(ERROR) << "Failed to create dex2oat";
return EXIT_FAILURE;
}
@@ -980,6 +966,21 @@
}
}
+ // If we're in small mode, but the program is small, turn off small mode.
+ // It doesn't make a difference for the boot image, so let's skip the check
+ // altogether.
+ if (Runtime::Current()->IsSmallMode() && !image) {
+ size_t num_methods = 0;
+ for (size_t i = 0; i != dex_files.size(); ++i) {
+ const DexFile* dex_file = dex_files[i];
+ CHECK(dex_file != NULL);
+ num_methods += dex_file->NumMethodIds();
+ }
+ if (num_methods <= Runtime::Current()->GetSmallModeMethodThreshold()) {
+ Runtime::Current()->SetSmallMode(false);
+ LOG(INFO) << "Below method threshold, compiling anyways";
+ }
+ }
UniquePtr<const CompilerDriver> compiler(dex2oat->CreateOatFile(boot_image_option,
host_prefix.get(),
diff --git a/src/oat_test.cc b/src/oat_test.cc
index 5d6edf2..7c702e2 100644
--- a/src/oat_test.cc
+++ b/src/oat_test.cc
@@ -76,7 +76,7 @@
#else
CompilerBackend compiler_backend = kQuick;
#endif
- compiler_driver_.reset(new CompilerDriver(compiler_backend, kThumb2, false, 2, false, false,
+ compiler_driver_.reset(new CompilerDriver(compiler_backend, kThumb2, false, 2, false,
NULL, true, true));
compiler_driver_->CompileAll(class_loader, class_linker->GetBootClassPath());
}
diff --git a/src/runtime.cc b/src/runtime.cc
index 25d26b8..d886fe3 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -364,6 +364,10 @@
parsed->hook_exit_ = exit;
parsed->hook_abort_ = NULL; // We don't call abort(3) by default; see Runtime::Abort.
+ parsed->small_mode_ = true;
+ parsed->small_mode_method_threshold_ = Runtime::kDefaultSmallModeMethodThreshold;
+ parsed->small_mode_method_dex_size_limit_ = Runtime::kDefaultSmallModeMethodDexSizeLimit;
+
// gLogVerbosity.class_linker = true; // TODO: don't check this in!
// gLogVerbosity.compiler = true; // TODO: don't check this in!
// gLogVerbosity.heap = true; // TODO: don't check this in!
@@ -571,6 +575,12 @@
Trace::SetDefaultClockSource(kProfilerClockSourceWall);
} else if (option == "-Xprofile:dualclock") {
Trace::SetDefaultClockSource(kProfilerClockSourceDual);
+ } else if (option == "-small") {
+ parsed->small_mode_ = true;
+ } else if (StartsWith(option, "-small-mode-methods-max:")) {
+ parsed->small_mode_method_threshold_ = ParseIntegerOrDie(option);
+ } else if (StartsWith(option, "-small-mode-methods-size-max:")) {
+ parsed->small_mode_method_dex_size_limit_ = ParseIntegerOrDie(option);
} else {
if (!ignore_unrecognized) {
// TODO: print usage via vfprintf
@@ -791,6 +801,10 @@
is_zygote_ = options->is_zygote_;
is_concurrent_gc_enabled_ = options->is_concurrent_gc_enabled_;
+ small_mode_ = options->small_mode_;
+ small_mode_method_threshold_ = options->small_mode_method_threshold_;
+ small_mode_method_dex_size_limit_ = options->small_mode_method_dex_size_limit_;
+
vfprintf_ = options->hook_vfprintf_;
exit_ = options->hook_exit_;
abort_ = options->hook_abort_;
diff --git a/src/runtime.h b/src/runtime.h
index c7ccda1..ac9b50b 100644
--- a/src/runtime.h
+++ b/src/runtime.h
@@ -61,6 +61,9 @@
public:
typedef std::vector<std::pair<std::string, const void*> > Options;
+ static const size_t kDefaultSmallModeMethodThreshold = 10;
+ static const size_t kDefaultSmallModeMethodDexSizeLimit = 100;
+
class ParsedOptions {
public:
// returns null if problem parsing and ignore_unrecognized is false
@@ -95,6 +98,9 @@
void (*hook_exit_)(jint status);
void (*hook_abort_)();
std::vector<std::string> properties_;
+ bool small_mode_;
+ size_t small_mode_method_threshold_;
+ size_t small_mode_method_dex_size_limit_;
private:
ParsedOptions() {}
@@ -116,6 +122,23 @@
return is_concurrent_gc_enabled_;
}
+ bool IsSmallMode() const {
+ return small_mode_;
+ }
+
+
+ void SetSmallMode(bool small_mode) {
+ small_mode_ = small_mode;
+ }
+
+ size_t GetSmallModeMethodThreshold() const {
+ return small_mode_method_threshold_;
+ }
+
+ size_t GetSmallModeMethodDexSizeLimit() const {
+ return small_mode_method_dex_size_limit_;
+ }
+
const std::string& GetHostPrefix() const {
DCHECK(!IsStarted());
return host_prefix_;
@@ -339,6 +362,10 @@
bool is_zygote_;
bool is_concurrent_gc_enabled_;
+ bool small_mode_;
+ size_t small_mode_method_threshold_;
+ size_t small_mode_method_dex_size_limit_;
+
// The host prefix is used during cross compilation. It is removed
// from the start of host paths such as:
// $ANDROID_PRODUCT_OUT/system/framework/boot.oat
diff --git a/src/runtime_support.cc b/src/runtime_support.cc
index 6ea05b4..d9b369b 100644
--- a/src/runtime_support.cc
+++ b/src/runtime_support.cc
@@ -211,7 +211,7 @@
if (fields_class->IsInitialized()) {
return resolved_field;
} else if (Runtime::Current()->GetClassLinker()->EnsureInitialized(fields_class, true, true)) {
- // otherwise let's ensure the class is initialized before resolving the field
+ // Otherwise let's ensure the class is initialized before resolving the field.
return resolved_field;
} else {
DCHECK(self->IsExceptionPending()); // Throw exception and unwind