Compile less stuff
Don't compile class initializers, compile programs with fewer than
commmand-line specified number of methods, mildly refactor SLOW_MODE,
rename into LIGHT_MODE.
Also, walks the image for uncompiled methods and fixes up with pointers to the
interpreter entry point.
(Removed hot method list and light method limit as these are experimental.)
Change-Id: I2ae33d8add84ab9f4d76f9d910cae422c81a7832
diff --git a/src/class_linker.cc b/src/class_linker.cc
index 4774c63..7dcd511 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -954,10 +954,11 @@
mirror::ObjectArray<mirror::Class>* class_roots =
space->GetImageHeader().GetImageRoot(ImageHeader::kClassRoots)->AsObjectArray<mirror::Class>();
+ class_roots_ = class_roots;
// Special case of setting up the String class early so that we can test arbitrary objects
// as being Strings or not
- mirror::String::SetClass(class_roots->Get(kJavaLangString));
+ mirror::String::SetClass(GetClassRoot(kJavaLangString));
CHECK_EQ(oat_file->GetOatHeader().GetDexFileCount(),
static_cast<uint32_t>(dex_caches->GetLength()));
@@ -978,6 +979,11 @@
AppendToBootClassPath(*dex_file, dex_cache);
}
+ // Set classes on AbstractMethod early so that IsMethod tests can be performed during the live
+ // bitmap walk.
+ mirror::AbstractMethod::SetClasses(GetClassRoot(kJavaLangReflectConstructor),
+ GetClassRoot(kJavaLangReflectMethod));
+
// reinit clases_ table
{
ReaderMutexLock mu(self, *Locks::heap_bitmap_lock_);
@@ -994,8 +1000,6 @@
DCHECK(array_iftable_ == GetClassRoot(kBooleanArrayClass)->GetIfTable());
// String class root was set above
mirror::Field::SetClass(GetClassRoot(kJavaLangReflectField));
- mirror::AbstractMethod::SetClasses(GetClassRoot(kJavaLangReflectConstructor),
- GetClassRoot(kJavaLangReflectMethod));
mirror::BooleanArray::SetArrayClass(GetClassRoot(kBooleanArrayClass));
mirror::ByteArray::SetArrayClass(GetClassRoot(kByteArrayClass));
mirror::CharArray::SetArrayClass(GetClassRoot(kCharArrayClass));
@@ -1029,6 +1033,15 @@
DCHECK(existing == NULL) << kh.GetDescriptor();
return;
}
+
+ // Check if object is an uncompiled method and point the to the interpreter entry point.
+ if (obj->IsMethod()) {
+ mirror::AbstractMethod* method = obj->AsMethod();
+ if (method->GetCode() == NULL) {
+ const void* interpreter_entry = GetInterpreterEntryPoint();
+ method->SetCode(interpreter_entry);
+ }
+ }
}
// Keep in sync with InitCallback. Anything we visit, we need to
diff --git a/src/common_test.h b/src/common_test.h
index 4f91717..68b0cf6 100644
--- a/src/common_test.h
+++ b/src/common_test.h
@@ -212,7 +212,7 @@
compiler_driver_->GetCompiledMethod(CompilerDriver::MethodReference(&dex_file,
method->GetDexMethodIndex()));
-#ifndef ART_SLOW_MODE
+#ifndef ART_LIGHT_MODE
CHECK(compiled_method != NULL) << PrettyMethod(method);
#endif
}
@@ -373,8 +373,8 @@
}
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, image_classes_.get(),
- true, true));
+ compiler_driver_.reset(new CompilerDriver(compiler_backend, instruction_set, true, 2, false, false,
+ image_classes_.get(), true, true));
// Create the heap thread pool so that the GC runs in parallel for tests. Normally, the thread
// pool is created by the runtime.
diff --git a/src/compiler/driver/compiler_driver.cc b/src/compiler/driver/compiler_driver.cc
index 204f639..f08e629 100644
--- a/src/compiler/driver/compiler_driver.cc
+++ b/src/compiler/driver/compiler_driver.cc
@@ -284,9 +284,9 @@
}
CompilerDriver::CompilerDriver(CompilerBackend compiler_backend, InstructionSet instruction_set,
- bool image, size_t thread_count, bool support_debugging,
- const std::set<std::string>* image_classes, bool dump_stats,
- bool dump_timings)
+ bool image, size_t thread_count, bool support_debugging, bool light_mode,
+ const std::set<std::string>* image_classes,
+ bool dump_stats, bool dump_timings)
: compiler_backend_(compiler_backend),
instruction_set_(instruction_set),
freezing_constructor_lock_("freezing constructor lock"),
@@ -295,6 +295,7 @@
image_(image),
thread_count_(thread_count),
support_debugging_(support_debugging),
+ light_mode_(light_mode),
start_ns_(0),
stats_(new AOTCompilationStats),
dump_stats_(dump_stats),
@@ -1612,10 +1613,15 @@
CHECK(compiled_method != NULL);
} else if ((access_flags & kAccAbstract) != 0) {
} else {
- bool dont_compile = false;
-#if ART_SLOW_MODE
- dont_compile = (image_classes_ == NULL) || (image_classes_->size() == 0);
-#endif // ART_SLOW_MODE
+ std::string method_name(PrettyMethod(method_idx, dex_file, false));
+ // In light mode we only compile image classes.
+ bool dont_compile = light_mode_ && ((image_classes_ == NULL) || (image_classes_->size() == 0));
+
+ // Don't compile class initializers, ever.
+ if ((access_flags & kAccConstructor) && (access_flags & kAccStatic)) {
+ dont_compile = true;
+ }
+
if (!dont_compile) {
compiled_method = (*compiler_)(*this, code_item, access_flags, invoke_type, class_def_idx,
method_idx, class_loader, dex_file);
diff --git a/src/compiler/driver/compiler_driver.h b/src/compiler/driver/compiler_driver.h
index 385bc00..fae6902 100644
--- a/src/compiler/driver/compiler_driver.h
+++ b/src/compiler/driver/compiler_driver.h
@@ -67,9 +67,9 @@
// 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,
- const std::set<std::string>* image_classes, bool dump_stats,
- bool dump_timings);
+ size_t thread_count, bool support_debugging, bool light_mode,
+ const std::set<std::string>* image_classes,
+ bool dump_stats, bool dump_timings);
~CompilerDriver();
@@ -84,6 +84,10 @@
return support_debugging_;
}
+ bool IsLightMode() const {
+ return light_mode_;
+ }
+
InstructionSet GetInstructionSet() const {
return instruction_set_;
}
@@ -340,6 +344,7 @@
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 ecba628..97212ce 100644
--- a/src/dex2oat.cc
+++ b/src/dex2oat.cc
@@ -137,6 +137,8 @@
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);
}
@@ -144,14 +146,15 @@
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)
+ InstructionSet instruction_set, size_t thread_count, bool support_debugging,
+ bool light_mode)
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);
+ support_debugging, light_mode);
return true;
}
@@ -160,6 +163,7 @@
LOG(INFO) << "dex2oat took " << PrettyDuration(NanoTime() - start_ns_) << " (threads: " << thread_count_ << ")";
}
+
// Make a list of descriptors for classes to include in the image
const std::set<std::string>* GetImageClassDescriptors(const char* image_classes_filename)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
@@ -261,6 +265,7 @@
image,
thread_count_,
support_debugging_,
+ light_mode_,
image_classes,
dump_stats,
dump_timings));
@@ -339,14 +344,23 @@
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)
+ size_t thread_count, bool support_debugging, bool light_mode)
: 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()) {
}
@@ -484,6 +498,7 @@
Runtime* runtime_;
size_t thread_count_;
bool support_debugging_;
+ bool light_mode_;
uint64_t start_ns_;
DISALLOW_IMPLICIT_CONSTRUCTORS(Dex2Oat);
@@ -671,6 +686,7 @@
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
@@ -690,6 +706,10 @@
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]);
bool log_options = false;
@@ -718,6 +738,8 @@
}
} 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") {
@@ -923,7 +945,7 @@
}
Dex2Oat* p_dex2oat;
- if (!Dex2Oat::Create(&p_dex2oat, options, compiler_backend, instruction_set, thread_count, support_debugging)) {
+ if (!Dex2Oat::Create(&p_dex2oat, options, compiler_backend, instruction_set, thread_count, support_debugging, light_mode)) {
LOG(ERROR) << "Failed to create dex2oat";
return EXIT_FAILURE;
}
@@ -970,6 +992,7 @@
}
}
+
UniquePtr<const CompilerDriver> compiler(dex2oat->CreateOatFile(boot_image_option,
host_prefix.get(),
android_root,
diff --git a/src/oat_test.cc b/src/oat_test.cc
index 75a9dbb..5d6edf2 100644
--- a/src/oat_test.cc
+++ b/src/oat_test.cc
@@ -76,7 +76,8 @@
#else
CompilerBackend compiler_backend = kQuick;
#endif
- compiler_driver_.reset(new CompilerDriver(compiler_backend, kThumb2, false, 2, false, NULL, true, true));
+ compiler_driver_.reset(new CompilerDriver(compiler_backend, kThumb2, false, 2, false, false,
+ NULL, true, true));
compiler_driver_->CompileAll(class_loader, class_linker->GetBootClassPath());
}