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_ARRAY_INL_H_
18 #define ART_RUNTIME_MIRROR_OBJECT_ARRAY_INL_H_
19
20 #include "object_array.h"
21
22 #include <string>
23
24 #include "android-base/stringprintf.h"
25
26 #include "array-inl.h"
27 #include "class.h"
28 #include "obj_ptr-inl.h"
29 #include "object-inl.h"
30 #include "read_barrier-inl.h"
31 #include "runtime.h"
32 #include "thread-current-inl.h"
33 #include "write_barrier-inl.h"
34
35 namespace art {
36 namespace mirror {
37
38 template<class T> template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
Get(int32_t i)39 inline ObjPtr<T> ObjectArray<T>::Get(int32_t i) {
40 if (!CheckIsValidIndex<kVerifyFlags>(i)) {
41 DCHECK(Thread::Current()->IsExceptionPending());
42 return nullptr;
43 }
44 return GetFieldObject<T, kVerifyFlags, kReadBarrierOption>(OffsetOfElement(i));
45 }
46
47 template<class T> template<VerifyObjectFlags kVerifyFlags>
CheckAssignable(ObjPtr<T> object)48 inline bool ObjectArray<T>::CheckAssignable(ObjPtr<T> object) {
49 if (object != nullptr) {
50 ObjPtr<Class> element_class = GetClass<kVerifyFlags>()->GetComponentType();
51 if (UNLIKELY(!object->InstanceOf(element_class))) {
52 ThrowArrayStoreException(object);
53 return false;
54 }
55 }
56 return true;
57 }
58
59 template<class T>
Set(int32_t i,ObjPtr<T> object)60 inline void ObjectArray<T>::Set(int32_t i, ObjPtr<T> object) {
61 if (Runtime::Current()->IsActiveTransaction()) {
62 Set<true>(i, object);
63 } else {
64 Set<false>(i, object);
65 }
66 }
67
68 template<class T>
69 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
Set(int32_t i,ObjPtr<T> object)70 inline void ObjectArray<T>::Set(int32_t i, ObjPtr<T> object) {
71 if (CheckIsValidIndex(i) && CheckAssignable<kVerifyFlags>(object)) {
72 SetFieldObject<kTransactionActive, kCheckTransaction, kVerifyFlags>(OffsetOfElement(i), object);
73 } else {
74 DCHECK(Thread::Current()->IsExceptionPending());
75 }
76 }
77
78 template<class T>
79 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
SetWithoutChecks(int32_t i,ObjPtr<T> object)80 inline void ObjectArray<T>::SetWithoutChecks(int32_t i, ObjPtr<T> object) {
81 DCHECK(CheckIsValidIndex<kVerifyFlags>(i));
82 DCHECK(CheckAssignable<static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis)>(object));
83 SetFieldObject<kTransactionActive, kCheckTransaction, kVerifyFlags>(OffsetOfElement(i), object);
84 }
85
86 template<class T>
87 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
SetWithoutChecksAndWriteBarrier(int32_t i,ObjPtr<T> object)88 inline void ObjectArray<T>::SetWithoutChecksAndWriteBarrier(int32_t i, ObjPtr<T> object) {
89 DCHECK(CheckIsValidIndex<kVerifyFlags>(i));
90 // TODO: enable this check. It fails when writing the image in ImageWriter::FixupObjectArray.
91 // DCHECK(CheckAssignable(object));
92 SetFieldObjectWithoutWriteBarrier<kTransactionActive, kCheckTransaction, kVerifyFlags>(
93 OffsetOfElement(i), object);
94 }
95
96 template<class T> template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
GetWithoutChecks(int32_t i)97 inline ObjPtr<T> ObjectArray<T>::GetWithoutChecks(int32_t i) {
98 DCHECK(CheckIsValidIndex(i));
99 return GetFieldObject<T, kVerifyFlags, kReadBarrierOption>(OffsetOfElement(i));
100 }
101
102 template<class T>
AssignableMemmove(int32_t dst_pos,ObjPtr<ObjectArray<T>> src,int32_t src_pos,int32_t count)103 inline void ObjectArray<T>::AssignableMemmove(int32_t dst_pos,
104 ObjPtr<ObjectArray<T>> src,
105 int32_t src_pos,
106 int32_t count) {
107 if (kIsDebugBuild) {
108 for (int i = 0; i < count; ++i) {
109 // The get will perform the VerifyObject.
110 src->GetWithoutChecks(src_pos + i);
111 }
112 }
113 // Perform the memmove using int memmove then perform the write barrier.
114 static_assert(sizeof(HeapReference<T>) == sizeof(uint32_t),
115 "art::mirror::HeapReference<T> and uint32_t have different sizes.");
116 // TODO: Optimize this later?
117 // We can't use memmove since it does not handle read barriers and may do by per byte copying.
118 // See b/32012820.
119 const bool copy_forward = (src != this) || (dst_pos < src_pos) || (dst_pos - src_pos >= count);
120 if (copy_forward) {
121 // Forward copy.
122 bool baker_non_gray_case = false;
123 if (kUseReadBarrier && kUseBakerReadBarrier) {
124 uintptr_t fake_address_dependency;
125 if (!ReadBarrier::IsGray(src.Ptr(), &fake_address_dependency)) {
126 baker_non_gray_case = true;
127 DCHECK_EQ(fake_address_dependency, 0U);
128 src.Assign(reinterpret_cast<ObjectArray<T>*>(
129 reinterpret_cast<uintptr_t>(src.Ptr()) | fake_address_dependency));
130 for (int i = 0; i < count; ++i) {
131 // We can skip the RB here because 'src' isn't gray.
132 ObjPtr<T> obj = src->template GetWithoutChecks<kDefaultVerifyFlags, kWithoutReadBarrier>(
133 src_pos + i);
134 SetWithoutChecksAndWriteBarrier<false>(dst_pos + i, obj);
135 }
136 }
137 }
138 if (!baker_non_gray_case) {
139 for (int i = 0; i < count; ++i) {
140 // We need a RB here. ObjectArray::GetWithoutChecks() contains a RB.
141 ObjPtr<T> obj = src->GetWithoutChecks(src_pos + i);
142 SetWithoutChecksAndWriteBarrier<false>(dst_pos + i, obj);
143 }
144 }
145 } else {
146 // Backward copy.
147 bool baker_non_gray_case = false;
148 if (kUseReadBarrier && kUseBakerReadBarrier) {
149 uintptr_t fake_address_dependency;
150 if (!ReadBarrier::IsGray(src.Ptr(), &fake_address_dependency)) {
151 baker_non_gray_case = true;
152 DCHECK_EQ(fake_address_dependency, 0U);
153 src.Assign(reinterpret_cast<ObjectArray<T>*>(
154 reinterpret_cast<uintptr_t>(src.Ptr()) | fake_address_dependency));
155 for (int i = count - 1; i >= 0; --i) {
156 // We can skip the RB here because 'src' isn't gray.
157 ObjPtr<T> obj = src->template GetWithoutChecks<kDefaultVerifyFlags, kWithoutReadBarrier>(
158 src_pos + i);
159 SetWithoutChecksAndWriteBarrier<false>(dst_pos + i, obj);
160 }
161 }
162 }
163 if (!baker_non_gray_case) {
164 for (int i = count - 1; i >= 0; --i) {
165 // We need a RB here. ObjectArray::GetWithoutChecks() contains a RB.
166 ObjPtr<T> obj = src->GetWithoutChecks(src_pos + i);
167 SetWithoutChecksAndWriteBarrier<false>(dst_pos + i, obj);
168 }
169 }
170 }
171 WriteBarrier::ForArrayWrite(this, dst_pos, count);
172 if (kIsDebugBuild) {
173 for (int i = 0; i < count; ++i) {
174 // The get will perform the VerifyObject.
175 GetWithoutChecks(dst_pos + i);
176 }
177 }
178 }
179
180 template<class T>
AssignableMemcpy(int32_t dst_pos,ObjPtr<ObjectArray<T>> src,int32_t src_pos,int32_t count)181 inline void ObjectArray<T>::AssignableMemcpy(int32_t dst_pos,
182 ObjPtr<ObjectArray<T>> src,
183 int32_t src_pos,
184 int32_t count) {
185 if (kIsDebugBuild) {
186 for (int i = 0; i < count; ++i) {
187 // The get will perform the VerifyObject.
188 src->GetWithoutChecks(src_pos + i);
189 }
190 }
191 // Perform the memmove using int memcpy then perform the write barrier.
192 static_assert(sizeof(HeapReference<T>) == sizeof(uint32_t),
193 "art::mirror::HeapReference<T> and uint32_t have different sizes.");
194 // TODO: Optimize this later?
195 // We can't use memmove since it does not handle read barriers and may do by per byte copying.
196 // See b/32012820.
197 bool baker_non_gray_case = false;
198 if (kUseReadBarrier && kUseBakerReadBarrier) {
199 uintptr_t fake_address_dependency;
200 if (!ReadBarrier::IsGray(src.Ptr(), &fake_address_dependency)) {
201 baker_non_gray_case = true;
202 DCHECK_EQ(fake_address_dependency, 0U);
203 src.Assign(reinterpret_cast<ObjectArray<T>*>(
204 reinterpret_cast<uintptr_t>(src.Ptr()) | fake_address_dependency));
205 for (int i = 0; i < count; ++i) {
206 // We can skip the RB here because 'src' isn't gray.
207 ObjPtr<Object> obj =
208 src->template GetWithoutChecks<kDefaultVerifyFlags, kWithoutReadBarrier>(src_pos + i);
209 SetWithoutChecksAndWriteBarrier<false>(dst_pos + i, obj);
210 }
211 }
212 }
213 if (!baker_non_gray_case) {
214 for (int i = 0; i < count; ++i) {
215 // We need a RB here. ObjectArray::GetWithoutChecks() contains a RB.
216 ObjPtr<T> obj = src->GetWithoutChecks(src_pos + i);
217 SetWithoutChecksAndWriteBarrier<false>(dst_pos + i, obj);
218 }
219 }
220 WriteBarrier::ForArrayWrite(this, dst_pos, count);
221 if (kIsDebugBuild) {
222 for (int i = 0; i < count; ++i) {
223 // The get will perform the VerifyObject.
224 GetWithoutChecks(dst_pos + i);
225 }
226 }
227 }
228
229 template<class T>
230 template<bool kTransactionActive>
AssignableCheckingMemcpy(int32_t dst_pos,ObjPtr<ObjectArray<T>> src,int32_t src_pos,int32_t count,bool throw_exception)231 inline void ObjectArray<T>::AssignableCheckingMemcpy(int32_t dst_pos,
232 ObjPtr<ObjectArray<T>> src,
233 int32_t src_pos,
234 int32_t count,
235 bool throw_exception) {
236 DCHECK_NE(this, src)
237 << "This case should be handled with memmove that handles overlaps correctly";
238 // We want to avoid redundant IsAssignableFrom checks where possible, so we cache a class that
239 // we know is assignable to the destination array's component type.
240 ObjPtr<Class> dst_class = GetClass()->GetComponentType();
241 ObjPtr<Class> lastAssignableElementClass = dst_class;
242
243 ObjPtr<T> o = nullptr;
244 int i = 0;
245 bool baker_non_gray_case = false;
246 if (kUseReadBarrier && kUseBakerReadBarrier) {
247 uintptr_t fake_address_dependency;
248 if (!ReadBarrier::IsGray(src.Ptr(), &fake_address_dependency)) {
249 baker_non_gray_case = true;
250 DCHECK_EQ(fake_address_dependency, 0U);
251 src.Assign(reinterpret_cast<ObjectArray<T>*>(
252 reinterpret_cast<uintptr_t>(src.Ptr()) | fake_address_dependency));
253 for (; i < count; ++i) {
254 // The follow get operations force the objects to be verified.
255 // We can skip the RB here because 'src' isn't gray.
256 o = src->template GetWithoutChecks<kDefaultVerifyFlags, kWithoutReadBarrier>(
257 src_pos + i);
258 if (o == nullptr) {
259 // Null is always assignable.
260 SetWithoutChecks<kTransactionActive>(dst_pos + i, nullptr);
261 } else {
262 // TODO: use the underlying class reference to avoid uncompression when not necessary.
263 ObjPtr<Class> o_class = o->GetClass();
264 if (LIKELY(lastAssignableElementClass == o_class)) {
265 SetWithoutChecks<kTransactionActive>(dst_pos + i, o);
266 } else if (LIKELY(dst_class->IsAssignableFrom(o_class))) {
267 lastAssignableElementClass = o_class;
268 SetWithoutChecks<kTransactionActive>(dst_pos + i, o);
269 } else {
270 // Can't put this element into the array, break to perform write-barrier and throw
271 // exception.
272 break;
273 }
274 }
275 }
276 }
277 }
278 if (!baker_non_gray_case) {
279 for (; i < count; ++i) {
280 // The follow get operations force the objects to be verified.
281 // We need a RB here. ObjectArray::GetWithoutChecks() contains a RB.
282 o = src->GetWithoutChecks(src_pos + i);
283 if (o == nullptr) {
284 // Null is always assignable.
285 SetWithoutChecks<kTransactionActive>(dst_pos + i, nullptr);
286 } else {
287 // TODO: use the underlying class reference to avoid uncompression when not necessary.
288 ObjPtr<Class> o_class = o->GetClass();
289 if (LIKELY(lastAssignableElementClass == o_class)) {
290 SetWithoutChecks<kTransactionActive>(dst_pos + i, o);
291 } else if (LIKELY(dst_class->IsAssignableFrom(o_class))) {
292 lastAssignableElementClass = o_class;
293 SetWithoutChecks<kTransactionActive>(dst_pos + i, o);
294 } else {
295 // Can't put this element into the array, break to perform write-barrier and throw
296 // exception.
297 break;
298 }
299 }
300 }
301 }
302 WriteBarrier::ForArrayWrite(this, dst_pos, count);
303 if (UNLIKELY(i != count)) {
304 std::string actualSrcType(mirror::Object::PrettyTypeOf(o));
305 std::string dstType(PrettyTypeOf());
306 Thread* self = Thread::Current();
307 std::string msg = android::base::StringPrintf(
308 "source[%d] of type %s cannot be stored in destination array of type %s",
309 src_pos + i,
310 actualSrcType.c_str(),
311 dstType.c_str());
312 if (throw_exception) {
313 self->ThrowNewException("Ljava/lang/ArrayStoreException;", msg.c_str());
314 } else {
315 LOG(FATAL) << msg;
316 }
317 }
318 }
319
320 template<class T>
OffsetOfElement(int32_t i)321 inline MemberOffset ObjectArray<T>::OffsetOfElement(int32_t i) {
322 return MemberOffset(DataOffset(kHeapReferenceSize).Int32Value() + (i * kHeapReferenceSize));
323 }
324
325 template<class T> template<typename Visitor>
VisitReferences(const Visitor & visitor)326 inline void ObjectArray<T>::VisitReferences(const Visitor& visitor) {
327 const size_t length = static_cast<size_t>(GetLength());
328 for (size_t i = 0; i < length; ++i) {
329 visitor(this, OffsetOfElement(i), false);
330 }
331 }
332
333 } // namespace mirror
334 } // namespace art
335
336 #endif // ART_RUNTIME_MIRROR_OBJECT_ARRAY_INL_H_
337