array-inl.h revision a55cf41c9d1da7ee8b2f63974dedfb484042dd03
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_ARRAY_INL_H_ 18#define ART_RUNTIME_MIRROR_ARRAY_INL_H_ 19 20#include "array.h" 21 22#include "class.h" 23#include "gc/heap-inl.h" 24#include "thread.h" 25#include "utils.h" 26 27namespace art { 28namespace mirror { 29 30static inline size_t HeaderSize(size_t component_size) { 31 return sizeof(Object) + (component_size == sizeof(int64_t) ? 8 : 4); 32} 33 34template<VerifyObjectFlags kVerifyFlags> 35inline size_t Array::SizeOf() { 36 // This is safe from overflow because the array was already allocated, so we know it's sane. 37 size_t component_size = GetClass<kVerifyFlags>()->GetComponentSize(); 38 // Don't need to check this since we already check this in GetClass. 39 int32_t component_count = 40 GetLength<static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis)>(); 41 size_t header_size = HeaderSize(component_size); 42 size_t data_size = component_count * component_size; 43 return header_size + data_size; 44} 45 46static inline size_t ComputeArraySize(Thread* self, Class* array_class, int32_t component_count, 47 size_t component_size) 48 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 49 DCHECK(array_class != NULL); 50 DCHECK_GE(component_count, 0); 51 DCHECK(array_class->IsArrayClass()); 52 53 size_t header_size = HeaderSize(component_size); 54 size_t data_size = component_count * component_size; 55 size_t size = header_size + data_size; 56 57 // Check for overflow and throw OutOfMemoryError if this was an unreasonable request. 58 size_t component_shift = sizeof(size_t) * 8 - 1 - CLZ(component_size); 59 if (UNLIKELY(data_size >> component_shift != size_t(component_count) || size < data_size)) { 60 self->ThrowOutOfMemoryError(StringPrintf("%s of length %d would overflow", 61 PrettyDescriptor(array_class).c_str(), 62 component_count).c_str()); 63 return 0; // failure 64 } 65 return size; 66} 67 68// Used for setting the array length in the allocation code path to ensure it is guarded by a 69// StoreStore fence. 70class SetLengthVisitor { 71 public: 72 explicit SetLengthVisitor(int32_t length) : length_(length) { 73 } 74 75 void operator()(Object* obj, size_t usable_size) const 76 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 77 UNUSED(usable_size); 78 // Avoid AsArray as object is not yet in live bitmap or allocation stack. 79 Array* array = down_cast<Array*>(obj); 80 // DCHECK(array->IsArrayInstance()); 81 array->SetLength(length_); 82 } 83 84 private: 85 const int32_t length_; 86 87 DISALLOW_COPY_AND_ASSIGN(SetLengthVisitor); 88}; 89 90// Similar to SetLengthVisitor, used for setting the array length to fill the usable size of an 91// array. 92class SetLengthToUsableSizeVisitor { 93 public: 94 SetLengthToUsableSizeVisitor(int32_t min_length, size_t header_size, size_t component_size) : 95 minimum_length_(min_length), header_size_(header_size), component_size_(component_size) { 96 } 97 98 void operator()(Object* obj, size_t usable_size) const 99 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 100 // Avoid AsArray as object is not yet in live bitmap or allocation stack. 101 Array* array = down_cast<Array*>(obj); 102 // DCHECK(array->IsArrayInstance()); 103 int32_t length = (usable_size - header_size_) / component_size_; 104 DCHECK_GE(length, minimum_length_); 105 byte* old_end = reinterpret_cast<byte*>(array->GetRawData(component_size_, minimum_length_)); 106 byte* new_end = reinterpret_cast<byte*>(array->GetRawData(component_size_, length)); 107 // Ensure space beyond original allocation is zeroed. 108 memset(old_end, 0, new_end - old_end); 109 array->SetLength(length); 110 } 111 112 private: 113 const int32_t minimum_length_; 114 const size_t header_size_; 115 const size_t component_size_; 116 117 DISALLOW_COPY_AND_ASSIGN(SetLengthToUsableSizeVisitor); 118}; 119 120template <bool kIsInstrumented> 121inline Array* Array::Alloc(Thread* self, Class* array_class, int32_t component_count, 122 size_t component_size, gc::AllocatorType allocator_type, 123 bool fill_usable) { 124 DCHECK(allocator_type != gc::kAllocatorTypeLOS); 125 size_t size = ComputeArraySize(self, array_class, component_count, component_size); 126 if (UNLIKELY(size == 0)) { 127 return nullptr; 128 } 129 gc::Heap* heap = Runtime::Current()->GetHeap(); 130 Array* result; 131 if (!fill_usable) { 132 SetLengthVisitor visitor(component_count); 133 result = down_cast<Array*>( 134 heap->AllocObjectWithAllocator<kIsInstrumented, true>(self, array_class, size, 135 allocator_type, visitor)); 136 } else { 137 SetLengthToUsableSizeVisitor visitor(component_count, HeaderSize(component_size), 138 component_size); 139 result = down_cast<Array*>( 140 heap->AllocObjectWithAllocator<kIsInstrumented, true>(self, array_class, size, 141 allocator_type, visitor)); 142 } 143 if (kIsDebugBuild && result != nullptr && Runtime::Current()->IsStarted()) { 144 CHECK_EQ(array_class->GetComponentSize(), component_size); 145 if (!fill_usable) { 146 CHECK_EQ(result->SizeOf(), size); 147 } else { 148 CHECK_GE(result->SizeOf(), size); 149 } 150 } 151 return result; 152} 153 154template<class T> 155inline void PrimitiveArray<T>::VisitRoots(RootCallback* callback, void* arg) { 156 if (array_class_ != nullptr) { 157 callback(reinterpret_cast<mirror::Object**>(&array_class_), arg, 0, kRootStickyClass); 158 } 159} 160 161// Similar to memmove except elements are of aligned appropriately for T, count is in T sized units 162// copies are guaranteed not to tear when T is less-than 64bit. 163template<typename T> 164static inline void ArrayBackwardCopy(T* d, const T* s, int32_t count) { 165 d += count; 166 s += count; 167 for (int32_t i = 0; i < count; ++i) { 168 d--; 169 s--; 170 *d = *s; 171 } 172} 173 174template<typename T> 175inline PrimitiveArray<T>* PrimitiveArray<T>::Alloc(Thread* self, size_t length) { 176 DCHECK(array_class_ != NULL); 177 Array* raw_array = Array::Alloc<true>(self, array_class_, length, sizeof(T), 178 Runtime::Current()->GetHeap()->GetCurrentAllocator()); 179 return down_cast<PrimitiveArray<T>*>(raw_array); 180} 181 182template<class T> 183inline void PrimitiveArray<T>::Memmove(int32_t dst_pos, PrimitiveArray<T>* src, int32_t src_pos, 184 int32_t count) { 185 if (UNLIKELY(count == 0)) { 186 return; 187 } 188 DCHECK_GE(dst_pos, 0); 189 DCHECK_GE(src_pos, 0); 190 DCHECK_GT(count, 0); 191 DCHECK(src != nullptr); 192 DCHECK_LT(dst_pos, GetLength()); 193 DCHECK_LE(dst_pos, GetLength() - count); 194 DCHECK_LT(src_pos, src->GetLength()); 195 DCHECK_LE(src_pos, src->GetLength() - count); 196 197 // Note for non-byte copies we can't rely on standard libc functions like memcpy(3) and memmove(3) 198 // in our implementation, because they may copy byte-by-byte. 199 if (LIKELY(src != this) || (dst_pos < src_pos) || (dst_pos - src_pos >= count)) { 200 // Forward copy ok. 201 Memcpy(dst_pos, src, src_pos, count); 202 } else { 203 // Backward copy necessary. 204 void* dst_raw = GetRawData(sizeof(T), dst_pos); 205 const void* src_raw = src->GetRawData(sizeof(T), src_pos); 206 if (sizeof(T) == sizeof(uint8_t)) { 207 // TUNING: use memmove here? 208 uint8_t* d = reinterpret_cast<uint8_t*>(dst_raw); 209 const uint8_t* s = reinterpret_cast<const uint8_t*>(src_raw); 210 ArrayBackwardCopy<uint8_t>(d, s, count); 211 } else if (sizeof(T) == sizeof(uint16_t)) { 212 uint16_t* d = reinterpret_cast<uint16_t*>(dst_raw); 213 const uint16_t* s = reinterpret_cast<const uint16_t*>(src_raw); 214 ArrayBackwardCopy<uint16_t>(d, s, count); 215 } else if (sizeof(T) == sizeof(uint32_t)) { 216 uint32_t* d = reinterpret_cast<uint32_t*>(dst_raw); 217 const uint32_t* s = reinterpret_cast<const uint32_t*>(src_raw); 218 ArrayBackwardCopy<uint32_t>(d, s, count); 219 } else { 220 DCHECK_EQ(sizeof(T), sizeof(uint64_t)); 221 uint64_t* d = reinterpret_cast<uint64_t*>(dst_raw); 222 const uint64_t* s = reinterpret_cast<const uint64_t*>(src_raw); 223 ArrayBackwardCopy<uint64_t>(d, s, count); 224 } 225 } 226} 227 228// Similar to memcpy except elements are of aligned appropriately for T, count is in T sized units 229// copies are guaranteed not to tear when T is less-than 64bit. 230template<typename T> 231static inline void ArrayForwardCopy(T* d, const T* s, int32_t count) { 232 for (int32_t i = 0; i < count; ++i) { 233 *d = *s; 234 d++; 235 s++; 236 } 237} 238 239 240template<class T> 241inline void PrimitiveArray<T>::Memcpy(int32_t dst_pos, PrimitiveArray<T>* src, int32_t src_pos, 242 int32_t count) { 243 if (UNLIKELY(count == 0)) { 244 return; 245 } 246 DCHECK_GE(dst_pos, 0); 247 DCHECK_GE(src_pos, 0); 248 DCHECK_GT(count, 0); 249 DCHECK(src != nullptr); 250 DCHECK_LT(dst_pos, GetLength()); 251 DCHECK_LE(dst_pos, GetLength() - count); 252 DCHECK_LT(src_pos, src->GetLength()); 253 DCHECK_LE(src_pos, src->GetLength() - count); 254 255 // Note for non-byte copies we can't rely on standard libc functions like memcpy(3) and memmove(3) 256 // in our implementation, because they may copy byte-by-byte. 257 void* dst_raw = GetRawData(sizeof(T), dst_pos); 258 const void* src_raw = src->GetRawData(sizeof(T), src_pos); 259 if (sizeof(T) == sizeof(uint8_t)) { 260 memcpy(dst_raw, src_raw, count); 261 } else if (sizeof(T) == sizeof(uint16_t)) { 262 uint16_t* d = reinterpret_cast<uint16_t*>(dst_raw); 263 const uint16_t* s = reinterpret_cast<const uint16_t*>(src_raw); 264 ArrayForwardCopy<uint16_t>(d, s, count); 265 } else if (sizeof(T) == sizeof(uint32_t)) { 266 uint32_t* d = reinterpret_cast<uint32_t*>(dst_raw); 267 const uint32_t* s = reinterpret_cast<const uint32_t*>(src_raw); 268 ArrayForwardCopy<uint32_t>(d, s, count); 269 } else { 270 DCHECK_EQ(sizeof(T), sizeof(uint64_t)); 271 uint64_t* d = reinterpret_cast<uint64_t*>(dst_raw); 272 const uint64_t* s = reinterpret_cast<const uint64_t*>(src_raw); 273 ArrayForwardCopy<uint64_t>(d, s, count); 274 } 275} 276 277} // namespace mirror 278} // namespace art 279 280#endif // ART_RUNTIME_MIRROR_ARRAY_INL_H_ 281