diff options
Diffstat (limited to 'compiler/image_writer.cc')
| -rw-r--r-- | compiler/image_writer.cc | 149 |
1 files changed, 65 insertions, 84 deletions
diff --git a/compiler/image_writer.cc b/compiler/image_writer.cc index 73574ba673..3d3130962a 100644 --- a/compiler/image_writer.cc +++ b/compiler/image_writer.cc @@ -124,7 +124,10 @@ bool ImageWriter::PrepareImageAddressSpace() { { ScopedObjectAccess soa(Thread::Current()); PruneNonImageClasses(); // Remove junk - ComputeLazyFieldsForImageClasses(); // Add useful information + if (!compile_app_image_) { + // Avoid for app image since this may increase RAM and image size. + ComputeLazyFieldsForImageClasses(); // Add useful information + } } heap->CollectGarbage(false); // Remove garbage. @@ -735,20 +738,20 @@ bool ImageWriter::IsBootClassLoaderNonImageClass(mirror::Class* klass) { return IsBootClassLoaderClass(klass) && !IsInBootImage(klass); } -bool ImageWriter::ContainsBootClassLoaderNonImageClass(mirror::Class* klass) { +bool ImageWriter::PruneAppImageClass(mirror::Class* klass) { bool early_exit = false; std::unordered_set<mirror::Class*> visited; - return ContainsBootClassLoaderNonImageClassInternal(klass, &early_exit, &visited); + return PruneAppImageClassInternal(klass, &early_exit, &visited); } -bool ImageWriter::ContainsBootClassLoaderNonImageClassInternal( +bool ImageWriter::PruneAppImageClassInternal( mirror::Class* klass, bool* early_exit, std::unordered_set<mirror::Class*>* visited) { DCHECK(early_exit != nullptr); DCHECK(visited != nullptr); DCHECK(compile_app_image_); - if (klass == nullptr) { + if (klass == nullptr || IsInBootImage(klass)) { return false; } auto found = prune_class_memo_.find(klass); @@ -762,7 +765,11 @@ bool ImageWriter::ContainsBootClassLoaderNonImageClassInternal( return false; } visited->emplace(klass); - bool result = IsBootClassLoaderNonImageClass(klass); + bool result = IsBootClassLoaderClass(klass); + std::string temp; + // Prune if not an image class, this handles any broken sets of image classes such as having a + // class in the set but not it's superclass. + result = result || !compiler_driver_.IsImageClass(klass->GetDescriptor(&temp)); bool my_early_exit = false; // Only for ourselves, ignore caller. // Remove classes that failed to verify since we don't want to have java.lang.VerifyError in the // app image. @@ -775,17 +782,15 @@ bool ImageWriter::ContainsBootClassLoaderNonImageClassInternal( // 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 || ContainsBootClassLoaderNonImageClassInternal( - if_table->GetInterface(i), - &my_early_exit, - visited); + result = result || PruneAppImageClassInternal(if_table->GetInterface(i), + &my_early_exit, + visited); } } if (klass->IsObjectArrayClass()) { - result = result || ContainsBootClassLoaderNonImageClassInternal( - klass->GetComponentType(), - &my_early_exit, - visited); + result = result || PruneAppImageClassInternal(klass->GetComponentType(), + &my_early_exit, + visited); } // Check static fields and their classes. size_t num_static_fields = klass->NumReferenceStaticFields(); @@ -798,27 +803,22 @@ bool ImageWriter::ContainsBootClassLoaderNonImageClassInternal( mirror::Object* ref = klass->GetFieldObject<mirror::Object>(field_offset); if (ref != nullptr) { if (ref->IsClass()) { - result = result || - ContainsBootClassLoaderNonImageClassInternal( - ref->AsClass(), - &my_early_exit, - visited); + result = result || PruneAppImageClassInternal(ref->AsClass(), + &my_early_exit, + visited); + } else { + result = result || PruneAppImageClassInternal(ref->GetClass(), + &my_early_exit, + visited); } - result = result || - ContainsBootClassLoaderNonImageClassInternal( - ref->GetClass(), - &my_early_exit, - visited); } field_offset = MemberOffset(field_offset.Uint32Value() + sizeof(mirror::HeapReference<mirror::Object>)); } } - result = result || - ContainsBootClassLoaderNonImageClassInternal( - klass->GetSuperClass(), - &my_early_exit, - visited); + result = result || PruneAppImageClassInternal(klass->GetSuperClass(), + &my_early_exit, + visited); // Erase the element we stored earlier since we are exiting the function. auto it = visited->find(klass); DCHECK(it != visited->end()); @@ -837,15 +837,21 @@ bool ImageWriter::KeepClass(Class* klass) { if (klass == nullptr) { return false; } + if (compile_app_image_ && Runtime::Current()->GetHeap()->ObjectIsInBootImageSpace(klass)) { + // Already in boot image, return true. + return true; + } + std::string temp; + if (!compiler_driver_.IsImageClass(klass->GetDescriptor(&temp))) { + 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. // Keep classes in the boot image space since we don't want to re-resolve these. - return Runtime::Current()->GetHeap()->ObjectIsInBootImageSpace(klass) || - !ContainsBootClassLoaderNonImageClass(klass); + return !PruneAppImageClass(klass); } - std::string temp; - return compiler_driver_.IsImageClass(klass->GetDescriptor(&temp)); + return true; } class NonImageClassesVisitor : public ClassVisitor { @@ -873,6 +879,7 @@ void ImageWriter::PruneNonImageClasses() { class_linker->VisitClasses(&visitor); // Remove the undesired classes from the class roots. + VLOG(compiler) << "Pruning " << visitor.classes_to_prune_.size() << " classes"; for (mirror::Class* klass : visitor.classes_to_prune_) { std::string temp; const char* name = klass->GetDescriptor(&temp); @@ -891,10 +898,10 @@ void ImageWriter::PruneNonImageClasses() { ReaderMutexLock mu(self, *Locks::classlinker_classes_lock_); // For ClassInClassTable ReaderMutexLock mu2(self, *class_linker->DexLock()); for (const ClassLinker::DexCacheData& data : class_linker->GetDexCachesData()) { - mirror::DexCache* dex_cache = down_cast<mirror::DexCache*>(self->DecodeJObject(data.weak_root)); - if (dex_cache == nullptr) { + if (self->IsJWeakCleared(data.weak_root)) { continue; } + mirror::DexCache* dex_cache = self->DecodeJObject(data.weak_root)->AsDexCache(); for (size_t i = 0; i < dex_cache->NumResolvedTypes(); i++) { Class* klass = dex_cache->GetResolvedType(i); if (klass != nullptr && !KeepClass(klass)) { @@ -907,10 +914,10 @@ void ImageWriter::PruneNonImageClasses() { mirror::DexCache::GetElementPtrSize(resolved_methods, i, target_ptr_size_); DCHECK(method != nullptr) << "Expected resolution method instead of null method"; mirror::Class* declaring_class = method->GetDeclaringClass(); - // Miranda methods may be held live by a class which was not an image class but have a + // Copied 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->IsCopied() || !KeepClass(declaring_class)) { mirror::DexCache::SetElementPtrSize(resolved_methods, i, resolution_method, @@ -1820,12 +1827,16 @@ uintptr_t ImageWriter::NativeOffsetInImage(void* obj) { } template <typename T> -T* ImageWriter::NativeLocationInImage(T* obj, const char* oat_filename) { +T* ImageWriter::NativeLocationInImage(T* obj) { if (obj == nullptr || IsInBootImage(obj)) { return obj; } else { - ImageInfo& image_info = GetImageInfo(oat_filename); - return reinterpret_cast<T*>(image_info.image_begin_ + NativeOffsetInImage(obj)); + auto it = native_object_relocations_.find(obj); + CHECK(it != native_object_relocations_.end()) << obj << " spaces " + << Runtime::Current()->GetHeap()->DumpSpaces(); + const NativeObjectRelocation& relocation = it->second; + ImageInfo& image_info = GetImageInfo(relocation.oat_filename); + return reinterpret_cast<T*>(image_info.image_begin_ + relocation.offset); } } @@ -1842,33 +1853,19 @@ T* ImageWriter::NativeCopyLocation(T* obj, mirror::DexCache* dex_cache) { class NativeLocationVisitor { public: - explicit NativeLocationVisitor(ImageWriter* image_writer, const char* oat_filename) - : image_writer_(image_writer), oat_filename_(oat_filename) {} + explicit NativeLocationVisitor(ImageWriter* image_writer) : image_writer_(image_writer) {} template <typename T> T* operator()(T* ptr) const SHARED_REQUIRES(Locks::mutator_lock_) { - return image_writer_->NativeLocationInImage(ptr, oat_filename_); - } - - ArtMethod* operator()(ArtMethod* method) const SHARED_REQUIRES(Locks::mutator_lock_) { - const char* oat_filename = method->IsRuntimeMethod() ? image_writer_->GetDefaultOatFilename() : - image_writer_->GetOatFilenameForDexCache(method->GetDexCache()); - return image_writer_->NativeLocationInImage(method, oat_filename); - } - - ArtField* operator()(ArtField* field) const SHARED_REQUIRES(Locks::mutator_lock_) { - const char* oat_filename = image_writer_->GetOatFilenameForDexCache(field->GetDexCache()); - return image_writer_->NativeLocationInImage(field, oat_filename); + return image_writer_->NativeLocationInImage(ptr); } private: ImageWriter* const image_writer_; - const char* oat_filename_; }; void ImageWriter::FixupClass(mirror::Class* orig, mirror::Class* copy) { - const char* oat_filename = GetOatFilename(orig); - orig->FixupNativePointers(copy, target_ptr_size_, NativeLocationVisitor(this, oat_filename)); + orig->FixupNativePointers(copy, target_ptr_size_, NativeLocationVisitor(this)); FixupClassVisitor visitor(this, copy); static_cast<mirror::Object*>(orig)->VisitReferences(visitor, visitor); @@ -1952,11 +1949,10 @@ void ImageWriter::FixupDexCache(mirror::DexCache* orig_dex_cache, // 64-bit values here, clearing the top 32 bits for 32-bit targets. The zero-extension is // done by casting to the unsigned type uintptr_t before casting to int64_t, i.e. // static_cast<int64_t>(reinterpret_cast<uintptr_t>(image_begin_ + offset))). - const char* oat_filename = GetOatFilenameForDexCache(orig_dex_cache); GcRoot<mirror::String>* orig_strings = orig_dex_cache->GetStrings(); if (orig_strings != nullptr) { copy_dex_cache->SetFieldPtrWithSize<false>(mirror::DexCache::StringsOffset(), - NativeLocationInImage(orig_strings, oat_filename), + NativeLocationInImage(orig_strings), /*pointer size*/8u); orig_dex_cache->FixupStrings(NativeCopyLocation(orig_strings, orig_dex_cache), ImageAddressVisitor(this)); @@ -1964,7 +1960,7 @@ void ImageWriter::FixupDexCache(mirror::DexCache* orig_dex_cache, GcRoot<mirror::Class>* orig_types = orig_dex_cache->GetResolvedTypes(); if (orig_types != nullptr) { copy_dex_cache->SetFieldPtrWithSize<false>(mirror::DexCache::ResolvedTypesOffset(), - NativeLocationInImage(orig_types, oat_filename), + NativeLocationInImage(orig_types), /*pointer size*/8u); orig_dex_cache->FixupResolvedTypes(NativeCopyLocation(orig_types, orig_dex_cache), ImageAddressVisitor(this)); @@ -1972,32 +1968,25 @@ void ImageWriter::FixupDexCache(mirror::DexCache* orig_dex_cache, ArtMethod** orig_methods = orig_dex_cache->GetResolvedMethods(); if (orig_methods != nullptr) { copy_dex_cache->SetFieldPtrWithSize<false>(mirror::DexCache::ResolvedMethodsOffset(), - NativeLocationInImage(orig_methods, oat_filename), + NativeLocationInImage(orig_methods), /*pointer size*/8u); ArtMethod** copy_methods = NativeCopyLocation(orig_methods, orig_dex_cache); for (size_t i = 0, num = orig_dex_cache->NumResolvedMethods(); i != num; ++i) { ArtMethod* orig = mirror::DexCache::GetElementPtrSize(orig_methods, i, target_ptr_size_); - const char* method_oat_filename; - if (orig == nullptr || orig->IsRuntimeMethod()) { - method_oat_filename = default_oat_filename_; - } else { - method_oat_filename = GetOatFilenameForDexCache(orig->GetDexCache()); - } - ArtMethod* copy = NativeLocationInImage(orig, method_oat_filename); + // NativeLocationInImage also handles runtime methods since these have relocation info. + ArtMethod* copy = NativeLocationInImage(orig); mirror::DexCache::SetElementPtrSize(copy_methods, i, copy, target_ptr_size_); } } ArtField** orig_fields = orig_dex_cache->GetResolvedFields(); if (orig_fields != nullptr) { copy_dex_cache->SetFieldPtrWithSize<false>(mirror::DexCache::ResolvedFieldsOffset(), - NativeLocationInImage(orig_fields, oat_filename), + NativeLocationInImage(orig_fields), /*pointer size*/8u); ArtField** copy_fields = NativeCopyLocation(orig_fields, orig_dex_cache); for (size_t i = 0, num = orig_dex_cache->NumResolvedFields(); i != num; ++i) { ArtField* orig = mirror::DexCache::GetElementPtrSize(orig_fields, i, target_ptr_size_); - const char* field_oat_filename = - orig == nullptr ? default_oat_filename_ : GetOatFilenameForDexCache(orig->GetDexCache()); - ArtField* copy = NativeLocationInImage(orig, field_oat_filename); + ArtField* copy = NativeLocationInImage(orig); mirror::DexCache::SetElementPtrSize(copy_fields, i, copy, target_ptr_size_); } } @@ -2089,20 +2078,10 @@ void ImageWriter::CopyAndFixupMethod(ArtMethod* orig, copy->SetDeclaringClass(GetImageAddress(orig->GetDeclaringClassUnchecked())); - const char* oat_filename; - if (orig->IsRuntimeMethod() || compile_app_image_) { - oat_filename = default_oat_filename_; - } else { - auto it = dex_file_oat_filename_map_.find(orig->GetDexFile()); - DCHECK(it != dex_file_oat_filename_map_.end()) << orig->GetDexFile()->GetLocation(); - oat_filename = it->second; - } ArtMethod** orig_resolved_methods = orig->GetDexCacheResolvedMethods(target_ptr_size_); - copy->SetDexCacheResolvedMethods(NativeLocationInImage(orig_resolved_methods, oat_filename), - target_ptr_size_); + copy->SetDexCacheResolvedMethods(NativeLocationInImage(orig_resolved_methods), target_ptr_size_); GcRoot<mirror::Class>* orig_resolved_types = orig->GetDexCacheResolvedTypes(target_ptr_size_); - copy->SetDexCacheResolvedTypes(NativeLocationInImage(orig_resolved_types, oat_filename), - target_ptr_size_); + copy->SetDexCacheResolvedTypes(NativeLocationInImage(orig_resolved_types), target_ptr_size_); // OatWriter replaces the code_ with an offset value. Here we re-adjust to a pointer relative to // oat_begin_ @@ -2324,6 +2303,8 @@ ImageWriter::ImageWriter( image_info_map_.emplace(oat_filename, ImageInfo()); } std::fill_n(image_methods_, arraysize(image_methods_), nullptr); + CHECK_EQ(compile_app_image, !Runtime::Current()->GetHeap()->GetBootImageSpaces().empty()) + << "Compiling a boot image should occur iff there are no boot image spaces loaded"; } ImageWriter::ImageInfo::ImageInfo() |