diff options
Diffstat (limited to 'compiler/image_writer.cc')
| -rw-r--r-- | compiler/image_writer.cc | 217 |
1 files changed, 118 insertions, 99 deletions
diff --git a/compiler/image_writer.cc b/compiler/image_writer.cc index 0c85323805..3d9e7e7cda 100644 --- a/compiler/image_writer.cc +++ b/compiler/image_writer.cc @@ -334,9 +334,9 @@ void ImageWriter::PrepareDexCacheArraySlots() { Thread* const self = Thread::Current(); ReaderMutexLock mu(self, *class_linker->DexLock()); uint32_t size = 0u; - for (jobject weak_root : class_linker->GetDexCaches()) { + for (const ClassLinker::DexCacheData& data : class_linker->GetDexCachesData()) { mirror::DexCache* dex_cache = - down_cast<mirror::DexCache*>(self->DecodeJObject(weak_root)); + down_cast<mirror::DexCache*>(self->DecodeJObject(data.weak_root)); if (dex_cache == nullptr || IsInBootImage(dex_cache)) { continue; } @@ -372,9 +372,9 @@ void ImageWriter::AddMethodPointerArray(mirror::PointerArray* arr) { DCHECK(arr != nullptr); if (kIsDebugBuild) { for (size_t i = 0, len = arr->GetLength(); i < len; i++) { - auto* method = arr->GetElementPtrSize<ArtMethod*>(i, target_ptr_size_); + ArtMethod* method = arr->GetElementPtrSize<ArtMethod*>(i, target_ptr_size_); if (method != nullptr && !method->IsRuntimeMethod()) { - auto* klass = method->GetDeclaringClass(); + mirror::Class* klass = method->GetDeclaringClass(); CHECK(klass == nullptr || KeepClass(klass)) << PrettyClass(klass) << " should be a kept class"; } @@ -514,7 +514,7 @@ bool ImageWriter::IsImageBinSlotAssigned(mirror::Object* object) const { size_t offset = lock_word.ForwardingAddress(); BinSlot bin_slot(offset); DCHECK_LT(bin_slot.GetIndex(), bin_slot_sizes_[bin_slot.GetBin()]) - << "bin slot offset should not exceed the size of that bin"; + << "bin slot offset should not exceed the size of that bin"; } return true; } @@ -537,8 +537,13 @@ bool ImageWriter::AllocMemory() { const size_t length = RoundUp(image_objects_offset_begin_ + GetBinSizeSum() + intern_table_bytes_, kPageSize); std::string error_msg; - image_.reset(MemMap::MapAnonymous("image writer image", nullptr, length, PROT_READ | PROT_WRITE, - false, false, &error_msg)); + image_.reset(MemMap::MapAnonymous("image writer image", + nullptr, + length, + PROT_READ | PROT_WRITE, + false, + false, + &error_msg)); if (UNLIKELY(image_.get() == nullptr)) { LOG(ERROR) << "Failed to allocate memory for image file generation: " << error_msg; return false; @@ -547,7 +552,9 @@ bool ImageWriter::AllocMemory() { // Create the image bitmap, only needs to cover mirror object section which is up to image_end_. CHECK_LE(image_end_, length); image_bitmap_.reset(gc::accounting::ContinuousSpaceBitmap::Create( - "image bitmap", image_->Begin(), RoundUp(image_end_, kPageSize))); + "image bitmap", + image_->Begin(), + RoundUp(image_end_, kPageSize))); if (image_bitmap_.get() == nullptr) { LOG(ERROR) << "Failed to allocate memory for image bitmap"; return false; @@ -676,8 +683,8 @@ void ImageWriter::PruneNonImageClasses() { ScopedAssertNoThreadSuspension sa(self, __FUNCTION__); ReaderMutexLock mu(self, *Locks::classlinker_classes_lock_); // For ClassInClassTable ReaderMutexLock mu2(self, *class_linker->DexLock()); - for (jobject weak_root : class_linker->GetDexCaches()) { - mirror::DexCache* dex_cache = down_cast<mirror::DexCache*>(self->DecodeJObject(weak_root)); + 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) { continue; } @@ -799,8 +806,9 @@ ObjectArray<Object>* ImageWriter::CreateImageRoots() const { { 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)); + for (const ClassLinker::DexCacheData& data : class_linker->GetDexCachesData()) { + mirror::DexCache* dex_cache = + down_cast<mirror::DexCache*>(self->DecodeJObject(data.weak_root)); dex_cache_count += IsInBootImage(dex_cache) ? 0u : 1u; } } @@ -811,15 +819,17 @@ ObjectArray<Object>* ImageWriter::CreateImageRoots() const { 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)); + for (const ClassLinker::DexCacheData& data : class_linker->GetDexCachesData()) { + mirror::DexCache* dex_cache = + down_cast<mirror::DexCache*>(self->DecodeJObject(data.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."; size_t i = 0; - for (jobject weak_root : class_linker->GetDexCaches()) { - mirror::DexCache* dex_cache = down_cast<mirror::DexCache*>(self->DecodeJObject(weak_root)); + for (const ClassLinker::DexCacheData& data : class_linker->GetDexCachesData()) { + mirror::DexCache* dex_cache = + down_cast<mirror::DexCache*>(self->DecodeJObject(data.weak_root)); if (!IsInBootImage(dex_cache)) { dex_caches->Set<false>(i, dex_cache); ++i; @@ -905,8 +915,8 @@ void ImageWriter::WalkFieldsInOrder(mirror::Object* obj) { size_t& offset = bin_slot_sizes_[kBinArtField]; DCHECK(!IsInBootImage(cur_fields)); native_object_relocations_.emplace( - cur_fields, NativeObjectRelocation { - offset, kNativeObjectRelocationTypeArtFieldArray }); + cur_fields, + NativeObjectRelocation {offset, kNativeObjectRelocationTypeArtFieldArray }); offset += header_size; // Forward individual fields so that we can quickly find where they belong. for (size_t i = 0, count = cur_fields->size(); i < count; ++i) { @@ -917,7 +927,8 @@ void ImageWriter::WalkFieldsInOrder(mirror::Object* obj) { << " already assigned " << PrettyField(field) << " static=" << field->IsStatic(); DCHECK(!IsInBootImage(field)); native_object_relocations_.emplace( - field, NativeObjectRelocation {offset, kNativeObjectRelocationTypeArtField }); + field, + NativeObjectRelocation {offset, kNativeObjectRelocationTypeArtField }); offset += sizeof(ArtField); } } @@ -940,8 +951,9 @@ void ImageWriter::WalkFieldsInOrder(mirror::Object* obj) { any_dirty = any_dirty || WillMethodBeDirty(&m); ++count; } - NativeObjectRelocationType type = any_dirty ? kNativeObjectRelocationTypeArtMethodDirty : - kNativeObjectRelocationTypeArtMethodClean; + NativeObjectRelocationType type = any_dirty + ? kNativeObjectRelocationTypeArtMethodDirty + : kNativeObjectRelocationTypeArtMethodClean; Bin bin_type = BinTypeForNativeRelocationType(type); // Forward the entire array at once, but header first. const size_t header_size = LengthPrefixedArray<ArtMethod>::ComputeSize(0, @@ -1124,8 +1136,9 @@ void ImageWriter::CreateHeader(size_t oat_loaded_size, size_t oat_data_offset) { cur_pos = RoundUp(cur_pos, ArtMethod::Alignment(target_ptr_size_)); // Add method section. auto* methods_section = §ions[ImageHeader::kSectionArtMethods]; - *methods_section = ImageSection(cur_pos, bin_slot_sizes_[kBinArtMethodClean] + - bin_slot_sizes_[kBinArtMethodDirty]); + *methods_section = ImageSection(cur_pos, + bin_slot_sizes_[kBinArtMethodClean] + + bin_slot_sizes_[kBinArtMethodDirty]); CHECK_EQ(bin_slot_offsets_[kBinArtMethodClean], methods_section->Offset()); cur_pos = methods_section->End(); // Add dex cache arrays section. @@ -1156,12 +1169,17 @@ void ImageWriter::CreateHeader(size_t oat_loaded_size, size_t oat_data_offset) { CHECK_EQ(AlignUp(image_begin_ + image_end, kPageSize), oat_file_begin) << "Oat file should be right after the image."; // Create the header. - new (image_->Begin()) ImageHeader( - PointerToLowMemUInt32(image_begin_), image_end, - sections, image_roots_address_, oat_file_->GetOatHeader().GetChecksum(), - PointerToLowMemUInt32(oat_file_begin), PointerToLowMemUInt32(oat_data_begin_), - PointerToLowMemUInt32(oat_data_end), PointerToLowMemUInt32(oat_file_end), target_ptr_size_, - compile_pic_); + new (image_->Begin()) ImageHeader(PointerToLowMemUInt32(image_begin_), + image_end, + sections, + image_roots_address_, + oat_file_->GetOatHeader().GetChecksum(), + PointerToLowMemUInt32(oat_file_begin), + PointerToLowMemUInt32(oat_data_begin_), + PointerToLowMemUInt32(oat_data_end), + PointerToLowMemUInt32(oat_file_end), + target_ptr_size_, + compile_pic_); } ArtMethod* ImageWriter::GetImageMethodAddress(ArtMethod* method) { @@ -1371,14 +1389,16 @@ class FixupVisitor { // Use SetFieldObjectWithoutWriteBarrier to avoid card marking since we are writing to the // image. copy_->SetFieldObjectWithoutWriteBarrier<false, true, kVerifyNone>( - offset, image_writer_->GetImageAddress(ref)); + offset, + image_writer_->GetImageAddress(ref)); } // java.lang.ref.Reference visitor. void operator()(mirror::Class* klass ATTRIBUTE_UNUSED, mirror::Reference* ref) const SHARED_REQUIRES(Locks::mutator_lock_) REQUIRES(Locks::heap_bitmap_lock_) { copy_->SetFieldObjectWithoutWriteBarrier<false, true, kVerifyNone>( - mirror::Reference::ReferentOffset(), image_writer_->GetImageAddress(ref->GetReferent())); + mirror::Reference::ReferentOffset(), + image_writer_->GetImageAddress(ref->GetReferent())); } protected: @@ -1421,34 +1441,28 @@ T* ImageWriter::NativeLocationInImage(T* obj) { : reinterpret_cast<T*>(image_begin_ + NativeOffsetInImage(obj)); } -void ImageWriter::FixupClass(mirror::Class* orig, mirror::Class* copy) { - // Update the field arrays. - copy->SetSFieldsPtrUnchecked(NativeLocationInImage(orig->GetSFieldsPtr())); - copy->SetIFieldsPtrUnchecked(NativeLocationInImage(orig->GetIFieldsPtr())); - // Update direct and virtual method arrays. - copy->SetDirectMethodsPtrUnchecked(NativeLocationInImage(orig->GetDirectMethodsPtr())); - copy->SetVirtualMethodsPtr(NativeLocationInImage(orig->GetVirtualMethodsPtr())); - // 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_); - } - } +template <typename T> +T* ImageWriter::NativeCopyLocation(T* obj) { + return (obj == nullptr || IsInBootImage(obj)) + ? obj + : reinterpret_cast<T*>(image_->Begin() + NativeOffsetInImage(obj)); +} + +class NativeLocationVisitor { + public: + explicit NativeLocationVisitor(ImageWriter* image_writer) : image_writer_(image_writer) {} + + template <typename T> + T* operator()(T* ptr) const { + return image_writer_->NativeLocationInImage(ptr); } + + private: + ImageWriter* const image_writer_; +}; + +void ImageWriter::FixupClass(mirror::Class* orig, mirror::Class* copy) { + orig->FixupNativePointers(copy, target_ptr_size_, NativeLocationVisitor(this)); FixupClassVisitor visitor(this, copy); static_cast<mirror::Object*>(orig)->VisitReferences(visitor, visitor); } @@ -1508,6 +1522,21 @@ void ImageWriter::FixupObject(Object* orig, Object* copy) { } } + +class ImageAddressVisitor { + public: + explicit ImageAddressVisitor(ImageWriter* image_writer) : image_writer_(image_writer) {} + + template <typename T> + T* operator()(T* ptr) const SHARED_REQUIRES(Locks::mutator_lock_) { + return image_writer_->GetImageAddress(ptr); + } + + private: + ImageWriter* const image_writer_; +}; + + void ImageWriter::FixupDexCache(mirror::DexCache* orig_dex_cache, mirror::DexCache* copy_dex_cache) { // Though the DexCache array fields are usually treated as native pointers, we set the full @@ -1516,52 +1545,39 @@ void ImageWriter::FixupDexCache(mirror::DexCache* orig_dex_cache, // static_cast<int64_t>(reinterpret_cast<uintptr_t>(image_begin_ + offset))). GcRoot<mirror::String>* orig_strings = orig_dex_cache->GetStrings(); if (orig_strings != nullptr) { - uintptr_t copy_strings_offset = NativeOffsetInImage(orig_strings); - copy_dex_cache->SetField64<false>( - mirror::DexCache::StringsOffset(), - static_cast<int64_t>(reinterpret_cast<uintptr_t>(image_begin_ + copy_strings_offset))); - GcRoot<mirror::String>* copy_strings = - reinterpret_cast<GcRoot<mirror::String>*>(image_->Begin() + copy_strings_offset); - for (size_t i = 0, num = orig_dex_cache->NumStrings(); i != num; ++i) { - copy_strings[i] = GcRoot<mirror::String>(GetImageAddress(orig_strings[i].Read())); - } + copy_dex_cache->SetFieldPtrWithSize<false>(mirror::DexCache::StringsOffset(), + NativeLocationInImage(orig_strings), + /*pointer size*/8u); + orig_dex_cache->FixupStrings(NativeCopyLocation(orig_strings), ImageAddressVisitor(this)); } GcRoot<mirror::Class>* orig_types = orig_dex_cache->GetResolvedTypes(); if (orig_types != nullptr) { - uintptr_t copy_types_offset = NativeOffsetInImage(orig_types); - copy_dex_cache->SetField64<false>( - mirror::DexCache::ResolvedTypesOffset(), - static_cast<int64_t>(reinterpret_cast<uintptr_t>(image_begin_ + copy_types_offset))); - GcRoot<mirror::Class>* copy_types = - reinterpret_cast<GcRoot<mirror::Class>*>(image_->Begin() + copy_types_offset); - for (size_t i = 0, num = orig_dex_cache->NumResolvedTypes(); i != num; ++i) { - copy_types[i] = GcRoot<mirror::Class>(GetImageAddress(orig_types[i].Read())); - } + copy_dex_cache->SetFieldPtrWithSize<false>(mirror::DexCache::ResolvedTypesOffset(), + NativeLocationInImage(orig_types), + /*pointer size*/8u); + orig_dex_cache->FixupResolvedTypes(NativeCopyLocation(orig_types), ImageAddressVisitor(this)); } ArtMethod** orig_methods = orig_dex_cache->GetResolvedMethods(); if (orig_methods != nullptr) { - uintptr_t copy_methods_offset = NativeOffsetInImage(orig_methods); - copy_dex_cache->SetField64<false>( - mirror::DexCache::ResolvedMethodsOffset(), - static_cast<int64_t>(reinterpret_cast<uintptr_t>(image_begin_ + copy_methods_offset))); - ArtMethod** copy_methods = - reinterpret_cast<ArtMethod**>(image_->Begin() + copy_methods_offset); + copy_dex_cache->SetFieldPtrWithSize<false>(mirror::DexCache::ResolvedMethodsOffset(), + NativeLocationInImage(orig_methods), + /*pointer size*/8u); + ArtMethod** copy_methods = NativeCopyLocation(orig_methods); 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_); } } ArtField** orig_fields = orig_dex_cache->GetResolvedFields(); if (orig_fields != nullptr) { - uintptr_t copy_fields_offset = NativeOffsetInImage(orig_fields); - copy_dex_cache->SetField64<false>( - mirror::DexCache::ResolvedFieldsOffset(), - static_cast<int64_t>(reinterpret_cast<uintptr_t>(image_begin_ + copy_fields_offset))); - ArtField** copy_fields = reinterpret_cast<ArtField**>(image_->Begin() + copy_fields_offset); + copy_dex_cache->SetFieldPtrWithSize<false>(mirror::DexCache::ResolvedFieldsOffset(), + NativeLocationInImage(orig_fields), + /*pointer size*/8u); + ArtField** copy_fields = NativeCopyLocation(orig_fields); 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_); } } @@ -1572,7 +1588,7 @@ const uint8_t* ImageWriter::GetOatAddress(OatAddress type) const { // 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(); + gc::space::ImageSpace* image_space = Runtime::Current()->GetHeap()->GetBootImageSpace(); DCHECK(image_space != nullptr); const OatFile* oat_file = image_space->GetOatFile(); CHECK(oat_file != nullptr); @@ -1604,7 +1620,7 @@ const uint8_t* ImageWriter::GetQuickCode(ArtMethod* method, bool* quick_is_inter DCHECK(!method->IsResolutionMethod()) << PrettyMethod(method); DCHECK(!method->IsImtConflictMethod()) << PrettyMethod(method); DCHECK(!method->IsImtUnimplementedMethod()) << PrettyMethod(method); - DCHECK(!method->IsAbstract()) << PrettyMethod(method); + DCHECK(method->IsInvokable()) << PrettyMethod(method); DCHECK(!IsInBootImage(method)) << PrettyMethod(method); // Use original code if it exists. Otherwise, set the code pointer to the resolution @@ -1651,7 +1667,7 @@ const uint8_t* ImageWriter::GetQuickEntryPoint(ArtMethod* method) { // 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())) { + if (UNLIKELY(!method->IsInvokable())) { return GetOatAddress(kOatAddressQuickToInterpreterBridge); } else { bool quick_is_interpreted; @@ -1697,7 +1713,7 @@ void ImageWriter::CopyAndFixupMethod(ArtMethod* orig, ArtMethod* copy) { // 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(orig->IsAbstract())) { + if (UNLIKELY(!orig->IsInvokable())) { copy->SetEntryPointFromQuickCompiledCodePtrSize( GetOatAddress(kOatAddressQuickToInterpreterBridge), target_ptr_size_); } else { @@ -1727,8 +1743,10 @@ static OatHeader* GetOatHeaderFromElf(ElfFile* elf) { void ImageWriter::SetOatChecksumFromElfFile(File* elf_file) { std::string error_msg; - std::unique_ptr<ElfFile> elf(ElfFile::Open(elf_file, PROT_READ|PROT_WRITE, - MAP_SHARED, &error_msg)); + std::unique_ptr<ElfFile> elf(ElfFile::Open(elf_file, + PROT_READ | PROT_WRITE, + MAP_SHARED, + &error_msg)); if (elf.get() == nullptr) { LOG(FATAL) << "Unable open oat file: " << error_msg; return; @@ -1771,10 +1789,11 @@ uint32_t ImageWriter::BinSlot::GetIndex() const { uint8_t* ImageWriter::GetOatFileBegin() const { DCHECK_GT(intern_table_bytes_, 0u); - size_t native_sections_size = - bin_slot_sizes_[kBinArtField] + bin_slot_sizes_[kBinArtMethodDirty] + - bin_slot_sizes_[kBinArtMethodClean] + bin_slot_sizes_[kBinDexCacheArray] + - intern_table_bytes_; + size_t native_sections_size = bin_slot_sizes_[kBinArtField] + + bin_slot_sizes_[kBinArtMethodDirty] + + bin_slot_sizes_[kBinArtMethodClean] + + bin_slot_sizes_[kBinDexCacheArray] + + intern_table_bytes_; return image_begin_ + RoundUp(image_end_ + native_sections_size, kPageSize); } |