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