diff options
author | Andreas Gampe <agampe@google.com> | 2015-04-15 02:37:28 -0700 |
---|---|---|
committer | Andreas Gampe <agampe@google.com> | 2015-04-21 15:03:15 -0700 |
commit | 70bef0d8f6aa30b0da5c6ca56e1bc5729f74654b (patch) | |
tree | aea4a31294c5a6a30c52ee886d5884a0b5b84fde /compiler/driver | |
parent | bbf02afc641a393d33342976e269218668c07386 (diff) | |
download | android_art-70bef0d8f6aa30b0da5c6ca56e1bc5729f74654b.tar.gz android_art-70bef0d8f6aa30b0da5c6ca56e1bc5729f74654b.tar.bz2 android_art-70bef0d8f6aa30b0da5c6ca56e1bc5729f74654b.zip |
ART: Add compiled-methods
Add a dex2oat option for compiled-methods, a more granular filter
than compiled-classes. Add compiler-driver support for it.
Refactor dex2oat to reuse file reading.
Add a test to oat_test.
Change-Id: I78d0d040bce7738b4bb7aabe7768b5788d2587ac
Diffstat (limited to 'compiler/driver')
-rw-r--r-- | compiler/driver/compiler_driver.cc | 23 | ||||
-rw-r--r-- | compiler/driver/compiler_driver.h | 9 | ||||
-rw-r--r-- | compiler/driver/compiler_driver_test.cc | 54 |
3 files changed, 83 insertions, 3 deletions
diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc index 1832647f4e..e665e1d4e8 100644 --- a/compiler/driver/compiler_driver.cc +++ b/compiler/driver/compiler_driver.cc @@ -76,8 +76,8 @@ static constexpr bool kTimeCompileMethod = !kIsDebugBuild; // Whether to produce 64-bit ELF files for 64-bit targets. Leave this off for now. static constexpr bool kProduce64BitELFFiles = false; -// Whether classes-to-compile is only applied to the boot image, or, when given, too all -// compilations. +// Whether classes-to-compile and methods-to-compile are only applied to the boot image, or, when +// given, too all compilations. static constexpr bool kRestrictCompilationFiltersToImage = true; static double Percentage(size_t x, size_t y) { @@ -349,6 +349,7 @@ CompilerDriver::CompilerDriver(const CompilerOptions* compiler_options, const InstructionSetFeatures* instruction_set_features, bool image, std::unordered_set<std::string>* image_classes, std::unordered_set<std::string>* compiled_classes, + std::unordered_set<std::string>* compiled_methods, size_t thread_count, bool dump_stats, bool dump_passes, const std::string& dump_cfg_file_name, CumulativeLogger* timer, int swap_fd, const std::string& profile_file) @@ -369,6 +370,7 @@ CompilerDriver::CompilerDriver(const CompilerOptions* compiler_options, image_(image), image_classes_(image_classes), classes_to_compile_(compiled_classes), + methods_to_compile_(compiled_methods), had_hard_verifier_failure_(false), thread_count_(thread_count), stats_(new AOTCompilationStats), @@ -670,6 +672,19 @@ bool CompilerDriver::IsClassToCompile(const char* descriptor) const { return classes_to_compile_->find(descriptor) != classes_to_compile_->end(); } +bool CompilerDriver::IsMethodToCompile(const MethodReference& method_ref) const { + if (kRestrictCompilationFiltersToImage && !IsImage()) { + return true; + } + + if (methods_to_compile_ == nullptr) { + return true; + } + + std::string tmp = PrettyMethod(method_ref.dex_method_index, *method_ref.dex_file, true); + return methods_to_compile_->find(tmp.c_str()) != methods_to_compile_->end(); +} + static void ResolveExceptionsForMethod(MutableHandle<mirror::ArtMethod> method_handle, std::set<std::pair<uint16_t, const DexFile*>>& exceptions_to_resolve) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { @@ -2232,7 +2247,9 @@ void CompilerDriver::CompileMethod(Thread* self, const DexFile::CodeItem* code_i // Basic checks, e.g., not <clinit>. verification_results_->IsCandidateForCompilation(method_ref, access_flags) && // Did not fail to create VerifiedMethod metadata. - has_verified_method; + has_verified_method && + // Is eligable for compilation by methods-to-compile filter. + IsMethodToCompile(method_ref); 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 ce13a17792..50e1fb14e5 100644 --- a/compiler/driver/compiler_driver.h +++ b/compiler/driver/compiler_driver.h @@ -104,6 +104,7 @@ class CompilerDriver { const InstructionSetFeatures* instruction_set_features, bool image, std::unordered_set<std::string>* image_classes, std::unordered_set<std::string>* compiled_classes, + std::unordered_set<std::string>* compiled_methods, size_t thread_count, bool dump_stats, bool dump_passes, const std::string& dump_cfg_file_name, CumulativeLogger* timer, int swap_fd, @@ -428,6 +429,9 @@ class CompilerDriver { // Checks whether the provided class should be compiled, i.e., is in classes_to_compile_. bool IsClassToCompile(const char* descriptor) const; + // Checks whether the provided method should be compiled, i.e., is in method_to_compile_. + bool IsMethodToCompile(const MethodReference& method_ref) const; + void RecordClassStatus(ClassReference ref, mirror::Class::Status status) LOCKS_EXCLUDED(compiled_classes_lock_); @@ -597,6 +601,11 @@ class CompilerDriver { // This option may be restricted to the boot image, depending on a flag in the implementation. std::unique_ptr<std::unordered_set<std::string>> classes_to_compile_; + // Specifies the methods that will be compiled. Note that if methods_to_compile_ is nullptr, + // all methods are eligible for compilation (compilation filters etc. will still apply). + // This option may be restricted to the boot image, depending on a flag in the implementation. + std::unique_ptr<std::unordered_set<std::string>> methods_to_compile_; + bool had_hard_verifier_failure_; size_t thread_count_; diff --git a/compiler/driver/compiler_driver_test.cc b/compiler/driver/compiler_driver_test.cc index e78ff9078b..ded50ca105 100644 --- a/compiler/driver/compiler_driver_test.cc +++ b/compiler/driver/compiler_driver_test.cc @@ -175,6 +175,60 @@ TEST_F(CompilerDriverTest, AbstractMethodErrorStub) { } } +class CompilerDriverMethodsTest : public CompilerDriverTest { + protected: + std::unordered_set<std::string>* GetCompiledMethods() OVERRIDE { + return new std::unordered_set<std::string>({ + "byte StaticLeafMethods.identity(byte)", + "int StaticLeafMethods.sum(int, int, int)", + "double StaticLeafMethods.sum(double, double, double, double)" + }); + } +}; + +TEST_F(CompilerDriverMethodsTest, Selection) { + Thread* self = Thread::Current(); + jobject class_loader; + { + ScopedObjectAccess soa(self); + class_loader = LoadDex("StaticLeafMethods"); + } + ASSERT_NE(class_loader, nullptr); + + // Need to enable dex-file writability. Methods rejected to be compiled will run through the + // dex-to-dex compiler. + for (const DexFile* dex_file : GetDexFiles(class_loader)) { + ASSERT_TRUE(dex_file->EnableWrite()); + } + + CompileAll(class_loader); + + ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); + StackHandleScope<1> hs(self); + ScopedObjectAccess soa(self); + Handle<mirror::ClassLoader> h_loader(hs.NewHandle( + reinterpret_cast<mirror::ClassLoader*>(self->DecodeJObject(class_loader)))); + mirror::Class* klass = class_linker->FindClass(self, "LStaticLeafMethods;", h_loader); + ASSERT_NE(klass, nullptr); + + std::unique_ptr<std::unordered_set<std::string>> expected(GetCompiledMethods()); + + for (int32_t i = 0; static_cast<uint32_t>(i) < klass->NumDirectMethods(); i++) { + mirror::ArtMethod* m = klass->GetDirectMethod(i); + std::string name = PrettyMethod(m, true); + const void* code = + m->GetEntryPointFromQuickCompiledCodePtrSize(InstructionSetPointerSize(kRuntimeISA)); + ASSERT_NE(code, nullptr); + if (expected->find(name) != expected->end()) { + expected->erase(name); + EXPECT_FALSE(class_linker->IsQuickToInterpreterBridge(code)); + } else { + EXPECT_TRUE(class_linker->IsQuickToInterpreterBridge(code)); + } + } + EXPECT_TRUE(expected->empty()); +} + // TODO: need check-cast test (when stub complete & we can throw/catch } // namespace art |