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