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