diff options
| author | Vladimir Marko <vmarko@google.com> | 2018-06-21 16:15:42 +0100 |
|---|---|---|
| committer | Vladimir Marko <vmarko@google.com> | 2018-06-25 11:30:07 +0100 |
| commit | dc4bccef0ded1c261bf9838def2ef329765a8682 (patch) | |
| tree | f007ff3f747ae2d1e6a20d9bd9c017b2ce191f1e /compiler/driver | |
| parent | eebb821b1adaf2db7662fc1c3ff4e9fcfe59a694 (diff) | |
| download | art-dc4bccef0ded1c261bf9838def2ef329765a8682.tar.gz art-dc4bccef0ded1c261bf9838def2ef329765a8682.tar.bz2 art-dc4bccef0ded1c261bf9838def2ef329765a8682.zip | |
Move image_classes_ to CompilerOptions.
Test: m test-art-host-gtest
Test: testrunner.py --host --optimizing
Change-Id: Ifb30e071d7b39ae939fc3f83d7eba82fd077c7e8
Diffstat (limited to 'compiler/driver')
| -rw-r--r-- | compiler/driver/compiler_driver.cc | 108 | ||||
| -rw-r--r-- | compiler/driver/compiler_driver.h | 35 | ||||
| -rw-r--r-- | compiler/driver/compiler_options.cc | 14 | ||||
| -rw-r--r-- | compiler/driver/compiler_options.h | 17 |
4 files changed, 82 insertions, 92 deletions
diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc index bd2b1070fc..ed4fb6f30f 100644 --- a/compiler/driver/compiler_driver.cc +++ b/compiler/driver/compiler_driver.cc @@ -67,7 +67,6 @@ #include "mirror/object-refvisitor-inl.h" #include "mirror/object_array-inl.h" #include "mirror/throwable.h" -#include "nativehelper/ScopedLocalRef.h" #include "object_lock.h" #include "profile/profile_compilation_info.h" #include "runtime.h" @@ -264,7 +263,7 @@ CompilerDriver::CompilerDriver( Compiler::Kind compiler_kind, InstructionSet instruction_set, const InstructionSetFeatures* instruction_set_features, - std::unique_ptr<HashSet<std::string>>&& image_classes, + HashSet<std::string>* image_classes, size_t thread_count, int swap_fd, const ProfileCompilationInfo* profile_compilation_info) @@ -293,7 +292,7 @@ CompilerDriver::CompilerDriver( compiler_->Init(); if (GetCompilerOptions().IsBootImage()) { - CHECK(image_classes_.get() != nullptr) << "Expected image classes for boot image"; + CHECK(image_classes_ != nullptr) << "Expected image classes for boot image"; } compiled_method_storage_.SetDedupeEnabled(compiler_options_->DeduplicateCode()); @@ -351,12 +350,6 @@ void CompilerDriver::CompileAll(jobject class_loader, InitializeThreadPools(); - VLOG(compiler) << "Before precompile " << GetMemoryUsageString(false); - // Precompile: - // 1) Load image classes - // 2) Resolve all classes - // 3) Attempt to verify all classes - // 4) Attempt to initialize image classes, and trivially initialized classes PreCompile(class_loader, dex_files, timings); if (GetCompilerOptions().IsBootImage()) { // We don't need to setup the intrinsics for non boot image compilation, as @@ -673,46 +666,24 @@ static void CompileMethodQuick( quick_fn); } -void CompilerDriver::CompileOne(Thread* self, ArtMethod* method, TimingLogger* timings) { - DCHECK(!Runtime::Current()->IsStarted()); - jobject jclass_loader; - const DexFile* dex_file; - uint16_t class_def_idx; - uint32_t method_idx = method->GetDexMethodIndex(); - uint32_t access_flags = method->GetAccessFlags(); - InvokeType invoke_type = method->GetInvokeType(); - StackHandleScope<2> hs(self); - Handle<mirror::DexCache> dex_cache(hs.NewHandle(method->GetDexCache())); - Handle<mirror::ClassLoader> class_loader( - hs.NewHandle(method->GetDeclaringClass()->GetClassLoader())); - { - ScopedObjectAccessUnchecked soa(self); - ScopedLocalRef<jobject> local_class_loader( - soa.Env(), soa.AddLocalReference<jobject>(class_loader.Get())); - jclass_loader = soa.Env()->NewGlobalRef(local_class_loader.get()); - // Find the dex_file - dex_file = method->GetDexFile(); - class_def_idx = method->GetClassDefIndex(); - } - const DexFile::CodeItem* code_item = dex_file->GetCodeItem(method->GetCodeItemOffset()); - - // Go to native so that we don't block GC during compilation. - ScopedThreadSuspension sts(self, kNative); - - std::vector<const DexFile*> dex_files; - dex_files.push_back(dex_file); - - InitializeThreadPools(); - - PreCompile(jclass_loader, dex_files, timings); - +// Compile a single Method. (For testing only.) +void CompilerDriver::CompileOne(Thread* self, + jobject class_loader, + const DexFile& dex_file, + uint16_t class_def_idx, + uint32_t method_idx, + uint32_t access_flags, + InvokeType invoke_type, + const DexFile::CodeItem* code_item, + Handle<mirror::DexCache> dex_cache, + Handle<mirror::ClassLoader> h_class_loader) { // Can we run DEX-to-DEX compiler on this class ? optimizer::DexToDexCompiler::CompilationLevel dex_to_dex_compilation_level = GetDexToDexCompilationLevel(self, *this, - jclass_loader, - *dex_file, - dex_file->GetClassDef(class_def_idx)); + class_loader, + dex_file, + dex_file.GetClassDef(class_def_idx)); CompileMethodQuick(self, this, @@ -721,8 +692,8 @@ void CompilerDriver::CompileOne(Thread* self, ArtMethod* method, TimingLogger* t invoke_type, class_def_idx, method_idx, - class_loader, - *dex_file, + h_class_loader, + dex_file, dex_to_dex_compilation_level, true, dex_cache); @@ -737,17 +708,13 @@ void CompilerDriver::CompileOne(Thread* self, ArtMethod* method, TimingLogger* t invoke_type, class_def_idx, method_idx, - class_loader, - *dex_file, + h_class_loader, + dex_file, dex_to_dex_compilation_level, true, dex_cache); dex_to_dex_compiler_.ClearState(); } - - FreeThreadPools(); - - self->GetJniEnv()->DeleteGlobalRef(jclass_loader); } void CompilerDriver::Resolve(jobject class_loader, @@ -838,7 +805,7 @@ static void InitializeTypeCheckBitstrings(CompilerDriver* driver, // primitive) classes. We may reconsider this in future if it's deemed to be beneficial. // And we cannot use it for classes outside the boot image as we do not know the runtime // value of their bitstring when compiling (it may not even get assigned at runtime). - if (descriptor[0] == 'L' && driver->IsImageClass(descriptor)) { + if (descriptor[0] == 'L' && driver->GetCompilerOptions().IsImageClass(descriptor)) { ObjPtr<mirror::Class> klass = class_linker->LookupResolvedType(type_index, dex_cache.Get(), @@ -918,6 +885,16 @@ void CompilerDriver::PreCompile(jobject class_loader, const std::vector<const DexFile*>& dex_files, TimingLogger* timings) { CheckThreadPools(); + VLOG(compiler) << "Before precompile " << GetMemoryUsageString(false); + + // Precompile: + // 1) Load image classes. + // 2) Resolve all classes. + // 3) For deterministic boot image, resolve strings for const-string instructions. + // 4) Attempt to verify all classes. + // 5) Attempt to initialize image classes, and trivially initialized classes. + // 6) Update the set of image classes. + // 7) For deterministic boot image, initialize bitstrings for type checking. LoadImageClasses(timings); VLOG(compiler) << "LoadImageClasses: " << GetMemoryUsageString(false); @@ -988,16 +965,6 @@ void CompilerDriver::PreCompile(jobject class_loader, } } -bool CompilerDriver::IsImageClass(const char* descriptor) const { - if (image_classes_ != nullptr) { - // If we have a set of image classes, use those. - return image_classes_->find(StringPiece(descriptor)) != image_classes_->end(); - } - // No set of image classes, assume we include all the classes. - // NOTE: Currently only reachable from InitImageMethodVisitor for the app image case. - return !GetCompilerOptions().IsBootImage(); -} - bool CompilerDriver::IsClassToCompile(const char* descriptor) const { if (classes_to_compile_ == nullptr) { return true; @@ -1116,7 +1083,7 @@ void CompilerDriver::LoadImageClasses(TimingLogger* timings) { Thread* self = Thread::Current(); ScopedObjectAccess soa(self); ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); - CHECK(image_classes_.get() != nullptr); + CHECK(image_classes_ != nullptr); for (auto it = image_classes_->begin(), end = image_classes_->end(); it != end;) { const std::string& descriptor(*it); StackHandleScope<1> hs(self); @@ -1174,7 +1141,7 @@ void CompilerDriver::LoadImageClasses(TimingLogger* timings) { // We walk the roots looking for classes so that we'll pick up the // above classes plus any classes them depend on such super // classes, interfaces, and the required ClassLinker roots. - RecordImageClassesVisitor visitor(image_classes_.get()); + RecordImageClassesVisitor visitor(image_classes_); class_linker->VisitClasses(&visitor); CHECK(!image_classes_->empty()); @@ -1358,7 +1325,7 @@ void CompilerDriver::UpdateImageClasses(TimingLogger* timings) { VariableSizedHandleScope hs(Thread::Current()); std::string error_msg; std::unique_ptr<ClinitImageUpdate> update(ClinitImageUpdate::Create(hs, - image_classes_.get(), + image_classes_, Thread::Current(), runtime->GetClassLinker())); @@ -1382,7 +1349,7 @@ bool CompilerDriver::CanAssumeClassIsLoaded(mirror::Class* klass) { } std::string temp; const char* descriptor = klass->GetDescriptor(&temp); - return IsImageClass(descriptor); + return GetCompilerOptions().IsImageClass(descriptor); } bool CompilerDriver::CanAccessTypeWithoutChecks(ObjPtr<mirror::Class> referrer_class, @@ -2292,7 +2259,7 @@ class InitializeClassVisitor : public CompilationVisitor { (is_app_image || is_boot_image) && is_superclass_initialized && !too_many_encoded_fields && - manager_->GetCompiler()->IsImageClass(descriptor)) { + manager_->GetCompiler()->GetCompilerOptions().IsImageClass(descriptor)) { bool can_init_static_fields = false; if (is_boot_image) { // We need to initialize static fields, we only do this for image classes that aren't @@ -2982,8 +2949,7 @@ bool CompilerDriver::MayInlineInternal(const DexFile* inlined_from, const DexFile* inlined_into) const { // We're not allowed to inline across dex files if we're the no-inline-from dex file. if (inlined_from != inlined_into && - compiler_options_->GetNoInlineFromDexFile() != nullptr && - ContainsElement(*compiler_options_->GetNoInlineFromDexFile(), inlined_from)) { + ContainsElement(compiler_options_->GetNoInlineFromDexFile(), inlined_from)) { return false; } diff --git a/compiler/driver/compiler_driver.h b/compiler/driver/compiler_driver.h index ff70d96272..36e93a84d1 100644 --- a/compiler/driver/compiler_driver.h +++ b/compiler/driver/compiler_driver.h @@ -99,7 +99,7 @@ class CompilerDriver { Compiler::Kind compiler_kind, InstructionSet instruction_set, const InstructionSetFeatures* instruction_set_features, - std::unique_ptr<HashSet<std::string>>&& image_classes, + HashSet<std::string>* image_classes, size_t thread_count, int swap_fd, const ProfileCompilationInfo* profile_compilation_info); @@ -122,9 +122,18 @@ class CompilerDriver { TimingLogger* timings) REQUIRES(!Locks::mutator_lock_); - // Compile a single Method. - void CompileOne(Thread* self, ArtMethod* method, TimingLogger* timings) - REQUIRES_SHARED(Locks::mutator_lock_); + // Compile a single Method. (For testing only.) + void CompileOne(Thread* self, + jobject class_loader, + const DexFile& dex_file, + uint16_t class_def_idx, + uint32_t method_idx, + uint32_t access_flags, + InvokeType invoke_type, + const DexFile::CodeItem* code_item, + Handle<mirror::DexCache> dex_cache, + Handle<mirror::ClassLoader> h_class_loader) + REQUIRES(!Locks::mutator_lock_); VerificationResults* GetVerificationResults() const; @@ -144,10 +153,6 @@ class CompilerDriver { return compiler_.get(); } - const HashSet<std::string>* GetImageClasses() const { - return image_classes_.get(); - } - // Generate the trampolines that are invoked by unresolved direct methods. std::unique_ptr<const std::vector<uint8_t>> CreateJniDlsymLookup() const; std::unique_ptr<const std::vector<uint8_t>> CreateQuickGenericJniTrampoline() const; @@ -308,9 +313,6 @@ class CompilerDriver { return compiled_method_storage_.DedupeEnabled(); } - // Checks if class specified by type_idx is one of the image_classes_ - bool IsImageClass(const char* descriptor) const; - // Checks whether the provided class should be compiled, i.e., is in classes_to_compile_. bool IsClassToCompile(const char* descriptor) const; @@ -491,9 +493,11 @@ class CompilerDriver { // in the .oat_patches ELF section if requested in the compiler options. Atomic<size_t> non_relative_linker_patch_count_; - // If image_ is true, specifies the classes that will be included in the image. - // Note if image_classes_ is null, all classes are included in the image. - std::unique_ptr<HashSet<std::string>> image_classes_; + // Image classes to be updated by PreCompile(). + // TODO: Remove this member which is a non-const pointer to the CompilerOptions' data. + // Pass this explicitly to the PreCompile() which should be called directly from + // Dex2Oat rather than implicitly by CompileAll(). + HashSet<std::string>* image_classes_; // Specifies the classes that will be compiled. Note that if classes_to_compile_ is null, // all classes are eligible for compilation (duplication filters etc. will still apply). @@ -505,8 +509,8 @@ class CompilerDriver { bool had_hard_verifier_failure_; // A thread pool that can (potentially) run tasks in parallel. - std::unique_ptr<ThreadPool> parallel_thread_pool_; size_t parallel_thread_count_; + std::unique_ptr<ThreadPool> parallel_thread_pool_; // A thread pool that guarantees running single-threaded on the main thread. std::unique_ptr<ThreadPool> single_thread_pool_; @@ -534,6 +538,7 @@ class CompilerDriver { // Compiler for dex to dex (quickening). optimizer::DexToDexCompiler dex_to_dex_compiler_; + friend class CommonCompilerTest; friend class CompileClassVisitor; friend class DexToDexDecompilerTest; friend class verifier::VerifierDepsTest; diff --git a/compiler/driver/compiler_options.cc b/compiler/driver/compiler_options.cc index 933be4f004..3d37b680ee 100644 --- a/compiler/driver/compiler_options.cc +++ b/compiler/driver/compiler_options.cc @@ -37,7 +37,8 @@ CompilerOptions::CompilerOptions() tiny_method_threshold_(kDefaultTinyMethodThreshold), num_dex_methods_threshold_(kDefaultNumDexMethodsThreshold), inline_max_code_units_(kUnsetInlineMaxCodeUnits), - no_inline_from_(nullptr), + no_inline_from_(), + image_classes_(), boot_image_(false), core_image_(false), app_image_(false), @@ -67,8 +68,8 @@ CompilerOptions::CompilerOptions() } CompilerOptions::~CompilerOptions() { - // The destructor looks empty but it destroys a PassManagerOptions object. We keep it here - // because we don't want to include the PassManagerOptions definition from the header file. + // Everything done by member destructors. + // The definitions of classes forward-declared in the header have now been #included. } namespace { @@ -129,4 +130,11 @@ bool CompilerOptions::ParseCompilerOptions(const std::vector<std::string>& optio #pragma GCC diagnostic pop +bool CompilerOptions::IsImageClass(const char* descriptor) const { + // Historical note: We used to hold the set indirectly and there was a distinction between an + // empty set and a null, null meaning to include all classes. However, the distiction has been + // removed; if we don't have a profile, we treat it as an empty set of classes. b/77340429 + return image_classes_.find(StringPiece(descriptor)) != image_classes_.end(); +} + } // namespace art diff --git a/compiler/driver/compiler_options.h b/compiler/driver/compiler_options.h index cee989b315..0709fafaeb 100644 --- a/compiler/driver/compiler_options.h +++ b/compiler/driver/compiler_options.h @@ -22,6 +22,7 @@ #include <vector> #include "base/globals.h" +#include "base/hash_set.h" #include "base/macros.h" #include "base/utils.h" #include "compiler_filter.h" @@ -230,10 +231,16 @@ class CompilerOptions FINAL { return abort_on_soft_verifier_failure_; } - const std::vector<const DexFile*>* GetNoInlineFromDexFile() const { + const std::vector<const DexFile*>& GetNoInlineFromDexFile() const { return no_inline_from_; } + const HashSet<std::string>& GetImageClasses() const { + return image_classes_; + } + + bool IsImageClass(const char* descriptor) const; + bool ParseCompilerOptions(const std::vector<std::string>& options, bool ignore_unrecognized, std::string* error_msg); @@ -301,10 +308,14 @@ class CompilerOptions FINAL { size_t num_dex_methods_threshold_; size_t inline_max_code_units_; - // Dex files from which we should not inline code. + // Dex files from which we should not inline code. Does not own the dex files. // This is usually a very short list (i.e. a single dex file), so we // prefer vector<> over a lookup-oriented container, such as set<>. - const std::vector<const DexFile*>* no_inline_from_; + std::vector<const DexFile*> no_inline_from_; + + // Image classes, specifies the classes that will be included in the image if creating an image. + // Must not be empty for real boot image, only for tests pretending to compile boot image. + HashSet<std::string> image_classes_; bool boot_image_; bool core_image_; |
