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