blob: 34925f52e2623718e5e8e2b146e77baebbd52974 [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>
Andreas Gampe46ee31b2016-12-14 10:11:49 -080023
Vladimir Marko80afd022015-05-19 18:08:00 +010024#include "base/bit_utils.h"
Andreas Gampec6ea7d02017-02-01 16:46:28 -080025#include "class.h"
Mathieu Chartier1a5337f2016-10-13 13:48:23 -070026#include "obj_ptr-inl.h"
Andreas Gampe88dbad32018-06-26 19:54:12 -070027#include "runtime.h"
Andreas Gampe895f9222017-07-05 09:53:32 -070028#include "thread-current-inl.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080029
30namespace art {
31namespace mirror {
32
Andreas Gampe542451c2016-07-26 09:02:02 -070033inline uint32_t Array::ClassSize(PointerSize pointer_size) {
Mingyao Yang98d1cc82014-05-15 17:02:16 -070034 uint32_t vtable_entries = Object::kVTableLength;
Mathieu Chartiere401d142015-04-22 13:56:20 -070035 return Class::ComputeClassSize(true, vtable_entries, 0, 0, 0, 0, 0, pointer_size);
Mingyao Yang98d1cc82014-05-15 17:02:16 -070036}
37
Vladimir Markod355acf2019-03-21 17:09:40 +000038template<VerifyObjectFlags kVerifyFlags>
Ian Rogersef7d42f2014-01-06 12:55:46 -080039inline size_t Array::SizeOf() {
Vladimir Markod355acf2019-03-21 17:09:40 +000040 // No read barrier is needed for reading a constant primitive field through
41 // constant reference field chain. See ReadBarrierOption.
42 size_t component_size_shift =
43 GetClass<kVerifyFlags, kWithoutReadBarrier>()->GetComponentSizeShift();
Mathieu Chartier4e305412014-02-19 10:54:44 -080044 // Don't need to check this since we already check this in GetClass.
45 int32_t component_count =
46 GetLength<static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis)>();
Vladimir Markod355acf2019-03-21 17:09:40 +000047 // This is safe from overflow because the array was already allocated, so we know it's sane.
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
Alex Light440b5d92017-01-24 15:32:25 -080063template<typename T>
Ian Rogersb0fa5dc2014-04-28 16:47:08 -070064inline T PrimitiveArray<T>::Get(int32_t i) {
65 if (!CheckIsValidIndex(i)) {
66 DCHECK(Thread::Current()->IsExceptionPending());
67 return T(0);
68 }
69 return GetWithoutChecks(i);
70}
71
72template<typename T>
73inline void PrimitiveArray<T>::Set(int32_t i, T value) {
74 if (Runtime::Current()->IsActiveTransaction()) {
75 Set<true>(i, value);
76 } else {
77 Set<false>(i, value);
78 }
79}
80
81template<typename T>
82template<bool kTransactionActive, bool kCheckTransaction>
83inline void PrimitiveArray<T>::Set(int32_t i, T value) {
84 if (CheckIsValidIndex(i)) {
85 SetWithoutChecks<kTransactionActive, kCheckTransaction>(i, value);
86 } else {
87 DCHECK(Thread::Current()->IsExceptionPending());
88 }
89}
90
91template<typename T>
Andreas Gampe3b45ef22015-05-26 21:34:09 -070092template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
Ian Rogersb0fa5dc2014-04-28 16:47:08 -070093inline void PrimitiveArray<T>::SetWithoutChecks(int32_t i, T value) {
94 if (kCheckTransaction) {
95 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
96 }
97 if (kTransactionActive) {
98 Runtime::Current()->RecordWriteArray(this, i, GetWithoutChecks(i));
99 }
Andreas Gampe3b45ef22015-05-26 21:34:09 -0700100 DCHECK(CheckIsValidIndex<kVerifyFlags>(i));
Ian Rogersb0fa5dc2014-04-28 16:47:08 -0700101 GetData()[i] = value;
102}
Ian Rogers99cb4ea2014-03-26 22:53:56 -0700103// Backward copy where elements are of aligned appropriately for T. Count is in T sized units.
104// Copies are guaranteed not to tear when the sizeof T is less-than 64bit.
Ian Rogersef7d42f2014-01-06 12:55:46 -0800105template<typename T>
106static inline void ArrayBackwardCopy(T* d, const T* s, int32_t count) {
107 d += count;
108 s += count;
109 for (int32_t i = 0; i < count; ++i) {
110 d--;
111 s--;
112 *d = *s;
113 }
114}
115
Ian Rogers99cb4ea2014-03-26 22:53:56 -0700116// Forward copy where elements are of aligned appropriately for T. Count is in T sized units.
117// Copies are guaranteed not to tear when the sizeof T is less-than 64bit.
Ian Rogers6fac4472014-02-25 17:01:10 -0800118template<typename T>
Ian Rogers99cb4ea2014-03-26 22:53:56 -0700119static inline void ArrayForwardCopy(T* d, const T* s, int32_t count) {
120 for (int32_t i = 0; i < count; ++i) {
121 *d = *s;
122 d++;
123 s++;
124 }
Ian Rogers6fac4472014-02-25 17:01:10 -0800125}
126
Ian Rogersef7d42f2014-01-06 12:55:46 -0800127template<class T>
Mathieu Chartier31e88222016-10-14 18:43:19 -0700128inline void PrimitiveArray<T>::Memmove(int32_t dst_pos,
129 ObjPtr<PrimitiveArray<T>> src,
130 int32_t src_pos,
Ian Rogers6fac4472014-02-25 17:01:10 -0800131 int32_t count) {
Ian Rogersef7d42f2014-01-06 12:55:46 -0800132 if (UNLIKELY(count == 0)) {
133 return;
134 }
135 DCHECK_GE(dst_pos, 0);
136 DCHECK_GE(src_pos, 0);
137 DCHECK_GT(count, 0);
138 DCHECK(src != nullptr);
139 DCHECK_LT(dst_pos, GetLength());
140 DCHECK_LE(dst_pos, GetLength() - count);
141 DCHECK_LT(src_pos, src->GetLength());
142 DCHECK_LE(src_pos, src->GetLength() - count);
143
144 // Note for non-byte copies we can't rely on standard libc functions like memcpy(3) and memmove(3)
145 // in our implementation, because they may copy byte-by-byte.
Ian Rogers99cb4ea2014-03-26 22:53:56 -0700146 if (LIKELY(src != this)) {
147 // Memcpy ok for guaranteed non-overlapping distinct arrays.
Ian Rogersef7d42f2014-01-06 12:55:46 -0800148 Memcpy(dst_pos, src, src_pos, count);
149 } else {
Ian Rogers99cb4ea2014-03-26 22:53:56 -0700150 // Handle copies within the same array using the appropriate direction copy.
Ian Rogersef7d42f2014-01-06 12:55:46 -0800151 void* dst_raw = GetRawData(sizeof(T), dst_pos);
152 const void* src_raw = src->GetRawData(sizeof(T), src_pos);
153 if (sizeof(T) == sizeof(uint8_t)) {
Ian Rogersef7d42f2014-01-06 12:55:46 -0800154 uint8_t* d = reinterpret_cast<uint8_t*>(dst_raw);
155 const uint8_t* s = reinterpret_cast<const uint8_t*>(src_raw);
Ian Rogers99cb4ea2014-03-26 22:53:56 -0700156 memmove(d, s, count);
Ian Rogersef7d42f2014-01-06 12:55:46 -0800157 } else {
Ian Rogers99cb4ea2014-03-26 22:53:56 -0700158 const bool copy_forward = (dst_pos < src_pos) || (dst_pos - src_pos >= count);
159 if (sizeof(T) == sizeof(uint16_t)) {
160 uint16_t* d = reinterpret_cast<uint16_t*>(dst_raw);
161 const uint16_t* s = reinterpret_cast<const uint16_t*>(src_raw);
162 if (copy_forward) {
163 ArrayForwardCopy<uint16_t>(d, s, count);
164 } else {
165 ArrayBackwardCopy<uint16_t>(d, s, count);
166 }
167 } else if (sizeof(T) == sizeof(uint32_t)) {
168 uint32_t* d = reinterpret_cast<uint32_t*>(dst_raw);
169 const uint32_t* s = reinterpret_cast<const uint32_t*>(src_raw);
170 if (copy_forward) {
171 ArrayForwardCopy<uint32_t>(d, s, count);
172 } else {
173 ArrayBackwardCopy<uint32_t>(d, s, count);
174 }
175 } else {
176 DCHECK_EQ(sizeof(T), sizeof(uint64_t));
177 uint64_t* d = reinterpret_cast<uint64_t*>(dst_raw);
178 const uint64_t* s = reinterpret_cast<const uint64_t*>(src_raw);
179 if (copy_forward) {
180 ArrayForwardCopy<uint64_t>(d, s, count);
181 } else {
182 ArrayBackwardCopy<uint64_t>(d, s, count);
183 }
184 }
Ian Rogersef7d42f2014-01-06 12:55:46 -0800185 }
186 }
187}
188
Ian Rogersef7d42f2014-01-06 12:55:46 -0800189template<class T>
Mathieu Chartier31e88222016-10-14 18:43:19 -0700190inline void PrimitiveArray<T>::Memcpy(int32_t dst_pos,
191 ObjPtr<PrimitiveArray<T>> src,
192 int32_t src_pos,
Ian Rogers6fac4472014-02-25 17:01:10 -0800193 int32_t count) {
Ian Rogersef7d42f2014-01-06 12:55:46 -0800194 if (UNLIKELY(count == 0)) {
195 return;
196 }
197 DCHECK_GE(dst_pos, 0);
198 DCHECK_GE(src_pos, 0);
199 DCHECK_GT(count, 0);
200 DCHECK(src != nullptr);
201 DCHECK_LT(dst_pos, GetLength());
202 DCHECK_LE(dst_pos, GetLength() - count);
203 DCHECK_LT(src_pos, src->GetLength());
204 DCHECK_LE(src_pos, src->GetLength() - count);
205
206 // Note for non-byte copies we can't rely on standard libc functions like memcpy(3) and memmove(3)
207 // in our implementation, because they may copy byte-by-byte.
208 void* dst_raw = GetRawData(sizeof(T), dst_pos);
209 const void* src_raw = src->GetRawData(sizeof(T), src_pos);
210 if (sizeof(T) == sizeof(uint8_t)) {
211 memcpy(dst_raw, src_raw, count);
212 } else if (sizeof(T) == sizeof(uint16_t)) {
213 uint16_t* d = reinterpret_cast<uint16_t*>(dst_raw);
214 const uint16_t* s = reinterpret_cast<const uint16_t*>(src_raw);
215 ArrayForwardCopy<uint16_t>(d, s, count);
216 } else if (sizeof(T) == sizeof(uint32_t)) {
217 uint32_t* d = reinterpret_cast<uint32_t*>(dst_raw);
218 const uint32_t* s = reinterpret_cast<const uint32_t*>(src_raw);
219 ArrayForwardCopy<uint32_t>(d, s, count);
220 } else {
221 DCHECK_EQ(sizeof(T), sizeof(uint64_t));
222 uint64_t* d = reinterpret_cast<uint64_t*>(dst_raw);
223 const uint64_t* s = reinterpret_cast<const uint64_t*>(src_raw);
224 ArrayForwardCopy<uint64_t>(d, s, count);
225 }
226}
227
Andreas Gampea2fed082019-02-01 09:34:43 -0800228template<typename T, PointerSize kPointerSize, VerifyObjectFlags kVerifyFlags>
229inline T PointerArray::GetElementPtrSize(uint32_t idx) {
230 // C style casts here since we sometimes have T be a pointer, or sometimes an integer
231 // (for stack traces).
232 if (kPointerSize == PointerSize::k64) {
233 return (T)static_cast<uintptr_t>(AsLongArray<kVerifyFlags>()->GetWithoutChecks(idx));
234 }
235 return (T)static_cast<uintptr_t>(AsIntArray<kVerifyFlags>()->GetWithoutChecks(idx));
236}
Andreas Gampe3aa868a2019-02-04 11:18:43 -0800237template<typename T, PointerSize kPointerSize, VerifyObjectFlags kVerifyFlags>
238inline T PointerArray::GetElementPtrSizeUnchecked(uint32_t idx) {
239 // C style casts here since we sometimes have T be a pointer, or sometimes an integer
240 // (for stack traces).
241 if (kPointerSize == PointerSize::k64) {
242 return (T)static_cast<uintptr_t>(AsLongArrayUnchecked<kVerifyFlags>()->GetWithoutChecks(idx));
243 }
244 return (T)static_cast<uintptr_t>(AsIntArrayUnchecked<kVerifyFlags>()->GetWithoutChecks(idx));
245}
Vladimir Marko104883b2018-11-09 17:12:23 +0000246template<typename T, VerifyObjectFlags kVerifyFlags>
Andreas Gampe542451c2016-07-26 09:02:02 -0700247inline T PointerArray::GetElementPtrSize(uint32_t idx, PointerSize ptr_size) {
Andreas Gampe542451c2016-07-26 09:02:02 -0700248 if (ptr_size == PointerSize::k64) {
Andreas Gampea2fed082019-02-01 09:34:43 -0800249 return GetElementPtrSize<T, PointerSize::k64, kVerifyFlags>(idx);
Mathieu Chartiere401d142015-04-22 13:56:20 -0700250 }
Andreas Gampea2fed082019-02-01 09:34:43 -0800251 return GetElementPtrSize<T, PointerSize::k32, kVerifyFlags>(idx);
Mathieu Chartiere401d142015-04-22 13:56:20 -0700252}
253
Mathieu Chartierd329a3b2016-01-27 15:30:10 -0800254template<bool kTransactionActive, bool kUnchecked>
Andreas Gampe542451c2016-07-26 09:02:02 -0700255inline void PointerArray::SetElementPtrSize(uint32_t idx, uint64_t element, PointerSize ptr_size) {
256 if (ptr_size == PointerSize::k64) {
Vladimir Marko4617d582019-03-28 13:48:31 +0000257 (kUnchecked ? ObjPtr<LongArray>::DownCast(ObjPtr<Object>(this)) : AsLongArray())->
Mathieu Chartierd329a3b2016-01-27 15:30:10 -0800258 SetWithoutChecks<kTransactionActive>(idx, element);
Mathieu Chartiere401d142015-04-22 13:56:20 -0700259 } else {
Mathieu Chartierd329a3b2016-01-27 15:30:10 -0800260 DCHECK_LE(element, static_cast<uint64_t>(0xFFFFFFFFu));
Vladimir Marko4617d582019-03-28 13:48:31 +0000261 (kUnchecked ? ObjPtr<IntArray>::DownCast(ObjPtr<Object>(this)) : AsIntArray())
Mathieu Chartierd329a3b2016-01-27 15:30:10 -0800262 ->SetWithoutChecks<kTransactionActive>(idx, static_cast<uint32_t>(element));
Mathieu Chartiere401d142015-04-22 13:56:20 -0700263 }
264}
265
Mathieu Chartierd329a3b2016-01-27 15:30:10 -0800266template<bool kTransactionActive, bool kUnchecked, typename T>
Andreas Gampe542451c2016-07-26 09:02:02 -0700267inline void PointerArray::SetElementPtrSize(uint32_t idx, T* element, PointerSize ptr_size) {
Mathieu Chartier1bbfab62016-01-27 16:37:19 -0800268 SetElementPtrSize<kTransactionActive, kUnchecked>(idx,
269 reinterpret_cast<uintptr_t>(element),
270 ptr_size);
Mathieu Chartierd329a3b2016-01-27 15:30:10 -0800271}
272
Vladimir Marko104883b2018-11-09 17:12:23 +0000273template <VerifyObjectFlags kVerifyFlags, typename Visitor>
Vladimir Markoc524e9e2019-03-26 10:54:50 +0000274inline void PointerArray::Fixup(ObjPtr<mirror::PointerArray> dest,
Andreas Gampe542451c2016-07-26 09:02:02 -0700275 PointerSize pointer_size,
Mathieu Chartier4b00d342015-11-13 10:42:08 -0800276 const Visitor& visitor) {
277 for (size_t i = 0, count = GetLength(); i < count; ++i) {
Vladimir Marko104883b2018-11-09 17:12:23 +0000278 void* ptr = GetElementPtrSize<void*, kVerifyFlags>(i, pointer_size);
Mathieu Chartier4b00d342015-11-13 10:42:08 -0800279 void* new_ptr = visitor(ptr);
280 if (ptr != new_ptr) {
281 dest->SetElementPtrSize<false, true>(i, new_ptr, pointer_size);
282 }
283 }
284}
285
Alex Lighta01de592016-11-15 10:43:06 -0800286template<bool kUnchecked>
287void PointerArray::Memcpy(int32_t dst_pos,
288 ObjPtr<PointerArray> src,
289 int32_t src_pos,
290 int32_t count,
291 PointerSize ptr_size) {
292 DCHECK(!Runtime::Current()->IsActiveTransaction());
293 DCHECK(!src.IsNull());
294 if (ptr_size == PointerSize::k64) {
Vladimir Marko4617d582019-03-28 13:48:31 +0000295 ObjPtr<LongArray> l_this = (kUnchecked ? ObjPtr<LongArray>::DownCast(ObjPtr<Object>(this))
296 : AsLongArray());
297 ObjPtr<LongArray> l_src = (kUnchecked ? ObjPtr<LongArray>::DownCast(ObjPtr<Object>(src))
298 : src->AsLongArray());
Alex Lighta01de592016-11-15 10:43:06 -0800299 l_this->Memcpy(dst_pos, l_src, src_pos, count);
300 } else {
Vladimir Marko4617d582019-03-28 13:48:31 +0000301 ObjPtr<IntArray> i_this = (kUnchecked ? ObjPtr<IntArray>::DownCast(ObjPtr<Object>(this))
302 : AsIntArray());
303 ObjPtr<IntArray> i_src = (kUnchecked ? ObjPtr<IntArray>::DownCast(ObjPtr<Object>(src.Ptr()))
304 : src->AsIntArray());
Alex Lighta01de592016-11-15 10:43:06 -0800305 i_this->Memcpy(dst_pos, i_src, src_pos, count);
306 }
307}
308
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800309} // namespace mirror
310} // namespace art
311
Brian Carlstromfc0e3212013-07-17 14:40:12 -0700312#endif // ART_RUNTIME_MIRROR_ARRAY_INL_H_