diff options
| -rw-r--r-- | compiler/image_writer.cc | 112 | ||||
| -rw-r--r-- | compiler/image_writer.h | 6 | ||||
| -rw-r--r-- | patchoat/patchoat.cc | 78 | ||||
| -rw-r--r-- | patchoat/patchoat.h | 3 | ||||
| -rw-r--r-- | runtime/mirror/array-inl.h | 13 | ||||
| -rw-r--r-- | runtime/mirror/array.h | 6 | ||||
| -rw-r--r-- | runtime/mirror/class-inl.h | 51 | ||||
| -rw-r--r-- | runtime/mirror/class.h | 7 | ||||
| -rw-r--r-- | runtime/mirror/dex_cache-inl.h | 26 | ||||
| -rw-r--r-- | runtime/mirror/dex_cache.h | 8 |
10 files changed, 198 insertions, 112 deletions
diff --git a/compiler/image_writer.cc b/compiler/image_writer.cc index 3777015858..3d9e7e7cda 100644 --- a/compiler/image_writer.cc +++ b/compiler/image_writer.cc @@ -1441,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); } @@ -1528,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 @@ -1536,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_); } } diff --git a/compiler/image_writer.h b/compiler/image_writer.h index a0a785e21c..22cb91a56d 100644 --- a/compiler/image_writer.h +++ b/compiler/image_writer.h @@ -347,9 +347,14 @@ class ImageWriter FINAL { uintptr_t NativeOffsetInImage(void* obj); + // Location of where the object will be when the image is loaded at runtime. template <typename T> T* NativeLocationInImage(T* obj); + // Location of where the temporary copy of the object currently is. + template <typename T> + T* NativeCopyLocation(T* obj); + // Return true of obj is inside of the boot image space. This may only return true if we are // compiling an app image. bool IsInBootImage(const void* obj) const; @@ -446,6 +451,7 @@ class ImageWriter FINAL { friend class FixupClassVisitor; friend class FixupRootVisitor; friend class FixupVisitor; + friend class NativeLocationVisitor; friend class NonImageClassesVisitor; DISALLOW_COPY_AND_ASSIGN(ImageWriter); }; diff --git a/patchoat/patchoat.cc b/patchoat/patchoat.cc index c587f68234..3d9f7dc2d5 100644 --- a/patchoat/patchoat.cc +++ b/patchoat/patchoat.cc @@ -526,13 +526,26 @@ void PatchOat::PatchInternedStrings(const ImageHeader* image_header) { temp_table.VisitRoots(&visitor, kVisitRootFlagAllRoots); } +class RelocatedPointerVisitor { + public: + explicit RelocatedPointerVisitor(PatchOat* patch_oat) : patch_oat_(patch_oat) {} + + template <typename T> + T* operator()(T* ptr) const { + return patch_oat_->RelocatedAddressOfPointer(ptr); + } + + private: + PatchOat* const patch_oat_; +}; + void PatchOat::PatchDexFileArrays(mirror::ObjectArray<mirror::Object>* img_roots) { auto* dex_caches = down_cast<mirror::ObjectArray<mirror::DexCache>*>( img_roots->Get(ImageHeader::kDexCaches)); + const size_t pointer_size = InstructionSetPointerSize(isa_); for (size_t i = 0, count = dex_caches->GetLength(); i < count; ++i) { auto* orig_dex_cache = dex_caches->GetWithoutChecks(i); auto* copy_dex_cache = RelocatedCopyOf(orig_dex_cache); - const size_t pointer_size = InstructionSetPointerSize(isa_); // Though the DexCache array fields are usually treated as native pointers, we set the full // 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. @@ -543,10 +556,7 @@ void PatchOat::PatchDexFileArrays(mirror::ObjectArray<mirror::Object>* img_roots mirror::DexCache::StringsOffset(), static_cast<int64_t>(reinterpret_cast<uintptr_t>(relocated_strings))); if (orig_strings != nullptr) { - GcRoot<mirror::String>* copy_strings = RelocatedCopyOf(orig_strings); - for (size_t j = 0, num = orig_dex_cache->NumStrings(); j != num; ++j) { - copy_strings[j] = GcRoot<mirror::String>(RelocatedAddressOfPointer(orig_strings[j].Read())); - } + orig_dex_cache->FixupStrings(RelocatedCopyOf(orig_strings), RelocatedPointerVisitor(this)); } GcRoot<mirror::Class>* orig_types = orig_dex_cache->GetResolvedTypes(); GcRoot<mirror::Class>* relocated_types = RelocatedAddressOfPointer(orig_types); @@ -554,10 +564,8 @@ void PatchOat::PatchDexFileArrays(mirror::ObjectArray<mirror::Object>* img_roots mirror::DexCache::ResolvedTypesOffset(), static_cast<int64_t>(reinterpret_cast<uintptr_t>(relocated_types))); if (orig_types != nullptr) { - GcRoot<mirror::Class>* copy_types = RelocatedCopyOf(orig_types); - for (size_t j = 0, num = orig_dex_cache->NumResolvedTypes(); j != num; ++j) { - copy_types[j] = GcRoot<mirror::Class>(RelocatedAddressOfPointer(orig_types[j].Read())); - } + orig_dex_cache->FixupResolvedTypes(RelocatedCopyOf(orig_types), + RelocatedPointerVisitor(this)); } ArtMethod** orig_methods = orig_dex_cache->GetResolvedMethods(); ArtMethod** relocated_methods = RelocatedAddressOfPointer(orig_methods); @@ -588,25 +596,6 @@ void PatchOat::PatchDexFileArrays(mirror::ObjectArray<mirror::Object>* img_roots } } -void PatchOat::FixupNativePointerArray(mirror::PointerArray* object) { - if (object->IsIntArray()) { - mirror::IntArray* arr = object->AsIntArray(); - mirror::IntArray* copy_arr = down_cast<mirror::IntArray*>(RelocatedCopyOf(arr)); - for (size_t j = 0, count2 = arr->GetLength(); j < count2; ++j) { - copy_arr->SetWithoutChecks<false>( - j, RelocatedAddressOfIntPointer(arr->GetWithoutChecks(j))); - } - } else { - CHECK(object->IsLongArray()); - mirror::LongArray* arr = object->AsLongArray(); - mirror::LongArray* copy_arr = down_cast<mirror::LongArray*>(RelocatedCopyOf(arr)); - for (size_t j = 0, count2 = arr->GetLength(); j < count2; ++j) { - copy_arr->SetWithoutChecks<false>( - j, RelocatedAddressOfIntPointer(arr->GetWithoutChecks(j))); - } - } -} - bool PatchOat::PatchImage() { ImageHeader* image_header = reinterpret_cast<ImageHeader*>(image_->Begin()); CHECK_GT(image_->Size(), sizeof(ImageHeader)); @@ -674,17 +663,14 @@ void PatchOat::VisitObject(mirror::Object* object) { PatchOat::PatchVisitor visitor(this, copy); object->VisitReferences<kVerifyNone>(visitor, visitor); if (object->IsClass<kVerifyNone>()) { - auto* klass = object->AsClass(); - auto* copy_klass = down_cast<mirror::Class*>(copy); - copy_klass->SetDexCacheStrings(RelocatedAddressOfPointer(klass->GetDexCacheStrings())); - copy_klass->SetSFieldsPtrUnchecked(RelocatedAddressOfPointer(klass->GetSFieldsPtr())); - copy_klass->SetIFieldsPtrUnchecked(RelocatedAddressOfPointer(klass->GetIFieldsPtr())); - copy_klass->SetDirectMethodsPtrUnchecked( - RelocatedAddressOfPointer(klass->GetDirectMethodsPtr())); - copy_klass->SetVirtualMethodsPtr(RelocatedAddressOfPointer(klass->GetVirtualMethodsPtr())); + const size_t pointer_size = InstructionSetPointerSize(isa_); + mirror::Class* klass = object->AsClass(); + mirror::Class* copy_klass = down_cast<mirror::Class*>(copy); + RelocatedPointerVisitor native_visitor(this); + klass->FixupNativePointers(copy_klass, pointer_size, native_visitor); auto* vtable = klass->GetVTable(); if (vtable != nullptr) { - FixupNativePointerArray(vtable); + vtable->Fixup(RelocatedCopyOf(vtable), pointer_size, native_visitor); } auto* iftable = klass->GetIfTable(); if (iftable != nullptr) { @@ -692,24 +678,12 @@ void PatchOat::VisitObject(mirror::Object* object) { if (iftable->GetMethodArrayCount(i) > 0) { auto* method_array = iftable->GetMethodArray(i); CHECK(method_array != nullptr); - FixupNativePointerArray(method_array); + method_array->Fixup(RelocatedCopyOf(method_array), pointer_size, native_visitor); } } } - if (klass->ShouldHaveEmbeddedImtAndVTable()) { - const size_t pointer_size = InstructionSetPointerSize(isa_); - for (int32_t i = 0; i < klass->GetEmbeddedVTableLength(); ++i) { - copy_klass->SetEmbeddedVTableEntryUnchecked(i, RelocatedAddressOfPointer( - klass->GetEmbeddedVTableEntry(i, pointer_size)), pointer_size); - } - for (size_t i = 0; i < mirror::Class::kImtSize; ++i) { - copy_klass->SetEmbeddedImTableEntry(i, RelocatedAddressOfPointer( - klass->GetEmbeddedImTableEntry(i, pointer_size)), pointer_size); - } - } - } - if (object->GetClass() == mirror::Method::StaticClass() || - object->GetClass() == mirror::Constructor::StaticClass()) { + } else if (object->GetClass() == mirror::Method::StaticClass() || + object->GetClass() == mirror::Constructor::StaticClass()) { // Need to go update the ArtMethod. auto* dest = down_cast<mirror::AbstractMethod*>(copy); auto* src = down_cast<mirror::AbstractMethod*>(object); diff --git a/patchoat/patchoat.h b/patchoat/patchoat.h index 87ecc618eb..09150144ec 100644 --- a/patchoat/patchoat.h +++ b/patchoat/patchoat.h @@ -102,8 +102,6 @@ class PatchOat { SHARED_REQUIRES(Locks::mutator_lock_); void FixupMethod(ArtMethod* object, ArtMethod* copy) SHARED_REQUIRES(Locks::mutator_lock_); - void FixupNativePointerArray(mirror::PointerArray* object) - SHARED_REQUIRES(Locks::mutator_lock_); bool InHeap(mirror::Object*); // Patches oat in place, modifying the oat_file given to the constructor. @@ -200,6 +198,7 @@ class PatchOat { TimingLogger* timings_; friend class FixupRootVisitor; + friend class RelocatedPointerVisitor; friend class PatchOatArtFieldVisitor; friend class PatchOatArtMethodVisitor; DISALLOW_IMPLICIT_CONSTRUCTORS(PatchOat); diff --git a/runtime/mirror/array-inl.h b/runtime/mirror/array-inl.h index ec7d758ebb..b6f424b3a4 100644 --- a/runtime/mirror/array-inl.h +++ b/runtime/mirror/array-inl.h @@ -394,6 +394,19 @@ inline void PointerArray::SetElementPtrSize(uint32_t idx, T element, size_t ptr_ } } +template <typename Visitor> +inline void PointerArray::Fixup(mirror::PointerArray* dest, + size_t pointer_size, + const Visitor& visitor) { + for (size_t i = 0, count = GetLength(); i < count; ++i) { + void* ptr = GetElementPtrSize<void*>(i, pointer_size); + void* new_ptr = visitor(ptr); + if (ptr != new_ptr) { + dest->SetElementPtrSize<false, true>(i, new_ptr, pointer_size); + } + } +} + } // namespace mirror } // namespace art diff --git a/runtime/mirror/array.h b/runtime/mirror/array.h index 7458424bac..50d77ebdb8 100644 --- a/runtime/mirror/array.h +++ b/runtime/mirror/array.h @@ -190,6 +190,12 @@ class PointerArray : public Array { template<bool kTransactionActive = false, bool kUnchecked = false, typename T> void SetElementPtrSize(uint32_t idx, T element, size_t ptr_size) SHARED_REQUIRES(Locks::mutator_lock_); + + // Fixup the pointers in the dest arrays by passing our pointers through the visitor. Only copies + // to dest if visitor(source_ptr) != source_ptr. + template <typename Visitor> + void Fixup(mirror::PointerArray* dest, size_t pointer_size, const Visitor& visitor) + SHARED_REQUIRES(Locks::mutator_lock_); }; } // namespace mirror diff --git a/runtime/mirror/class-inl.h b/runtime/mirror/class-inl.h index 174de0e2f6..9e416dc888 100644 --- a/runtime/mirror/class-inl.h +++ b/runtime/mirror/class-inl.h @@ -937,6 +937,57 @@ inline uint32_t Class::NumStaticFields() { return arr != nullptr ? arr->size() : 0u; } +template <typename Visitor> +inline void Class::FixupNativePointers(mirror::Class* dest, + size_t pointer_size, + const Visitor& visitor) { + // Update the field arrays. + LengthPrefixedArray<ArtField>* const sfields = GetSFieldsPtr(); + LengthPrefixedArray<ArtField>* const new_sfields = visitor(sfields); + if (sfields != new_sfields) { + dest->SetSFieldsPtrUnchecked(new_sfields); + } + LengthPrefixedArray<ArtField>* const ifields = GetIFieldsPtr(); + LengthPrefixedArray<ArtField>* const new_ifields = visitor(ifields); + if (ifields != new_ifields) { + dest->SetIFieldsPtrUnchecked(new_ifields); + } + // Update direct and virtual method arrays. + LengthPrefixedArray<ArtMethod>* direct_methods = GetDirectMethodsPtr(); + LengthPrefixedArray<ArtMethod>* new_direct_methods = visitor(direct_methods); + if (direct_methods != new_direct_methods) { + dest->SetDirectMethodsPtrUnchecked(new_direct_methods); + } + LengthPrefixedArray<ArtMethod>* virtual_methods = GetVirtualMethodsPtr(); + LengthPrefixedArray<ArtMethod>* new_virtual_methods = visitor(virtual_methods); + if (virtual_methods != new_virtual_methods) { + dest->SetVirtualMethodsPtr(new_virtual_methods); + } + // Update dex cache strings. + GcRoot<mirror::String>* strings = GetDexCacheStrings(); + GcRoot<mirror::String>* new_strings = visitor(strings); + if (strings != new_strings) { + dest->SetDexCacheStrings(new_strings); + } + // Fix up embedded tables. + if (!IsTemp() && ShouldHaveEmbeddedImtAndVTable()) { + for (int32_t i = 0, count = GetEmbeddedVTableLength(); i < count; ++i) { + ArtMethod* method = GetEmbeddedVTableEntry(i, pointer_size); + ArtMethod* new_method = visitor(method); + if (method != new_method) { + dest->SetEmbeddedVTableEntryUnchecked(i, new_method, pointer_size); + } + } + for (size_t i = 0; i < mirror::Class::kImtSize; ++i) { + ArtMethod* method = GetEmbeddedImTableEntry(i, pointer_size); + ArtMethod* new_method = visitor(method); + if (method != new_method) { + dest->SetEmbeddedImTableEntry(i, new_method, pointer_size); + } + } + } +} + } // namespace mirror } // namespace art diff --git a/runtime/mirror/class.h b/runtime/mirror/class.h index 80e136c2cc..19a84f2e7f 100644 --- a/runtime/mirror/class.h +++ b/runtime/mirror/class.h @@ -1157,6 +1157,13 @@ class MANAGED Class FINAL : public Object { ALWAYS_INLINE LengthPrefixedArray<ArtMethod>* GetVirtualMethodsPtrUnchecked() SHARED_REQUIRES(Locks::mutator_lock_); + // Fix up all of the native pointers in the class by running them through the visitor. Only sets + // the corresponding entry in dest if visitor(obj) != obj to prevent dirty memory. Dest should be + // initialized to a copy of *this to prevent issues. + template <typename Visitor> + void FixupNativePointers(mirror::Class* dest, size_t pointer_size, const Visitor& visitor) + SHARED_REQUIRES(Locks::mutator_lock_); + private: void SetVerifyError(Object* klass) SHARED_REQUIRES(Locks::mutator_lock_); diff --git a/runtime/mirror/dex_cache-inl.h b/runtime/mirror/dex_cache-inl.h index f8ccfb1b39..975af61ca8 100644 --- a/runtime/mirror/dex_cache-inl.h +++ b/runtime/mirror/dex_cache-inl.h @@ -137,6 +137,32 @@ inline void DexCache::VisitReferences(mirror::Class* klass, const Visitor& visit } } +template <typename Visitor> +inline void DexCache::FixupStrings(GcRoot<mirror::String>* dest, const Visitor& visitor) { + GcRoot<mirror::String>* src = GetStrings(); + for (size_t i = 0, count = NumStrings(); i < count; ++i) { + // TODO: Probably don't need read barrier for most callers. + mirror::String* source = src[i].Read(); + mirror::String* new_source = visitor(source); + if (source != new_source) { + dest[i] = GcRoot<mirror::String>(new_source); + } + } +} + +template <typename Visitor> +inline void DexCache::FixupResolvedTypes(GcRoot<mirror::Class>* dest, const Visitor& visitor) { + GcRoot<mirror::Class>* src = GetResolvedTypes(); + for (size_t i = 0, count = NumResolvedTypes(); i < count; ++i) { + // TODO: Probably don't need read barrier for most callers. + mirror::Class* source = src[i].Read(); + mirror::Class* new_source = visitor(source); + if (source != new_source) { + dest[i] = GcRoot<mirror::Class>(new_source); + } + } +} + } // namespace mirror } // namespace art diff --git a/runtime/mirror/dex_cache.h b/runtime/mirror/dex_cache.h index 3144553657..32eb59540d 100644 --- a/runtime/mirror/dex_cache.h +++ b/runtime/mirror/dex_cache.h @@ -61,6 +61,14 @@ class MANAGED DexCache FINAL : public Object { void Fixup(ArtMethod* trampoline, size_t pointer_size) SHARED_REQUIRES(Locks::mutator_lock_); + template <typename Visitor> + void FixupStrings(GcRoot<mirror::String>* dest, const Visitor& visitor) + SHARED_REQUIRES(Locks::mutator_lock_); + + template <typename Visitor> + void FixupResolvedTypes(GcRoot<mirror::Class>* dest, const Visitor& visitor) + SHARED_REQUIRES(Locks::mutator_lock_); + String* GetLocation() SHARED_REQUIRES(Locks::mutator_lock_) { return GetFieldObject<String>(OFFSET_OF_OBJECT_MEMBER(DexCache, location_)); } |