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