ART: Remove ArtMethod::dex_cache_resolved_methods_.
Test: m test-art-host-gtest
Test: testrunner.py --host
Test: testrunner.py --target on Nexus 6P
Test: Repeat the above tests with ART_HEAP_POISONING=true
Test: Build aosp_mips64-eng
Change-Id: I9cd0b8aa5001542b0863cccfca4f9c1cd4d25396
diff --git a/compiler/image_writer.cc b/compiler/image_writer.cc
index 115e722..6ee9cc6 100644
--- a/compiler/image_writer.cc
+++ b/compiler/image_writer.cc
@@ -2593,10 +2593,6 @@
CopyReference(copy->GetDeclaringClassAddressWithoutBarrier(), orig->GetDeclaringClassUnchecked());
- mirror::MethodDexCacheType* orig_resolved_methods =
- orig->GetDexCacheResolvedMethods(target_ptr_size_);
- copy->SetDexCacheResolvedMethods(NativeLocationInImage(orig_resolved_methods), target_ptr_size_);
-
// OatWriter replaces the code_ with an offset value. Here we re-adjust to a pointer relative to
// oat_begin_
diff --git a/openjdkjvmti/ti_redefine.cc b/openjdkjvmti/ti_redefine.cc
index c679d73..1b4e910 100644
--- a/openjdkjvmti/ti_redefine.cc
+++ b/openjdkjvmti/ti_redefine.cc
@@ -1364,7 +1364,6 @@
}
void Redefiner::ClassRedefinition::UpdateMethods(art::ObjPtr<art::mirror::Class> mclass,
- art::ObjPtr<art::mirror::DexCache> new_dex_cache,
const art::DexFile::ClassDef& class_def) {
art::ClassLinker* linker = driver_->runtime_->GetClassLinker();
art::PointerSize image_pointer_size = linker->GetImagePointerSize();
@@ -1396,7 +1395,6 @@
method.SetDexMethodIndex(dex_method_idx);
linker->SetEntryPointsToInterpreter(&method);
method.SetCodeItemOffset(dex_file_->FindCodeItemOffset(class_def, dex_method_idx));
- method.SetDexCacheResolvedMethods(new_dex_cache->GetResolvedMethods(), image_pointer_size);
// Clear all the intrinsics related flags.
method.ClearAccessFlags(art::kAccIntrinsic | (~art::kAccFlagsNotUsedByIntrinsic));
// Notify the jit that this method is redefined.
@@ -1433,7 +1431,7 @@
art::ObjPtr<art::mirror::Object> original_dex_file) {
DCHECK_EQ(dex_file_->NumClassDefs(), 1u);
const art::DexFile::ClassDef& class_def = dex_file_->GetClassDef(0);
- UpdateMethods(mclass, new_dex_cache, class_def);
+ UpdateMethods(mclass, class_def);
UpdateFields(mclass);
// Update the class fields.
diff --git a/openjdkjvmti/ti_redefine.h b/openjdkjvmti/ti_redefine.h
index 984f922..528563b 100644
--- a/openjdkjvmti/ti_redefine.h
+++ b/openjdkjvmti/ti_redefine.h
@@ -184,7 +184,6 @@
REQUIRES(art::Locks::mutator_lock_);
void UpdateMethods(art::ObjPtr<art::mirror::Class> mclass,
- art::ObjPtr<art::mirror::DexCache> new_dex_cache,
const art::DexFile::ClassDef& class_def)
REQUIRES(art::Locks::mutator_lock_);
diff --git a/patchoat/patchoat.cc b/patchoat/patchoat.cc
index ed7623a..efa2969 100644
--- a/patchoat/patchoat.cc
+++ b/patchoat/patchoat.cc
@@ -686,8 +686,6 @@
// Just update the entry points if it looks like we should.
// TODO: sanity check all the pointers' values
copy->SetDeclaringClass(RelocatedAddressOfPointer(object->GetDeclaringClass()));
- copy->SetDexCacheResolvedMethods(
- RelocatedAddressOfPointer(object->GetDexCacheResolvedMethods(pointer_size)), pointer_size);
copy->SetEntryPointFromQuickCompiledCodePtrSize(RelocatedAddressOfPointer(
object->GetEntryPointFromQuickCompiledCodePtrSize(pointer_size)), pointer_size);
// No special handling for IMT conflict table since all pointers are moved by the same offset.
diff --git a/runtime/arch/arm/quick_entrypoints_arm.S b/runtime/arch/arm/quick_entrypoints_arm.S
index ea8d501..ab9ca84 100644
--- a/runtime/arch/arm/quick_entrypoints_arm.S
+++ b/runtime/arch/arm/quick_entrypoints_arm.S
@@ -1596,10 +1596,21 @@
.cfi_rel_offset r1, 0
.cfi_rel_offset r2, 4
ldr r4, [sp, #(2 * 4)] // Load referrer.
- ubfx r1, r12, #0, #METHOD_DEX_CACHE_HASH_BITS // Calculate DexCache method slot index.
- ldr r4, [r4, #ART_METHOD_DEX_CACHE_METHODS_OFFSET_32] // Load dex cache methods array
- add r4, r4, r1, lsl #(POINTER_SIZE_SHIFT + 1) // Load DexCache method slot address.
ldr r2, [r0, #ART_METHOD_JNI_OFFSET_32] // Load ImtConflictTable
+ // Load the declaring class (without read barrier) and access flags (for obsolete method check).
+ // The obsolete flag is set with suspended threads, so we do not need an acquire operation here.
+#if ART_METHOD_ACCESS_FLAGS_OFFSET != ART_METHOD_DECLARING_CLASS_OFFSET + 4
+#error "Expecting declaring class and access flags to be consecutive for LDRD."
+#endif
+ ldrd r0, r1, [r4, #ART_METHOD_DECLARING_CLASS_OFFSET]
+ // If the method is obsolete, just go through the dex cache miss slow path.
+ lsrs r1, #(ACC_OBSOLETE_METHOD_SHIFT + 1)
+ bcs .Limt_conflict_trampoline_dex_cache_miss
+ ldr r4, [r0, #MIRROR_CLASS_DEX_CACHE_OFFSET] // Load the DexCache (without read barrier).
+ UNPOISON_HEAP_REF r4
+ ubfx r1, r12, #0, #METHOD_DEX_CACHE_HASH_BITS // Calculate DexCache method slot index.
+ ldr r4, [r4, #MIRROR_DEX_CACHE_RESOLVED_METHODS_OFFSET] // Load the resolved methods.
+ add r4, r4, r1, lsl #(POINTER_SIZE_SHIFT + 1) // Load DexCache method slot address.
// FIXME: Configure the build to use the faster code when appropriate.
// Currently we fall back to the slower version.
diff --git a/runtime/arch/arm64/quick_entrypoints_arm64.S b/runtime/arch/arm64/quick_entrypoints_arm64.S
index 6c9ce93..adfc88f 100644
--- a/runtime/arch/arm64/quick_entrypoints_arm64.S
+++ b/runtime/arch/arm64/quick_entrypoints_arm64.S
@@ -2060,8 +2060,18 @@
.extern artLookupResolvedMethod
ENTRY art_quick_imt_conflict_trampoline
ldr xIP0, [sp, #0] // Load referrer
+ // Load the declaring class (without read barrier) and access flags (for obsolete method check).
+ // The obsolete flag is set with suspended threads, so we do not need an acquire operation here.
+#if ART_METHOD_ACCESS_FLAGS_OFFSET != ART_METHOD_DECLARING_CLASS_OFFSET + 4
+#error "Expecting declaring class and access flags to be consecutive for LDP."
+#endif
+ ldp wIP0, w15, [xIP0, #ART_METHOD_DECLARING_CLASS_OFFSET]
+ // If the method is obsolete, just go through the dex cache miss slow path.
+ tbnz x15, #ACC_OBSOLETE_METHOD_SHIFT, .Limt_conflict_trampoline_dex_cache_miss
+ ldr wIP0, [xIP0, #MIRROR_CLASS_DEX_CACHE_OFFSET] // Load the DexCache (without read barrier).
+ UNPOISON_HEAP_REF wIP0
ubfx x15, xIP1, #0, #METHOD_DEX_CACHE_HASH_BITS // Calculate DexCache method slot index.
- ldr xIP0, [xIP0, #ART_METHOD_DEX_CACHE_METHODS_OFFSET_64] // Load dex cache methods array
+ ldr xIP0, [xIP0, #MIRROR_DEX_CACHE_RESOLVED_METHODS_OFFSET] // Load the resolved methods.
add xIP0, xIP0, x15, lsl #(POINTER_SIZE_SHIFT + 1) // Load DexCache method slot address.
// Relaxed atomic load x14:x15 from the dex cache slot.
diff --git a/runtime/arch/mips/quick_entrypoints_mips.S b/runtime/arch/mips/quick_entrypoints_mips.S
index bb82d58..b876353 100644
--- a/runtime/arch/mips/quick_entrypoints_mips.S
+++ b/runtime/arch/mips/quick_entrypoints_mips.S
@@ -2112,10 +2112,18 @@
SETUP_SAVE_REFS_AND_ARGS_FRAME_REGISTERS_ONLY /* save_s4_thru_s8 */ 0
lw $t8, FRAME_SIZE_SAVE_REFS_AND_ARGS($sp) # $t8 = referrer.
+ // If the method is obsolete, just go through the dex cache miss slow path.
+ // The obsolete flag is set with suspended threads, so we do not need an acquire operation here.
+ lw $t9, ART_METHOD_ACCESS_FLAGS_OFFSET($t8) # $t9 = access flags.
+ sll $t9, $t9, 31 - ACC_OBSOLETE_METHOD_SHIFT # Move obsolete method bit to sign bit.
+ bltz $t9, .Limt_conflict_trampoline_dex_cache_miss
+ lw $t8, ART_METHOD_DECLARING_CLASS_OFFSET($t8) # $t8 = declaring class (no read barrier).
+ lw $t8, MIRROR_CLASS_DEX_CACHE_OFFSET($t8) # $t8 = dex cache (without read barrier).
+ UNPOISON_HEAP_REF $t8
la $t9, __atomic_load_8
addiu $sp, $sp, -ARG_SLOT_SIZE # Reserve argument slots on the stack.
.cfi_adjust_cfa_offset ARG_SLOT_SIZE
- lw $t8, ART_METHOD_DEX_CACHE_METHODS_OFFSET_32($t8) # $t8 = dex cache methods array.
+ lw $t8, MIRROR_DEX_CACHE_RESOLVED_METHODS_OFFSET($t8) # $t8 = dex cache methods array.
move $s2, $t7 # $s2 = method index (callee-saved).
lw $s3, ART_METHOD_JNI_OFFSET_32($a0) # $s3 = ImtConflictTable (callee-saved).
diff --git a/runtime/arch/mips64/quick_entrypoints_mips64.S b/runtime/arch/mips64/quick_entrypoints_mips64.S
index 7350c85..eeaae3c 100644
--- a/runtime/arch/mips64/quick_entrypoints_mips64.S
+++ b/runtime/arch/mips64/quick_entrypoints_mips64.S
@@ -2024,8 +2024,16 @@
SETUP_SAVE_REFS_AND_ARGS_FRAME_INTERNAL /* save_s4_thru_s8 */ 0
ld $t1, FRAME_SIZE_SAVE_REFS_AND_ARGS($sp) # $t1 = referrer.
+ // If the method is obsolete, just go through the dex cache miss slow path.
+ // The obsolete flag is set with suspended threads, so we do not need an acquire operation here.
+ lw $t9, ART_METHOD_ACCESS_FLAGS_OFFSET($t1) # $t9 = access flags.
+ sll $t9, $t9, 31 - ACC_OBSOLETE_METHOD_SHIFT # Move obsolete method bit to sign bit.
+ bltzc $t9, .Limt_conflict_trampoline_dex_cache_miss
+ lwu $t1, ART_METHOD_DECLARING_CLASS_OFFSET($t1) # $t1 = declaring class (no read barrier).
+ lwu $t1, MIRROR_CLASS_DEX_CACHE_OFFSET($t1) # $t1 = dex cache (without read barrier).
+ UNPOISON_HEAP_REF $t1
dla $t9, __atomic_load_16
- ld $t1, ART_METHOD_DEX_CACHE_METHODS_OFFSET_64($t1) # $t1 = dex cache methods array.
+ ld $t1, MIRROR_DEX_CACHE_RESOLVED_METHODS_OFFSET($t1) # $t1 = dex cache methods array.
dext $s2, $t0, 0, 32 # $s2 = zero-extended method index
# (callee-saved).
diff --git a/runtime/arch/x86/quick_entrypoints_x86.S b/runtime/arch/x86/quick_entrypoints_x86.S
index af82e08..eecca58 100644
--- a/runtime/arch/x86/quick_entrypoints_x86.S
+++ b/runtime/arch/x86/quick_entrypoints_x86.S
@@ -1787,7 +1787,14 @@
PUSH ESI
PUSH EDX
movl 16(%esp), %edi // Load referrer.
- movl ART_METHOD_DEX_CACHE_METHODS_OFFSET_32(%edi), %edi // Load dex cache methods array.
+ // If the method is obsolete, just go through the dex cache miss slow path.
+ // The obsolete flag is set with suspended threads, so we do not need an acquire operation here.
+ testl LITERAL(ACC_OBSOLETE_METHOD), ART_METHOD_ACCESS_FLAGS_OFFSET(%edi)
+ jnz .Limt_conflict_trampoline_dex_cache_miss
+ movl ART_METHOD_DECLARING_CLASS_OFFSET(%edi), %edi // Load declaring class (no read barrier).
+ movl MIRROR_CLASS_DEX_CACHE_OFFSET(%edi), %edi // Load the DexCache (without read barrier).
+ UNPOISON_HEAP_REF edi
+ movl MIRROR_DEX_CACHE_RESOLVED_METHODS_OFFSET(%edi), %edi // Load the resolved methods.
pushl ART_METHOD_JNI_OFFSET_32(%eax) // Push ImtConflictTable.
CFI_ADJUST_CFA_OFFSET(4)
movd %xmm7, %eax // Get target method index stored in xmm7.
diff --git a/runtime/arch/x86_64/quick_entrypoints_x86_64.S b/runtime/arch/x86_64/quick_entrypoints_x86_64.S
index 6bf0828..2c3da90 100644
--- a/runtime/arch/x86_64/quick_entrypoints_x86_64.S
+++ b/runtime/arch/x86_64/quick_entrypoints_x86_64.S
@@ -1646,7 +1646,14 @@
int3
#else
movq __SIZEOF_POINTER__(%rsp), %r10 // Load referrer.
- movq ART_METHOD_DEX_CACHE_METHODS_OFFSET_64(%r10), %r10 // Load dex cache methods array.
+ // If the method is obsolete, just go through the dex cache miss slow path.
+ // The obsolete flag is set with suspended threads, so we do not need an acquire operation here.
+ testl LITERAL(ACC_OBSOLETE_METHOD), ART_METHOD_ACCESS_FLAGS_OFFSET(%r10)
+ jnz .Limt_conflict_trampoline_dex_cache_miss
+ movl ART_METHOD_DECLARING_CLASS_OFFSET(%r10), %r10d // Load declaring class (no read barrier).
+ movl MIRROR_CLASS_DEX_CACHE_OFFSET(%r10), %r10d // Load the DexCache (without read barrier).
+ UNPOISON_HEAP_REF r10d
+ movq MIRROR_DEX_CACHE_RESOLVED_METHODS_OFFSET(%r10), %r10 // Load the resolved methods.
mov %eax, %r11d // Remember method index in R11.
andl LITERAL(METHOD_DEX_CACHE_SIZE_MINUS_ONE), %eax // Calculate DexCache method slot index.
shll LITERAL(1), %eax // Multiply by 2 as entries have size 2 * __SIZEOF_POINTER__.
diff --git a/runtime/art_method-inl.h b/runtime/art_method-inl.h
index 11f8253..1588920 100644
--- a/runtime/art_method-inl.h
+++ b/runtime/art_method-inl.h
@@ -102,58 +102,6 @@
return GetDexMethodIndexUnchecked();
}
-inline mirror::MethodDexCacheType* ArtMethod::GetDexCacheResolvedMethods(PointerSize pointer_size) {
- return GetNativePointer<mirror::MethodDexCacheType*>(DexCacheResolvedMethodsOffset(pointer_size),
- pointer_size);
-}
-
-inline ArtMethod* ArtMethod::GetDexCacheResolvedMethod(uint16_t method_index,
- PointerSize pointer_size) {
- // NOTE: Unchecked, i.e. not throwing AIOOB. We don't even know the length here
- // without accessing the DexCache and we don't want to do that in release build.
- DCHECK_LT(method_index, GetInterfaceMethodIfProxy(pointer_size)->GetDexFile()->NumMethodIds());
- uint32_t slot_idx = method_index % mirror::DexCache::kDexCacheMethodCacheSize;
- DCHECK_LT(slot_idx, GetInterfaceMethodIfProxy(pointer_size)->GetDexCache()->NumResolvedMethods());
- mirror::MethodDexCachePair pair = mirror::DexCache::GetNativePairPtrSize(
- GetDexCacheResolvedMethods(pointer_size), slot_idx, pointer_size);
- ArtMethod* method = pair.GetObjectForIndex(method_index);
- if (LIKELY(method != nullptr)) {
- auto* declaring_class = method->GetDeclaringClass();
- if (LIKELY(declaring_class == nullptr || !declaring_class->IsErroneous())) {
- return method;
- }
- }
- return nullptr;
-}
-
-inline void ArtMethod::SetDexCacheResolvedMethod(uint16_t method_index,
- ArtMethod* new_method,
- PointerSize pointer_size) {
- // NOTE: Unchecked, i.e. not throwing AIOOB. We don't even know the length here
- // without accessing the DexCache and we don't want to do that in release build.
- DCHECK_LT(method_index, GetInterfaceMethodIfProxy(pointer_size)->GetDexFile()->NumMethodIds());
- DCHECK(new_method == nullptr || new_method->GetDeclaringClass() != nullptr);
- uint32_t slot_idx = method_index % mirror::DexCache::kDexCacheMethodCacheSize;
- DCHECK_LT(slot_idx, GetInterfaceMethodIfProxy(pointer_size)->GetDexCache()->NumResolvedMethods());
- mirror::MethodDexCachePair pair(new_method, method_index);
- mirror::DexCache::SetNativePairPtrSize(
- GetDexCacheResolvedMethods(pointer_size), slot_idx, pair, pointer_size);
-}
-
-inline bool ArtMethod::HasDexCacheResolvedMethods(PointerSize pointer_size) {
- return GetDexCacheResolvedMethods(pointer_size) != nullptr;
-}
-
-inline bool ArtMethod::HasSameDexCacheResolvedMethods(ArtMethod* other, PointerSize pointer_size) {
- return GetDexCacheResolvedMethods(pointer_size) ==
- other->GetDexCacheResolvedMethods(pointer_size);
-}
-
-inline bool ArtMethod::HasSameDexCacheResolvedMethods(mirror::MethodDexCacheType* other_cache,
- PointerSize pointer_size) {
- return GetDexCacheResolvedMethods(pointer_size) == other_cache;
-}
-
inline ObjPtr<mirror::Class> ArtMethod::LookupResolvedClassFromTypeIndex(dex::TypeIndex type_idx) {
ObjPtr<mirror::DexCache> dex_cache = GetDexCache();
ObjPtr<mirror::Class> type = dex_cache->GetResolvedType(type_idx);
@@ -403,13 +351,6 @@
return interface_method;
}
-inline void ArtMethod::SetDexCacheResolvedMethods(mirror::MethodDexCacheType* new_dex_cache_methods,
- PointerSize pointer_size) {
- SetNativePointer(DexCacheResolvedMethodsOffset(pointer_size),
- new_dex_cache_methods,
- pointer_size);
-}
-
inline dex::TypeIndex ArtMethod::GetReturnTypeIndex() {
DCHECK(!IsProxyMethod());
const DexFile* dex_file = GetDexFile();
@@ -489,18 +430,12 @@
}
template <typename Visitor>
-inline void ArtMethod::UpdateObjectsForImageRelocation(const Visitor& visitor,
- PointerSize pointer_size) {
+inline void ArtMethod::UpdateObjectsForImageRelocation(const Visitor& visitor) {
mirror::Class* old_class = GetDeclaringClassUnchecked<kWithoutReadBarrier>();
mirror::Class* new_class = visitor(old_class);
if (old_class != new_class) {
SetDeclaringClass(new_class);
}
- mirror::MethodDexCacheType* old_methods = GetDexCacheResolvedMethods(pointer_size);
- mirror::MethodDexCacheType* new_methods = visitor(old_methods);
- if (old_methods != new_methods) {
- SetDexCacheResolvedMethods(new_methods, pointer_size);
- }
}
template <ReadBarrierOption kReadBarrierOption, typename Visitor>
diff --git a/runtime/art_method.h b/runtime/art_method.h
index 64988f2..2d67761 100644
--- a/runtime/art_method.h
+++ b/runtime/art_method.h
@@ -137,6 +137,10 @@
} while (!access_flags_.compare_exchange_weak(old_access_flags, new_access_flags));
}
+ static MemberOffset AccessFlagsOffset() {
+ return MemberOffset(OFFSETOF_MEMBER(ArtMethod, access_flags_));
+ }
+
// Approximate what kind of method call would be used for this method.
InvokeType GetInvokeType() REQUIRES_SHARED(Locks::mutator_lock_);
@@ -356,26 +360,6 @@
dex_method_index_ = new_idx;
}
- ALWAYS_INLINE mirror::MethodDexCacheType* GetDexCacheResolvedMethods(PointerSize pointer_size)
- REQUIRES_SHARED(Locks::mutator_lock_);
- ALWAYS_INLINE ArtMethod* GetDexCacheResolvedMethod(uint16_t method_index,
- PointerSize pointer_size)
- REQUIRES_SHARED(Locks::mutator_lock_);
-
- ALWAYS_INLINE void SetDexCacheResolvedMethod(uint16_t method_index,
- ArtMethod* new_method,
- PointerSize pointer_size)
- REQUIRES_SHARED(Locks::mutator_lock_);
- ALWAYS_INLINE void SetDexCacheResolvedMethods(mirror::MethodDexCacheType* new_dex_cache_methods,
- PointerSize pointer_size)
- REQUIRES_SHARED(Locks::mutator_lock_);
- bool HasDexCacheResolvedMethods(PointerSize pointer_size) REQUIRES_SHARED(Locks::mutator_lock_);
- bool HasSameDexCacheResolvedMethods(ArtMethod* other, PointerSize pointer_size)
- REQUIRES_SHARED(Locks::mutator_lock_);
- bool HasSameDexCacheResolvedMethods(mirror::MethodDexCacheType* other_cache,
- PointerSize pointer_size)
- REQUIRES_SHARED(Locks::mutator_lock_);
-
// Lookup the Class* from the type index into this method's dex cache.
ObjPtr<mirror::Class> LookupResolvedClassFromTypeIndex(dex::TypeIndex type_idx)
REQUIRES_SHARED(Locks::mutator_lock_);
@@ -427,12 +411,6 @@
void UnregisterNative() REQUIRES_SHARED(Locks::mutator_lock_);
- static MemberOffset DexCacheResolvedMethodsOffset(PointerSize pointer_size) {
- return MemberOffset(PtrSizedFieldsOffset(pointer_size) + OFFSETOF_MEMBER(
- PtrSizedFields, dex_cache_resolved_methods_) / sizeof(void*)
- * static_cast<size_t>(pointer_size));
- }
-
static MemberOffset DataOffset(PointerSize pointer_size) {
return MemberOffset(PtrSizedFieldsOffset(pointer_size) + OFFSETOF_MEMBER(
PtrSizedFields, data_) / sizeof(void*) * static_cast<size_t>(pointer_size));
@@ -686,8 +664,7 @@
// Update heap objects and non-entrypoint pointers by the passed in visitor for image relocation.
// Does not use read barrier.
template <typename Visitor>
- ALWAYS_INLINE void UpdateObjectsForImageRelocation(const Visitor& visitor,
- PointerSize pointer_size)
+ ALWAYS_INLINE void UpdateObjectsForImageRelocation(const Visitor& visitor)
REQUIRES_SHARED(Locks::mutator_lock_);
// Update entry points by passing them through the visitor.
@@ -728,9 +705,6 @@
// Must be the last fields in the method.
struct PtrSizedFields {
- // Short cuts to declaring_class_->dex_cache_ member for fast compiled code access.
- mirror::MethodDexCacheType* dex_cache_resolved_methods_;
-
// Depending on the method type, the data is
// - native method: pointer to the JNI function registered to this method
// or a function to resolve the JNI function,
diff --git a/runtime/class_linker-inl.h b/runtime/class_linker-inl.h
index 439ecaf..d6f0030 100644
--- a/runtime/class_linker-inl.h
+++ b/runtime/class_linker-inl.h
@@ -186,7 +186,8 @@
// lookup in the context of the original method from where it steals the code.
// However, we delay the GetInterfaceMethodIfProxy() until needed.
DCHECK(!referrer->IsProxyMethod() || referrer->IsConstructor());
- ArtMethod* resolved_method = referrer->GetDexCacheResolvedMethod(method_idx, image_pointer_size_);
+ ArtMethod* resolved_method = referrer->GetDexCache<kWithoutReadBarrier>()->GetResolvedMethod(
+ method_idx, image_pointer_size_);
if (resolved_method == nullptr) {
return nullptr;
}
@@ -226,7 +227,8 @@
// However, we delay the GetInterfaceMethodIfProxy() until needed.
DCHECK(!referrer->IsProxyMethod() || referrer->IsConstructor());
Thread::PoisonObjectPointersIfDebug();
- ArtMethod* resolved_method = referrer->GetDexCacheResolvedMethod(method_idx, image_pointer_size_);
+ ArtMethod* resolved_method = referrer->GetDexCache<kWithoutReadBarrier>()->GetResolvedMethod(
+ method_idx, image_pointer_size_);
DCHECK(resolved_method == nullptr || !resolved_method->IsRuntimeMethod());
if (UNLIKELY(resolved_method == nullptr)) {
referrer = referrer->GetInterfaceMethodIfProxy(image_pointer_size_);
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 051c0c2..1beb783 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -1115,35 +1115,6 @@
return true;
}
-class FixupArtMethodArrayVisitor : public ArtMethodVisitor {
- public:
- explicit FixupArtMethodArrayVisitor(const ImageHeader& header) : header_(header) {}
-
- virtual void Visit(ArtMethod* method) REQUIRES_SHARED(Locks::mutator_lock_) {
- const bool is_copied = method->IsCopied();
- mirror::MethodDexCacheType* resolved_methods =
- method->GetDexCacheResolvedMethods(kRuntimePointerSize);
- if (resolved_methods != nullptr) {
- bool in_image_space = false;
- if (kIsDebugBuild || is_copied) {
- in_image_space = header_.GetImageSection(ImageHeader::kSectionDexCacheArrays).Contains(
- reinterpret_cast<const uint8_t*>(resolved_methods) - header_.GetImageBegin());
- }
- // Must be in image space for non-miranda method.
- DCHECK(is_copied || in_image_space)
- << resolved_methods << " is not in image starting at "
- << reinterpret_cast<void*>(header_.GetImageBegin());
- if (!is_copied || in_image_space) {
- method->SetDexCacheResolvedMethods(method->GetDexCache()->GetResolvedMethods(),
- kRuntimePointerSize);
- }
- }
- }
-
- private:
- const ImageHeader& header_;
-};
-
class VerifyDeclaringClassVisitor : public ArtMethodVisitor {
public:
VerifyDeclaringClassVisitor() REQUIRES_SHARED(Locks::mutator_lock_, Locks::heap_bitmap_lock_)
@@ -1492,12 +1463,6 @@
FixupInternVisitor fixup_intern_visitor;
bitmap->VisitMarkedRange(objects_begin, objects_end, fixup_intern_visitor);
}
- if (*out_forward_dex_cache_array) {
- ScopedTrace timing("Fixup ArtMethod dex cache arrays");
- FixupArtMethodArrayVisitor visitor(header);
- header.VisitPackedArtMethods(&visitor, space->Begin(), kRuntimePointerSize);
- Runtime::Current()->GetHeap()->WriteBarrierEveryFieldOf(class_loader.Get());
- }
if (kVerifyArtMethodDeclaringClasses) {
ScopedTrace timing("Verify declaring classes");
ReaderMutexLock rmu(self, *Locks::heap_bitmap_lock_);
@@ -3444,8 +3409,6 @@
dst->SetDeclaringClass(klass.Get());
dst->SetCodeItemOffset(it.GetMethodCodeItemOffset());
- dst->SetDexCacheResolvedMethods(klass->GetDexCache()->GetResolvedMethods(), image_pointer_size_);
-
uint32_t access_flags = it.GetMethodAccessFlags();
if (UNLIKELY(strcmp("finalize", method_name) == 0)) {
@@ -4729,7 +4692,6 @@
// The proxy method doesn't have its own dex cache or dex file and so it steals those of its
// interface prototype. The exception to this are Constructors and the Class of the Proxy itself.
- CHECK(prototype->HasSameDexCacheResolvedMethods(method, image_pointer_size_));
auto* np = method->GetInterfaceMethodIfProxy(image_pointer_size_);
CHECK_EQ(prototype->GetDeclaringClass()->GetDexCache(), np->GetDexCache());
CHECK_EQ(prototype->GetDexMethodIndex(), method->GetDexMethodIndex());
diff --git a/runtime/class_linker_test.cc b/runtime/class_linker_test.cc
index 5e9707c..f887b8e 100644
--- a/runtime/class_linker_test.cc
+++ b/runtime/class_linker_test.cc
@@ -245,11 +245,6 @@
EXPECT_TRUE(method->GetDeclaringClass() != nullptr);
EXPECT_TRUE(method->GetName() != nullptr);
EXPECT_TRUE(method->GetSignature() != Signature::NoSignature());
-
- EXPECT_TRUE(method->HasDexCacheResolvedMethods(kRuntimePointerSize));
- EXPECT_TRUE(method->HasSameDexCacheResolvedMethods(
- method->GetDeclaringClass()->GetDexCache()->GetResolvedMethods(),
- kRuntimePointerSize));
}
void AssertField(ObjPtr<mirror::Class> klass, ArtField* field)
diff --git a/runtime/entrypoints/entrypoint_utils-inl.h b/runtime/entrypoints/entrypoint_utils-inl.h
index be3e4f8..8253739 100644
--- a/runtime/entrypoints/entrypoint_utils-inl.h
+++ b/runtime/entrypoints/entrypoint_utils-inl.h
@@ -83,7 +83,7 @@
ObjPtr<mirror::DexCache> dex_cache = caller->GetDexCache();
const DexFile* dex_file = dex_cache->GetDexFile();
const DexFile::MethodId& method_id = dex_file->GetMethodId(method_index);
- ArtMethod* inlined_method = caller->GetDexCacheResolvedMethod(method_index, kRuntimePointerSize);
+ ArtMethod* inlined_method = dex_cache->GetResolvedMethod(method_index, kRuntimePointerSize);
if (inlined_method != nullptr) {
DCHECK(!inlined_method->IsRuntimeMethod());
return inlined_method;
@@ -106,7 +106,7 @@
<< dex_file->GetMethodSignature(method_id) << " declared. "
<< "This must be due to duplicate classes or playing wrongly with class loaders";
}
- caller->SetDexCacheResolvedMethod(method_index, inlined_method, kRuntimePointerSize);
+ dex_cache->SetResolvedMethod(method_index, inlined_method, kRuntimePointerSize);
return inlined_method;
}
diff --git a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
index 5f71326..7b83f20 100644
--- a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
@@ -1271,7 +1271,7 @@
// FindVirtualMethodFor... This is ok for FindDexMethodIndexInOtherDexFile that only cares
// about the name and signature.
uint32_t update_dex_cache_method_index = called->GetDexMethodIndex();
- if (!called->HasSameDexCacheResolvedMethods(caller, kRuntimePointerSize)) {
+ if (called->GetDexFile() != caller->GetDexFile()) {
// Calling from one dex file to another, need to compute the method index appropriate to
// the caller's dex file. Since we get here only if the original called was a runtime
// method, we've got the correct dex_file and a dex_method_idx from above.
@@ -1283,12 +1283,16 @@
called->FindDexMethodIndexInOtherDexFile(*caller_dex_file,
caller_method_name_and_sig_index);
}
- if ((update_dex_cache_method_index != DexFile::kDexNoIndex) &&
- (caller->GetDexCacheResolvedMethod(
- update_dex_cache_method_index, kRuntimePointerSize) != called)) {
- caller->SetDexCacheResolvedMethod(update_dex_cache_method_index,
- called,
- kRuntimePointerSize);
+ if (update_dex_cache_method_index != DexFile::kDexNoIndex) {
+ // Note: We do not need the read barrier for the dex cache as the SetResolvedMethod()
+ // operates on native (non-moveable) data and constants (num_resolved_methods_).
+ ObjPtr<mirror::DexCache> caller_dex_cache = caller->GetDexCache<kWithoutReadBarrier>();
+ if (caller_dex_cache->GetResolvedMethod(
+ update_dex_cache_method_index, kRuntimePointerSize) != called) {
+ caller_dex_cache->SetResolvedMethod(update_dex_cache_method_index,
+ called,
+ kRuntimePointerSize);
+ }
}
} else if (invoke_type == kStatic) {
const auto called_dex_method_idx = called->GetDexMethodIndex();
diff --git a/runtime/gc/space/image_space.cc b/runtime/gc/space/image_space.cc
index 14e017a..1a48b46 100644
--- a/runtime/gc/space/image_space.cc
+++ b/runtime/gc/space/image_space.cc
@@ -1128,7 +1128,7 @@
}
} else {
if (fixup_heap_objects_) {
- method->UpdateObjectsForImageRelocation(ForwardObjectAdapter(this), pointer_size_);
+ method->UpdateObjectsForImageRelocation(ForwardObjectAdapter(this));
}
method->UpdateEntrypoints<kWithoutReadBarrier>(ForwardCodeAdapter(this), pointer_size_);
}
diff --git a/runtime/generated/asm_support_gen.h b/runtime/generated/asm_support_gen.h
index 314c45e..071d1ae 100644
--- a/runtime/generated/asm_support_gen.h
+++ b/runtime/generated/asm_support_gen.h
@@ -48,6 +48,10 @@
DEFINE_CHECK_EQ(static_cast<int32_t>(THREAD_CARD_TABLE_OFFSET), (static_cast<int32_t>(art::Thread:: CardTableOffset<art::kRuntimePointerSize>().Int32Value())))
#define CODEITEM_INSNS_OFFSET 16
DEFINE_CHECK_EQ(static_cast<int32_t>(CODEITEM_INSNS_OFFSET), (static_cast<int32_t>(__builtin_offsetof(art::DexFile::CodeItem, insns_))))
+#define MIRROR_CLASS_DEX_CACHE_OFFSET 16
+DEFINE_CHECK_EQ(static_cast<int32_t>(MIRROR_CLASS_DEX_CACHE_OFFSET), (static_cast<int32_t>(art::mirror::Class:: DexCacheOffset().Int32Value())))
+#define MIRROR_DEX_CACHE_RESOLVED_METHODS_OFFSET 48
+DEFINE_CHECK_EQ(static_cast<int32_t>(MIRROR_DEX_CACHE_RESOLVED_METHODS_OFFSET), (static_cast<int32_t>(art::mirror::DexCache:: ResolvedMethodsOffset().Int32Value())))
#define MIRROR_OBJECT_CLASS_OFFSET 0
DEFINE_CHECK_EQ(static_cast<int32_t>(MIRROR_OBJECT_CLASS_OFFSET), (static_cast<int32_t>(art::mirror::Object:: ClassOffset().Int32Value())))
#define MIRROR_OBJECT_LOCK_WORD_OFFSET 4
@@ -60,20 +64,18 @@
DEFINE_CHECK_EQ(static_cast<uint32_t>(ACCESS_FLAGS_CLASS_IS_INTERFACE), (static_cast<uint32_t>((art::kAccInterface))))
#define ACCESS_FLAGS_CLASS_IS_FINALIZABLE_BIT 0x1f
DEFINE_CHECK_EQ(static_cast<uint32_t>(ACCESS_FLAGS_CLASS_IS_FINALIZABLE_BIT), (static_cast<uint32_t>((art::MostSignificantBit(art::kAccClassIsFinalizable)))))
-#define ART_METHOD_DEX_CACHE_METHODS_OFFSET_32 20
-DEFINE_CHECK_EQ(static_cast<int32_t>(ART_METHOD_DEX_CACHE_METHODS_OFFSET_32), (static_cast<int32_t>(art::ArtMethod:: DexCacheResolvedMethodsOffset(art::PointerSize::k32).Int32Value())))
-#define ART_METHOD_DEX_CACHE_METHODS_OFFSET_64 24
-DEFINE_CHECK_EQ(static_cast<int32_t>(ART_METHOD_DEX_CACHE_METHODS_OFFSET_64), (static_cast<int32_t>(art::ArtMethod:: DexCacheResolvedMethodsOffset(art::PointerSize::k64).Int32Value())))
-#define ART_METHOD_JNI_OFFSET_32 24
+#define ART_METHOD_JNI_OFFSET_32 20
DEFINE_CHECK_EQ(static_cast<int32_t>(ART_METHOD_JNI_OFFSET_32), (static_cast<int32_t>(art::ArtMethod:: EntryPointFromJniOffset(art::PointerSize::k32).Int32Value())))
-#define ART_METHOD_JNI_OFFSET_64 32
+#define ART_METHOD_JNI_OFFSET_64 24
DEFINE_CHECK_EQ(static_cast<int32_t>(ART_METHOD_JNI_OFFSET_64), (static_cast<int32_t>(art::ArtMethod:: EntryPointFromJniOffset(art::PointerSize::k64).Int32Value())))
-#define ART_METHOD_QUICK_CODE_OFFSET_32 28
+#define ART_METHOD_QUICK_CODE_OFFSET_32 24
DEFINE_CHECK_EQ(static_cast<int32_t>(ART_METHOD_QUICK_CODE_OFFSET_32), (static_cast<int32_t>(art::ArtMethod:: EntryPointFromQuickCompiledCodeOffset(art::PointerSize::k32).Int32Value())))
-#define ART_METHOD_QUICK_CODE_OFFSET_64 40
+#define ART_METHOD_QUICK_CODE_OFFSET_64 32
DEFINE_CHECK_EQ(static_cast<int32_t>(ART_METHOD_QUICK_CODE_OFFSET_64), (static_cast<int32_t>(art::ArtMethod:: EntryPointFromQuickCompiledCodeOffset(art::PointerSize::k64).Int32Value())))
#define ART_METHOD_DECLARING_CLASS_OFFSET 0
DEFINE_CHECK_EQ(static_cast<int32_t>(ART_METHOD_DECLARING_CLASS_OFFSET), (static_cast<int32_t>(art::ArtMethod:: DeclaringClassOffset().Int32Value())))
+#define ART_METHOD_ACCESS_FLAGS_OFFSET 4
+DEFINE_CHECK_EQ(static_cast<int32_t>(ART_METHOD_ACCESS_FLAGS_OFFSET), (static_cast<int32_t>(art::ArtMethod:: AccessFlagsOffset().Int32Value())))
#define STRING_DEX_CACHE_ELEMENT_SIZE_SHIFT 3
DEFINE_CHECK_EQ(static_cast<int32_t>(STRING_DEX_CACHE_ELEMENT_SIZE_SHIFT), (static_cast<int32_t>(art::WhichPowerOf2(sizeof(art::mirror::StringDexCachePair)))))
#define STRING_DEX_CACHE_SIZE_MINUS_ONE 1023
@@ -126,6 +128,10 @@
DEFINE_CHECK_EQ(static_cast<uint32_t>(OBJECT_ALIGNMENT_MASK_TOGGLED), (static_cast<uint32_t>(~static_cast<uint32_t>(art::kObjectAlignment - 1))))
#define OBJECT_ALIGNMENT_MASK_TOGGLED64 0xfffffffffffffff8
DEFINE_CHECK_EQ(static_cast<uint64_t>(OBJECT_ALIGNMENT_MASK_TOGGLED64), (static_cast<uint64_t>(~static_cast<uint64_t>(art::kObjectAlignment - 1))))
+#define ACC_OBSOLETE_METHOD 262144
+DEFINE_CHECK_EQ(static_cast<int32_t>(ACC_OBSOLETE_METHOD), (static_cast<int32_t>(art::kAccObsoleteMethod)))
+#define ACC_OBSOLETE_METHOD_SHIFT 18
+DEFINE_CHECK_EQ(static_cast<int32_t>(ACC_OBSOLETE_METHOD_SHIFT), (static_cast<int32_t>(art::WhichPowerOf2(art::kAccObsoleteMethod))))
#define ROSALLOC_MAX_THREAD_LOCAL_BRACKET_SIZE 128
DEFINE_CHECK_EQ(static_cast<int32_t>(ROSALLOC_MAX_THREAD_LOCAL_BRACKET_SIZE), (static_cast<int32_t>((art::gc::allocator::RosAlloc::kMaxThreadLocalBracketSize))))
#define ROSALLOC_BRACKET_QUANTUM_SIZE_SHIFT 3
diff --git a/runtime/image.cc b/runtime/image.cc
index 950ac5d..1f7e0f3 100644
--- a/runtime/image.cc
+++ b/runtime/image.cc
@@ -26,7 +26,7 @@
namespace art {
const uint8_t ImageHeader::kImageMagic[] = { 'a', 'r', 't', '\n' };
-const uint8_t ImageHeader::kImageVersion[] = { '0', '4', '6', '\0' }; // Hash-based methods array.
+const uint8_t ImageHeader::kImageVersion[] = { '0', '4', '7', '\0' }; // Smaller ArtMethod.
ImageHeader::ImageHeader(uint32_t image_begin,
uint32_t image_size,
diff --git a/tools/cpp-define-generator/constant_globals.def b/tools/cpp-define-generator/constant_globals.def
index dbaf33c..5018f52 100644
--- a/tools/cpp-define-generator/constant_globals.def
+++ b/tools/cpp-define-generator/constant_globals.def
@@ -19,6 +19,7 @@
#if defined(DEFINE_INCLUDE_DEPENDENCIES)
#include <atomic> // std::memory_order_relaxed
#include "globals.h" // art::kObjectAlignment
+#include "modifiers.h"
#endif
DEFINE_EXPR(STD_MEMORY_ORDER_RELAXED, int32_t, std::memory_order_relaxed)
@@ -30,5 +31,8 @@
DEFINE_OBJECT_EXPR(ALIGNMENT_MASK_TOGGLED, uint32_t, ~static_cast<uint32_t>(art::kObjectAlignment - 1))
DEFINE_OBJECT_EXPR(ALIGNMENT_MASK_TOGGLED64, uint64_t, ~static_cast<uint64_t>(art::kObjectAlignment - 1))
+DEFINE_EXPR(ACC_OBSOLETE_METHOD, int32_t, art::kAccObsoleteMethod)
+DEFINE_EXPR(ACC_OBSOLETE_METHOD_SHIFT, int32_t, art::WhichPowerOf2(art::kAccObsoleteMethod))
+
#undef DEFINE_OBJECT_EXPR
diff --git a/tools/cpp-define-generator/offset_dexcache.def b/tools/cpp-define-generator/offset_art_method.def
similarity index 95%
rename from tools/cpp-define-generator/offset_dexcache.def
rename to tools/cpp-define-generator/offset_art_method.def
index 43f9434..e6a0907 100644
--- a/tools/cpp-define-generator/offset_dexcache.def
+++ b/tools/cpp-define-generator/offset_art_method.def
@@ -33,10 +33,10 @@
DEFINE_EXPR(DECLARING_CLASS_ ## field_name ## _OFFSET, int32_t, art::mirror::Class::method_name##Offset().Int32Value())
// New macro suffix Method Name (of the Offset method)
-DEFINE_ART_METHOD_OFFSET_SIZED(DEX_CACHE_METHODS, DexCacheResolvedMethods)
DEFINE_ART_METHOD_OFFSET_SIZED(JNI, EntryPointFromJni)
DEFINE_ART_METHOD_OFFSET_SIZED(QUICK_CODE, EntryPointFromQuickCompiledCode)
DEFINE_ART_METHOD_OFFSET(DECLARING_CLASS, DeclaringClass)
+DEFINE_ART_METHOD_OFFSET(ACCESS_FLAGS, AccessFlags)
#undef DEFINE_ART_METHOD_OFFSET
#undef DEFINE_ART_METHOD_OFFSET_32
diff --git a/tools/cpp-define-generator/offset_mirror_class.def b/tools/cpp-define-generator/offset_mirror_class.def
new file mode 100644
index 0000000..9b7bfce
--- /dev/null
+++ b/tools/cpp-define-generator/offset_mirror_class.def
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// Offsets within java.lang.Class (mirror::Class).
+
+#if defined(DEFINE_INCLUDE_DEPENDENCIES)
+#include "mirror/class.h" // art::mirror::Object
+#endif
+
+#include "common.def" // DEFINE_OFFSET_EXPR
+
+#define DEFINE_MIRROR_CLASS_OFFSET(field_name, method_name) \
+ DEFINE_OFFSET_EXPR(MIRROR_CLASS, field_name, int32_t, art::mirror::Class::method_name##Offset().Int32Value())
+
+// New macro suffix Method Name (of the Offset method)
+DEFINE_MIRROR_CLASS_OFFSET(DEX_CACHE, DexCache)
+
+#undef DEFINE_MIRROR_CLASS_OFFSET
+#include "common_undef.def" // undef DEFINE_OFFSET_EXPR
diff --git a/tools/cpp-define-generator/offset_mirror_dex_cache.def b/tools/cpp-define-generator/offset_mirror_dex_cache.def
new file mode 100644
index 0000000..8f008bb
--- /dev/null
+++ b/tools/cpp-define-generator/offset_mirror_dex_cache.def
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// Offsets within java.lang.DexCache (mirror::DexCache).
+
+#if defined(DEFINE_INCLUDE_DEPENDENCIES)
+#include "mirror/class.h" // art::mirror::Object
+#endif
+
+#include "common.def" // DEFINE_OFFSET_EXPR
+
+#define DEFINE_MIRROR_DEX_CACHE_OFFSET(field_name, method_name) \
+ DEFINE_OFFSET_EXPR(MIRROR_DEX_CACHE, field_name, int32_t, art::mirror::DexCache::method_name##Offset().Int32Value())
+
+// New macro suffix Method Name (of the Offset method)
+DEFINE_MIRROR_DEX_CACHE_OFFSET(RESOLVED_METHODS, ResolvedMethods)
+
+#undef DEFINE_MIRROR_CLASS_OFFSET
+#include "common_undef.def" // undef DEFINE_OFFSET_EXPR
diff --git a/tools/cpp-define-generator/offsets_all.def b/tools/cpp-define-generator/offsets_all.def
index b8947de..c2e8c97 100644
--- a/tools/cpp-define-generator/offsets_all.def
+++ b/tools/cpp-define-generator/offsets_all.def
@@ -42,12 +42,13 @@
// #include "offset_shadow_frame.def"
#include "offset_codeitem.def"
// TODO: MIRROR_OBJECT_HEADER_SIZE (depends on #ifdef read barrier)
-// TODO: MIRROR_CLASS offsets (see above)
+#include "offset_mirror_class.def"
+#include "offset_mirror_dex_cache.def"
#include "offset_mirror_object.def"
#include "constant_class.def"
// TODO: MIRROR_*_ARRAY offsets (depends on header size)
// TODO: MIRROR_STRING offsets (depends on header size)
-#include "offset_dexcache.def"
+#include "offset_art_method.def"
#include "constant_dexcache.def"
#include "constant_card_table.def"
#include "constant_heap.def"