• 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_OBJECT_REFVISITOR_INL_H_
18 #define ART_RUNTIME_MIRROR_OBJECT_REFVISITOR_INL_H_
19 
20 #include "object-inl.h"
21 
22 #include "class-refvisitor-inl.h"
23 #include "class_loader-inl.h"
24 #include "dex_cache-inl.h"
25 
26 namespace art HIDDEN {
27 namespace mirror {
28 
29 template <VerifyObjectFlags kVerifyFlags,
30           ReadBarrierOption kReadBarrierOption>
CheckNoReferenceField(ObjPtr<mirror::Class> klass)31 static void CheckNoReferenceField(ObjPtr<mirror::Class> klass)
32     REQUIRES_SHARED(art::Locks::mutator_lock_) {
33   if (!kIsDebugBuild) {
34     return;
35   }
36   CHECK(!klass->IsClassClass<kVerifyFlags>());
37   CHECK((!klass->IsObjectArrayClass<kVerifyFlags, kReadBarrierOption>()));
38   // String still has instance fields for reflection purposes but these don't exist in
39   // actual string instances.
40   if (!klass->IsStringClass<kVerifyFlags>()) {
41     size_t total_reference_instance_fields = 0;
42     ObjPtr<Class> super_class = klass;
43     do {
44       total_reference_instance_fields +=
45           super_class->NumReferenceInstanceFields<kVerifyFlags>();
46       super_class = super_class->GetSuperClass<kVerifyFlags, kReadBarrierOption>();
47     } while (super_class != nullptr);
48     // The only reference field should be the object's class.
49     CHECK_EQ(total_reference_instance_fields, 1u);
50   }
51 }
52 
53 template <VerifyObjectFlags kVerifyFlags>
CheckNormalClass(ObjPtr<mirror::Class> klass)54 static void CheckNormalClass(ObjPtr<mirror::Class> klass)
55     REQUIRES_SHARED(art::Locks::mutator_lock_) {
56   DCHECK(!klass->IsVariableSize<kVerifyFlags>());
57   DCHECK(!klass->IsClassClass<kVerifyFlags>());
58   DCHECK(!klass->IsStringClass<kVerifyFlags>());
59   DCHECK(!klass->IsClassLoaderClass<kVerifyFlags>());
60   DCHECK(!klass->IsArrayClass<kVerifyFlags>());
61 }
62 
63 template <bool kVisitNativeRoots,
64           VerifyObjectFlags kVerifyFlags,
65           ReadBarrierOption kReadBarrierOption,
66           typename Visitor,
67           typename JavaLangRefVisitor>
VisitReferences(const Visitor & visitor,const JavaLangRefVisitor & ref_visitor)68 inline void Object::VisitReferences(const Visitor& visitor,
69                                     const JavaLangRefVisitor& ref_visitor) {
70   visitor(this, ClassOffset(), /* is_static= */ false);
71   ObjPtr<Class> klass = GetClass<kVerifyFlags, kReadBarrierOption>();
72   const uint32_t class_flags = klass->GetClassFlags<kVerifyNone>();
73   if (LIKELY(class_flags == kClassFlagNormal) || class_flags == kClassFlagRecord) {
74     CheckNormalClass<kVerifyFlags>(klass);
75     VisitInstanceFieldsReferences<kVerifyFlags, kReadBarrierOption>(klass, visitor);
76     return;
77   }
78 
79   if ((class_flags & kClassFlagNoReferenceFields) != 0) {
80     CheckNoReferenceField<kVerifyFlags, kReadBarrierOption>(klass);
81     return;
82   }
83 
84   DCHECK(!klass->IsStringClass<kVerifyFlags>());
85   if (class_flags == kClassFlagClass) {
86     DCHECK(klass->IsClassClass<kVerifyFlags>());
87     ObjPtr<Class> as_klass = AsClass<kVerifyNone>();
88     as_klass->VisitReferences<kVisitNativeRoots, kVerifyFlags, kReadBarrierOption>(klass, visitor);
89     return;
90   }
91 
92   if (class_flags == kClassFlagObjectArray) {
93     DCHECK((klass->IsObjectArrayClass<kVerifyFlags, kReadBarrierOption>()));
94     AsObjectArray<mirror::Object, kVerifyNone>()->VisitReferences(visitor);
95     return;
96   }
97 
98   if ((class_flags & kClassFlagReference) != 0) {
99     VisitInstanceFieldsReferences<kVerifyFlags, kReadBarrierOption>(klass, visitor);
100     ref_visitor(klass, AsReference<kVerifyFlags, kReadBarrierOption>());
101     return;
102   }
103 
104   if (class_flags == kClassFlagDexCache) {
105     DCHECK(klass->IsDexCacheClass<kVerifyFlags>());
106     ObjPtr<mirror::DexCache> const dex_cache = AsDexCache<kVerifyFlags, kReadBarrierOption>();
107     dex_cache->VisitReferences<kVisitNativeRoots,
108                                kVerifyFlags,
109                                kReadBarrierOption>(klass, visitor);
110     return;
111   }
112 
113   if (class_flags == kClassFlagClassLoader) {
114     DCHECK(klass->IsClassLoaderClass<kVerifyFlags>());
115     ObjPtr<mirror::ClassLoader> const class_loader =
116         AsClassLoader<kVerifyFlags, kReadBarrierOption>();
117     class_loader->VisitReferences<kVisitNativeRoots,
118                                   kVerifyFlags,
119                                   kReadBarrierOption>(klass, visitor);
120     return;
121   }
122 
123   LOG(FATAL) << "Unexpected class flags: " << std::hex << class_flags
124             << " for " << klass->PrettyClass();
125 }
126 
127 // Could be called with from-space address of the object as we access klass and
128 // length (in case of arrays/strings) and we don't want to cause cascading faults.
129 template <bool kFetchObjSize,
130           bool kVisitNativeRoots,
131           VerifyObjectFlags kVerifyFlags,
132           ReadBarrierOption kReadBarrierOption,
133           typename Visitor>
VisitRefsForCompaction(const Visitor & visitor,MemberOffset begin,MemberOffset end)134 inline size_t Object::VisitRefsForCompaction(const Visitor& visitor,
135                                              MemberOffset begin,
136                                              MemberOffset end) {
137   constexpr VerifyObjectFlags kSizeOfFlags = RemoveThisFlags(kVerifyFlags);
138   size_t size;
139   // We want to continue using pre-compact klass to avoid cascading faults.
140   ObjPtr<Class> klass = GetClass<kVerifyFlags, kReadBarrierOption>();
141   DCHECK(klass != nullptr) << "obj=" << this;
142   const uint32_t class_flags = klass->GetClassFlags<kVerifyNone>();
143   if (LIKELY(class_flags == kClassFlagNormal) || class_flags == kClassFlagRecord) {
144     CheckNormalClass<kVerifyFlags>(klass);
145     VisitInstanceFieldsReferences<kVerifyFlags, kReadBarrierOption>(klass, visitor);
146     size = kFetchObjSize ? klass->GetObjectSize<kSizeOfFlags>() : 0;
147   } else if ((class_flags & kClassFlagNoReferenceFields) != 0) {
148     if ((class_flags & kClassFlagString) != 0) {
149       size = kFetchObjSize ? static_cast<String*>(this)->SizeOf<kSizeOfFlags>() : 0;
150     } else if (klass->IsArrayClass<kVerifyFlags>()) {
151       // TODO: We can optimize this by implementing a SizeOf() version which takes
152       // component-size-shift as an argument, thereby avoiding multiple loads of
153       // component_type.
154       size = kFetchObjSize
155              ? static_cast<Array*>(this)->SizeOf<kSizeOfFlags, kReadBarrierOption>()
156              : 0;
157     } else {
158       // Only possibility left is of a normal klass instance with no references.
159       size = kFetchObjSize ? klass->GetObjectSize<kSizeOfFlags>() : 0;
160     }
161   } else if (class_flags == kClassFlagClass) {
162     DCHECK(klass->IsClassClass<kVerifyFlags>());
163     ObjPtr<Class> as_klass = ObjPtr<Class>::DownCast(this);
164     as_klass->VisitReferences<kVisitNativeRoots, kVerifyFlags, kReadBarrierOption>(klass,
165                                                                                    visitor);
166     size = kFetchObjSize ? as_klass->SizeOf<kSizeOfFlags>() : 0;
167   } else if (class_flags == kClassFlagObjectArray) {
168     ObjPtr<ObjectArray<Object>> obj_arr = ObjPtr<ObjectArray<Object>>::DownCast(this);
169     obj_arr->VisitReferences(visitor, begin, end);
170     size = kFetchObjSize ?
171                obj_arr->SizeOf<kSizeOfFlags, kReadBarrierOption, /*kIsObjArray*/ true>() :
172                0;
173   } else if ((class_flags & kClassFlagReference) != 0) {
174     VisitInstanceFieldsReferences<kVerifyFlags, kReadBarrierOption>(klass, visitor);
175     // Visit referent also as this is about updating the reference only.
176     // There is no reference processing happening here.
177     visitor(this, mirror::Reference::ReferentOffset(), /* is_static= */ false);
178     size = kFetchObjSize ? klass->GetObjectSize<kSizeOfFlags>() : 0;
179   } else if (class_flags == kClassFlagDexCache) {
180     DCHECK(klass->IsDexCacheClass<kVerifyFlags>());
181     ObjPtr<DexCache> const dex_cache = ObjPtr<DexCache>::DownCast(this);
182     dex_cache->VisitReferences<kVisitNativeRoots,
183                                kVerifyFlags,
184                                kReadBarrierOption>(klass, visitor);
185     size = kFetchObjSize ? klass->GetObjectSize<kSizeOfFlags>() : 0;
186   } else if (class_flags == kClassFlagClassLoader) {
187     DCHECK(klass->IsClassLoaderClass<kVerifyFlags>());
188     ObjPtr<ClassLoader> const class_loader = ObjPtr<ClassLoader>::DownCast(this);
189     class_loader->VisitReferences<kVisitNativeRoots,
190                                   kVerifyFlags,
191                                   kReadBarrierOption>(klass, visitor);
192     size = kFetchObjSize ? klass->GetObjectSize<kSizeOfFlags>() : 0;
193   } else {
194     LOG(FATAL) << "Unexpected class flags: " << std::hex << class_flags
195                << " for " << klass->PrettyClass();
196     size = -1;
197   }
198   visitor(this, ClassOffset(), /* is_static= */ false);
199   return size;
200 }
201 
202 }  // namespace mirror
203 }  // namespace art
204 
205 #endif  // ART_RUNTIME_MIRROR_OBJECT_REFVISITOR_INL_H_
206