1/* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#ifndef ART_RUNTIME_MIRROR_CLASS_INL_H_ 18#define ART_RUNTIME_MIRROR_CLASS_INL_H_ 19 20#include "class.h" 21 22#include "art_field-inl.h" 23#include "art_method.h" 24#include "art_method-inl.h" 25#include "base/array_slice.h" 26#include "base/length_prefixed_array.h" 27#include "class_loader.h" 28#include "common_throws.h" 29#include "dex_cache.h" 30#include "dex_file.h" 31#include "gc/heap-inl.h" 32#include "iftable.h" 33#include "object_array-inl.h" 34#include "read_barrier-inl.h" 35#include "reference-inl.h" 36#include "runtime.h" 37#include "string.h" 38#include "utils.h" 39 40namespace art { 41namespace mirror { 42 43template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption> 44inline uint32_t Class::GetObjectSize() { 45 // Note: Extra parentheses to avoid the comma being interpreted as macro parameter separator. 46 DCHECK((!IsVariableSize<kVerifyFlags, kReadBarrierOption>())) << " class=" << PrettyTypeOf(this); 47 return GetField32(ObjectSizeOffset()); 48} 49 50template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption> 51inline Class* Class::GetSuperClass() { 52 // Can only get super class for loaded classes (hack for when runtime is 53 // initializing) 54 DCHECK(IsLoaded<kVerifyFlags>() || 55 IsErroneous<kVerifyFlags>() || 56 !Runtime::Current()->IsStarted()) << IsLoaded(); 57 return GetFieldObject<Class, kVerifyFlags, kReadBarrierOption>( 58 OFFSET_OF_OBJECT_MEMBER(Class, super_class_)); 59} 60 61inline ClassLoader* Class::GetClassLoader() { 62 return GetFieldObject<ClassLoader>(OFFSET_OF_OBJECT_MEMBER(Class, class_loader_)); 63} 64 65template<VerifyObjectFlags kVerifyFlags> 66inline DexCache* Class::GetDexCache() { 67 return GetFieldObject<DexCache, kVerifyFlags>(OFFSET_OF_OBJECT_MEMBER(Class, dex_cache_)); 68} 69 70inline uint32_t Class::GetCopiedMethodsStartOffset() { 71 return GetFieldShort(OFFSET_OF_OBJECT_MEMBER(Class, copied_methods_offset_)); 72} 73 74inline uint32_t Class::GetDirectMethodsStartOffset() { 75 return 0; 76} 77 78inline uint32_t Class::GetVirtualMethodsStartOffset() { 79 return GetFieldShort(OFFSET_OF_OBJECT_MEMBER(Class, virtual_methods_offset_)); 80} 81 82template<VerifyObjectFlags kVerifyFlags> 83inline ArraySlice<ArtMethod> Class::GetDirectMethodsSlice(size_t pointer_size) { 84 DCHECK(IsLoaded() || IsErroneous()); 85 DCHECK(ValidPointerSize(pointer_size)) << pointer_size; 86 return GetDirectMethodsSliceUnchecked(pointer_size); 87} 88 89inline ArraySlice<ArtMethod> Class::GetDirectMethodsSliceUnchecked(size_t pointer_size) { 90 return ArraySlice<ArtMethod>(GetMethodsPtr(), 91 GetDirectMethodsStartOffset(), 92 GetVirtualMethodsStartOffset(), 93 ArtMethod::Size(pointer_size), 94 ArtMethod::Alignment(pointer_size)); 95} 96 97template<VerifyObjectFlags kVerifyFlags> 98inline ArraySlice<ArtMethod> Class::GetDeclaredMethodsSlice(size_t pointer_size) { 99 DCHECK(IsLoaded() || IsErroneous()); 100 DCHECK(ValidPointerSize(pointer_size)) << pointer_size; 101 return GetDeclaredMethodsSliceUnchecked(pointer_size); 102} 103 104inline ArraySlice<ArtMethod> Class::GetDeclaredMethodsSliceUnchecked(size_t pointer_size) { 105 return ArraySlice<ArtMethod>(GetMethodsPtr(), 106 GetDirectMethodsStartOffset(), 107 GetCopiedMethodsStartOffset(), 108 ArtMethod::Size(pointer_size), 109 ArtMethod::Alignment(pointer_size)); 110} 111template<VerifyObjectFlags kVerifyFlags> 112inline ArraySlice<ArtMethod> Class::GetDeclaredVirtualMethodsSlice(size_t pointer_size) { 113 DCHECK(IsLoaded() || IsErroneous()); 114 DCHECK(ValidPointerSize(pointer_size)) << pointer_size; 115 return GetDeclaredVirtualMethodsSliceUnchecked(pointer_size); 116} 117 118inline ArraySlice<ArtMethod> Class::GetDeclaredVirtualMethodsSliceUnchecked(size_t pointer_size) { 119 return ArraySlice<ArtMethod>(GetMethodsPtr(), 120 GetVirtualMethodsStartOffset(), 121 GetCopiedMethodsStartOffset(), 122 ArtMethod::Size(pointer_size), 123 ArtMethod::Alignment(pointer_size)); 124} 125 126template<VerifyObjectFlags kVerifyFlags> 127inline ArraySlice<ArtMethod> Class::GetVirtualMethodsSlice(size_t pointer_size) { 128 DCHECK(IsLoaded() || IsErroneous()); 129 DCHECK(ValidPointerSize(pointer_size)) << pointer_size; 130 return GetVirtualMethodsSliceUnchecked(pointer_size); 131} 132 133inline ArraySlice<ArtMethod> Class::GetVirtualMethodsSliceUnchecked(size_t pointer_size) { 134 LengthPrefixedArray<ArtMethod>* methods = GetMethodsPtr(); 135 return ArraySlice<ArtMethod>(methods, 136 GetVirtualMethodsStartOffset(), 137 NumMethods(), 138 ArtMethod::Size(pointer_size), 139 ArtMethod::Alignment(pointer_size)); 140} 141 142template<VerifyObjectFlags kVerifyFlags> 143inline ArraySlice<ArtMethod> Class::GetCopiedMethodsSlice(size_t pointer_size) { 144 DCHECK(IsLoaded() || IsErroneous()); 145 DCHECK(ValidPointerSize(pointer_size)) << pointer_size; 146 return GetCopiedMethodsSliceUnchecked(pointer_size); 147} 148 149inline ArraySlice<ArtMethod> Class::GetCopiedMethodsSliceUnchecked(size_t pointer_size) { 150 LengthPrefixedArray<ArtMethod>* methods = GetMethodsPtr(); 151 return ArraySlice<ArtMethod>(methods, 152 GetCopiedMethodsStartOffset(), 153 NumMethods(), 154 ArtMethod::Size(pointer_size), 155 ArtMethod::Alignment(pointer_size)); 156} 157 158inline LengthPrefixedArray<ArtMethod>* Class::GetMethodsPtr() { 159 return reinterpret_cast<LengthPrefixedArray<ArtMethod>*>( 160 static_cast<uintptr_t>(GetField64(OFFSET_OF_OBJECT_MEMBER(Class, methods_)))); 161} 162 163template<VerifyObjectFlags kVerifyFlags> 164inline ArraySlice<ArtMethod> Class::GetMethodsSlice(size_t pointer_size) { 165 DCHECK(IsLoaded() || IsErroneous()); 166 LengthPrefixedArray<ArtMethod>* methods = GetMethodsPtr(); 167 return ArraySlice<ArtMethod>(methods, 168 0, 169 NumMethods(), 170 ArtMethod::Size(pointer_size), 171 ArtMethod::Alignment(pointer_size)); 172} 173 174 175inline uint32_t Class::NumMethods() { 176 LengthPrefixedArray<ArtMethod>* methods = GetMethodsPtr(); 177 return (methods == nullptr) ? 0 : methods->size(); 178} 179 180inline ArtMethod* Class::GetDirectMethodUnchecked(size_t i, size_t pointer_size) { 181 CheckPointerSize(pointer_size); 182 return &GetDirectMethodsSliceUnchecked(pointer_size).At(i); 183} 184 185inline ArtMethod* Class::GetDirectMethod(size_t i, size_t pointer_size) { 186 CheckPointerSize(pointer_size); 187 return &GetDirectMethodsSlice(pointer_size).At(i); 188} 189 190inline void Class::SetMethodsPtr(LengthPrefixedArray<ArtMethod>* new_methods, 191 uint32_t num_direct, 192 uint32_t num_virtual) { 193 DCHECK(GetMethodsPtr() == nullptr); 194 SetMethodsPtrUnchecked(new_methods, num_direct, num_virtual); 195} 196 197 198inline void Class::SetMethodsPtrUnchecked(LengthPrefixedArray<ArtMethod>* new_methods, 199 uint32_t num_direct, 200 uint32_t num_virtual) { 201 DCHECK_LE(num_direct + num_virtual, (new_methods == nullptr) ? 0 : new_methods->size()); 202 SetMethodsPtrInternal(new_methods); 203 SetFieldShort<false>(OFFSET_OF_OBJECT_MEMBER(Class, copied_methods_offset_), 204 dchecked_integral_cast<uint16_t>(num_direct + num_virtual)); 205 SetFieldShort<false>(OFFSET_OF_OBJECT_MEMBER(Class, virtual_methods_offset_), 206 dchecked_integral_cast<uint16_t>(num_direct)); 207} 208 209inline void Class::SetMethodsPtrInternal(LengthPrefixedArray<ArtMethod>* new_methods) { 210 SetField64<false>(OFFSET_OF_OBJECT_MEMBER(Class, methods_), 211 static_cast<uint64_t>(reinterpret_cast<uintptr_t>(new_methods))); 212} 213 214template<VerifyObjectFlags kVerifyFlags> 215inline ArtMethod* Class::GetVirtualMethod(size_t i, size_t pointer_size) { 216 CheckPointerSize(pointer_size); 217 DCHECK(IsResolved<kVerifyFlags>() || IsErroneous<kVerifyFlags>()) 218 << PrettyClass(this) << " status=" << GetStatus(); 219 return GetVirtualMethodUnchecked(i, pointer_size); 220} 221 222inline ArtMethod* Class::GetVirtualMethodDuringLinking(size_t i, size_t pointer_size) { 223 CheckPointerSize(pointer_size); 224 DCHECK(IsLoaded() || IsErroneous()); 225 return GetVirtualMethodUnchecked(i, pointer_size); 226} 227 228inline ArtMethod* Class::GetVirtualMethodUnchecked(size_t i, size_t pointer_size) { 229 CheckPointerSize(pointer_size); 230 return &GetVirtualMethodsSliceUnchecked(pointer_size).At(i); 231} 232 233template<VerifyObjectFlags kVerifyFlags, 234 ReadBarrierOption kReadBarrierOption> 235inline PointerArray* Class::GetVTable() { 236 DCHECK(IsResolved<kVerifyFlags>() || IsErroneous<kVerifyFlags>()); 237 return GetFieldObject<PointerArray, kVerifyFlags, kReadBarrierOption>( 238 OFFSET_OF_OBJECT_MEMBER(Class, vtable_)); 239} 240 241inline PointerArray* Class::GetVTableDuringLinking() { 242 DCHECK(IsLoaded() || IsErroneous()); 243 return GetFieldObject<PointerArray>(OFFSET_OF_OBJECT_MEMBER(Class, vtable_)); 244} 245 246inline void Class::SetVTable(PointerArray* new_vtable) { 247 SetFieldObject<false>(OFFSET_OF_OBJECT_MEMBER(Class, vtable_), new_vtable); 248} 249 250inline bool Class::HasVTable() { 251 return GetVTable() != nullptr || ShouldHaveEmbeddedVTable(); 252} 253 254inline int32_t Class::GetVTableLength() { 255 if (ShouldHaveEmbeddedVTable()) { 256 return GetEmbeddedVTableLength(); 257 } 258 return GetVTable() != nullptr ? GetVTable()->GetLength() : 0; 259} 260 261inline ArtMethod* Class::GetVTableEntry(uint32_t i, size_t pointer_size) { 262 if (ShouldHaveEmbeddedVTable()) { 263 return GetEmbeddedVTableEntry(i, pointer_size); 264 } 265 auto* vtable = GetVTable(); 266 DCHECK(vtable != nullptr); 267 return vtable->GetElementPtrSize<ArtMethod*>(i, pointer_size); 268} 269 270inline int32_t Class::GetEmbeddedVTableLength() { 271 return GetField32(MemberOffset(EmbeddedVTableLengthOffset())); 272} 273 274inline void Class::SetEmbeddedVTableLength(int32_t len) { 275 SetField32<false>(MemberOffset(EmbeddedVTableLengthOffset()), len); 276} 277 278inline ImTable* Class::GetImt(size_t pointer_size) { 279 return GetFieldPtrWithSize<ImTable*>(MemberOffset(ImtPtrOffset(pointer_size)), pointer_size); 280} 281 282inline void Class::SetImt(ImTable* imt, size_t pointer_size) { 283 return SetFieldPtrWithSize<false>(MemberOffset(ImtPtrOffset(pointer_size)), imt, pointer_size); 284} 285 286inline MemberOffset Class::EmbeddedVTableEntryOffset(uint32_t i, size_t pointer_size) { 287 return MemberOffset( 288 EmbeddedVTableOffset(pointer_size).Uint32Value() + i * VTableEntrySize(pointer_size)); 289} 290 291inline ArtMethod* Class::GetEmbeddedVTableEntry(uint32_t i, size_t pointer_size) { 292 return GetFieldPtrWithSize<ArtMethod*>(EmbeddedVTableEntryOffset(i, pointer_size), pointer_size); 293} 294 295inline void Class::SetEmbeddedVTableEntryUnchecked( 296 uint32_t i, ArtMethod* method, size_t pointer_size) { 297 SetFieldPtrWithSize<false>(EmbeddedVTableEntryOffset(i, pointer_size), method, pointer_size); 298} 299 300inline void Class::SetEmbeddedVTableEntry(uint32_t i, ArtMethod* method, size_t pointer_size) { 301 auto* vtable = GetVTableDuringLinking(); 302 CHECK_EQ(method, vtable->GetElementPtrSize<ArtMethod*>(i, pointer_size)); 303 SetEmbeddedVTableEntryUnchecked(i, method, pointer_size); 304} 305 306inline bool Class::Implements(Class* klass) { 307 DCHECK(klass != nullptr); 308 DCHECK(klass->IsInterface()) << PrettyClass(this); 309 // All interfaces implemented directly and by our superclass, and 310 // recursively all super-interfaces of those interfaces, are listed 311 // in iftable_, so we can just do a linear scan through that. 312 int32_t iftable_count = GetIfTableCount(); 313 IfTable* iftable = GetIfTable(); 314 for (int32_t i = 0; i < iftable_count; i++) { 315 if (iftable->GetInterface(i) == klass) { 316 return true; 317 } 318 } 319 return false; 320} 321 322// Determine whether "this" is assignable from "src", where both of these 323// are array classes. 324// 325// Consider an array class, e.g. Y[][], where Y is a subclass of X. 326// Y[][] = Y[][] --> true (identity) 327// X[][] = Y[][] --> true (element superclass) 328// Y = Y[][] --> false 329// Y[] = Y[][] --> false 330// Object = Y[][] --> true (everything is an object) 331// Object[] = Y[][] --> true 332// Object[][] = Y[][] --> true 333// Object[][][] = Y[][] --> false (too many []s) 334// Serializable = Y[][] --> true (all arrays are Serializable) 335// Serializable[] = Y[][] --> true 336// Serializable[][] = Y[][] --> false (unless Y is Serializable) 337// 338// Don't forget about primitive types. 339// Object[] = int[] --> false 340// 341inline bool Class::IsArrayAssignableFromArray(Class* src) { 342 DCHECK(IsArrayClass()) << PrettyClass(this); 343 DCHECK(src->IsArrayClass()) << PrettyClass(src); 344 return GetComponentType()->IsAssignableFrom(src->GetComponentType()); 345} 346 347inline bool Class::IsAssignableFromArray(Class* src) { 348 DCHECK(!IsInterface()) << PrettyClass(this); // handled first in IsAssignableFrom 349 DCHECK(src->IsArrayClass()) << PrettyClass(src); 350 if (!IsArrayClass()) { 351 // If "this" is not also an array, it must be Object. 352 // src's super should be java_lang_Object, since it is an array. 353 Class* java_lang_Object = src->GetSuperClass(); 354 DCHECK(java_lang_Object != nullptr) << PrettyClass(src); 355 DCHECK(java_lang_Object->GetSuperClass() == nullptr) << PrettyClass(src); 356 return this == java_lang_Object; 357 } 358 return IsArrayAssignableFromArray(src); 359} 360 361template <bool throw_on_failure, bool use_referrers_cache> 362inline bool Class::ResolvedFieldAccessTest(Class* access_to, ArtField* field, 363 uint32_t field_idx, DexCache* dex_cache) { 364 DCHECK_EQ(use_referrers_cache, dex_cache == nullptr); 365 if (UNLIKELY(!this->CanAccess(access_to))) { 366 // The referrer class can't access the field's declaring class but may still be able 367 // to access the field if the FieldId specifies an accessible subclass of the declaring 368 // class rather than the declaring class itself. 369 DexCache* referrer_dex_cache = use_referrers_cache ? this->GetDexCache() : dex_cache; 370 uint32_t class_idx = referrer_dex_cache->GetDexFile()->GetFieldId(field_idx).class_idx_; 371 // The referenced class has already been resolved with the field, but may not be in the dex 372 // cache. Using ResolveType here without handles in the caller should be safe since there 373 // should be no thread suspension due to the class being resolved. 374 // TODO: Clean this up to use handles in the caller. 375 Class* dex_access_to; 376 { 377 StackHandleScope<2> hs(Thread::Current()); 378 Handle<mirror::DexCache> h_dex_cache(hs.NewHandle(referrer_dex_cache)); 379 Handle<mirror::ClassLoader> h_class_loader(hs.NewHandle(access_to->GetClassLoader())); 380 dex_access_to = Runtime::Current()->GetClassLinker()->ResolveType( 381 *referrer_dex_cache->GetDexFile(), 382 class_idx, 383 h_dex_cache, 384 h_class_loader); 385 } 386 DCHECK(dex_access_to != nullptr); 387 if (UNLIKELY(!this->CanAccess(dex_access_to))) { 388 if (throw_on_failure) { 389 ThrowIllegalAccessErrorClass(this, dex_access_to); 390 } 391 return false; 392 } 393 } 394 if (LIKELY(this->CanAccessMember(access_to, field->GetAccessFlags()))) { 395 return true; 396 } 397 if (throw_on_failure) { 398 ThrowIllegalAccessErrorField(this, field); 399 } 400 return false; 401} 402 403template <bool throw_on_failure, bool use_referrers_cache, InvokeType throw_invoke_type> 404inline bool Class::ResolvedMethodAccessTest(Class* access_to, ArtMethod* method, 405 uint32_t method_idx, DexCache* dex_cache) { 406 static_assert(throw_on_failure || throw_invoke_type == kStatic, "Non-default throw invoke type"); 407 DCHECK_EQ(use_referrers_cache, dex_cache == nullptr); 408 if (UNLIKELY(!this->CanAccess(access_to))) { 409 // The referrer class can't access the method's declaring class but may still be able 410 // to access the method if the MethodId specifies an accessible subclass of the declaring 411 // class rather than the declaring class itself. 412 DexCache* referrer_dex_cache = use_referrers_cache ? this->GetDexCache() : dex_cache; 413 uint32_t class_idx = referrer_dex_cache->GetDexFile()->GetMethodId(method_idx).class_idx_; 414 // The referenced class has already been resolved with the method, but may not be in the dex 415 // cache. Using ResolveType here without handles in the caller should be safe since there 416 // should be no thread suspension due to the class being resolved. 417 // TODO: Clean this up to use handles in the caller. 418 Class* dex_access_to; 419 { 420 StackHandleScope<2> hs(Thread::Current()); 421 Handle<mirror::DexCache> h_dex_cache(hs.NewHandle(referrer_dex_cache)); 422 Handle<mirror::ClassLoader> h_class_loader(hs.NewHandle(access_to->GetClassLoader())); 423 dex_access_to = Runtime::Current()->GetClassLinker()->ResolveType( 424 *referrer_dex_cache->GetDexFile(), 425 class_idx, 426 h_dex_cache, 427 h_class_loader); 428 } 429 DCHECK(dex_access_to != nullptr); 430 if (UNLIKELY(!this->CanAccess(dex_access_to))) { 431 if (throw_on_failure) { 432 ThrowIllegalAccessErrorClassForMethodDispatch(this, dex_access_to, 433 method, throw_invoke_type); 434 } 435 return false; 436 } 437 } 438 if (LIKELY(this->CanAccessMember(access_to, method->GetAccessFlags()))) { 439 return true; 440 } 441 if (throw_on_failure) { 442 ThrowIllegalAccessErrorMethod(this, method); 443 } 444 return false; 445} 446 447inline bool Class::CanAccessResolvedField(Class* access_to, ArtField* field, 448 DexCache* dex_cache, uint32_t field_idx) { 449 return ResolvedFieldAccessTest<false, false>(access_to, field, field_idx, dex_cache); 450} 451 452inline bool Class::CheckResolvedFieldAccess(Class* access_to, ArtField* field, 453 uint32_t field_idx) { 454 return ResolvedFieldAccessTest<true, true>(access_to, field, field_idx, nullptr); 455} 456 457inline bool Class::CanAccessResolvedMethod(Class* access_to, ArtMethod* method, 458 DexCache* dex_cache, uint32_t method_idx) { 459 return ResolvedMethodAccessTest<false, false, kStatic>(access_to, method, method_idx, dex_cache); 460} 461 462template <InvokeType throw_invoke_type> 463inline bool Class::CheckResolvedMethodAccess(Class* access_to, ArtMethod* method, 464 uint32_t method_idx) { 465 return ResolvedMethodAccessTest<true, true, throw_invoke_type>(access_to, method, method_idx, 466 nullptr); 467} 468 469inline bool Class::IsSubClass(Class* klass) { 470 DCHECK(!IsInterface()) << PrettyClass(this); 471 DCHECK(!IsArrayClass()) << PrettyClass(this); 472 Class* current = this; 473 do { 474 if (current == klass) { 475 return true; 476 } 477 current = current->GetSuperClass(); 478 } while (current != nullptr); 479 return false; 480} 481 482inline ArtMethod* Class::FindVirtualMethodForInterface(ArtMethod* method, size_t pointer_size) { 483 Class* declaring_class = method->GetDeclaringClass(); 484 DCHECK(declaring_class != nullptr) << PrettyClass(this); 485 DCHECK(declaring_class->IsInterface()) << PrettyMethod(method); 486 // TODO cache to improve lookup speed 487 const int32_t iftable_count = GetIfTableCount(); 488 IfTable* iftable = GetIfTable(); 489 for (int32_t i = 0; i < iftable_count; i++) { 490 if (iftable->GetInterface(i) == declaring_class) { 491 return iftable->GetMethodArray(i)->GetElementPtrSize<ArtMethod*>( 492 method->GetMethodIndex(), pointer_size); 493 } 494 } 495 return nullptr; 496} 497 498inline ArtMethod* Class::FindVirtualMethodForVirtual(ArtMethod* method, size_t pointer_size) { 499 // Only miranda or default methods may come from interfaces and be used as a virtual. 500 DCHECK(!method->GetDeclaringClass()->IsInterface() || method->IsDefault() || method->IsMiranda()); 501 // The argument method may from a super class. 502 // Use the index to a potentially overridden one for this instance's class. 503 return GetVTableEntry(method->GetMethodIndex(), pointer_size); 504} 505 506inline ArtMethod* Class::FindVirtualMethodForSuper(ArtMethod* method, size_t pointer_size) { 507 DCHECK(!method->GetDeclaringClass()->IsInterface()); 508 return GetSuperClass()->GetVTableEntry(method->GetMethodIndex(), pointer_size); 509} 510 511inline ArtMethod* Class::FindVirtualMethodForVirtualOrInterface(ArtMethod* method, 512 size_t pointer_size) { 513 if (method->IsDirect()) { 514 return method; 515 } 516 if (method->GetDeclaringClass()->IsInterface() && !method->IsCopied()) { 517 return FindVirtualMethodForInterface(method, pointer_size); 518 } 519 return FindVirtualMethodForVirtual(method, pointer_size); 520} 521 522template<VerifyObjectFlags kVerifyFlags, 523 ReadBarrierOption kReadBarrierOption> 524inline IfTable* Class::GetIfTable() { 525 return GetFieldObject<IfTable, kVerifyFlags, kReadBarrierOption>( 526 OFFSET_OF_OBJECT_MEMBER(Class, iftable_)); 527} 528 529inline int32_t Class::GetIfTableCount() { 530 IfTable* iftable = GetIfTable(); 531 if (iftable == nullptr) { 532 return 0; 533 } 534 return iftable->Count(); 535} 536 537inline void Class::SetIfTable(IfTable* new_iftable) { 538 SetFieldObject<false>(OFFSET_OF_OBJECT_MEMBER(Class, iftable_), new_iftable); 539} 540 541inline LengthPrefixedArray<ArtField>* Class::GetIFieldsPtr() { 542 DCHECK(IsLoaded() || IsErroneous()) << GetStatus(); 543 return GetFieldPtr<LengthPrefixedArray<ArtField>*>(OFFSET_OF_OBJECT_MEMBER(Class, ifields_)); 544} 545 546template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption> 547inline MemberOffset Class::GetFirstReferenceInstanceFieldOffset() { 548 Class* super_class = GetSuperClass<kVerifyFlags, kReadBarrierOption>(); 549 return (super_class != nullptr) 550 ? MemberOffset(RoundUp(super_class->GetObjectSize(), 551 sizeof(mirror::HeapReference<mirror::Object>))) 552 : ClassOffset(); 553} 554 555template <VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption> 556inline MemberOffset Class::GetFirstReferenceStaticFieldOffset(size_t pointer_size) { 557 DCHECK(IsResolved()); 558 uint32_t base = sizeof(mirror::Class); // Static fields come after the class. 559 if (ShouldHaveEmbeddedVTable<kVerifyFlags, kReadBarrierOption>()) { 560 // Static fields come after the embedded tables. 561 base = mirror::Class::ComputeClassSize( 562 true, GetEmbeddedVTableLength(), 0, 0, 0, 0, 0, pointer_size); 563 } 564 return MemberOffset(base); 565} 566 567inline MemberOffset Class::GetFirstReferenceStaticFieldOffsetDuringLinking(size_t pointer_size) { 568 DCHECK(IsLoaded()); 569 uint32_t base = sizeof(mirror::Class); // Static fields come after the class. 570 if (ShouldHaveEmbeddedVTable()) { 571 // Static fields come after the embedded tables. 572 base = mirror::Class::ComputeClassSize(true, GetVTableDuringLinking()->GetLength(), 573 0, 0, 0, 0, 0, pointer_size); 574 } 575 return MemberOffset(base); 576} 577 578inline void Class::SetIFieldsPtr(LengthPrefixedArray<ArtField>* new_ifields) { 579 DCHECK(GetIFieldsPtrUnchecked() == nullptr); 580 return SetFieldPtr<false>(OFFSET_OF_OBJECT_MEMBER(Class, ifields_), new_ifields); 581} 582 583inline void Class::SetIFieldsPtrUnchecked(LengthPrefixedArray<ArtField>* new_ifields) { 584 SetFieldPtr<false, true, kVerifyNone>(OFFSET_OF_OBJECT_MEMBER(Class, ifields_), new_ifields); 585} 586 587inline LengthPrefixedArray<ArtField>* Class::GetSFieldsPtrUnchecked() { 588 return GetFieldPtr<LengthPrefixedArray<ArtField>*>(OFFSET_OF_OBJECT_MEMBER(Class, sfields_)); 589} 590 591inline LengthPrefixedArray<ArtField>* Class::GetIFieldsPtrUnchecked() { 592 return GetFieldPtr<LengthPrefixedArray<ArtField>*>(OFFSET_OF_OBJECT_MEMBER(Class, ifields_)); 593} 594 595inline LengthPrefixedArray<ArtField>* Class::GetSFieldsPtr() { 596 DCHECK(IsLoaded() || IsErroneous()) << GetStatus(); 597 return GetSFieldsPtrUnchecked(); 598} 599 600inline void Class::SetSFieldsPtr(LengthPrefixedArray<ArtField>* new_sfields) { 601 DCHECK((IsRetired() && new_sfields == nullptr) || 602 GetFieldPtr<ArtField*>(OFFSET_OF_OBJECT_MEMBER(Class, sfields_)) == nullptr); 603 SetFieldPtr<false>(OFFSET_OF_OBJECT_MEMBER(Class, sfields_), new_sfields); 604} 605 606inline void Class::SetSFieldsPtrUnchecked(LengthPrefixedArray<ArtField>* new_sfields) { 607 SetFieldPtr<false, true, kVerifyNone>(OFFSET_OF_OBJECT_MEMBER(Class, sfields_), new_sfields); 608} 609 610inline ArtField* Class::GetStaticField(uint32_t i) { 611 return &GetSFieldsPtr()->At(i); 612} 613 614inline ArtField* Class::GetInstanceField(uint32_t i) { 615 return &GetIFieldsPtr()->At(i); 616} 617 618template<VerifyObjectFlags kVerifyFlags> 619inline uint32_t Class::GetReferenceInstanceOffsets() { 620 DCHECK(IsResolved<kVerifyFlags>() || IsErroneous<kVerifyFlags>()); 621 return GetField32<kVerifyFlags>(OFFSET_OF_OBJECT_MEMBER(Class, reference_instance_offsets_)); 622} 623 624inline void Class::SetClinitThreadId(pid_t new_clinit_thread_id) { 625 if (Runtime::Current()->IsActiveTransaction()) { 626 SetField32<true>(OFFSET_OF_OBJECT_MEMBER(Class, clinit_thread_id_), new_clinit_thread_id); 627 } else { 628 SetField32<false>(OFFSET_OF_OBJECT_MEMBER(Class, clinit_thread_id_), new_clinit_thread_id); 629 } 630} 631 632template<VerifyObjectFlags kVerifyFlags> 633inline uint32_t Class::GetAccessFlags() { 634 // Check class is loaded/retired or this is java.lang.String that has a 635 // circularity issue during loading the names of its members 636 DCHECK(IsIdxLoaded<kVerifyFlags>() || IsRetired<kVerifyFlags>() || 637 IsErroneous<static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis)>() || 638 this == String::GetJavaLangString()) 639 << "IsIdxLoaded=" << IsIdxLoaded<kVerifyFlags>() 640 << " IsRetired=" << IsRetired<kVerifyFlags>() 641 << " IsErroneous=" << 642 IsErroneous<static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis)>() 643 << " IsString=" << (this == String::GetJavaLangString()) 644 << " status= " << GetStatus<kVerifyFlags>() 645 << " descriptor=" << PrettyDescriptor(this); 646 return GetField32<kVerifyFlags>(AccessFlagsOffset()); 647} 648 649inline String* Class::GetName() { 650 return GetFieldObject<String>(OFFSET_OF_OBJECT_MEMBER(Class, name_)); 651} 652 653inline void Class::SetName(String* name) { 654 if (Runtime::Current()->IsActiveTransaction()) { 655 SetFieldObject<true>(OFFSET_OF_OBJECT_MEMBER(Class, name_), name); 656 } else { 657 SetFieldObject<false>(OFFSET_OF_OBJECT_MEMBER(Class, name_), name); 658 } 659} 660 661template<VerifyObjectFlags kVerifyFlags> 662inline Primitive::Type Class::GetPrimitiveType() { 663 static_assert(sizeof(Primitive::Type) == sizeof(int32_t), 664 "art::Primitive::Type and int32_t have different sizes."); 665 int32_t v32 = GetField32<kVerifyFlags>(OFFSET_OF_OBJECT_MEMBER(Class, primitive_type_)); 666 Primitive::Type type = static_cast<Primitive::Type>(v32 & 0xFFFF); 667 DCHECK_EQ(static_cast<size_t>(v32 >> 16), Primitive::ComponentSizeShift(type)); 668 return type; 669} 670 671template<VerifyObjectFlags kVerifyFlags> 672inline size_t Class::GetPrimitiveTypeSizeShift() { 673 static_assert(sizeof(Primitive::Type) == sizeof(int32_t), 674 "art::Primitive::Type and int32_t have different sizes."); 675 int32_t v32 = GetField32<kVerifyFlags>(OFFSET_OF_OBJECT_MEMBER(Class, primitive_type_)); 676 size_t size_shift = static_cast<Primitive::Type>(v32 >> 16); 677 DCHECK_EQ(size_shift, Primitive::ComponentSizeShift(static_cast<Primitive::Type>(v32 & 0xFFFF))); 678 return size_shift; 679} 680 681inline void Class::CheckObjectAlloc() { 682 DCHECK(!IsArrayClass()) 683 << PrettyClass(this) 684 << "A array shouldn't be allocated through this " 685 << "as it requires a pre-fence visitor that sets the class size."; 686 DCHECK(!IsClassClass()) 687 << PrettyClass(this) 688 << "A class object shouldn't be allocated through this " 689 << "as it requires a pre-fence visitor that sets the class size."; 690 DCHECK(!IsStringClass()) 691 << PrettyClass(this) 692 << "A string shouldn't be allocated through this " 693 << "as it requires a pre-fence visitor that sets the class size."; 694 DCHECK(IsInstantiable()) << PrettyClass(this); 695 // TODO: decide whether we want this check. It currently fails during bootstrap. 696 // DCHECK(!Runtime::Current()->IsStarted() || IsInitializing()) << PrettyClass(this); 697 DCHECK_GE(this->object_size_, sizeof(Object)); 698} 699 700template<bool kIsInstrumented, bool kCheckAddFinalizer> 701inline Object* Class::Alloc(Thread* self, gc::AllocatorType allocator_type) { 702 CheckObjectAlloc(); 703 gc::Heap* heap = Runtime::Current()->GetHeap(); 704 const bool add_finalizer = kCheckAddFinalizer && IsFinalizable(); 705 if (!kCheckAddFinalizer) { 706 DCHECK(!IsFinalizable()); 707 } 708 mirror::Object* obj = 709 heap->AllocObjectWithAllocator<kIsInstrumented, false>(self, this, this->object_size_, 710 allocator_type, VoidFunctor()); 711 if (add_finalizer && LIKELY(obj != nullptr)) { 712 heap->AddFinalizerReference(self, &obj); 713 if (UNLIKELY(self->IsExceptionPending())) { 714 // Failed to allocate finalizer reference, it means that the whole allocation failed. 715 obj = nullptr; 716 } 717 } 718 return obj; 719} 720 721inline Object* Class::AllocObject(Thread* self) { 722 return Alloc<true>(self, Runtime::Current()->GetHeap()->GetCurrentAllocator()); 723} 724 725inline Object* Class::AllocNonMovableObject(Thread* self) { 726 return Alloc<true>(self, Runtime::Current()->GetHeap()->GetCurrentNonMovingAllocator()); 727} 728 729inline uint32_t Class::ComputeClassSize(bool has_embedded_vtable, 730 uint32_t num_vtable_entries, 731 uint32_t num_8bit_static_fields, 732 uint32_t num_16bit_static_fields, 733 uint32_t num_32bit_static_fields, 734 uint32_t num_64bit_static_fields, 735 uint32_t num_ref_static_fields, 736 size_t pointer_size) { 737 // Space used by java.lang.Class and its instance fields. 738 uint32_t size = sizeof(Class); 739 // Space used by embedded tables. 740 if (has_embedded_vtable) { 741 size = RoundUp(size + sizeof(uint32_t), pointer_size); 742 size += pointer_size; // size of pointer to IMT 743 size += num_vtable_entries * VTableEntrySize(pointer_size); 744 } 745 746 // Space used by reference statics. 747 size += num_ref_static_fields * sizeof(HeapReference<Object>); 748 if (!IsAligned<8>(size) && num_64bit_static_fields > 0) { 749 uint32_t gap = 8 - (size & 0x7); 750 size += gap; // will be padded 751 // Shuffle 4-byte fields forward. 752 while (gap >= sizeof(uint32_t) && num_32bit_static_fields != 0) { 753 --num_32bit_static_fields; 754 gap -= sizeof(uint32_t); 755 } 756 // Shuffle 2-byte fields forward. 757 while (gap >= sizeof(uint16_t) && num_16bit_static_fields != 0) { 758 --num_16bit_static_fields; 759 gap -= sizeof(uint16_t); 760 } 761 // Shuffle byte fields forward. 762 while (gap >= sizeof(uint8_t) && num_8bit_static_fields != 0) { 763 --num_8bit_static_fields; 764 gap -= sizeof(uint8_t); 765 } 766 } 767 // Guaranteed to be at least 4 byte aligned. No need for further alignments. 768 // Space used for primitive static fields. 769 size += num_8bit_static_fields * sizeof(uint8_t) + num_16bit_static_fields * sizeof(uint16_t) + 770 num_32bit_static_fields * sizeof(uint32_t) + num_64bit_static_fields * sizeof(uint64_t); 771 return size; 772} 773 774template <bool kVisitNativeRoots, 775 VerifyObjectFlags kVerifyFlags, 776 ReadBarrierOption kReadBarrierOption, 777 typename Visitor> 778inline void Class::VisitReferences(mirror::Class* klass, const Visitor& visitor) { 779 VisitInstanceFieldsReferences<kVerifyFlags, kReadBarrierOption>(klass, visitor); 780 // Right after a class is allocated, but not yet loaded 781 // (kStatusNotReady, see ClassLinker::LoadClass()), GC may find it 782 // and scan it. IsTemp() may call Class::GetAccessFlags() but may 783 // fail in the DCHECK in Class::GetAccessFlags() because the class 784 // status is kStatusNotReady. To avoid it, rely on IsResolved() 785 // only. This is fine because a temp class never goes into the 786 // kStatusResolved state. 787 if (IsResolved<kVerifyFlags>()) { 788 // Temp classes don't ever populate imt/vtable or static fields and they are not even 789 // allocated with the right size for those. Also, unresolved classes don't have fields 790 // linked yet. 791 VisitStaticFieldsReferences<kVerifyFlags, kReadBarrierOption>(this, visitor); 792 } 793 if (kVisitNativeRoots) { 794 // Since this class is reachable, we must also visit the associated roots when we scan it. 795 VisitNativeRoots(visitor, Runtime::Current()->GetClassLinker()->GetImagePointerSize()); 796 } 797} 798 799template<ReadBarrierOption kReadBarrierOption> 800inline bool Class::IsReferenceClass() const { 801 return this == Reference::GetJavaLangRefReference<kReadBarrierOption>(); 802} 803 804template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption> 805inline bool Class::IsClassClass() { 806 Class* java_lang_Class = GetClass<kVerifyFlags, kReadBarrierOption>()-> 807 template GetClass<kVerifyFlags, kReadBarrierOption>(); 808 return this == java_lang_Class; 809} 810 811inline const DexFile& Class::GetDexFile() { 812 return *GetDexCache()->GetDexFile(); 813} 814 815inline bool Class::DescriptorEquals(const char* match) { 816 if (IsArrayClass()) { 817 return match[0] == '[' && GetComponentType()->DescriptorEquals(match + 1); 818 } else if (IsPrimitive()) { 819 return strcmp(Primitive::Descriptor(GetPrimitiveType()), match) == 0; 820 } else if (IsProxyClass()) { 821 return ProxyDescriptorEquals(match); 822 } else { 823 const DexFile& dex_file = GetDexFile(); 824 const DexFile::TypeId& type_id = dex_file.GetTypeId(GetClassDef()->class_idx_); 825 return strcmp(dex_file.GetTypeDescriptor(type_id), match) == 0; 826 } 827} 828 829inline void Class::AssertInitializedOrInitializingInThread(Thread* self) { 830 if (kIsDebugBuild && !IsInitialized()) { 831 CHECK(IsInitializing()) << PrettyClass(this) << " is not initializing: " << GetStatus(); 832 CHECK_EQ(GetClinitThreadId(), self->GetTid()) << PrettyClass(this) 833 << " is initializing in a different thread"; 834 } 835} 836 837inline ObjectArray<Class>* Class::GetInterfaces() { 838 CHECK(IsProxyClass()); 839 // First static field. 840 auto* field = GetStaticField(0); 841 DCHECK_STREQ(field->GetName(), "interfaces"); 842 MemberOffset field_offset = field->GetOffset(); 843 return GetFieldObject<ObjectArray<Class>>(field_offset); 844} 845 846inline ObjectArray<ObjectArray<Class>>* Class::GetThrows() { 847 CHECK(IsProxyClass()); 848 // Second static field. 849 auto* field = GetStaticField(1); 850 DCHECK_STREQ(field->GetName(), "throws"); 851 MemberOffset field_offset = field->GetOffset(); 852 return GetFieldObject<ObjectArray<ObjectArray<Class>>>(field_offset); 853} 854 855inline MemberOffset Class::GetDisableIntrinsicFlagOffset() { 856 CHECK(IsReferenceClass()); 857 // First static field 858 auto* field = GetStaticField(0); 859 DCHECK_STREQ(field->GetName(), "disableIntrinsic"); 860 return field->GetOffset(); 861} 862 863inline MemberOffset Class::GetSlowPathFlagOffset() { 864 CHECK(IsReferenceClass()); 865 // Second static field 866 auto* field = GetStaticField(1); 867 DCHECK_STREQ(field->GetName(), "slowPathEnabled"); 868 return field->GetOffset(); 869} 870 871inline bool Class::GetSlowPathEnabled() { 872 return GetFieldBoolean(GetSlowPathFlagOffset()); 873} 874 875inline void Class::SetSlowPath(bool enabled) { 876 SetFieldBoolean<false, false>(GetSlowPathFlagOffset(), enabled); 877} 878 879inline void Class::InitializeClassVisitor::operator()( 880 mirror::Object* obj, size_t usable_size) const { 881 DCHECK_LE(class_size_, usable_size); 882 // Avoid AsClass as object is not yet in live bitmap or allocation stack. 883 mirror::Class* klass = down_cast<mirror::Class*>(obj); 884 // DCHECK(klass->IsClass()); 885 klass->SetClassSize(class_size_); 886 klass->SetPrimitiveType(Primitive::kPrimNot); // Default to not being primitive. 887 klass->SetDexClassDefIndex(DexFile::kDexNoIndex16); // Default to no valid class def index. 888 klass->SetDexTypeIndex(DexFile::kDexNoIndex16); // Default to no valid type index. 889} 890 891inline void Class::SetAccessFlags(uint32_t new_access_flags) { 892 // Called inside a transaction when setting pre-verified flag during boot image compilation. 893 if (Runtime::Current()->IsActiveTransaction()) { 894 SetField32<true>(AccessFlagsOffset(), new_access_flags); 895 } else { 896 SetField32<false>(AccessFlagsOffset(), new_access_flags); 897 } 898} 899 900inline void Class::SetClassFlags(uint32_t new_flags) { 901 if (Runtime::Current()->IsActiveTransaction()) { 902 SetField32<true>(OFFSET_OF_OBJECT_MEMBER(Class, class_flags_), new_flags); 903 } else { 904 SetField32<false>(OFFSET_OF_OBJECT_MEMBER(Class, class_flags_), new_flags); 905 } 906} 907 908inline uint32_t Class::NumDirectInterfaces() { 909 if (IsPrimitive()) { 910 return 0; 911 } else if (IsArrayClass()) { 912 return 2; 913 } else if (IsProxyClass()) { 914 mirror::ObjectArray<mirror::Class>* interfaces = GetInterfaces(); 915 return interfaces != nullptr ? interfaces->GetLength() : 0; 916 } else { 917 const DexFile::TypeList* interfaces = GetInterfaceTypeList(); 918 if (interfaces == nullptr) { 919 return 0; 920 } else { 921 return interfaces->Size(); 922 } 923 } 924} 925 926inline void Class::SetDexCacheStrings(GcRoot<String>* new_dex_cache_strings) { 927 SetFieldPtr<false>(DexCacheStringsOffset(), new_dex_cache_strings); 928} 929 930inline GcRoot<String>* Class::GetDexCacheStrings() { 931 return GetFieldPtr<GcRoot<String>*>(DexCacheStringsOffset()); 932} 933 934template<class Visitor> 935void mirror::Class::VisitNativeRoots(Visitor& visitor, size_t pointer_size) { 936 for (ArtField& field : GetSFieldsUnchecked()) { 937 // Visit roots first in case the declaring class gets moved. 938 field.VisitRoots(visitor); 939 if (kIsDebugBuild && IsResolved()) { 940 CHECK_EQ(field.GetDeclaringClass(), this) << GetStatus(); 941 } 942 } 943 for (ArtField& field : GetIFieldsUnchecked()) { 944 // Visit roots first in case the declaring class gets moved. 945 field.VisitRoots(visitor); 946 if (kIsDebugBuild && IsResolved()) { 947 CHECK_EQ(field.GetDeclaringClass(), this) << GetStatus(); 948 } 949 } 950 for (ArtMethod& method : GetMethods(pointer_size)) { 951 method.VisitRoots(visitor, pointer_size); 952 } 953} 954 955inline IterationRange<StrideIterator<ArtMethod>> Class::GetDirectMethods(size_t pointer_size) { 956 CheckPointerSize(pointer_size); 957 return GetDirectMethodsSliceUnchecked(pointer_size).AsRange(); 958} 959 960inline IterationRange<StrideIterator<ArtMethod>> Class::GetDeclaredMethods( 961 size_t pointer_size) { 962 CheckPointerSize(pointer_size); 963 return GetDeclaredMethodsSliceUnchecked(pointer_size).AsRange(); 964} 965 966inline IterationRange<StrideIterator<ArtMethod>> Class::GetDeclaredVirtualMethods( 967 size_t pointer_size) { 968 CheckPointerSize(pointer_size); 969 return GetDeclaredVirtualMethodsSliceUnchecked(pointer_size).AsRange(); 970} 971 972inline IterationRange<StrideIterator<ArtMethod>> Class::GetVirtualMethods(size_t pointer_size) { 973 CheckPointerSize(pointer_size); 974 return GetVirtualMethodsSliceUnchecked(pointer_size).AsRange(); 975} 976 977inline IterationRange<StrideIterator<ArtMethod>> Class::GetCopiedMethods(size_t pointer_size) { 978 CheckPointerSize(pointer_size); 979 return GetCopiedMethodsSliceUnchecked(pointer_size).AsRange(); 980} 981 982 983inline IterationRange<StrideIterator<ArtMethod>> Class::GetMethods(size_t pointer_size) { 984 CheckPointerSize(pointer_size); 985 return MakeIterationRangeFromLengthPrefixedArray(GetMethodsPtr(), 986 ArtMethod::Size(pointer_size), 987 ArtMethod::Alignment(pointer_size)); 988} 989 990inline IterationRange<StrideIterator<ArtField>> Class::GetIFields() { 991 return MakeIterationRangeFromLengthPrefixedArray(GetIFieldsPtr()); 992} 993 994inline IterationRange<StrideIterator<ArtField>> Class::GetSFields() { 995 return MakeIterationRangeFromLengthPrefixedArray(GetSFieldsPtr()); 996} 997 998inline IterationRange<StrideIterator<ArtField>> Class::GetIFieldsUnchecked() { 999 return MakeIterationRangeFromLengthPrefixedArray(GetIFieldsPtrUnchecked()); 1000} 1001 1002inline IterationRange<StrideIterator<ArtField>> Class::GetSFieldsUnchecked() { 1003 return MakeIterationRangeFromLengthPrefixedArray(GetSFieldsPtrUnchecked()); 1004} 1005 1006inline MemberOffset Class::EmbeddedVTableOffset(size_t pointer_size) { 1007 CheckPointerSize(pointer_size); 1008 return MemberOffset(ImtPtrOffset(pointer_size).Uint32Value() + pointer_size); 1009} 1010 1011inline void Class::CheckPointerSize(size_t pointer_size) { 1012 DCHECK(ValidPointerSize(pointer_size)) << pointer_size; 1013 DCHECK_EQ(pointer_size, Runtime::Current()->GetClassLinker()->GetImagePointerSize()); 1014} 1015 1016template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption> 1017inline Class* Class::GetComponentType() { 1018 return GetFieldObject<Class, kVerifyFlags, kReadBarrierOption>(ComponentTypeOffset()); 1019} 1020 1021template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption> 1022inline bool Class::IsArrayClass() { 1023 return GetComponentType<kVerifyFlags, kReadBarrierOption>() != nullptr; 1024} 1025 1026inline bool Class::IsAssignableFrom(Class* src) { 1027 DCHECK(src != nullptr); 1028 if (this == src) { 1029 // Can always assign to things of the same type. 1030 return true; 1031 } else if (IsObjectClass()) { 1032 // Can assign any reference to java.lang.Object. 1033 return !src->IsPrimitive(); 1034 } else if (IsInterface()) { 1035 return src->Implements(this); 1036 } else if (src->IsArrayClass()) { 1037 return IsAssignableFromArray(src); 1038 } else { 1039 return !src->IsInterface() && src->IsSubClass(this); 1040 } 1041} 1042 1043inline uint32_t Class::NumDirectMethods() { 1044 return GetVirtualMethodsStartOffset(); 1045} 1046 1047inline uint32_t Class::NumDeclaredVirtualMethods() { 1048 return GetCopiedMethodsStartOffset() - GetVirtualMethodsStartOffset(); 1049} 1050 1051inline uint32_t Class::NumVirtualMethods() { 1052 return NumMethods() - GetVirtualMethodsStartOffset(); 1053} 1054 1055inline uint32_t Class::NumInstanceFields() { 1056 LengthPrefixedArray<ArtField>* arr = GetIFieldsPtrUnchecked(); 1057 return arr != nullptr ? arr->size() : 0u; 1058} 1059 1060inline uint32_t Class::NumStaticFields() { 1061 LengthPrefixedArray<ArtField>* arr = GetSFieldsPtrUnchecked(); 1062 return arr != nullptr ? arr->size() : 0u; 1063} 1064 1065template <VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption, typename Visitor> 1066inline void Class::FixupNativePointers(mirror::Class* dest, 1067 size_t pointer_size, 1068 const Visitor& visitor) { 1069 // Update the field arrays. 1070 LengthPrefixedArray<ArtField>* const sfields = GetSFieldsPtr(); 1071 LengthPrefixedArray<ArtField>* const new_sfields = visitor(sfields); 1072 if (sfields != new_sfields) { 1073 dest->SetSFieldsPtrUnchecked(new_sfields); 1074 } 1075 LengthPrefixedArray<ArtField>* const ifields = GetIFieldsPtr(); 1076 LengthPrefixedArray<ArtField>* const new_ifields = visitor(ifields); 1077 if (ifields != new_ifields) { 1078 dest->SetIFieldsPtrUnchecked(new_ifields); 1079 } 1080 // Update method array. 1081 LengthPrefixedArray<ArtMethod>* methods = GetMethodsPtr(); 1082 LengthPrefixedArray<ArtMethod>* new_methods = visitor(methods); 1083 if (methods != new_methods) { 1084 dest->SetMethodsPtrInternal(new_methods); 1085 } 1086 // Update dex cache strings. 1087 GcRoot<mirror::String>* strings = GetDexCacheStrings(); 1088 GcRoot<mirror::String>* new_strings = visitor(strings); 1089 if (strings != new_strings) { 1090 dest->SetDexCacheStrings(new_strings); 1091 } 1092 // Fix up embedded tables. 1093 if (!IsTemp() && ShouldHaveEmbeddedVTable<kVerifyNone, kReadBarrierOption>()) { 1094 for (int32_t i = 0, count = GetEmbeddedVTableLength(); i < count; ++i) { 1095 ArtMethod* method = GetEmbeddedVTableEntry(i, pointer_size); 1096 ArtMethod* new_method = visitor(method); 1097 if (method != new_method) { 1098 dest->SetEmbeddedVTableEntryUnchecked(i, new_method, pointer_size); 1099 } 1100 } 1101 } 1102 if (!IsTemp() && ShouldHaveImt<kVerifyNone, kReadBarrierOption>()) { 1103 dest->SetImt(visitor(GetImt(pointer_size)), pointer_size); 1104 } 1105} 1106 1107} // namespace mirror 1108} // namespace art 1109 1110#endif // ART_RUNTIME_MIRROR_CLASS_INL_H_ 1111