• 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-inl.h"
24 #include "class_linker-inl.h"
25 #include "class_loader.h"
26 #include "common_throws.h"
27 #include "dex_cache.h"
28 #include "dex_file.h"
29 #include "gc/heap-inl.h"
30 #include "iftable.h"
31 #include "object_array-inl.h"
32 #include "read_barrier-inl.h"
33 #include "reference-inl.h"
34 #include "runtime.h"
35 #include "string.h"
36 
37 namespace art {
38 namespace mirror {
39 
40 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
GetObjectSize()41 inline uint32_t Class::GetObjectSize() {
42   if (kIsDebugBuild) {
43     // Use a local variable as (D)CHECK can't handle the space between
44     // the two template params.
45     bool is_variable_size = IsVariableSize<kVerifyFlags, kReadBarrierOption>();
46     CHECK(!is_variable_size) << " class=" << PrettyTypeOf(this);
47   }
48   return GetField32(OFFSET_OF_OBJECT_MEMBER(Class, object_size_));
49 }
50 
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() || IsErroneous() || !Runtime::Current()->IsStarted()) << IsLoaded();
55   return GetFieldObject<Class>(OFFSET_OF_OBJECT_MEMBER(Class, super_class_));
56 }
57 
GetClassLoader()58 inline ClassLoader* Class::GetClassLoader() {
59   return GetFieldObject<ClassLoader>(OFFSET_OF_OBJECT_MEMBER(Class, class_loader_));
60 }
61 
62 template<VerifyObjectFlags kVerifyFlags>
GetDexCache()63 inline DexCache* Class::GetDexCache() {
64   return GetFieldObject<DexCache, kVerifyFlags>(OFFSET_OF_OBJECT_MEMBER(Class, dex_cache_));
65 }
66 
GetDirectMethods()67 inline ObjectArray<ArtMethod>* Class::GetDirectMethods() {
68   DCHECK(IsLoaded() || IsErroneous());
69   return GetFieldObject<ObjectArray<ArtMethod>>(OFFSET_OF_OBJECT_MEMBER(Class, direct_methods_));
70 }
71 
SetDirectMethods(ObjectArray<ArtMethod> * new_direct_methods)72 inline void Class::SetDirectMethods(ObjectArray<ArtMethod>* new_direct_methods)
73     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
74   DCHECK(NULL == GetFieldObject<ObjectArray<ArtMethod>>(
75       OFFSET_OF_OBJECT_MEMBER(Class, direct_methods_)));
76   DCHECK_NE(0, new_direct_methods->GetLength());
77   SetFieldObject<false>(OFFSET_OF_OBJECT_MEMBER(Class, direct_methods_), new_direct_methods);
78 }
79 
GetDirectMethod(int32_t i)80 inline ArtMethod* Class::GetDirectMethod(int32_t i) {
81   return GetDirectMethods()->Get(i);
82 }
83 
SetDirectMethod(uint32_t i,ArtMethod * f)84 inline void Class::SetDirectMethod(uint32_t i, ArtMethod* f)  // TODO: uint16_t
85     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
86   ObjectArray<ArtMethod>* direct_methods =
87       GetFieldObject<ObjectArray<ArtMethod>>(OFFSET_OF_OBJECT_MEMBER(Class, direct_methods_));
88   direct_methods->Set<false>(i, f);
89 }
90 
91 // Returns the number of static, private, and constructor methods.
NumDirectMethods()92 inline uint32_t Class::NumDirectMethods() {
93   return (GetDirectMethods() != NULL) ? GetDirectMethods()->GetLength() : 0;
94 }
95 
96 template<VerifyObjectFlags kVerifyFlags>
GetVirtualMethods()97 inline ObjectArray<ArtMethod>* Class::GetVirtualMethods() {
98   DCHECK(IsLoaded() || IsErroneous());
99   return GetFieldObject<ObjectArray<ArtMethod>>(OFFSET_OF_OBJECT_MEMBER(Class, virtual_methods_));
100 }
101 
SetVirtualMethods(ObjectArray<ArtMethod> * new_virtual_methods)102 inline void Class::SetVirtualMethods(ObjectArray<ArtMethod>* new_virtual_methods) {
103   // TODO: we reassign virtual methods to grow the table for miranda
104   // methods.. they should really just be assigned once.
105   DCHECK_NE(0, new_virtual_methods->GetLength());
106   SetFieldObject<false>(OFFSET_OF_OBJECT_MEMBER(Class, virtual_methods_), new_virtual_methods);
107 }
108 
NumVirtualMethods()109 inline uint32_t Class::NumVirtualMethods() {
110   return (GetVirtualMethods() != NULL) ? GetVirtualMethods()->GetLength() : 0;
111 }
112 
113 template<VerifyObjectFlags kVerifyFlags>
GetVirtualMethod(uint32_t i)114 inline ArtMethod* Class::GetVirtualMethod(uint32_t i) {
115   DCHECK(IsResolved<kVerifyFlags>() || IsErroneous<kVerifyFlags>());
116   return GetVirtualMethods()->Get(i);
117 }
118 
GetVirtualMethodDuringLinking(uint32_t i)119 inline ArtMethod* Class::GetVirtualMethodDuringLinking(uint32_t i) {
120   DCHECK(IsLoaded() || IsErroneous());
121   return GetVirtualMethods()->Get(i);
122 }
123 
SetVirtualMethod(uint32_t i,ArtMethod * f)124 inline void Class::SetVirtualMethod(uint32_t i, ArtMethod* f)  // TODO: uint16_t
125     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
126   ObjectArray<ArtMethod>* virtual_methods =
127       GetFieldObject<ObjectArray<ArtMethod>>(OFFSET_OF_OBJECT_MEMBER(Class, virtual_methods_));
128   virtual_methods->Set<false>(i, f);
129 }
130 
GetVTable()131 inline ObjectArray<ArtMethod>* Class::GetVTable() {
132   DCHECK(IsResolved() || IsErroneous());
133   return GetFieldObject<ObjectArray<ArtMethod>>(OFFSET_OF_OBJECT_MEMBER(Class, vtable_));
134 }
135 
GetVTableDuringLinking()136 inline ObjectArray<ArtMethod>* Class::GetVTableDuringLinking() {
137   DCHECK(IsLoaded() || IsErroneous());
138   return GetFieldObject<ObjectArray<ArtMethod>>(OFFSET_OF_OBJECT_MEMBER(Class, vtable_));
139 }
140 
SetVTable(ObjectArray<ArtMethod> * new_vtable)141 inline void Class::SetVTable(ObjectArray<ArtMethod>* new_vtable) {
142   SetFieldObject<false>(OFFSET_OF_OBJECT_MEMBER(Class, vtable_), new_vtable);
143 }
144 
GetImTable()145 inline ObjectArray<ArtMethod>* Class::GetImTable() {
146   return GetFieldObject<ObjectArray<ArtMethod>>(OFFSET_OF_OBJECT_MEMBER(Class, imtable_));
147 }
148 
SetImTable(ObjectArray<ArtMethod> * new_imtable)149 inline void Class::SetImTable(ObjectArray<ArtMethod>* new_imtable) {
150   SetFieldObject<false>(OFFSET_OF_OBJECT_MEMBER(Class, imtable_), new_imtable);
151 }
152 
GetEmbeddedImTableEntry(uint32_t i)153 inline ArtMethod* Class::GetEmbeddedImTableEntry(uint32_t i) {
154   uint32_t offset = EmbeddedImTableOffset().Uint32Value() + i * sizeof(ImTableEntry);
155   return GetFieldObject<mirror::ArtMethod>(MemberOffset(offset));
156 }
157 
SetEmbeddedImTableEntry(uint32_t i,ArtMethod * method)158 inline void Class::SetEmbeddedImTableEntry(uint32_t i, ArtMethod* method) {
159   uint32_t offset = EmbeddedImTableOffset().Uint32Value() + i * sizeof(ImTableEntry);
160   SetFieldObject<false>(MemberOffset(offset), method);
161   CHECK(method == GetImTable()->Get(i));
162 }
163 
HasVTable()164 inline bool Class::HasVTable() {
165   return (GetVTable() != nullptr) || ShouldHaveEmbeddedImtAndVTable();
166 }
167 
GetVTableLength()168 inline int32_t Class::GetVTableLength() {
169   if (ShouldHaveEmbeddedImtAndVTable()) {
170     return GetEmbeddedVTableLength();
171   }
172   return (GetVTable() != nullptr) ? GetVTable()->GetLength() : 0;
173 }
174 
GetVTableEntry(uint32_t i)175 inline ArtMethod* Class::GetVTableEntry(uint32_t i) {
176   if (ShouldHaveEmbeddedImtAndVTable()) {
177     return GetEmbeddedVTableEntry(i);
178   }
179   return (GetVTable() != nullptr) ? GetVTable()->Get(i) : nullptr;
180 }
181 
GetEmbeddedVTableLength()182 inline int32_t Class::GetEmbeddedVTableLength() {
183   return GetField32(EmbeddedVTableLengthOffset());
184 }
185 
SetEmbeddedVTableLength(int32_t len)186 inline void Class::SetEmbeddedVTableLength(int32_t len) {
187   SetField32<false>(EmbeddedVTableLengthOffset(), len);
188 }
189 
GetEmbeddedVTableEntry(uint32_t i)190 inline ArtMethod* Class::GetEmbeddedVTableEntry(uint32_t i) {
191   uint32_t offset = EmbeddedVTableOffset().Uint32Value() + i * sizeof(VTableEntry);
192   return GetFieldObject<mirror::ArtMethod>(MemberOffset(offset));
193 }
194 
SetEmbeddedVTableEntry(uint32_t i,ArtMethod * method)195 inline void Class::SetEmbeddedVTableEntry(uint32_t i, ArtMethod* method) {
196   uint32_t offset = EmbeddedVTableOffset().Uint32Value() + i * sizeof(VTableEntry);
197   SetFieldObject<false>(MemberOffset(offset), method);
198   CHECK(method == GetVTableDuringLinking()->Get(i));
199 }
200 
Implements(Class * klass)201 inline bool Class::Implements(Class* klass) {
202   DCHECK(klass != NULL);
203   DCHECK(klass->IsInterface()) << PrettyClass(this);
204   // All interfaces implemented directly and by our superclass, and
205   // recursively all super-interfaces of those interfaces, are listed
206   // in iftable_, so we can just do a linear scan through that.
207   int32_t iftable_count = GetIfTableCount();
208   IfTable* iftable = GetIfTable();
209   for (int32_t i = 0; i < iftable_count; i++) {
210     if (iftable->GetInterface(i) == klass) {
211       return true;
212     }
213   }
214   return false;
215 }
216 
217 // Determine whether "this" is assignable from "src", where both of these
218 // are array classes.
219 //
220 // Consider an array class, e.g. Y[][], where Y is a subclass of X.
221 //   Y[][]            = Y[][] --> true (identity)
222 //   X[][]            = Y[][] --> true (element superclass)
223 //   Y                = Y[][] --> false
224 //   Y[]              = Y[][] --> false
225 //   Object           = Y[][] --> true (everything is an object)
226 //   Object[]         = Y[][] --> true
227 //   Object[][]       = Y[][] --> true
228 //   Object[][][]     = Y[][] --> false (too many []s)
229 //   Serializable     = Y[][] --> true (all arrays are Serializable)
230 //   Serializable[]   = Y[][] --> true
231 //   Serializable[][] = Y[][] --> false (unless Y is Serializable)
232 //
233 // Don't forget about primitive types.
234 //   Object[]         = int[] --> false
235 //
IsArrayAssignableFromArray(Class * src)236 inline bool Class::IsArrayAssignableFromArray(Class* src) {
237   DCHECK(IsArrayClass())  << PrettyClass(this);
238   DCHECK(src->IsArrayClass()) << PrettyClass(src);
239   return GetComponentType()->IsAssignableFrom(src->GetComponentType());
240 }
241 
IsAssignableFromArray(Class * src)242 inline bool Class::IsAssignableFromArray(Class* src) {
243   DCHECK(!IsInterface()) << PrettyClass(this);  // handled first in IsAssignableFrom
244   DCHECK(src->IsArrayClass()) << PrettyClass(src);
245   if (!IsArrayClass()) {
246     // If "this" is not also an array, it must be Object.
247     // src's super should be java_lang_Object, since it is an array.
248     Class* java_lang_Object = src->GetSuperClass();
249     DCHECK(java_lang_Object != NULL) << PrettyClass(src);
250     DCHECK(java_lang_Object->GetSuperClass() == NULL) << PrettyClass(src);
251     return this == java_lang_Object;
252   }
253   return IsArrayAssignableFromArray(src);
254 }
255 
256 template <bool throw_on_failure, bool use_referrers_cache>
ResolvedFieldAccessTest(Class * access_to,ArtField * field,uint32_t field_idx,DexCache * dex_cache)257 inline bool Class::ResolvedFieldAccessTest(Class* access_to, ArtField* field,
258                                            uint32_t field_idx, DexCache* dex_cache) {
259   DCHECK_EQ(use_referrers_cache, dex_cache == nullptr);
260   if (UNLIKELY(!this->CanAccess(access_to))) {
261     // The referrer class can't access the field's declaring class but may still be able
262     // to access the field if the FieldId specifies an accessible subclass of the declaring
263     // class rather than the declaring class itself.
264     DexCache* referrer_dex_cache = use_referrers_cache ? this->GetDexCache() : dex_cache;
265     uint32_t class_idx = referrer_dex_cache->GetDexFile()->GetFieldId(field_idx).class_idx_;
266     // The referenced class has already been resolved with the field, get it from the dex cache.
267     Class* dex_access_to = referrer_dex_cache->GetResolvedType(class_idx);
268     DCHECK(dex_access_to != nullptr);
269     if (UNLIKELY(!this->CanAccess(dex_access_to))) {
270       if (throw_on_failure) {
271         ThrowIllegalAccessErrorClass(this, dex_access_to);
272       }
273       return false;
274     }
275     DCHECK_EQ(this->CanAccessMember(access_to, field->GetAccessFlags()),
276               this->CanAccessMember(dex_access_to, field->GetAccessFlags()));
277   }
278   if (LIKELY(this->CanAccessMember(access_to, field->GetAccessFlags()))) {
279     return true;
280   }
281   if (throw_on_failure) {
282     ThrowIllegalAccessErrorField(this, field);
283   }
284   return false;
285 }
286 
287 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)288 inline bool Class::ResolvedMethodAccessTest(Class* access_to, ArtMethod* method,
289                                             uint32_t method_idx, DexCache* dex_cache) {
290   COMPILE_ASSERT(throw_on_failure || throw_invoke_type == kStatic, non_default_throw_invoke_type);
291   DCHECK_EQ(use_referrers_cache, dex_cache == nullptr);
292   if (UNLIKELY(!this->CanAccess(access_to))) {
293     // The referrer class can't access the method's declaring class but may still be able
294     // to access the method if the MethodId specifies an accessible subclass of the declaring
295     // class rather than the declaring class itself.
296     DexCache* referrer_dex_cache = use_referrers_cache ? this->GetDexCache() : dex_cache;
297     uint32_t class_idx = referrer_dex_cache->GetDexFile()->GetMethodId(method_idx).class_idx_;
298     // The referenced class has already been resolved with the method, get it from the dex cache.
299     Class* dex_access_to = referrer_dex_cache->GetResolvedType(class_idx);
300     DCHECK(dex_access_to != nullptr);
301     if (UNLIKELY(!this->CanAccess(dex_access_to))) {
302       if (throw_on_failure) {
303         ThrowIllegalAccessErrorClassForMethodDispatch(this, dex_access_to,
304                                                       method, throw_invoke_type);
305       }
306       return false;
307     }
308     DCHECK_EQ(this->CanAccessMember(access_to, method->GetAccessFlags()),
309               this->CanAccessMember(dex_access_to, method->GetAccessFlags()));
310   }
311   if (LIKELY(this->CanAccessMember(access_to, method->GetAccessFlags()))) {
312     return true;
313   }
314   if (throw_on_failure) {
315     ThrowIllegalAccessErrorMethod(this, method);
316   }
317   return false;
318 }
319 
CanAccessResolvedField(Class * access_to,ArtField * field,DexCache * dex_cache,uint32_t field_idx)320 inline bool Class::CanAccessResolvedField(Class* access_to, ArtField* field,
321                                           DexCache* dex_cache, uint32_t field_idx) {
322   return ResolvedFieldAccessTest<false, false>(access_to, field, field_idx, dex_cache);
323 }
324 
CheckResolvedFieldAccess(Class * access_to,ArtField * field,uint32_t field_idx)325 inline bool Class::CheckResolvedFieldAccess(Class* access_to, ArtField* field,
326                                             uint32_t field_idx) {
327   return ResolvedFieldAccessTest<true, true>(access_to, field, field_idx, nullptr);
328 }
329 
CanAccessResolvedMethod(Class * access_to,ArtMethod * method,DexCache * dex_cache,uint32_t method_idx)330 inline bool Class::CanAccessResolvedMethod(Class* access_to, ArtMethod* method,
331                                            DexCache* dex_cache, uint32_t method_idx) {
332   return ResolvedMethodAccessTest<false, false, kStatic>(access_to, method, method_idx, dex_cache);
333 }
334 
335 template <InvokeType throw_invoke_type>
CheckResolvedMethodAccess(Class * access_to,ArtMethod * method,uint32_t method_idx)336 inline bool Class::CheckResolvedMethodAccess(Class* access_to, ArtMethod* method,
337                                              uint32_t method_idx) {
338   return ResolvedMethodAccessTest<true, true, throw_invoke_type>(access_to, method, method_idx,
339                                                                  nullptr);
340 }
341 
IsSubClass(Class * klass)342 inline bool Class::IsSubClass(Class* klass) {
343   DCHECK(!IsInterface()) << PrettyClass(this);
344   DCHECK(!IsArrayClass()) << PrettyClass(this);
345   Class* current = this;
346   do {
347     if (current == klass) {
348       return true;
349     }
350     current = current->GetSuperClass();
351   } while (current != NULL);
352   return false;
353 }
354 
FindVirtualMethodForInterface(ArtMethod * method)355 inline ArtMethod* Class::FindVirtualMethodForInterface(ArtMethod* method) {
356   Class* declaring_class = method->GetDeclaringClass();
357   DCHECK(declaring_class != NULL) << PrettyClass(this);
358   DCHECK(declaring_class->IsInterface()) << PrettyMethod(method);
359   // TODO cache to improve lookup speed
360   int32_t iftable_count = GetIfTableCount();
361   IfTable* iftable = GetIfTable();
362   for (int32_t i = 0; i < iftable_count; i++) {
363     if (iftable->GetInterface(i) == declaring_class) {
364       return iftable->GetMethodArray(i)->Get(method->GetMethodIndex());
365     }
366   }
367   return NULL;
368 }
369 
FindVirtualMethodForVirtual(ArtMethod * method)370 inline ArtMethod* Class::FindVirtualMethodForVirtual(ArtMethod* method) {
371   DCHECK(!method->GetDeclaringClass()->IsInterface() || method->IsMiranda());
372   // The argument method may from a super class.
373   // Use the index to a potentially overridden one for this instance's class.
374   return GetVTableEntry(method->GetMethodIndex());
375 }
376 
FindVirtualMethodForSuper(ArtMethod * method)377 inline ArtMethod* Class::FindVirtualMethodForSuper(ArtMethod* method) {
378   DCHECK(!method->GetDeclaringClass()->IsInterface());
379   return GetSuperClass()->GetVTableEntry(method->GetMethodIndex());
380 }
381 
FindVirtualMethodForVirtualOrInterface(ArtMethod * method)382 inline ArtMethod* Class::FindVirtualMethodForVirtualOrInterface(ArtMethod* method) {
383   if (method->IsDirect()) {
384     return method;
385   }
386   if (method->GetDeclaringClass()->IsInterface() && !method->IsMiranda()) {
387     return FindVirtualMethodForInterface(method);
388   }
389   return FindVirtualMethodForVirtual(method);
390 }
391 
GetIfTable()392 inline IfTable* Class::GetIfTable() {
393   return GetFieldObject<IfTable>(OFFSET_OF_OBJECT_MEMBER(Class, iftable_));
394 }
395 
GetIfTableCount()396 inline int32_t Class::GetIfTableCount() {
397   IfTable* iftable = GetIfTable();
398   if (iftable == NULL) {
399     return 0;
400   }
401   return iftable->Count();
402 }
403 
SetIfTable(IfTable * new_iftable)404 inline void Class::SetIfTable(IfTable* new_iftable) {
405   SetFieldObject<false>(OFFSET_OF_OBJECT_MEMBER(Class, iftable_), new_iftable);
406 }
407 
GetIFields()408 inline ObjectArray<ArtField>* Class::GetIFields() {
409   DCHECK(IsLoaded() || IsErroneous());
410   return GetFieldObject<ObjectArray<ArtField>>(OFFSET_OF_OBJECT_MEMBER(Class, ifields_));
411 }
412 
SetIFields(ObjectArray<ArtField> * new_ifields)413 inline void Class::SetIFields(ObjectArray<ArtField>* new_ifields)
414     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
415   DCHECK(NULL == GetFieldObject<ObjectArray<ArtField>>(OFFSET_OF_OBJECT_MEMBER(Class, ifields_)));
416   SetFieldObject<false>(OFFSET_OF_OBJECT_MEMBER(Class, ifields_), new_ifields);
417 }
418 
GetSFields()419 inline ObjectArray<ArtField>* Class::GetSFields() {
420   DCHECK(IsLoaded() || IsErroneous());
421   return GetFieldObject<ObjectArray<ArtField>>(OFFSET_OF_OBJECT_MEMBER(Class, sfields_));
422 }
423 
SetSFields(ObjectArray<ArtField> * new_sfields)424 inline void Class::SetSFields(ObjectArray<ArtField>* new_sfields)
425     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
426   DCHECK((IsRetired() && new_sfields == nullptr) ||
427          (NULL == GetFieldObject<ObjectArray<ArtField>>(OFFSET_OF_OBJECT_MEMBER(Class, sfields_))));
428   SetFieldObject<false>(OFFSET_OF_OBJECT_MEMBER(Class, sfields_), new_sfields);
429 }
430 
NumStaticFields()431 inline uint32_t Class::NumStaticFields() {
432   return (GetSFields() != NULL) ? GetSFields()->GetLength() : 0;
433 }
434 
435 
GetStaticField(uint32_t i)436 inline ArtField* Class::GetStaticField(uint32_t i)  // TODO: uint16_t
437     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
438   return GetSFields()->GetWithoutChecks(i);
439 }
440 
SetStaticField(uint32_t i,ArtField * f)441 inline void Class::SetStaticField(uint32_t i, ArtField* f)  // TODO: uint16_t
442     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
443   ObjectArray<ArtField>* sfields= GetFieldObject<ObjectArray<ArtField>>(
444       OFFSET_OF_OBJECT_MEMBER(Class, sfields_));
445   sfields->Set<false>(i, f);
446 }
447 
NumInstanceFields()448 inline uint32_t Class::NumInstanceFields() {
449   return (GetIFields() != NULL) ? GetIFields()->GetLength() : 0;
450 }
451 
GetInstanceField(uint32_t i)452 inline ArtField* Class::GetInstanceField(uint32_t i) {  // TODO: uint16_t
453   DCHECK_NE(NumInstanceFields(), 0U);
454   return GetIFields()->GetWithoutChecks(i);
455 }
456 
SetInstanceField(uint32_t i,ArtField * f)457 inline void Class::SetInstanceField(uint32_t i, ArtField* f)  // TODO: uint16_t
458     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
459   ObjectArray<ArtField>* ifields= GetFieldObject<ObjectArray<ArtField>>(
460       OFFSET_OF_OBJECT_MEMBER(Class, ifields_));
461   ifields->Set<false>(i, f);
462 }
463 
464 template<VerifyObjectFlags kVerifyFlags>
GetReferenceInstanceOffsets()465 inline uint32_t Class::GetReferenceInstanceOffsets() {
466   DCHECK(IsResolved<kVerifyFlags>() || IsErroneous<kVerifyFlags>());
467   return GetField32<kVerifyFlags>(OFFSET_OF_OBJECT_MEMBER(Class, reference_instance_offsets_));
468 }
469 
SetClinitThreadId(pid_t new_clinit_thread_id)470 inline void Class::SetClinitThreadId(pid_t new_clinit_thread_id) {
471   if (Runtime::Current()->IsActiveTransaction()) {
472     SetField32<true>(OFFSET_OF_OBJECT_MEMBER(Class, clinit_thread_id_), new_clinit_thread_id);
473   } else {
474     SetField32<false>(OFFSET_OF_OBJECT_MEMBER(Class, clinit_thread_id_), new_clinit_thread_id);
475   }
476 }
477 
SetVerifyErrorClass(Class * klass)478 inline void Class::SetVerifyErrorClass(Class* klass) {
479   CHECK(klass != NULL) << PrettyClass(this);
480   if (Runtime::Current()->IsActiveTransaction()) {
481     SetFieldObject<true>(OFFSET_OF_OBJECT_MEMBER(Class, verify_error_class_), klass);
482   } else {
483     SetFieldObject<false>(OFFSET_OF_OBJECT_MEMBER(Class, verify_error_class_), klass);
484   }
485 }
486 
487 template<VerifyObjectFlags kVerifyFlags>
GetAccessFlags()488 inline uint32_t Class::GetAccessFlags() {
489   // Check class is loaded/retired or this is java.lang.String that has a
490   // circularity issue during loading the names of its members
491   DCHECK(IsIdxLoaded<kVerifyFlags>() || IsRetired<kVerifyFlags>() ||
492          IsErroneous<static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis)>() ||
493          this == String::GetJavaLangString() ||
494          this == ArtField::GetJavaLangReflectArtField() ||
495          this == ArtMethod::GetJavaLangReflectArtMethod());
496   return GetField32<kVerifyFlags>(OFFSET_OF_OBJECT_MEMBER(Class, access_flags_));
497 }
498 
GetName()499 inline String* Class::GetName() {
500   return GetFieldObject<String>(OFFSET_OF_OBJECT_MEMBER(Class, name_));
501 }
SetName(String * name)502 inline void Class::SetName(String* name) {
503   if (Runtime::Current()->IsActiveTransaction()) {
504     SetFieldObject<true>(OFFSET_OF_OBJECT_MEMBER(Class, name_), name);
505   } else {
506     SetFieldObject<false>(OFFSET_OF_OBJECT_MEMBER(Class, name_), name);
507   }
508 }
509 
510 template<VerifyObjectFlags kVerifyFlags>
GetPrimitiveType()511 inline Primitive::Type Class::GetPrimitiveType() {
512   DCHECK_EQ(sizeof(Primitive::Type), sizeof(int32_t));
513   return static_cast<Primitive::Type>(
514       GetField32<kVerifyFlags>(OFFSET_OF_OBJECT_MEMBER(Class, primitive_type_)));
515 }
516 
CheckObjectAlloc()517 inline void Class::CheckObjectAlloc() {
518   DCHECK(!IsArrayClass())
519       << PrettyClass(this)
520       << "A array shouldn't be allocated through this "
521       << "as it requires a pre-fence visitor that sets the class size.";
522   DCHECK(!IsClassClass())
523       << PrettyClass(this)
524       << "A class object shouldn't be allocated through this "
525       << "as it requires a pre-fence visitor that sets the class size.";
526   DCHECK(IsInstantiable()) << PrettyClass(this);
527   // TODO: decide whether we want this check. It currently fails during bootstrap.
528   // DCHECK(!Runtime::Current()->IsStarted() || IsInitializing()) << PrettyClass(this);
529   DCHECK_GE(this->object_size_, sizeof(Object));
530 }
531 
532 template<bool kIsInstrumented, bool kCheckAddFinalizer>
Alloc(Thread * self,gc::AllocatorType allocator_type)533 inline Object* Class::Alloc(Thread* self, gc::AllocatorType allocator_type) {
534   CheckObjectAlloc();
535   gc::Heap* heap = Runtime::Current()->GetHeap();
536   const bool add_finalizer = kCheckAddFinalizer && IsFinalizable();
537   if (!kCheckAddFinalizer) {
538     DCHECK(!IsFinalizable());
539   }
540   mirror::Object* obj =
541       heap->AllocObjectWithAllocator<kIsInstrumented, false>(self, this, this->object_size_,
542                                                              allocator_type, VoidFunctor());
543   if (add_finalizer && LIKELY(obj != nullptr)) {
544     heap->AddFinalizerReference(self, &obj);
545   }
546   return obj;
547 }
548 
AllocObject(Thread * self)549 inline Object* Class::AllocObject(Thread* self) {
550   return Alloc<true>(self, Runtime::Current()->GetHeap()->GetCurrentAllocator());
551 }
552 
AllocNonMovableObject(Thread * self)553 inline Object* Class::AllocNonMovableObject(Thread* self) {
554   return Alloc<true>(self, Runtime::Current()->GetHeap()->GetCurrentNonMovingAllocator());
555 }
556 
ComputeClassSize(bool has_embedded_tables,uint32_t num_vtable_entries,uint32_t num_32bit_static_fields,uint32_t num_64bit_static_fields,uint32_t num_ref_static_fields)557 inline uint32_t Class::ComputeClassSize(bool has_embedded_tables,
558                                         uint32_t num_vtable_entries,
559                                         uint32_t num_32bit_static_fields,
560                                         uint32_t num_64bit_static_fields,
561                                         uint32_t num_ref_static_fields) {
562   // Space used by java.lang.Class and its instance fields.
563   uint32_t size = sizeof(Class);
564   // Space used by embedded tables.
565   if (has_embedded_tables) {
566     uint32_t embedded_imt_size = kImtSize * sizeof(ImTableEntry);
567     uint32_t embedded_vtable_size = num_vtable_entries * sizeof(VTableEntry);
568     size += embedded_imt_size +
569             sizeof(int32_t) /* vtable len */ +
570             embedded_vtable_size;
571   }
572   // Space used by reference statics.
573   size +=  num_ref_static_fields * sizeof(HeapReference<Object>);
574   // Possible pad for alignment.
575   if (((size & 7) != 0) && (num_64bit_static_fields > 0)) {
576     size += sizeof(uint32_t);
577     if (num_32bit_static_fields != 0) {
578       // Shuffle one 32 bit static field forward.
579       num_32bit_static_fields--;
580     }
581   }
582   // Space used for primitive static fields.
583   size += (num_32bit_static_fields * sizeof(uint32_t)) +
584       (num_64bit_static_fields * sizeof(uint64_t));
585   return size;
586 }
587 
588 template <bool kVisitClass, typename Visitor>
VisitReferences(mirror::Class * klass,const Visitor & visitor)589 inline void Class::VisitReferences(mirror::Class* klass, const Visitor& visitor) {
590   // Visit the static fields first so that we don't overwrite the SFields / IFields instance
591   // fields.
592   VisitInstanceFieldsReferences<kVisitClass>(klass, visitor);
593   if (!IsTemp()) {
594     // Temp classes don't ever populate imt/vtable or static fields and they are not even
595     // allocated with the right size for those.
596     VisitStaticFieldsReferences<kVisitClass>(this, visitor);
597     if (ShouldHaveEmbeddedImtAndVTable()) {
598       VisitEmbeddedImtAndVTable(visitor);
599     }
600   }
601 }
602 
603 template<typename Visitor>
VisitEmbeddedImtAndVTable(const Visitor & visitor)604 inline void Class::VisitEmbeddedImtAndVTable(const Visitor& visitor) {
605   uint32_t pos = sizeof(mirror::Class);
606 
607   size_t count = kImtSize;
608   for (size_t i = 0; i < count; ++i) {
609     MemberOffset offset = MemberOffset(pos);
610     visitor(this, offset, true);
611     pos += sizeof(ImTableEntry);
612   }
613 
614   // Skip vtable length.
615   pos += sizeof(int32_t);
616 
617   count = GetEmbeddedVTableLength();
618   for (size_t i = 0; i < count; ++i) {
619     MemberOffset offset = MemberOffset(pos);
620     visitor(this, offset, true);
621     pos += sizeof(VTableEntry);
622   }
623 }
624 
625 template<ReadBarrierOption kReadBarrierOption>
IsArtFieldClass()626 inline bool Class::IsArtFieldClass() const {
627   return this == ArtField::GetJavaLangReflectArtField<kReadBarrierOption>();
628 }
629 
630 template<ReadBarrierOption kReadBarrierOption>
IsArtMethodClass()631 inline bool Class::IsArtMethodClass() const {
632   return this == ArtMethod::GetJavaLangReflectArtMethod<kReadBarrierOption>();
633 }
634 
635 template<ReadBarrierOption kReadBarrierOption>
IsReferenceClass()636 inline bool Class::IsReferenceClass() const {
637   return this == Reference::GetJavaLangRefReference<kReadBarrierOption>();
638 }
639 
640 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
IsClassClass()641 inline bool Class::IsClassClass() {
642   Class* java_lang_Class = GetClass<kVerifyFlags, kReadBarrierOption>()->
643       template GetClass<kVerifyFlags, kReadBarrierOption>();
644   return this == java_lang_Class;
645 }
646 
GetDexFile()647 inline const DexFile& Class::GetDexFile() {
648   return *GetDexCache()->GetDexFile();
649 }
650 
DescriptorEquals(const char * match)651 inline bool Class::DescriptorEquals(const char* match) {
652   if (IsArrayClass()) {
653     return match[0] == '[' && GetComponentType()->DescriptorEquals(match + 1);
654   } else if (IsPrimitive()) {
655     return strcmp(Primitive::Descriptor(GetPrimitiveType()), match) == 0;
656   } else if (IsProxyClass()) {
657     return Runtime::Current()->GetClassLinker()->GetDescriptorForProxy(this) == match;
658   } else {
659     const DexFile& dex_file = GetDexFile();
660     const DexFile::TypeId& type_id = dex_file.GetTypeId(GetClassDef()->class_idx_);
661     return strcmp(dex_file.GetTypeDescriptor(type_id), match) == 0;
662   }
663 }
664 
AssertInitializedOrInitializingInThread(Thread * self)665 inline void Class::AssertInitializedOrInitializingInThread(Thread* self) {
666   if (kIsDebugBuild && !IsInitialized()) {
667     CHECK(IsInitializing()) << PrettyClass(this) << " is not initializing: " << GetStatus();
668     CHECK_EQ(GetClinitThreadId(), self->GetTid()) << PrettyClass(this)
669                                                   << " is initializing in a different thread";
670   }
671 }
672 
GetInterfaces()673 inline ObjectArray<Class>* Class::GetInterfaces() {
674   CHECK(IsProxyClass());
675   // First static field.
676   DCHECK(GetSFields()->Get(0)->IsArtField());
677   DCHECK_STREQ(GetSFields()->Get(0)->GetName(), "interfaces");
678   MemberOffset field_offset = GetSFields()->Get(0)->GetOffset();
679   return GetFieldObject<ObjectArray<Class>>(field_offset);
680 }
681 
GetThrows()682 inline ObjectArray<ObjectArray<Class>>* Class::GetThrows() {
683   CHECK(IsProxyClass());
684   // Second static field.
685   DCHECK(GetSFields()->Get(1)->IsArtField());
686   DCHECK_STREQ(GetSFields()->Get(1)->GetName(), "throws");
687   MemberOffset field_offset = GetSFields()->Get(1)->GetOffset();
688   return GetFieldObject<ObjectArray<ObjectArray<Class>>>(field_offset);
689 }
690 
GetDisableIntrinsicFlagOffset()691 inline MemberOffset Class::GetDisableIntrinsicFlagOffset() {
692   CHECK(IsReferenceClass());
693   // First static field
694   DCHECK(GetSFields()->Get(0)->IsArtField());
695   DCHECK_STREQ(GetSFields()->Get(0)->GetName(), "disableIntrinsic");
696   return GetSFields()->Get(0)->GetOffset();
697 }
698 
GetSlowPathFlagOffset()699 inline MemberOffset Class::GetSlowPathFlagOffset() {
700   CHECK(IsReferenceClass());
701   // Second static field
702   DCHECK(GetSFields()->Get(1)->IsArtField());
703   DCHECK_STREQ(GetSFields()->Get(1)->GetName(), "slowPathEnabled");
704   return GetSFields()->Get(1)->GetOffset();
705 }
706 
GetSlowPathEnabled()707 inline bool Class::GetSlowPathEnabled() {
708   return GetField32(GetSlowPathFlagOffset());
709 }
710 
SetSlowPath(bool enabled)711 inline void Class::SetSlowPath(bool enabled) {
712   SetField32<false>(GetSlowPathFlagOffset(), enabled);
713 }
714 
operator()715 inline void Class::InitializeClassVisitor::operator()(
716     mirror::Object* obj, size_t usable_size) const {
717   DCHECK_LE(class_size_, usable_size);
718   // Avoid AsClass as object is not yet in live bitmap or allocation stack.
719   mirror::Class* klass = down_cast<mirror::Class*>(obj);
720   // DCHECK(klass->IsClass());
721   klass->SetClassSize(class_size_);
722   klass->SetPrimitiveType(Primitive::kPrimNot);  // Default to not being primitive.
723   klass->SetDexClassDefIndex(DexFile::kDexNoIndex16);  // Default to no valid class def index.
724   klass->SetDexTypeIndex(DexFile::kDexNoIndex16);  // Default to no valid type index.
725 }
726 
SetAccessFlags(uint32_t new_access_flags)727 inline void Class::SetAccessFlags(uint32_t new_access_flags) {
728   // Called inside a transaction when setting pre-verified flag during boot image compilation.
729   if (Runtime::Current()->IsActiveTransaction()) {
730     SetField32<true>(OFFSET_OF_OBJECT_MEMBER(Class, access_flags_), new_access_flags);
731   } else {
732     SetField32<false>(OFFSET_OF_OBJECT_MEMBER(Class, access_flags_), new_access_flags);
733   }
734 }
735 
736 }  // namespace mirror
737 }  // namespace art
738 
739 #endif  // ART_RUNTIME_MIRROR_CLASS_INL_H_
740