OSDN Git Service

Fix handling of dex cache arrays for method types.
authorNarayan Kamath <narayan@google.com>
Fri, 14 Oct 2016 17:49:12 +0000 (18:49 +0100)
committerNarayan Kamath <narayan@google.com>
Mon, 17 Oct 2016 15:29:32 +0000 (16:29 +0100)
- Add support for relocating method type dex cache arrays.
- Add missing call to MethodTypeDexCachePair::Initialize in the
  class_linker.
- Fix alignment calculation for method_types in
  DexCacheArraysLayout.
- Removed unused MethodTypeOffset(uint32_t) method.

Fixes tests with --pic.

Test: make test-art-host
Bug: 30550796

Change-Id: I2bba7228762b9e9834e7659fe62090be78afdfa8

compiler/image_writer.cc
patchoat/patchoat.cc
runtime/class_linker.cc
runtime/gc/space/image_space.cc
runtime/mirror/dex_cache-inl.h
runtime/mirror/dex_cache.h
runtime/utils/dex_cache_arrays_layout-inl.h
runtime/utils/dex_cache_arrays_layout.h

index 13c73dc..7560011 100644 (file)
@@ -461,6 +461,12 @@ void ImageWriter::PrepareDexCacheArraySlots() {
                                dex_cache);
     DCHECK_EQ(dex_file->NumStringIds() != 0u, dex_cache->GetStrings() != nullptr);
     AddDexCacheArrayRelocation(dex_cache->GetStrings(), start + layout.StringsOffset(), dex_cache);
+
+    if (dex_cache->GetResolvedMethodTypes() != nullptr) {
+      AddDexCacheArrayRelocation(dex_cache->GetResolvedMethodTypes(),
+                                 start + layout.MethodTypesOffset(),
+                                 dex_cache);
+    }
   }
 }
 
@@ -2164,6 +2170,14 @@ void ImageWriter::FixupDexCache(mirror::DexCache* orig_dex_cache,
       mirror::DexCache::SetElementPtrSize(copy_fields, i, copy, target_ptr_size_);
     }
   }
+  mirror::MethodTypeDexCacheType* orig_method_types = orig_dex_cache->GetResolvedMethodTypes();
+  if (orig_method_types != nullptr) {
+    copy_dex_cache->SetFieldPtrWithSize<false>(mirror::DexCache::ResolvedMethodTypesOffset(),
+                                               NativeLocationInImage(orig_method_types),
+                                               PointerSize::k64);
+    orig_dex_cache->FixupResolvedMethodTypes(NativeCopyLocation(orig_method_types, orig_dex_cache),
+                                             ImageAddressVisitor(this));
+  }
 
   // Remove the DexFile pointers. They will be fixed up when the runtime loads the oat file. Leaving
   // compiler pointers in here will make the output non-deterministic.
index f3eb663..b5c252d 100644 (file)
@@ -677,6 +677,16 @@ void PatchOat::PatchDexFileArrays(mirror::ObjectArray<mirror::Object>* img_roots
         mirror::DexCache::SetElementPtrSize(copy_fields, j, copy, pointer_size);
       }
     }
+    mirror::MethodTypeDexCacheType* orig_method_types = orig_dex_cache->GetResolvedMethodTypes();
+    mirror::MethodTypeDexCacheType* relocated_method_types =
+        RelocatedAddressOfPointer(orig_method_types);
+    copy_dex_cache->SetField64<false>(
+        mirror::DexCache::ResolvedMethodTypesOffset(),
+        static_cast<int64_t>(reinterpret_cast<uintptr_t>(relocated_method_types)));
+    if (orig_method_types != nullptr) {
+      orig_dex_cache->FixupResolvedMethodTypes(RelocatedCopyOf(orig_method_types),
+                                               RelocatedPointerVisitor(this));
+    }
   }
 }
 
index eb2316b..d7d6f2b 100644 (file)
@@ -1377,6 +1377,7 @@ bool ClassLinker::UpdateAppImageClassLoadersAndDexCaches(
                 std::memory_order_relaxed);
           }
 
+          mirror::MethodTypeDexCachePair::Initialize(method_types);
           dex_cache->SetResolvedMethodTypes(method_types);
         }
       }
index a40e408..bc63b38 100644 (file)
@@ -1254,6 +1254,16 @@ class ImageSpaceLoader {
             }
           }
         }
+
+        mirror::MethodTypeDexCacheType* method_types = dex_cache->GetResolvedMethodTypes();
+        if (method_types != nullptr) {
+          mirror::MethodTypeDexCacheType* new_method_types =
+              fixup_adapter.ForwardObject(method_types);
+          if (method_types != new_method_types) {
+            dex_cache->SetResolvedMethodTypes(new_method_types);
+          }
+          dex_cache->FixupResolvedMethodTypes<kWithoutReadBarrier>(new_method_types, fixup_adapter);
+        }
       }
     }
     {
index b388f65..cf45748 100644 (file)
@@ -207,6 +207,19 @@ inline void DexCache::FixupResolvedTypes(GcRoot<mirror::Class>* dest, const Visi
   }
 }
 
