class-inl.h revision da7c650022a974be10e2f00fa07d5109e3d8826f
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 "class_loader.h" 26#include "common_throws.h" 27#include "dex_cache.h" 28#include "dex_file.h" 29#include "gc/heap-inl.h" 30#include "iftable.h" 31#include "object_array-inl.h" 32#include "read_barrier-inl.h" 33#include "reference-inl.h" 34#include "runtime.h" 35#include "string.h" 36#include "utils.h" 37 38namespace art { 39namespace mirror { 40 41template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption> 42inline uint32_t Class::GetObjectSize() { 43 // Note: Extra parentheses to avoid the comma being interpreted as macro parameter separator. 44 DCHECK((!IsVariableSize<kVerifyFlags, kReadBarrierOption>())) << " class=" << PrettyTypeOf(this); 45 return GetField32(ObjectSizeOffset()); 46} 47 48inline Class* Class::GetSuperClass() { 49 // Can only get super class for loaded classes (hack for when runtime is 50 // initializing) 51 DCHECK(IsLoaded() || IsErroneous() || !Runtime::Current()->IsStarted()) << IsLoaded(); 52 return GetFieldObject<Class>(OFFSET_OF_OBJECT_MEMBER(Class, super_class_)); 53} 54 55inline ClassLoader* Class::GetClassLoader() { 56 return GetFieldObject<ClassLoader>(OFFSET_OF_OBJECT_MEMBER(Class, class_loader_)); 57} 58 59template<VerifyObjectFlags kVerifyFlags> 60inline DexCache* Class::GetDexCache() { 61 return GetFieldObject<DexCache, kVerifyFlags>(OFFSET_OF_OBJECT_MEMBER(Class, dex_cache_)); 62} 63 64inline ArtMethod* Class::GetDirectMethodsPtr() { 65 DCHECK(IsLoaded() || IsErroneous()); 66 return GetDirectMethodsPtrUnchecked(); 67} 68 69inline ArtMethod* Class::GetDirectMethodsPtrUnchecked() { 70 return reinterpret_cast<ArtMethod*>(GetField64(OFFSET_OF_OBJECT_MEMBER(Class, direct_methods_))); 71} 72 73inline ArtMethod* Class::GetVirtualMethodsPtrUnchecked() { 74 return reinterpret_cast<ArtMethod*>(GetField64(OFFSET_OF_OBJECT_MEMBER(Class, virtual_methods_))); 75} 76 77inline void Class::SetDirectMethodsPtr(ArtMethod* new_direct_methods) { 78 DCHECK(GetDirectMethodsPtrUnchecked() == nullptr); 79 SetDirectMethodsPtrUnchecked(new_direct_methods); 80} 81 82inline void Class::SetDirectMethodsPtrUnchecked(ArtMethod* new_direct_methods) { 83 SetField64<false>(OFFSET_OF_OBJECT_MEMBER(Class, direct_methods_), 84 reinterpret_cast<uint64_t>(new_direct_methods)); 85} 86 87inline ArtMethod* Class::GetDirectMethodUnchecked(size_t i, size_t pointer_size) { 88 CheckPointerSize(pointer_size); 89 auto* methods = GetDirectMethodsPtrUnchecked(); 90 DCHECK(methods != nullptr); 91 return reinterpret_cast<ArtMethod*>(reinterpret_cast<uintptr_t>(methods) + 92 ArtMethod::ObjectSize(pointer_size) * i); 93} 94 95inline ArtMethod* Class::GetDirectMethod(size_t i, size_t pointer_size) { 96 CheckPointerSize(pointer_size); 97 auto* methods = GetDirectMethodsPtr(); 98 DCHECK(methods != nullptr); 99 return reinterpret_cast<ArtMethod*>(reinterpret_cast<uintptr_t>(methods) + 100 ArtMethod::ObjectSize(pointer_size) * i); 101} 102 103template<VerifyObjectFlags kVerifyFlags> 104inline ArtMethod* Class::GetVirtualMethodsPtr() { 105 DCHECK(IsLoaded<kVerifyFlags>() || IsErroneous<kVerifyFlags>()); 106 return GetVirtualMethodsPtrUnchecked(); 107} 108 109inline void Class::SetVirtualMethodsPtr(ArtMethod* new_virtual_methods) { 110 // TODO: we reassign virtual methods to grow the table for miranda 111 // methods.. they should really just be assigned once. 112 SetField64<false>(OFFSET_OF_OBJECT_MEMBER(Class, virtual_methods_), 113 reinterpret_cast<uint64_t>(new_virtual_methods)); 114} 115 116template<VerifyObjectFlags kVerifyFlags> 117inline ArtMethod* Class::GetVirtualMethod(size_t i, size_t pointer_size) { 118 CheckPointerSize(pointer_size); 119 DCHECK(IsResolved<kVerifyFlags>() || IsErroneous<kVerifyFlags>()) 120 << PrettyClass(this) << " status=" << GetStatus(); 121 return GetVirtualMethodUnchecked(i, pointer_size); 122} 123 124inline ArtMethod* Class::GetVirtualMethodDuringLinking(size_t i, size_t pointer_size) { 125 CheckPointerSize(pointer_size); 126 DCHECK(IsLoaded() || IsErroneous()); 127 return GetVirtualMethodUnchecked(i, pointer_size); 128} 129 130inline ArtMethod* Class::GetVirtualMethodUnchecked(size_t i, size_t pointer_size) { 131 CheckPointerSize(pointer_size); 132 auto* methods = GetVirtualMethodsPtrUnchecked(); 133 DCHECK(methods != nullptr); 134 return reinterpret_cast<ArtMethod*>(reinterpret_cast<uintptr_t>(methods) + 135 ArtMethod::ObjectSize(pointer_size) * i); 136} 137 138inline PointerArray* Class::GetVTable() { 139 DCHECK(IsResolved() || IsErroneous()); 140 return GetFieldObject<PointerArray>(OFFSET_OF_OBJECT_MEMBER(Class, vtable_)); 141} 142 143inline PointerArray* Class::GetVTableDuringLinking() { 144 DCHECK(IsLoaded() || IsErroneous()); 145 return GetFieldObject<PointerArray>(OFFSET_OF_OBJECT_MEMBER(Class, vtable_)); 146} 147 148inline void Class::SetVTable(PointerArray* new_vtable) { 149 SetFieldObject<false>(OFFSET_OF_OBJECT_MEMBER(Class, vtable_), new_vtable); 150} 151 152inline MemberOffset Class::EmbeddedImTableEntryOffset(uint32_t i, size_t pointer_size) { 153 DCHECK_LT(i, kImtSize); 154 return MemberOffset( 155 EmbeddedImTableOffset(pointer_size).Uint32Value() + i * ImTableEntrySize(pointer_size)); 156} 157 158inline ArtMethod* Class::GetEmbeddedImTableEntry(uint32_t i, size_t pointer_size) { 159 DCHECK(ShouldHaveEmbeddedImtAndVTable()); 160 return GetFieldPtrWithSize<ArtMethod*>( 161 EmbeddedImTableEntryOffset(i, pointer_size), pointer_size); 162} 163 164inline void Class::SetEmbeddedImTableEntry(uint32_t i, ArtMethod* method, size_t pointer_size) { 165 DCHECK(ShouldHaveEmbeddedImtAndVTable()); 166 SetFieldPtrWithSize<false>(EmbeddedImTableEntryOffset(i, pointer_size), method, pointer_size); 167} 168 169inline bool Class::HasVTable() { 170 return GetVTable() != nullptr || ShouldHaveEmbeddedImtAndVTable(); 171} 172 173inline int32_t Class::GetVTableLength() { 174 if (ShouldHaveEmbeddedImtAndVTable()) { 175 return GetEmbeddedVTableLength(); 176 } 177 return GetVTable() != nullptr ? GetVTable()->GetLength() : 0; 178} 179 180inline ArtMethod* Class::GetVTableEntry(uint32_t i, size_t pointer_size) { 181 if (ShouldHaveEmbeddedImtAndVTable()) { 182 return GetEmbeddedVTableEntry(i, pointer_size); 183 } 184 auto* vtable = GetVTable(); 185 DCHECK(vtable != nullptr); 186 return vtable->GetElementPtrSize<ArtMethod*>(i, pointer_size); 187} 188 189inline int32_t Class::GetEmbeddedVTableLength() { 190 return GetField32(MemberOffset(EmbeddedVTableLengthOffset())); 191} 192 193inline void Class::SetEmbeddedVTableLength(int32_t len) { 194 SetField32<false>(MemberOffset(EmbeddedVTableLengthOffset()), len); 195} 196 197inline MemberOffset Class::EmbeddedVTableEntryOffset(uint32_t i, size_t pointer_size) { 198 return MemberOffset( 199 EmbeddedVTableOffset(pointer_size).Uint32Value() + i * VTableEntrySize(pointer_size)); 200} 201 202inline ArtMethod* Class::GetEmbeddedVTableEntry(uint32_t i, size_t pointer_size) { 203 return GetFieldPtrWithSize<ArtMethod*>(EmbeddedVTableEntryOffset(i, pointer_size), pointer_size); 204} 205 206inline void Class::SetEmbeddedVTableEntryUnchecked( 207 uint32_t i, ArtMethod* method, size_t pointer_size) { 208 SetFieldPtrWithSize<false>(EmbeddedVTableEntryOffset(i, pointer_size), method, pointer_size); 209} 210 211inline void Class::SetEmbeddedVTableEntry(uint32_t i, ArtMethod* method, size_t pointer_size) { 212 auto* vtable = GetVTableDuringLinking(); 213 CHECK_EQ(method, vtable->GetElementPtrSize<ArtMethod*>(i, pointer_size)); 214 SetEmbeddedVTableEntryUnchecked(i, method, pointer_size); 215} 216 217inline bool Class::Implements(Class* klass) { 218 DCHECK(klass != nullptr); 219 DCHECK(klass->IsInterface()) << PrettyClass(this); 220 // All interfaces implemented directly and by our superclass, and 221 // recursively all super-interfaces of those interfaces, are listed 222 // in iftable_, so we can just do a linear scan through that. 223 int32_t iftable_count = GetIfTableCount(); 224 IfTable* iftable = GetIfTable(); 225 for (int32_t i = 0; i < iftable_count; i++) { 226 if (iftable->GetInterface(i) == klass) { 227 return true; 228 } 229 } 230 return false; 231} 232 233// Determine whether "this" is assignable from "src", where both of these 234// are array classes. 235// 236// Consider an array class, e.g. Y[][], where Y is a subclass of X. 237// Y[][] = Y[][] --> true (identity) 238// X[][] = Y[][] --> true (element superclass) 239// Y = Y[][] --> false 240// Y[] = Y[][] --> false 241// Object = Y[][] --> true (everything is an object) 242// Object[] = Y[][] --> true 243// Object[][] = Y[][] --> true 244// Object[][][] = Y[][] --> false (too many []s) 245// Serializable = Y[][] --> true (all arrays are Serializable) 246// Serializable[] = Y[][] --> true 247// Serializable[][] = Y[][] --> false (unless Y is Serializable) 248// 249// Don't forget about primitive types. 250// Object[] = int[] --> false 251// 252inline bool Class::IsArrayAssignableFromArray(Class* src) { 253 DCHECK(IsArrayClass()) << PrettyClass(this); 254 DCHECK(src->IsArrayClass()) << PrettyClass(src); 255 return GetComponentType()->IsAssignableFrom(src->GetComponentType()); 256} 257 258inline bool Class::IsAssignableFromArray(Class* src) { 259 DCHECK(!IsInterface()) << PrettyClass(this); // handled first in IsAssignableFrom 260 DCHECK(src->IsArrayClass()) << PrettyClass(src); 261 if (!IsArrayClass()) { 262 // If "this" is not also an array, it must be Object. 263 // src's super should be java_lang_Object, since it is an array. 264 Class* java_lang_Object = src->GetSuperClass(); 265 DCHECK(java_lang_Object != nullptr) << PrettyClass(src); 266 DCHECK(java_lang_Object->GetSuperClass() == nullptr) << PrettyClass(src); 267 return this == java_lang_Object; 268 } 269 return IsArrayAssignableFromArray(src); 270} 271 272template <bool throw_on_failure, bool use_referrers_cache> 273inline bool Class::ResolvedFieldAccessTest(Class* access_to, ArtField* field, 274 uint32_t field_idx, DexCache* dex_cache) { 275 DCHECK_EQ(use_referrers_cache, dex_cache == nullptr); 276 if (UNLIKELY(!this->CanAccess(access_to))) { 277 // The referrer class can't access the field's declaring class but may still be able 278 // to access the field if the FieldId specifies an accessible subclass of the declaring 279 // class rather than the declaring class itself. 280 DexCache* referrer_dex_cache = use_referrers_cache ? this->GetDexCache() : dex_cache; 281 uint32_t class_idx = referrer_dex_cache->GetDexFile()->GetFieldId(field_idx).class_idx_; 282 // The referenced class has already been resolved with the field, get it from the dex cache. 283 Class* dex_access_to = referrer_dex_cache->GetResolvedType(class_idx); 284 DCHECK(dex_access_to != nullptr); 285 if (UNLIKELY(!this->CanAccess(dex_access_to))) { 286 if (throw_on_failure) { 287 ThrowIllegalAccessErrorClass(this, dex_access_to); 288 } 289 return false; 290 } 291 DCHECK_EQ(this->CanAccessMember(access_to, field->GetAccessFlags()), 292 this->CanAccessMember(dex_access_to, field->GetAccessFlags())); 293 } 294 if (LIKELY(this->CanAccessMember(access_to, field->GetAccessFlags()))) { 295 return true; 296 } 297 if (throw_on_failure) { 298 ThrowIllegalAccessErrorField(this, field); 299 } 300 return false; 301} 302 303template <bool throw_on_failure, bool use_referrers_cache, InvokeType throw_invoke_type> 304inline bool Class::ResolvedMethodAccessTest(Class* access_to, ArtMethod* method, 305 uint32_t method_idx, DexCache* dex_cache) { 306 static_assert(throw_on_failure || throw_invoke_type == kStatic, "Non-default throw invoke type"); 307 DCHECK_EQ(use_referrers_cache, dex_cache == nullptr); 308 if (UNLIKELY(!this->CanAccess(access_to))) { 309 // The referrer class can't access the method's declaring class but may still be able 310 // to access the method if the MethodId specifies an accessible subclass of the declaring 311 // class rather than the declaring class itself. 312 DexCache* referrer_dex_cache = use_referrers_cache ? this->GetDexCache() : dex_cache; 313 uint32_t class_idx = referrer_dex_cache->GetDexFile()->GetMethodId(method_idx).class_idx_; 314 // The referenced class has already been resolved with the method, get it from the dex cache. 315 Class* dex_access_to = referrer_dex_cache->GetResolvedType(class_idx); 316 DCHECK(dex_access_to != nullptr); 317 if (UNLIKELY(!this->CanAccess(dex_access_to))) { 318 if (throw_on_failure) { 319 ThrowIllegalAccessErrorClassForMethodDispatch(this, dex_access_to, 320 method, throw_invoke_type); 321 } 322 return false; 323 } 324 DCHECK_EQ(this->CanAccessMember(access_to, method->GetAccessFlags()), 325 this->CanAccessMember(dex_access_to, method->GetAccessFlags())); 326 } 327 if (LIKELY(this->CanAccessMember(access_to, method->GetAccessFlags()))) { 328 return true; 329 } 330 if (throw_on_failure) { 331 ThrowIllegalAccessErrorMethod(this, method); 332 } 333 return false; 334} 335 336inline bool Class::CanAccessResolvedField(Class* access_to, ArtField* field, 337 DexCache* dex_cache, uint32_t field_idx) { 338 return ResolvedFieldAccessTest<false, false>(access_to, field, field_idx, dex_cache); 339} 340 341inline bool Class::CheckResolvedFieldAccess(Class* access_to, ArtField* field, 342 uint32_t field_idx) { 343 return ResolvedFieldAccessTest<true, true>(access_to, field, field_idx, nullptr); 344} 345 346inline bool Class::CanAccessResolvedMethod(Class* access_to, ArtMethod* method, 347 DexCache* dex_cache, uint32_t method_idx) { 348 return ResolvedMethodAccessTest<false, false, kStatic>(access_to, method, method_idx, dex_cache); 349} 350 351template <InvokeType throw_invoke_type> 352inline bool Class::CheckResolvedMethodAccess(Class* access_to, ArtMethod* method, 353 uint32_t method_idx) { 354 return ResolvedMethodAccessTest<true, true, throw_invoke_type>(access_to, method, method_idx, 355 nullptr); 356} 357 358inline bool Class::IsSubClass(Class* klass) { 359 DCHECK(!IsInterface()) << PrettyClass(this); 360 DCHECK(!IsArrayClass()) << PrettyClass(this); 361 Class* current = this; 362 do { 363 if (current == klass) { 364 return true; 365 } 366 current = current->GetSuperClass(); 367 } while (current != nullptr); 368 return false; 369} 370 371inline ArtMethod* Class::FindVirtualMethodForInterface(ArtMethod* method, size_t pointer_size) { 372 Class* declaring_class = method->GetDeclaringClass(); 373 DCHECK(declaring_class != nullptr) << PrettyClass(this); 374 DCHECK(declaring_class->IsInterface()) << PrettyMethod(method); 375 // TODO cache to improve lookup speed 376 const int32_t iftable_count = GetIfTableCount(); 377 IfTable* iftable = GetIfTable(); 378 for (int32_t i = 0; i < iftable_count; i++) { 379 if (iftable->GetInterface(i) == declaring_class) { 380 return iftable->GetMethodArray(i)->GetElementPtrSize<ArtMethod*>( 381 method->GetMethodIndex(), pointer_size); 382 } 383 } 384 return nullptr; 385} 386 387inline ArtMethod* Class::FindVirtualMethodForVirtual(ArtMethod* method, size_t pointer_size) { 388 DCHECK(!method->GetDeclaringClass()->IsInterface() || method->IsMiranda()); 389 // The argument method may from a super class. 390 // Use the index to a potentially overridden one for this instance's class. 391 return GetVTableEntry(method->GetMethodIndex(), pointer_size); 392} 393 394inline ArtMethod* Class::FindVirtualMethodForSuper(ArtMethod* method, size_t pointer_size) { 395 DCHECK(!method->GetDeclaringClass()->IsInterface()); 396 return GetSuperClass()->GetVTableEntry(method->GetMethodIndex(), pointer_size); 397} 398 399inline ArtMethod* Class::FindVirtualMethodForVirtualOrInterface(ArtMethod* method, 400 size_t pointer_size) { 401 if (method->IsDirect()) { 402 return method; 403 } 404 if (method->GetDeclaringClass()->IsInterface() && !method->IsMiranda()) { 405 return FindVirtualMethodForInterface(method, pointer_size); 406 } 407 return FindVirtualMethodForVirtual(method, pointer_size); 408} 409 410inline IfTable* Class::GetIfTable() { 411 return GetFieldObject<IfTable>(OFFSET_OF_OBJECT_MEMBER(Class, iftable_)); 412} 413 414inline int32_t Class::GetIfTableCount() { 415 IfTable* iftable = GetIfTable(); 416 if (iftable == nullptr) { 417 return 0; 418 } 419 return iftable->Count(); 420} 421 422inline void Class::SetIfTable(IfTable* new_iftable) { 423 SetFieldObject<false>(OFFSET_OF_OBJECT_MEMBER(Class, iftable_), new_iftable); 424} 425 426inline ArtField* Class::GetIFields() { 427 DCHECK(IsLoaded() || IsErroneous()); 428 return GetFieldPtr<ArtField*>(OFFSET_OF_OBJECT_MEMBER(Class, ifields_)); 429} 430 431inline MemberOffset Class::GetFirstReferenceInstanceFieldOffset() { 432 Class* super_class = GetSuperClass(); 433 return (super_class != nullptr) 434 ? MemberOffset(RoundUp(super_class->GetObjectSize(), 435 sizeof(mirror::HeapReference<mirror::Object>))) 436 : ClassOffset(); 437} 438 439inline MemberOffset Class::GetFirstReferenceStaticFieldOffset(size_t pointer_size) { 440 DCHECK(IsResolved()); 441 uint32_t base = sizeof(mirror::Class); // Static fields come after the class. 442 if (ShouldHaveEmbeddedImtAndVTable()) { 443 // Static fields come after the embedded tables. 444 base = mirror::Class::ComputeClassSize( 445 true, GetEmbeddedVTableLength(), 0, 0, 0, 0, 0, pointer_size); 446 } 447 return MemberOffset(base); 448} 449 450inline MemberOffset Class::GetFirstReferenceStaticFieldOffsetDuringLinking(size_t pointer_size) { 451 DCHECK(IsLoaded()); 452 uint32_t base = sizeof(mirror::Class); // Static fields come after the class. 453 if (ShouldHaveEmbeddedImtAndVTable()) { 454 // Static fields come after the embedded tables. 455 base = mirror::Class::ComputeClassSize(true, GetVTableDuringLinking()->GetLength(), 456 0, 0, 0, 0, 0, pointer_size); 457 } 458 return MemberOffset(base); 459} 460 461inline void Class::SetIFields(ArtField* new_ifields) { 462 DCHECK(GetIFieldsUnchecked() == nullptr); 463 return SetFieldPtr<false>(OFFSET_OF_OBJECT_MEMBER(Class, ifields_), new_ifields); 464} 465 466inline void Class::SetIFieldsUnchecked(ArtField* new_ifields) { 467 SetFieldPtr<false, true, kVerifyNone>(OFFSET_OF_OBJECT_MEMBER(Class, ifields_), new_ifields); 468} 469 470inline ArtField* Class::GetSFieldsUnchecked() { 471 return GetFieldPtr<ArtField*>(OFFSET_OF_OBJECT_MEMBER(Class, sfields_)); 472} 473 474inline ArtField* Class::GetIFieldsUnchecked() { 475 return GetFieldPtr<ArtField*>(OFFSET_OF_OBJECT_MEMBER(Class, ifields_)); 476} 477 478inline ArtField* Class::GetSFields() { 479 DCHECK(IsLoaded() || IsErroneous()) << GetStatus(); 480 return GetSFieldsUnchecked(); 481} 482 483inline void Class::SetSFields(ArtField* new_sfields) { 484 DCHECK((IsRetired() && new_sfields == nullptr) || 485 GetFieldPtr<ArtField*>(OFFSET_OF_OBJECT_MEMBER(Class, sfields_)) == nullptr); 486 SetFieldPtr<false>(OFFSET_OF_OBJECT_MEMBER(Class, sfields_), new_sfields); 487} 488 489inline void Class::SetSFieldsUnchecked(ArtField* new_sfields) { 490 SetFieldPtr<false, true, kVerifyNone>(OFFSET_OF_OBJECT_MEMBER(Class, sfields_), new_sfields); 491} 492 493inline ArtField* Class::GetStaticField(uint32_t i) { 494 DCHECK_LT(i, NumStaticFields()); 495 return &GetSFields()[i]; 496} 497 498inline ArtField* Class::GetInstanceField(uint32_t i) { 499 DCHECK_LT(i, NumInstanceFields()); 500 return &GetIFields()[i]; 501} 502 503template<VerifyObjectFlags kVerifyFlags> 504inline uint32_t Class::GetReferenceInstanceOffsets() { 505 DCHECK(IsResolved<kVerifyFlags>() || IsErroneous<kVerifyFlags>()); 506 return GetField32<kVerifyFlags>(OFFSET_OF_OBJECT_MEMBER(Class, reference_instance_offsets_)); 507} 508 509inline void Class::SetClinitThreadId(pid_t new_clinit_thread_id) { 510 if (Runtime::Current()->IsActiveTransaction()) { 511 SetField32<true>(OFFSET_OF_OBJECT_MEMBER(Class, clinit_thread_id_), new_clinit_thread_id); 512 } else { 513 SetField32<false>(OFFSET_OF_OBJECT_MEMBER(Class, clinit_thread_id_), new_clinit_thread_id); 514 } 515} 516 517inline void Class::SetVerifyErrorClass(Class* klass) { 518 CHECK(klass != nullptr) << PrettyClass(this); 519 if (Runtime::Current()->IsActiveTransaction()) { 520 SetFieldObject<true>(OFFSET_OF_OBJECT_MEMBER(Class, verify_error_class_), klass); 521 } else { 522 SetFieldObject<false>(OFFSET_OF_OBJECT_MEMBER(Class, verify_error_class_), klass); 523 } 524} 525 526template<VerifyObjectFlags kVerifyFlags> 527inline uint32_t Class::GetAccessFlags() { 528 // Check class is loaded/retired or this is java.lang.String that has a 529 // circularity issue during loading the names of its members 530 DCHECK(IsIdxLoaded<kVerifyFlags>() || IsRetired<kVerifyFlags>() || 531 IsErroneous<static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis)>() || 532 this == String::GetJavaLangString()) 533 << "IsIdxLoaded=" << IsIdxLoaded<kVerifyFlags>() 534 << " IsRetired=" << IsRetired<kVerifyFlags>() 535 << " IsErroneous=" << 536 IsErroneous<static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis)>() 537 << " IsString=" << (this == String::GetJavaLangString()) 538 << " descriptor=" << PrettyDescriptor(this); 539 return GetField32<kVerifyFlags>(AccessFlagsOffset()); 540} 541 542inline String* Class::GetName() { 543 return GetFieldObject<String>(OFFSET_OF_OBJECT_MEMBER(Class, name_)); 544} 545inline void Class::SetName(String* name) { 546 if (Runtime::Current()->IsActiveTransaction()) { 547 SetFieldObject<true>(OFFSET_OF_OBJECT_MEMBER(Class, name_), name); 548 } else { 549 SetFieldObject<false>(OFFSET_OF_OBJECT_MEMBER(Class, name_), name); 550 } 551} 552 553template<VerifyObjectFlags kVerifyFlags> 554inline Primitive::Type Class::GetPrimitiveType() { 555 static_assert(sizeof(Primitive::Type) == sizeof(int32_t), 556 "art::Primitive::Type and int32_t have different sizes."); 557 int32_t v32 = GetField32<kVerifyFlags>(OFFSET_OF_OBJECT_MEMBER(Class, primitive_type_)); 558 Primitive::Type type = static_cast<Primitive::Type>(v32 & 0xFFFF); 559 DCHECK_EQ(static_cast<size_t>(v32 >> 16), Primitive::ComponentSizeShift(type)); 560 return type; 561} 562 563template<VerifyObjectFlags kVerifyFlags> 564inline size_t Class::GetPrimitiveTypeSizeShift() { 565 static_assert(sizeof(Primitive::Type) == sizeof(int32_t), 566 "art::Primitive::Type and int32_t have different sizes."); 567 int32_t v32 = GetField32<kVerifyFlags>(OFFSET_OF_OBJECT_MEMBER(Class, primitive_type_)); 568 size_t size_shift = static_cast<Primitive::Type>(v32 >> 16); 569 DCHECK_EQ(size_shift, Primitive::ComponentSizeShift(static_cast<Primitive::Type>(v32 & 0xFFFF))); 570 return size_shift; 571} 572 573inline void Class::CheckObjectAlloc() { 574 DCHECK(!IsArrayClass()) 575 << PrettyClass(this) 576 << "A array shouldn't be allocated through this " 577 << "as it requires a pre-fence visitor that sets the class size."; 578 DCHECK(!IsClassClass()) 579 << PrettyClass(this) 580 << "A class object shouldn't be allocated through this " 581 << "as it requires a pre-fence visitor that sets the class size."; 582 DCHECK(!IsStringClass()) 583 << PrettyClass(this) 584 << "A string shouldn't be allocated through this " 585 << "as it requires a pre-fence visitor that sets the class size."; 586 DCHECK(IsInstantiable()) << PrettyClass(this); 587 // TODO: decide whether we want this check. It currently fails during bootstrap. 588 // DCHECK(!Runtime::Current()->IsStarted() || IsInitializing()) << PrettyClass(this); 589 DCHECK_GE(this->object_size_, sizeof(Object)); 590} 591 592template<bool kIsInstrumented, bool kCheckAddFinalizer> 593inline Object* Class::Alloc(Thread* self, gc::AllocatorType allocator_type) { 594 CheckObjectAlloc(); 595 gc::Heap* heap = Runtime::Current()->GetHeap(); 596 const bool add_finalizer = kCheckAddFinalizer && IsFinalizable(); 597 if (!kCheckAddFinalizer) { 598 DCHECK(!IsFinalizable()); 599 } 600 mirror::Object* obj = 601 heap->AllocObjectWithAllocator<kIsInstrumented, false>(self, this, this->object_size_, 602 allocator_type, VoidFunctor()); 603 if (add_finalizer && LIKELY(obj != nullptr)) { 604 heap->AddFinalizerReference(self, &obj); 605 if (UNLIKELY(self->IsExceptionPending())) { 606 // Failed to allocate finalizer reference, it means that the whole allocation failed. 607 obj = nullptr; 608 } 609 } 610 return obj; 611} 612 613inline Object* Class::AllocObject(Thread* self) { 614 return Alloc<true>(self, Runtime::Current()->GetHeap()->GetCurrentAllocator()); 615} 616 617inline Object* Class::AllocNonMovableObject(Thread* self) { 618 return Alloc<true>(self, Runtime::Current()->GetHeap()->GetCurrentNonMovingAllocator()); 619} 620 621inline uint32_t Class::ComputeClassSize(bool has_embedded_tables, 622 uint32_t num_vtable_entries, 623 uint32_t num_8bit_static_fields, 624 uint32_t num_16bit_static_fields, 625 uint32_t num_32bit_static_fields, 626 uint32_t num_64bit_static_fields, 627 uint32_t num_ref_static_fields, 628 size_t pointer_size) { 629 // Space used by java.lang.Class and its instance fields. 630 uint32_t size = sizeof(Class); 631 // Space used by embedded tables. 632 if (has_embedded_tables) { 633 const uint32_t embedded_imt_size = kImtSize * ImTableEntrySize(pointer_size); 634 const uint32_t embedded_vtable_size = num_vtable_entries * VTableEntrySize(pointer_size); 635 size = RoundUp(size + sizeof(uint32_t) /* embedded vtable len */, pointer_size) + 636 embedded_imt_size + embedded_vtable_size; 637 } 638 639 // Space used by reference statics. 640 size += num_ref_static_fields * sizeof(HeapReference<Object>); 641 if (!IsAligned<8>(size) && num_64bit_static_fields > 0) { 642 uint32_t gap = 8 - (size & 0x7); 643 size += gap; // will be padded 644 // Shuffle 4-byte fields forward. 645 while (gap >= sizeof(uint32_t) && num_32bit_static_fields != 0) { 646 --num_32bit_static_fields; 647 gap -= sizeof(uint32_t); 648 } 649 // Shuffle 2-byte fields forward. 650 while (gap >= sizeof(uint16_t) && num_16bit_static_fields != 0) { 651 --num_16bit_static_fields; 652 gap -= sizeof(uint16_t); 653 } 654 // Shuffle byte fields forward. 655 while (gap >= sizeof(uint8_t) && num_8bit_static_fields != 0) { 656 --num_8bit_static_fields; 657 gap -= sizeof(uint8_t); 658 } 659 } 660 // Guaranteed to be at least 4 byte aligned. No need for further alignments. 661 // Space used for primitive static fields. 662 size += num_8bit_static_fields * sizeof(uint8_t) + num_16bit_static_fields * sizeof(uint16_t) + 663 num_32bit_static_fields * sizeof(uint32_t) + num_64bit_static_fields * sizeof(uint64_t); 664 return size; 665} 666 667template <bool kVisitClass, typename Visitor> 668inline void Class::VisitReferences(mirror::Class* klass, const Visitor& visitor) { 669 VisitInstanceFieldsReferences<kVisitClass>(klass, visitor); 670 // Right after a class is allocated, but not yet loaded 671 // (kStatusNotReady, see ClassLinker::LoadClass()), GC may find it 672 // and scan it. IsTemp() may call Class::GetAccessFlags() but may 673 // fail in the DCHECK in Class::GetAccessFlags() because the class 674 // status is kStatusNotReady. To avoid it, rely on IsResolved() 675 // only. This is fine because a temp class never goes into the 676 // kStatusResolved state. 677 if (IsResolved()) { 678 // Temp classes don't ever populate imt/vtable or static fields and they are not even 679 // allocated with the right size for those. Also, unresolved classes don't have fields 680 // linked yet. 681 VisitStaticFieldsReferences<kVisitClass>(this, visitor); 682 } 683 // Since this class is reachable, we must also visit the associated roots when we scan it. 684 VisitNativeRoots(visitor, Runtime::Current()->GetClassLinker()->GetImagePointerSize()); 685} 686 687template<ReadBarrierOption kReadBarrierOption> 688inline bool Class::IsReferenceClass() const { 689 return this == Reference::GetJavaLangRefReference<kReadBarrierOption>(); 690} 691 692template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption> 693inline bool Class::IsClassClass() { 694 Class* java_lang_Class = GetClass<kVerifyFlags, kReadBarrierOption>()-> 695 template GetClass<kVerifyFlags, kReadBarrierOption>(); 696 return this == java_lang_Class; 697} 698 699inline const DexFile& Class::GetDexFile() { 700 return *GetDexCache()->GetDexFile(); 701} 702 703inline bool Class::DescriptorEquals(const char* match) { 704 if (IsArrayClass()) { 705 return match[0] == '[' && GetComponentType()->DescriptorEquals(match + 1); 706 } else if (IsPrimitive()) { 707 return strcmp(Primitive::Descriptor(GetPrimitiveType()), match) == 0; 708 } else if (IsProxyClass()) { 709 return ProxyDescriptorEquals(match); 710 } else { 711 const DexFile& dex_file = GetDexFile(); 712 const DexFile::TypeId& type_id = dex_file.GetTypeId(GetClassDef()->class_idx_); 713 return strcmp(dex_file.GetTypeDescriptor(type_id), match) == 0; 714 } 715} 716 717inline void Class::AssertInitializedOrInitializingInThread(Thread* self) { 718 if (kIsDebugBuild && !IsInitialized()) { 719 CHECK(IsInitializing()) << PrettyClass(this) << " is not initializing: " << GetStatus(); 720 CHECK_EQ(GetClinitThreadId(), self->GetTid()) << PrettyClass(this) 721 << " is initializing in a different thread"; 722 } 723} 724 725inline ObjectArray<Class>* Class::GetInterfaces() { 726 CHECK(IsProxyClass()); 727 // First static field. 728 auto* field = GetStaticField(0); 729 DCHECK_STREQ(field->GetName(), "interfaces"); 730 MemberOffset field_offset = field->GetOffset(); 731 return GetFieldObject<ObjectArray<Class>>(field_offset); 732} 733 734inline ObjectArray<ObjectArray<Class>>* Class::GetThrows() { 735 CHECK(IsProxyClass()); 736 // Second static field. 737 auto* field = GetStaticField(1); 738 DCHECK_STREQ(field->GetName(), "throws"); 739 MemberOffset field_offset = field->GetOffset(); 740 return GetFieldObject<ObjectArray<ObjectArray<Class>>>(field_offset); 741} 742 743inline MemberOffset Class::GetDisableIntrinsicFlagOffset() { 744 CHECK(IsReferenceClass()); 745 // First static field 746 auto* field = GetStaticField(0); 747 DCHECK_STREQ(field->GetName(), "disableIntrinsic"); 748 return field->GetOffset(); 749} 750 751inline MemberOffset Class::GetSlowPathFlagOffset() { 752 CHECK(IsReferenceClass()); 753 // Second static field 754 auto* field = GetStaticField(1); 755 DCHECK_STREQ(field->GetName(), "slowPathEnabled"); 756 return field->GetOffset(); 757} 758 759inline bool Class::GetSlowPathEnabled() { 760 return GetFieldBoolean(GetSlowPathFlagOffset()); 761} 762 763inline void Class::SetSlowPath(bool enabled) { 764 SetFieldBoolean<false, false>(GetSlowPathFlagOffset(), enabled); 765} 766 767inline void Class::InitializeClassVisitor::operator()( 768 mirror::Object* obj, size_t usable_size) const { 769 DCHECK_LE(class_size_, usable_size); 770 // Avoid AsClass as object is not yet in live bitmap or allocation stack. 771 mirror::Class* klass = down_cast<mirror::Class*>(obj); 772 // DCHECK(klass->IsClass()); 773 klass->SetClassSize(class_size_); 774 klass->SetPrimitiveType(Primitive::kPrimNot); // Default to not being primitive. 775 klass->SetDexClassDefIndex(DexFile::kDexNoIndex16); // Default to no valid class def index. 776 klass->SetDexTypeIndex(DexFile::kDexNoIndex16); // Default to no valid type index. 777} 778 779inline void Class::SetAccessFlags(uint32_t new_access_flags) { 780 // Called inside a transaction when setting pre-verified flag during boot image compilation. 781 if (Runtime::Current()->IsActiveTransaction()) { 782 SetField32<true>(OFFSET_OF_OBJECT_MEMBER(Class, access_flags_), new_access_flags); 783 } else { 784 SetField32<false>(OFFSET_OF_OBJECT_MEMBER(Class, access_flags_), new_access_flags); 785 } 786} 787 788inline uint32_t Class::NumDirectInterfaces() { 789 if (IsPrimitive()) { 790 return 0; 791 } else if (IsArrayClass()) { 792 return 2; 793 } else if (IsProxyClass()) { 794 mirror::ObjectArray<mirror::Class>* interfaces = GetInterfaces(); 795 return interfaces != nullptr ? interfaces->GetLength() : 0; 796 } else { 797 const DexFile::TypeList* interfaces = GetInterfaceTypeList(); 798 if (interfaces == nullptr) { 799 return 0; 800 } else { 801 return interfaces->Size(); 802 } 803 } 804} 805 806inline void Class::SetDexCacheStrings(ObjectArray<String>* new_dex_cache_strings) { 807 SetFieldObject<false>(DexCacheStringsOffset(), new_dex_cache_strings); 808} 809 810inline ObjectArray<String>* Class::GetDexCacheStrings() { 811 return GetFieldObject<ObjectArray<String>>(DexCacheStringsOffset()); 812} 813 814template<class Visitor> 815void mirror::Class::VisitNativeRoots(Visitor& visitor, size_t pointer_size) { 816 ArtField* const sfields = GetSFieldsUnchecked(); 817 // Since we visit class roots while we may be writing these fields, check against null. 818 if (sfields != nullptr) { 819 for (size_t i = 0, count = NumStaticFields(); i < count; ++i) { 820 auto* f = &sfields[i]; 821 // Visit roots first in case the declaring class gets moved. 822 f->VisitRoots(visitor); 823 if (kIsDebugBuild && IsResolved()) { 824 CHECK_EQ(f->GetDeclaringClass(), this) << GetStatus(); 825 } 826 } 827 } 828 ArtField* const ifields = GetIFieldsUnchecked(); 829 if (ifields != nullptr) { 830 for (size_t i = 0, count = NumInstanceFields(); i < count; ++i) { 831 auto* f = &ifields[i]; 832 // Visit roots first in case the declaring class gets moved. 833 f->VisitRoots(visitor); 834 if (kIsDebugBuild && IsResolved()) { 835 CHECK_EQ(f->GetDeclaringClass(), this) << GetStatus(); 836 } 837 } 838 } 839 // We may see GetDirectMethodsPtr() == null with NumDirectMethods() != 0 if the root marking 840 // thread reads a null DirectMethodsBegin() but a non null DirectMethodsBegin() due to a race 841 // SetDirectMethodsPtr from class linking. Same for virtual methods. 842 // In this case, it is safe to avoid marking the roots since we must be either the CC or CMS. If 843 // we are CMS then the roots are already marked through other sources, otherwise the roots are 844 // already marked due to the to-space invariant. 845 // Unchecked versions since we may visit roots of classes that aren't yet loaded. 846 if (GetDirectMethodsPtrUnchecked() != nullptr) { 847 for (auto& m : GetDirectMethods(pointer_size)) { 848 m.VisitRoots(visitor); 849 } 850 } 851 if (GetVirtualMethodsPtrUnchecked() != nullptr) { 852 for (auto& m : GetVirtualMethods(pointer_size)) { 853 m.VisitRoots(visitor); 854 } 855 } 856} 857 858inline StrideIterator<ArtMethod> Class::DirectMethodsBegin(size_t pointer_size) { 859 CheckPointerSize(pointer_size); 860 auto* methods = GetDirectMethodsPtrUnchecked(); 861 auto stride = ArtMethod::ObjectSize(pointer_size); 862 return StrideIterator<ArtMethod>(reinterpret_cast<uintptr_t>(methods), stride); 863} 864 865inline StrideIterator<ArtMethod> Class::DirectMethodsEnd(size_t pointer_size) { 866 CheckPointerSize(pointer_size); 867 auto* methods = GetDirectMethodsPtrUnchecked(); 868 auto stride = ArtMethod::ObjectSize(pointer_size); 869 auto count = NumDirectMethods(); 870 return StrideIterator<ArtMethod>(reinterpret_cast<uintptr_t>(methods) + stride * count, stride); 871} 872 873inline IterationRange<StrideIterator<ArtMethod>> Class::GetDirectMethods(size_t pointer_size) { 874 CheckPointerSize(pointer_size); 875 return MakeIterationRange(DirectMethodsBegin(pointer_size), DirectMethodsEnd(pointer_size)); 876} 877 878inline StrideIterator<ArtMethod> Class::VirtualMethodsBegin(size_t pointer_size) { 879 CheckPointerSize(pointer_size); 880 auto* methods = GetVirtualMethodsPtrUnchecked(); 881 auto stride = ArtMethod::ObjectSize(pointer_size); 882 return StrideIterator<ArtMethod>(reinterpret_cast<uintptr_t>(methods), stride); 883} 884 885inline StrideIterator<ArtMethod> Class::VirtualMethodsEnd(size_t pointer_size) { 886 CheckPointerSize(pointer_size); 887 auto* methods = GetVirtualMethodsPtrUnchecked(); 888 auto stride = ArtMethod::ObjectSize(pointer_size); 889 auto count = NumVirtualMethods(); 890 return StrideIterator<ArtMethod>(reinterpret_cast<uintptr_t>(methods) + stride * count, stride); 891} 892 893inline IterationRange<StrideIterator<ArtMethod>> Class::GetVirtualMethods(size_t pointer_size) { 894 return MakeIterationRange(VirtualMethodsBegin(pointer_size), VirtualMethodsEnd(pointer_size)); 895} 896 897inline MemberOffset Class::EmbeddedImTableOffset(size_t pointer_size) { 898 CheckPointerSize(pointer_size); 899 // Round up since we want the embedded imt and vtable to be pointer size aligned in case 64 bits. 900 // Add 32 bits for embedded vtable length. 901 return MemberOffset( 902 RoundUp(EmbeddedVTableLengthOffset().Uint32Value() + sizeof(uint32_t), pointer_size)); 903} 904 905inline MemberOffset Class::EmbeddedVTableOffset(size_t pointer_size) { 906 CheckPointerSize(pointer_size); 907 return MemberOffset(EmbeddedImTableOffset(pointer_size).Uint32Value() + 908 kImtSize * ImTableEntrySize(pointer_size)); 909} 910 911inline void Class::CheckPointerSize(size_t pointer_size) { 912 DCHECK(ValidPointerSize(pointer_size)) << pointer_size; 913 DCHECK_EQ(pointer_size, Runtime::Current()->GetClassLinker()->GetImagePointerSize()); 914} 915 916} // namespace mirror 917} // namespace art 918 919#endif // ART_RUNTIME_MIRROR_CLASS_INL_H_ 920