diff options
author | Mathieu Chartier <mathieuc@google.com> | 2015-03-27 14:35:38 -0700 |
---|---|---|
committer | Mathieu Chartier <mathieuc@google.com> | 2015-04-10 12:57:27 -0700 |
commit | c785344b87221f5e4e6473e5b762e4e61fe65dcf (patch) | |
tree | cd32ad2c2604596a18926f04d4c313dab255ecfd /patchoat | |
parent | a29d93b380c9aeb8270e281aefbdd0c77a430d43 (diff) | |
download | art-c785344b87221f5e4e6473e5b762e4e61fe65dcf.zip art-c785344b87221f5e4e6473e5b762e4e61fe65dcf.tar.gz art-c785344b87221f5e4e6473e5b762e4e61fe65dcf.tar.bz2 |
Move ArtField to native
Add linear alloc. Moved ArtField to be native object. Changed image
writer to put ArtFields after the mirror section.
Savings:
2MB on low ram devices
4MB on normal devices
Total PSS measurements before (normal N5, 95s after shell start):
Image size: 7729152 bytes
23112 kB: .NonMoving
23212 kB: .NonMoving
22868 kB: .NonMoving
23072 kB: .NonMoving
22836 kB: .NonMoving
19618 kB: .Zygote
19850 kB: .Zygote
19623 kB: .Zygote
19924 kB: .Zygote
19612 kB: .Zygote
Avg: 42745.4 kB
After:
Image size: 7462912 bytes
17440 kB: .NonMoving
16776 kB: .NonMoving
16804 kB: .NonMoving
17812 kB: .NonMoving
16820 kB: .NonMoving
18788 kB: .Zygote
18856 kB: .Zygote
19064 kB: .Zygote
18841 kB: .Zygote
18629 kB: .Zygote
3499 kB: .LinearAlloc
3408 kB: .LinearAlloc
3424 kB: .LinearAlloc
3600 kB: .LinearAlloc
3436 kB: .LinearAlloc
Avg: 39439.4 kB
No reflection performance changes.
Bug: 19264997
Bug: 17643507
Change-Id: I10c73a37913332080aeb978c7c94713bdfe4fe1c
Diffstat (limited to 'patchoat')
-rw-r--r-- | patchoat/patchoat.cc | 87 | ||||
-rw-r--r-- | patchoat/patchoat.h | 23 |
2 files changed, 83 insertions, 27 deletions
diff --git a/patchoat/patchoat.cc b/patchoat/patchoat.cc index 9584064..74c9c38 100644 --- a/patchoat/patchoat.cc +++ b/patchoat/patchoat.cc @@ -24,6 +24,7 @@ #include <string> #include <vector> +#include "art_field-inl.h" #include "base/dumpable.h" #include "base/scoped_flock.h" #include "base/stringpiece.h" @@ -34,7 +35,6 @@ #include "elf_file_impl.h" #include "gc/space/image_space.h" #include "image.h" -#include "mirror/art_field-inl.h" #include "mirror/art_method-inl.h" #include "mirror/object-inl.h" #include "mirror/reference.h" @@ -415,13 +415,64 @@ bool PatchOat::ReplaceOatFileWithSymlink(const std::string& input_oat_filename, return true; } +void PatchOat::PatchArtFields(const ImageHeader* image_header) { + const size_t art_field_size = image_header->GetArtFieldsSize(); + const size_t art_field_offset = image_header->GetArtFieldsOffset(); + for (size_t pos = 0; pos < art_field_size; pos += sizeof(ArtField)) { + auto* field = reinterpret_cast<ArtField*>(heap_->Begin() + art_field_offset + pos); + auto* dest_field = RelocatedCopyOf(field); + dest_field->SetDeclaringClass(RelocatedAddressOfPointer(field->GetDeclaringClass())); + } +} + +void PatchOat::PatchDexFileArrays(mirror::ObjectArray<mirror::Object>* img_roots) { + auto* dex_caches = down_cast<mirror::ObjectArray<mirror::DexCache>*>( + img_roots->Get(ImageHeader::kDexCaches)); + for (size_t i = 0, count = dex_caches->GetLength(); i < count; ++i) { + auto* dex_cache = dex_caches->GetWithoutChecks(i); + auto* fields = dex_cache->GetResolvedFields(); + if (fields == nullptr) { + continue; + } + CHECK(!fields->IsObjectArray()); + CHECK(fields->IsArrayInstance()); + auto* component_type = fields->GetClass()->GetComponentType(); + if (component_type->IsPrimitiveInt()) { + mirror::IntArray* arr = fields->AsIntArray(); + mirror::IntArray* copy_arr = down_cast<mirror::IntArray*>(RelocatedCopyOf(arr)); + for (size_t j = 0, count2 = arr->GetLength(); j < count2; ++j) { + auto f = arr->GetWithoutChecks(j); + if (f != 0) { + copy_arr->SetWithoutChecks<false>(j, f + delta_); + } + } + } else { + CHECK(component_type->IsPrimitiveLong()); + mirror::LongArray* arr = fields->AsLongArray(); + mirror::LongArray* copy_arr = down_cast<mirror::LongArray*>(RelocatedCopyOf(arr)); + for (size_t j = 0, count2 = arr->GetLength(); j < count2; ++j) { + auto f = arr->GetWithoutChecks(j); + if (f != 0) { + copy_arr->SetWithoutChecks<false>(j, f + delta_); + } + } + } + } +} + bool PatchOat::PatchImage() { ImageHeader* image_header = reinterpret_cast<ImageHeader*>(image_->Begin()); CHECK_GT(image_->Size(), sizeof(ImageHeader)); // These are the roots from the original file. - mirror::Object* img_roots = image_header->GetImageRoots(); + auto* img_roots = image_header->GetImageRoots(); image_header->RelocateImage(delta_); + // Patch and update ArtFields. + PatchArtFields(image_header); + + // Patch dex file int/long arrays which point to ArtFields. + PatchDexFileArrays(img_roots); + VisitObject(img_roots); if (!image_header->IsValid()) { LOG(ERROR) << "reloction renders image header invalid"; @@ -448,7 +499,7 @@ void PatchOat::PatchVisitor::operator() (mirror::Object* obj, MemberOffset off, bool is_static_unused ATTRIBUTE_UNUSED) const { mirror::Object* referent = obj->GetFieldObject<mirror::Object, kVerifyNone>(off); DCHECK(patcher_->InHeap(referent)) << "Referent is not in the heap."; - mirror::Object* moved_object = patcher_->RelocatedAddressOf(referent); + mirror::Object* moved_object = patcher_->RelocatedAddressOfPointer(referent); copy_->SetFieldObjectWithoutWriteBarrier<false, true, kVerifyNone>(off, moved_object); } @@ -457,30 +508,10 @@ void PatchOat::PatchVisitor::operator() (mirror::Class* cls ATTRIBUTE_UNUSED, MemberOffset off = mirror::Reference::ReferentOffset(); mirror::Object* referent = ref->GetReferent(); DCHECK(patcher_->InHeap(referent)) << "Referent is not in the heap."; - mirror::Object* moved_object = patcher_->RelocatedAddressOf(referent); + mirror::Object* moved_object = patcher_->RelocatedAddressOfPointer(referent); copy_->SetFieldObjectWithoutWriteBarrier<false, true, kVerifyNone>(off, moved_object); } -mirror::Object* PatchOat::RelocatedCopyOf(mirror::Object* obj) { - if (obj == nullptr) { - return nullptr; - } - DCHECK_GT(reinterpret_cast<uintptr_t>(obj), reinterpret_cast<uintptr_t>(heap_->Begin())); - DCHECK_LT(reinterpret_cast<uintptr_t>(obj), reinterpret_cast<uintptr_t>(heap_->End())); - uintptr_t heap_off = - reinterpret_cast<uintptr_t>(obj) - reinterpret_cast<uintptr_t>(heap_->Begin()); - DCHECK_LT(heap_off, image_->Size()); - return reinterpret_cast<mirror::Object*>(image_->Begin() + heap_off); -} - -mirror::Object* PatchOat::RelocatedAddressOf(mirror::Object* obj) { - if (obj == nullptr) { - return nullptr; - } else { - return reinterpret_cast<mirror::Object*>(reinterpret_cast<uint8_t*>(obj) + delta_); - } -} - const OatHeader* PatchOat::GetOatHeader(const ElfFile* elf_file) { if (elf_file->Is64Bit()) { return GetOatHeader<ElfFileImpl64>(elf_file->GetImpl64()); @@ -507,7 +538,7 @@ void PatchOat::VisitObject(mirror::Object* object) { if (kUseBakerOrBrooksReadBarrier) { object->AssertReadBarrierPointer(); if (kUseBrooksReadBarrier) { - mirror::Object* moved_to = RelocatedAddressOf(object); + mirror::Object* moved_to = RelocatedAddressOfPointer(object); copy->SetReadBarrierPointer(moved_to); DCHECK_EQ(copy->GetReadBarrierPointer(), moved_to); } @@ -516,6 +547,12 @@ void PatchOat::VisitObject(mirror::Object* object) { object->VisitReferences<true, kVerifyNone>(visitor, visitor); if (object->IsArtMethod<kVerifyNone>()) { FixupMethod(down_cast<mirror::ArtMethod*>(object), down_cast<mirror::ArtMethod*>(copy)); + } else if (object->IsClass<kVerifyNone>()) { + mirror::Class* klass = down_cast<mirror::Class*>(object); + down_cast<mirror::Class*>(copy)->SetSFieldsUnchecked( + RelocatedAddressOfPointer(klass->GetSFields())); + down_cast<mirror::Class*>(copy)->SetIFieldsUnchecked( + RelocatedAddressOfPointer(klass->GetIFields())); } } diff --git a/patchoat/patchoat.h b/patchoat/patchoat.h index 578df3a..418650a 100644 --- a/patchoat/patchoat.h +++ b/patchoat/patchoat.h @@ -117,12 +117,31 @@ class PatchOat { bool PatchOatHeader(ElfFileImpl* oat_file); bool PatchImage() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + void PatchArtFields(const ImageHeader* image_header) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + void PatchDexFileArrays(mirror::ObjectArray<mirror::Object>* img_roots) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); bool WriteElf(File* out); bool WriteImage(File* out); - mirror::Object* RelocatedCopyOf(mirror::Object*); - mirror::Object* RelocatedAddressOf(mirror::Object* obj); + template <typename T> + T* RelocatedCopyOf(T* obj) { + if (obj == nullptr) { + return nullptr; + } + DCHECK_GT(reinterpret_cast<uintptr_t>(obj), reinterpret_cast<uintptr_t>(heap_->Begin())); + DCHECK_LT(reinterpret_cast<uintptr_t>(obj), reinterpret_cast<uintptr_t>(heap_->End())); + uintptr_t heap_off = + reinterpret_cast<uintptr_t>(obj) - reinterpret_cast<uintptr_t>(heap_->Begin()); + DCHECK_LT(heap_off, image_->Size()); + return reinterpret_cast<T*>(image_->Begin() + heap_off); + } + + template <typename T> + T* RelocatedAddressOfPointer(T* obj) { + return obj == nullptr ? nullptr : + reinterpret_cast<T*>(reinterpret_cast<uintptr_t>(obj) + delta_); + } // Look up the oat header from any elf file. static const OatHeader* GetOatHeader(const ElfFile* elf_file); |