blob: 3a0cbe2a597363e22498e6e2acac9cc689c051a7 [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"
Mathieu Chartiere401d142015-04-22 13:56:20 -070025#include "base/casts.h"
Andreas Gampec6ea7d02017-02-01 16:46:28 -080026#include "class.h"
Mathieu Chartier1a5337f2016-10-13 13:48:23 -070027#include "obj_ptr-inl.h"
Andreas Gampe88dbad32018-06-26 19:54:12 -070028#include "runtime.h"
Andreas Gampe895f9222017-07-05 09:53:32 -070029#include "thread-current-inl.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080030
31namespace art {
32namespace mirror {
33
Andreas Gampe542451c2016-07-26 09:02:02 -070034inline uint32_t Array::ClassSize(PointerSize pointer_size) {
Mingyao Yang98d1cc82014-05-15 17:02:16 -070035 uint32_t vtable_entries = Object::kVTableLength;
Mathieu Chartiere401d142015-04-22 13:56:20 -070036 return Class::ComputeClassSize(true, vtable_entries, 0, 0, 0, 0, 0, pointer_size);
Mingyao Yang98d1cc82014-05-15 17:02:16 -070037}
38
Hiroshi Yamauchi6e83c172014-05-01 21:25:41 -070039template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
Ian Rogersef7d42f2014-01-06 12:55:46 -080040inline size_t Array::SizeOf() {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080041 // This is safe from overflow because the array was already allocated, so we know it's sane.
Hiroshi Yamauchif0edfc32014-09-25 11:46:46 -070042 size_t component_size_shift = GetClass<kVerifyFlags, kReadBarrierOption>()->
43 template GetComponentSizeShift<kReadBarrierOption>();
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)>();
Hiroshi Yamauchif0edfc32014-09-25 11:46:46 -070047 size_t header_size = DataOffset(1U << component_size_shift).SizeValue();
48 size_t data_size = component_count << component_size_shift;
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080049 return header_size + data_size;
50}
51
Ian Rogersb0fa5dc2014-04-28 16:47:08 -070052template<VerifyObjectFlags kVerifyFlags>
53inline bool Array::CheckIsValidIndex(int32_t index) {
54 if (UNLIKELY(static_cast<uint32_t>(index) >=
55 static_cast<uint32_t>(GetLength<kVerifyFlags>()))) {
56 ThrowArrayIndexOutOfBoundsException(index);
57 return false;
58 }
59 return true;
60}
61
Alex Light440b5d92017-01-24 15:32:25 -080062template<typename T>
Ian Rogersb0fa5dc2014-04-28 16:47:08 -070063inline T PrimitiveArray<T>::Get(int32_t i) {
64 if (!CheckIsValidIndex(i)) {
65 DCHECK(Thread::Current()->IsExceptionPending());
66 return T(0);
67 }
68 return GetWithoutChecks(i);
69}
70
71template<typename T>
72inline void PrimitiveArray<T>::Set(int32_t i, T value) {
73 if (Runtime::Current()->IsActiveTransaction()) {
74 Set<true>(i, value);
75 } else {
76 Set<false>(i, value);
77 }
78}
79
80template<typename T>
81template<bool kTransactionActive, bool kCheckTransaction>
82inline void PrimitiveArray<T>::Set(int32_t i, T value) {
83 if (CheckIsValidIndex(i)) {
84 SetWithoutChecks<kTransactionActive, kCheckTransaction>(i, value);
85 } else {
86 DCHECK(Thread::Current()->IsExceptionPending());
87 }
88}
89
90template<typename T>
Andreas Gampe3b45ef22015-05-26 21:34:09 -070091template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
Ian Rogersb0fa5dc2014-04-28 16:47:08 -070092inline void PrimitiveArray<T>::SetWithoutChecks(int32_t i, T value) {
93 if (kCheckTransaction) {
94 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
95 }
96 if (kTransactionActive) {
97 Runtime::Current()->RecordWriteArray(this, i, GetWithoutChecks(i));
98 }
Andreas Gampe3b45ef22015-05-26 21:34:09 -070099 DCHECK(CheckIsValidIndex<kVerifyFlags>(i));
Ian Rogersb0fa5dc2014-04-28 16:47:08 -0700100 GetData()[i] = value;
101}
Ian Rogers99cb4ea2014-03-26 22:53:56 -0700102// Backward copy where elements are of aligned appropriately for T. Count is in T sized units.
103// Copies are guaranteed not to tear when the sizeof T is less-than 64bit.
Ian Rogersef7d42f2014-01-06 12:55:46 -0800104template<typename T>
105static inline void ArrayBackwardCopy(T* d, const T* s, int32_t count) {
106 d += count;
107 s += count;
108 for (int32_t i = 0; i < count; ++i) {
109 d--;
110 s--;
111 *d = *s;
112 }
113}
114
Ian Rogers99cb4ea2014-03-26 22:53:56 -0700115// Forward copy where elements are of aligned appropriately for T. Count is in T sized units.
116// Copies are guaranteed not to tear when the sizeof T is less-than 64bit.
Ian Rogers6fac4472014-02-25 17:01:10 -0800117template<typename T>
Ian Rogers99cb4ea2014-03-26 22:53:56 -0700118static inline void ArrayForwardCopy(T* d, const T* s, int32_t count) {
119 for (int32_t i = 0; i < count; ++i) {
120 *d = *s;
121 d++;
122 s++;
123 }
Ian Rogers6fac4472014-02-25 17:01:10 -0800124}
125
Ian Rogersef7d42f2014-01-06 12:55:46 -0800126template<class T>
Mathieu Chartier31e88222016-10-14 18:43:19 -0700127inline void PrimitiveArray<T>::Memmove(int32_t dst_pos,
128 ObjPtr<PrimitiveArray<T>> src,
129 int32_t src_pos,
Ian Rogers6fac4472014-02-25 17:01:10 -0800130 int32_t count) {
Ian Rogersef7d42f2014-01-06 12:55:46 -0800131 if (UNLIKELY(count == 0)) {
132 return;
133 }
134 DCHECK_GE(dst_pos, 0);
135 DCHECK_GE(src_pos, 0);
136 DCHECK_GT(count, 0);
137 DCHECK(src != nullptr);
138 DCHECK_LT(dst_pos, GetLength());
139 DCHECK_LE(dst_pos, GetLength() - count);
140 DCHECK_LT(src_pos, src->GetLength());
141 DCHECK_LE(src_pos, src->GetLength() - count);
142
143 // Note for non-byte copies we can't rely on standard libc functions like memcpy(3) and memmove(3)
144 // in our implementation, because they may copy byte-by-byte.
Ian Rogers99cb4ea2014-03-26 22:53:56 -0700145 if (LIKELY(src != this)) {
146 // Memcpy ok for guaranteed non-overlapping distinct arrays.
Ian Rogersef7d42f2014-01-06 12:55:46 -0800147 Memcpy(dst_pos, src, src_pos, count);
148 } else {
Ian Rogers99cb4ea2014-03-26 22:53:56 -0700149 // Handle copies within the same array using the appropriate direction copy.
Ian Rogersef7d42f2014-01-06 12:55:46 -0800150 void* dst_raw = GetRawData(sizeof(T), dst_pos);
151 const void* src_raw = src->GetRawData(sizeof(T), src_pos);
152 if (sizeof(T) == sizeof(uint8_t)) {
Ian Rogersef7d42f2014-01-06 12:55:46 -0800153 uint8_t* d = reinterpret_cast<uint8_t*>(dst_raw);
154 const uint8_t* s = reinterpret_cast<const uint8_t*>(src_raw);
Ian Rogers99cb4ea2014-03-26 22:53:56 -0700155 memmove(d, s, count);
Ian Rogersef7d42f2014-01-06 12:55:46 -0800156 } else {
Ian Rogers99cb4ea2014-03-26 22:53:56 -0700157 const bool copy_forward = (dst_pos < src_pos) || (dst_pos - src_pos >= count);
158 if (sizeof(T) == sizeof(uint16_t)) {
159 uint16_t* d = reinterpret_cast<uint16_t*>(dst_raw);
160 const uint16_t* s = reinterpret_cast<const uint16_t*>(src_raw);
161 if (copy_forward) {
162 ArrayForwardCopy<uint16_t>(d, s, count);
163 } else {
164 ArrayBackwardCopy<uint16_t>(d, s, count);
165 }
166 } else if (sizeof(T) == sizeof(uint32_t)) {
167 uint32_t* d = reinterpret_cast<uint32_t*>(dst_raw);
168 const uint32_t* s = reinterpret_cast<const uint32_t*>(src_raw);
169 if (copy_forward) {
170 ArrayForwardCopy<uint32_t>(d, s, count);
171 } else {
172 ArrayBackwardCopy<uint32_t>(d, s, count);
173 }
174 } else {
175 DCHECK_EQ(sizeof(T), sizeof(uint64_t));
176 uint64_t* d = reinterpret_cast<uint64_t*>(dst_raw);
177 const uint64_t* s = reinterpret_cast<const uint64_t*>(src_raw);
178 if (copy_forward) {
179 ArrayForwardCopy<uint64_t>(d, s, count);
180 } else {
181 ArrayBackwardCopy<uint64_t>(d, s, count);
182 }
183 }
Ian Rogersef7d42f2014-01-06 12:55:46 -0800184 }
185 }
186}
187
Ian Rogersef7d42f2014-01-06 12:55:46 -0800188template<class T>
Mathieu Chartier31e88222016-10-14 18:43:19 -0700189inline void PrimitiveArray<T>::Memcpy(int32_t dst_pos,
190 ObjPtr<PrimitiveArray<T>> src,
191 int32_t src_pos,
Ian Rogers6fac4472014-02-25 17:01:10 -0800192 int32_t count) {
Ian Rogersef7d42f2014-01-06 12:55:46 -0800193 if (UNLIKELY(count == 0)) {
194 return;
195 }
196 DCHECK_GE(dst_pos, 0);
197 DCHECK_GE(src_pos, 0);
198 DCHECK_GT(count, 0);
199 DCHECK(src != nullptr);
200 DCHECK_LT(dst_pos, GetLength());
201 DCHECK_LE(dst_pos, GetLength() - count);
202 DCHECK_LT(src_pos, src->GetLength());
203 DCHECK_LE(src_pos, src->GetLength() - count);
204
205 // Note for non-byte copies we can't rely on standard libc functions like memcpy(3) and memmove(3)
206 // in our implementation, because they may copy byte-by-byte.
207 void* dst_raw = GetRawData(sizeof(T), dst_pos);
208 const void* src_raw = src->GetRawData(sizeof(T), src_pos);
209 if (sizeof(T) == sizeof(uint8_t)) {
210 memcpy(dst_raw, src_raw, 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 ArrayForwardCopy<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 ArrayForwardCopy<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 ArrayForwardCopy<uint64_t>(d, s, count);
224 }
225}
226
Andreas Gampea2fed082019-02-01 09:34:43 -0800227template<typename T, PointerSize kPointerSize, VerifyObjectFlags kVerifyFlags>
228inline T PointerArray::GetElementPtrSize(uint32_t idx) {
229 // C style casts here since we sometimes have T be a pointer, or sometimes an integer
230 // (for stack traces).
231 if (kPointerSize == PointerSize::k64) {
232 return (T)static_cast<uintptr_t>(AsLongArray<kVerifyFlags>()->GetWithoutChecks(idx));
233 }
234 return (T)static_cast<uintptr_t>(AsIntArray<kVerifyFlags>()->GetWithoutChecks(idx));
235}
Andreas Gampe3aa868a2019-02-04 11:18:43 -0800236template<typename T, PointerSize kPointerSize, VerifyObjectFlags kVerifyFlags>
237inline T PointerArray::GetElementPtrSizeUnchecked(uint32_t idx) {
238 // C style casts here since we sometimes have T be a pointer, or sometimes an integer
239 // (for stack traces).
240 if (kPointerSize == PointerSize::k64) {
241 return (T)static_cast<uintptr_t>(AsLongArrayUnchecked<kVerifyFlags>()->GetWithoutChecks(idx));
242 }
243 return (T)static_cast<uintptr_t>(AsIntArrayUnchecked<kVerifyFlags>()->GetWithoutChecks(idx));
244}
Vladimir Marko104883b2018-11-09 17:12:23 +0000245template<typename T, VerifyObjectFlags kVerifyFlags>
Andreas Gampe542451c2016-07-26 09:02:02 -0700246inline T PointerArray::GetElementPtrSize(uint32_t idx, PointerSize ptr_size) {
Andreas Gampe542451c2016-07-26 09:02:02 -0700247 if (ptr_size == PointerSize::k64) {
Andreas Gampea2fed082019-02-01 09:34:43 -0800248 return GetElementPtrSize<T, PointerSize::k64, kVerifyFlags>(idx);
Mathieu Chartiere401d142015-04-22 13:56:20 -0700249 }
Andreas Gampea2fed082019-02-01 09:34:43 -0800250 return GetElementPtrSize<T, PointerSize::k32, kVerifyFlags>(idx);
Mathieu Chartiere401d142015-04-22 13:56:20 -0700251}
252
Mathieu Chartierd329a3b2016-01-27 15:30:10 -0800253template<bool kTransactionActive, bool kUnchecked>
Andreas Gampe542451c2016-07-26 09:02:02 -0700254inline void PointerArray::SetElementPtrSize(uint32_t idx, uint64_t element, PointerSize ptr_size) {
255 if (ptr_size == PointerSize::k64) {
Mathieu Chartiere401d142015-04-22 13:56:20 -0700256 (kUnchecked ? down_cast<LongArray*>(static_cast<Object*>(this)) : AsLongArray())->
Mathieu Chartierd329a3b2016-01-27 15:30:10 -0800257 SetWithoutChecks<kTransactionActive>(idx, element);
Mathieu Chartiere401d142015-04-22 13:56:20 -0700258 } else {
Mathieu Chartierd329a3b2016-01-27 15:30:10 -0800259 DCHECK_LE(element, static_cast<uint64_t>(0xFFFFFFFFu));
Mathieu Chartiere401d142015-04-22 13:56:20 -0700260 (kUnchecked ? down_cast<IntArray*>(static_cast<Object*>(this)) : AsIntArray())
Mathieu Chartierd329a3b2016-01-27 15:30:10 -0800261 ->SetWithoutChecks<kTransactionActive>(idx, static_cast<uint32_t>(element));
Mathieu Chartiere401d142015-04-22 13:56:20 -0700262 }
263}
264
Mathieu Chartierd329a3b2016-01-27 15:30:10 -0800265template<bool kTransactionActive, bool kUnchecked, typename T>
Andreas Gampe542451c2016-07-26 09:02:02 -0700266inline void PointerArray::SetElementPtrSize(uint32_t idx, T* element, PointerSize ptr_size) {
Mathieu Chartier1bbfab62016-01-27 16:37:19 -0800267 SetElementPtrSize<kTransactionActive, kUnchecked>(idx,
268 reinterpret_cast<uintptr_t>(element),
269 ptr_size);
Mathieu Chartierd329a3b2016-01-27 15:30:10 -0800270}
271
Vladimir Marko104883b2018-11-09 17:12:23 +0000272template <VerifyObjectFlags kVerifyFlags, typename Visitor>
Vladimir Markoc524e9e2019-03-26 10:54:50 +0000273inline void PointerArray::Fixup(ObjPtr<mirror::PointerArray> dest,
Andreas Gampe542451c2016-07-26 09:02:02 -0700274 PointerSize pointer_size,
Mathieu Chartier4b00d342015-11-13 10:42:08 -0800275 const Visitor& visitor) {
276 for (size_t i = 0, count = GetLength(); i < count; ++i) {
Vladimir Marko104883b2018-11-09 17:12:23 +0000277 void* ptr = GetElementPtrSize<void*, kVerifyFlags>(i, pointer_size);
Mathieu Chartier4b00d342015-11-13 10:42:08 -0800278 void* new_ptr = visitor(ptr);
279 if (ptr != new_ptr) {
280 dest->SetElementPtrSize<false, true>(i, new_ptr, pointer_size);
281 }
282 }
283}
284
Alex Lighta01de592016-11-15 10:43:06 -0800285template<bool kUnchecked>
286void PointerArray::Memcpy(int32_t dst_pos,
287 ObjPtr<PointerArray> src,
288 int32_t src_pos,
289 int32_t count,
290 PointerSize ptr_size) {
291 DCHECK(!Runtime::Current()->IsActiveTransaction());
292 DCHECK(!src.IsNull());
293 if (ptr_size == PointerSize::k64) {
294 LongArray* l_this = (kUnchecked ? down_cast<LongArray*>(static_cast<Object*>(this))
295 : AsLongArray());
296 LongArray* l_src = (kUnchecked ? down_cast<LongArray*>(static_cast<Object*>(src.Ptr()))
297 : src->AsLongArray());
298 l_this->Memcpy(dst_pos, l_src, src_pos, count);
299 } else {
300 IntArray* i_this = (kUnchecked ? down_cast<IntArray*>(static_cast<Object*>(this))
301 : AsIntArray());
302 IntArray* i_src = (kUnchecked ? down_cast<IntArray*>(static_cast<Object*>(src.Ptr()))
303 : src->AsIntArray());
304 i_this->Memcpy(dst_pos, i_src, src_pos, count);
305 }
306}
307
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800308} // namespace mirror
309} // namespace art
310
Brian Carlstromfc0e3212013-07-17 14:40:12 -0700311#endif // ART_RUNTIME_MIRROR_ARRAY_INL_H_