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