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