1 /*
2  * Copyright (C) 2017 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_EXT_INL_H_
18 #define ART_RUNTIME_MIRROR_CLASS_EXT_INL_H_
19 
20 #include "class_ext.h"
21 
22 #include "array-inl.h"
23 #include "art_method-inl.h"
24 #include "base/enums.h"
25 #include "base/globals.h"
26 #include "class_root.h"
27 #include "handle_scope.h"
28 #include "jni/jni_internal.h"
29 #include "jni_id_type.h"
30 #include "mirror/array.h"
31 #include "mirror/object.h"
32 #include "object-inl.h"
33 #include "verify_object.h"
34 #include "well_known_classes.h"
35 
36 namespace art {
37 namespace mirror {
38 
39 template <VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
EnsureJniIdsArrayPresent(MemberOffset off,size_t count)40 inline bool ClassExt::EnsureJniIdsArrayPresent(MemberOffset off, size_t count) {
41   ObjPtr<Object> existing(
42       GetFieldObject<Object, kVerifyFlags, kReadBarrierOption>(off));
43   if (!existing.IsNull()) {
44     return true;
45   }
46   Thread* self = Thread::Current();
47   StackHandleScope<2> hs(self);
48   Handle<ClassExt> h_this(hs.NewHandle(this));
49   MutableHandle<Object> new_arr(hs.NewHandle<Object>(nullptr));
50   if (UNLIKELY(Runtime::Current()->GetJniIdType() == JniIdType::kSwapablePointer)) {
51     new_arr.Assign(Runtime::Current()->GetJniIdManager()->GetPointerMarker());
52   } else {
53     new_arr.Assign(Runtime::Current()->GetClassLinker()->AllocPointerArray(self, count));
54   }
55   if (new_arr.IsNull()) {
56     // Fail.
57     self->AssertPendingOOMException();
58     return false;
59   }
60   bool set;
61   // Set the ext_data_ field using CAS semantics.
62   if (Runtime::Current()->IsActiveTransaction()) {
63     set = h_this->CasFieldObject<true>(
64         off, nullptr, new_arr.Get(), CASMode::kStrong, std::memory_order_seq_cst);
65   } else {
66     set = h_this->CasFieldObject<false>(
67         off, nullptr, new_arr.Get(), CASMode::kStrong, std::memory_order_seq_cst);
68   }
69   if (kIsDebugBuild) {
70     ObjPtr<Object> ret(
71         set ? new_arr.Get()
72             : h_this->GetFieldObject<PointerArray, kVerifyFlags, kReadBarrierOption>(off));
73     CHECK(!ret.IsNull());
74   }
75   return true;
76 }
77 
78 template <VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
EnsureJMethodIDsArrayPresent(size_t count)79 inline bool ClassExt::EnsureJMethodIDsArrayPresent(size_t count) {
80   return EnsureJniIdsArrayPresent<kVerifyFlags, kReadBarrierOption>(
81       MemberOffset(OFFSET_OF_OBJECT_MEMBER(ClassExt, jmethod_ids_)), count);
82 }
83 template <VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
EnsureStaticJFieldIDsArrayPresent(size_t count)84 inline bool ClassExt::EnsureStaticJFieldIDsArrayPresent(size_t count) {
85   return EnsureJniIdsArrayPresent<kVerifyFlags, kReadBarrierOption>(
86       MemberOffset(OFFSET_OF_OBJECT_MEMBER(ClassExt, static_jfield_ids_)), count);
87 }
88 template <VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
EnsureInstanceJFieldIDsArrayPresent(size_t count)89 inline bool ClassExt::EnsureInstanceJFieldIDsArrayPresent(size_t count) {
90   return EnsureJniIdsArrayPresent<kVerifyFlags, kReadBarrierOption>(
91       MemberOffset(OFFSET_OF_OBJECT_MEMBER(ClassExt, instance_jfield_ids_)), count);
92 }
93 
94 template <VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
GetInstanceJFieldIDs()95 inline ObjPtr<Object> ClassExt::GetInstanceJFieldIDs() {
96   return GetFieldObject<Object, kVerifyFlags, kReadBarrierOption>(
97       OFFSET_OF_OBJECT_MEMBER(ClassExt, instance_jfield_ids_));
98 }
99 template <VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
HasInstanceFieldPointerIdMarker()100 inline bool ClassExt::HasInstanceFieldPointerIdMarker() {
101   ObjPtr<Object> arr(GetInstanceJFieldIDs<kVerifyFlags, kReadBarrierOption>());
102   return !arr.IsNull() && !arr->IsArrayInstance();
103 }
104 template <VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
GetInstanceJFieldIDsPointerArray()105 inline ObjPtr<PointerArray> ClassExt::GetInstanceJFieldIDsPointerArray() {
106   DCHECK(!HasInstanceFieldPointerIdMarker());
107   return down_cast<PointerArray*>(GetInstanceJFieldIDs<kVerifyFlags, kReadBarrierOption>().Ptr());
108 }
109 
110 template <VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
GetStaticJFieldIDs()111 inline ObjPtr<Object> ClassExt::GetStaticJFieldIDs() {
112   return GetFieldObject<Object, kVerifyFlags, kReadBarrierOption>(
113       OFFSET_OF_OBJECT_MEMBER(ClassExt, static_jfield_ids_));
114 }
115 template <VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
GetStaticJFieldIDsPointerArray()116 inline ObjPtr<PointerArray> ClassExt::GetStaticJFieldIDsPointerArray() {
117   DCHECK(!HasStaticFieldPointerIdMarker());
118   return down_cast<PointerArray*>(GetStaticJFieldIDs<kVerifyFlags, kReadBarrierOption>().Ptr());
119 }
120 template <VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
HasStaticFieldPointerIdMarker()121 inline bool ClassExt::HasStaticFieldPointerIdMarker() {
122   ObjPtr<Object> arr(GetStaticJFieldIDs<kVerifyFlags, kReadBarrierOption>());
123   return !arr.IsNull() && !arr->IsArrayInstance();
124 }
125 
126 template <VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
GetObsoleteClass()127 inline ObjPtr<Class> ClassExt::GetObsoleteClass() {
128   return GetFieldObject<Class, kVerifyFlags, kReadBarrierOption>(
129       OFFSET_OF_OBJECT_MEMBER(ClassExt, obsolete_class_));
130 }
131 
132 template <VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
GetJMethodIDs()133 inline ObjPtr<Object> ClassExt::GetJMethodIDs() {
134   return GetFieldObject<Object, kVerifyFlags, kReadBarrierOption>(
135       OFFSET_OF_OBJECT_MEMBER(ClassExt, jmethod_ids_));
136 }
137 template <VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
GetJMethodIDsPointerArray()138 inline ObjPtr<PointerArray> ClassExt::GetJMethodIDsPointerArray() {
139   DCHECK(!HasMethodPointerIdMarker());
140   return down_cast<PointerArray*>(GetJMethodIDs<kVerifyFlags, kReadBarrierOption>().Ptr());
141 }
142 template <VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
HasMethodPointerIdMarker()143 inline bool ClassExt::HasMethodPointerIdMarker() {
144   ObjPtr<Object> arr(GetJMethodIDs<kVerifyFlags, kReadBarrierOption>());
145   return !arr.IsNull() && !arr->IsArrayInstance();
146 }
147 
148 
GetVerifyError()149 inline ObjPtr<Object> ClassExt::GetVerifyError() {
150   return GetFieldObject<ClassExt>(OFFSET_OF_OBJECT_MEMBER(ClassExt, verify_error_));
151 }
152 
GetObsoleteDexCaches()153 inline ObjPtr<ObjectArray<DexCache>> ClassExt::GetObsoleteDexCaches() {
154   return GetFieldObject<ObjectArray<DexCache>>(
155       OFFSET_OF_OBJECT_MEMBER(ClassExt, obsolete_dex_caches_));
156 }
157 
158 template<VerifyObjectFlags kVerifyFlags,
159          ReadBarrierOption kReadBarrierOption>
GetObsoleteMethods()160 inline ObjPtr<PointerArray> ClassExt::GetObsoleteMethods() {
161   return GetFieldObject<PointerArray, kVerifyFlags, kReadBarrierOption>(
162       OFFSET_OF_OBJECT_MEMBER(ClassExt, obsolete_methods_));
163 }
164 
GetOriginalDexFile()165 inline ObjPtr<Object> ClassExt::GetOriginalDexFile() {
166   return GetFieldObject<Object>(OFFSET_OF_OBJECT_MEMBER(ClassExt, original_dex_file_));
167 }
168 
169 template<ReadBarrierOption kReadBarrierOption, class Visitor>
VisitNativeRoots(Visitor & visitor,PointerSize pointer_size)170 void ClassExt::VisitNativeRoots(Visitor& visitor, PointerSize pointer_size) {
171   VisitMethods<kReadBarrierOption>([&](ArtMethod* method) {
172     method->VisitRoots<kReadBarrierOption>(visitor, pointer_size);
173   }, pointer_size);
174 }
175 
176 template<ReadBarrierOption kReadBarrierOption, class Visitor>
VisitMethods(Visitor visitor,PointerSize pointer_size)177 void ClassExt::VisitMethods(Visitor visitor, PointerSize pointer_size) {
178   ObjPtr<PointerArray> arr(GetObsoleteMethods<kDefaultVerifyFlags, kReadBarrierOption>());
179   if (!arr.IsNull()) {
180     int32_t len = arr->GetLength();
181     for (int32_t i = 0; i < len; i++) {
182       ArtMethod* method = arr->GetElementPtrSize<ArtMethod*>(i, pointer_size);
183       if (method != nullptr) {
184         visitor(method);
185       }
186     }
187   }
188 }
189 
190 template<ReadBarrierOption kReadBarrierOption, class Visitor>
VisitJMethodIDs(Visitor v)191 void ClassExt::VisitJMethodIDs(Visitor v) {
192   ObjPtr<Object> arr(GetJMethodIDs<kDefaultVerifyFlags, kReadBarrierOption>());
193   if (!arr.IsNull() && arr->IsArrayInstance()) {
194     ObjPtr<PointerArray> marr(down_cast<PointerArray*>(arr.Ptr()));
195     int32_t len = marr->GetLength();
196     for (int32_t i = 0; i < len; i++) {
197       jmethodID id = marr->GetElementPtrSize<jmethodID>(i, kRuntimePointerSize);
198       if (id != nullptr) {
199         v(id, i);
200       }
201     }
202   }
203 }
204 template<ReadBarrierOption kReadBarrierOption, class Visitor>
VisitJFieldIDs(Visitor v)205 void ClassExt::VisitJFieldIDs(Visitor v) {
206   ObjPtr<Object> sarr_obj(GetStaticJFieldIDs<kDefaultVerifyFlags, kReadBarrierOption>());
207   if (!sarr_obj.IsNull() && sarr_obj->IsArrayInstance()) {
208     ObjPtr<PointerArray> sarr(down_cast<PointerArray*>(sarr_obj->AsArray().Ptr()));
209     int32_t len = sarr->GetLength();
210     for (int32_t i = 0; i < len; i++) {
211       jfieldID id = sarr->GetElementPtrSize<jfieldID>(i, kRuntimePointerSize);
212       if (id != nullptr) {
213         v(id, i, true);
214       }
215     }
216   }
217   ObjPtr<PointerArray> iarr_obj(GetInstanceJFieldIDs<kDefaultVerifyFlags, kReadBarrierOption>());
218   if (!iarr_obj.IsNull() && iarr_obj->IsArrayInstance()) {
219     ObjPtr<PointerArray> iarr(down_cast<PointerArray*>(iarr_obj->AsArray().Ptr()));
220     int32_t len = iarr->GetLength();
221     for (int32_t i = 0; i < len; i++) {
222       jfieldID id = iarr->GetElementPtrSize<jfieldID>(i, kRuntimePointerSize);
223       if (id != nullptr) {
224         v(id, i, false);
225       }
226     }
227   }
228 }
229 
230 }  // namespace mirror
231 }  // namespace art
232 
233 #endif  // ART_RUNTIME_MIRROR_CLASS_EXT_INL_H_
234