blob: 704fb118e3376747c73cfded18dcd1e99e34b5a8 [file] [log] [blame]
Ian Rogers2dd0e2c2013-01-24 12:42:14 -08001/*
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
Brian Carlstromfc0e3212013-07-17 14:40:12 -070017#ifndef ART_RUNTIME_MIRROR_ARRAY_INL_H_
18#define ART_RUNTIME_MIRROR_ARRAY_INL_H_
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080019
20#include "array.h"
21
Andreas Gampe57943812017-12-06 21:39:13 -080022#include <android-base/logging.h>
23#include <android-base/stringprintf.h>
Andreas Gampe46ee31b2016-12-14 10:11:49 -080024
Vladimir Marko80afd022015-05-19 18:08:00 +010025#include "base/bit_utils.h"
Mathieu Chartiere401d142015-04-22 13:56:20 -070026#include "base/casts.h"
Andreas Gampec6ea7d02017-02-01 16:46:28 -080027#include "class.h"
Hiroshi Yamauchi3b4c1892013-09-12 21:33:12 -070028#include "gc/heap-inl.h"
Mathieu Chartier1a5337f2016-10-13 13:48:23 -070029#include "obj_ptr-inl.h"
Andreas Gampe895f9222017-07-05 09:53:32 -070030#include "thread-current-inl.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080031
32namespace art {
33namespace mirror {
34
Andreas Gampe542451c2016-07-26 09:02:02 -070035inline uint32_t Array::ClassSize(PointerSize pointer_size) {
Mingyao Yang98d1cc82014-05-15 17:02:16 -070036 uint32_t vtable_entries = Object::kVTableLength;
Mathieu Chartiere401d142015-04-22 13:56:20 -070037 return Class::ComputeClassSize(true, vtable_entries, 0, 0, 0, 0, 0, pointer_size);
Mingyao Yang98d1cc82014-05-15 17:02:16 -070038}
39
Hiroshi Yamauchi6e83c172014-05-01 21:25:41 -070040template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
Ian Rogersef7d42f2014-01-06 12:55:46 -080041inline size_t Array::SizeOf() {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080042 // This is safe from overflow because the array was already allocated, so we know it's sane.
Hiroshi Yamauchif0edfc32014-09-25 11:46:46 -070043 size_t component_size_shift = GetClass<kVerifyFlags, kReadBarrierOption>()->
44 template GetComponentSizeShift<kReadBarrierOption>();
Mathieu Chartier4e305412014-02-19 10:54:44 -080045 // Don't need to check this since we already check this in GetClass.
46 int32_t component_count =
47 GetLength<static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis)>();
Hiroshi Yamauchif0edfc32014-09-25 11:46:46 -070048 size_t header_size = DataOffset(1U << component_size_shift).SizeValue();
49 size_t data_size = component_count << component_size_shift;
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080050 return header_size + data_size;
51}
52
Ian Rogersb0fa5dc2014-04-28 16:47:08 -070053template<VerifyObjectFlags kVerifyFlags>
54inline bool Array::CheckIsValidIndex(int32_t index) {
55 if (UNLIKELY(static_cast<uint32_t>(index) >=
56 static_cast<uint32_t>(GetLength<kVerifyFlags>()))) {
57 ThrowArrayIndexOutOfBoundsException(index);
58 return false;
59 }
60 return true;
61}
62
Vladimir Marko20f85592015-03-19 10:07:02 +000063static inline size_t ComputeArraySize(int32_t component_count, size_t component_size_shift) {
Hiroshi Yamauchi967a0ad2013-09-10 16:24:21 -070064 DCHECK_GE(component_count, 0);
Hiroshi Yamauchi967a0ad2013-09-10 16:24:21 -070065
Hiroshi Yamauchif0edfc32014-09-25 11:46:46 -070066 size_t component_size = 1U << component_size_shift;
Hiroshi Yamauchiaa866f52014-03-21 16:18:30 -070067 size_t header_size = Array::DataOffset(component_size).SizeValue();
Hiroshi Yamauchif0edfc32014-09-25 11:46:46 -070068 size_t data_size = static_cast<size_t>(component_count) << component_size_shift;
Hiroshi Yamauchi967a0ad2013-09-10 16:24:21 -070069 size_t size = header_size + data_size;
70
Vladimir Marko20f85592015-03-19 10:07:02 +000071 // Check for size_t overflow if this was an unreasonable request
72 // but let the caller throw OutOfMemoryError.
Hiroshi Yamauchif0edfc32014-09-25 11:46:46 -070073#ifdef __LP64__
74 // 64-bit. No overflow as component_count is 32-bit and the maximum
75 // component size is 8.
76 DCHECK_LE((1U << component_size_shift), 8U);
77#else
78 // 32-bit.
79 DCHECK_NE(header_size, 0U);
80 DCHECK_EQ(RoundUp(header_size, component_size), header_size);
81 // The array length limit (exclusive).
82 const size_t length_limit = (0U - header_size) >> component_size_shift;
83 if (UNLIKELY(length_limit <= static_cast<size_t>(component_count))) {
Hiroshi Yamauchi3b4c1892013-09-12 21:33:12 -070084 return 0; // failure
Hiroshi Yamauchi967a0ad2013-09-10 16:24:21 -070085 }
Hiroshi Yamauchif0edfc32014-09-25 11:46:46 -070086#endif
Hiroshi Yamauchi3b4c1892013-09-12 21:33:12 -070087 return size;
88}
Hiroshi Yamauchi967a0ad2013-09-10 16:24:21 -070089
Ian Rogers6fac4472014-02-25 17:01:10 -080090// Used for setting the array length in the allocation code path to ensure it is guarded by a
91// StoreStore fence.
Mathieu Chartier1febddf2013-11-20 12:33:14 -080092class SetLengthVisitor {
93 public:
94 explicit SetLengthVisitor(int32_t length) : length_(length) {
Hiroshi Yamauchi967a0ad2013-09-10 16:24:21 -070095 }
Mathieu Chartier1febddf2013-11-20 12:33:14 -080096
Mathieu Chartier9d156d52016-10-06 17:44:26 -070097 void operator()(ObjPtr<Object> obj, size_t usable_size ATTRIBUTE_UNUSED) const
Andreas Gampebdf7f1c2016-08-30 16:38:47 -070098 REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogersef7d42f2014-01-06 12:55:46 -080099 // Avoid AsArray as object is not yet in live bitmap or allocation stack.
Mathieu Chartier9d156d52016-10-06 17:44:26 -0700100 ObjPtr<Array> array = ObjPtr<Array>::DownCast(obj);
Ian Rogersef7d42f2014-01-06 12:55:46 -0800101 // DCHECK(array->IsArrayInstance());
Mathieu Chartier1febddf2013-11-20 12:33:14 -0800102 array->SetLength(length_);
103 }
104
105 private:
106 const int32_t length_;
Ian Rogers6fac4472014-02-25 17:01:10 -0800107
108 DISALLOW_COPY_AND_ASSIGN(SetLengthVisitor);
109};
110
111// Similar to SetLengthVisitor, used for setting the array length to fill the usable size of an
112// array.
113class SetLengthToUsableSizeVisitor {
114 public:
Hiroshi Yamauchif0edfc32014-09-25 11:46:46 -0700115 SetLengthToUsableSizeVisitor(int32_t min_length, size_t header_size,
116 size_t component_size_shift) :
117 minimum_length_(min_length), header_size_(header_size),
118 component_size_shift_(component_size_shift) {
Ian Rogers6fac4472014-02-25 17:01:10 -0800119 }
120
Mathieu Chartier9d156d52016-10-06 17:44:26 -0700121 void operator()(ObjPtr<Object> obj, size_t usable_size) const
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700122 REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogers6fac4472014-02-25 17:01:10 -0800123 // Avoid AsArray as object is not yet in live bitmap or allocation stack.
Mathieu Chartier9d156d52016-10-06 17:44:26 -0700124 ObjPtr<Array> array = ObjPtr<Array>::DownCast(obj);
Ian Rogers6fac4472014-02-25 17:01:10 -0800125 // DCHECK(array->IsArrayInstance());
Hiroshi Yamauchif0edfc32014-09-25 11:46:46 -0700126 int32_t length = (usable_size - header_size_) >> component_size_shift_;
Ian Rogersa55cf412014-02-27 00:31:26 -0800127 DCHECK_GE(length, minimum_length_);
Ian Rogers13735952014-10-08 12:43:28 -0700128 uint8_t* old_end = reinterpret_cast<uint8_t*>(array->GetRawData(1U << component_size_shift_,
129 minimum_length_));
130 uint8_t* new_end = reinterpret_cast<uint8_t*>(array->GetRawData(1U << component_size_shift_,
131 length));
Ian Rogersa55cf412014-02-27 00:31:26 -0800132 // Ensure space beyond original allocation is zeroed.
133 memset(old_end, 0, new_end - old_end);
Ian Rogers6fac4472014-02-25 17:01:10 -0800134 array->SetLength(length);
135 }
136
137 private:
Ian Rogersa55cf412014-02-27 00:31:26 -0800138 const int32_t minimum_length_;
Ian Rogers6fac4472014-02-25 17:01:10 -0800139 const size_t header_size_;
Hiroshi Yamauchif0edfc32014-09-25 11:46:46 -0700140 const size_t component_size_shift_;
Ian Rogers6fac4472014-02-25 17:01:10 -0800141
142 DISALLOW_COPY_AND_ASSIGN(SetLengthToUsableSizeVisitor);
Mathieu Chartier1febddf2013-11-20 12:33:14 -0800143};
Hiroshi Yamauchi967a0ad2013-09-10 16:24:21 -0700144
Hiroshi Yamauchif0edfc32014-09-25 11:46:46 -0700145template <bool kIsInstrumented, bool kFillUsable>
Vladimir Markobcf17522018-06-01 13:14:32 +0100146inline ObjPtr<Array> Array::Alloc(Thread* self,
147 ObjPtr<Class> array_class,
148 int32_t component_count,
149 size_t component_size_shift,
150 gc::AllocatorType allocator_type) {
Ian Rogers6fac4472014-02-25 17:01:10 -0800151 DCHECK(allocator_type != gc::kAllocatorTypeLOS);
Vladimir Marko20f85592015-03-19 10:07:02 +0000152 DCHECK(array_class != nullptr);
153 DCHECK(array_class->IsArrayClass());
Hiroshi Yamauchif0edfc32014-09-25 11:46:46 -0700154 DCHECK_EQ(array_class->GetComponentSizeShift(), component_size_shift);
155 DCHECK_EQ(array_class->GetComponentSize(), (1U << component_size_shift));
Vladimir Marko20f85592015-03-19 10:07:02 +0000156 size_t size = ComputeArraySize(component_count, component_size_shift);
Hiroshi Yamauchif0edfc32014-09-25 11:46:46 -0700157#ifdef __LP64__
158 // 64-bit. No size_t overflow.
159 DCHECK_NE(size, 0U);
160#else
161 // 32-bit.
Hiroshi Yamauchi3b4c1892013-09-12 21:33:12 -0700162 if (UNLIKELY(size == 0)) {
Andreas Gampe46ee31b2016-12-14 10:11:49 -0800163 self->ThrowOutOfMemoryError(android::base::StringPrintf("%s of length %d would overflow",
164 array_class->PrettyDescriptor().c_str(),
165 component_count).c_str());
Mathieu Chartiercbb2d202013-11-14 17:45:16 -0800166 return nullptr;
Hiroshi Yamauchi3b4c1892013-09-12 21:33:12 -0700167 }
Hiroshi Yamauchif0edfc32014-09-25 11:46:46 -0700168#endif
Hiroshi Yamauchi3b4c1892013-09-12 21:33:12 -0700169 gc::Heap* heap = Runtime::Current()->GetHeap();
Vladimir Markobcf17522018-06-01 13:14:32 +0100170 ObjPtr<Array> result;
Hiroshi Yamauchif0edfc32014-09-25 11:46:46 -0700171 if (!kFillUsable) {
Ian Rogers6fac4472014-02-25 17:01:10 -0800172 SetLengthVisitor visitor(component_count);
Vladimir Markobcf17522018-06-01 13:14:32 +0100173 result = ObjPtr<Array>::DownCast(MakeObjPtr(
Ian Rogers6fac4472014-02-25 17:01:10 -0800174 heap->AllocObjectWithAllocator<kIsInstrumented, true>(self, array_class, size,
Vladimir Markobcf17522018-06-01 13:14:32 +0100175 allocator_type, visitor)));
Ian Rogers6fac4472014-02-25 17:01:10 -0800176 } else {
Hiroshi Yamauchif0edfc32014-09-25 11:46:46 -0700177 SetLengthToUsableSizeVisitor visitor(component_count,
178 DataOffset(1U << component_size_shift).SizeValue(),
179 component_size_shift);
Vladimir Markobcf17522018-06-01 13:14:32 +0100180 result = ObjPtr<Array>::DownCast(MakeObjPtr(
Ian Rogers6fac4472014-02-25 17:01:10 -0800181 heap->AllocObjectWithAllocator<kIsInstrumented, true>(self, array_class, size,
Vladimir Markobcf17522018-06-01 13:14:32 +0100182 allocator_type, visitor)));
Ian Rogers6fac4472014-02-25 17:01:10 -0800183 }
184 if (kIsDebugBuild && result != nullptr && Runtime::Current()->IsStarted()) {
Mathieu Chartier85801542014-02-27 18:06:26 -0800185 array_class = result->GetClass(); // In case the array class moved.
Hiroshi Yamauchif0edfc32014-09-25 11:46:46 -0700186 CHECK_EQ(array_class->GetComponentSize(), 1U << component_size_shift);
187 if (!kFillUsable) {
Ian Rogers6fac4472014-02-25 17:01:10 -0800188 CHECK_EQ(result->SizeOf(), size);
189 } else {
190 CHECK_GE(result->SizeOf(), size);
191 }
192 }
193 return result;
Hiroshi Yamauchi967a0ad2013-09-10 16:24:21 -0700194}
195
Ian Rogers99cb4ea2014-03-26 22:53:56 -0700196template<typename T>
Vladimir Markobcf17522018-06-01 13:14:32 +0100197inline ObjPtr<PrimitiveArray<T>> PrimitiveArray<T>::AllocateAndFill(Thread* self,
198 const T* data,
199 size_t length) {
Alex Light440b5d92017-01-24 15:32:25 -0800200 StackHandleScope<1> hs(self);
201 Handle<PrimitiveArray<T>> arr(hs.NewHandle(PrimitiveArray<T>::Alloc(self, length)));
202 if (!arr.IsNull()) {
203 // Copy it in. Just skip if it's null
204 memcpy(arr->GetData(), data, sizeof(T) * length);
205 }
206 return arr.Get();
207}
208
209template<typename T>
Ian Rogersb0fa5dc2014-04-28 16:47:08 -0700210inline T PrimitiveArray<T>::Get(int32_t i) {
211 if (!CheckIsValidIndex(i)) {
212 DCHECK(Thread::Current()->IsExceptionPending());
213 return T(0);
214 }
215 return GetWithoutChecks(i);
216}
217
218template<typename T>
219inline void PrimitiveArray<T>::Set(int32_t i, T value) {
220 if (Runtime::Current()->IsActiveTransaction()) {
221 Set<true>(i, value);
222 } else {
223 Set<false>(i, value);
224 }
225}
226
227template<typename T>
228template<bool kTransactionActive, bool kCheckTransaction>
229inline void PrimitiveArray<T>::Set(int32_t i, T value) {
230 if (CheckIsValidIndex(i)) {
231 SetWithoutChecks<kTransactionActive, kCheckTransaction>(i, value);
232 } else {
233 DCHECK(Thread::Current()->IsExceptionPending());
234 }
235}
236
237template<typename T>
Andreas Gampe3b45ef22015-05-26 21:34:09 -0700238template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
Ian Rogersb0fa5dc2014-04-28 16:47:08 -0700239inline void PrimitiveArray<T>::SetWithoutChecks(int32_t i, T value) {
240 if (kCheckTransaction) {
241 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
242 }
243 if (kTransactionActive) {
244 Runtime::Current()->RecordWriteArray(this, i, GetWithoutChecks(i));
245 }
Andreas Gampe3b45ef22015-05-26 21:34:09 -0700246 DCHECK(CheckIsValidIndex<kVerifyFlags>(i));
Ian Rogersb0fa5dc2014-04-28 16:47:08 -0700247 GetData()[i] = value;
248}
Ian Rogers99cb4ea2014-03-26 22:53:56 -0700249// Backward copy where elements are of aligned appropriately for T. Count is in T sized units.
250// Copies are guaranteed not to tear when the sizeof T is less-than 64bit.
Ian Rogersef7d42f2014-01-06 12:55:46 -0800251template<typename T>
252static inline void ArrayBackwardCopy(T* d, const T* s, int32_t count) {
253 d += count;
254 s += count;
255 for (int32_t i = 0; i < count; ++i) {
256 d--;
257 s--;
258 *d = *s;
259 }
260}
261
Ian Rogers99cb4ea2014-03-26 22:53:56 -0700262// Forward copy where elements are of aligned appropriately for T. Count is in T sized units.
263// Copies are guaranteed not to tear when the sizeof T is less-than 64bit.
Ian Rogers6fac4472014-02-25 17:01:10 -0800264template<typename T>
Ian Rogers99cb4ea2014-03-26 22:53:56 -0700265static inline void ArrayForwardCopy(T* d, const T* s, int32_t count) {
266 for (int32_t i = 0; i < count; ++i) {
267 *d = *s;
268 d++;
269 s++;
270 }
Ian Rogers6fac4472014-02-25 17:01:10 -0800271}
272
Ian Rogersef7d42f2014-01-06 12:55:46 -0800273template<class T>
Mathieu Chartier31e88222016-10-14 18:43:19 -0700274inline void PrimitiveArray<T>::Memmove(int32_t dst_pos,
275 ObjPtr<PrimitiveArray<T>> src,
276 int32_t src_pos,
Ian Rogers6fac4472014-02-25 17:01:10 -0800277 int32_t count) {
Ian Rogersef7d42f2014-01-06 12:55:46 -0800278 if (UNLIKELY(count == 0)) {
279 return;
280 }
281 DCHECK_GE(dst_pos, 0);
282 DCHECK_GE(src_pos, 0);
283 DCHECK_GT(count, 0);
284 DCHECK(src != nullptr);
285 DCHECK_LT(dst_pos, GetLength());
286 DCHECK_LE(dst_pos, GetLength() - count);
287 DCHECK_LT(src_pos, src->GetLength());
288 DCHECK_LE(src_pos, src->GetLength() - count);
289
290 // Note for non-byte copies we can't rely on standard libc functions like memcpy(3) and memmove(3)
291 // in our implementation, because they may copy byte-by-byte.
Ian Rogers99cb4ea2014-03-26 22:53:56 -0700292 if (LIKELY(src != this)) {
293 // Memcpy ok for guaranteed non-overlapping distinct arrays.
Ian Rogersef7d42f2014-01-06 12:55:46 -0800294 Memcpy(dst_pos, src, src_pos, count);
295 } else {
Ian Rogers99cb4ea2014-03-26 22:53:56 -0700296 // Handle copies within the same array using the appropriate direction copy.
Ian Rogersef7d42f2014-01-06 12:55:46 -0800297 void* dst_raw = GetRawData(sizeof(T), dst_pos);
298 const void* src_raw = src->GetRawData(sizeof(T), src_pos);
299 if (sizeof(T) == sizeof(uint8_t)) {
Ian Rogersef7d42f2014-01-06 12:55:46 -0800300 uint8_t* d = reinterpret_cast<uint8_t*>(dst_raw);
301 const uint8_t* s = reinterpret_cast<const uint8_t*>(src_raw);
Ian Rogers99cb4ea2014-03-26 22:53:56 -0700302 memmove(d, s, count);
Ian Rogersef7d42f2014-01-06 12:55:46 -0800303 } else {
Ian Rogers99cb4ea2014-03-26 22:53:56 -0700304 const bool copy_forward = (dst_pos < src_pos) || (dst_pos - src_pos >= count);
305 if (sizeof(T) == sizeof(uint16_t)) {
306 uint16_t* d = reinterpret_cast<uint16_t*>(dst_raw);
307 const uint16_t* s = reinterpret_cast<const uint16_t*>(src_raw);
308 if (copy_forward) {
309 ArrayForwardCopy<uint16_t>(d, s, count);
310 } else {
311 ArrayBackwardCopy<uint16_t>(d, s, count);
312 }
313 } else if (sizeof(T) == sizeof(uint32_t)) {
314 uint32_t* d = reinterpret_cast<uint32_t*>(dst_raw);
315 const uint32_t* s = reinterpret_cast<const uint32_t*>(src_raw);
316 if (copy_forward) {
317 ArrayForwardCopy<uint32_t>(d, s, count);
318 } else {
319 ArrayBackwardCopy<uint32_t>(d, s, count);
320 }
321 } else {
322 DCHECK_EQ(sizeof(T), sizeof(uint64_t));
323 uint64_t* d = reinterpret_cast<uint64_t*>(dst_raw);
324 const uint64_t* s = reinterpret_cast<const uint64_t*>(src_raw);
325 if (copy_forward) {
326 ArrayForwardCopy<uint64_t>(d, s, count);
327 } else {
328 ArrayBackwardCopy<uint64_t>(d, s, count);
329 }
330 }
Ian Rogersef7d42f2014-01-06 12:55:46 -0800331 }
332 }
333}
334
Ian Rogersef7d42f2014-01-06 12:55:46 -0800335template<class T>
Mathieu Chartier31e88222016-10-14 18:43:19 -0700336inline void PrimitiveArray<T>::Memcpy(int32_t dst_pos,
337 ObjPtr<PrimitiveArray<T>> src,
338 int32_t src_pos,
Ian Rogers6fac4472014-02-25 17:01:10 -0800339 int32_t count) {
Ian Rogersef7d42f2014-01-06 12:55:46 -0800340 if (UNLIKELY(count == 0)) {
341 return;
342 }
343 DCHECK_GE(dst_pos, 0);
344 DCHECK_GE(src_pos, 0);
345 DCHECK_GT(count, 0);
346 DCHECK(src != nullptr);
347 DCHECK_LT(dst_pos, GetLength());
348 DCHECK_LE(dst_pos, GetLength() - count);
349 DCHECK_LT(src_pos, src->GetLength());
350 DCHECK_LE(src_pos, src->GetLength() - count);
351
352 // Note for non-byte copies we can't rely on standard libc functions like memcpy(3) and memmove(3)
353 // in our implementation, because they may copy byte-by-byte.
354 void* dst_raw = GetRawData(sizeof(T), dst_pos);
355 const void* src_raw = src->GetRawData(sizeof(T), src_pos);
356 if (sizeof(T) == sizeof(uint8_t)) {
357 memcpy(dst_raw, src_raw, count);
358 } else if (sizeof(T) == sizeof(uint16_t)) {
359 uint16_t* d = reinterpret_cast<uint16_t*>(dst_raw);
360 const uint16_t* s = reinterpret_cast<const uint16_t*>(src_raw);
361 ArrayForwardCopy<uint16_t>(d, s, count);
362 } else if (sizeof(T) == sizeof(uint32_t)) {
363 uint32_t* d = reinterpret_cast<uint32_t*>(dst_raw);
364 const uint32_t* s = reinterpret_cast<const uint32_t*>(src_raw);
365 ArrayForwardCopy<uint32_t>(d, s, count);
366 } else {
367 DCHECK_EQ(sizeof(T), sizeof(uint64_t));
368 uint64_t* d = reinterpret_cast<uint64_t*>(dst_raw);
369 const uint64_t* s = reinterpret_cast<const uint64_t*>(src_raw);
370 ArrayForwardCopy<uint64_t>(d, s, count);
371 }
372}
373
Mathieu Chartierdfe02f62016-02-01 20:15:11 -0800374template<typename T, VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
Andreas Gampe542451c2016-07-26 09:02:02 -0700375inline T PointerArray::GetElementPtrSize(uint32_t idx, PointerSize ptr_size) {
Mathieu Chartiere401d142015-04-22 13:56:20 -0700376 // C style casts here since we sometimes have T be a pointer, or sometimes an integer
377 // (for stack traces).
Andreas Gampe542451c2016-07-26 09:02:02 -0700378 if (ptr_size == PointerSize::k64) {
Mathieu Chartierdfe02f62016-02-01 20:15:11 -0800379 return (T)static_cast<uintptr_t>(
380 AsLongArray<kVerifyFlags, kReadBarrierOption>()->GetWithoutChecks(idx));
Mathieu Chartiere401d142015-04-22 13:56:20 -0700381 }
Colin Cross32f53882017-03-15 15:25:24 -0700382 return (T)static_cast<uintptr_t>(static_cast<uint32_t>(
383 AsIntArray<kVerifyFlags, kReadBarrierOption>()->GetWithoutChecks(idx)));
Mathieu Chartiere401d142015-04-22 13:56:20 -0700384}
385
Mathieu Chartierd329a3b2016-01-27 15:30:10 -0800386template<bool kTransactionActive, bool kUnchecked>
Andreas Gampe542451c2016-07-26 09:02:02 -0700387inline void PointerArray::SetElementPtrSize(uint32_t idx, uint64_t element, PointerSize ptr_size) {
388 if (ptr_size == PointerSize::k64) {
Mathieu Chartiere401d142015-04-22 13:56:20 -0700389 (kUnchecked ? down_cast<LongArray*>(static_cast<Object*>(this)) : AsLongArray())->
Mathieu Chartierd329a3b2016-01-27 15:30:10 -0800390 SetWithoutChecks<kTransactionActive>(idx, element);
Mathieu Chartiere401d142015-04-22 13:56:20 -0700391 } else {
Mathieu Chartierd329a3b2016-01-27 15:30:10 -0800392 DCHECK_LE(element, static_cast<uint64_t>(0xFFFFFFFFu));
Mathieu Chartiere401d142015-04-22 13:56:20 -0700393 (kUnchecked ? down_cast<IntArray*>(static_cast<Object*>(this)) : AsIntArray())
Mathieu Chartierd329a3b2016-01-27 15:30:10 -0800394 ->SetWithoutChecks<kTransactionActive>(idx, static_cast<uint32_t>(element));
Mathieu Chartiere401d142015-04-22 13:56:20 -0700395 }
396}
397
Mathieu Chartierd329a3b2016-01-27 15:30:10 -0800398template<bool kTransactionActive, bool kUnchecked, typename T>
Andreas Gampe542451c2016-07-26 09:02:02 -0700399inline void PointerArray::SetElementPtrSize(uint32_t idx, T* element, PointerSize ptr_size) {
Mathieu Chartier1bbfab62016-01-27 16:37:19 -0800400 SetElementPtrSize<kTransactionActive, kUnchecked>(idx,
401 reinterpret_cast<uintptr_t>(element),
402 ptr_size);
Mathieu Chartierd329a3b2016-01-27 15:30:10 -0800403}
404
Mathieu Chartierdfe02f62016-02-01 20:15:11 -0800405template <VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption, typename Visitor>
Mathieu Chartier4b00d342015-11-13 10:42:08 -0800406inline void PointerArray::Fixup(mirror::PointerArray* dest,
Andreas Gampe542451c2016-07-26 09:02:02 -0700407 PointerSize pointer_size,
Mathieu Chartier4b00d342015-11-13 10:42:08 -0800408 const Visitor& visitor) {
409 for (size_t i = 0, count = GetLength(); i < count; ++i) {
Mathieu Chartierdfe02f62016-02-01 20:15:11 -0800410 void* ptr = GetElementPtrSize<void*, kVerifyFlags, kReadBarrierOption>(i, pointer_size);
Mathieu Chartier4b00d342015-11-13 10:42:08 -0800411 void* new_ptr = visitor(ptr);
412 if (ptr != new_ptr) {
413 dest->SetElementPtrSize<false, true>(i, new_ptr, pointer_size);
414 }
415 }
416}
417
Alex Lighta01de592016-11-15 10:43:06 -0800418template<bool kUnchecked>
419void PointerArray::Memcpy(int32_t dst_pos,
420 ObjPtr<PointerArray> src,
421 int32_t src_pos,
422 int32_t count,
423 PointerSize ptr_size) {
424 DCHECK(!Runtime::Current()->IsActiveTransaction());
425 DCHECK(!src.IsNull());
426 if (ptr_size == PointerSize::k64) {
427 LongArray* l_this = (kUnchecked ? down_cast<LongArray*>(static_cast<Object*>(this))
428 : AsLongArray());
429 LongArray* l_src = (kUnchecked ? down_cast<LongArray*>(static_cast<Object*>(src.Ptr()))
430 : src->AsLongArray());
431 l_this->Memcpy(dst_pos, l_src, src_pos, count);
432 } else {
433 IntArray* i_this = (kUnchecked ? down_cast<IntArray*>(static_cast<Object*>(this))
434 : AsIntArray());
435 IntArray* i_src = (kUnchecked ? down_cast<IntArray*>(static_cast<Object*>(src.Ptr()))
436 : src->AsIntArray());
437 i_this->Memcpy(dst_pos, i_src, src_pos, count);
438 }
439}
440
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800441} // namespace mirror
442} // namespace art
443
Brian Carlstromfc0e3212013-07-17 14:40:12 -0700444#endif // ART_RUNTIME_MIRROR_ARRAY_INL_H_