+template <ReadBarrierOption kReadBarrierOption, typename Visitor>
+inline void DexCache::FixupResolvedMethodTypes(mirror::MethodTypeDexCacheType* dest,
+                                               const Visitor& visitor) {
+  mirror::MethodTypeDexCacheType* src = GetResolvedMethodTypes();
+  for (size_t i = 0, count = NumResolvedMethodTypes(); i < count; ++i) {
+    MethodTypeDexCachePair source = src[i].load(std::memory_order_relaxed);
+    mirror::MethodType* ptr = source.object.Read<kReadBarrierOption>();
+    mirror::MethodType* new_source = visitor(ptr);
+    source.object = GcRoot<MethodType>(new_source);
+    dest[i].store(source, std::memory_order_relaxed);
+  }
+}
+
 }  // namespace mirror
 }  // namespace art
 
index 2fcabb5..7538c20 100644 (file)
@@ -160,6 +160,10 @@ class MANAGED DexCache FINAL : public Object {
   void FixupResolvedTypes(GcRoot<mirror::Class>* dest, const Visitor& visitor)
       REQUIRES_SHARED(Locks::mutator_lock_);
 
+  template <ReadBarrierOption kReadBarrierOption = kWithReadBarrier, typename Visitor>
+  void FixupResolvedMethodTypes(MethodTypeDexCacheType* dest, const Visitor& visitor)
+      REQUIRES_SHARED(Locks::mutator_lock_);
+
   String* GetLocation() REQUIRES_SHARED(Locks::mutator_lock_) {
     return GetFieldObject<String>(OFFSET_OF_OBJECT_MEMBER(DexCache, location_));
   }
@@ -282,7 +286,7 @@ class MANAGED DexCache FINAL : public Object {
 
   MethodTypeDexCacheType* GetResolvedMethodTypes()
       ALWAYS_INLINE REQUIRES_SHARED(Locks::mutator_lock_) {
-    return GetFieldPtr<MethodTypeDexCacheType*>(ResolvedMethodTypesOffset());
+    return GetFieldPtr64<MethodTypeDexCacheType*>(ResolvedMethodTypesOffset());
   }
 
   void SetResolvedMethodTypes(MethodTypeDexCacheType* resolved_method_types)
index 5ccd446..5ca7684 100644 (file)
@@ -39,7 +39,7 @@ inline DexCacheArraysLayout::DexCacheArraysLayout(PointerSize pointer_size,
       fields_offset_(
           RoundUp(strings_offset_ + StringsSize(header.string_ids_size_), FieldsAlignment())),
       method_types_offset_(
-          RoundUp(fields_offset_ + FieldsSize(header.field_ids_size_), Alignment())),
+          RoundUp(fields_offset_ + FieldsSize(header.field_ids_size_), MethodTypesAlignment())),
       size_(
           RoundUp(method_types_offset_ + MethodTypesSize(header.proto_ids_size_), Alignment())) {
 }
@@ -51,7 +51,11 @@ inline DexCacheArraysLayout::DexCacheArraysLayout(PointerSize pointer_size, cons
 inline constexpr size_t DexCacheArraysLayout::Alignment() {
   // GcRoot<> alignment is 4, i.e. lower than or equal to the pointer alignment.
   static_assert(alignof(GcRoot<mirror::Class>) == 4, "Expecting alignof(GcRoot<>) == 4");
-  static_assert(alignof(mirror::StringDexCacheType) == 8, "Expecting alignof(StringDexCacheType) == 8");
+  static_assert(alignof(mirror::StringDexCacheType) == 8,
+                "Expecting alignof(StringDexCacheType) == 8");
+  static_assert(alignof(mirror::MethodTypeDexCacheType) == 8,
+                "Expecting alignof(MethodTypeDexCacheType) == 8");
+  // This is the same as alignof(MethodTypeDexCacheType).
   return alignof(mirror::StringDexCacheType);
 }
 
@@ -120,12 +124,6 @@ inline size_t DexCacheArraysLayout::FieldsAlignment() const {
   return static_cast<size_t>(pointer_size_);
 }
 
-inline size_t DexCacheArraysLayout::MethodTypeOffset(uint32_t proto_idx) const {
-  return strings_offset_
-      + ElementOffset(PointerSize::k64,
-                      proto_idx % mirror::DexCache::kDexCacheMethodTypeCacheSize);
-}
-
 inline size_t DexCacheArraysLayout::MethodTypesSize(size_t num_elements) const {
   size_t cache_size = mirror::DexCache::kDexCacheMethodTypeCacheSize;
   if (num_elements < cache_size) {
index e222b46..ae3bfab 100644 (file)
@@ -99,8 +99,6 @@ class DexCacheArraysLayout {
     return method_types_offset_;
   }
 
-  size_t MethodTypeOffset(uint32_t method_type_idx) const;
-
   size_t MethodTypesSize(size_t num_elements) const;
 
   size_t MethodTypesAlignment() const;