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