diff options
| author | 2015-11-05 08:49:07 +0000 | |
|---|---|---|
| committer | 2015-11-05 08:49:07 +0000 | |
| commit | c09b3344568f9533a0954f5dfba20d65d05ec4c1 (patch) | |
| tree | baddee32ea987039bd7b88bdf45c709c2260b46d /compiler | |
| parent | f97ad8115d00d5bd9bbd9c485a7a4b8107f620a2 (diff) | |
| parent | 4b018565e57c3349a3c1b5ec8ac9dae261c5e00b (diff) | |
Merge "Revert "Add basic image writer support for app images""
Diffstat (limited to 'compiler')
| -rw-r--r-- | compiler/dex/quick/arm64/call_arm64.cc | 2 | ||||
| -rw-r--r-- | compiler/driver/compiler_driver.cc | 38 | ||||
| -rw-r--r-- | compiler/driver/compiler_driver.h | 8 | ||||
| -rw-r--r-- | compiler/image_test.cc | 17 | ||||
| -rw-r--r-- | compiler/image_writer.cc | 360 | ||||
| -rw-r--r-- | compiler/image_writer.h | 96 | ||||
| -rw-r--r-- | compiler/oat_test.cc | 1 | ||||
| -rw-r--r-- | compiler/oat_writer.cc | 31 | ||||
| -rw-r--r-- | compiler/oat_writer.h | 6 |
9 files changed, 163 insertions, 396 deletions
diff --git a/compiler/dex/quick/arm64/call_arm64.cc b/compiler/dex/quick/arm64/call_arm64.cc index b1acf5e691..036da2e2b2 100644 --- a/compiler/dex/quick/arm64/call_arm64.cc +++ b/compiler/dex/quick/arm64/call_arm64.cc @@ -447,7 +447,7 @@ void Arm64Mir2Lir::GenSpecialExitForSuspend() { static bool Arm64UseRelativeCall(CompilationUnit* cu, const MethodReference& target_method) { // Emit relative calls anywhere in the image or within a dex file otherwise. - return cu->compiler_driver->IsBootImage() || cu->dex_file == target_method.dex_file; + return cu->compiler_driver->IsImage() || cu->dex_file == target_method.dex_file; } /* diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc index 0e73bd926e..d055b37ea7 100644 --- a/compiler/driver/compiler_driver.cc +++ b/compiler/driver/compiler_driver.cc @@ -341,7 +341,7 @@ CompilerDriver::CompilerDriver(const CompilerOptions* compiler_options, Compiler::Kind compiler_kind, InstructionSet instruction_set, const InstructionSetFeatures* instruction_set_features, - bool boot_image, std::unordered_set<std::string>* image_classes, + 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, @@ -361,7 +361,7 @@ CompilerDriver::CompilerDriver(const CompilerOptions* compiler_options, compiled_methods_lock_("compiled method lock"), compiled_methods_(MethodTable::key_compare()), non_relative_linker_patch_count_(0u), - boot_image_(boot_image), + image_(image), image_classes_(image_classes), classes_to_compile_(compiled_classes), methods_to_compile_(compiled_methods), @@ -383,7 +383,7 @@ CompilerDriver::CompilerDriver(const CompilerOptions* compiler_options, compiler_->Init(); - CHECK_EQ(boot_image_, image_classes_.get() != nullptr); + CHECK_EQ(image_, image_classes_.get() != nullptr); // Read the profile file if one is provided. if (!profile_file.empty()) { @@ -781,7 +781,7 @@ void CompilerDriver::PreCompile(jobject class_loader, const std::vector<const De } bool CompilerDriver::IsImageClass(const char* descriptor) const { - if (!IsBootImage()) { + if (!IsImage()) { // NOTE: Currently unreachable, all callers check IsImage(). return false; } else { @@ -790,7 +790,7 @@ bool CompilerDriver::IsImageClass(const char* descriptor) const { } bool CompilerDriver::IsClassToCompile(const char* descriptor) const { - if (kRestrictCompilationFiltersToImage && !IsBootImage()) { + if (kRestrictCompilationFiltersToImage && !IsImage()) { return true; } @@ -801,7 +801,7 @@ bool CompilerDriver::IsClassToCompile(const char* descriptor) const { } bool CompilerDriver::IsMethodToCompile(const MethodReference& method_ref) const { - if (kRestrictCompilationFiltersToImage && !IsBootImage()) { + if (kRestrictCompilationFiltersToImage && !IsImage()) { return true; } @@ -889,7 +889,7 @@ class RecordImageClassesVisitor : public ClassVisitor { // Make a list of descriptors for classes to include in the image void CompilerDriver::LoadImageClasses(TimingLogger* timings) { CHECK(timings != nullptr); - if (!IsBootImage()) { + if (!IsImage()) { return; } @@ -1118,7 +1118,7 @@ class ClinitImageUpdate { }; void CompilerDriver::UpdateImageClasses(TimingLogger* timings) { - if (IsBootImage()) { + if (IsImage()) { TimingLogger::ScopedTiming t("UpdateImageClasses", timings); Runtime* runtime = Runtime::Current(); @@ -1145,7 +1145,7 @@ bool CompilerDriver::CanAssumeClassIsLoaded(mirror::Class* klass) { // Having the klass reference here implies that the klass is already loaded. return true; } - if (!IsBootImage()) { + if (!IsImage()) { // Assume loaded only if klass is in the boot image. App classes cannot be assumed // loaded because we don't even know what class loader will be used to load them. bool class_in_image = runtime->GetHeap()->FindSpaceFromObject(klass, false)->IsImageSpace(); @@ -1157,7 +1157,7 @@ bool CompilerDriver::CanAssumeClassIsLoaded(mirror::Class* klass) { } bool CompilerDriver::CanAssumeTypeIsPresentInDexCache(const DexFile& dex_file, uint32_t type_idx) { - if (IsBootImage() && + if (IsImage() && IsImageClass(dex_file.StringDataByIdx(dex_file.GetTypeId(type_idx).descriptor_idx_))) { { ScopedObjectAccess soa(Thread::Current()); @@ -1183,7 +1183,7 @@ bool CompilerDriver::CanAssumeStringIsPresentInDexCache(const DexFile& dex_file, // See also Compiler::ResolveDexFile bool result = false; - if (IsBootImage()) { + if (IsImage()) { // We resolve all const-string strings when building for the image. ScopedObjectAccess soa(Thread::Current()); StackHandleScope<1> hs(soa.Self()); @@ -1300,7 +1300,7 @@ bool CompilerDriver::CanEmbedTypeInCode(const DexFile& dex_file, uint32_t type_i if (compiling_boot) { // boot -> boot class pointers. // True if the class is in the image at boot compiling time. - const bool is_image_class = IsBootImage() && IsImageClass( + const bool is_image_class = IsImage() && IsImageClass( dex_file.StringDataByIdx(dex_file.GetTypeId(type_idx).descriptor_idx_)); // True if pc relative load works. if (is_image_class && support_boot_image_fixup) { @@ -1548,7 +1548,7 @@ void CompilerDriver::GetCodeAndMethodForDirectCall(InvokeType* type, InvokeType } if (!use_dex_cache && force_relocations) { bool is_in_image; - if (IsBootImage()) { + if (IsImage()) { is_in_image = IsImageClass(method->GetDeclaringClassDescriptor()); } else { is_in_image = instruction_set_ != kX86 && instruction_set_ != kX86_64 && @@ -2019,7 +2019,7 @@ void CompilerDriver::ResolveDexFile(jobject class_loader, const DexFile& dex_fil ParallelCompilationManager context(class_linker, class_loader, this, &dex_file, dex_files, thread_pool); - if (IsBootImage()) { + if (IsImage()) { // For images we resolve all types, such as array, whereas for applications just those with // classdefs are resolved by ResolveClassFieldsAndMethods. TimingLogger::ScopedTiming t("Resolve Types", timings); @@ -2101,8 +2101,8 @@ class VerifyClassVisitor : public CompilationVisitor { // It is *very* problematic if there are verification errors in the boot classpath. For example, // we rely on things working OK without verification when the decryption dialog is brought up. // So abort in a debug build if we find this violated. - DCHECK(!manager_->GetCompiler()->IsBootImage() || klass->IsVerified()) - << "Boot classpath class " << PrettyClass(klass.Get()) << " failed to fully verify."; + DCHECK(!manager_->GetCompiler()->IsImage() || klass->IsVerified()) << "Boot classpath class " + << PrettyClass(klass.Get()) << " failed to fully verify."; } soa.Self()->AssertNoPendingException(); } @@ -2222,7 +2222,7 @@ class InitializeClassVisitor : public CompilationVisitor { if (!klass->IsInitialized()) { // We need to initialize static fields, we only do this for image classes that aren't // marked with the $NoPreloadHolder (which implies this should not be initialized early). - bool can_init_static_fields = manager_->GetCompiler()->IsBootImage() && + bool can_init_static_fields = manager_->GetCompiler()->IsImage() && manager_->GetCompiler()->IsImageClass(descriptor) && !StringPiece(descriptor).ends_with("$NoPreloadHolder;"); if (can_init_static_fields) { @@ -2286,7 +2286,7 @@ void CompilerDriver::InitializeClasses(jobject jni_class_loader, const DexFile& ParallelCompilationManager context(class_linker, jni_class_loader, this, &dex_file, dex_files, thread_pool); size_t thread_count; - if (IsBootImage()) { + if (IsImage()) { // TODO: remove this when transactional mode supports multithreading. thread_count = 1U; } else { @@ -2304,7 +2304,7 @@ void CompilerDriver::InitializeClasses(jobject class_loader, CHECK(dex_file != nullptr); InitializeClasses(class_loader, *dex_file, dex_files, thread_pool, timings); } - if (IsBootImage()) { + if (IsImage()) { // Prune garbage objects created during aborted transactions. Runtime::Current()->GetHeap()->CollectGarbage(true); } diff --git a/compiler/driver/compiler_driver.h b/compiler/driver/compiler_driver.h index 15b6bba270..4ed4dc60d2 100644 --- a/compiler/driver/compiler_driver.h +++ b/compiler/driver/compiler_driver.h @@ -92,7 +92,7 @@ class CompilerDriver { Compiler::Kind compiler_kind, InstructionSet instruction_set, const InstructionSetFeatures* instruction_set_features, - bool boot_image, std::unordered_set<std::string>* image_classes, + 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, @@ -156,8 +156,8 @@ class CompilerDriver { } // Are we compiling and creating an image file? - bool IsBootImage() const { - return boot_image_; + bool IsImage() const { + return image_; } const std::unordered_set<std::string>* GetImageClasses() const { @@ -637,7 +637,7 @@ class CompilerDriver { // in the .oat_patches ELF section if requested in the compiler options. size_t non_relative_linker_patch_count_ GUARDED_BY(compiled_methods_lock_); - const bool boot_image_; + const bool image_; // If image_ is true, specifies the classes that will be included in // the image. Note if image_classes_ is null, all classes are diff --git a/compiler/image_test.cc b/compiler/image_test.cc index a38e1f54c0..fd6cd82f7c 100644 --- a/compiler/image_test.cc +++ b/compiler/image_test.cc @@ -64,10 +64,8 @@ TEST_F(ImageTest, WriteRead) { ScratchFile oat_file(OS::CreateEmptyFile(oat_filename.c_str())); const uintptr_t requested_image_base = ART_BASE_ADDRESS; - std::unique_ptr<ImageWriter> writer(new ImageWriter(*compiler_driver_, - requested_image_base, - /*compile_pic*/false, - /*compile_app_image*/false)); + std::unique_ptr<ImageWriter> writer(new ImageWriter(*compiler_driver_, requested_image_base, + /*compile_pic*/false)); // TODO: compile_pic should be a test argument. { { @@ -83,15 +81,8 @@ TEST_F(ImageTest, WriteRead) { t.NewTiming("WriteElf"); SafeMap<std::string, std::string> key_value_store; - OatWriter oat_writer(class_linker->GetBootClassPath(), - 0, - 0, - 0, - compiler_driver_.get(), - writer.get(), - /*compiling_boot_image*/true, - &timings, - &key_value_store); + OatWriter oat_writer(class_linker->GetBootClassPath(), 0, 0, 0, compiler_driver_.get(), + writer.get(), &timings, &key_value_store); bool success = writer->PrepareImageAddressSpace() && compiler_driver_->WriteElf(GetTestAndroidRoot(), !kIsTargetBuild, diff --git a/compiler/image_writer.cc b/compiler/image_writer.cc index 0c85323805..af2a4f9426 100644 --- a/compiler/image_writer.cc +++ b/compiler/image_writer.cc @@ -20,7 +20,6 @@ #include <memory> #include <numeric> -#include <unordered_set> #include <vector> #include "art_field-inl.h" @@ -73,27 +72,6 @@ namespace art { // Separate objects into multiple bins to optimize dirty memory use. static constexpr bool kBinObjects = true; -// Return true if an object is already in an image space. -bool ImageWriter::IsInBootImage(const void* obj) const { - if (!compile_app_image_) { - DCHECK(boot_image_space_ == nullptr); - return false; - } - const uint8_t* image_begin = boot_image_space_->Begin(); - // Real image end including ArtMethods and ArtField sections. - const uint8_t* image_end = image_begin + boot_image_space_->GetImageHeader().GetImageSize(); - return image_begin <= obj && obj < image_end; -} - -bool ImageWriter::IsInBootOatFile(const void* ptr) const { - if (!compile_app_image_) { - DCHECK(boot_image_space_ == nullptr); - return false; - } - const ImageHeader& image_header = boot_image_space_->GetImageHeader(); - return image_header.GetOatFileBegin() <= ptr && ptr < image_header.GetOatFileEnd(); -} - static void CheckNoDexObjectsCallback(Object* obj, void* arg ATTRIBUTE_UNUSED) SHARED_REQUIRES(Locks::mutator_lock_) { Class* klass = obj->GetClass(); @@ -107,20 +85,12 @@ static void CheckNoDexObjects() { bool ImageWriter::PrepareImageAddressSpace() { target_ptr_size_ = InstructionSetPointerSize(compiler_driver_.GetInstructionSet()); - gc::Heap* const heap = Runtime::Current()->GetHeap(); - // Cache boot image space. - for (gc::space::ContinuousSpace* space : heap->GetContinuousSpaces()) { - if (space->IsImageSpace()) { - CHECK(compile_app_image_); - CHECK(boot_image_space_ == nullptr) << "Multiple image spaces"; - boot_image_space_ = space->AsImageSpace(); - } - } { ScopedObjectAccess soa(Thread::Current()); PruneNonImageClasses(); // Remove junk ComputeLazyFieldsForImageClasses(); // Add useful information } + gc::Heap* heap = Runtime::Current()->GetHeap(); heap->CollectGarbage(false); // Remove garbage. // Dex caches must not have their dex fields set in the image. These are memory buffers of mapped @@ -174,21 +144,21 @@ bool ImageWriter::Write(int image_fd, Runtime::Current()->GetOatFileManager().RegisterOatFile( std::unique_ptr<const OatFile>(oat_file_)); - const OatHeader& oat_header = oat_file_->GetOatHeader(); - oat_address_offsets_[kOatAddressInterpreterToInterpreterBridge] = - oat_header.GetInterpreterToInterpreterBridgeOffset(); - oat_address_offsets_[kOatAddressInterpreterToCompiledCodeBridge] = - oat_header.GetInterpreterToCompiledCodeBridgeOffset(); - oat_address_offsets_[kOatAddressJNIDlsymLookup] = - oat_header.GetJniDlsymLookupOffset(); - oat_address_offsets_[kOatAddressQuickGenericJNITrampoline] = - oat_header.GetQuickGenericJniTrampolineOffset(); - oat_address_offsets_[kOatAddressQuickIMTConflictTrampoline] = - oat_header.GetQuickImtConflictTrampolineOffset(); - oat_address_offsets_[kOatAddressQuickResolutionTrampoline] = - oat_header.GetQuickResolutionTrampolineOffset(); - oat_address_offsets_[kOatAddressQuickToInterpreterBridge] = - oat_header.GetQuickToInterpreterBridgeOffset(); + interpreter_to_interpreter_bridge_offset_ = + oat_file_->GetOatHeader().GetInterpreterToInterpreterBridgeOffset(); + interpreter_to_compiled_code_bridge_offset_ = + oat_file_->GetOatHeader().GetInterpreterToCompiledCodeBridgeOffset(); + + jni_dlsym_lookup_offset_ = oat_file_->GetOatHeader().GetJniDlsymLookupOffset(); + + quick_generic_jni_trampoline_offset_ = + oat_file_->GetOatHeader().GetQuickGenericJniTrampolineOffset(); + quick_imt_conflict_trampoline_offset_ = + oat_file_->GetOatHeader().GetQuickImtConflictTrampolineOffset(); + quick_resolution_trampoline_offset_ = + oat_file_->GetOatHeader().GetQuickResolutionTrampolineOffset(); + quick_to_interpreter_bridge_offset_ = + oat_file_->GetOatHeader().GetQuickToInterpreterBridgeOffset(); size_t oat_loaded_size = 0; size_t oat_data_offset = 0; @@ -337,7 +307,7 @@ void ImageWriter::PrepareDexCacheArraySlots() { for (jobject weak_root : class_linker->GetDexCaches()) { mirror::DexCache* dex_cache = down_cast<mirror::DexCache*>(self->DecodeJObject(weak_root)); - if (dex_cache == nullptr || IsInBootImage(dex_cache)) { + if (dex_cache == nullptr) { continue; } const DexFile* dex_file = dex_cache->GetDexFile(); @@ -361,7 +331,6 @@ void ImageWriter::PrepareDexCacheArraySlots() { void ImageWriter::AddDexCacheArrayRelocation(void* array, size_t offset) { if (array != nullptr) { - DCHECK(!IsInBootImage(array)); native_object_relocations_.emplace( array, NativeObjectRelocation { offset, kNativeObjectRelocationTypeDexCacheArray }); @@ -375,8 +344,8 @@ void ImageWriter::AddMethodPointerArray(mirror::PointerArray* arr) { auto* method = arr->GetElementPtrSize<ArtMethod*>(i, target_ptr_size_); if (method != nullptr && !method->IsRuntimeMethod()) { auto* klass = method->GetDeclaringClass(); - CHECK(klass == nullptr || KeepClass(klass)) - << PrettyClass(klass) << " should be a kept class"; + CHECK(klass == nullptr || IsImageClass(klass)) << PrettyClass(klass) + << " should be an image class"; } } } @@ -570,66 +539,10 @@ void ImageWriter::ComputeLazyFieldsForImageClasses() { class_linker->VisitClassesWithoutClassesLock(&visitor); } -static bool IsBootClassLoaderClass(mirror::Class* klass) SHARED_REQUIRES(Locks::mutator_lock_) { - return klass->GetClassLoader() == nullptr; -} - -bool ImageWriter::IsBootClassLoaderNonImageClass(mirror::Class* klass) { - return IsBootClassLoaderClass(klass) && !IsInBootImage(klass); -} - -bool ImageWriter::ContainsBootClassLoaderNonImageClass(mirror::Class* klass) { - if (klass == nullptr) { - return false; - } - auto found = prune_class_memo_.find(klass); - if (found != prune_class_memo_.end()) { - // Already computed, return the found value. - return found->second; - } - // Place holder value to prevent infinite recursion. - prune_class_memo_.emplace(klass, false); - bool result = IsBootClassLoaderNonImageClass(klass); - if (!result) { - // Check interfaces since these wont be visited through VisitReferences.) - mirror::IfTable* if_table = klass->GetIfTable(); - for (size_t i = 0, num_interfaces = klass->GetIfTableCount(); i < num_interfaces; ++i) { - result = result || ContainsBootClassLoaderNonImageClass(if_table->GetInterface(i)); - } - } - // Check static fields and their classes. - size_t num_static_fields = klass->NumReferenceStaticFields(); - if (num_static_fields != 0 && klass->IsResolved()) { - // Presumably GC can happen when we are cross compiling, it should not cause performance - // problems to do pointer size logic. - MemberOffset field_offset = klass->GetFirstReferenceStaticFieldOffset( - Runtime::Current()->GetClassLinker()->GetImagePointerSize()); - for (size_t i = 0u; i < num_static_fields; ++i) { - mirror::Object* ref = klass->GetFieldObject<mirror::Object>(field_offset); - if (ref != nullptr) { - if (ref->IsClass()) { - result = result || ContainsBootClassLoaderNonImageClass(ref->AsClass()); - } - result = result || ContainsBootClassLoaderNonImageClass(ref->GetClass()); - } - field_offset = MemberOffset(field_offset.Uint32Value() + - sizeof(mirror::HeapReference<mirror::Object>)); - } - } - result = result || ContainsBootClassLoaderNonImageClass(klass->GetSuperClass()); - prune_class_memo_[klass] = result; - return result; -} - -bool ImageWriter::KeepClass(Class* klass) { +bool ImageWriter::IsImageClass(Class* klass) { if (klass == nullptr) { return false; } - if (compile_app_image_) { - // For app images, we need to prune boot loader classes that are not in the boot image since - // these may have already been loaded when the app image is loaded. - return !ContainsBootClassLoaderNonImageClass(klass); - } std::string temp; return compiler_driver_.IsImageClass(klass->GetDescriptor(&temp)); } @@ -639,17 +552,21 @@ class NonImageClassesVisitor : public ClassVisitor { explicit NonImageClassesVisitor(ImageWriter* image_writer) : image_writer_(image_writer) {} bool Visit(Class* klass) OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_) { - if (!image_writer_->KeepClass(klass)) { - classes_to_prune_.insert(klass); + if (!image_writer_->IsImageClass(klass)) { + std::string temp; + non_image_classes_.insert(klass->GetDescriptor(&temp)); } return true; } - std::unordered_set<mirror::Class*> classes_to_prune_; + std::set<std::string> non_image_classes_; ImageWriter* const image_writer_; }; void ImageWriter::PruneNonImageClasses() { + if (compiler_driver_.GetImageClasses() == nullptr) { + return; + } Runtime* runtime = Runtime::Current(); ClassLinker* class_linker = runtime->GetClassLinker(); Thread* self = Thread::Current(); @@ -659,14 +576,8 @@ void ImageWriter::PruneNonImageClasses() { class_linker->VisitClasses(&visitor); // Remove the undesired classes from the class roots. - for (mirror::Class* klass : visitor.classes_to_prune_) { - std::string temp; - const char* name = klass->GetDescriptor(&temp); - VLOG(compiler) << "Pruning class " << name; - if (!compile_app_image_) { - DCHECK(IsBootClassLoaderClass(klass)); - } - bool result = class_linker->RemoveClass(name, klass->GetClassLoader()); + for (const std::string& it : visitor.non_image_classes_) { + bool result = class_linker->RemoveClass(it.c_str(), nullptr); DCHECK(result); } @@ -683,7 +594,7 @@ void ImageWriter::PruneNonImageClasses() { } for (size_t i = 0; i < dex_cache->NumResolvedTypes(); i++) { Class* klass = dex_cache->GetResolvedType(i); - if (klass != nullptr && !KeepClass(klass)) { + if (klass != nullptr && !IsImageClass(klass)) { dex_cache->SetResolvedType(i, nullptr); } } @@ -696,7 +607,7 @@ void ImageWriter::PruneNonImageClasses() { // Miranda methods may be held live by a class which was not an image class but have a // declaring class which is an image class. Set it to the resolution method to be safe and // prevent dangling pointers. - if (method->IsMiranda() || !KeepClass(declaring_class)) { + if (method->IsMiranda() || !IsImageClass(declaring_class)) { mirror::DexCache::SetElementPtrSize(resolved_methods, i, resolution_method, @@ -710,7 +621,7 @@ void ImageWriter::PruneNonImageClasses() { } for (size_t i = 0; i < dex_cache->NumResolvedFields(); i++) { ArtField* field = dex_cache->GetResolvedField(i, target_ptr_size_); - if (field != nullptr && !KeepClass(field->GetDeclaringClass())) { + if (field != nullptr && !IsImageClass(field->GetDeclaringClass())) { dex_cache->SetResolvedField(i, nullptr, target_ptr_size_); } } @@ -721,9 +632,6 @@ void ImageWriter::PruneNonImageClasses() { // Drop the array class cache in the ClassLinker, as these are roots holding those classes live. class_linker->DropFindArrayClassCache(); - - // Clear to save RAM. - prune_class_memo_.clear(); } void ImageWriter::CheckNonImageClassesRemoved() { @@ -735,13 +643,13 @@ void ImageWriter::CheckNonImageClassesRemoved() { void ImageWriter::CheckNonImageClassesRemovedCallback(Object* obj, void* arg) { ImageWriter* image_writer = reinterpret_cast<ImageWriter*>(arg); - if (obj->IsClass() && !image_writer->IsInBootImage(obj)) { + if (obj->IsClass()) { Class* klass = obj->AsClass(); - if (!image_writer->KeepClass(klass)) { + if (!image_writer->IsImageClass(klass)) { image_writer->DumpImageClasses(); std::string temp; - CHECK(image_writer->KeepClass(klass)) << klass->GetDescriptor(&temp) - << " " << PrettyDescriptor(klass); + CHECK(image_writer->IsImageClass(klass)) << klass->GetDescriptor(&temp) + << " " << PrettyDescriptor(klass); } } } @@ -795,35 +703,25 @@ ObjectArray<Object>* ImageWriter::CreateImageRoots() const { // ObjectArray, we lock the dex lock twice, first to get the number // of dex caches first and then lock it again to copy the dex // caches. We check that the number of dex caches does not change. - size_t dex_cache_count = 0; + size_t dex_cache_count; { ReaderMutexLock mu(self, *class_linker->DexLock()); - // Count number of dex caches not in the boot image. - for (jobject weak_root : class_linker->GetDexCaches()) { - mirror::DexCache* dex_cache = down_cast<mirror::DexCache*>(self->DecodeJObject(weak_root)); - dex_cache_count += IsInBootImage(dex_cache) ? 0u : 1u; - } + dex_cache_count = class_linker->GetDexCacheCount(); } Handle<ObjectArray<Object>> dex_caches( - hs.NewHandle(ObjectArray<Object>::Alloc(self, object_array_class.Get(), dex_cache_count))); + hs.NewHandle(ObjectArray<Object>::Alloc(self, object_array_class.Get(), + dex_cache_count))); CHECK(dex_caches.Get() != nullptr) << "Failed to allocate a dex cache array."; { ReaderMutexLock mu(self, *class_linker->DexLock()); - size_t non_image_dex_caches = 0; - // Re-count number of non image dex caches. - for (jobject weak_root : class_linker->GetDexCaches()) { - mirror::DexCache* dex_cache = down_cast<mirror::DexCache*>(self->DecodeJObject(weak_root)); - non_image_dex_caches += IsInBootImage(dex_cache) ? 0u : 1u; - } - CHECK_EQ(dex_cache_count, non_image_dex_caches) - << "The number of non-image dex caches changed."; + CHECK_EQ(dex_cache_count, class_linker->GetDexCacheCount()) + << "The number of dex caches changed."; size_t i = 0; for (jobject weak_root : class_linker->GetDexCaches()) { - mirror::DexCache* dex_cache = down_cast<mirror::DexCache*>(self->DecodeJObject(weak_root)); - if (!IsInBootImage(dex_cache)) { - dex_caches->Set<false>(i, dex_cache); - ++i; - } + mirror::DexCache* dex_cache = + down_cast<mirror::DexCache*>(self->DecodeJObject(weak_root)); + dex_caches->Set<false>(i, dex_cache); + ++i; } } @@ -863,10 +761,6 @@ void ImageWriter::WalkInstanceFields(mirror::Object* obj, mirror::Class* klass) // For an unvisited object, visit it then all its children found via fields. void ImageWriter::WalkFieldsInOrder(mirror::Object* obj) { - if (IsInBootImage(obj)) { - // Object is in the image, don't need to fix it up. - return; - } // Use our own visitor routine (instead of GC visitor) to get better locality between // an object and its fields if (!IsImageBinSlotAssigned(obj)) { @@ -903,7 +797,6 @@ void ImageWriter::WalkFieldsInOrder(mirror::Object* obj) { CHECK(it == native_object_relocations_.end()) << "Field array " << cur_fields << " already forwarded"; size_t& offset = bin_slot_sizes_[kBinArtField]; - DCHECK(!IsInBootImage(cur_fields)); native_object_relocations_.emplace( cur_fields, NativeObjectRelocation { offset, kNativeObjectRelocationTypeArtFieldArray }); @@ -915,7 +808,6 @@ void ImageWriter::WalkFieldsInOrder(mirror::Object* obj) { auto it2 = native_object_relocations_.find(field); CHECK(it2 == native_object_relocations_.end()) << "Field at index=" << i << " already assigned " << PrettyField(field) << " static=" << field->IsStatic(); - DCHECK(!IsInBootImage(field)); native_object_relocations_.emplace( field, NativeObjectRelocation {offset, kNativeObjectRelocationTypeArtField }); offset += sizeof(ArtField); @@ -951,7 +843,6 @@ void ImageWriter::WalkFieldsInOrder(mirror::Object* obj) { CHECK(it == native_object_relocations_.end()) << "Method array " << array << " already forwarded"; size_t& offset = bin_slot_sizes_[bin_type]; - DCHECK(!IsInBootImage(array)); native_object_relocations_.emplace(array, NativeObjectRelocation { offset, any_dirty ? kNativeObjectRelocationTypeArtMethodArrayDirty : kNativeObjectRelocationTypeArtMethodArrayClean }); @@ -976,7 +867,6 @@ void ImageWriter::WalkFieldsInOrder(mirror::Object* obj) { } void ImageWriter::AssignMethodOffset(ArtMethod* method, NativeObjectRelocationType type) { - DCHECK(!IsInBootImage(method)); auto it = native_object_relocations_.find(method); CHECK(it == native_object_relocations_.end()) << "Method " << method << " already assigned " << PrettyMethod(method); @@ -994,13 +884,10 @@ void ImageWriter::WalkFieldsCallback(mirror::Object* obj, void* arg) { void ImageWriter::UnbinObjectsIntoOffsetCallback(mirror::Object* obj, void* arg) { ImageWriter* writer = reinterpret_cast<ImageWriter*>(arg); DCHECK(writer != nullptr); - if (!writer->IsInBootImage(obj)) { - writer->UnbinObjectsIntoOffset(obj); - } + writer->UnbinObjectsIntoOffset(obj); } void ImageWriter::UnbinObjectsIntoOffset(mirror::Object* obj) { - DCHECK(!IsInBootImage(obj)); CHECK(obj != nullptr); // We know the bin slot, and the total bin sizes for all objects by now, @@ -1038,15 +925,13 @@ void ImageWriter::CalculateNewObjectOffsets() { image_methods_[ImageHeader::kRefsAndArgsSaveMethod] = runtime->GetCalleeSaveMethod(Runtime::kRefsAndArgs); - // Add room for fake length prefixed array for holding the image methods. + // Add room for fake length prefixed array. const auto image_method_type = kNativeObjectRelocationTypeArtMethodArrayClean; auto it = native_object_relocations_.find(&image_method_array_); CHECK(it == native_object_relocations_.end()); size_t& offset = bin_slot_sizes_[BinTypeForNativeRelocationType(image_method_type)]; - if (!compile_app_image_) { - native_object_relocations_.emplace(&image_method_array_, - NativeObjectRelocation { offset, image_method_type }); - } + native_object_relocations_.emplace(&image_method_array_, + NativeObjectRelocation { offset, image_method_type }); size_t method_alignment = ArtMethod::Alignment(target_ptr_size_); const size_t array_size = LengthPrefixedArray<ArtMethod>::ComputeSize( 0, ArtMethod::Size(target_ptr_size_), method_alignment); @@ -1055,10 +940,7 @@ void ImageWriter::CalculateNewObjectOffsets() { for (auto* m : image_methods_) { CHECK(m != nullptr); CHECK(m->IsRuntimeMethod()); - DCHECK_EQ(compile_app_image_, IsInBootImage(m)) << "Trampolines should be in boot image"; - if (!IsInBootImage(m)) { - AssignMethodOffset(m, kNativeObjectRelocationTypeArtMethodClean); - } + AssignMethodOffset(m, kNativeObjectRelocationTypeArtMethodClean); } // Calculate size of the dex cache arrays slot and prepare offsets. PrepareDexCacheArraySlots(); @@ -1208,7 +1090,6 @@ void ImageWriter::CopyAndFixupNativeData() { NativeObjectRelocation& relocation = pair.second; auto* dest = image_->Begin() + relocation.offset; DCHECK_GE(dest, image_->Begin() + image_end_); - DCHECK(!IsInBootImage(pair.first)); switch (relocation.type) { case kNativeObjectRelocationTypeArtField: { memcpy(dest, pair.first, sizeof(ArtField)); @@ -1245,18 +1126,16 @@ void ImageWriter::CopyAndFixupNativeData() { auto* image_header = reinterpret_cast<ImageHeader*>(image_->Begin()); const ImageSection& methods_section = image_header->GetMethodsSection(); for (size_t i = 0; i < ImageHeader::kImageMethodsCount; ++i) { - ArtMethod* method = image_methods_[i]; - CHECK(method != nullptr); - if (!IsInBootImage(method)) { - auto it = native_object_relocations_.find(method); - CHECK(it != native_object_relocations_.end()) << "No fowarding for " << PrettyMethod(method); - NativeObjectRelocation& relocation = it->second; - CHECK(methods_section.Contains(relocation.offset)) << relocation.offset << " not in " - << methods_section; - CHECK(relocation.IsArtMethodRelocation()) << relocation.type; - method = reinterpret_cast<ArtMethod*>(image_begin_ + it->second.offset); - } - image_header->SetImageMethod(static_cast<ImageHeader::ImageMethod>(i), method); + auto* m = image_methods_[i]; + CHECK(m != nullptr); + auto it = native_object_relocations_.find(m); + CHECK(it != native_object_relocations_.end()) << "No fowarding for " << PrettyMethod(m); + NativeObjectRelocation& relocation = it->second; + CHECK(methods_section.Contains(relocation.offset)) << relocation.offset << " not in " + << methods_section; + CHECK(relocation.IsArtMethodRelocation()) << relocation.type; + auto* dest = reinterpret_cast<ArtMethod*>(image_begin_ + it->second.offset); + image_header->SetImageMethod(static_cast<ImageHeader::ImageMethod>(i), dest); } // Write the intern table into the image. const ImageSection& intern_table_section = image_header->GetImageSection( @@ -1304,8 +1183,8 @@ void ImageWriter::FixupPointerArray(mirror::Object* dst, mirror::PointerArray* a dst->SetClass(GetImageAddress(arr->GetClass())); auto* dest_array = down_cast<mirror::PointerArray*>(dst); for (size_t i = 0, count = num_elements; i < count; ++i) { - void* elem = arr->GetElementPtrSize<void*>(i, target_ptr_size_); - if (elem != nullptr && !IsInBootImage(elem)) { + auto* elem = arr->GetElementPtrSize<void*>(i, target_ptr_size_); + if (elem != nullptr) { auto it = native_object_relocations_.find(elem); if (UNLIKELY(it == native_object_relocations_.end())) { if (it->second.IsArtMethodRelocation()) { @@ -1330,9 +1209,6 @@ void ImageWriter::FixupPointerArray(mirror::Object* dst, mirror::PointerArray* a } void ImageWriter::CopyAndFixupObject(Object* obj) { - if (IsInBootImage(obj)) { - return; - } size_t offset = GetImageOffset(obj); auto* dst = reinterpret_cast<Object*>(image_->Begin() + offset); DCHECK_LT(offset, image_end_); @@ -1406,19 +1282,18 @@ class FixupClassVisitor FINAL : public FixupVisitor { uintptr_t ImageWriter::NativeOffsetInImage(void* obj) { DCHECK(obj != nullptr); - DCHECK(!IsInBootImage(obj)); auto it = native_object_relocations_.find(obj); - CHECK(it != native_object_relocations_.end()) << obj << " spaces " - << Runtime::Current()->GetHeap()->DumpSpaces(); + CHECK(it != native_object_relocations_.end()) << obj; const NativeObjectRelocation& relocation = it->second; return relocation.offset; } template <typename T> T* ImageWriter::NativeLocationInImage(T* obj) { - return (obj == nullptr || IsInBootImage(obj)) - ? obj - : reinterpret_cast<T*>(image_begin_ + NativeOffsetInImage(obj)); + if (obj == nullptr) { + return nullptr; + } + return reinterpret_cast<T*>(image_begin_ + NativeOffsetInImage(obj)); } void ImageWriter::FixupClass(mirror::Class* orig, mirror::Class* copy) { @@ -1431,22 +1306,18 @@ void ImageWriter::FixupClass(mirror::Class* orig, mirror::Class* copy) { // Update dex cache strings. copy->SetDexCacheStrings(NativeLocationInImage(orig->GetDexCacheStrings())); // Fix up embedded tables. - if (!orig->IsTemp()) { - // TODO: Why do we have temp classes in some cases? - if (orig->ShouldHaveEmbeddedImtAndVTable()) { - for (int32_t i = 0; i < orig->GetEmbeddedVTableLength(); ++i) { - ArtMethod* orig_method = orig->GetEmbeddedVTableEntry(i, target_ptr_size_); - copy->SetEmbeddedVTableEntryUnchecked( - i, - NativeLocationInImage(orig_method), - target_ptr_size_); - } - for (size_t i = 0; i < mirror::Class::kImtSize; ++i) { - copy->SetEmbeddedImTableEntry( - i, - NativeLocationInImage(orig->GetEmbeddedImTableEntry(i, target_ptr_size_)), - target_ptr_size_); - } + if (orig->ShouldHaveEmbeddedImtAndVTable()) { + for (int32_t i = 0; i < orig->GetEmbeddedVTableLength(); ++i) { + auto it = native_object_relocations_.find(orig->GetEmbeddedVTableEntry(i, target_ptr_size_)); + CHECK(it != native_object_relocations_.end()) << PrettyClass(orig); + copy->SetEmbeddedVTableEntryUnchecked( + i, reinterpret_cast<ArtMethod*>(image_begin_ + it->second.offset), target_ptr_size_); + } + for (size_t i = 0; i < mirror::Class::kImtSize; ++i) { + auto it = native_object_relocations_.find(orig->GetEmbeddedImTableEntry(i, target_ptr_size_)); + CHECK(it != native_object_relocations_.end()) << PrettyClass(orig); + copy->SetEmbeddedImTableEntry( + i, reinterpret_cast<ArtMethod*>(image_begin_ + it->second.offset), target_ptr_size_); } } FixupClassVisitor visitor(this, copy); @@ -1548,7 +1419,7 @@ void ImageWriter::FixupDexCache(mirror::DexCache* orig_dex_cache, reinterpret_cast<ArtMethod**>(image_->Begin() + copy_methods_offset); for (size_t i = 0, num = orig_dex_cache->NumResolvedMethods(); i != num; ++i) { ArtMethod* orig = mirror::DexCache::GetElementPtrSize(orig_methods, i, target_ptr_size_); - ArtMethod* copy = IsInBootImage(orig) ? orig : NativeLocationInImage(orig); + ArtMethod* copy = NativeLocationInImage(orig); mirror::DexCache::SetElementPtrSize(copy_methods, i, copy, target_ptr_size_); } } @@ -1561,51 +1432,15 @@ void ImageWriter::FixupDexCache(mirror::DexCache* orig_dex_cache, ArtField** copy_fields = reinterpret_cast<ArtField**>(image_->Begin() + copy_fields_offset); for (size_t i = 0, num = orig_dex_cache->NumResolvedFields(); i != num; ++i) { ArtField* orig = mirror::DexCache::GetElementPtrSize(orig_fields, i, target_ptr_size_); - ArtField* copy = IsInBootImage(orig) ? orig : NativeLocationInImage(orig); + ArtField* copy = NativeLocationInImage(orig); mirror::DexCache::SetElementPtrSize(copy_fields, i, copy, target_ptr_size_); } } } -const uint8_t* ImageWriter::GetOatAddress(OatAddress type) const { - DCHECK_LT(type, kOatAddressCount); - // If we are compiling an app image, we need to use the stubs of the boot image. - if (compile_app_image_) { - // Use the current image pointers. - gc::space::ImageSpace* image_space = Runtime::Current()->GetHeap()->GetImageSpace(); - DCHECK(image_space != nullptr); - const OatFile* oat_file = image_space->GetOatFile(); - CHECK(oat_file != nullptr); - const OatHeader& header = oat_file->GetOatHeader(); - switch (type) { - // TODO: We could maybe clean this up if we stored them in an array in the oat header. - case kOatAddressQuickGenericJNITrampoline: - return static_cast<const uint8_t*>(header.GetQuickGenericJniTrampoline()); - case kOatAddressInterpreterToInterpreterBridge: - return static_cast<const uint8_t*>(header.GetInterpreterToInterpreterBridge()); - case kOatAddressInterpreterToCompiledCodeBridge: - return static_cast<const uint8_t*>(header.GetInterpreterToCompiledCodeBridge()); - case kOatAddressJNIDlsymLookup: - return static_cast<const uint8_t*>(header.GetJniDlsymLookup()); - case kOatAddressQuickIMTConflictTrampoline: - return static_cast<const uint8_t*>(header.GetQuickImtConflictTrampoline()); - case kOatAddressQuickResolutionTrampoline: - return static_cast<const uint8_t*>(header.GetQuickResolutionTrampoline()); - case kOatAddressQuickToInterpreterBridge: - return static_cast<const uint8_t*>(header.GetQuickToInterpreterBridge()); - default: - UNREACHABLE(); - } - } - return GetOatAddressForOffset(oat_address_offsets_[type]); -} - const uint8_t* ImageWriter::GetQuickCode(ArtMethod* method, bool* quick_is_interpreted) { - DCHECK(!method->IsResolutionMethod()) << PrettyMethod(method); - DCHECK(!method->IsImtConflictMethod()) << PrettyMethod(method); - DCHECK(!method->IsImtUnimplementedMethod()) << PrettyMethod(method); - DCHECK(!method->IsAbstract()) << PrettyMethod(method); - DCHECK(!IsInBootImage(method)) << PrettyMethod(method); + DCHECK(!method->IsResolutionMethod() && !method->IsImtConflictMethod() && + !method->IsImtUnimplementedMethod() && !method->IsAbstract()) << PrettyMethod(method); // Use original code if it exists. Otherwise, set the code pointer to the resolution // trampoline. @@ -1613,26 +1448,27 @@ const uint8_t* ImageWriter::GetQuickCode(ArtMethod* method, bool* quick_is_inter // Quick entrypoint: uint32_t quick_oat_code_offset = PointerToLowMemUInt32( method->GetEntryPointFromQuickCompiledCodePtrSize(target_ptr_size_)); - const uint8_t* quick_code = GetOatAddressForOffset(quick_oat_code_offset); + const uint8_t* quick_code = GetOatAddress(quick_oat_code_offset); *quick_is_interpreted = false; if (quick_code != nullptr && (!method->IsStatic() || method->IsConstructor() || method->GetDeclaringClass()->IsInitialized())) { // We have code for a non-static or initialized method, just use the code. + DCHECK_GE(quick_code, oat_data_begin_); } else if (quick_code == nullptr && method->IsNative() && (!method->IsStatic() || method->GetDeclaringClass()->IsInitialized())) { // Non-static or initialized native method missing compiled code, use generic JNI version. - quick_code = GetOatAddress(kOatAddressQuickGenericJNITrampoline); + quick_code = GetOatAddress(quick_generic_jni_trampoline_offset_); + DCHECK_GE(quick_code, oat_data_begin_); } else if (quick_code == nullptr && !method->IsNative()) { // We don't have code at all for a non-native method, use the interpreter. - quick_code = GetOatAddress(kOatAddressQuickToInterpreterBridge); + quick_code = GetOatAddress(quick_to_interpreter_bridge_offset_); *quick_is_interpreted = true; + DCHECK_GE(quick_code, oat_data_begin_); } else { CHECK(!method->GetDeclaringClass()->IsInitialized()); // We have code for a static method, but need to go through the resolution stub for class // initialization. - quick_code = GetOatAddress(kOatAddressQuickResolutionTrampoline); - } - if (!IsInBootOatFile(quick_code)) { + quick_code = GetOatAddress(quick_resolution_trampoline_offset_); DCHECK_GE(quick_code, oat_data_begin_); } return quick_code; @@ -1643,16 +1479,16 @@ const uint8_t* ImageWriter::GetQuickEntryPoint(ArtMethod* method) { // The resolution method has a special trampoline to call. Runtime* runtime = Runtime::Current(); if (UNLIKELY(method == runtime->GetResolutionMethod())) { - return GetOatAddress(kOatAddressQuickResolutionTrampoline); + return GetOatAddress(quick_resolution_trampoline_offset_); } else if (UNLIKELY(method == runtime->GetImtConflictMethod() || method == runtime->GetImtUnimplementedMethod())) { - return GetOatAddress(kOatAddressQuickIMTConflictTrampoline); + return GetOatAddress(quick_imt_conflict_trampoline_offset_); } else { // We assume all methods have code. If they don't currently then we set them to the use the // resolution trampoline. Abstract methods never have code and so we need to make sure their // use results in an AbstractMethodError. We use the interpreter to achieve this. if (UNLIKELY(method->IsAbstract())) { - return GetOatAddress(kOatAddressQuickToInterpreterBridge); + return GetOatAddress(quick_to_interpreter_bridge_offset_); } else { bool quick_is_interpreted; return GetQuickCode(method, &quick_is_interpreted); @@ -1677,11 +1513,11 @@ void ImageWriter::CopyAndFixupMethod(ArtMethod* orig, ArtMethod* copy) { Runtime* runtime = Runtime::Current(); if (UNLIKELY(orig == runtime->GetResolutionMethod())) { copy->SetEntryPointFromQuickCompiledCodePtrSize( - GetOatAddress(kOatAddressQuickResolutionTrampoline), target_ptr_size_); + GetOatAddress(quick_resolution_trampoline_offset_), target_ptr_size_); } else if (UNLIKELY(orig == runtime->GetImtConflictMethod() || orig == runtime->GetImtUnimplementedMethod())) { copy->SetEntryPointFromQuickCompiledCodePtrSize( - GetOatAddress(kOatAddressQuickIMTConflictTrampoline), target_ptr_size_); + GetOatAddress(quick_imt_conflict_trampoline_offset_), target_ptr_size_); } else if (UNLIKELY(orig->IsRuntimeMethod())) { bool found_one = false; for (size_t i = 0; i < static_cast<size_t>(Runtime::kLastCalleeSaveType); ++i) { @@ -1699,7 +1535,7 @@ void ImageWriter::CopyAndFixupMethod(ArtMethod* orig, ArtMethod* copy) { // use results in an AbstractMethodError. We use the interpreter to achieve this. if (UNLIKELY(orig->IsAbstract())) { copy->SetEntryPointFromQuickCompiledCodePtrSize( - GetOatAddress(kOatAddressQuickToInterpreterBridge), target_ptr_size_); + GetOatAddress(quick_to_interpreter_bridge_offset_), target_ptr_size_); } else { bool quick_is_interpreted; const uint8_t* quick_code = GetQuickCode(orig, &quick_is_interpreted); @@ -1710,7 +1546,7 @@ void ImageWriter::CopyAndFixupMethod(ArtMethod* orig, ArtMethod* copy) { // The native method's pointer is set to a stub to lookup via dlsym. // Note this is not the code_ pointer, that is handled above. copy->SetEntryPointFromJniPtrSize( - GetOatAddress(kOatAddressJNIDlsymLookup), target_ptr_size_); + GetOatAddress(jni_dlsym_lookup_offset_), target_ptr_size_); } } } diff --git a/compiler/image_writer.h b/compiler/image_writer.h index 120de97620..7a2febcea1 100644 --- a/compiler/image_writer.h +++ b/compiler/image_writer.h @@ -40,42 +40,27 @@ #include "utils.h" namespace art { -namespace gc { -namespace space { -class ImageSpace; -} // namespace space -} // namespace gc static constexpr int kInvalidImageFd = -1; // Write a Space built during compilation for use during execution. class ImageWriter FINAL { public: - ImageWriter(const CompilerDriver& compiler_driver, - uintptr_t image_begin, - bool compile_pic, - bool compile_app_image) - : compiler_driver_(compiler_driver), - image_begin_(reinterpret_cast<uint8_t*>(image_begin)), - image_end_(0), - image_objects_offset_begin_(0), - image_roots_address_(0), - oat_file_(nullptr), - oat_data_begin_(nullptr), - compile_pic_(compile_pic), - compile_app_image_(compile_app_image), - boot_image_space_(nullptr), + ImageWriter(const CompilerDriver& compiler_driver, uintptr_t image_begin, + bool compile_pic) + : compiler_driver_(compiler_driver), image_begin_(reinterpret_cast<uint8_t*>(image_begin)), + image_end_(0), image_objects_offset_begin_(0), image_roots_address_(0), oat_file_(nullptr), + oat_data_begin_(nullptr), interpreter_to_interpreter_bridge_offset_(0), + interpreter_to_compiled_code_bridge_offset_(0), jni_dlsym_lookup_offset_(0), + quick_generic_jni_trampoline_offset_(0), + quick_imt_conflict_trampoline_offset_(0), quick_resolution_trampoline_offset_(0), + quick_to_interpreter_bridge_offset_(0), compile_pic_(compile_pic), target_ptr_size_(InstructionSetPointerSize(compiler_driver_.GetInstructionSet())), - bin_slot_sizes_(), - bin_slot_offsets_(), - bin_slot_count_(), - intern_table_bytes_(0u), - image_method_array_(ImageHeader::kImageMethodsCount), - dirty_methods_(0u), - clean_methods_(0u) { + bin_slot_sizes_(), bin_slot_offsets_(), bin_slot_count_(), + intern_table_bytes_(0u), image_method_array_(ImageHeader::kImageMethodsCount), + dirty_methods_(0u), clean_methods_(0u) { CHECK_NE(image_begin, 0U); - std::fill_n(image_methods_, arraysize(image_methods_), nullptr); - std::fill_n(oat_address_offsets_, arraysize(oat_address_offsets_), 0); + std::fill(image_methods_, image_methods_ + arraysize(image_methods_), nullptr); } ~ImageWriter() { @@ -89,9 +74,8 @@ class ImageWriter FINAL { template <typename T> T* GetImageAddress(T* object) const SHARED_REQUIRES(Locks::mutator_lock_) { - return (object == nullptr || IsInBootImage(object)) - ? object - : reinterpret_cast<T*>(image_begin_ + GetImageOffset(object)); + return object == nullptr ? nullptr : + reinterpret_cast<T*>(image_begin_ + GetImageOffset(object)); } ArtMethod* GetImageMethodAddress(ArtMethod* method) SHARED_REQUIRES(Locks::mutator_lock_); @@ -166,19 +150,6 @@ class ImageWriter FINAL { }; friend std::ostream& operator<<(std::ostream& stream, const NativeObjectRelocationType& type); - enum OatAddress { - kOatAddressInterpreterToInterpreterBridge, - kOatAddressInterpreterToCompiledCodeBridge, - kOatAddressJNIDlsymLookup, - kOatAddressQuickGenericJNITrampoline, - kOatAddressQuickIMTConflictTrampoline, - kOatAddressQuickResolutionTrampoline, - kOatAddressQuickToInterpreterBridge, - // Number of elements in the enum. - kOatAddressCount, - }; - friend std::ostream& operator<<(std::ostream& stream, const OatAddress& oat_address); - static constexpr size_t kBinBits = MinimumBitsToStore<uint32_t>(kBinMirrorCount - 1); // uint32 = typeof(lockword_) // Subtract read barrier bits since we want these to remain 0, or else it may result in DCHECK @@ -244,10 +215,7 @@ class ImageWriter FINAL { return reinterpret_cast<mirror::Object*>(dst); } - // Returns the address in the boot image if we are compiling the app image. - const uint8_t* GetOatAddress(OatAddress type) const; - - const uint8_t* GetOatAddressForOffset(uint32_t offset) const { + const uint8_t* GetOatAddress(uint32_t offset) const { // With Quick, code is within the OatFile, as there are all in one // .o ELF object. DCHECK_LE(offset, oat_file_->Size()); @@ -256,7 +224,7 @@ class ImageWriter FINAL { } // Returns true if the class was in the original requested image classes list. - bool KeepClass(mirror::Class* klass) SHARED_REQUIRES(Locks::mutator_lock_); + bool IsImageClass(mirror::Class* klass) SHARED_REQUIRES(Locks::mutator_lock_); // Debug aid that list of requested image classes. void DumpImageClasses(); @@ -331,11 +299,6 @@ class ImageWriter FINAL { void AssignMethodOffset(ArtMethod* method, NativeObjectRelocationType type) SHARED_REQUIRES(Locks::mutator_lock_); - bool IsBootClassLoaderNonImageClass(mirror::Class* klass) SHARED_REQUIRES(Locks::mutator_lock_); - - bool ContainsBootClassLoaderNonImageClass(mirror::Class* klass) - SHARED_REQUIRES(Locks::mutator_lock_); - static Bin BinTypeForNativeRelocationType(NativeObjectRelocationType type); uintptr_t NativeOffsetInImage(void* obj); @@ -343,13 +306,6 @@ class ImageWriter FINAL { template <typename T> T* NativeLocationInImage(T* obj); - // Return true of obj is inside of the boot image space. This may only return true if we are - // compiling an app image. - bool IsInBootImage(const void* obj) const; - - // Return true if ptr is within the boot oat file. - bool IsInBootOatFile(const void* ptr) const; - const CompilerDriver& compiler_driver_; // Beginning target image address for the output image. @@ -388,14 +344,14 @@ class ImageWriter FINAL { std::unique_ptr<gc::accounting::ContinuousSpaceBitmap> image_bitmap_; // Offset from oat_data_begin_ to the stubs. - uint32_t oat_address_offsets_[kOatAddressCount]; - - // Boolean flags. + uint32_t interpreter_to_interpreter_bridge_offset_; + uint32_t interpreter_to_compiled_code_bridge_offset_; + uint32_t jni_dlsym_lookup_offset_; + uint32_t quick_generic_jni_trampoline_offset_; + uint32_t quick_imt_conflict_trampoline_offset_; + uint32_t quick_resolution_trampoline_offset_; + uint32_t quick_to_interpreter_bridge_offset_; const bool compile_pic_; - const bool compile_app_image_; - - // Boot image space for fast lookups. - gc::space::ImageSpace* boot_image_space_; // Size of pointers on the target architecture. size_t target_ptr_size_; @@ -432,10 +388,6 @@ class ImageWriter FINAL { uint64_t dirty_methods_; uint64_t clean_methods_; - // Prune class memoization table. - std::unordered_map<mirror::Class*, bool> prune_class_memo_; - - friend class ContainsBootClassLoaderNonImageClassVisitor; friend class FixupClassVisitor; friend class FixupRootVisitor; friend class FixupVisitor; diff --git a/compiler/oat_test.cc b/compiler/oat_test.cc index 83d783408f..ea3cb667e2 100644 --- a/compiler/oat_test.cc +++ b/compiler/oat_test.cc @@ -111,7 +111,6 @@ TEST_F(OatTest, WriteRead) { 0, compiler_driver_.get(), nullptr, - /*compiling_boot_image*/false, &timings, &key_value_store); bool success = compiler_driver_->WriteElf(GetTestAndroidRoot(), diff --git a/compiler/oat_writer.cc b/compiler/oat_writer.cc index 3f2271ef11..c7b8884214 100644 --- a/compiler/oat_writer.cc +++ b/compiler/oat_writer.cc @@ -65,12 +65,10 @@ OatWriter::OatWriter(const std::vector<const DexFile*>& dex_files, int32_t image_patch_delta, const CompilerDriver* compiler, ImageWriter* image_writer, - bool compiling_boot_image, TimingLogger* timings, SafeMap<std::string, std::string>* key_value_store) : compiler_driver_(compiler), image_writer_(image_writer), - compiling_boot_image_(compiling_boot_image), dex_files_(&dex_files), size_(0u), bss_size_(0u), @@ -115,9 +113,7 @@ OatWriter::OatWriter(const std::vector<const DexFile*>& dex_files, size_oat_lookup_table_(0), method_offset_map_() { CHECK(key_value_store != nullptr); - if (compiling_boot_image) { - CHECK(image_writer != nullptr); - } + InstructionSet instruction_set = compiler_driver_->GetInstructionSet(); const InstructionSetFeatures* features = compiler_driver_->GetInstructionSetFeatures(); relative_patcher_ = linker::RelativePatcher::Create(instruction_set, features, @@ -158,7 +154,7 @@ OatWriter::OatWriter(const std::vector<const DexFile*>& dex_files, } size_ = offset; - if (!HasBootImage()) { + if (!HasImage()) { // Allocate space for app dex cache arrays in the .bss section. size_t bss_start = RoundUp(size_, kPageSize); size_t pointer_size = GetInstructionSetPointerSize(instruction_set); @@ -171,10 +167,9 @@ OatWriter::OatWriter(const std::vector<const DexFile*>& dex_files, } CHECK_EQ(dex_files_->size(), oat_dex_files_.size()); - if (compiling_boot_image_) { - CHECK_EQ(image_writer_ != nullptr, - key_value_store_->find(OatHeader::kImageLocationKey) == key_value_store_->end()); - } + CHECK_EQ(compiler->IsImage(), image_writer_ != nullptr); + CHECK_EQ(compiler->IsImage(), + key_value_store_->find(OatHeader::kImageLocationKey) == key_value_store_->end()); CHECK_ALIGNED(image_patch_delta_, kPageSize); } @@ -677,7 +672,7 @@ class OatWriter::WriteCodeMethodVisitor : public OatDexMethodVisitor { class_linker_(Runtime::Current()->GetClassLinker()), dex_cache_(nullptr) { patched_code_.reserve(16 * KB); - if (writer_->HasBootImage()) { + if (writer_->HasImage()) { // If we're creating the image, the address space must be ready so that we can apply patches. CHECK(writer_->image_writer_->IsImageAddressSpaceReady()); } @@ -860,7 +855,7 @@ class OatWriter::WriteCodeMethodVisitor : public OatDexMethodVisitor { } uint32_t GetDexCacheOffset(const LinkerPatch& patch) SHARED_REQUIRES(Locks::mutator_lock_) { - if (writer_->HasBootImage()) { + if (writer_->HasImage()) { auto* element = writer_->image_writer_->GetDexCacheArrayElementImageAddress<const uint8_t*>( patch.TargetDexCacheDexFile(), patch.TargetDexCacheElementOffset()); const uint8_t* oat_data = writer_->image_writer_->GetOatFileBegin() + file_offset_; @@ -873,7 +868,7 @@ class OatWriter::WriteCodeMethodVisitor : public OatDexMethodVisitor { void PatchObjectAddress(std::vector<uint8_t>* code, uint32_t offset, mirror::Object* object) SHARED_REQUIRES(Locks::mutator_lock_) { - if (writer_->HasBootImage()) { + if (writer_->HasImage()) { object = writer_->image_writer_->GetImageAddress(object); } else { // NOTE: We're using linker patches for app->boot references when the image can @@ -893,7 +888,7 @@ class OatWriter::WriteCodeMethodVisitor : public OatDexMethodVisitor { void PatchMethodAddress(std::vector<uint8_t>* code, uint32_t offset, ArtMethod* method) SHARED_REQUIRES(Locks::mutator_lock_) { - if (writer_->HasBootImage()) { + if (writer_->HasImage()) { method = writer_->image_writer_->GetImageMethodAddress(method); } else if (kIsDebugBuild) { // NOTE: We're using linker patches for app->boot references when the image can @@ -916,7 +911,7 @@ class OatWriter::WriteCodeMethodVisitor : public OatDexMethodVisitor { void PatchCodeAddress(std::vector<uint8_t>* code, uint32_t offset, uint32_t target_offset) SHARED_REQUIRES(Locks::mutator_lock_) { uint32_t address = target_offset; - if (writer_->HasBootImage()) { + if (writer_->HasImage()) { address = PointerToLowMemUInt32(writer_->image_writer_->GetOatFileBegin() + writer_->oat_data_offset_ + target_offset); } @@ -1128,7 +1123,7 @@ size_t OatWriter::InitOatCode(size_t offset) { offset = RoundUp(offset, kPageSize); oat_header_->SetExecutableOffset(offset); size_executable_offset_alignment_ = offset - old_offset; - if (compiler_driver_->IsBootImage()) { + if (compiler_driver_->IsImage()) { CHECK_EQ(image_patch_delta_, 0); InstructionSet instruction_set = compiler_driver_->GetInstructionSet(); @@ -1169,7 +1164,7 @@ size_t OatWriter::InitOatCodeDexFiles(size_t offset) { } while (false) VISIT(InitCodeMethodVisitor); - if (compiler_driver_->IsBootImage()) { + if (compiler_driver_->IsImage()) { VISIT(InitImageMethodVisitor); } @@ -1413,7 +1408,7 @@ size_t OatWriter::WriteMaps(OutputStream* out, const size_t file_offset, size_t } size_t OatWriter::WriteCode(OutputStream* out, const size_t file_offset, size_t relative_offset) { - if (compiler_driver_->IsBootImage()) { + if (compiler_driver_->IsImage()) { InstructionSet instruction_set = compiler_driver_->GetInstructionSet(); #define DO_TRAMPOLINE(field) \ diff --git a/compiler/oat_writer.h b/compiler/oat_writer.h index 7027434cca..f2fe048174 100644 --- a/compiler/oat_writer.h +++ b/compiler/oat_writer.h @@ -93,7 +93,6 @@ class OatWriter { int32_t image_patch_delta, const CompilerDriver* compiler, ImageWriter* image_writer, - bool compiling_boot_image, TimingLogger* timings, SafeMap<std::string, std::string>* key_value_store); @@ -104,10 +103,6 @@ class OatWriter { return image_writer_ != nullptr; } - bool HasBootImage() const { - return compiling_boot_image_; - } - const OatHeader& GetOatHeader() const { return *oat_header_; } @@ -284,7 +279,6 @@ class OatWriter { const CompilerDriver* const compiler_driver_; ImageWriter* const image_writer_; - const bool compiling_boot_image_; // note OatFile does not take ownership of the DexFiles const std::vector<const DexFile*>* dex_files_; |