xref: /aosp_15_r20/art/runtime/mirror/class-inl.h (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker  * Copyright (C) 2011 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker  *
4*795d594fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker  *
8*795d594fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker  *
10*795d594fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker  * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker  */
16*795d594fSAndroid Build Coastguard Worker 
17*795d594fSAndroid Build Coastguard Worker #ifndef ART_RUNTIME_MIRROR_CLASS_INL_H_
18*795d594fSAndroid Build Coastguard Worker #define ART_RUNTIME_MIRROR_CLASS_INL_H_
19*795d594fSAndroid Build Coastguard Worker 
20*795d594fSAndroid Build Coastguard Worker #include "class.h"
21*795d594fSAndroid Build Coastguard Worker 
22*795d594fSAndroid Build Coastguard Worker #include "art_field.h"
23*795d594fSAndroid Build Coastguard Worker #include "art_method.h"
24*795d594fSAndroid Build Coastguard Worker #include "base/array_slice.h"
25*795d594fSAndroid Build Coastguard Worker #include "base/iteration_range.h"
26*795d594fSAndroid Build Coastguard Worker #include "base/length_prefixed_array.h"
27*795d594fSAndroid Build Coastguard Worker #include "base/stride_iterator.h"
28*795d594fSAndroid Build Coastguard Worker #include "base/utils.h"
29*795d594fSAndroid Build Coastguard Worker #include "class_linker.h"
30*795d594fSAndroid Build Coastguard Worker #include "class_loader.h"
31*795d594fSAndroid Build Coastguard Worker #include "common_throws.h"
32*795d594fSAndroid Build Coastguard Worker #include "dex/dex_file-inl.h"
33*795d594fSAndroid Build Coastguard Worker #include "dex/invoke_type.h"
34*795d594fSAndroid Build Coastguard Worker #include "dex_cache.h"
35*795d594fSAndroid Build Coastguard Worker #include "hidden_api.h"
36*795d594fSAndroid Build Coastguard Worker #include "iftable-inl.h"
37*795d594fSAndroid Build Coastguard Worker #include "imtable.h"
38*795d594fSAndroid Build Coastguard Worker #include "object-inl.h"
39*795d594fSAndroid Build Coastguard Worker #include "read_barrier-inl.h"
40*795d594fSAndroid Build Coastguard Worker #include "runtime.h"
41*795d594fSAndroid Build Coastguard Worker #include "string.h"
42*795d594fSAndroid Build Coastguard Worker #include "subtype_check.h"
43*795d594fSAndroid Build Coastguard Worker #include "thread-current-inl.h"
44*795d594fSAndroid Build Coastguard Worker 
45*795d594fSAndroid Build Coastguard Worker namespace art HIDDEN {
46*795d594fSAndroid Build Coastguard Worker namespace mirror {
47*795d594fSAndroid Build Coastguard Worker 
48*795d594fSAndroid Build Coastguard Worker template<VerifyObjectFlags kVerifyFlags>
GetObjectSize()49*795d594fSAndroid Build Coastguard Worker inline uint32_t Class::GetObjectSize() {
50*795d594fSAndroid Build Coastguard Worker   // Note: Extra parentheses to avoid the comma being interpreted as macro parameter separator.
51*795d594fSAndroid Build Coastguard Worker   DCHECK((!IsVariableSize<kVerifyFlags>())) << "class=" << PrettyTypeOf();
52*795d594fSAndroid Build Coastguard Worker   return GetField32(ObjectSizeOffset());
53*795d594fSAndroid Build Coastguard Worker }
54*795d594fSAndroid Build Coastguard Worker 
55*795d594fSAndroid Build Coastguard Worker template<VerifyObjectFlags kVerifyFlags>
GetObjectSizeAllocFastPath()56*795d594fSAndroid Build Coastguard Worker inline uint32_t Class::GetObjectSizeAllocFastPath() {
57*795d594fSAndroid Build Coastguard Worker   // Note: Extra parentheses to avoid the comma being interpreted as macro parameter separator.
58*795d594fSAndroid Build Coastguard Worker   DCHECK((!IsVariableSize<kVerifyFlags>())) << "class=" << PrettyTypeOf();
59*795d594fSAndroid Build Coastguard Worker   return GetField32(ObjectSizeAllocFastPathOffset());
60*795d594fSAndroid Build Coastguard Worker }
61*795d594fSAndroid Build Coastguard Worker 
62*795d594fSAndroid Build Coastguard Worker template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
GetSuperClass()63*795d594fSAndroid Build Coastguard Worker inline ObjPtr<Class> Class::GetSuperClass() {
64*795d594fSAndroid Build Coastguard Worker   // Can only get super class for loaded classes (hack for when runtime is
65*795d594fSAndroid Build Coastguard Worker   // initializing)
66*795d594fSAndroid Build Coastguard Worker   DCHECK(IsLoaded<kVerifyFlags>() ||
67*795d594fSAndroid Build Coastguard Worker          IsErroneous<kVerifyFlags>() ||
68*795d594fSAndroid Build Coastguard Worker          !Runtime::Current()->IsStarted()) << IsLoaded();
69*795d594fSAndroid Build Coastguard Worker   return GetFieldObject<Class, kVerifyFlags, kReadBarrierOption>(
70*795d594fSAndroid Build Coastguard Worker       OFFSET_OF_OBJECT_MEMBER(Class, super_class_));
71*795d594fSAndroid Build Coastguard Worker }
72*795d594fSAndroid Build Coastguard Worker 
SetSuperClass(ObjPtr<Class> new_super_class)73*795d594fSAndroid Build Coastguard Worker inline void Class::SetSuperClass(ObjPtr<Class> new_super_class) {
74*795d594fSAndroid Build Coastguard Worker   // Super class is assigned once, except during class linker initialization.
75*795d594fSAndroid Build Coastguard Worker   if (kIsDebugBuild) {
76*795d594fSAndroid Build Coastguard Worker     ObjPtr<Class> old_super_class =
77*795d594fSAndroid Build Coastguard Worker         GetFieldObject<Class>(OFFSET_OF_OBJECT_MEMBER(Class, super_class_));
78*795d594fSAndroid Build Coastguard Worker     DCHECK(old_super_class == nullptr || old_super_class == new_super_class);
79*795d594fSAndroid Build Coastguard Worker   }
80*795d594fSAndroid Build Coastguard Worker   DCHECK(new_super_class != nullptr);
81*795d594fSAndroid Build Coastguard Worker   SetFieldObject</*kTransactionActive=*/ false, /*kCheckTransaction=*/ false>(
82*795d594fSAndroid Build Coastguard Worker       OFFSET_OF_OBJECT_MEMBER(Class, super_class_), new_super_class);
83*795d594fSAndroid Build Coastguard Worker }
84*795d594fSAndroid Build Coastguard Worker 
HasSuperClass()85*795d594fSAndroid Build Coastguard Worker inline bool Class::HasSuperClass() {
86*795d594fSAndroid Build Coastguard Worker   // No read barrier is needed for comparing with null. See ReadBarrierOption.
87*795d594fSAndroid Build Coastguard Worker   return GetSuperClass<kDefaultVerifyFlags, kWithoutReadBarrier>() != nullptr;
88*795d594fSAndroid Build Coastguard Worker }
89*795d594fSAndroid Build Coastguard Worker 
90*795d594fSAndroid Build Coastguard Worker template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
GetClassLoader()91*795d594fSAndroid Build Coastguard Worker inline ObjPtr<ClassLoader> Class::GetClassLoader() {
92*795d594fSAndroid Build Coastguard Worker   return GetFieldObject<ClassLoader, kVerifyFlags, kReadBarrierOption>(
93*795d594fSAndroid Build Coastguard Worker       OFFSET_OF_OBJECT_MEMBER(Class, class_loader_));
94*795d594fSAndroid Build Coastguard Worker }
95*795d594fSAndroid Build Coastguard Worker 
96*795d594fSAndroid Build Coastguard Worker template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
GetExtData()97*795d594fSAndroid Build Coastguard Worker inline ObjPtr<ClassExt> Class::GetExtData() {
98*795d594fSAndroid Build Coastguard Worker   return GetFieldObject<ClassExt, kVerifyFlags, kReadBarrierOption>(
99*795d594fSAndroid Build Coastguard Worker       OFFSET_OF_OBJECT_MEMBER(Class, ext_data_));
100*795d594fSAndroid Build Coastguard Worker }
101*795d594fSAndroid Build Coastguard Worker 
102*795d594fSAndroid Build Coastguard Worker template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
GetDexCache()103*795d594fSAndroid Build Coastguard Worker inline ObjPtr<DexCache> Class::GetDexCache() {
104*795d594fSAndroid Build Coastguard Worker   return GetFieldObject<DexCache, kVerifyFlags, kReadBarrierOption>(
105*795d594fSAndroid Build Coastguard Worker       OFFSET_OF_OBJECT_MEMBER(Class, dex_cache_));
106*795d594fSAndroid Build Coastguard Worker }
107*795d594fSAndroid Build Coastguard Worker 
GetCopiedMethodsStartOffset()108*795d594fSAndroid Build Coastguard Worker inline uint32_t Class::GetCopiedMethodsStartOffset() {
109*795d594fSAndroid Build Coastguard Worker   // Object::GetFieldShort returns an int16_t value, but
110*795d594fSAndroid Build Coastguard Worker   // Class::copied_methods_offset_ is an uint16_t value; cast the
111*795d594fSAndroid Build Coastguard Worker   // latter to uint16_t before returning it as an uint32_t value, so
112*795d594fSAndroid Build Coastguard Worker   // that uint16_t values between 2^15 and 2^16-1 are correctly
113*795d594fSAndroid Build Coastguard Worker   // handled.
114*795d594fSAndroid Build Coastguard Worker   return static_cast<uint16_t>(
115*795d594fSAndroid Build Coastguard Worker       GetFieldShort(OFFSET_OF_OBJECT_MEMBER(Class, copied_methods_offset_)));
116*795d594fSAndroid Build Coastguard Worker }
117*795d594fSAndroid Build Coastguard Worker 
GetDirectMethodsStartOffset()118*795d594fSAndroid Build Coastguard Worker inline uint32_t Class::GetDirectMethodsStartOffset() {
119*795d594fSAndroid Build Coastguard Worker   return 0;
120*795d594fSAndroid Build Coastguard Worker }
121*795d594fSAndroid Build Coastguard Worker 
GetVirtualMethodsStartOffset()122*795d594fSAndroid Build Coastguard Worker inline uint32_t Class::GetVirtualMethodsStartOffset() {
123*795d594fSAndroid Build Coastguard Worker   // Object::GetFieldShort returns an int16_t value, but
124*795d594fSAndroid Build Coastguard Worker   // Class::virtual_method_offset_ is an uint16_t value; cast the
125*795d594fSAndroid Build Coastguard Worker   // latter to uint16_t before returning it as an uint32_t value, so
126*795d594fSAndroid Build Coastguard Worker   // that uint16_t values between 2^15 and 2^16-1 are correctly
127*795d594fSAndroid Build Coastguard Worker   // handled.
128*795d594fSAndroid Build Coastguard Worker   return static_cast<uint16_t>(
129*795d594fSAndroid Build Coastguard Worker       GetFieldShort(OFFSET_OF_OBJECT_MEMBER(Class, virtual_methods_offset_)));
130*795d594fSAndroid Build Coastguard Worker }
131*795d594fSAndroid Build Coastguard Worker 
132*795d594fSAndroid Build Coastguard Worker template<VerifyObjectFlags kVerifyFlags>
GetDirectMethodsSlice(PointerSize pointer_size)133*795d594fSAndroid Build Coastguard Worker inline ArraySlice<ArtMethod> Class::GetDirectMethodsSlice(PointerSize pointer_size) {
134*795d594fSAndroid Build Coastguard Worker   DCHECK(IsLoaded() || IsErroneous()) << GetStatus();
135*795d594fSAndroid Build Coastguard Worker   return GetDirectMethodsSliceUnchecked(pointer_size);
136*795d594fSAndroid Build Coastguard Worker }
137*795d594fSAndroid Build Coastguard Worker 
GetDirectMethodsSliceUnchecked(PointerSize pointer_size)138*795d594fSAndroid Build Coastguard Worker inline ArraySlice<ArtMethod> Class::GetDirectMethodsSliceUnchecked(PointerSize pointer_size) {
139*795d594fSAndroid Build Coastguard Worker   return GetMethodsSliceRangeUnchecked(GetMethodsPtr(),
140*795d594fSAndroid Build Coastguard Worker                                        pointer_size,
141*795d594fSAndroid Build Coastguard Worker                                        GetDirectMethodsStartOffset(),
142*795d594fSAndroid Build Coastguard Worker                                        GetVirtualMethodsStartOffset());
143*795d594fSAndroid Build Coastguard Worker }
144*795d594fSAndroid Build Coastguard Worker 
145*795d594fSAndroid Build Coastguard Worker template<VerifyObjectFlags kVerifyFlags>
GetDeclaredMethodsSlice(PointerSize pointer_size)146*795d594fSAndroid Build Coastguard Worker inline ArraySlice<ArtMethod> Class::GetDeclaredMethodsSlice(PointerSize pointer_size) {
147*795d594fSAndroid Build Coastguard Worker   DCHECK(IsLoaded() || IsErroneous()) << GetStatus();
148*795d594fSAndroid Build Coastguard Worker   return GetDeclaredMethodsSliceUnchecked(pointer_size);
149*795d594fSAndroid Build Coastguard Worker }
150*795d594fSAndroid Build Coastguard Worker 
GetDeclaredMethodsSliceUnchecked(PointerSize pointer_size)151*795d594fSAndroid Build Coastguard Worker inline ArraySlice<ArtMethod> Class::GetDeclaredMethodsSliceUnchecked(PointerSize pointer_size) {
152*795d594fSAndroid Build Coastguard Worker   return GetMethodsSliceRangeUnchecked(GetMethodsPtr(),
153*795d594fSAndroid Build Coastguard Worker                                        pointer_size,
154*795d594fSAndroid Build Coastguard Worker                                        GetDirectMethodsStartOffset(),
155*795d594fSAndroid Build Coastguard Worker                                        GetCopiedMethodsStartOffset());
156*795d594fSAndroid Build Coastguard Worker }
157*795d594fSAndroid Build Coastguard Worker 
158*795d594fSAndroid Build Coastguard Worker template<VerifyObjectFlags kVerifyFlags>
GetDeclaredVirtualMethodsSlice(PointerSize pointer_size)159*795d594fSAndroid Build Coastguard Worker inline ArraySlice<ArtMethod> Class::GetDeclaredVirtualMethodsSlice(PointerSize pointer_size) {
160*795d594fSAndroid Build Coastguard Worker   DCHECK(IsLoaded() || IsErroneous()) << GetStatus();
161*795d594fSAndroid Build Coastguard Worker   return GetDeclaredVirtualMethodsSliceUnchecked(pointer_size);
162*795d594fSAndroid Build Coastguard Worker }
163*795d594fSAndroid Build Coastguard Worker 
GetDeclaredVirtualMethodsSliceUnchecked(PointerSize pointer_size)164*795d594fSAndroid Build Coastguard Worker inline ArraySlice<ArtMethod> Class::GetDeclaredVirtualMethodsSliceUnchecked(
165*795d594fSAndroid Build Coastguard Worker     PointerSize pointer_size) {
166*795d594fSAndroid Build Coastguard Worker   return GetMethodsSliceRangeUnchecked(GetMethodsPtr(),
167*795d594fSAndroid Build Coastguard Worker                                        pointer_size,
168*795d594fSAndroid Build Coastguard Worker                                        GetVirtualMethodsStartOffset(),
169*795d594fSAndroid Build Coastguard Worker                                        GetCopiedMethodsStartOffset());
170*795d594fSAndroid Build Coastguard Worker }
171*795d594fSAndroid Build Coastguard Worker 
172*795d594fSAndroid Build Coastguard Worker template<VerifyObjectFlags kVerifyFlags>
GetVirtualMethodsSlice(PointerSize pointer_size)173*795d594fSAndroid Build Coastguard Worker inline ArraySlice<ArtMethod> Class::GetVirtualMethodsSlice(PointerSize pointer_size) {
174*795d594fSAndroid Build Coastguard Worker   DCHECK(IsLoaded() || IsErroneous());
175*795d594fSAndroid Build Coastguard Worker   return GetVirtualMethodsSliceUnchecked(pointer_size);
176*795d594fSAndroid Build Coastguard Worker }
177*795d594fSAndroid Build Coastguard Worker 
GetVirtualMethodsSliceUnchecked(PointerSize pointer_size)178*795d594fSAndroid Build Coastguard Worker inline ArraySlice<ArtMethod> Class::GetVirtualMethodsSliceUnchecked(PointerSize pointer_size) {
179*795d594fSAndroid Build Coastguard Worker   LengthPrefixedArray<ArtMethod>* methods = GetMethodsPtr();
180*795d594fSAndroid Build Coastguard Worker   return GetMethodsSliceRangeUnchecked(methods,
181*795d594fSAndroid Build Coastguard Worker                                        pointer_size,
182*795d594fSAndroid Build Coastguard Worker                                        GetVirtualMethodsStartOffset(),
183*795d594fSAndroid Build Coastguard Worker                                        NumMethods(methods));
184*795d594fSAndroid Build Coastguard Worker }
185*795d594fSAndroid Build Coastguard Worker 
186*795d594fSAndroid Build Coastguard Worker template<VerifyObjectFlags kVerifyFlags>
GetCopiedMethodsSlice(PointerSize pointer_size)187*795d594fSAndroid Build Coastguard Worker inline ArraySlice<ArtMethod> Class::GetCopiedMethodsSlice(PointerSize pointer_size) {
188*795d594fSAndroid Build Coastguard Worker   DCHECK(IsLoaded() || IsErroneous());
189*795d594fSAndroid Build Coastguard Worker   return GetCopiedMethodsSliceUnchecked(pointer_size);
190*795d594fSAndroid Build Coastguard Worker }
191*795d594fSAndroid Build Coastguard Worker 
GetCopiedMethodsSliceUnchecked(PointerSize pointer_size)192*795d594fSAndroid Build Coastguard Worker inline ArraySlice<ArtMethod> Class::GetCopiedMethodsSliceUnchecked(PointerSize pointer_size) {
193*795d594fSAndroid Build Coastguard Worker   LengthPrefixedArray<ArtMethod>* methods = GetMethodsPtr();
194*795d594fSAndroid Build Coastguard Worker   return GetMethodsSliceRangeUnchecked(methods,
195*795d594fSAndroid Build Coastguard Worker                                        pointer_size,
196*795d594fSAndroid Build Coastguard Worker                                        GetCopiedMethodsStartOffset(),
197*795d594fSAndroid Build Coastguard Worker                                        NumMethods(methods));
198*795d594fSAndroid Build Coastguard Worker }
199*795d594fSAndroid Build Coastguard Worker 
GetMethodsPtr()200*795d594fSAndroid Build Coastguard Worker inline LengthPrefixedArray<ArtMethod>* Class::GetMethodsPtr() {
201*795d594fSAndroid Build Coastguard Worker   return reinterpret_cast<LengthPrefixedArray<ArtMethod>*>(
202*795d594fSAndroid Build Coastguard Worker       static_cast<uintptr_t>(GetField64(OFFSET_OF_OBJECT_MEMBER(Class, methods_))));
203*795d594fSAndroid Build Coastguard Worker }
204*795d594fSAndroid Build Coastguard Worker 
205*795d594fSAndroid Build Coastguard Worker template<VerifyObjectFlags kVerifyFlags>
GetMethodsSlice(PointerSize pointer_size)206*795d594fSAndroid Build Coastguard Worker inline ArraySlice<ArtMethod> Class::GetMethodsSlice(PointerSize pointer_size) {
207*795d594fSAndroid Build Coastguard Worker   DCHECK(IsLoaded() || IsErroneous());
208*795d594fSAndroid Build Coastguard Worker   LengthPrefixedArray<ArtMethod>* methods = GetMethodsPtr();
209*795d594fSAndroid Build Coastguard Worker   return GetMethodsSliceRangeUnchecked(methods, pointer_size, 0, NumMethods(methods));
210*795d594fSAndroid Build Coastguard Worker }
211*795d594fSAndroid Build Coastguard Worker 
GetMethodsSliceRangeUnchecked(LengthPrefixedArray<ArtMethod> * methods,PointerSize pointer_size,uint32_t start_offset,uint32_t end_offset)212*795d594fSAndroid Build Coastguard Worker inline ArraySlice<ArtMethod> Class::GetMethodsSliceRangeUnchecked(
213*795d594fSAndroid Build Coastguard Worker     LengthPrefixedArray<ArtMethod>* methods,
214*795d594fSAndroid Build Coastguard Worker     PointerSize pointer_size,
215*795d594fSAndroid Build Coastguard Worker     uint32_t start_offset,
216*795d594fSAndroid Build Coastguard Worker     uint32_t end_offset) {
217*795d594fSAndroid Build Coastguard Worker   DCHECK_LE(start_offset, end_offset);
218*795d594fSAndroid Build Coastguard Worker   DCHECK_LE(end_offset, NumMethods(methods));
219*795d594fSAndroid Build Coastguard Worker   uint32_t size = end_offset - start_offset;
220*795d594fSAndroid Build Coastguard Worker   if (size == 0u) {
221*795d594fSAndroid Build Coastguard Worker     return ArraySlice<ArtMethod>();
222*795d594fSAndroid Build Coastguard Worker   }
223*795d594fSAndroid Build Coastguard Worker   DCHECK(methods != nullptr);
224*795d594fSAndroid Build Coastguard Worker   DCHECK_LE(end_offset, methods->size());
225*795d594fSAndroid Build Coastguard Worker   size_t method_size = ArtMethod::Size(pointer_size);
226*795d594fSAndroid Build Coastguard Worker   size_t method_alignment = ArtMethod::Alignment(pointer_size);
227*795d594fSAndroid Build Coastguard Worker   ArraySlice<ArtMethod> slice(&methods->At(0u, method_size, method_alignment),
228*795d594fSAndroid Build Coastguard Worker                               methods->size(),
229*795d594fSAndroid Build Coastguard Worker                               method_size);
230*795d594fSAndroid Build Coastguard Worker   return slice.SubArray(start_offset, size);
231*795d594fSAndroid Build Coastguard Worker }
232*795d594fSAndroid Build Coastguard Worker 
NumMethods()233*795d594fSAndroid Build Coastguard Worker inline uint32_t Class::NumMethods() {
234*795d594fSAndroid Build Coastguard Worker   return NumMethods(GetMethodsPtr());
235*795d594fSAndroid Build Coastguard Worker }
236*795d594fSAndroid Build Coastguard Worker 
NumMethods(LengthPrefixedArray<ArtMethod> * methods)237*795d594fSAndroid Build Coastguard Worker inline uint32_t Class::NumMethods(LengthPrefixedArray<ArtMethod>* methods) {
238*795d594fSAndroid Build Coastguard Worker   return (methods == nullptr) ? 0 : methods->size();
239*795d594fSAndroid Build Coastguard Worker }
240*795d594fSAndroid Build Coastguard Worker 
GetDirectMethodUnchecked(size_t i,PointerSize pointer_size)241*795d594fSAndroid Build Coastguard Worker inline ArtMethod* Class::GetDirectMethodUnchecked(size_t i, PointerSize pointer_size) {
242*795d594fSAndroid Build Coastguard Worker   CheckPointerSize(pointer_size);
243*795d594fSAndroid Build Coastguard Worker   return &GetDirectMethodsSliceUnchecked(pointer_size)[i];
244*795d594fSAndroid Build Coastguard Worker }
245*795d594fSAndroid Build Coastguard Worker 
GetDirectMethod(size_t i,PointerSize pointer_size)246*795d594fSAndroid Build Coastguard Worker inline ArtMethod* Class::GetDirectMethod(size_t i, PointerSize pointer_size) {
247*795d594fSAndroid Build Coastguard Worker   CheckPointerSize(pointer_size);
248*795d594fSAndroid Build Coastguard Worker   return &GetDirectMethodsSlice(pointer_size)[i];
249*795d594fSAndroid Build Coastguard Worker }
250*795d594fSAndroid Build Coastguard Worker 
SetMethodsPtr(LengthPrefixedArray<ArtMethod> * new_methods,uint32_t num_direct,uint32_t num_virtual)251*795d594fSAndroid Build Coastguard Worker inline void Class::SetMethodsPtr(LengthPrefixedArray<ArtMethod>* new_methods,
252*795d594fSAndroid Build Coastguard Worker                                  uint32_t num_direct,
253*795d594fSAndroid Build Coastguard Worker                                  uint32_t num_virtual) {
254*795d594fSAndroid Build Coastguard Worker   DCHECK(GetMethodsPtr() == nullptr);
255*795d594fSAndroid Build Coastguard Worker   SetMethodsPtrUnchecked(new_methods, num_direct, num_virtual);
256*795d594fSAndroid Build Coastguard Worker }
257*795d594fSAndroid Build Coastguard Worker 
258*795d594fSAndroid Build Coastguard Worker 
SetMethodsPtrUnchecked(LengthPrefixedArray<ArtMethod> * new_methods,uint32_t num_direct,uint32_t num_virtual)259*795d594fSAndroid Build Coastguard Worker inline void Class::SetMethodsPtrUnchecked(LengthPrefixedArray<ArtMethod>* new_methods,
260*795d594fSAndroid Build Coastguard Worker                                           uint32_t num_direct,
261*795d594fSAndroid Build Coastguard Worker                                           uint32_t num_virtual) {
262*795d594fSAndroid Build Coastguard Worker   DCHECK_LE(num_direct + num_virtual, (new_methods == nullptr) ? 0 : new_methods->size());
263*795d594fSAndroid Build Coastguard Worker   SetField64<false>(OFFSET_OF_OBJECT_MEMBER(Class, methods_),
264*795d594fSAndroid Build Coastguard Worker                     static_cast<uint64_t>(reinterpret_cast<uintptr_t>(new_methods)));
265*795d594fSAndroid Build Coastguard Worker   SetFieldShort<false>(OFFSET_OF_OBJECT_MEMBER(Class, copied_methods_offset_),
266*795d594fSAndroid Build Coastguard Worker                     dchecked_integral_cast<uint16_t>(num_direct + num_virtual));
267*795d594fSAndroid Build Coastguard Worker   SetFieldShort<false>(OFFSET_OF_OBJECT_MEMBER(Class, virtual_methods_offset_),
268*795d594fSAndroid Build Coastguard Worker                        dchecked_integral_cast<uint16_t>(num_direct));
269*795d594fSAndroid Build Coastguard Worker }
270*795d594fSAndroid Build Coastguard Worker 
271*795d594fSAndroid Build Coastguard Worker template<VerifyObjectFlags kVerifyFlags>
GetVirtualMethod(size_t i,PointerSize pointer_size)272*795d594fSAndroid Build Coastguard Worker inline ArtMethod* Class::GetVirtualMethod(size_t i, PointerSize pointer_size) {
273*795d594fSAndroid Build Coastguard Worker   CheckPointerSize(pointer_size);
274*795d594fSAndroid Build Coastguard Worker   DCHECK(IsResolved<kVerifyFlags>() || IsErroneous<kVerifyFlags>())
275*795d594fSAndroid Build Coastguard Worker       << Class::PrettyClass() << " status=" << GetStatus();
276*795d594fSAndroid Build Coastguard Worker   return GetVirtualMethodUnchecked(i, pointer_size);
277*795d594fSAndroid Build Coastguard Worker }
278*795d594fSAndroid Build Coastguard Worker 
GetVirtualMethodDuringLinking(size_t i,PointerSize pointer_size)279*795d594fSAndroid Build Coastguard Worker inline ArtMethod* Class::GetVirtualMethodDuringLinking(size_t i, PointerSize pointer_size) {
280*795d594fSAndroid Build Coastguard Worker   CheckPointerSize(pointer_size);
281*795d594fSAndroid Build Coastguard Worker   DCHECK(IsLoaded() || IsErroneous());
282*795d594fSAndroid Build Coastguard Worker   return GetVirtualMethodUnchecked(i, pointer_size);
283*795d594fSAndroid Build Coastguard Worker }
284*795d594fSAndroid Build Coastguard Worker 
GetVirtualMethodUnchecked(size_t i,PointerSize pointer_size)285*795d594fSAndroid Build Coastguard Worker inline ArtMethod* Class::GetVirtualMethodUnchecked(size_t i, PointerSize pointer_size) {
286*795d594fSAndroid Build Coastguard Worker   CheckPointerSize(pointer_size);
287*795d594fSAndroid Build Coastguard Worker   return &GetVirtualMethodsSliceUnchecked(pointer_size)[i];
288*795d594fSAndroid Build Coastguard Worker }
289*795d594fSAndroid Build Coastguard Worker 
290*795d594fSAndroid Build Coastguard Worker template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
GetVTable()291*795d594fSAndroid Build Coastguard Worker inline ObjPtr<PointerArray> Class::GetVTable() {
292*795d594fSAndroid Build Coastguard Worker   DCHECK(IsLoaded<kVerifyFlags>() || IsErroneous<kVerifyFlags>());
293*795d594fSAndroid Build Coastguard Worker   return GetFieldObject<PointerArray, kVerifyFlags, kReadBarrierOption>(
294*795d594fSAndroid Build Coastguard Worker       OFFSET_OF_OBJECT_MEMBER(Class, vtable_));
295*795d594fSAndroid Build Coastguard Worker }
296*795d594fSAndroid Build Coastguard Worker 
GetVTableDuringLinking()297*795d594fSAndroid Build Coastguard Worker inline ObjPtr<PointerArray> Class::GetVTableDuringLinking() {
298*795d594fSAndroid Build Coastguard Worker   DCHECK(IsLoaded() || IsErroneous());
299*795d594fSAndroid Build Coastguard Worker   return GetFieldObject<PointerArray>(OFFSET_OF_OBJECT_MEMBER(Class, vtable_));
300*795d594fSAndroid Build Coastguard Worker }
301*795d594fSAndroid Build Coastguard Worker 
SetVTable(ObjPtr<PointerArray> new_vtable)302*795d594fSAndroid Build Coastguard Worker inline void Class::SetVTable(ObjPtr<PointerArray> new_vtable) {
303*795d594fSAndroid Build Coastguard Worker   SetFieldObject</*kTransactionActive=*/ false, /*kCheckTransaction=*/ false>(
304*795d594fSAndroid Build Coastguard Worker       OFFSET_OF_OBJECT_MEMBER(Class, vtable_), new_vtable);
305*795d594fSAndroid Build Coastguard Worker }
306*795d594fSAndroid Build Coastguard Worker 
307*795d594fSAndroid Build Coastguard Worker template<VerifyObjectFlags kVerifyFlags>
ShouldHaveImt()308*795d594fSAndroid Build Coastguard Worker inline bool Class::ShouldHaveImt() {
309*795d594fSAndroid Build Coastguard Worker   return ShouldHaveEmbeddedVTable<kVerifyFlags>();
310*795d594fSAndroid Build Coastguard Worker }
311*795d594fSAndroid Build Coastguard Worker 
312*795d594fSAndroid Build Coastguard Worker template<VerifyObjectFlags kVerifyFlags>
ShouldHaveEmbeddedVTable()313*795d594fSAndroid Build Coastguard Worker inline bool Class::ShouldHaveEmbeddedVTable() {
314*795d594fSAndroid Build Coastguard Worker   return IsInstantiable<kVerifyFlags>();
315*795d594fSAndroid Build Coastguard Worker }
316*795d594fSAndroid Build Coastguard Worker 
HasVTable()317*795d594fSAndroid Build Coastguard Worker inline bool Class::HasVTable() {
318*795d594fSAndroid Build Coastguard Worker   // No read barrier is needed for comparing with null. See ReadBarrierOption.
319*795d594fSAndroid Build Coastguard Worker   return GetVTable<kDefaultVerifyFlags, kWithoutReadBarrier>() != nullptr ||
320*795d594fSAndroid Build Coastguard Worker          ShouldHaveEmbeddedVTable();
321*795d594fSAndroid Build Coastguard Worker }
322*795d594fSAndroid Build Coastguard Worker 
323*795d594fSAndroid Build Coastguard Worker template<VerifyObjectFlags kVerifyFlags>
GetVTableLength()324*795d594fSAndroid Build Coastguard Worker inline int32_t Class::GetVTableLength() {
325*795d594fSAndroid Build Coastguard Worker   if (ShouldHaveEmbeddedVTable<kVerifyFlags>()) {
326*795d594fSAndroid Build Coastguard Worker     return GetEmbeddedVTableLength();
327*795d594fSAndroid Build Coastguard Worker   }
328*795d594fSAndroid Build Coastguard Worker   // We do not need a read barrier here as the length is constant,
329*795d594fSAndroid Build Coastguard Worker   // both from-space and to-space vtables shall yield the same result.
330*795d594fSAndroid Build Coastguard Worker   ObjPtr<PointerArray> vtable = GetVTable<kVerifyFlags, kWithoutReadBarrier>();
331*795d594fSAndroid Build Coastguard Worker   return vtable != nullptr ? vtable->GetLength() : 0;
332*795d594fSAndroid Build Coastguard Worker }
333*795d594fSAndroid Build Coastguard Worker 
334*795d594fSAndroid Build Coastguard Worker template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
GetVTableEntry(uint32_t i,PointerSize pointer_size)335*795d594fSAndroid Build Coastguard Worker inline ArtMethod* Class::GetVTableEntry(uint32_t i, PointerSize pointer_size) {
336*795d594fSAndroid Build Coastguard Worker   if (ShouldHaveEmbeddedVTable<kVerifyFlags>()) {
337*795d594fSAndroid Build Coastguard Worker     return GetEmbeddedVTableEntry(i, pointer_size);
338*795d594fSAndroid Build Coastguard Worker   }
339*795d594fSAndroid Build Coastguard Worker   ObjPtr<PointerArray> vtable = GetVTable<kVerifyFlags, kReadBarrierOption>();
340*795d594fSAndroid Build Coastguard Worker   DCHECK(vtable != nullptr);
341*795d594fSAndroid Build Coastguard Worker   return vtable->GetElementPtrSize<ArtMethod*, kVerifyFlags>(i, pointer_size);
342*795d594fSAndroid Build Coastguard Worker }
343*795d594fSAndroid Build Coastguard Worker 
344*795d594fSAndroid Build Coastguard Worker template<VerifyObjectFlags kVerifyFlags>
GetEmbeddedVTableLength()345*795d594fSAndroid Build Coastguard Worker inline int32_t Class::GetEmbeddedVTableLength() {
346*795d594fSAndroid Build Coastguard Worker   return GetField32<kVerifyFlags>(MemberOffset(EmbeddedVTableLengthOffset()));
347*795d594fSAndroid Build Coastguard Worker }
348*795d594fSAndroid Build Coastguard Worker 
SetEmbeddedVTableLength(int32_t len)349*795d594fSAndroid Build Coastguard Worker inline void Class::SetEmbeddedVTableLength(int32_t len) {
350*795d594fSAndroid Build Coastguard Worker   SetField32</*kTransactionActive=*/ false, /*kCheckTransaction=*/ false>(
351*795d594fSAndroid Build Coastguard Worker       MemberOffset(EmbeddedVTableLengthOffset()), len);
352*795d594fSAndroid Build Coastguard Worker }
353*795d594fSAndroid Build Coastguard Worker 
GetImt(PointerSize pointer_size)354*795d594fSAndroid Build Coastguard Worker inline ImTable* Class::GetImt(PointerSize pointer_size) {
355*795d594fSAndroid Build Coastguard Worker   return GetFieldPtrWithSize<ImTable*>(ImtPtrOffset(pointer_size), pointer_size);
356*795d594fSAndroid Build Coastguard Worker }
357*795d594fSAndroid Build Coastguard Worker 
SetImt(ImTable * imt,PointerSize pointer_size)358*795d594fSAndroid Build Coastguard Worker inline void Class::SetImt(ImTable* imt, PointerSize pointer_size) {
359*795d594fSAndroid Build Coastguard Worker   return SetFieldPtrWithSize</*kTransactionActive=*/ false, /*kCheckTransaction=*/ false>(
360*795d594fSAndroid Build Coastguard Worker       ImtPtrOffset(pointer_size), imt, pointer_size);
361*795d594fSAndroid Build Coastguard Worker }
362*795d594fSAndroid Build Coastguard Worker 
EmbeddedVTableEntryOffset(uint32_t i,PointerSize pointer_size)363*795d594fSAndroid Build Coastguard Worker inline MemberOffset Class::EmbeddedVTableEntryOffset(uint32_t i, PointerSize pointer_size) {
364*795d594fSAndroid Build Coastguard Worker   return MemberOffset(
365*795d594fSAndroid Build Coastguard Worker       EmbeddedVTableOffset(pointer_size).Uint32Value() + i * VTableEntrySize(pointer_size));
366*795d594fSAndroid Build Coastguard Worker }
367*795d594fSAndroid Build Coastguard Worker 
GetEmbeddedVTableEntry(uint32_t i,PointerSize pointer_size)368*795d594fSAndroid Build Coastguard Worker inline ArtMethod* Class::GetEmbeddedVTableEntry(uint32_t i, PointerSize pointer_size) {
369*795d594fSAndroid Build Coastguard Worker   return GetFieldPtrWithSize<ArtMethod*>(EmbeddedVTableEntryOffset(i, pointer_size), pointer_size);
370*795d594fSAndroid Build Coastguard Worker }
371*795d594fSAndroid Build Coastguard Worker 
SetEmbeddedVTableEntryUnchecked(uint32_t i,ArtMethod * method,PointerSize pointer_size)372*795d594fSAndroid Build Coastguard Worker inline void Class::SetEmbeddedVTableEntryUnchecked(
373*795d594fSAndroid Build Coastguard Worker     uint32_t i, ArtMethod* method, PointerSize pointer_size) {
374*795d594fSAndroid Build Coastguard Worker   SetFieldPtrWithSize</*kTransactionActive=*/ false, /*kCheckTransaction=*/ false>(
375*795d594fSAndroid Build Coastguard Worker       EmbeddedVTableEntryOffset(i, pointer_size), method, pointer_size);
376*795d594fSAndroid Build Coastguard Worker }
377*795d594fSAndroid Build Coastguard Worker 
SetEmbeddedVTableEntry(uint32_t i,ArtMethod * method,PointerSize pointer_size)378*795d594fSAndroid Build Coastguard Worker inline void Class::SetEmbeddedVTableEntry(uint32_t i, ArtMethod* method, PointerSize pointer_size) {
379*795d594fSAndroid Build Coastguard Worker   ObjPtr<PointerArray> vtable = GetVTableDuringLinking();
380*795d594fSAndroid Build Coastguard Worker   CHECK_EQ(method, vtable->GetElementPtrSize<ArtMethod*>(i, pointer_size));
381*795d594fSAndroid Build Coastguard Worker   SetEmbeddedVTableEntryUnchecked(i, method, pointer_size);
382*795d594fSAndroid Build Coastguard Worker }
383*795d594fSAndroid Build Coastguard Worker 
Implements(ObjPtr<Class> klass)384*795d594fSAndroid Build Coastguard Worker inline bool Class::Implements(ObjPtr<Class> klass) {
385*795d594fSAndroid Build Coastguard Worker   DCHECK(klass != nullptr);
386*795d594fSAndroid Build Coastguard Worker   DCHECK(klass->IsInterface()) << PrettyClass();
387*795d594fSAndroid Build Coastguard Worker   // All interfaces implemented directly and by our superclass, and
388*795d594fSAndroid Build Coastguard Worker   // recursively all super-interfaces of those interfaces, are listed
389*795d594fSAndroid Build Coastguard Worker   // in iftable_, so we can just do a linear scan through that.
390*795d594fSAndroid Build Coastguard Worker   int32_t iftable_count = GetIfTableCount();
391*795d594fSAndroid Build Coastguard Worker   ObjPtr<IfTable> iftable = GetIfTable();
392*795d594fSAndroid Build Coastguard Worker   for (int32_t i = 0; i < iftable_count; i++) {
393*795d594fSAndroid Build Coastguard Worker     if (iftable->GetInterface(i) == klass) {
394*795d594fSAndroid Build Coastguard Worker       return true;
395*795d594fSAndroid Build Coastguard Worker     }
396*795d594fSAndroid Build Coastguard Worker   }
397*795d594fSAndroid Build Coastguard Worker   return false;
398*795d594fSAndroid Build Coastguard Worker }
399*795d594fSAndroid Build Coastguard Worker 
400*795d594fSAndroid Build Coastguard Worker template<VerifyObjectFlags kVerifyFlags>
IsVariableSize()401*795d594fSAndroid Build Coastguard Worker inline bool Class::IsVariableSize() {
402*795d594fSAndroid Build Coastguard Worker   // Classes, arrays, and strings vary in size, and so the object_size_ field cannot
403*795d594fSAndroid Build Coastguard Worker   // be used to Get their instance size
404*795d594fSAndroid Build Coastguard Worker   return IsClassClass<kVerifyFlags>() ||
405*795d594fSAndroid Build Coastguard Worker          IsArrayClass<kVerifyFlags>() ||
406*795d594fSAndroid Build Coastguard Worker          IsStringClass<kVerifyFlags>();
407*795d594fSAndroid Build Coastguard Worker }
408*795d594fSAndroid Build Coastguard Worker 
SetObjectSize(uint32_t new_object_size)409*795d594fSAndroid Build Coastguard Worker inline void Class::SetObjectSize(uint32_t new_object_size) {
410*795d594fSAndroid Build Coastguard Worker   DCHECK(!IsVariableSize());
411*795d594fSAndroid Build Coastguard Worker   // Not called within a transaction.
412*795d594fSAndroid Build Coastguard Worker   return SetField32<false>(OFFSET_OF_OBJECT_MEMBER(Class, object_size_), new_object_size);
413*795d594fSAndroid Build Coastguard Worker }
414*795d594fSAndroid Build Coastguard Worker 
415*795d594fSAndroid Build Coastguard Worker template<typename T>
IsDiscoverable(bool public_only,const hiddenapi::AccessContext & access_context,T * member)416*795d594fSAndroid Build Coastguard Worker inline bool Class::IsDiscoverable(bool public_only,
417*795d594fSAndroid Build Coastguard Worker                                   const hiddenapi::AccessContext& access_context,
418*795d594fSAndroid Build Coastguard Worker                                   T* member) {
419*795d594fSAndroid Build Coastguard Worker   if (public_only && ((member->GetAccessFlags() & kAccPublic) == 0)) {
420*795d594fSAndroid Build Coastguard Worker     return false;
421*795d594fSAndroid Build Coastguard Worker   }
422*795d594fSAndroid Build Coastguard Worker 
423*795d594fSAndroid Build Coastguard Worker   return !hiddenapi::ShouldDenyAccessToMember(
424*795d594fSAndroid Build Coastguard Worker       member, access_context, hiddenapi::AccessMethod::kNone);
425*795d594fSAndroid Build Coastguard Worker }
426*795d594fSAndroid Build Coastguard Worker 
427*795d594fSAndroid Build Coastguard Worker // Determine whether "this" is assignable from "src", where both of these
428*795d594fSAndroid Build Coastguard Worker // are array classes.
429*795d594fSAndroid Build Coastguard Worker //
430*795d594fSAndroid Build Coastguard Worker // Consider an array class, e.g. Y[][], where Y is a subclass of X.
431*795d594fSAndroid Build Coastguard Worker //   Y[][]            = Y[][] --> true (identity)
432*795d594fSAndroid Build Coastguard Worker //   X[][]            = Y[][] --> true (element superclass)
433*795d594fSAndroid Build Coastguard Worker //   Y                = Y[][] --> false
434*795d594fSAndroid Build Coastguard Worker //   Y[]              = Y[][] --> false
435*795d594fSAndroid Build Coastguard Worker //   Object           = Y[][] --> true (everything is an object)
436*795d594fSAndroid Build Coastguard Worker //   Object[]         = Y[][] --> true
437*795d594fSAndroid Build Coastguard Worker //   Object[][]       = Y[][] --> true
438*795d594fSAndroid Build Coastguard Worker //   Object[][][]     = Y[][] --> false (too many []s)
439*795d594fSAndroid Build Coastguard Worker //   Serializable     = Y[][] --> true (all arrays are Serializable)
440*795d594fSAndroid Build Coastguard Worker //   Serializable[]   = Y[][] --> true
441*795d594fSAndroid Build Coastguard Worker //   Serializable[][] = Y[][] --> false (unless Y is Serializable)
442*795d594fSAndroid Build Coastguard Worker //
443*795d594fSAndroid Build Coastguard Worker // Don't forget about primitive types.
444*795d594fSAndroid Build Coastguard Worker //   Object[]         = int[] --> false
445*795d594fSAndroid Build Coastguard Worker //
IsArrayAssignableFromArray(ObjPtr<Class> src)446*795d594fSAndroid Build Coastguard Worker inline bool Class::IsArrayAssignableFromArray(ObjPtr<Class> src) {
447*795d594fSAndroid Build Coastguard Worker   DCHECK(IsArrayClass()) << PrettyClass();
448*795d594fSAndroid Build Coastguard Worker   DCHECK(src->IsArrayClass()) << src->PrettyClass();
449*795d594fSAndroid Build Coastguard Worker   return GetComponentType()->IsAssignableFrom(src->GetComponentType());
450*795d594fSAndroid Build Coastguard Worker }
451*795d594fSAndroid Build Coastguard Worker 
IsAssignableFromArray(ObjPtr<Class> src)452*795d594fSAndroid Build Coastguard Worker inline bool Class::IsAssignableFromArray(ObjPtr<Class> src) {
453*795d594fSAndroid Build Coastguard Worker   DCHECK(!IsInterface()) << PrettyClass();  // handled first in IsAssignableFrom
454*795d594fSAndroid Build Coastguard Worker   DCHECK(src->IsArrayClass()) << src->PrettyClass();
455*795d594fSAndroid Build Coastguard Worker   if (!IsArrayClass()) {
456*795d594fSAndroid Build Coastguard Worker     // If "this" is not also an array, it must be Object.
457*795d594fSAndroid Build Coastguard Worker     // src's super should be java_lang_Object, since it is an array.
458*795d594fSAndroid Build Coastguard Worker     ObjPtr<Class> java_lang_Object = src->GetSuperClass();
459*795d594fSAndroid Build Coastguard Worker     DCHECK(java_lang_Object != nullptr) << src->PrettyClass();
460*795d594fSAndroid Build Coastguard Worker     DCHECK(java_lang_Object->GetSuperClass() == nullptr) << src->PrettyClass();
461*795d594fSAndroid Build Coastguard Worker     return this == java_lang_Object;
462*795d594fSAndroid Build Coastguard Worker   }
463*795d594fSAndroid Build Coastguard Worker   return IsArrayAssignableFromArray(src);
464*795d594fSAndroid Build Coastguard Worker }
465*795d594fSAndroid Build Coastguard Worker 
466*795d594fSAndroid Build Coastguard Worker template <bool throw_on_failure>
ResolvedFieldAccessTest(ObjPtr<Class> access_to,ArtField * field,ObjPtr<DexCache> dex_cache,uint32_t field_idx)467*795d594fSAndroid Build Coastguard Worker inline bool Class::ResolvedFieldAccessTest(ObjPtr<Class> access_to,
468*795d594fSAndroid Build Coastguard Worker                                            ArtField* field,
469*795d594fSAndroid Build Coastguard Worker                                            ObjPtr<DexCache> dex_cache,
470*795d594fSAndroid Build Coastguard Worker                                            uint32_t field_idx) {
471*795d594fSAndroid Build Coastguard Worker   DCHECK(dex_cache != nullptr);
472*795d594fSAndroid Build Coastguard Worker   if (UNLIKELY(!this->CanAccess(access_to))) {
473*795d594fSAndroid Build Coastguard Worker     // The referrer class can't access the field's declaring class but may still be able
474*795d594fSAndroid Build Coastguard Worker     // to access the field if the FieldId specifies an accessible subclass of the declaring
475*795d594fSAndroid Build Coastguard Worker     // class rather than the declaring class itself.
476*795d594fSAndroid Build Coastguard Worker     dex::TypeIndex class_idx = dex_cache->GetDexFile()->GetFieldId(field_idx).class_idx_;
477*795d594fSAndroid Build Coastguard Worker     // The referenced class has already been resolved with the field, but may not be in the dex
478*795d594fSAndroid Build Coastguard Worker     // cache. Use LookupResolveType here to search the class table if it is not in the dex cache.
479*795d594fSAndroid Build Coastguard Worker     // should be no thread suspension due to the class being resolved.
480*795d594fSAndroid Build Coastguard Worker     ObjPtr<Class> dex_access_to = Runtime::Current()->GetClassLinker()->LookupResolvedType(
481*795d594fSAndroid Build Coastguard Worker         class_idx,
482*795d594fSAndroid Build Coastguard Worker         dex_cache,
483*795d594fSAndroid Build Coastguard Worker         GetClassLoader());
484*795d594fSAndroid Build Coastguard Worker     DCHECK(dex_access_to != nullptr);
485*795d594fSAndroid Build Coastguard Worker     if (UNLIKELY(!this->CanAccess(dex_access_to))) {
486*795d594fSAndroid Build Coastguard Worker       if (throw_on_failure) {
487*795d594fSAndroid Build Coastguard Worker         ThrowIllegalAccessErrorClass(this, dex_access_to);
488*795d594fSAndroid Build Coastguard Worker       }
489*795d594fSAndroid Build Coastguard Worker       return false;
490*795d594fSAndroid Build Coastguard Worker     }
491*795d594fSAndroid Build Coastguard Worker   }
492*795d594fSAndroid Build Coastguard Worker   if (LIKELY(this->CanAccessMember(access_to, field->GetAccessFlags()))) {
493*795d594fSAndroid Build Coastguard Worker     return true;
494*795d594fSAndroid Build Coastguard Worker   }
495*795d594fSAndroid Build Coastguard Worker   if (throw_on_failure) {
496*795d594fSAndroid Build Coastguard Worker     ThrowIllegalAccessErrorField(this, field);
497*795d594fSAndroid Build Coastguard Worker   }
498*795d594fSAndroid Build Coastguard Worker   return false;
499*795d594fSAndroid Build Coastguard Worker }
500*795d594fSAndroid Build Coastguard Worker 
CanAccessResolvedField(ObjPtr<Class> access_to,ArtField * field,ObjPtr<DexCache> dex_cache,uint32_t field_idx)501*795d594fSAndroid Build Coastguard Worker inline bool Class::CanAccessResolvedField(ObjPtr<Class> access_to,
502*795d594fSAndroid Build Coastguard Worker                                           ArtField* field,
503*795d594fSAndroid Build Coastguard Worker                                           ObjPtr<DexCache> dex_cache,
504*795d594fSAndroid Build Coastguard Worker                                           uint32_t field_idx) {
505*795d594fSAndroid Build Coastguard Worker   return ResolvedFieldAccessTest<false>(access_to, field, dex_cache, field_idx);
506*795d594fSAndroid Build Coastguard Worker }
507*795d594fSAndroid Build Coastguard Worker 
CheckResolvedFieldAccess(ObjPtr<Class> access_to,ArtField * field,ObjPtr<DexCache> dex_cache,uint32_t field_idx)508*795d594fSAndroid Build Coastguard Worker inline bool Class::CheckResolvedFieldAccess(ObjPtr<Class> access_to,
509*795d594fSAndroid Build Coastguard Worker                                             ArtField* field,
510*795d594fSAndroid Build Coastguard Worker                                             ObjPtr<DexCache> dex_cache,
511*795d594fSAndroid Build Coastguard Worker                                             uint32_t field_idx) {
512*795d594fSAndroid Build Coastguard Worker   return ResolvedFieldAccessTest<true>(access_to, field, dex_cache, field_idx);
513*795d594fSAndroid Build Coastguard Worker }
514*795d594fSAndroid Build Coastguard Worker 
IsObsoleteVersionOf(ObjPtr<Class> klass)515*795d594fSAndroid Build Coastguard Worker inline bool Class::IsObsoleteVersionOf(ObjPtr<Class> klass) {
516*795d594fSAndroid Build Coastguard Worker   DCHECK(!klass->IsObsoleteObject()) << klass->PrettyClass() << " is obsolete!";
517*795d594fSAndroid Build Coastguard Worker   if (LIKELY(!IsObsoleteObject())) {
518*795d594fSAndroid Build Coastguard Worker     return false;
519*795d594fSAndroid Build Coastguard Worker   }
520*795d594fSAndroid Build Coastguard Worker   ObjPtr<Class> current(klass);
521*795d594fSAndroid Build Coastguard Worker   do {
522*795d594fSAndroid Build Coastguard Worker     if (UNLIKELY(current == this)) {
523*795d594fSAndroid Build Coastguard Worker       return true;
524*795d594fSAndroid Build Coastguard Worker     } else {
525*795d594fSAndroid Build Coastguard Worker       current = current->GetObsoleteClass();
526*795d594fSAndroid Build Coastguard Worker     }
527*795d594fSAndroid Build Coastguard Worker   } while (!current.IsNull());
528*795d594fSAndroid Build Coastguard Worker   return false;
529*795d594fSAndroid Build Coastguard Worker }
530*795d594fSAndroid Build Coastguard Worker 
IsSubClass(ObjPtr<Class> klass)531*795d594fSAndroid Build Coastguard Worker inline bool Class::IsSubClass(ObjPtr<Class> klass) {
532*795d594fSAndroid Build Coastguard Worker   // Since the SubtypeCheck::IsSubtypeOf needs to lookup the Depth,
533*795d594fSAndroid Build Coastguard Worker   // it is always O(Depth) in terms of speed to do the check.
534*795d594fSAndroid Build Coastguard Worker   //
535*795d594fSAndroid Build Coastguard Worker   // So always do the "slow" linear scan in normal release builds.
536*795d594fSAndroid Build Coastguard Worker   //
537*795d594fSAndroid Build Coastguard Worker   // Future note: If we could have the depth in O(1) we could use the 'fast'
538*795d594fSAndroid Build Coastguard Worker   // method instead as it avoids a loop and a read barrier.
539*795d594fSAndroid Build Coastguard Worker   bool result = false;
540*795d594fSAndroid Build Coastguard Worker   DCHECK(!IsInterface()) << PrettyClass();
541*795d594fSAndroid Build Coastguard Worker   DCHECK(!IsArrayClass()) << PrettyClass();
542*795d594fSAndroid Build Coastguard Worker   ObjPtr<Class> current = this;
543*795d594fSAndroid Build Coastguard Worker   do {
544*795d594fSAndroid Build Coastguard Worker     if (current == klass) {
545*795d594fSAndroid Build Coastguard Worker       result = true;
546*795d594fSAndroid Build Coastguard Worker       break;
547*795d594fSAndroid Build Coastguard Worker     }
548*795d594fSAndroid Build Coastguard Worker     current = current->GetSuperClass();
549*795d594fSAndroid Build Coastguard Worker   } while (current != nullptr);
550*795d594fSAndroid Build Coastguard Worker 
551*795d594fSAndroid Build Coastguard Worker   if (kIsDebugBuild && kBitstringSubtypeCheckEnabled) {
552*795d594fSAndroid Build Coastguard Worker     ObjPtr<mirror::Class> dis(this);
553*795d594fSAndroid Build Coastguard Worker 
554*795d594fSAndroid Build Coastguard Worker     SubtypeCheckInfo::Result sc_result = SubtypeCheck<ObjPtr<Class>>::IsSubtypeOf(dis, klass);
555*795d594fSAndroid Build Coastguard Worker     if (sc_result != SubtypeCheckInfo::kUnknownSubtypeOf) {
556*795d594fSAndroid Build Coastguard Worker       // Note: The "kUnknownSubTypeOf" can be avoided if and only if:
557*795d594fSAndroid Build Coastguard Worker       //   SubtypeCheck::EnsureInitialized(source)
558*795d594fSAndroid Build Coastguard Worker       //       happens-before source.IsSubClass(target)
559*795d594fSAndroid Build Coastguard Worker       //   SubtypeCheck::EnsureAssigned(target).GetState() == Assigned
560*795d594fSAndroid Build Coastguard Worker       //       happens-before source.IsSubClass(target)
561*795d594fSAndroid Build Coastguard Worker       //
562*795d594fSAndroid Build Coastguard Worker       // When code generated by optimizing compiler executes this operation, both
563*795d594fSAndroid Build Coastguard Worker       // happens-before are guaranteed, so there is no fallback code there.
564*795d594fSAndroid Build Coastguard Worker       SubtypeCheckInfo::Result expected_result =
565*795d594fSAndroid Build Coastguard Worker           result ? SubtypeCheckInfo::kSubtypeOf : SubtypeCheckInfo::kNotSubtypeOf;
566*795d594fSAndroid Build Coastguard Worker       DCHECK_EQ(expected_result, sc_result)
567*795d594fSAndroid Build Coastguard Worker           << "source: " << PrettyClass() << "target: " << klass->PrettyClass();
568*795d594fSAndroid Build Coastguard Worker     }
569*795d594fSAndroid Build Coastguard Worker   }
570*795d594fSAndroid Build Coastguard Worker 
571*795d594fSAndroid Build Coastguard Worker   return result;
572*795d594fSAndroid Build Coastguard Worker }
573*795d594fSAndroid Build Coastguard Worker 
FindVirtualMethodForInterface(ArtMethod * method,PointerSize pointer_size)574*795d594fSAndroid Build Coastguard Worker inline ArtMethod* Class::FindVirtualMethodForInterface(ArtMethod* method,
575*795d594fSAndroid Build Coastguard Worker                                                        PointerSize pointer_size) {
576*795d594fSAndroid Build Coastguard Worker   ObjPtr<Class> declaring_class = method->GetDeclaringClass();
577*795d594fSAndroid Build Coastguard Worker   DCHECK(declaring_class != nullptr) << PrettyClass();
578*795d594fSAndroid Build Coastguard Worker   if (UNLIKELY(!declaring_class->IsInterface())) {
579*795d594fSAndroid Build Coastguard Worker     DCHECK(declaring_class->IsObjectClass()) << method->PrettyMethod();
580*795d594fSAndroid Build Coastguard Worker     DCHECK(method->IsPublic() && !method->IsStatic());
581*795d594fSAndroid Build Coastguard Worker     return FindVirtualMethodForVirtual(method, pointer_size);
582*795d594fSAndroid Build Coastguard Worker   }
583*795d594fSAndroid Build Coastguard Worker   DCHECK(!method->IsCopied());
584*795d594fSAndroid Build Coastguard Worker   // TODO cache to improve lookup speed
585*795d594fSAndroid Build Coastguard Worker   const int32_t iftable_count = GetIfTableCount();
586*795d594fSAndroid Build Coastguard Worker   ObjPtr<IfTable> iftable = GetIfTable();
587*795d594fSAndroid Build Coastguard Worker   for (int32_t i = 0; i < iftable_count; i++) {
588*795d594fSAndroid Build Coastguard Worker     if (iftable->GetInterface(i) == declaring_class) {
589*795d594fSAndroid Build Coastguard Worker       return iftable->GetMethodArray(i)->GetElementPtrSize<ArtMethod*>(
590*795d594fSAndroid Build Coastguard Worker           method->GetMethodIndex(), pointer_size);
591*795d594fSAndroid Build Coastguard Worker     }
592*795d594fSAndroid Build Coastguard Worker   }
593*795d594fSAndroid Build Coastguard Worker   return nullptr;
594*795d594fSAndroid Build Coastguard Worker }
595*795d594fSAndroid Build Coastguard Worker 
FindVirtualMethodForVirtual(ArtMethod * method,PointerSize pointer_size)596*795d594fSAndroid Build Coastguard Worker inline ArtMethod* Class::FindVirtualMethodForVirtual(ArtMethod* method, PointerSize pointer_size) {
597*795d594fSAndroid Build Coastguard Worker   // Only miranda or default methods may come from interfaces and be used as a virtual.
598*795d594fSAndroid Build Coastguard Worker   DCHECK(!method->GetDeclaringClass()->IsInterface() || method->IsDefault() || method->IsMiranda());
599*795d594fSAndroid Build Coastguard Worker   DCHECK(method->GetDeclaringClass()->IsAssignableFrom(this))
600*795d594fSAndroid Build Coastguard Worker       << "Method " << method->PrettyMethod()
601*795d594fSAndroid Build Coastguard Worker       << " is not declared in " << PrettyDescriptor() << " or its super classes";
602*795d594fSAndroid Build Coastguard Worker   // The argument method may from a super class.
603*795d594fSAndroid Build Coastguard Worker   // Use the index to a potentially overridden one for this instance's class.
604*795d594fSAndroid Build Coastguard Worker   return GetVTableEntry(method->GetMethodIndex(), pointer_size);
605*795d594fSAndroid Build Coastguard Worker }
606*795d594fSAndroid Build Coastguard Worker 
FindVirtualMethodForSuper(ArtMethod * method,PointerSize pointer_size)607*795d594fSAndroid Build Coastguard Worker inline ArtMethod* Class::FindVirtualMethodForSuper(ArtMethod* method, PointerSize pointer_size) {
608*795d594fSAndroid Build Coastguard Worker   DCHECK(!method->GetDeclaringClass()->IsInterface());
609*795d594fSAndroid Build Coastguard Worker   DCHECK(method->GetDeclaringClass()->IsAssignableFrom(this))
610*795d594fSAndroid Build Coastguard Worker       << "Method " << method->PrettyMethod()
611*795d594fSAndroid Build Coastguard Worker       << " is not declared in " << PrettyDescriptor() << " or its super classes";
612*795d594fSAndroid Build Coastguard Worker   return GetSuperClass()->GetVTableEntry(method->GetMethodIndex(), pointer_size);
613*795d594fSAndroid Build Coastguard Worker }
614*795d594fSAndroid Build Coastguard Worker 
FindVirtualMethodForVirtualOrInterface(ArtMethod * method,PointerSize pointer_size)615*795d594fSAndroid Build Coastguard Worker inline ArtMethod* Class::FindVirtualMethodForVirtualOrInterface(ArtMethod* method,
616*795d594fSAndroid Build Coastguard Worker                                                                 PointerSize pointer_size) {
617*795d594fSAndroid Build Coastguard Worker   if (method->IsDirect()) {
618*795d594fSAndroid Build Coastguard Worker     return method;
619*795d594fSAndroid Build Coastguard Worker   }
620*795d594fSAndroid Build Coastguard Worker   if (method->GetDeclaringClass()->IsInterface() && !method->IsCopied()) {
621*795d594fSAndroid Build Coastguard Worker     return FindVirtualMethodForInterface(method, pointer_size);
622*795d594fSAndroid Build Coastguard Worker   }
623*795d594fSAndroid Build Coastguard Worker   return FindVirtualMethodForVirtual(method, pointer_size);
624*795d594fSAndroid Build Coastguard Worker }
625*795d594fSAndroid Build Coastguard Worker 
626*795d594fSAndroid Build Coastguard Worker template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
GetIfTable()627*795d594fSAndroid Build Coastguard Worker inline ObjPtr<IfTable> Class::GetIfTable() {
628*795d594fSAndroid Build Coastguard Worker   ObjPtr<IfTable> ret = GetFieldObject<IfTable, kVerifyFlags, kReadBarrierOption>(IfTableOffset());
629*795d594fSAndroid Build Coastguard Worker   DCHECK(ret != nullptr) << PrettyClass(this);
630*795d594fSAndroid Build Coastguard Worker   return ret;
631*795d594fSAndroid Build Coastguard Worker }
632*795d594fSAndroid Build Coastguard Worker 
633*795d594fSAndroid Build Coastguard Worker template<VerifyObjectFlags kVerifyFlags>
GetIfTableCount()634*795d594fSAndroid Build Coastguard Worker inline int32_t Class::GetIfTableCount() {
635*795d594fSAndroid Build Coastguard Worker   // We do not need a read barrier here as the length is constant,
636*795d594fSAndroid Build Coastguard Worker   // both from-space and to-space iftables shall yield the same result.
637*795d594fSAndroid Build Coastguard Worker   return GetIfTable<kVerifyFlags, kWithoutReadBarrier>()->Count();
638*795d594fSAndroid Build Coastguard Worker }
639*795d594fSAndroid Build Coastguard Worker 
SetIfTable(ObjPtr<IfTable> new_iftable)640*795d594fSAndroid Build Coastguard Worker inline void Class::SetIfTable(ObjPtr<IfTable> new_iftable) {
641*795d594fSAndroid Build Coastguard Worker   DCHECK(new_iftable != nullptr) << PrettyClass(this);
642*795d594fSAndroid Build Coastguard Worker   SetFieldObject</*kTransactionActive=*/ false, /*kCheckTransaction=*/ false>(
643*795d594fSAndroid Build Coastguard Worker       IfTableOffset(), new_iftable);
644*795d594fSAndroid Build Coastguard Worker }
645*795d594fSAndroid Build Coastguard Worker 
GetIFieldsPtr()646*795d594fSAndroid Build Coastguard Worker inline LengthPrefixedArray<ArtField>* Class::GetIFieldsPtr() {
647*795d594fSAndroid Build Coastguard Worker   DCHECK(IsLoaded() || IsErroneous()) << GetStatus();
648*795d594fSAndroid Build Coastguard Worker   return GetFieldPtr<LengthPrefixedArray<ArtField>*>(OFFSET_OF_OBJECT_MEMBER(Class, ifields_));
649*795d594fSAndroid Build Coastguard Worker }
650*795d594fSAndroid Build Coastguard Worker 
651*795d594fSAndroid Build Coastguard Worker template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
GetFirstReferenceInstanceFieldOffset()652*795d594fSAndroid Build Coastguard Worker inline MemberOffset Class::GetFirstReferenceInstanceFieldOffset() {
653*795d594fSAndroid Build Coastguard Worker   ObjPtr<Class> super_class = GetSuperClass<kVerifyFlags, kReadBarrierOption>();
654*795d594fSAndroid Build Coastguard Worker   return (super_class != nullptr)
655*795d594fSAndroid Build Coastguard Worker       ? MemberOffset(RoundUp(super_class->GetObjectSize<kVerifyFlags>(), kHeapReferenceSize))
656*795d594fSAndroid Build Coastguard Worker       : ClassOffset();
657*795d594fSAndroid Build Coastguard Worker }
658*795d594fSAndroid Build Coastguard Worker 
659*795d594fSAndroid Build Coastguard Worker template <VerifyObjectFlags kVerifyFlags>
GetFirstReferenceStaticFieldOffset(PointerSize pointer_size)660*795d594fSAndroid Build Coastguard Worker inline MemberOffset Class::GetFirstReferenceStaticFieldOffset(PointerSize pointer_size) {
661*795d594fSAndroid Build Coastguard Worker   DCHECK(IsResolved<kVerifyFlags>());
662*795d594fSAndroid Build Coastguard Worker   uint32_t base = sizeof(Class);  // Static fields come after the class.
663*795d594fSAndroid Build Coastguard Worker   if (ShouldHaveEmbeddedVTable<kVerifyFlags>()) {
664*795d594fSAndroid Build Coastguard Worker     // Static fields come after the embedded tables.
665*795d594fSAndroid Build Coastguard Worker     base = Class::ComputeClassSize(
666*795d594fSAndroid Build Coastguard Worker         true, GetEmbeddedVTableLength<kVerifyFlags>(), 0, 0, 0, 0, 0, 0, pointer_size);
667*795d594fSAndroid Build Coastguard Worker   }
668*795d594fSAndroid Build Coastguard Worker   return MemberOffset(base);
669*795d594fSAndroid Build Coastguard Worker }
670*795d594fSAndroid Build Coastguard Worker 
GetFirstReferenceStaticFieldOffsetDuringLinking(PointerSize pointer_size)671*795d594fSAndroid Build Coastguard Worker inline MemberOffset Class::GetFirstReferenceStaticFieldOffsetDuringLinking(
672*795d594fSAndroid Build Coastguard Worker     PointerSize pointer_size) {
673*795d594fSAndroid Build Coastguard Worker   DCHECK(IsLoaded());
674*795d594fSAndroid Build Coastguard Worker   uint32_t base = sizeof(Class);  // Static fields come after the class.
675*795d594fSAndroid Build Coastguard Worker   if (ShouldHaveEmbeddedVTable()) {
676*795d594fSAndroid Build Coastguard Worker     // Static fields come after the embedded tables.
677*795d594fSAndroid Build Coastguard Worker     base = Class::ComputeClassSize(
678*795d594fSAndroid Build Coastguard Worker         true, GetVTableDuringLinking()->GetLength(), 0, 0, 0, 0, 0, 0, pointer_size);
679*795d594fSAndroid Build Coastguard Worker   }
680*795d594fSAndroid Build Coastguard Worker   return MemberOffset(base);
681*795d594fSAndroid Build Coastguard Worker }
682*795d594fSAndroid Build Coastguard Worker 
SetIFieldsPtr(LengthPrefixedArray<ArtField> * new_ifields)683*795d594fSAndroid Build Coastguard Worker inline void Class::SetIFieldsPtr(LengthPrefixedArray<ArtField>* new_ifields) {
684*795d594fSAndroid Build Coastguard Worker   DCHECK(GetIFieldsPtrUnchecked() == nullptr);
685*795d594fSAndroid Build Coastguard Worker   return SetFieldPtr<false>(OFFSET_OF_OBJECT_MEMBER(Class, ifields_), new_ifields);
686*795d594fSAndroid Build Coastguard Worker }
687*795d594fSAndroid Build Coastguard Worker 
SetIFieldsPtrUnchecked(LengthPrefixedArray<ArtField> * new_ifields)688*795d594fSAndroid Build Coastguard Worker inline void Class::SetIFieldsPtrUnchecked(LengthPrefixedArray<ArtField>* new_ifields) {
689*795d594fSAndroid Build Coastguard Worker   SetFieldPtr<false, true, kVerifyNone>(OFFSET_OF_OBJECT_MEMBER(Class, ifields_), new_ifields);
690*795d594fSAndroid Build Coastguard Worker }
691*795d594fSAndroid Build Coastguard Worker 
GetSFieldsPtrUnchecked()692*795d594fSAndroid Build Coastguard Worker inline LengthPrefixedArray<ArtField>* Class::GetSFieldsPtrUnchecked() {
693*795d594fSAndroid Build Coastguard Worker   return GetFieldPtr<LengthPrefixedArray<ArtField>*>(OFFSET_OF_OBJECT_MEMBER(Class, sfields_));
694*795d594fSAndroid Build Coastguard Worker }
695*795d594fSAndroid Build Coastguard Worker 
GetIFieldsPtrUnchecked()696*795d594fSAndroid Build Coastguard Worker inline LengthPrefixedArray<ArtField>* Class::GetIFieldsPtrUnchecked() {
697*795d594fSAndroid Build Coastguard Worker   return GetFieldPtr<LengthPrefixedArray<ArtField>*>(OFFSET_OF_OBJECT_MEMBER(Class, ifields_));
698*795d594fSAndroid Build Coastguard Worker }
699*795d594fSAndroid Build Coastguard Worker 
GetSFieldsPtr()700*795d594fSAndroid Build Coastguard Worker inline LengthPrefixedArray<ArtField>* Class::GetSFieldsPtr() {
701*795d594fSAndroid Build Coastguard Worker   DCHECK(IsLoaded() || IsErroneous()) << GetStatus();
702*795d594fSAndroid Build Coastguard Worker   return GetSFieldsPtrUnchecked();
703*795d594fSAndroid Build Coastguard Worker }
704*795d594fSAndroid Build Coastguard Worker 
SetSFieldsPtr(LengthPrefixedArray<ArtField> * new_sfields)705*795d594fSAndroid Build Coastguard Worker inline void Class::SetSFieldsPtr(LengthPrefixedArray<ArtField>* new_sfields) {
706*795d594fSAndroid Build Coastguard Worker   DCHECK((IsRetired() && new_sfields == nullptr) ||
707*795d594fSAndroid Build Coastguard Worker          GetFieldPtr<ArtField*>(OFFSET_OF_OBJECT_MEMBER(Class, sfields_)) == nullptr);
708*795d594fSAndroid Build Coastguard Worker   SetFieldPtr<false>(OFFSET_OF_OBJECT_MEMBER(Class, sfields_), new_sfields);
709*795d594fSAndroid Build Coastguard Worker }
710*795d594fSAndroid Build Coastguard Worker 
SetSFieldsPtrUnchecked(LengthPrefixedArray<ArtField> * new_sfields)711*795d594fSAndroid Build Coastguard Worker inline void Class::SetSFieldsPtrUnchecked(LengthPrefixedArray<ArtField>* new_sfields) {
712*795d594fSAndroid Build Coastguard Worker   SetFieldPtr<false, true, kVerifyNone>(OFFSET_OF_OBJECT_MEMBER(Class, sfields_), new_sfields);
713*795d594fSAndroid Build Coastguard Worker }
714*795d594fSAndroid Build Coastguard Worker 
GetStaticField(uint32_t i)715*795d594fSAndroid Build Coastguard Worker inline ArtField* Class::GetStaticField(uint32_t i) {
716*795d594fSAndroid Build Coastguard Worker   return &GetSFieldsPtr()->At(i);
717*795d594fSAndroid Build Coastguard Worker }
718*795d594fSAndroid Build Coastguard Worker 
GetInstanceField(uint32_t i)719*795d594fSAndroid Build Coastguard Worker inline ArtField* Class::GetInstanceField(uint32_t i) {
720*795d594fSAndroid Build Coastguard Worker   return &GetIFieldsPtr()->At(i);
721*795d594fSAndroid Build Coastguard Worker }
722*795d594fSAndroid Build Coastguard Worker 
723*795d594fSAndroid Build Coastguard Worker template<VerifyObjectFlags kVerifyFlags>
GetReferenceInstanceOffsets()724*795d594fSAndroid Build Coastguard Worker inline uint32_t Class::GetReferenceInstanceOffsets() {
725*795d594fSAndroid Build Coastguard Worker   DCHECK(IsResolved<kVerifyFlags>() || IsErroneous<kVerifyFlags>());
726*795d594fSAndroid Build Coastguard Worker   return GetField32<kVerifyFlags>(OFFSET_OF_OBJECT_MEMBER(Class, reference_instance_offsets_));
727*795d594fSAndroid Build Coastguard Worker }
728*795d594fSAndroid Build Coastguard Worker 
SetClinitThreadId(pid_t new_clinit_thread_id)729*795d594fSAndroid Build Coastguard Worker inline void Class::SetClinitThreadId(pid_t new_clinit_thread_id) {
730*795d594fSAndroid Build Coastguard Worker   SetField32Transaction(OFFSET_OF_OBJECT_MEMBER(Class, clinit_thread_id_), new_clinit_thread_id);
731*795d594fSAndroid Build Coastguard Worker }
732*795d594fSAndroid Build Coastguard Worker 
733*795d594fSAndroid Build Coastguard Worker template<VerifyObjectFlags kVerifyFlags,
734*795d594fSAndroid Build Coastguard Worker          ReadBarrierOption kReadBarrierOption>
GetName()735*795d594fSAndroid Build Coastguard Worker inline ObjPtr<String> Class::GetName() {
736*795d594fSAndroid Build Coastguard Worker   return GetFieldObject<String, kVerifyFlags, kReadBarrierOption>(
737*795d594fSAndroid Build Coastguard Worker       OFFSET_OF_OBJECT_MEMBER(Class, name_));
738*795d594fSAndroid Build Coastguard Worker }
739*795d594fSAndroid Build Coastguard Worker 
SetName(ObjPtr<String> name)740*795d594fSAndroid Build Coastguard Worker inline void Class::SetName(ObjPtr<String> name) {
741*795d594fSAndroid Build Coastguard Worker   SetFieldObjectTransaction(OFFSET_OF_OBJECT_MEMBER(Class, name_), name);
742*795d594fSAndroid Build Coastguard Worker }
743*795d594fSAndroid Build Coastguard Worker 
744*795d594fSAndroid Build Coastguard Worker template<VerifyObjectFlags kVerifyFlags>
GetPrimitiveType()745*795d594fSAndroid Build Coastguard Worker inline Primitive::Type Class::GetPrimitiveType() {
746*795d594fSAndroid Build Coastguard Worker   static_assert(sizeof(Primitive::Type) == sizeof(int32_t),
747*795d594fSAndroid Build Coastguard Worker                 "art::Primitive::Type and int32_t have different sizes.");
748*795d594fSAndroid Build Coastguard Worker   int32_t v32 = GetField32<kVerifyFlags>(OFFSET_OF_OBJECT_MEMBER(Class, primitive_type_));
749*795d594fSAndroid Build Coastguard Worker   Primitive::Type type = static_cast<Primitive::Type>(v32 & kPrimitiveTypeMask);
750*795d594fSAndroid Build Coastguard Worker   DCHECK_EQ(static_cast<size_t>(v32 >> kPrimitiveTypeSizeShiftShift),
751*795d594fSAndroid Build Coastguard Worker             Primitive::ComponentSizeShift(type));
752*795d594fSAndroid Build Coastguard Worker   return type;
753*795d594fSAndroid Build Coastguard Worker }
754*795d594fSAndroid Build Coastguard Worker 
755*795d594fSAndroid Build Coastguard Worker template<VerifyObjectFlags kVerifyFlags>
GetPrimitiveTypeSizeShift()756*795d594fSAndroid Build Coastguard Worker inline size_t Class::GetPrimitiveTypeSizeShift() {
757*795d594fSAndroid Build Coastguard Worker   static_assert(sizeof(Primitive::Type) == sizeof(int32_t),
758*795d594fSAndroid Build Coastguard Worker                 "art::Primitive::Type and int32_t have different sizes.");
759*795d594fSAndroid Build Coastguard Worker   int32_t v32 = GetField32<kVerifyFlags>(OFFSET_OF_OBJECT_MEMBER(Class, primitive_type_));
760*795d594fSAndroid Build Coastguard Worker   size_t size_shift = static_cast<Primitive::Type>(v32 >> kPrimitiveTypeSizeShiftShift);
761*795d594fSAndroid Build Coastguard Worker   DCHECK_EQ(size_shift,
762*795d594fSAndroid Build Coastguard Worker             Primitive::ComponentSizeShift(static_cast<Primitive::Type>(v32 & kPrimitiveTypeMask)));
763*795d594fSAndroid Build Coastguard Worker   return size_shift;
764*795d594fSAndroid Build Coastguard Worker }
765*795d594fSAndroid Build Coastguard Worker 
766*795d594fSAndroid Build Coastguard Worker template <VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
VerifyOverflowReferenceBitmap()767*795d594fSAndroid Build Coastguard Worker inline void Class::VerifyOverflowReferenceBitmap() {
768*795d594fSAndroid Build Coastguard Worker   // Can't reliably access super-classes during CMC compaction.
769*795d594fSAndroid Build Coastguard Worker   if (Runtime::Current() != nullptr && Runtime::Current()->GetHeap() != nullptr &&
770*795d594fSAndroid Build Coastguard Worker       Runtime::Current()->GetHeap()->IsPerformingUffdCompaction()) {
771*795d594fSAndroid Build Coastguard Worker     return;
772*795d594fSAndroid Build Coastguard Worker   }
773*795d594fSAndroid Build Coastguard Worker   CHECK(!IsVariableSize<kVerifyFlags>());
774*795d594fSAndroid Build Coastguard Worker   ObjPtr<Class> klass;
775*795d594fSAndroid Build Coastguard Worker   ObjPtr<mirror::Class> super_class;
776*795d594fSAndroid Build Coastguard Worker   size_t num_bits =
777*795d594fSAndroid Build Coastguard Worker       (RoundUp(GetObjectSize<kVerifyFlags>(), sizeof(mirror::HeapReference<mirror::Object>)) -
778*795d594fSAndroid Build Coastguard Worker        mirror::kObjectHeaderSize) /
779*795d594fSAndroid Build Coastguard Worker       sizeof(mirror::HeapReference<mirror::Object>);
780*795d594fSAndroid Build Coastguard Worker   std::vector<bool> check_bitmap(num_bits, false);
781*795d594fSAndroid Build Coastguard Worker   for (klass = this; klass != nullptr; klass = super_class) {
782*795d594fSAndroid Build Coastguard Worker     super_class = klass->GetSuperClass<kVerifyFlags, kReadBarrierOption>();
783*795d594fSAndroid Build Coastguard Worker     if (klass->NumReferenceInstanceFields<kVerifyFlags>() != 0) {
784*795d594fSAndroid Build Coastguard Worker       break;
785*795d594fSAndroid Build Coastguard Worker     }
786*795d594fSAndroid Build Coastguard Worker   }
787*795d594fSAndroid Build Coastguard Worker 
788*795d594fSAndroid Build Coastguard Worker   if (super_class != nullptr) {
789*795d594fSAndroid Build Coastguard Worker     std::vector<ObjPtr<Class>> klasses;
790*795d594fSAndroid Build Coastguard Worker     for (; klass != nullptr; klass = super_class) {
791*795d594fSAndroid Build Coastguard Worker       super_class = klass->GetSuperClass<kVerifyFlags, kReadBarrierOption>();
792*795d594fSAndroid Build Coastguard Worker       if (super_class != nullptr) {
793*795d594fSAndroid Build Coastguard Worker         klasses.push_back(klass);
794*795d594fSAndroid Build Coastguard Worker       }
795*795d594fSAndroid Build Coastguard Worker     }
796*795d594fSAndroid Build Coastguard Worker 
797*795d594fSAndroid Build Coastguard Worker     for (auto iter = klasses.rbegin(); iter != klasses.rend(); iter++) {
798*795d594fSAndroid Build Coastguard Worker       klass = *iter;
799*795d594fSAndroid Build Coastguard Worker       size_t idx = (klass->GetFirstReferenceInstanceFieldOffset<kVerifyFlags, kReadBarrierOption>()
800*795d594fSAndroid Build Coastguard Worker                         .Uint32Value() -
801*795d594fSAndroid Build Coastguard Worker                     mirror::kObjectHeaderSize) /
802*795d594fSAndroid Build Coastguard Worker                    sizeof(mirror::HeapReference<mirror::Object>);
803*795d594fSAndroid Build Coastguard Worker       uint32_t num_refs = klass->NumReferenceInstanceFields<kVerifyFlags>();
804*795d594fSAndroid Build Coastguard Worker       for (uint32_t i = 0; i < num_refs; i++) {
805*795d594fSAndroid Build Coastguard Worker         check_bitmap[idx++] = true;
806*795d594fSAndroid Build Coastguard Worker       }
807*795d594fSAndroid Build Coastguard Worker       CHECK_LE(idx, num_bits) << PrettyClass();
808*795d594fSAndroid Build Coastguard Worker     }
809*795d594fSAndroid Build Coastguard Worker   }
810*795d594fSAndroid Build Coastguard Worker 
811*795d594fSAndroid Build Coastguard Worker   uint32_t ref_offsets =
812*795d594fSAndroid Build Coastguard Worker       GetField32<kVerifyFlags>(OFFSET_OF_OBJECT_MEMBER(Class, reference_instance_offsets_));
813*795d594fSAndroid Build Coastguard Worker   CHECK_NE(ref_offsets, 0u) << PrettyClass();
814*795d594fSAndroid Build Coastguard Worker   CHECK((ref_offsets & kVisitReferencesSlowpathMask) != 0) << PrettyClass();
815*795d594fSAndroid Build Coastguard Worker   uint32_t bitmap_num_words = ref_offsets & ~kVisitReferencesSlowpathMask;
816*795d594fSAndroid Build Coastguard Worker   uint32_t* overflow_bitmap = reinterpret_cast<uint32_t*>(
817*795d594fSAndroid Build Coastguard Worker       reinterpret_cast<uint8_t*>(this) +
818*795d594fSAndroid Build Coastguard Worker       (GetClassSize<kVerifyFlags>() - bitmap_num_words * sizeof(uint32_t)));
819*795d594fSAndroid Build Coastguard Worker   for (uint32_t i = 0, field_offset = 0; i < bitmap_num_words; i++, field_offset += 32) {
820*795d594fSAndroid Build Coastguard Worker     ref_offsets = overflow_bitmap[i];
821*795d594fSAndroid Build Coastguard Worker     uint32_t check_bitmap_idx = field_offset;
822*795d594fSAndroid Build Coastguard Worker     // Confirm that all the bits in check_bitmap that ought to be set, are set.
823*795d594fSAndroid Build Coastguard Worker     while (ref_offsets != 0) {
824*795d594fSAndroid Build Coastguard Worker       if ((ref_offsets & 1) != 0) {
825*795d594fSAndroid Build Coastguard Worker         CHECK(check_bitmap[check_bitmap_idx])
826*795d594fSAndroid Build Coastguard Worker             << PrettyClass() << " i:" << i << " field_offset:" << field_offset
827*795d594fSAndroid Build Coastguard Worker             << " check_bitmap_idx:" << check_bitmap_idx << " bitmap_word:" << overflow_bitmap[i];
828*795d594fSAndroid Build Coastguard Worker         check_bitmap[check_bitmap_idx] = false;
829*795d594fSAndroid Build Coastguard Worker       }
830*795d594fSAndroid Build Coastguard Worker       ref_offsets >>= 1;
831*795d594fSAndroid Build Coastguard Worker       check_bitmap_idx++;
832*795d594fSAndroid Build Coastguard Worker     }
833*795d594fSAndroid Build Coastguard Worker   }
834*795d594fSAndroid Build Coastguard Worker   // Confirm that there is no other bit set.
835*795d594fSAndroid Build Coastguard Worker   std::ostringstream oss;
836*795d594fSAndroid Build Coastguard Worker   bool found = false;
837*795d594fSAndroid Build Coastguard Worker   for (size_t i = 0; i < check_bitmap.size(); i++) {
838*795d594fSAndroid Build Coastguard Worker     if (check_bitmap[i]) {
839*795d594fSAndroid Build Coastguard Worker       if (!found) {
840*795d594fSAndroid Build Coastguard Worker         DumpClass(oss, kDumpClassFullDetail);
841*795d594fSAndroid Build Coastguard Worker         oss << " set-bits:";
842*795d594fSAndroid Build Coastguard Worker       }
843*795d594fSAndroid Build Coastguard Worker       found = true;
844*795d594fSAndroid Build Coastguard Worker       oss << i << ",";
845*795d594fSAndroid Build Coastguard Worker     }
846*795d594fSAndroid Build Coastguard Worker   }
847*795d594fSAndroid Build Coastguard Worker   if (found) {
848*795d594fSAndroid Build Coastguard Worker     oss << " stored-bitmap:";
849*795d594fSAndroid Build Coastguard Worker     for (size_t i = 0; i < bitmap_num_words; i++) {
850*795d594fSAndroid Build Coastguard Worker       oss << overflow_bitmap[i] << ":";
851*795d594fSAndroid Build Coastguard Worker     }
852*795d594fSAndroid Build Coastguard Worker     LOG(FATAL) << oss.str();
853*795d594fSAndroid Build Coastguard Worker   }
854*795d594fSAndroid Build Coastguard Worker }
855*795d594fSAndroid Build Coastguard Worker 
AdjustClassSizeForReferenceOffsetBitmapDuringLinking(ObjPtr<Class> klass,size_t class_size)856*795d594fSAndroid Build Coastguard Worker inline size_t Class::AdjustClassSizeForReferenceOffsetBitmapDuringLinking(ObjPtr<Class> klass,
857*795d594fSAndroid Build Coastguard Worker                                                                           size_t class_size) {
858*795d594fSAndroid Build Coastguard Worker   if (klass->IsInstantiable()) {
859*795d594fSAndroid Build Coastguard Worker     // Find the first class with non-zero instance field count and its super-class'
860*795d594fSAndroid Build Coastguard Worker     // object-size together will tell us the required size.
861*795d594fSAndroid Build Coastguard Worker     for (ObjPtr<Class> k = klass; k != nullptr; k = k->GetSuperClass()) {
862*795d594fSAndroid Build Coastguard Worker       size_t num_reference_fields = k->NumReferenceInstanceFieldsDuringLinking();
863*795d594fSAndroid Build Coastguard Worker       if (num_reference_fields != 0) {
864*795d594fSAndroid Build Coastguard Worker         ObjPtr<Class> super = k->GetSuperClass();
865*795d594fSAndroid Build Coastguard Worker         // Leave it for mirror::Object (the class field is handled specially).
866*795d594fSAndroid Build Coastguard Worker         if (super != nullptr) {
867*795d594fSAndroid Build Coastguard Worker           // All of the fields that contain object references are guaranteed to be grouped in
868*795d594fSAndroid Build Coastguard Worker           // memory starting at an appropriately aligned address after super class object data.
869*795d594fSAndroid Build Coastguard Worker           uint32_t start_offset =
870*795d594fSAndroid Build Coastguard Worker               RoundUp(super->GetObjectSize(), sizeof(mirror::HeapReference<mirror::Object>));
871*795d594fSAndroid Build Coastguard Worker           uint32_t start_bit = (start_offset - mirror::kObjectHeaderSize) /
872*795d594fSAndroid Build Coastguard Worker                                sizeof(mirror::HeapReference<mirror::Object>);
873*795d594fSAndroid Build Coastguard Worker           if (start_bit + num_reference_fields > 31) {
874*795d594fSAndroid Build Coastguard Worker             // Alignment that maybe required at the end of static fields smaller than 32-bit.
875*795d594fSAndroid Build Coastguard Worker             class_size = RoundUp(class_size, sizeof(uint32_t));
876*795d594fSAndroid Build Coastguard Worker             // 32-bit words required for the overflow bitmap.
877*795d594fSAndroid Build Coastguard Worker             class_size += RoundUp(start_bit + num_reference_fields, 32) / 32 * sizeof(uint32_t);
878*795d594fSAndroid Build Coastguard Worker           }
879*795d594fSAndroid Build Coastguard Worker         }
880*795d594fSAndroid Build Coastguard Worker         break;
881*795d594fSAndroid Build Coastguard Worker       }
882*795d594fSAndroid Build Coastguard Worker     }
883*795d594fSAndroid Build Coastguard Worker   }
884*795d594fSAndroid Build Coastguard Worker   return class_size;
885*795d594fSAndroid Build Coastguard Worker }
886*795d594fSAndroid Build Coastguard Worker 
ComputeClassSize(bool has_embedded_vtable,uint32_t num_vtable_entries,uint32_t num_8bit_static_fields,uint32_t num_16bit_static_fields,uint32_t num_32bit_static_fields,uint32_t num_64bit_static_fields,uint32_t num_ref_static_fields,uint32_t num_ref_bitmap_entries,PointerSize pointer_size)887*795d594fSAndroid Build Coastguard Worker inline uint32_t Class::ComputeClassSize(bool has_embedded_vtable,
888*795d594fSAndroid Build Coastguard Worker                                         uint32_t num_vtable_entries,
889*795d594fSAndroid Build Coastguard Worker                                         uint32_t num_8bit_static_fields,
890*795d594fSAndroid Build Coastguard Worker                                         uint32_t num_16bit_static_fields,
891*795d594fSAndroid Build Coastguard Worker                                         uint32_t num_32bit_static_fields,
892*795d594fSAndroid Build Coastguard Worker                                         uint32_t num_64bit_static_fields,
893*795d594fSAndroid Build Coastguard Worker                                         uint32_t num_ref_static_fields,
894*795d594fSAndroid Build Coastguard Worker                                         uint32_t num_ref_bitmap_entries,
895*795d594fSAndroid Build Coastguard Worker                                         PointerSize pointer_size) {
896*795d594fSAndroid Build Coastguard Worker   // Space used by java.lang.Class and its instance fields.
897*795d594fSAndroid Build Coastguard Worker   uint32_t size = sizeof(Class);
898*795d594fSAndroid Build Coastguard Worker   // Space used by embedded tables.
899*795d594fSAndroid Build Coastguard Worker   if (has_embedded_vtable) {
900*795d594fSAndroid Build Coastguard Worker     size = RoundUp(size + sizeof(uint32_t), static_cast<size_t>(pointer_size));
901*795d594fSAndroid Build Coastguard Worker     size += static_cast<size_t>(pointer_size);  // size of pointer to IMT
902*795d594fSAndroid Build Coastguard Worker     size += num_vtable_entries * VTableEntrySize(pointer_size);
903*795d594fSAndroid Build Coastguard Worker   }
904*795d594fSAndroid Build Coastguard Worker 
905*795d594fSAndroid Build Coastguard Worker   // Space used by reference statics.
906*795d594fSAndroid Build Coastguard Worker   size += num_ref_static_fields * kHeapReferenceSize;
907*795d594fSAndroid Build Coastguard Worker   if (!IsAligned<8>(size) && num_64bit_static_fields > 0) {
908*795d594fSAndroid Build Coastguard Worker     uint32_t gap = 8 - (size & 0x7);
909*795d594fSAndroid Build Coastguard Worker     size += gap;  // will be padded
910*795d594fSAndroid Build Coastguard Worker     // Shuffle 4-byte fields forward.
911*795d594fSAndroid Build Coastguard Worker     while (gap >= sizeof(uint32_t) && num_32bit_static_fields != 0) {
912*795d594fSAndroid Build Coastguard Worker       --num_32bit_static_fields;
913*795d594fSAndroid Build Coastguard Worker       gap -= sizeof(uint32_t);
914*795d594fSAndroid Build Coastguard Worker     }
915*795d594fSAndroid Build Coastguard Worker     // Shuffle 2-byte fields forward.
916*795d594fSAndroid Build Coastguard Worker     while (gap >= sizeof(uint16_t) && num_16bit_static_fields != 0) {
917*795d594fSAndroid Build Coastguard Worker       --num_16bit_static_fields;
918*795d594fSAndroid Build Coastguard Worker       gap -= sizeof(uint16_t);
919*795d594fSAndroid Build Coastguard Worker     }
920*795d594fSAndroid Build Coastguard Worker     // Shuffle byte fields forward.
921*795d594fSAndroid Build Coastguard Worker     while (gap >= sizeof(uint8_t) && num_8bit_static_fields != 0) {
922*795d594fSAndroid Build Coastguard Worker       --num_8bit_static_fields;
923*795d594fSAndroid Build Coastguard Worker       gap -= sizeof(uint8_t);
924*795d594fSAndroid Build Coastguard Worker     }
925*795d594fSAndroid Build Coastguard Worker   }
926*795d594fSAndroid Build Coastguard Worker   // Guaranteed to be at least 4 byte aligned. No need for further alignments.
927*795d594fSAndroid Build Coastguard Worker   // Space used for primitive static fields.
928*795d594fSAndroid Build Coastguard Worker   size += num_8bit_static_fields * sizeof(uint8_t) + num_16bit_static_fields * sizeof(uint16_t) +
929*795d594fSAndroid Build Coastguard Worker       num_32bit_static_fields * sizeof(uint32_t) + num_64bit_static_fields * sizeof(uint64_t);
930*795d594fSAndroid Build Coastguard Worker 
931*795d594fSAndroid Build Coastguard Worker   // Space used by reference-offset bitmap.
932*795d594fSAndroid Build Coastguard Worker   if (num_ref_bitmap_entries > 0) {
933*795d594fSAndroid Build Coastguard Worker     size = RoundUp(size, sizeof(uint32_t));
934*795d594fSAndroid Build Coastguard Worker     size += num_ref_bitmap_entries * sizeof(uint32_t);
935*795d594fSAndroid Build Coastguard Worker   }
936*795d594fSAndroid Build Coastguard Worker   return size;
937*795d594fSAndroid Build Coastguard Worker }
938*795d594fSAndroid Build Coastguard Worker 
939*795d594fSAndroid Build Coastguard Worker template<VerifyObjectFlags kVerifyFlags>
IsClassClass()940*795d594fSAndroid Build Coastguard Worker inline bool Class::IsClassClass() {
941*795d594fSAndroid Build Coastguard Worker   // OK to look at from-space copies since java.lang.Class.class is non-moveable
942*795d594fSAndroid Build Coastguard Worker   // (even when running without boot image, see ClassLinker::InitWithoutImage())
943*795d594fSAndroid Build Coastguard Worker   // and we're reading it for comparison only. See ReadBarrierOption.
944*795d594fSAndroid Build Coastguard Worker   ObjPtr<Class> java_lang_Class = GetClass<kVerifyFlags, kWithoutReadBarrier>();
945*795d594fSAndroid Build Coastguard Worker   return this == java_lang_Class;
946*795d594fSAndroid Build Coastguard Worker }
947*795d594fSAndroid Build Coastguard Worker 
GetDexFile()948*795d594fSAndroid Build Coastguard Worker inline const DexFile& Class::GetDexFile() {
949*795d594fSAndroid Build Coastguard Worker   // From-space version is the same as the to-space version since the dex file never changes.
950*795d594fSAndroid Build Coastguard Worker   // Avoiding the read barrier here is important to prevent recursive AssertToSpaceInvariant issues
951*795d594fSAndroid Build Coastguard Worker   // from PrettyTypeOf.
952*795d594fSAndroid Build Coastguard Worker   return *GetDexCache<kDefaultVerifyFlags, kWithoutReadBarrier>()->GetDexFile();
953*795d594fSAndroid Build Coastguard Worker }
954*795d594fSAndroid Build Coastguard Worker 
GetDescriptorView()955*795d594fSAndroid Build Coastguard Worker inline std::string_view Class::GetDescriptorView() {
956*795d594fSAndroid Build Coastguard Worker   DCHECK(!IsArrayClass());
957*795d594fSAndroid Build Coastguard Worker   DCHECK(!IsPrimitive());
958*795d594fSAndroid Build Coastguard Worker   DCHECK(!IsProxyClass());
959*795d594fSAndroid Build Coastguard Worker   return GetDexFile().GetTypeDescriptorView(GetDexTypeIndex());
960*795d594fSAndroid Build Coastguard Worker }
961*795d594fSAndroid Build Coastguard Worker 
DescriptorEquals(std::string_view match)962*795d594fSAndroid Build Coastguard Worker inline bool Class::DescriptorEquals(std::string_view match) {
963*795d594fSAndroid Build Coastguard Worker   ObjPtr<mirror::Class> klass = this;
964*795d594fSAndroid Build Coastguard Worker   while (klass->IsArrayClass()) {
965*795d594fSAndroid Build Coastguard Worker     if (UNLIKELY(match.empty()) || match[0] != '[') {
966*795d594fSAndroid Build Coastguard Worker       return false;
967*795d594fSAndroid Build Coastguard Worker     }
968*795d594fSAndroid Build Coastguard Worker     match.remove_prefix(1u);
969*795d594fSAndroid Build Coastguard Worker     // No read barrier needed, we're reading a chain of constant references for comparison
970*795d594fSAndroid Build Coastguard Worker     // with null. Then we follow up below with reading constant references to read constant
971*795d594fSAndroid Build Coastguard Worker     // primitive data in both proxy and non-proxy paths. See ReadBarrierOption.
972*795d594fSAndroid Build Coastguard Worker     klass = klass->GetComponentType<kDefaultVerifyFlags, kWithoutReadBarrier>();
973*795d594fSAndroid Build Coastguard Worker   }
974*795d594fSAndroid Build Coastguard Worker   if (klass->IsPrimitive()) {
975*795d594fSAndroid Build Coastguard Worker     return match.length() == 1u && match[0] == Primitive::Descriptor(klass->GetPrimitiveType())[0];
976*795d594fSAndroid Build Coastguard Worker   } else if (UNLIKELY(klass->IsProxyClass())) {
977*795d594fSAndroid Build Coastguard Worker     return klass->ProxyDescriptorEquals(match);
978*795d594fSAndroid Build Coastguard Worker   } else {
979*795d594fSAndroid Build Coastguard Worker     const DexFile& dex_file = klass->GetDexFile();
980*795d594fSAndroid Build Coastguard Worker     const dex::TypeId& type_id = dex_file.GetTypeId(klass->GetDexTypeIndex());
981*795d594fSAndroid Build Coastguard Worker     return dex_file.GetTypeDescriptorView(type_id) == match;
982*795d594fSAndroid Build Coastguard Worker   }
983*795d594fSAndroid Build Coastguard Worker }
984*795d594fSAndroid Build Coastguard Worker 
DescriptorHash()985*795d594fSAndroid Build Coastguard Worker inline uint32_t Class::DescriptorHash() {
986*795d594fSAndroid Build Coastguard Worker   // No read barriers needed, we're reading a chain of constant references for comparison with null
987*795d594fSAndroid Build Coastguard Worker   // and retrieval of constant primitive data. See `ReadBarrierOption` and `Class::GetDescriptor()`.
988*795d594fSAndroid Build Coastguard Worker   ObjPtr<mirror::Class> klass = this;
989*795d594fSAndroid Build Coastguard Worker   uint32_t hash = StartModifiedUtf8Hash();
990*795d594fSAndroid Build Coastguard Worker   while (klass->IsArrayClass()) {
991*795d594fSAndroid Build Coastguard Worker     klass = klass->GetComponentType<kDefaultVerifyFlags, kWithoutReadBarrier>();
992*795d594fSAndroid Build Coastguard Worker     hash = UpdateModifiedUtf8Hash(hash, '[');
993*795d594fSAndroid Build Coastguard Worker   }
994*795d594fSAndroid Build Coastguard Worker   if (UNLIKELY(klass->IsProxyClass())) {
995*795d594fSAndroid Build Coastguard Worker     hash = UpdateHashForProxyClass(hash, klass);
996*795d594fSAndroid Build Coastguard Worker   } else if (klass->IsPrimitive()) {
997*795d594fSAndroid Build Coastguard Worker     hash = UpdateModifiedUtf8Hash(hash, Primitive::Descriptor(klass->GetPrimitiveType())[0]);
998*795d594fSAndroid Build Coastguard Worker   } else {
999*795d594fSAndroid Build Coastguard Worker     const DexFile& dex_file = klass->GetDexFile();
1000*795d594fSAndroid Build Coastguard Worker     const dex::TypeId& type_id = dex_file.GetTypeId(klass->GetDexTypeIndex());
1001*795d594fSAndroid Build Coastguard Worker     std::string_view descriptor = dex_file.GetTypeDescriptorView(type_id);
1002*795d594fSAndroid Build Coastguard Worker     hash = UpdateModifiedUtf8Hash(hash, descriptor);
1003*795d594fSAndroid Build Coastguard Worker   }
1004*795d594fSAndroid Build Coastguard Worker 
1005*795d594fSAndroid Build Coastguard Worker   if (kIsDebugBuild) {
1006*795d594fSAndroid Build Coastguard Worker     std::string temp;
1007*795d594fSAndroid Build Coastguard Worker     CHECK_EQ(hash, ComputeModifiedUtf8Hash(GetDescriptor(&temp)));
1008*795d594fSAndroid Build Coastguard Worker   }
1009*795d594fSAndroid Build Coastguard Worker 
1010*795d594fSAndroid Build Coastguard Worker   return hash;
1011*795d594fSAndroid Build Coastguard Worker }
1012*795d594fSAndroid Build Coastguard Worker 
AssertInitializedOrInitializingInThread(Thread * self)1013*795d594fSAndroid Build Coastguard Worker inline void Class::AssertInitializedOrInitializingInThread(Thread* self) {
1014*795d594fSAndroid Build Coastguard Worker   if (kIsDebugBuild && !IsInitialized()) {
1015*795d594fSAndroid Build Coastguard Worker     CHECK(IsInitializing()) << PrettyClass() << " is not initializing: " << GetStatus();
1016*795d594fSAndroid Build Coastguard Worker     CHECK_EQ(GetClinitThreadId(), self->GetTid())
1017*795d594fSAndroid Build Coastguard Worker         << PrettyClass() << " is initializing in a different thread";
1018*795d594fSAndroid Build Coastguard Worker   }
1019*795d594fSAndroid Build Coastguard Worker }
1020*795d594fSAndroid Build Coastguard Worker 
GetProxyInterfaces()1021*795d594fSAndroid Build Coastguard Worker inline ObjPtr<ObjectArray<Class>> Class::GetProxyInterfaces() {
1022*795d594fSAndroid Build Coastguard Worker   CHECK(IsProxyClass());
1023*795d594fSAndroid Build Coastguard Worker   // First static field.
1024*795d594fSAndroid Build Coastguard Worker   ArtField* field = GetStaticField(0);
1025*795d594fSAndroid Build Coastguard Worker   DCHECK_STREQ(field->GetName(), "interfaces");
1026*795d594fSAndroid Build Coastguard Worker   MemberOffset field_offset = field->GetOffset();
1027*795d594fSAndroid Build Coastguard Worker   return GetFieldObject<ObjectArray<Class>>(field_offset);
1028*795d594fSAndroid Build Coastguard Worker }
1029*795d594fSAndroid Build Coastguard Worker 
GetProxyThrows()1030*795d594fSAndroid Build Coastguard Worker inline ObjPtr<ObjectArray<ObjectArray<Class>>> Class::GetProxyThrows() {
1031*795d594fSAndroid Build Coastguard Worker   CHECK(IsProxyClass());
1032*795d594fSAndroid Build Coastguard Worker   // Second static field.
1033*795d594fSAndroid Build Coastguard Worker   ArtField* field = GetStaticField(1);
1034*795d594fSAndroid Build Coastguard Worker   DCHECK_STREQ(field->GetName(), "throws");
1035*795d594fSAndroid Build Coastguard Worker   MemberOffset field_offset = field->GetOffset();
1036*795d594fSAndroid Build Coastguard Worker   return GetFieldObject<ObjectArray<ObjectArray<Class>>>(field_offset);
1037*795d594fSAndroid Build Coastguard Worker }
1038*795d594fSAndroid Build Coastguard Worker 
IsBootStrapClassLoaded()1039*795d594fSAndroid Build Coastguard Worker inline bool Class::IsBootStrapClassLoaded() {
1040*795d594fSAndroid Build Coastguard Worker   // No read barrier is needed for comparing with null. See ReadBarrierOption.
1041*795d594fSAndroid Build Coastguard Worker   return GetClassLoader<kDefaultVerifyFlags, kWithoutReadBarrier>() == nullptr;
1042*795d594fSAndroid Build Coastguard Worker }
1043*795d594fSAndroid Build Coastguard Worker 
operator()1044*795d594fSAndroid Build Coastguard Worker inline void Class::InitializeClassVisitor::operator()(ObjPtr<Object> obj,
1045*795d594fSAndroid Build Coastguard Worker                                                       size_t usable_size) const {
1046*795d594fSAndroid Build Coastguard Worker   DCHECK_LE(class_size_, usable_size);
1047*795d594fSAndroid Build Coastguard Worker   // Avoid AsClass as object is not yet in live bitmap or allocation stack.
1048*795d594fSAndroid Build Coastguard Worker   ObjPtr<Class> klass = ObjPtr<Class>::DownCast(obj);
1049*795d594fSAndroid Build Coastguard Worker   klass->SetClassSize(class_size_);
1050*795d594fSAndroid Build Coastguard Worker   klass->SetPrimitiveType(Primitive::kPrimNot);  // Default to not being primitive.
1051*795d594fSAndroid Build Coastguard Worker   klass->SetDexClassDefIndex(DexFile::kDexNoIndex16);  // Default to no valid class def index.
1052*795d594fSAndroid Build Coastguard Worker   klass->SetDexTypeIndex(dex::TypeIndex(DexFile::kDexNoIndex16));  // Default to no valid type
1053*795d594fSAndroid Build Coastguard Worker                                                                    // index.
1054*795d594fSAndroid Build Coastguard Worker   // Default to force slow path until visibly initialized.
1055*795d594fSAndroid Build Coastguard Worker   // There is no need for release store (volatile) in pre-fence visitor.
1056*795d594fSAndroid Build Coastguard Worker   klass->SetField32</*kTransactionActive=*/ false, /*kCheckTransaction=*/ false>(
1057*795d594fSAndroid Build Coastguard Worker       ObjectSizeAllocFastPathOffset(), std::numeric_limits<uint32_t>::max());
1058*795d594fSAndroid Build Coastguard Worker }
1059*795d594fSAndroid Build Coastguard Worker 
SetAccessFlagsDuringLinking(uint32_t new_access_flags)1060*795d594fSAndroid Build Coastguard Worker inline void Class::SetAccessFlagsDuringLinking(uint32_t new_access_flags) {
1061*795d594fSAndroid Build Coastguard Worker   SetField32</*kTransactionActive=*/ false, /*kCheckTransaction=*/ false>(
1062*795d594fSAndroid Build Coastguard Worker       AccessFlagsOffset(), new_access_flags);
1063*795d594fSAndroid Build Coastguard Worker }
1064*795d594fSAndroid Build Coastguard Worker 
SetAccessFlags(uint32_t new_access_flags)1065*795d594fSAndroid Build Coastguard Worker inline void Class::SetAccessFlags(uint32_t new_access_flags) {
1066*795d594fSAndroid Build Coastguard Worker   // Called inside a transaction when setting pre-verified flag during boot image compilation.
1067*795d594fSAndroid Build Coastguard Worker   if (Runtime::Current()->IsActiveTransaction()) {
1068*795d594fSAndroid Build Coastguard Worker     SetField32<true>(AccessFlagsOffset(), new_access_flags);
1069*795d594fSAndroid Build Coastguard Worker   } else {
1070*795d594fSAndroid Build Coastguard Worker     SetField32<false>(AccessFlagsOffset(), new_access_flags);
1071*795d594fSAndroid Build Coastguard Worker   }
1072*795d594fSAndroid Build Coastguard Worker }
1073*795d594fSAndroid Build Coastguard Worker 
SetClassFlags(uint32_t new_flags)1074*795d594fSAndroid Build Coastguard Worker inline void Class::SetClassFlags(uint32_t new_flags) {
1075*795d594fSAndroid Build Coastguard Worker   SetField32</*kTransactionActive=*/ false, /*kCheckTransaction=*/ false>(
1076*795d594fSAndroid Build Coastguard Worker       OFFSET_OF_OBJECT_MEMBER(Class, class_flags_), new_flags);
1077*795d594fSAndroid Build Coastguard Worker }
1078*795d594fSAndroid Build Coastguard Worker 
NumDirectInterfaces()1079*795d594fSAndroid Build Coastguard Worker inline uint32_t Class::NumDirectInterfaces() {
1080*795d594fSAndroid Build Coastguard Worker   if (IsPrimitive()) {
1081*795d594fSAndroid Build Coastguard Worker     return 0;
1082*795d594fSAndroid Build Coastguard Worker   } else if (IsArrayClass()) {
1083*795d594fSAndroid Build Coastguard Worker     return 2;
1084*795d594fSAndroid Build Coastguard Worker   } else if (IsProxyClass()) {
1085*795d594fSAndroid Build Coastguard Worker     ObjPtr<ObjectArray<Class>> interfaces = GetProxyInterfaces();
1086*795d594fSAndroid Build Coastguard Worker     return interfaces != nullptr ? interfaces->GetLength() : 0;
1087*795d594fSAndroid Build Coastguard Worker   } else {
1088*795d594fSAndroid Build Coastguard Worker     const dex::TypeList* interfaces = GetInterfaceTypeList();
1089*795d594fSAndroid Build Coastguard Worker     if (interfaces == nullptr) {
1090*795d594fSAndroid Build Coastguard Worker       return 0;
1091*795d594fSAndroid Build Coastguard Worker     } else {
1092*795d594fSAndroid Build Coastguard Worker       return interfaces->Size();
1093*795d594fSAndroid Build Coastguard Worker     }
1094*795d594fSAndroid Build Coastguard Worker   }
1095*795d594fSAndroid Build Coastguard Worker }
1096*795d594fSAndroid Build Coastguard Worker 
GetDirectMethods(PointerSize pointer_size)1097*795d594fSAndroid Build Coastguard Worker inline ArraySlice<ArtMethod> Class::GetDirectMethods(PointerSize pointer_size) {
1098*795d594fSAndroid Build Coastguard Worker   CheckPointerSize(pointer_size);
1099*795d594fSAndroid Build Coastguard Worker   return GetDirectMethodsSliceUnchecked(pointer_size);
1100*795d594fSAndroid Build Coastguard Worker }
1101*795d594fSAndroid Build Coastguard Worker 
GetDeclaredMethods(PointerSize pointer_size)1102*795d594fSAndroid Build Coastguard Worker inline ArraySlice<ArtMethod> Class::GetDeclaredMethods(PointerSize pointer_size) {
1103*795d594fSAndroid Build Coastguard Worker   return GetDeclaredMethodsSliceUnchecked(pointer_size);
1104*795d594fSAndroid Build Coastguard Worker }
1105*795d594fSAndroid Build Coastguard Worker 
GetDeclaredVirtualMethods(PointerSize pointer_size)1106*795d594fSAndroid Build Coastguard Worker inline ArraySlice<ArtMethod> Class::GetDeclaredVirtualMethods(PointerSize pointer_size) {
1107*795d594fSAndroid Build Coastguard Worker   return GetDeclaredVirtualMethodsSliceUnchecked(pointer_size);
1108*795d594fSAndroid Build Coastguard Worker }
1109*795d594fSAndroid Build Coastguard Worker 
GetVirtualMethods(PointerSize pointer_size)1110*795d594fSAndroid Build Coastguard Worker inline ArraySlice<ArtMethod> Class::GetVirtualMethods(PointerSize pointer_size) {
1111*795d594fSAndroid Build Coastguard Worker   CheckPointerSize(pointer_size);
1112*795d594fSAndroid Build Coastguard Worker   return GetVirtualMethodsSliceUnchecked(pointer_size);
1113*795d594fSAndroid Build Coastguard Worker }
1114*795d594fSAndroid Build Coastguard Worker 
GetCopiedMethods(PointerSize pointer_size)1115*795d594fSAndroid Build Coastguard Worker inline ArraySlice<ArtMethod> Class::GetCopiedMethods(PointerSize pointer_size) {
1116*795d594fSAndroid Build Coastguard Worker   CheckPointerSize(pointer_size);
1117*795d594fSAndroid Build Coastguard Worker   return GetCopiedMethodsSliceUnchecked(pointer_size);
1118*795d594fSAndroid Build Coastguard Worker }
1119*795d594fSAndroid Build Coastguard Worker 
1120*795d594fSAndroid Build Coastguard Worker 
GetMethods(PointerSize pointer_size)1121*795d594fSAndroid Build Coastguard Worker inline ArraySlice<ArtMethod> Class::GetMethods(PointerSize pointer_size) {
1122*795d594fSAndroid Build Coastguard Worker   CheckPointerSize(pointer_size);
1123*795d594fSAndroid Build Coastguard Worker   LengthPrefixedArray<ArtMethod>* methods = GetMethodsPtr();
1124*795d594fSAndroid Build Coastguard Worker   return GetMethodsSliceRangeUnchecked(methods, pointer_size, 0u, NumMethods(methods));
1125*795d594fSAndroid Build Coastguard Worker }
1126*795d594fSAndroid Build Coastguard Worker 
GetIFields()1127*795d594fSAndroid Build Coastguard Worker inline IterationRange<StrideIterator<ArtField>> Class::GetIFields() {
1128*795d594fSAndroid Build Coastguard Worker   return MakeIterationRangeFromLengthPrefixedArray(GetIFieldsPtr());
1129*795d594fSAndroid Build Coastguard Worker }
1130*795d594fSAndroid Build Coastguard Worker 
GetSFields()1131*795d594fSAndroid Build Coastguard Worker inline IterationRange<StrideIterator<ArtField>> Class::GetSFields() {
1132*795d594fSAndroid Build Coastguard Worker   return MakeIterationRangeFromLengthPrefixedArray(GetSFieldsPtr());
1133*795d594fSAndroid Build Coastguard Worker }
1134*795d594fSAndroid Build Coastguard Worker 
GetIFieldsUnchecked()1135*795d594fSAndroid Build Coastguard Worker inline IterationRange<StrideIterator<ArtField>> Class::GetIFieldsUnchecked() {
1136*795d594fSAndroid Build Coastguard Worker   return MakeIterationRangeFromLengthPrefixedArray(GetIFieldsPtrUnchecked());
1137*795d594fSAndroid Build Coastguard Worker }
1138*795d594fSAndroid Build Coastguard Worker 
GetSFieldsUnchecked()1139*795d594fSAndroid Build Coastguard Worker inline IterationRange<StrideIterator<ArtField>> Class::GetSFieldsUnchecked() {
1140*795d594fSAndroid Build Coastguard Worker   return MakeIterationRangeFromLengthPrefixedArray(GetSFieldsPtrUnchecked());
1141*795d594fSAndroid Build Coastguard Worker }
1142*795d594fSAndroid Build Coastguard Worker 
CheckPointerSize(PointerSize pointer_size)1143*795d594fSAndroid Build Coastguard Worker inline void Class::CheckPointerSize(PointerSize pointer_size) {
1144*795d594fSAndroid Build Coastguard Worker   DCHECK_EQ(pointer_size, Runtime::Current()->GetClassLinker()->GetImagePointerSize());
1145*795d594fSAndroid Build Coastguard Worker }
1146*795d594fSAndroid Build Coastguard Worker 
1147*795d594fSAndroid Build Coastguard Worker template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
GetComponentType()1148*795d594fSAndroid Build Coastguard Worker inline ObjPtr<Class> Class::GetComponentType() {
1149*795d594fSAndroid Build Coastguard Worker   return GetFieldObject<Class, kVerifyFlags, kReadBarrierOption>(ComponentTypeOffset());
1150*795d594fSAndroid Build Coastguard Worker }
1151*795d594fSAndroid Build Coastguard Worker 
SetComponentType(ObjPtr<Class> new_component_type)1152*795d594fSAndroid Build Coastguard Worker inline void Class::SetComponentType(ObjPtr<Class> new_component_type) {
1153*795d594fSAndroid Build Coastguard Worker   DCHECK(GetComponentType() == nullptr);
1154*795d594fSAndroid Build Coastguard Worker   DCHECK(new_component_type != nullptr);
1155*795d594fSAndroid Build Coastguard Worker   // Component type is invariant: use non-transactional mode without check.
1156*795d594fSAndroid Build Coastguard Worker   SetFieldObject</*kTransactionActive=*/ false, /*kCheckTransaction=*/ false>(
1157*795d594fSAndroid Build Coastguard Worker       ComponentTypeOffset(), new_component_type);
1158*795d594fSAndroid Build Coastguard Worker }
1159*795d594fSAndroid Build Coastguard Worker 
GetComponentSize()1160*795d594fSAndroid Build Coastguard Worker inline size_t Class::GetComponentSize() {
1161*795d594fSAndroid Build Coastguard Worker   return 1U << GetComponentSizeShift();
1162*795d594fSAndroid Build Coastguard Worker }
1163*795d594fSAndroid Build Coastguard Worker 
1164*795d594fSAndroid Build Coastguard Worker template <ReadBarrierOption kReadBarrierOption>
GetComponentSizeShift()1165*795d594fSAndroid Build Coastguard Worker inline size_t Class::GetComponentSizeShift() {
1166*795d594fSAndroid Build Coastguard Worker   return GetComponentType<kDefaultVerifyFlags, kReadBarrierOption>()->GetPrimitiveTypeSizeShift();
1167*795d594fSAndroid Build Coastguard Worker }
1168*795d594fSAndroid Build Coastguard Worker 
IsObjectClass()1169*795d594fSAndroid Build Coastguard Worker inline bool Class::IsObjectClass() {
1170*795d594fSAndroid Build Coastguard Worker   // No read barrier is needed for comparing with null. See ReadBarrierOption.
1171*795d594fSAndroid Build Coastguard Worker   return !IsPrimitive() && GetSuperClass<kDefaultVerifyFlags, kWithoutReadBarrier>() == nullptr;
1172*795d594fSAndroid Build Coastguard Worker }
1173*795d594fSAndroid Build Coastguard Worker 
IsInstantiableNonArray()1174*795d594fSAndroid Build Coastguard Worker inline bool Class::IsInstantiableNonArray() {
1175*795d594fSAndroid Build Coastguard Worker   return !IsPrimitive() && !IsInterface() && !IsAbstract() && !IsArrayClass();
1176*795d594fSAndroid Build Coastguard Worker }
1177*795d594fSAndroid Build Coastguard Worker 
1178*795d594fSAndroid Build Coastguard Worker template<VerifyObjectFlags kVerifyFlags>
IsInstantiable()1179*795d594fSAndroid Build Coastguard Worker bool Class::IsInstantiable() {
1180*795d594fSAndroid Build Coastguard Worker   return (!IsPrimitive<kVerifyFlags>() &&
1181*795d594fSAndroid Build Coastguard Worker           !IsInterface<kVerifyFlags>() &&
1182*795d594fSAndroid Build Coastguard Worker           !IsAbstract<kVerifyFlags>()) ||
1183*795d594fSAndroid Build Coastguard Worker       (IsAbstract<kVerifyFlags>() && IsArrayClass<kVerifyFlags>());
1184*795d594fSAndroid Build Coastguard Worker }
1185*795d594fSAndroid Build Coastguard Worker 
1186*795d594fSAndroid Build Coastguard Worker template<VerifyObjectFlags kVerifyFlags>
IsArrayClass()1187*795d594fSAndroid Build Coastguard Worker inline bool Class::IsArrayClass() {
1188*795d594fSAndroid Build Coastguard Worker   // We do not need a read barrier for comparing with null.
1189*795d594fSAndroid Build Coastguard Worker   return GetComponentType<kVerifyFlags, kWithoutReadBarrier>() != nullptr;
1190*795d594fSAndroid Build Coastguard Worker }
1191*795d594fSAndroid Build Coastguard Worker 
1192*795d594fSAndroid Build Coastguard Worker template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
IsObjectArrayClass()1193*795d594fSAndroid Build Coastguard Worker inline bool Class::IsObjectArrayClass() {
1194*795d594fSAndroid Build Coastguard Worker   const ObjPtr<Class> component_type = GetComponentType<kVerifyFlags, kReadBarrierOption>();
1195*795d594fSAndroid Build Coastguard Worker   constexpr VerifyObjectFlags kNewFlags = RemoveThisFlags(kVerifyFlags);
1196*795d594fSAndroid Build Coastguard Worker   return component_type != nullptr && !component_type->IsPrimitive<kNewFlags>();
1197*795d594fSAndroid Build Coastguard Worker }
1198*795d594fSAndroid Build Coastguard Worker 
1199*795d594fSAndroid Build Coastguard Worker template<VerifyObjectFlags kVerifyFlags>
IsPrimitiveArray()1200*795d594fSAndroid Build Coastguard Worker bool Class::IsPrimitiveArray() {
1201*795d594fSAndroid Build Coastguard Worker   // We do not need a read barrier here as the primitive type is constant,
1202*795d594fSAndroid Build Coastguard Worker   // both from-space and to-space component type classes shall yield the same result.
1203*795d594fSAndroid Build Coastguard Worker   const ObjPtr<Class> component_type = GetComponentType<kVerifyFlags, kWithoutReadBarrier>();
1204*795d594fSAndroid Build Coastguard Worker   constexpr VerifyObjectFlags kNewFlags = RemoveThisFlags(kVerifyFlags);
1205*795d594fSAndroid Build Coastguard Worker   return component_type != nullptr && component_type->IsPrimitive<kNewFlags>();
1206*795d594fSAndroid Build Coastguard Worker }
1207*795d594fSAndroid Build Coastguard Worker 
IsAssignableFrom(ObjPtr<Class> src)1208*795d594fSAndroid Build Coastguard Worker inline bool Class::IsAssignableFrom(ObjPtr<Class> src) {
1209*795d594fSAndroid Build Coastguard Worker   DCHECK(src != nullptr);
1210*795d594fSAndroid Build Coastguard Worker   if (this == src) {
1211*795d594fSAndroid Build Coastguard Worker     // Can always assign to things of the same type.
1212*795d594fSAndroid Build Coastguard Worker     return true;
1213*795d594fSAndroid Build Coastguard Worker   } else if (IsObjectClass()) {
1214*795d594fSAndroid Build Coastguard Worker     // Can assign any reference to java.lang.Object.
1215*795d594fSAndroid Build Coastguard Worker     return !src->IsPrimitive();
1216*795d594fSAndroid Build Coastguard Worker   } else if (IsInterface()) {
1217*795d594fSAndroid Build Coastguard Worker     return src->Implements(this);
1218*795d594fSAndroid Build Coastguard Worker   } else if (src->IsArrayClass()) {
1219*795d594fSAndroid Build Coastguard Worker     return IsAssignableFromArray(src);
1220*795d594fSAndroid Build Coastguard Worker   } else {
1221*795d594fSAndroid Build Coastguard Worker     return !src->IsInterface() && src->IsSubClass(this);
1222*795d594fSAndroid Build Coastguard Worker   }
1223*795d594fSAndroid Build Coastguard Worker }
1224*795d594fSAndroid Build Coastguard Worker 
NumDirectMethods()1225*795d594fSAndroid Build Coastguard Worker inline uint32_t Class::NumDirectMethods() {
1226*795d594fSAndroid Build Coastguard Worker   return GetVirtualMethodsStartOffset();
1227*795d594fSAndroid Build Coastguard Worker }
1228*795d594fSAndroid Build Coastguard Worker 
NumDeclaredVirtualMethods()1229*795d594fSAndroid Build Coastguard Worker inline uint32_t Class::NumDeclaredVirtualMethods() {
1230*795d594fSAndroid Build Coastguard Worker   return GetCopiedMethodsStartOffset() - GetVirtualMethodsStartOffset();
1231*795d594fSAndroid Build Coastguard Worker }
1232*795d594fSAndroid Build Coastguard Worker 
NumVirtualMethods()1233*795d594fSAndroid Build Coastguard Worker inline uint32_t Class::NumVirtualMethods() {
1234*795d594fSAndroid Build Coastguard Worker   return NumMethods() - GetVirtualMethodsStartOffset();
1235*795d594fSAndroid Build Coastguard Worker }
1236*795d594fSAndroid Build Coastguard Worker 
NumInstanceFields()1237*795d594fSAndroid Build Coastguard Worker inline uint32_t Class::NumInstanceFields() {
1238*795d594fSAndroid Build Coastguard Worker   LengthPrefixedArray<ArtField>* arr = GetIFieldsPtrUnchecked();
1239*795d594fSAndroid Build Coastguard Worker   return arr != nullptr ? arr->size() : 0u;
1240*795d594fSAndroid Build Coastguard Worker }
1241*795d594fSAndroid Build Coastguard Worker 
NumStaticFields()1242*795d594fSAndroid Build Coastguard Worker inline uint32_t Class::NumStaticFields() {
1243*795d594fSAndroid Build Coastguard Worker   LengthPrefixedArray<ArtField>* arr = GetSFieldsPtrUnchecked();
1244*795d594fSAndroid Build Coastguard Worker   return arr != nullptr ? arr->size() : 0u;
1245*795d594fSAndroid Build Coastguard Worker }
1246*795d594fSAndroid Build Coastguard Worker 
1247*795d594fSAndroid Build Coastguard Worker template <typename T, VerifyObjectFlags kVerifyFlags, typename Visitor>
FixupNativePointer(Class * dest,PointerSize pointer_size,const Visitor & visitor,MemberOffset member_offset)1248*795d594fSAndroid Build Coastguard Worker inline void Class::FixupNativePointer(
1249*795d594fSAndroid Build Coastguard Worker     Class* dest, PointerSize pointer_size, const Visitor& visitor, MemberOffset member_offset) {
1250*795d594fSAndroid Build Coastguard Worker   void** address =
1251*795d594fSAndroid Build Coastguard Worker       reinterpret_cast<void**>(reinterpret_cast<uintptr_t>(dest) + member_offset.Uint32Value());
1252*795d594fSAndroid Build Coastguard Worker   T old_value = GetFieldPtrWithSize<T, kVerifyFlags>(member_offset, pointer_size);
1253*795d594fSAndroid Build Coastguard Worker   T new_value = visitor(old_value, address);
1254*795d594fSAndroid Build Coastguard Worker   if (old_value != new_value) {
1255*795d594fSAndroid Build Coastguard Worker     dest->SetFieldPtrWithSize</* kTransactionActive= */ false,
1256*795d594fSAndroid Build Coastguard Worker                               /* kCheckTransaction= */ true,
1257*795d594fSAndroid Build Coastguard Worker                               kVerifyNone>(member_offset, new_value, pointer_size);
1258*795d594fSAndroid Build Coastguard Worker   }
1259*795d594fSAndroid Build Coastguard Worker }
1260*795d594fSAndroid Build Coastguard Worker 
1261*795d594fSAndroid Build Coastguard Worker template <VerifyObjectFlags kVerifyFlags, typename Visitor>
FixupNativePointers(Class * dest,PointerSize pointer_size,const Visitor & visitor)1262*795d594fSAndroid Build Coastguard Worker inline void Class::FixupNativePointers(Class* dest,
1263*795d594fSAndroid Build Coastguard Worker                                        PointerSize pointer_size,
1264*795d594fSAndroid Build Coastguard Worker                                        const Visitor& visitor) {
1265*795d594fSAndroid Build Coastguard Worker   // Update the field arrays.
1266*795d594fSAndroid Build Coastguard Worker   FixupNativePointer<LengthPrefixedArray<ArtField>*, kVerifyFlags>(
1267*795d594fSAndroid Build Coastguard Worker       dest, pointer_size, visitor, OFFSET_OF_OBJECT_MEMBER(Class, sfields_));
1268*795d594fSAndroid Build Coastguard Worker   FixupNativePointer<LengthPrefixedArray<ArtField>*, kVerifyFlags>(
1269*795d594fSAndroid Build Coastguard Worker       dest, pointer_size, visitor, OFFSET_OF_OBJECT_MEMBER(Class, ifields_));
1270*795d594fSAndroid Build Coastguard Worker   // Update method array.
1271*795d594fSAndroid Build Coastguard Worker   FixupNativePointer<LengthPrefixedArray<ArtMethod>*, kVerifyFlags>(
1272*795d594fSAndroid Build Coastguard Worker       dest, pointer_size, visitor, OFFSET_OF_OBJECT_MEMBER(Class, methods_));
1273*795d594fSAndroid Build Coastguard Worker   // Fix up embedded tables.
1274*795d594fSAndroid Build Coastguard Worker   if (!IsTemp<kVerifyNone>() && ShouldHaveEmbeddedVTable<kVerifyNone>()) {
1275*795d594fSAndroid Build Coastguard Worker     for (int32_t i = 0, count = GetEmbeddedVTableLength<kVerifyFlags>(); i < count; ++i) {
1276*795d594fSAndroid Build Coastguard Worker       FixupNativePointer<ArtMethod*, kVerifyFlags>(
1277*795d594fSAndroid Build Coastguard Worker           dest, pointer_size, visitor, EmbeddedVTableEntryOffset(i, pointer_size));
1278*795d594fSAndroid Build Coastguard Worker     }
1279*795d594fSAndroid Build Coastguard Worker   }
1280*795d594fSAndroid Build Coastguard Worker   if (!IsTemp<kVerifyNone>() && ShouldHaveImt<kVerifyNone>()) {
1281*795d594fSAndroid Build Coastguard Worker     FixupNativePointer<ImTable*, kVerifyFlags>(
1282*795d594fSAndroid Build Coastguard Worker         dest, pointer_size, visitor, ImtPtrOffset(pointer_size));
1283*795d594fSAndroid Build Coastguard Worker   }
1284*795d594fSAndroid Build Coastguard Worker }
1285*795d594fSAndroid Build Coastguard Worker 
CanAccess(ObjPtr<Class> that)1286*795d594fSAndroid Build Coastguard Worker inline bool Class::CanAccess(ObjPtr<Class> that) {
1287*795d594fSAndroid Build Coastguard Worker   return this == that || that->IsPublic() || this->IsInSamePackage(that);
1288*795d594fSAndroid Build Coastguard Worker }
1289*795d594fSAndroid Build Coastguard Worker 
1290*795d594fSAndroid Build Coastguard Worker 
CanAccessMember(ObjPtr<Class> access_to,uint32_t member_flags)1291*795d594fSAndroid Build Coastguard Worker inline bool Class::CanAccessMember(ObjPtr<Class> access_to, uint32_t member_flags) {
1292*795d594fSAndroid Build Coastguard Worker   // Classes can access all of their own members
1293*795d594fSAndroid Build Coastguard Worker   if (this == access_to) {
1294*795d594fSAndroid Build Coastguard Worker     return true;
1295*795d594fSAndroid Build Coastguard Worker   }
1296*795d594fSAndroid Build Coastguard Worker   // Public members are trivially accessible
1297*795d594fSAndroid Build Coastguard Worker   if (member_flags & kAccPublic) {
1298*795d594fSAndroid Build Coastguard Worker     return true;
1299*795d594fSAndroid Build Coastguard Worker   }
1300*795d594fSAndroid Build Coastguard Worker   // Private members are trivially not accessible
1301*795d594fSAndroid Build Coastguard Worker   if (member_flags & kAccPrivate) {
1302*795d594fSAndroid Build Coastguard Worker     return false;
1303*795d594fSAndroid Build Coastguard Worker   }
1304*795d594fSAndroid Build Coastguard Worker   // Check for protected access from a sub-class, which may or may not be in the same package.
1305*795d594fSAndroid Build Coastguard Worker   if (member_flags & kAccProtected) {
1306*795d594fSAndroid Build Coastguard Worker     // This implementation is not compliant. We should actually check whether
1307*795d594fSAndroid Build Coastguard Worker     // the caller is a subclass of the static type of the receiver, instead of the declaring
1308*795d594fSAndroid Build Coastguard Worker     // class of the method we are trying to access.
1309*795d594fSAndroid Build Coastguard Worker     //
1310*795d594fSAndroid Build Coastguard Worker     // For example, a class outside of java.lang should not ne able to access `Object.clone`,
1311*795d594fSAndroid Build Coastguard Worker     // but this implementation allows it.
1312*795d594fSAndroid Build Coastguard Worker     //
1313*795d594fSAndroid Build Coastguard Worker     // To not break existing code, we decided not to fix this and accept the
1314*795d594fSAndroid Build Coastguard Worker     // leniency.
1315*795d594fSAndroid Build Coastguard Worker     if (access_to->IsAssignableFrom(this)) {
1316*795d594fSAndroid Build Coastguard Worker       return true;
1317*795d594fSAndroid Build Coastguard Worker     }
1318*795d594fSAndroid Build Coastguard Worker   }
1319*795d594fSAndroid Build Coastguard Worker   // Allow protected access from other classes in the same package.
1320*795d594fSAndroid Build Coastguard Worker   return this->IsInSamePackage(access_to);
1321*795d594fSAndroid Build Coastguard Worker }
1322*795d594fSAndroid Build Coastguard Worker 
CannotBeAssignedFromOtherTypes()1323*795d594fSAndroid Build Coastguard Worker inline bool Class::CannotBeAssignedFromOtherTypes() {
1324*795d594fSAndroid Build Coastguard Worker   if (!IsArrayClass()) {
1325*795d594fSAndroid Build Coastguard Worker     return IsFinal();
1326*795d594fSAndroid Build Coastguard Worker   }
1327*795d594fSAndroid Build Coastguard Worker   ObjPtr<Class> component = GetComponentType();
1328*795d594fSAndroid Build Coastguard Worker   return component->IsPrimitive() || component->CannotBeAssignedFromOtherTypes();
1329*795d594fSAndroid Build Coastguard Worker }
1330*795d594fSAndroid Build Coastguard Worker 
SetClassLoader(ObjPtr<ClassLoader> new_class_loader)1331*795d594fSAndroid Build Coastguard Worker inline void Class::SetClassLoader(ObjPtr<ClassLoader> new_class_loader) {
1332*795d594fSAndroid Build Coastguard Worker   SetFieldObject</*kTransactionActive=*/ false, /*kCheckTransaction=*/ false>(
1333*795d594fSAndroid Build Coastguard Worker       OFFSET_OF_OBJECT_MEMBER(Class, class_loader_), new_class_loader);
1334*795d594fSAndroid Build Coastguard Worker }
1335*795d594fSAndroid Build Coastguard Worker 
SetRecursivelyInitialized()1336*795d594fSAndroid Build Coastguard Worker inline void Class::SetRecursivelyInitialized() {
1337*795d594fSAndroid Build Coastguard Worker   DCHECK_EQ(GetLockOwnerThreadId(), Thread::Current()->GetThreadId());
1338*795d594fSAndroid Build Coastguard Worker   uint32_t flags = GetField32(OFFSET_OF_OBJECT_MEMBER(Class, access_flags_));
1339*795d594fSAndroid Build Coastguard Worker   SetAccessFlags(flags | kAccRecursivelyInitialized);
1340*795d594fSAndroid Build Coastguard Worker }
1341*795d594fSAndroid Build Coastguard Worker 
SetHasDefaultMethods()1342*795d594fSAndroid Build Coastguard Worker inline void Class::SetHasDefaultMethods() {
1343*795d594fSAndroid Build Coastguard Worker   DCHECK_EQ(GetLockOwnerThreadId(), Thread::Current()->GetThreadId());
1344*795d594fSAndroid Build Coastguard Worker   uint32_t flags = GetField32(OFFSET_OF_OBJECT_MEMBER(Class, access_flags_));
1345*795d594fSAndroid Build Coastguard Worker   SetAccessFlagsDuringLinking(flags | kAccHasDefaultMethod);
1346*795d594fSAndroid Build Coastguard Worker }
1347*795d594fSAndroid Build Coastguard Worker 
ClearFinalizable()1348*795d594fSAndroid Build Coastguard Worker inline void Class::ClearFinalizable() {
1349*795d594fSAndroid Build Coastguard Worker   // We're clearing the finalizable flag only for `Object` and `Enum`
1350*795d594fSAndroid Build Coastguard Worker   // during early setup without the boot image.
1351*795d594fSAndroid Build Coastguard Worker   DCHECK(IsObjectClass() ||
1352*795d594fSAndroid Build Coastguard Worker          (IsBootStrapClassLoaded() && DescriptorEquals("Ljava/lang/Enum;")));
1353*795d594fSAndroid Build Coastguard Worker   uint32_t flags = GetField32(OFFSET_OF_OBJECT_MEMBER(Class, access_flags_));
1354*795d594fSAndroid Build Coastguard Worker   SetAccessFlagsDuringLinking(flags & ~kAccClassIsFinalizable);
1355*795d594fSAndroid Build Coastguard Worker }
1356*795d594fSAndroid Build Coastguard Worker 
FindSuperImt(PointerSize pointer_size)1357*795d594fSAndroid Build Coastguard Worker inline ImTable* Class::FindSuperImt(PointerSize pointer_size) {
1358*795d594fSAndroid Build Coastguard Worker   ObjPtr<mirror::Class> klass = this;
1359*795d594fSAndroid Build Coastguard Worker   while (klass->HasSuperClass()) {
1360*795d594fSAndroid Build Coastguard Worker     klass = klass->GetSuperClass();
1361*795d594fSAndroid Build Coastguard Worker     if (klass->ShouldHaveImt()) {
1362*795d594fSAndroid Build Coastguard Worker       return klass->GetImt(pointer_size);
1363*795d594fSAndroid Build Coastguard Worker     }
1364*795d594fSAndroid Build Coastguard Worker   }
1365*795d594fSAndroid Build Coastguard Worker   return nullptr;
1366*795d594fSAndroid Build Coastguard Worker }
1367*795d594fSAndroid Build Coastguard Worker 
1368*795d594fSAndroid Build Coastguard Worker }  // namespace mirror
1369*795d594fSAndroid Build Coastguard Worker }  // namespace art
1370*795d594fSAndroid Build Coastguard Worker 
1371*795d594fSAndroid Build Coastguard Worker #endif  // ART_RUNTIME_MIRROR_CLASS_INL_H_
1372