summaryrefslogtreecommitdiffstats
path: root/patchoat
diff options
context:
space:
mode:
authorMathieu Chartier <mathieuc@google.com>2015-03-27 14:35:38 -0700
committerMathieu Chartier <mathieuc@google.com>2015-04-10 12:57:27 -0700
commitc785344b87221f5e4e6473e5b762e4e61fe65dcf (patch)
treecd32ad2c2604596a18926f04d4c313dab255ecfd /patchoat
parenta29d93b380c9aeb8270e281aefbdd0c77a430d43 (diff)
downloadart-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.cc87
-rw-r--r--patchoat/patchoat.h23
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);