From 85448d4b9c0720049a7ee4afa331870e87d83995 Mon Sep 17 00:00:00 2001 From: Andreas Gampe Date: Tue, 11 Nov 2014 13:28:29 -0800 Subject: [PATCH] ART: Compiled-classes list for compiler-driver Similar to the image-classes list, introduce a list of class names that are to be compiled when creating a boot image. This defaults to all classes. Bug: 18336591 (cherry picked from commit 26318f722958ac1cba6a812026a1377f37c54941) Change-Id: I95f69afdb500a9defb6795803d4040bbe67c5a01 --- compiler/common_compiler_test.cc | 2 +- compiler/driver/compiler_driver.cc | 33 ++++++++++++++++++++++++------ compiler/driver/compiler_driver.h | 12 ++++++++++- compiler/oat_test.cc | 2 +- dex2oat/dex2oat.cc | 42 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 82 insertions(+), 9 deletions(-) diff --git a/compiler/common_compiler_test.cc b/compiler/common_compiler_test.cc index 86167ec9b..5e4623d5b 100644 --- a/compiler/common_compiler_test.cc +++ b/compiler/common_compiler_test.cc @@ -321,7 +321,7 @@ void CommonCompilerTest::SetUp() { method_inliner_map_.get(), compiler_kind, instruction_set, instruction_set_features, - true, new std::set, + true, new std::set, nullptr, 2, true, true, timer_.get())); } // We typically don't generate an image in unit tests, disable this optimization by default. diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc index 9a44adef6..62d70e957 100644 --- a/compiler/driver/compiler_driver.cc +++ b/compiler/driver/compiler_driver.cc @@ -330,7 +330,8 @@ CompilerDriver::CompilerDriver(const CompilerOptions* compiler_options, Compiler::Kind compiler_kind, InstructionSet instruction_set, InstructionSetFeatures instruction_set_features, - bool image, std::set* image_classes, size_t thread_count, + bool image, std::set* image_classes, + std::set* compiled_classes, size_t thread_count, bool dump_stats, bool dump_passes, CumulativeLogger* timer, std::string profile_file) : profile_present_(false), compiler_options_(compiler_options), @@ -344,6 +345,7 @@ CompilerDriver::CompilerDriver(const CompilerOptions* compiler_options, compiled_methods_lock_("compiled method lock"), image_(image), image_classes_(image_classes), + classes_to_compile_(compiled_classes), thread_count_(thread_count), start_ns_(0), stats_(new AOTCompilationStats), @@ -585,7 +587,7 @@ void CompilerDriver::CompileOne(mirror::ArtMethod* method, TimingLogger* timings class_def); } CompileMethod(code_item, access_flags, invoke_type, class_def_idx, method_idx, jclass_loader, - *dex_file, dex_to_dex_compilation_level); + *dex_file, dex_to_dex_compilation_level, true); self->GetJniEnv()->DeleteGlobalRef(jclass_loader); @@ -628,6 +630,17 @@ bool CompilerDriver::IsImageClass(const char* descriptor) const { } } +bool CompilerDriver::IsClassToCompile(const char* descriptor) const { + if (!IsImage()) { + return true; + } else { + if (classes_to_compile_ == nullptr) { + return true; + } + return classes_to_compile_->find(descriptor) != classes_to_compile_->end(); + } +} + static void ResolveExceptionsForMethod(MethodHelper* mh, std::set>& exceptions_to_resolve) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { @@ -1956,6 +1969,10 @@ void CompilerDriver::CompileClass(const ParallelCompilationManager* manager, siz it.Next(); } CompilerDriver* driver = manager->GetCompiler(); + + bool compilation_enabled = driver->IsClassToCompile( + dex_file.StringByTypeIdx(class_def.class_idx_)); + // Compile direct methods int64_t previous_direct_method_idx = -1; while (it.HasNextDirectMethod()) { @@ -1969,7 +1986,8 @@ void CompilerDriver::CompileClass(const ParallelCompilationManager* manager, siz previous_direct_method_idx = method_idx; driver->CompileMethod(it.GetMethodCodeItem(), it.GetMethodAccessFlags(), it.GetMethodInvokeType(class_def), class_def_index, - method_idx, jclass_loader, dex_file, dex_to_dex_compilation_level); + method_idx, jclass_loader, dex_file, dex_to_dex_compilation_level, + compilation_enabled); it.Next(); } // Compile virtual methods @@ -1985,7 +2003,8 @@ void CompilerDriver::CompileClass(const ParallelCompilationManager* manager, siz previous_virtual_method_idx = method_idx; driver->CompileMethod(it.GetMethodCodeItem(), it.GetMethodAccessFlags(), it.GetMethodInvokeType(class_def), class_def_index, - method_idx, jclass_loader, dex_file, dex_to_dex_compilation_level); + method_idx, jclass_loader, dex_file, dex_to_dex_compilation_level, + compilation_enabled); it.Next(); } DCHECK(!it.HasNext()); @@ -2004,7 +2023,8 @@ void CompilerDriver::CompileMethod(const DexFile::CodeItem* code_item, uint32_t InvokeType invoke_type, uint16_t class_def_idx, uint32_t method_idx, jobject class_loader, const DexFile& dex_file, - DexToDexCompilationLevel dex_to_dex_compilation_level) { + DexToDexCompilationLevel dex_to_dex_compilation_level, + bool compilation_enabled) { CompiledMethod* compiled_method = nullptr; uint64_t start_ns = kTimeCompileMethod ? NanoTime() : 0; @@ -2020,7 +2040,8 @@ void CompilerDriver::CompileMethod(const DexFile::CodeItem* code_item, uint32_t } else if ((access_flags & kAccAbstract) != 0) { } else { MethodReference method_ref(&dex_file, method_idx); - bool compile = verification_results_->IsCandidateForCompilation(method_ref, access_flags); + bool compile = compilation_enabled && + verification_results_->IsCandidateForCompilation(method_ref, access_flags); if (compile) { // NOTE: if compiler declines to compile this method, it will return nullptr. compiled_method = compiler_->Compile(code_item, access_flags, invoke_type, class_def_idx, diff --git a/compiler/driver/compiler_driver.h b/compiler/driver/compiler_driver.h index 598e196c0..c487e425c 100644 --- a/compiler/driver/compiler_driver.h +++ b/compiler/driver/compiler_driver.h @@ -104,6 +104,7 @@ class CompilerDriver { InstructionSet instruction_set, InstructionSetFeatures instruction_set_features, bool image, std::set* image_classes, + std::set* compiled_classes, size_t thread_count, bool dump_stats, bool dump_passes, CumulativeLogger* timer, std::string profile_file = ""); @@ -588,6 +589,9 @@ class CompilerDriver { // Checks if class specified by type_idx is one of the image_classes_ bool IsImageClass(const char* descriptor) const; + // Checks if the provided class should be compiled, i.e., is in classes_to_compile_. + bool IsClassToCompile(const char* descriptor) const; + void RecordClassStatus(ClassReference ref, mirror::Class::Status status) LOCKS_EXCLUDED(compiled_classes_lock_); @@ -696,7 +700,8 @@ class CompilerDriver { void CompileMethod(const DexFile::CodeItem* code_item, uint32_t access_flags, InvokeType invoke_type, uint16_t class_def_idx, uint32_t method_idx, jobject class_loader, const DexFile& dex_file, - DexToDexCompilationLevel dex_to_dex_compilation_level) + DexToDexCompilationLevel dex_to_dex_compilation_level, + bool compilation_enabled) LOCKS_EXCLUDED(compiled_methods_lock_); static void CompileClass(const ParallelCompilationManager* context, size_t class_def_index) @@ -736,6 +741,11 @@ class CompilerDriver { // included in the image. std::unique_ptr> image_classes_; + // If image_ is true, specifies the classes that will be compiled in + // the image. Note if classes_to_compile_ is nullptr, all classes are + // included in the image. + std::unique_ptr> classes_to_compile_; + size_t thread_count_; uint64_t start_ns_; diff --git a/compiler/oat_test.cc b/compiler/oat_test.cc index 7c1f6c589..c94fc3094 100644 --- a/compiler/oat_test.cc +++ b/compiler/oat_test.cc @@ -105,7 +105,7 @@ TEST_F(OatTest, WriteRead) { verification_results_.get(), method_inliner_map_.get(), compiler_kind, insn_set, - insn_features, false, NULL, 2, true, true, + insn_features, false, NULL, nullptr, 2, true, true, timer_.get())); jobject class_loader = NULL; if (kCompile) { diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc index 833a678cf..853f103c2 100644 --- a/dex2oat/dex2oat.cc +++ b/dex2oat/dex2oat.cc @@ -353,6 +353,7 @@ class Dex2Oat { const std::string& bitcode_filename, bool image, std::unique_ptr>& image_classes, + std::unique_ptr>& compiled_classes, bool dump_stats, bool dump_passes, TimingLogger& timings, @@ -387,6 +388,7 @@ class Dex2Oat { instruction_set_features_, image, image_classes.release(), + compiled_classes.release(), thread_count_, dump_stats, dump_passes, @@ -840,6 +842,8 @@ static int dex2oat(int argc, char** argv) { std::string bitcode_filename; const char* image_classes_zip_filename = nullptr; const char* image_classes_filename = nullptr; + const char* compiled_classes_zip_filename = nullptr; + const char* compiled_classes_filename = nullptr; std::string image_filename; std::string boot_image_filename; uintptr_t image_base = 0; @@ -939,6 +943,10 @@ static int dex2oat(int argc, char** argv) { image_classes_filename = option.substr(strlen("--image-classes=")).data(); } else if (option.starts_with("--image-classes-zip=")) { image_classes_zip_filename = option.substr(strlen("--image-classes-zip=")).data(); + } else if (option.starts_with("--compiled-classes=")) { + compiled_classes_filename = option.substr(strlen("--compiled-classes=")).data(); + } else if (option.starts_with("--compiled-classes-zip=")) { + compiled_classes_zip_filename = option.substr(strlen("--compiled-classes-zip=")).data(); } else if (option.starts_with("--base=")) { const char* image_base_str = option.substr(strlen("--base=")).data(); char* end; @@ -1120,6 +1128,18 @@ static int dex2oat(int argc, char** argv) { Usage("--image-classes-zip should be used with --image-classes"); } + if (compiled_classes_filename != nullptr && !image) { + Usage("--compiled-classes should only be used with --image"); + } + + if (compiled_classes_filename != nullptr && !boot_image_option.empty()) { + Usage("--compiled-classes should not be used with --boot-image"); + } + + if (compiled_classes_zip_filename != nullptr && compiled_classes_filename == nullptr) { + Usage("--compiled-classes-zip should be used with --compiled-classes"); + } + if (dex_filenames.empty() && zip_fd == -1) { Usage("Input must be supplied with either --dex-file or --zip-fd"); } @@ -1326,6 +1346,27 @@ static int dex2oat(int argc, char** argv) { } else if (image) { image_classes.reset(new std::set); } + // If --compiled-classes was specified, calculate the full list of classes to compile in the + // image. + std::unique_ptr> compiled_classes(nullptr); + if (compiled_classes_filename != nullptr) { + std::string error_msg; + if (compiled_classes_zip_filename != nullptr) { + compiled_classes.reset(dex2oat->ReadImageClassesFromZip(compiled_classes_zip_filename, + compiled_classes_filename, + &error_msg)); + } else { + compiled_classes.reset(dex2oat->ReadImageClassesFromFile(compiled_classes_filename)); + } + if (compiled_classes.get() == nullptr) { + LOG(ERROR) << "Failed to create list of compiled classes from '" << compiled_classes_filename + << "': " << error_msg; + timings.EndTiming(); + return EXIT_FAILURE; + } + } else if (image) { + compiled_classes.reset(nullptr); // By default compile everything. + } std::vector dex_files; if (boot_image_option.empty()) { @@ -1427,6 +1468,7 @@ static int dex2oat(int argc, char** argv) { bitcode_filename, image, image_classes, + compiled_classes, dump_stats, dump_passes, timings, -- 2.11.0