summaryrefslogtreecommitdiff
path: root/compiler/image_writer.cc
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/image_writer.cc')
-rw-r--r--compiler/image_writer.cc217
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 = &sections[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);
}