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> 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> 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> 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> 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> 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> 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> 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> 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> 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> 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> 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> 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> 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> 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> 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