blob: 19d35a89ec58bcf821d49311d58d10caef4c2fff [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
Hiroshi Yamauchi6e83c172014-05-01 21:25:41 -070038template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
Ian Rogersef7d42f2014-01-06 12:55:46 -080039inline size_t Array::SizeOf() {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080040 // This is safe from overflow because the array was already allocated, so we know it's sane.
Hiroshi Yamauchif0edfc32014-09-25 11:46:46 -070041 size_t component_size_shift = GetClass<kVerifyFlags, kReadBarrierOption>()->
42 template GetComponentSizeShift<kReadBarrierOption>();
Mathieu Chartier4e305412014-02-19 10:54:44 -080043 // Don't need to check this since we already check this in GetClass.
44 int32_t component_count =
45 GetLength<static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis)>();
Hiroshi Yamauchif0edfc32014-09-25 11:46:46 -070046 size_t header_size = DataOffset(1U << component_size_shift).SizeValue();
47 size_t data_size = component_count << component_size_shift;
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080048 return header_size + data_size;
49}
50
Ian Rogersb0fa5dc2014-04-28 16:47:08 -070051template<VerifyObjectFlags kVerifyFlags>
52inline bool Array::CheckIsValidIndex(int32_t index) {
53 if (UNLIKELY(static_cast<uint32_t>(index) >=
54 static_cast<uint32_t>(GetLength<kVerifyFlags>()))) {
55 ThrowArrayIndexOutOfBoundsException(index);
56 return false;
57 }
58 return true;
59}
60
Alex Light440b5d92017-01-24 15:32:25 -080061template<typename T>
Ian Rogersb0fa5dc2014-04-28 16:47:08 -070062inline T PrimitiveArray<T>::Get(int32_t i) {
63 if (!CheckIsValidIndex(i)) {
64 DCHECK(Thread::Current()->IsExceptionPending());
65 return T(0);
66 }
67 return GetWithoutChecks(i);
68}
69
70template<typename T>
71inline void PrimitiveArray<T>::Set(int32_t i, T value) {
72 if (Runtime::Current()->IsActiveTransaction()) {
73 Set<true>(i, value);
74 } else {
75 Set<false>(i, value);
76 }
77}
78
79template<typename T>
80template<bool kTransactionActive, bool kCheckTransaction>
81inline void PrimitiveArray<T>::Set(int32_t i, T value) {
82 if (CheckIsValidIndex(i)) {
83 SetWithoutChecks<kTransactionActive, kCheckTransaction>(i, value);
84 } else {
85 DCHECK(Thread::Current()->IsExceptionPending());
86 }
87}
88
89template<typename T>
Andreas Gampe3b45ef22015-05-26 21:34:09 -070090template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
Ian Rogersb0fa5dc2014-04-28 16:47:08 -070091inline void PrimitiveArray<T>::SetWithoutChecks(int32_t i, T value) {
92 if (kCheckTransaction) {
93 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
94 }
95 if (kTransactionActive) {
96 Runtime::Current()->RecordWriteArray(this, i, GetWithoutChecks(i));
97 }
Andreas Gampe3b45ef22015-05-26 21:34:09 -070098 DCHECK(CheckIsValidIndex<kVerifyFlags>(i));
Ian Rogersb0fa5dc2014-04-28 16:47:08 -070099 GetData()[i] = value;
100}
Ian Rogers99cb4ea2014-03-26 22:53:56 -0700101// Backward copy where elements are of aligned appropriately for T. Count is in T sized units.
102// Copies are guaranteed not to tear when the sizeof T is less-than 64bit.
Ian Rogersef7d42f2014-01-06 12:55:46 -0800103template<typename T>
104static inline void ArrayBackwardCopy(T* d, const T* s, int32_t count) {
105 d += count;
106 s += count;
107 for (int32_t i = 0; i < count; ++i) {
108 d--;
109 s--;
110 *d = *s;
111 }
112}
113
Ian Rogers99cb4ea2014-03-26 22:53:56 -0700114// Forward copy where elements are of aligned appropriately for T. Count is in T sized units.
115// Copies are guaranteed not to tear when the sizeof T is less-than 64bit.
Ian Rogers6fac4472014-02-25 17:01:10 -0800116template<typename T>
Ian Rogers99cb4ea2014-03-26 22:53:56 -0700117static inline void ArrayForwardCopy(T* d, const T* s, int32_t count) {
118 for (int32_t i = 0; i < count; ++i) {
119 *d = *s;
120 d++;
121 s++;
122 }
Ian Rogers6fac4472014-02-25 17:01:10 -0800123}
124
Ian Rogersef7d42f2014-01-06 12:55:46 -0800125template<class T>
Mathieu Chartier31e88222016-10-14 18:43:19 -0700126inline void PrimitiveArray<T>::Memmove(int32_t dst_pos,
127 ObjPtr<PrimitiveArray<T>> src,
128 int32_t src_pos,
Ian Rogers6fac4472014-02-25 17:01:10 -0800129 int32_t count) {
Ian Rogersef7d42f2014-01-06 12:55:46 -0800130 if (UNLIKELY(count == 0)) {
131 return;
132 }
133 DCHECK_GE(dst_pos, 0);
134 DCHECK_GE(src_pos, 0);
135 DCHECK_GT(count, 0);
136 DCHECK(src != nullptr);
137 DCHECK_LT(dst_pos, GetLength());
138 DCHECK_LE(dst_pos, GetLength() - count);
139 DCHECK_LT(src_pos, src->GetLength());
140 DCHECK_LE(src_pos, src->GetLength() - count);
141
142 // Note for non-byte copies we can't rely on standard libc functions like memcpy(3) and memmove(3)
143 // in our implementation, because they may copy byte-by-byte.
Ian Rogers99cb4ea2014-03-26 22:53:56 -0700144 if (LIKELY(src != this)) {
145 // Memcpy ok for guaranteed non-overlapping distinct arrays.
Ian Rogersef7d42f2014-01-06 12:55:46 -0800146 Memcpy(dst_pos, src, src_pos, count);
147 } else {
Ian Rogers99cb4ea2014-03-26 22:53:56 -0700148 // Handle copies within the same array using the appropriate direction copy.
Ian Rogersef7d42f2014-01-06 12:55:46 -0800149 void* dst_raw = GetRawData(sizeof(T), dst_pos);
150 const void* src_raw = src->GetRawData(sizeof(T), src_pos);
151 if (sizeof(T) == sizeof(uint8_t)) {
Ian Rogersef7d42f2014-01-06 12:55:46 -0800152 uint8_t* d = reinterpret_cast<uint8_t*>(dst_raw);
153 const uint8_t* s = reinterpret_cast<const uint8_t*>(src_raw);
Ian Rogers99cb4ea2014-03-26 22:53:56 -0700154 memmove(d, s, count);
Ian Rogersef7d42f2014-01-06 12:55:46 -0800155 } else {
Ian Rogers99cb4ea2014-03-26 22:53:56 -0700156 const bool copy_forward = (dst_pos < src_pos) || (dst_pos - src_pos >= count);
157 if (sizeof(T) == sizeof(uint16_t)) {
158 uint16_t* d = reinterpret_cast<uint16_t*>(dst_raw);
159 const uint16_t* s = reinterpret_cast<const uint16_t*>(src_raw);
160 if (copy_forward) {
161 ArrayForwardCopy<uint16_t>(d, s, count);
162 } else {
163 ArrayBackwardCopy<uint16_t>(d, s, count);
164 }
165 } else if (sizeof(T) == sizeof(uint32_t)) {
166 uint32_t* d = reinterpret_cast<uint32_t*>(dst_raw);
167 const uint32_t* s = reinterpret_cast<const uint32_t*>(src_raw);
168 if (copy_forward) {
169 ArrayForwardCopy<uint32_t>(d, s, count);
170 } else {
171 ArrayBackwardCopy<uint32_t>(d, s, count);
172 }
173 } else {
174 DCHECK_EQ(sizeof(T), sizeof(uint64_t));
175 uint64_t* d = reinterpret_cast<uint64_t*>(dst_raw);
176 const uint64_t* s = reinterpret_cast<const uint64_t*>(src_raw);
177 if (copy_forward) {
178 ArrayForwardCopy<uint64_t>(d, s, count);
179 } else {
180 ArrayBackwardCopy<uint64_t>(d, s, count);
181 }
182 }
Ian Rogersef7d42f2014-01-06 12:55:46 -0800183 }
184 }
185}
186
Ian Rogersef7d42f2014-01-06 12:55:46 -0800187template<class T>
Mathieu Chartier31e88222016-10-14 18:43:19 -0700188inline void PrimitiveArray<T>::Memcpy(int32_t dst_pos,
189 ObjPtr<PrimitiveArray<T>> src,
190 int32_t src_pos,
Ian Rogers6fac4472014-02-25 17:01:10 -0800191 int32_t count) {
Ian Rogersef7d42f2014-01-06 12:55:46 -0800192 if (UNLIKELY(count == 0)) {
193 return;
194 }
195 DCHECK_GE(dst_pos, 0);
196 DCHECK_GE(src_pos, 0);
197 DCHECK_GT(count, 0);
198 DCHECK(src != nullptr);
199 DCHECK_LT(dst_pos, GetLength());
200 DCHECK_LE(dst_pos, GetLength() - count);
201 DCHECK_LT(src_pos, src->GetLength());
202 DCHECK_LE(src_pos, src->GetLength() - count);
203
204 // Note for non-byte copies we can't rely on standard libc functions like memcpy(3) and memmove(3)
205 // in our implementation, because they may copy byte-by-byte.
206 void* dst_raw = GetRawData(sizeof(T), dst_pos);
207 const void* src_raw = src->GetRawData(sizeof(T), src_pos);
208 if (sizeof(T) == sizeof(uint8_t)) {
209 memcpy(dst_raw, src_raw, count);
210 } else if (sizeof(T) == sizeof(uint16_t)) {
211 uint16_t* d = reinterpret_cast<uint16_t*>(dst_raw);
212 const uint16_t* s = reinterpret_cast<const uint16_t*>(src_raw);
213 ArrayForwardCopy<uint16_t>(d, s, count);
214 } else if (sizeof(T) == sizeof(uint32_t)) {
215 uint32_t* d = reinterpret_cast<uint32_t*>(dst_raw);
216 const uint32_t* s = reinterpret_cast<const uint32_t*>(src_raw);
217 ArrayForwardCopy<uint32_t>(d, s, count);
218 } else {
219 DCHECK_EQ(sizeof(T), sizeof(uint64_t));
220 uint64_t* d = reinterpret_cast<uint64_t*>(dst_raw);
221 const uint64_t* s = reinterpret_cast<const uint64_t*>(src_raw);
222 ArrayForwardCopy<uint64_t>(d, s, count);
223 }
224}
225
Andreas Gampea2fed082019-02-01 09:34:43 -0800226template<typename T, PointerSize kPointerSize, VerifyObjectFlags kVerifyFlags>
227inline T PointerArray::GetElementPtrSize(uint32_t idx) {
228 // C style casts here since we sometimes have T be a pointer, or sometimes an integer
229 // (for stack traces).
230 if (kPointerSize == PointerSize::k64) {
231 return (T)static_cast<uintptr_t>(AsLongArray<kVerifyFlags>()->GetWithoutChecks(idx));
232 }
233 return (T)static_cast<uintptr_t>(AsIntArray<kVerifyFlags>()->GetWithoutChecks(idx));
234}
Andreas Gampe3aa868a2019-02-04 11:18:43 -0800235template<typename T, PointerSize kPointerSize, VerifyObjectFlags kVerifyFlags>
236inline T PointerArray::GetElementPtrSizeUnchecked(uint32_t idx) {
237 // C style casts here since we sometimes have T be a pointer, or sometimes an integer
238 // (for stack traces).
239 if (kPointerSize == PointerSize::k64) {
240 return (T)static_cast<uintptr_t>(AsLongArrayUnchecked<kVerifyFlags>()->GetWithoutChecks(idx));
241 }
242 return (T)static_cast<uintptr_t>(AsIntArrayUnchecked<kVerifyFlags>()->GetWithoutChecks(idx));
243}
Vladimir Marko104883b2018-11-09 17:12:23 +0000244template<typename T, VerifyObjectFlags kVerifyFlags>
Andreas Gampe542451c2016-07-26 09:02:02 -0700245inline T PointerArray::GetElementPtrSize(uint32_t idx, PointerSize ptr_size) {
Andreas Gampe542451c2016-07-26 09:02:02 -0700246 if (ptr_size == PointerSize::k64) {
Andreas Gampea2fed082019-02-01 09:34:43 -0800247 return GetElementPtrSize<T, PointerSize::k64, kVerifyFlags>(idx);
Mathieu Chartiere401d142015-04-22 13:56:20 -0700248 }
Andreas Gampea2fed082019-02-01 09:34:43 -0800249 return GetElementPtrSize<T, PointerSize::k32, kVerifyFlags>(idx);
Mathieu Chartiere401d142015-04-22 13:56:20 -0700250}
251
Mathieu Chartierd329a3b2016-01-27 15:30:10 -0800252template<bool kTransactionActive, bool kUnchecked>
Andreas Gampe542451c2016-07-26 09:02:02 -0700253inline void PointerArray::SetElementPtrSize(uint32_t idx, uint64_t element, PointerSize ptr_size) {
254 if (ptr_size == PointerSize::k64) {
Vladimir Marko4617d582019-03-28 13:48:31 +0000255 (kUnchecked ? ObjPtr<LongArray>::DownCast(ObjPtr<Object>(this)) : AsLongArray())->
Mathieu Chartierd329a3b2016-01-27 15:30:10 -0800256 SetWithoutChecks<kTransactionActive>(idx, element);
Mathieu Chartiere401d142015-04-22 13:56:20 -0700257 } else {
Mathieu Chartierd329a3b2016-01-27 15:30:10 -0800258 DCHECK_LE(element, static_cast<uint64_t>(0xFFFFFFFFu));
Vladimir Marko4617d582019-03-28 13:48:31 +0000259 (kUnchecked ? ObjPtr<IntArray>::DownCast(ObjPtr<Object>(this)) : AsIntArray())
Mathieu Chartierd329a3b2016-01-27 15:30:10 -0800260 ->SetWithoutChecks<kTransactionActive>(idx, static_cast<uint32_t>(element));
Mathieu Chartiere401d142015-04-22 13:56:20 -0700261 }
262}
263
Mathieu Chartierd329a3b2016-01-27 15:30:10 -0800264template<bool kTransactionActive, bool kUnchecked, typename T>
Andreas Gampe542451c2016-07-26 09:02:02 -0700265inline void PointerArray::SetElementPtrSize(uint32_t idx, T* element, PointerSize ptr_size) {
Mathieu Chartier1bbfab62016-01-27 16:37:19 -0800266 SetElementPtrSize<kTransactionActive, kUnchecked>(idx,
267 reinterpret_cast<uintptr_t>(element),
268 ptr_size);
Mathieu Chartierd329a3b2016-01-27 15:30:10 -0800269}
270
Vladimir Marko104883b2018-11-09 17:12:23 +0000271template <VerifyObjectFlags kVerifyFlags, typename Visitor>
Vladimir Markoc524e9e2019-03-26 10:54:50 +0000272inline void PointerArray::Fixup(ObjPtr<mirror::PointerArray> dest,
Andreas Gampe542451c2016-07-26 09:02:02 -0700273 PointerSize pointer_size,
Mathieu Chartier4b00d342015-11-13 10:42:08 -0800274 const Visitor& visitor) {
275 for (size_t i = 0, count = GetLength(); i < count; ++i) {
Vladimir Marko104883b2018-11-09 17:12:23 +0000276 void* ptr = GetElementPtrSize<void*, kVerifyFlags>(i, pointer_size);
Mathieu Chartier4b00d342015-11-13 10:42:08 -0800277 void* new_ptr = visitor(ptr);
278 if (ptr != new_ptr) {
279 dest->SetElementPtrSize<false, true>(i, new_ptr, pointer_size);
280 }
281 }
282}
283
Alex Lighta01de592016-11-15 10:43:06 -0800284template<bool kUnchecked>
285void PointerArray::Memcpy(int32_t dst_pos,
286 ObjPtr<PointerArray> src,
287 int32_t src_pos,
288 int32_t count,
289 PointerSize ptr_size) {
290 DCHECK(!Runtime::Current()->IsActiveTransaction());
291 DCHECK(!src.IsNull());
292 if (ptr_size == PointerSize::k64) {
Vladimir Marko4617d582019-03-28 13:48:31 +0000293 ObjPtr<LongArray> l_this = (kUnchecked ? ObjPtr<LongArray>::DownCast(ObjPtr<Object>(this))
294 : AsLongArray());
295 ObjPtr<LongArray> l_src = (kUnchecked ? ObjPtr<LongArray>::DownCast(ObjPtr<Object>(src))
296 : src->AsLongArray());
Alex Lighta01de592016-11-15 10:43:06 -0800297 l_this->Memcpy(dst_pos, l_src, src_pos, count);
298 } else {
Vladimir Marko4617d582019-03-28 13:48:31 +0000299 ObjPtr<IntArray> i_this = (kUnchecked ? ObjPtr<IntArray>::DownCast(ObjPtr<Object>(this))
300 : AsIntArray());
301 ObjPtr<IntArray> i_src = (kUnchecked ? ObjPtr<IntArray>::DownCast(ObjPtr<Object>(src.Ptr()))
302 : src->AsIntArray());
Alex Lighta01de592016-11-15 10:43:06 -0800303 i_this->Memcpy(dst_pos, i_src, src_pos, count);
304 }
305}
306
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800307} // namespace mirror
308} // namespace art
309
Brian Carlstromfc0e3212013-07-17 14:40:12 -0700310#endif // ART_RUNTIME_MIRROR_ARRAY_INL_H_