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 40 namespace art { 41 namespace mirror { 42 43 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption> 44 inline 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 50 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption> 51 inline 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 61 inline ClassLoader* Class::GetClassLoader() { 62 return GetFieldObject<ClassLoader>(OFFSET_OF_OBJECT_MEMBER(Class, class_loader_)); 63 } 64 65 template<VerifyObjectFlags kVerifyFlags> 66 inline DexCache* Class::GetDexCache() { 67 return GetFieldObject<DexCache, kVerifyFlags>(OFFSET_OF_OBJECT_MEMBER(Class, dex_cache_)); 68 } 69 70 inline uint32_t Class::GetCopiedMethodsStartOffset() { 71 return GetFieldShort(OFFSET_OF_OBJECT_MEMBER(Class, copied_methods_offset_)); 72 } 73 74 inline uint32_t Class::GetDirectMethodsStartOffset() { 75 return 0; 76 } 77 78 inline uint32_t Class::GetVirtualMethodsStartOffset() { 79 return GetFieldShort(OFFSET_OF_OBJECT_MEMBER(Class, virtual_methods_offset_)); 80 } 81 82 template<VerifyObjectFlags kVerifyFlags> 83 inline 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 89 inline 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 97 template<VerifyObjectFlags kVerifyFlags> 98 inline 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 104 inline 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 } 111 template<VerifyObjectFlags kVerifyFlags> 112 inline 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 118 inline 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 126 template<VerifyObjectFlags kVerifyFlags> 127 inline 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 133 inline 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 142 template<VerifyObjectFlags kVerifyFlags> 143 inline 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 149 inline 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 158 inline LengthPrefixedArray<ArtMethod>* Class::GetMethodsPtr() { 159 return reinterpret_cast<LengthPrefixedArray<ArtMethod>*>( 160 static_cast<uintptr_t>(GetField64(OFFSET_OF_OBJECT_MEMBER(Class, methods_)))); 161 } 162 163 template<VerifyObjectFlags kVerifyFlags> 164 inline 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 175 inline uint32_t Class::NumMethods() { 176 LengthPrefixedArray<ArtMethod>* methods = GetMethodsPtr(); 177 return (methods == nullptr) ? 0 : methods->size(); 178 } 179 180 inline ArtMethod* Class::GetDirectMethodUnchecked(size_t i, size_t pointer_size) { 181 CheckPointerSize(pointer_size); 182 return &GetDirectMethodsSliceUnchecked(pointer_size).At(i); 183 } 184 185 inline ArtMethod* Class::GetDirectMethod(size_t i, size_t pointer_size) { 186 CheckPointerSize(pointer_size); 187 return &GetDirectMethodsSlice(pointer_size).At(i); 188 } 189 190 inline 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 198 inline 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 209 inline 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 214 template<VerifyObjectFlags kVerifyFlags> 215 inline 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 222 inline 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 228 inline ArtMethod* Class::GetVirtualMethodUnchecked(size_t i, size_t pointer_size) { 229 CheckPointerSize(pointer_size); 230 return &GetVirtualMethodsSliceUnchecked(pointer_size).At(i); 231 } 232 233 template<VerifyObjectFlags kVerifyFlags, 234 ReadBarrierOption kReadBarrierOption> 235 inline PointerArray* Class::GetVTable() { 236 DCHECK(IsResolved<kVerifyFlags>() || IsErroneous<kVerifyFlags>()); 237 return GetFieldObject<PointerArray, kVerifyFlags, kReadBarrierOption>( 238 OFFSET_OF_OBJECT_MEMBER(Class, vtable_)); 239 } 240 241 inline PointerArray* Class::GetVTableDuringLinking() { 242 DCHECK(IsLoaded() || IsErroneous()); 243 return GetFieldObject<PointerArray>(OFFSET_OF_OBJECT_MEMBER(Class, vtable_)); 244 } 245 246 inline void Class::SetVTable(PointerArray* new_vtable) { 247 SetFieldObject<false>(OFFSET_OF_OBJECT_MEMBER(Class, vtable_), new_vtable); 248 } 249 250 inline bool Class::HasVTable() { 251 return GetVTable() != nullptr || ShouldHaveEmbeddedVTable(); 252 } 253 254 inline int32_t Class::GetVTableLength() { 255 if (ShouldHaveEmbeddedVTable()) { 256 return GetEmbeddedVTableLength(); 257 } 258 return GetVTable() != nullptr ? GetVTable()->GetLength() : 0; 259 } 260 261 inline 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 270 inline int32_t Class::GetEmbeddedVTableLength() { 271 return GetField32(MemberOffset(EmbeddedVTableLengthOffset())); 272 } 273 274 inline void Class::SetEmbeddedVTableLength(int32_t len) { 275 SetField32<false>(MemberOffset(EmbeddedVTableLengthOffset()), len); 276 } 277 278 inline ImTable* Class::GetImt(size_t pointer_size) { 279 return GetFieldPtrWithSize<ImTable*>(MemberOffset(ImtPtrOffset(pointer_size)), pointer_size); 280 } 281 282 inline void Class::SetImt(ImTable* imt, size_t pointer_size) { 283 return SetFieldPtrWithSize<false>(MemberOffset(ImtPtrOffset(pointer_size)), imt, pointer_size); 284 } 285 286 inline MemberOffset Class::EmbeddedVTableEntryOffset(uint32_t i, size_t pointer_size) { 287 return MemberOffset( 288 EmbeddedVTableOffset(pointer_size).Uint32Value() + i * VTableEntrySize(pointer_size)); 289 } 290 291 inline ArtMethod* Class::GetEmbeddedVTableEntry(uint32_t i, size_t pointer_size) { 292 return GetFieldPtrWithSize<ArtMethod*>(EmbeddedVTableEntryOffset(i, pointer_size), pointer_size); 293 } 294 295 inline 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 300 inline 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 306 inline 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 // 341 inline bool Class::IsArrayAssignableFromArray(Class* src) { 342 DCHECK(IsArrayClass()) << PrettyClass(this); 343 DCHECK(src->IsArrayClass()) << PrettyClass(src); 344 return GetComponentType()->IsAssignableFrom(src->GetComponentType()); 345 } 346 347 inline 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 361 template <bool throw_on_failure, bool use_referrers_cache> 362 inline 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, get it from the dex cache. 372 Class* dex_access_to = referrer_dex_cache->GetResolvedType(class_idx); 373 DCHECK(dex_access_to != nullptr); 374 if (UNLIKELY(!this->CanAccess(dex_access_to))) { 375 if (throw_on_failure) { 376 ThrowIllegalAccessErrorClass(this, dex_access_to); 377 } 378 return false; 379 } 380 } 381 if (LIKELY(this->CanAccessMember(access_to, field->GetAccessFlags()))) { 382 return true; 383 } 384 if (throw_on_failure) { 385 ThrowIllegalAccessErrorField(this, field); 386 } 387 return false; 388 } 389 390 template <bool throw_on_failure, bool use_referrers_cache, InvokeType throw_invoke_type> 391 inline bool Class::ResolvedMethodAccessTest(Class* access_to, ArtMethod* method, 392 uint32_t method_idx, DexCache* dex_cache) { 393 static_assert(throw_on_failure || throw_invoke_type == kStatic, "Non-default throw invoke type"); 394 DCHECK_EQ(use_referrers_cache, dex_cache == nullptr); 395 if (UNLIKELY(!this->CanAccess(access_to))) { 396 // The referrer class can't access the method's declaring class but may still be able 397 // to access the method if the MethodId specifies an accessible subclass of the declaring 398 // class rather than the declaring class itself. 399 DexCache* referrer_dex_cache = use_referrers_cache ? this->GetDexCache() : dex_cache; 400 uint32_t class_idx = referrer_dex_cache->GetDexFile()->GetMethodId(method_idx).class_idx_; 401 // The referenced class has already been resolved with the method, get it from the dex cache. 402 Class* dex_access_to = referrer_dex_cache->GetResolvedType(class_idx); 403 DCHECK(dex_access_to != nullptr); 404 if (UNLIKELY(!this->CanAccess(dex_access_to))) { 405 if (throw_on_failure) { 406 ThrowIllegalAccessErrorClassForMethodDispatch(this, dex_access_to, 407 method, throw_invoke_type); 408 } 409 return false; 410 } 411 } 412 if (LIKELY(this->CanAccessMember(access_to, method->GetAccessFlags()))) { 413 return true; 414 } 415 if (throw_on_failure) { 416 ThrowIllegalAccessErrorMethod(this, method); 417 } 418 return false; 419 } 420 421 inline bool Class::CanAccessResolvedField(Class* access_to, ArtField* field, 422 DexCache* dex_cache, uint32_t field_idx) { 423 return ResolvedFieldAccessTest<false, false>(access_to, field, field_idx, dex_cache); 424 } 425 426 inline bool Class::CheckResolvedFieldAccess(Class* access_to, ArtField* field, 427 uint32_t field_idx) { 428 return ResolvedFieldAccessTest<true, true>(access_to, field, field_idx, nullptr); 429 } 430 431 inline bool Class::CanAccessResolvedMethod(Class* access_to, ArtMethod* method, 432 DexCache* dex_cache, uint32_t method_idx) { 433 return ResolvedMethodAccessTest<false, false, kStatic>(access_to, method, method_idx, dex_cache); 434 } 435 436 template <InvokeType throw_invoke_type> 437 inline bool Class::CheckResolvedMethodAccess(Class* access_to, ArtMethod* method, 438 uint32_t method_idx) { 439 return ResolvedMethodAccessTest<true, true, throw_invoke_type>(access_to, method, method_idx, 440 nullptr); 441 } 442 443 inline bool Class::IsSubClass(Class* klass) { 444 DCHECK(!IsInterface()) << PrettyClass(this); 445 DCHECK(!IsArrayClass()) << PrettyClass(this); 446 Class* current = this; 447 do { 448 if (current == klass) { 449 return true; 450 } 451 current = current->GetSuperClass(); 452 } while (current != nullptr); 453 return false; 454 } 455 456 inline ArtMethod* Class::FindVirtualMethodForInterface(ArtMethod* method, size_t pointer_size) { 457 Class* declaring_class = method->GetDeclaringClass(); 458 DCHECK(declaring_class != nullptr) << PrettyClass(this); 459 DCHECK(declaring_class->IsInterface()) << PrettyMethod(method); 460 // TODO cache to improve lookup speed 461 const int32_t iftable_count = GetIfTableCount(); 462 IfTable* iftable = GetIfTable(); 463 for (int32_t i = 0; i < iftable_count; i++) { 464 if (iftable->GetInterface(i) == declaring_class) { 465 return iftable->GetMethodArray(i)->GetElementPtrSize<ArtMethod*>( 466 method->GetMethodIndex(), pointer_size); 467 } 468 } 469 return nullptr; 470 } 471 472 inline ArtMethod* Class::FindVirtualMethodForVirtual(ArtMethod* method, size_t pointer_size) { 473 // Only miranda or default methods may come from interfaces and be used as a virtual. 474 DCHECK(!method->GetDeclaringClass()->IsInterface() || method->IsDefault() || method->IsMiranda()); 475 // The argument method may from a super class. 476 // Use the index to a potentially overridden one for this instance's class. 477 return GetVTableEntry(method->GetMethodIndex(), pointer_size); 478 } 479 480 inline ArtMethod* Class::FindVirtualMethodForSuper(ArtMethod* method, size_t pointer_size) { 481 DCHECK(!method->GetDeclaringClass()->IsInterface()); 482 return GetSuperClass()->GetVTableEntry(method->GetMethodIndex(), pointer_size); 483 } 484 485 inline ArtMethod* Class::FindVirtualMethodForVirtualOrInterface(ArtMethod* method, 486 size_t pointer_size) { 487 if (method->IsDirect()) { 488 return method; 489 } 490 if (method->GetDeclaringClass()->IsInterface() && !method->IsCopied()) { 491 return FindVirtualMethodForInterface(method, pointer_size); 492 } 493 return FindVirtualMethodForVirtual(method, pointer_size); 494 } 495 496 template<VerifyObjectFlags kVerifyFlags, 497 ReadBarrierOption kReadBarrierOption> 498 inline IfTable* Class::GetIfTable() { 499 return GetFieldObject<IfTable, kVerifyFlags, kReadBarrierOption>( 500 OFFSET_OF_OBJECT_MEMBER(Class, iftable_)); 501 } 502 503 inline int32_t Class::GetIfTableCount() { 504 IfTable* iftable = GetIfTable(); 505 if (iftable == nullptr) { 506 return 0; 507 } 508 return iftable->Count(); 509 } 510 511 inline void Class::SetIfTable(IfTable* new_iftable) { 512 SetFieldObject<false>(OFFSET_OF_OBJECT_MEMBER(Class, iftable_), new_iftable); 513 } 514 515 inline LengthPrefixedArray<ArtField>* Class::GetIFieldsPtr() { 516 DCHECK(IsLoaded() || IsErroneous()) << GetStatus(); 517 return GetFieldPtr<LengthPrefixedArray<ArtField>*>(OFFSET_OF_OBJECT_MEMBER(Class, ifields_)); 518 } 519 520 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption> 521 inline MemberOffset Class::GetFirstReferenceInstanceFieldOffset() { 522 Class* super_class = GetSuperClass<kVerifyFlags, kReadBarrierOption>(); 523 return (super_class != nullptr) 524 ? MemberOffset(RoundUp(super_class->GetObjectSize(), 525 sizeof(mirror::HeapReference<mirror::Object>))) 526 : ClassOffset(); 527 } 528 529 template <VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption> 530 inline MemberOffset Class::GetFirstReferenceStaticFieldOffset(size_t pointer_size) { 531 DCHECK(IsResolved()); 532 uint32_t base = sizeof(mirror::Class); // Static fields come after the class. 533 if (ShouldHaveEmbeddedVTable<kVerifyFlags, kReadBarrierOption>()) { 534 // Static fields come after the embedded tables. 535 base = mirror::Class::ComputeClassSize( 536 true, GetEmbeddedVTableLength(), 0, 0, 0, 0, 0, pointer_size); 537 } 538 return MemberOffset(base); 539 } 540 541 inline MemberOffset Class::GetFirstReferenceStaticFieldOffsetDuringLinking(size_t pointer_size) { 542 DCHECK(IsLoaded()); 543 uint32_t base = sizeof(mirror::Class); // Static fields come after the class. 544 if (ShouldHaveEmbeddedVTable()) { 545 // Static fields come after the embedded tables. 546 base = mirror::Class::ComputeClassSize(true, GetVTableDuringLinking()->GetLength(), 547 0, 0, 0, 0, 0, pointer_size); 548 } 549 return MemberOffset(base); 550 } 551 552 inline void Class::SetIFieldsPtr(LengthPrefixedArray<ArtField>* new_ifields) { 553 DCHECK(GetIFieldsPtrUnchecked() == nullptr); 554 return SetFieldPtr<false>(OFFSET_OF_OBJECT_MEMBER(Class, ifields_), new_ifields); 555 } 556 557 inline void Class::SetIFieldsPtrUnchecked(LengthPrefixedArray<ArtField>* new_ifields) { 558 SetFieldPtr<false, true, kVerifyNone>(OFFSET_OF_OBJECT_MEMBER(Class, ifields_), new_ifields); 559 } 560 561 inline LengthPrefixedArray<ArtField>* Class::GetSFieldsPtrUnchecked() { 562 return GetFieldPtr<LengthPrefixedArray<ArtField>*>(OFFSET_OF_OBJECT_MEMBER(Class, sfields_)); 563 } 564 565 inline LengthPrefixedArray<ArtField>* Class::GetIFieldsPtrUnchecked() { 566 return GetFieldPtr<LengthPrefixedArray<ArtField>*>(OFFSET_OF_OBJECT_MEMBER(Class, ifields_)); 567 } 568 569 inline LengthPrefixedArray<ArtField>* Class::GetSFieldsPtr() { 570 DCHECK(IsLoaded() || IsErroneous()) << GetStatus(); 571 return GetSFieldsPtrUnchecked(); 572 } 573 574 inline void Class::SetSFieldsPtr(LengthPrefixedArray<ArtField>* new_sfields) { 575 DCHECK((IsRetired() && new_sfields == nullptr) || 576 GetFieldPtr<ArtField*>(OFFSET_OF_OBJECT_MEMBER(Class, sfields_)) == nullptr); 577 SetFieldPtr<false>(OFFSET_OF_OBJECT_MEMBER(Class, sfields_), new_sfields); 578 } 579 580 inline void Class::SetSFieldsPtrUnchecked(LengthPrefixedArray<ArtField>* new_sfields) { 581 SetFieldPtr<false, true, kVerifyNone>(OFFSET_OF_OBJECT_MEMBER(Class, sfields_), new_sfields); 582 } 583 584 inline ArtField* Class::GetStaticField(uint32_t i) { 585 return &GetSFieldsPtr()->At(i); 586 } 587 588 inline ArtField* Class::GetInstanceField(uint32_t i) { 589 return &GetIFieldsPtr()->At(i); 590 } 591 592 template<VerifyObjectFlags kVerifyFlags> 593 inline uint32_t Class::GetReferenceInstanceOffsets() { 594 DCHECK(IsResolved<kVerifyFlags>() || IsErroneous<kVerifyFlags>()); 595 return GetField32<kVerifyFlags>(OFFSET_OF_OBJECT_MEMBER(Class, reference_instance_offsets_)); 596 } 597 598 inline void Class::SetClinitThreadId(pid_t new_clinit_thread_id) { 599 if (Runtime::Current()->IsActiveTransaction()) { 600 SetField32<true>(OFFSET_OF_OBJECT_MEMBER(Class, clinit_thread_id_), new_clinit_thread_id); 601 } else { 602 SetField32<false>(OFFSET_OF_OBJECT_MEMBER(Class, clinit_thread_id_), new_clinit_thread_id); 603 } 604 } 605 606 template<VerifyObjectFlags kVerifyFlags> 607 inline uint32_t Class::GetAccessFlags() { 608 // Check class is loaded/retired or this is java.lang.String that has a 609 // circularity issue during loading the names of its members 610 DCHECK(IsIdxLoaded<kVerifyFlags>() || IsRetired<kVerifyFlags>() || 611 IsErroneous<static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis)>() || 612 this == String::GetJavaLangString()) 613 << "IsIdxLoaded=" << IsIdxLoaded<kVerifyFlags>() 614 << " IsRetired=" << IsRetired<kVerifyFlags>() 615 << " IsErroneous=" << 616 IsErroneous<static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis)>() 617 << " IsString=" << (this == String::GetJavaLangString()) 618 << " status= " << GetStatus<kVerifyFlags>() 619 << " descriptor=" << PrettyDescriptor(this); 620 return GetField32<kVerifyFlags>(AccessFlagsOffset()); 621 } 622 623 inline String* Class::GetName() { 624 return GetFieldObject<String>(OFFSET_OF_OBJECT_MEMBER(Class, name_)); 625 } 626 627 inline void Class::SetName(String* name) { 628 if (Runtime::Current()->IsActiveTransaction()) { 629 SetFieldObject<true>(OFFSET_OF_OBJECT_MEMBER(Class, name_), name); 630 } else { 631 SetFieldObject<false>(OFFSET_OF_OBJECT_MEMBER(Class, name_), name); 632 } 633 } 634 635 template<VerifyObjectFlags kVerifyFlags> 636 inline Primitive::Type Class::GetPrimitiveType() { 637 static_assert(sizeof(Primitive::Type) == sizeof(int32_t), 638 "art::Primitive::Type and int32_t have different sizes."); 639 int32_t v32 = GetField32<kVerifyFlags>(OFFSET_OF_OBJECT_MEMBER(Class, primitive_type_)); 640 Primitive::Type type = static_cast<Primitive::Type>(v32 & 0xFFFF); 641 DCHECK_EQ(static_cast<size_t>(v32 >> 16), Primitive::ComponentSizeShift(type)); 642 return type; 643 } 644 645 template<VerifyObjectFlags kVerifyFlags> 646 inline size_t Class::GetPrimitiveTypeSizeShift() { 647 static_assert(sizeof(Primitive::Type) == sizeof(int32_t), 648 "art::Primitive::Type and int32_t have different sizes."); 649 int32_t v32 = GetField32<kVerifyFlags>(OFFSET_OF_OBJECT_MEMBER(Class, primitive_type_)); 650 size_t size_shift = static_cast<Primitive::Type>(v32 >> 16); 651 DCHECK_EQ(size_shift, Primitive::ComponentSizeShift(static_cast<Primitive::Type>(v32 & 0xFFFF))); 652 return size_shift; 653 } 654 655 inline void Class::CheckObjectAlloc() { 656 DCHECK(!IsArrayClass()) 657 << PrettyClass(this) 658 << "A array shouldn't be allocated through this " 659 << "as it requires a pre-fence visitor that sets the class size."; 660 DCHECK(!IsClassClass()) 661 << PrettyClass(this) 662 << "A class object shouldn't be allocated through this " 663 << "as it requires a pre-fence visitor that sets the class size."; 664 DCHECK(!IsStringClass()) 665 << PrettyClass(this) 666 << "A string shouldn't be allocated through this " 667 << "as it requires a pre-fence visitor that sets the class size."; 668 DCHECK(IsInstantiable()) << PrettyClass(this); 669 // TODO: decide whether we want this check. It currently fails during bootstrap. 670 // DCHECK(!Runtime::Current()->IsStarted() || IsInitializing()) << PrettyClass(this); 671 DCHECK_GE(this->object_size_, sizeof(Object)); 672 } 673 674 template<bool kIsInstrumented, bool kCheckAddFinalizer> 675 inline Object* Class::Alloc(Thread* self, gc::AllocatorType allocator_type) { 676 CheckObjectAlloc(); 677 gc::Heap* heap = Runtime::Current()->GetHeap(); 678 const bool add_finalizer = kCheckAddFinalizer && IsFinalizable(); 679 if (!kCheckAddFinalizer) { 680 DCHECK(!IsFinalizable()); 681 } 682 mirror::Object* obj = 683 heap->AllocObjectWithAllocator<kIsInstrumented, false>(self, this, this->object_size_, 684 allocator_type, VoidFunctor()); 685 if (add_finalizer && LIKELY(obj != nullptr)) { 686 heap->AddFinalizerReference(self, &obj); 687 if (UNLIKELY(self->IsExceptionPending())) { 688 // Failed to allocate finalizer reference, it means that the whole allocation failed. 689 obj = nullptr; 690 } 691 } 692 return obj; 693 } 694 695 inline Object* Class::AllocObject(Thread* self) { 696 return Alloc<true>(self, Runtime::Current()->GetHeap()->GetCurrentAllocator()); 697 } 698 699 inline Object* Class::AllocNonMovableObject(Thread* self) { 700 return Alloc<true>(self, Runtime::Current()->GetHeap()->GetCurrentNonMovingAllocator()); 701 } 702 703 inline uint32_t Class::ComputeClassSize(bool has_embedded_vtable, 704 uint32_t num_vtable_entries, 705 uint32_t num_8bit_static_fields, 706 uint32_t num_16bit_static_fields, 707 uint32_t num_32bit_static_fields, 708 uint32_t num_64bit_static_fields, 709 uint32_t num_ref_static_fields, 710 size_t pointer_size) { 711 // Space used by java.lang.Class and its instance fields. 712 uint32_t size = sizeof(Class); 713 // Space used by embedded tables. 714 if (has_embedded_vtable) { 715 size = RoundUp(size + sizeof(uint32_t), pointer_size); 716 size += pointer_size; // size of pointer to IMT 717 size += num_vtable_entries * VTableEntrySize(pointer_size); 718 } 719 720 // Space used by reference statics. 721 size += num_ref_static_fields * sizeof(HeapReference<Object>); 722 if (!IsAligned<8>(size) && num_64bit_static_fields > 0) { 723 uint32_t gap = 8 - (size & 0x7); 724 size += gap; // will be padded 725 // Shuffle 4-byte fields forward. 726 while (gap >= sizeof(uint32_t) && num_32bit_static_fields != 0) { 727 --num_32bit_static_fields; 728 gap -= sizeof(uint32_t); 729 } 730 // Shuffle 2-byte fields forward. 731 while (gap >= sizeof(uint16_t) && num_16bit_static_fields != 0) { 732 --num_16bit_static_fields; 733 gap -= sizeof(uint16_t); 734 } 735 // Shuffle byte fields forward. 736 while (gap >= sizeof(uint8_t) && num_8bit_static_fields != 0) { 737 --num_8bit_static_fields; 738 gap -= sizeof(uint8_t); 739 } 740 } 741 // Guaranteed to be at least 4 byte aligned. No need for further alignments. 742 // Space used for primitive static fields. 743 size += num_8bit_static_fields * sizeof(uint8_t) + num_16bit_static_fields * sizeof(uint16_t) + 744 num_32bit_static_fields * sizeof(uint32_t) + num_64bit_static_fields * sizeof(uint64_t); 745 return size; 746 } 747 748 template <bool kVisitNativeRoots, 749 VerifyObjectFlags kVerifyFlags, 750 ReadBarrierOption kReadBarrierOption, 751 typename Visitor> 752 inline void Class::VisitReferences(mirror::Class* klass, const Visitor& visitor) { 753 VisitInstanceFieldsReferences<kVerifyFlags, kReadBarrierOption>(klass, visitor); 754 // Right after a class is allocated, but not yet loaded 755 // (kStatusNotReady, see ClassLinker::LoadClass()), GC may find it 756 // and scan it. IsTemp() may call Class::GetAccessFlags() but may 757 // fail in the DCHECK in Class::GetAccessFlags() because the class 758 // status is kStatusNotReady. To avoid it, rely on IsResolved() 759 // only. This is fine because a temp class never goes into the 760 // kStatusResolved state. 761 if (IsResolved<kVerifyFlags>()) { 762 // Temp classes don't ever populate imt/vtable or static fields and they are not even 763 // allocated with the right size for those. Also, unresolved classes don't have fields 764 // linked yet. 765 VisitStaticFieldsReferences<kVerifyFlags, kReadBarrierOption>(this, visitor); 766 } 767 if (kVisitNativeRoots) { 768 // Since this class is reachable, we must also visit the associated roots when we scan it. 769 VisitNativeRoots(visitor, Runtime::Current()->GetClassLinker()->GetImagePointerSize()); 770 } 771 } 772 773 template<ReadBarrierOption kReadBarrierOption> 774 inline bool Class::IsReferenceClass() const { 775 return this == Reference::GetJavaLangRefReference<kReadBarrierOption>(); 776 } 777 778 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption> 779 inline bool Class::IsClassClass() { 780 Class* java_lang_Class = GetClass<kVerifyFlags, kReadBarrierOption>()-> 781 template GetClass<kVerifyFlags, kReadBarrierOption>(); 782 return this == java_lang_Class; 783 } 784 785 inline const DexFile& Class::GetDexFile() { 786 return *GetDexCache()->GetDexFile(); 787 } 788 789 inline bool Class::DescriptorEquals(const char* match) { 790 if (IsArrayClass()) { 791 return match[0] == '[' && GetComponentType()->DescriptorEquals(match + 1); 792 } else if (IsPrimitive()) { 793 return strcmp(Primitive::Descriptor(GetPrimitiveType()), match) == 0; 794 } else if (IsProxyClass()) { 795 return ProxyDescriptorEquals(match); 796 } else { 797 const DexFile& dex_file = GetDexFile(); 798 const DexFile::TypeId& type_id = dex_file.GetTypeId(GetClassDef()->class_idx_); 799 return strcmp(dex_file.GetTypeDescriptor(type_id), match) == 0; 800 } 801 } 802 803 inline void Class::AssertInitializedOrInitializingInThread(Thread* self) { 804 if (kIsDebugBuild && !IsInitialized()) { 805 CHECK(IsInitializing()) << PrettyClass(this) << " is not initializing: " << GetStatus(); 806 CHECK_EQ(GetClinitThreadId(), self->GetTid()) << PrettyClass(this) 807 << " is initializing in a different thread"; 808 } 809 } 810 811 inline ObjectArray<Class>* Class::GetInterfaces() { 812 CHECK(IsProxyClass()); 813 // First static field. 814 auto* field = GetStaticField(0); 815 DCHECK_STREQ(field->GetName(), "interfaces"); 816 MemberOffset field_offset = field->GetOffset(); 817 return GetFieldObject<ObjectArray<Class>>(field_offset); 818 } 819 820 inline ObjectArray<ObjectArray<Class>>* Class::GetThrows() { 821 CHECK(IsProxyClass()); 822 // Second static field. 823 auto* field = GetStaticField(1); 824 DCHECK_STREQ(field->GetName(), "throws"); 825 MemberOffset field_offset = field->GetOffset(); 826 return GetFieldObject<ObjectArray<ObjectArray<Class>>>(field_offset); 827 } 828 829 inline MemberOffset Class::GetDisableIntrinsicFlagOffset() { 830 CHECK(IsReferenceClass()); 831 // First static field 832 auto* field = GetStaticField(0); 833 DCHECK_STREQ(field->GetName(), "disableIntrinsic"); 834 return field->GetOffset(); 835 } 836 837 inline MemberOffset Class::GetSlowPathFlagOffset() { 838 CHECK(IsReferenceClass()); 839 // Second static field 840 auto* field = GetStaticField(1); 841 DCHECK_STREQ(field->GetName(), "slowPathEnabled"); 842 return field->GetOffset(); 843 } 844 845 inline bool Class::GetSlowPathEnabled() { 846 return GetFieldBoolean(GetSlowPathFlagOffset()); 847 } 848 849 inline void Class::SetSlowPath(bool enabled) { 850 SetFieldBoolean<false, false>(GetSlowPathFlagOffset(), enabled); 851 } 852 853 inline void Class::InitializeClassVisitor::operator()( 854 mirror::Object* obj, size_t usable_size) const { 855 DCHECK_LE(class_size_, usable_size); 856 // Avoid AsClass as object is not yet in live bitmap or allocation stack. 857 mirror::Class* klass = down_cast<mirror::Class*>(obj); 858 // DCHECK(klass->IsClass()); 859 klass->SetClassSize(class_size_); 860 klass->SetPrimitiveType(Primitive::kPrimNot); // Default to not being primitive. 861 klass->SetDexClassDefIndex(DexFile::kDexNoIndex16); // Default to no valid class def index. 862 klass->SetDexTypeIndex(DexFile::kDexNoIndex16); // Default to no valid type index. 863 } 864 865 inline void Class::SetAccessFlags(uint32_t new_access_flags) { 866 // Called inside a transaction when setting pre-verified flag during boot image compilation. 867 if (Runtime::Current()->IsActiveTransaction()) { 868 SetField32<true>(AccessFlagsOffset(), new_access_flags); 869 } else { 870 SetField32<false>(AccessFlagsOffset(), new_access_flags); 871 } 872 } 873 874 inline void Class::SetClassFlags(uint32_t new_flags) { 875 if (Runtime::Current()->IsActiveTransaction()) { 876 SetField32<true>(OFFSET_OF_OBJECT_MEMBER(Class, class_flags_), new_flags); 877 } else { 878 SetField32<false>(OFFSET_OF_OBJECT_MEMBER(Class, class_flags_), new_flags); 879 } 880 } 881 882 inline uint32_t Class::NumDirectInterfaces() { 883 if (IsPrimitive()) { 884 return 0; 885 } else if (IsArrayClass()) { 886 return 2; 887 } else if (IsProxyClass()) { 888 mirror::ObjectArray<mirror::Class>* interfaces = GetInterfaces(); 889 return interfaces != nullptr ? interfaces->GetLength() : 0; 890 } else { 891 const DexFile::TypeList* interfaces = GetInterfaceTypeList(); 892 if (interfaces == nullptr) { 893 return 0; 894 } else { 895 return interfaces->Size(); 896 } 897 } 898 } 899 900 inline void Class::SetDexCacheStrings(GcRoot<String>* new_dex_cache_strings) { 901 SetFieldPtr<false>(DexCacheStringsOffset(), new_dex_cache_strings); 902 } 903 904 inline GcRoot<String>* Class::GetDexCacheStrings() { 905 return GetFieldPtr<GcRoot<String>*>(DexCacheStringsOffset()); 906 } 907 908 template<class Visitor> 909 void mirror::Class::VisitNativeRoots(Visitor& visitor, size_t pointer_size) { 910 for (ArtField& field : GetSFieldsUnchecked()) { 911 // Visit roots first in case the declaring class gets moved. 912 field.VisitRoots(visitor); 913 if (kIsDebugBuild && IsResolved()) { 914 CHECK_EQ(field.GetDeclaringClass(), this) << GetStatus(); 915 } 916 } 917 for (ArtField& field : GetIFieldsUnchecked()) { 918 // Visit roots first in case the declaring class gets moved. 919 field.VisitRoots(visitor); 920 if (kIsDebugBuild && IsResolved()) { 921 CHECK_EQ(field.GetDeclaringClass(), this) << GetStatus(); 922 } 923 } 924 for (ArtMethod& method : GetMethods(pointer_size)) { 925 method.VisitRoots(visitor, pointer_size); 926 } 927 } 928 929 inline IterationRange<StrideIterator<ArtMethod>> Class::GetDirectMethods(size_t pointer_size) { 930 CheckPointerSize(pointer_size); 931 return GetDirectMethodsSliceUnchecked(pointer_size).AsRange(); 932 } 933 934 inline IterationRange<StrideIterator<ArtMethod>> Class::GetDeclaredMethods( 935 size_t pointer_size) { 936 CheckPointerSize(pointer_size); 937 return GetDeclaredMethodsSliceUnchecked(pointer_size).AsRange(); 938 } 939 940 inline IterationRange<StrideIterator<ArtMethod>> Class::GetDeclaredVirtualMethods( 941 size_t pointer_size) { 942 CheckPointerSize(pointer_size); 943 return GetDeclaredVirtualMethodsSliceUnchecked(pointer_size).AsRange(); 944 } 945 946 inline IterationRange<StrideIterator<ArtMethod>> Class::GetVirtualMethods(size_t pointer_size) { 947 CheckPointerSize(pointer_size); 948 return GetVirtualMethodsSliceUnchecked(pointer_size).AsRange(); 949 } 950 951 inline IterationRange<StrideIterator<ArtMethod>> Class::GetCopiedMethods(size_t pointer_size) { 952 CheckPointerSize(pointer_size); 953 return GetCopiedMethodsSliceUnchecked(pointer_size).AsRange(); 954 } 955 956 957 inline IterationRange<StrideIterator<ArtMethod>> Class::GetMethods(size_t pointer_size) { 958 CheckPointerSize(pointer_size); 959 return MakeIterationRangeFromLengthPrefixedArray(GetMethodsPtr(), 960 ArtMethod::Size(pointer_size), 961 ArtMethod::Alignment(pointer_size)); 962 } 963 964 inline IterationRange<StrideIterator<ArtField>> Class::GetIFields() { 965 return MakeIterationRangeFromLengthPrefixedArray(GetIFieldsPtr()); 966 } 967 968 inline IterationRange<StrideIterator<ArtField>> Class::GetSFields() { 969 return MakeIterationRangeFromLengthPrefixedArray(GetSFieldsPtr()); 970 } 971 972 inline IterationRange<StrideIterator<ArtField>> Class::GetIFieldsUnchecked() { 973 return MakeIterationRangeFromLengthPrefixedArray(GetIFieldsPtrUnchecked()); 974 } 975 976 inline IterationRange<StrideIterator<ArtField>> Class::GetSFieldsUnchecked() { 977 return MakeIterationRangeFromLengthPrefixedArray(GetSFieldsPtrUnchecked()); 978 } 979 980 inline MemberOffset Class::EmbeddedVTableOffset(size_t pointer_size) { 981 CheckPointerSize(pointer_size); 982 return MemberOffset(ImtPtrOffset(pointer_size).Uint32Value() + pointer_size); 983 } 984 985 inline void Class::CheckPointerSize(size_t pointer_size) { 986 DCHECK(ValidPointerSize(pointer_size)) << pointer_size; 987 DCHECK_EQ(pointer_size, Runtime::Current()->GetClassLinker()->GetImagePointerSize()); 988 } 989 990 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption> 991 inline Class* Class::GetComponentType() { 992 return GetFieldObject<Class, kVerifyFlags, kReadBarrierOption>(ComponentTypeOffset()); 993 } 994 995 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption> 996 inline bool Class::IsArrayClass() { 997 return GetComponentType<kVerifyFlags, kReadBarrierOption>() != nullptr; 998 } 999 1000 inline bool Class::IsAssignableFrom(Class* src) { 1001 DCHECK(src != nullptr); 1002 if (this == src) { 1003 // Can always assign to things of the same type. 1004 return true; 1005 } else if (IsObjectClass()) { 1006 // Can assign any reference to java.lang.Object. 1007 return !src->IsPrimitive(); 1008 } else if (IsInterface()) { 1009 return src->Implements(this); 1010 } else if (src->IsArrayClass()) { 1011 return IsAssignableFromArray(src); 1012 } else { 1013 return !src->IsInterface() && src->IsSubClass(this); 1014 } 1015 } 1016 1017 inline uint32_t Class::NumDirectMethods() { 1018 return GetVirtualMethodsStartOffset(); 1019 } 1020 1021 inline uint32_t Class::NumDeclaredVirtualMethods() { 1022 return GetCopiedMethodsStartOffset() - GetVirtualMethodsStartOffset(); 1023 } 1024 1025 inline uint32_t Class::NumVirtualMethods() { 1026 return NumMethods() - GetVirtualMethodsStartOffset(); 1027 } 1028 1029 inline uint32_t Class::NumInstanceFields() { 1030 LengthPrefixedArray<ArtField>* arr = GetIFieldsPtrUnchecked(); 1031 return arr != nullptr ? arr->size() : 0u; 1032 } 1033 1034 inline uint32_t Class::NumStaticFields() { 1035 LengthPrefixedArray<ArtField>* arr = GetSFieldsPtrUnchecked(); 1036 return arr != nullptr ? arr->size() : 0u; 1037 } 1038 1039 template <VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption, typename Visitor> 1040 inline void Class::FixupNativePointers(mirror::Class* dest, 1041 size_t pointer_size, 1042 const Visitor& visitor) { 1043 // Update the field arrays. 1044 LengthPrefixedArray<ArtField>* const sfields = GetSFieldsPtr(); 1045 LengthPrefixedArray<ArtField>* const new_sfields = visitor(sfields); 1046 if (sfields != new_sfields) { 1047 dest->SetSFieldsPtrUnchecked(new_sfields); 1048 } 1049 LengthPrefixedArray<ArtField>* const ifields = GetIFieldsPtr(); 1050 LengthPrefixedArray<ArtField>* const new_ifields = visitor(ifields); 1051 if (ifields != new_ifields) { 1052 dest->SetIFieldsPtrUnchecked(new_ifields); 1053 } 1054 // Update method array. 1055 LengthPrefixedArray<ArtMethod>* methods = GetMethodsPtr(); 1056 LengthPrefixedArray<ArtMethod>* new_methods = visitor(methods); 1057 if (methods != new_methods) { 1058 dest->SetMethodsPtrInternal(new_methods); 1059 } 1060 // Update dex cache strings. 1061 GcRoot<mirror::String>* strings = GetDexCacheStrings(); 1062 GcRoot<mirror::String>* new_strings = visitor(strings); 1063 if (strings != new_strings) { 1064 dest->SetDexCacheStrings(new_strings); 1065 } 1066 // Fix up embedded tables. 1067 if (!IsTemp() && ShouldHaveEmbeddedVTable<kVerifyNone, kReadBarrierOption>()) { 1068 for (int32_t i = 0, count = GetEmbeddedVTableLength(); i < count; ++i) { 1069 ArtMethod* method = GetEmbeddedVTableEntry(i, pointer_size); 1070 ArtMethod* new_method = visitor(method); 1071 if (method != new_method) { 1072 dest->SetEmbeddedVTableEntryUnchecked(i, new_method, pointer_size); 1073 } 1074 } 1075 } 1076 if (!IsTemp() && ShouldHaveImt<kVerifyNone, kReadBarrierOption>()) { 1077 dest->SetImt(visitor(GetImt(pointer_size)), pointer_size); 1078 } 1079 } 1080 1081 } // namespace mirror 1082 } // namespace art 1083 1084 #endif // ART_RUNTIME_MIRROR_CLASS_INL_H_ 1085