blob: 6674db2403ec47d87ac85848bfdcfdfef6ee40da [file] [log] [blame]
Elliott Hughesbf86d042011-08-31 17:53:14 -07001/*
2 * Copyright (C) 2008 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
Ian Rogers62d6c772013-02-27 08:32:07 -080017#include "common_throws.h"
Ian Rogers1d54e732013-05-02 21:10:01 -070018#include "gc/accounting/card_table-inl.h"
Elliott Hughesbf86d042011-08-31 17:53:14 -070019#include "jni_internal.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080020#include "mirror/array.h"
21#include "mirror/class.h"
22#include "mirror/class-inl.h"
23#include "mirror/object-inl.h"
Ian Rogers693ff612013-02-01 10:56:12 -080024#include "mirror/object_array-inl.h"
Ian Rogers1eb512d2013-10-18 15:42:20 -070025#include "scoped_fast_native_object_access.h"
Elliott Hughesbf86d042011-08-31 17:53:14 -070026
Elliott Hughesbf86d042011-08-31 17:53:14 -070027/*
28 * We make guarantees about the atomicity of accesses to primitive
29 * variables. These guarantees also apply to elements of arrays.
30 * In particular, 8-bit, 16-bit, and 32-bit accesses must be atomic and
31 * must not cause "word tearing". Accesses to 64-bit array elements must
32 * either be atomic or treated as two 32-bit operations. References are
33 * always read and written atomically, regardless of the number of bits
34 * used to represent them.
35 *
36 * We can't rely on standard libc functions like memcpy(3) and memmove(3)
37 * in our implementation of System.arraycopy, because they may copy
38 * byte-by-byte (either for the full run or for "unaligned" parts at the
39 * start or end). We need to use functions that guarantee 16-bit or 32-bit
40 * atomicity as appropriate.
41 *
42 * System.arraycopy() is heavily used, so having an efficient implementation
43 * is important. The bionic libc provides a platform-optimized memory move
44 * function that should be used when possible. If it's not available,
45 * the trivial "reference implementation" versions below can be used until
46 * a proper version can be written.
47 *
48 * For these functions, The caller must guarantee that dst/src are aligned
49 * appropriately for the element type, and that n is a multiple of the
50 * element size.
51 */
Elliott Hughesbf86d042011-08-31 17:53:14 -070052
Elliott Hughes6324e212013-02-15 17:55:35 -080053/*
54 * Works like memmove(), except:
55 * - if all arguments are at least 32-bit aligned, we guarantee that we
56 * will use operations that preserve atomicity of 32-bit values
57 * - if not, we guarantee atomicity of 16-bit values
58 *
59 * If all three arguments are not at least 16-bit aligned, the behavior
60 * of this function is undefined. (We could remove this restriction by
61 * testing for unaligned values and punting to memmove(), but that's
62 * not currently useful.)
63 *
64 * TODO: add loop for 64-bit alignment
65 * TODO: use __builtin_prefetch
66 * TODO: write ARM/MIPS/x86 optimized versions
67 */
68void MemmoveWords(void* dst, const void* src, size_t n) {
Elliott Hughescc607472011-10-17 15:34:11 -070069 DCHECK_EQ((((uintptr_t) dst | (uintptr_t) src | n) & 0x01), 0U);
Elliott Hughesbf86d042011-08-31 17:53:14 -070070
Elliott Hughes6324e212013-02-15 17:55:35 -080071 char* d = reinterpret_cast<char*>(dst);
72 const char* s = reinterpret_cast<const char*>(src);
73 size_t copyCount;
Elliott Hughesbf86d042011-08-31 17:53:14 -070074
Elliott Hughes6324e212013-02-15 17:55:35 -080075 // If the source and destination pointers are the same, this is
76 // an expensive no-op. Testing for an empty move now allows us
77 // to skip a check later.
78 if (n == 0 || d == s) {
79 return;
80 }
Elliott Hughesbf86d042011-08-31 17:53:14 -070081
Elliott Hughes6324e212013-02-15 17:55:35 -080082 // Determine if the source and destination buffers will overlap if
83 // we copy data forward (i.e. *dst++ = *src++).
84 //
85 // It's okay if the destination buffer starts before the source and
86 // there is some overlap, because the reader is always ahead of the
87 // writer.
88 if (LIKELY((d < s) || ((size_t)(d - s) >= n))) {
89 // Copy forward. We prefer 32-bit loads and stores even for 16-bit
90 // data, so sort that out.
91 if (((reinterpret_cast<uintptr_t>(d) | reinterpret_cast<uintptr_t>(s)) & 0x03) != 0) {
92 // Not 32-bit aligned. Two possibilities:
93 // (1) Congruent, we can align to 32-bit by copying one 16-bit val
94 // (2) Non-congruent, we can do one of:
95 // a. copy whole buffer as a series of 16-bit values
96 // b. load/store 32 bits, using shifts to ensure alignment
97 // c. just copy the as 32-bit values and assume the CPU
98 // will do a reasonable job
99 //
100 // We're currently using (a), which is suboptimal.
101 if (((reinterpret_cast<uintptr_t>(d) ^ reinterpret_cast<uintptr_t>(s)) & 0x03) != 0) {
102 copyCount = n;
103 } else {
104 copyCount = 2;
105 }
106 n -= copyCount;
107 copyCount /= sizeof(uint16_t);
108
109 while (copyCount--) {
110 *reinterpret_cast<uint16_t*>(d) = *reinterpret_cast<const uint16_t*>(s);
111 d += sizeof(uint16_t);
112 s += sizeof(uint16_t);
113 }
114 }
115
116 // Copy 32-bit aligned words.
117 copyCount = n / sizeof(uint32_t);
118 while (copyCount--) {
119 *reinterpret_cast<uint32_t*>(d) = *reinterpret_cast<const uint32_t*>(s);
120 d += sizeof(uint32_t);
121 s += sizeof(uint32_t);
122 }
123
124 // Check for leftovers. Either we finished exactly, or we have one remaining 16-bit chunk.
125 if ((n & 0x02) != 0) {
Brian Carlstrom2d888622013-07-18 17:02:00 -0700126 *reinterpret_cast<uint16_t*>(d) = *reinterpret_cast<const uint16_t*>(s);
Elliott Hughesbf86d042011-08-31 17:53:14 -0700127 }
128 } else {
Elliott Hughes6324e212013-02-15 17:55:35 -0800129 // Copy backward, starting at the end.
Elliott Hughesbf86d042011-08-31 17:53:14 -0700130 d += n;
131 s += n;
Elliott Hughes6324e212013-02-15 17:55:35 -0800132
133 if (((reinterpret_cast<uintptr_t>(d) | reinterpret_cast<uintptr_t>(s)) & 0x03) != 0) {
134 // try for 32-bit alignment.
135 if (((reinterpret_cast<uintptr_t>(d) ^ reinterpret_cast<uintptr_t>(s)) & 0x03) != 0) {
136 copyCount = n;
137 } else {
138 copyCount = 2;
139 }
140 n -= copyCount;
141 copyCount /= sizeof(uint16_t);
142
143 while (copyCount--) {
144 d -= sizeof(uint16_t);
145 s -= sizeof(uint16_t);
146 *reinterpret_cast<uint16_t*>(d) = *reinterpret_cast<const uint16_t*>(s);
147 }
148 }
149
150 // Copy 32-bit aligned words.
151 copyCount = n / sizeof(uint32_t);
152 while (copyCount--) {
153 d -= sizeof(uint32_t);
154 s -= sizeof(uint32_t);
155 *reinterpret_cast<uint32_t*>(d) = *reinterpret_cast<const uint32_t*>(s);
156 }
157
158 // Copy leftovers.
159 if ((n & 0x02) != 0) {
160 d -= sizeof(uint16_t);
161 s -= sizeof(uint16_t);
162 *reinterpret_cast<uint16_t*>(d) = *reinterpret_cast<const uint16_t*>(s);
Elliott Hughesbf86d042011-08-31 17:53:14 -0700163 }
164 }
165}
166
Elliott Hughes6324e212013-02-15 17:55:35 -0800167#define move16 MemmoveWords
168#define move32 MemmoveWords
Elliott Hughesbf86d042011-08-31 17:53:14 -0700169
170namespace art {
171
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800172static void ThrowArrayStoreException_NotAnArray(const char* identifier, mirror::Object* array)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700173 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Elliott Hughes54e7df12011-09-16 11:47:04 -0700174 std::string actualType(PrettyTypeOf(array));
Ian Rogers62d6c772013-02-27 08:32:07 -0800175 Thread* self = Thread::Current();
176 ThrowLocation throw_location = self->GetCurrentLocationForThrow();
177 self->ThrowNewExceptionF(throw_location, "Ljava/lang/ArrayStoreException;",
178 "%s of type %s is not an array", identifier, actualType.c_str());
Elliott Hughesbf86d042011-08-31 17:53:14 -0700179}
180
Elliott Hughes0512f022012-03-15 22:10:52 -0700181static void System_arraycopy(JNIEnv* env, jclass, jobject javaSrc, jint srcPos, jobject javaDst, jint dstPos, jint length) {
Ian Rogers1eb512d2013-10-18 15:42:20 -0700182 ScopedFastNativeObjectAccess soa(env);
Elliott Hughesbf86d042011-08-31 17:53:14 -0700183
184 // Null pointer checks.
Ian Rogers62d6c772013-02-27 08:32:07 -0800185 if (UNLIKELY(javaSrc == NULL)) {
186 ThrowNullPointerException(NULL, "src == null");
Elliott Hughesbf86d042011-08-31 17:53:14 -0700187 return;
188 }
Ian Rogers62d6c772013-02-27 08:32:07 -0800189 if (UNLIKELY(javaDst == NULL)) {
190 ThrowNullPointerException(NULL, "dst == null");
Elliott Hughesbf86d042011-08-31 17:53:14 -0700191 return;
192 }
193
194 // Make sure source and destination are both arrays.
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800195 mirror::Object* srcObject = soa.Decode<mirror::Object*>(javaSrc);
196 mirror::Object* dstObject = soa.Decode<mirror::Object*>(javaDst);
Ian Rogers62d6c772013-02-27 08:32:07 -0800197 if (UNLIKELY(!srcObject->IsArrayInstance())) {
Elliott Hughes81aa5b32012-01-17 13:47:13 -0800198 ThrowArrayStoreException_NotAnArray("source", srcObject);
Elliott Hughesbf86d042011-08-31 17:53:14 -0700199 return;
200 }
Ian Rogers62d6c772013-02-27 08:32:07 -0800201 if (UNLIKELY(!dstObject->IsArrayInstance())) {
Elliott Hughes81aa5b32012-01-17 13:47:13 -0800202 ThrowArrayStoreException_NotAnArray("destination", dstObject);
Elliott Hughesbf86d042011-08-31 17:53:14 -0700203 return;
204 }
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800205 mirror::Array* srcArray = srcObject->AsArray();
206 mirror::Array* dstArray = dstObject->AsArray();
207 mirror::Class* srcComponentType = srcArray->GetClass()->GetComponentType();
208 mirror::Class* dstComponentType = dstArray->GetClass()->GetComponentType();
Elliott Hughesbf86d042011-08-31 17:53:14 -0700209
210 // Bounds checking.
Ian Rogers62d6c772013-02-27 08:32:07 -0800211 if (UNLIKELY(srcPos < 0 || dstPos < 0 || length < 0 || srcPos > srcArray->GetLength() - length || dstPos > dstArray->GetLength() - length)) {
212 ThrowLocation throw_location = soa.Self()->GetCurrentLocationForThrow();
213 soa.Self()->ThrowNewExceptionF(throw_location, "Ljava/lang/ArrayIndexOutOfBoundsException;",
214 "src.length=%d srcPos=%d dst.length=%d dstPos=%d length=%d",
215 srcArray->GetLength(), srcPos, dstArray->GetLength(), dstPos, length);
Elliott Hughesbf86d042011-08-31 17:53:14 -0700216 return;
217 }
218
Elliott Hughesbf86d042011-08-31 17:53:14 -0700219 // Handle primitive arrays.
220 if (srcComponentType->IsPrimitive() || dstComponentType->IsPrimitive()) {
221 // If one of the arrays holds a primitive type the other array must hold the exact same type.
Ian Rogers62d6c772013-02-27 08:32:07 -0800222 if (UNLIKELY(srcComponentType != dstComponentType)) {
Elliott Hughes54e7df12011-09-16 11:47:04 -0700223 std::string srcType(PrettyTypeOf(srcArray));
224 std::string dstType(PrettyTypeOf(dstArray));
Ian Rogers62d6c772013-02-27 08:32:07 -0800225 ThrowLocation throw_location = soa.Self()->GetCurrentLocationForThrow();
226 soa.Self()->ThrowNewExceptionF(throw_location, "Ljava/lang/ArrayStoreException;",
227 "Incompatible types: src=%s, dst=%s",
228 srcType.c_str(), dstType.c_str());
Elliott Hughesbf86d042011-08-31 17:53:14 -0700229 return;
230 }
231
Ian Rogersa15e67d2012-02-28 13:51:55 -0800232 size_t width = srcArray->GetClass()->GetComponentSize();
233 uint8_t* dstBytes = reinterpret_cast<uint8_t*>(dstArray->GetRawData(width));
234 const uint8_t* srcBytes = reinterpret_cast<const uint8_t*>(srcArray->GetRawData(width));
235
236 switch (width) {
Elliott Hughesbf86d042011-08-31 17:53:14 -0700237 case 1:
238 memmove(dstBytes + dstPos, srcBytes + srcPos, length);
239 break;
240 case 2:
241 move16(dstBytes + dstPos * 2, srcBytes + srcPos * 2, length * 2);
242 break;
243 case 4:
244 move32(dstBytes + dstPos * 4, srcBytes + srcPos * 4, length * 4);
245 break;
246 case 8:
247 // We don't need to guarantee atomicity of the entire 64-bit word.
248 move32(dstBytes + dstPos * 8, srcBytes + srcPos * 8, length * 8);
249 break;
250 default:
Elliott Hughes54e7df12011-09-16 11:47:04 -0700251 LOG(FATAL) << "Unknown primitive array type: " << PrettyTypeOf(srcArray);
Elliott Hughesbf86d042011-08-31 17:53:14 -0700252 }
253
254 return;
255 }
256
257 // Neither class is primitive. Are the types trivially compatible?
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800258 const size_t width = sizeof(mirror::Object*);
Ian Rogersa15e67d2012-02-28 13:51:55 -0800259 uint8_t* dstBytes = reinterpret_cast<uint8_t*>(dstArray->GetRawData(width));
260 const uint8_t* srcBytes = reinterpret_cast<const uint8_t*>(srcArray->GetRawData(width));
Elliott Hughesab3530d2012-01-09 16:04:56 -0800261 if (dstArray == srcArray || dstComponentType->IsAssignableFrom(srcComponentType)) {
Elliott Hughesbf86d042011-08-31 17:53:14 -0700262 // Yes. Bulk copy.
Brian Carlstromb6db9d22011-09-18 11:39:12 -0700263 COMPILE_ASSERT(sizeof(width) == sizeof(uint32_t), move32_assumes_Object_references_are_32_bit);
Elliott Hughesbf86d042011-08-31 17:53:14 -0700264 move32(dstBytes + dstPos * width, srcBytes + srcPos * width, length * width);
Elliott Hughesb3bd5f02012-03-08 21:05:27 -0800265 Runtime::Current()->GetHeap()->WriteBarrierArray(dstArray, dstPos, length);
Elliott Hughesbf86d042011-08-31 17:53:14 -0700266 return;
267 }
268
Elliott Hughesab3530d2012-01-09 16:04:56 -0800269 // The arrays are not trivially compatible. However, we may still be able to copy some or all of
270 // the elements if the source objects are compatible (for example, copying an Object[] to
271 // String[], the Objects being copied might actually be Strings).
272 // We can't do a bulk move because that would introduce a check-use race condition, so we copy
273 // elements one by one.
Elliott Hughesbf86d042011-08-31 17:53:14 -0700274
Elliott Hughesab3530d2012-01-09 16:04:56 -0800275 // We already dealt with overlapping copies, so we don't need to cope with that case below.
276 CHECK_NE(dstArray, srcArray);
Elliott Hughesbf86d042011-08-31 17:53:14 -0700277
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800278 mirror::Object* const * srcObjects =
279 reinterpret_cast<mirror::Object* const *>(srcBytes + srcPos * width);
280 mirror::Object** dstObjects = reinterpret_cast<mirror::Object**>(dstBytes + dstPos * width);
281 mirror::Class* dstClass = dstArray->GetClass()->GetComponentType();
Elliott Hughesbf86d042011-08-31 17:53:14 -0700282
Elliott Hughesab3530d2012-01-09 16:04:56 -0800283 // We want to avoid redundant IsAssignableFrom checks where possible, so we cache a class that
284 // we know is assignable to the destination array's component type.
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800285 mirror::Class* lastAssignableElementClass = dstClass;
Elliott Hughesab3530d2012-01-09 16:04:56 -0800286
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800287 mirror::Object* o = NULL;
Elliott Hughesab3530d2012-01-09 16:04:56 -0800288 int i = 0;
289 for (; i < length; ++i) {
Elliott Hughes025c5de2012-01-10 11:05:48 -0800290 o = srcObjects[i];
Elliott Hughesab3530d2012-01-09 16:04:56 -0800291 if (o != NULL) {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800292 mirror::Class* oClass = o->GetClass();
Elliott Hughesab3530d2012-01-09 16:04:56 -0800293 if (lastAssignableElementClass == oClass) {
294 dstObjects[i] = o;
295 } else if (dstClass->IsAssignableFrom(oClass)) {
296 lastAssignableElementClass = oClass;
297 dstObjects[i] = o;
298 } else {
299 // Can't put this element into the array.
300 break;
301 }
302 } else {
303 dstObjects[i] = NULL;
Elliott Hughesbf86d042011-08-31 17:53:14 -0700304 }
305 }
306
Elliott Hughesb3bd5f02012-03-08 21:05:27 -0800307 Runtime::Current()->GetHeap()->WriteBarrierArray(dstArray, dstPos, length);
Ian Rogers62d6c772013-02-27 08:32:07 -0800308 if (UNLIKELY(i != length)) {
Elliott Hughes025c5de2012-01-10 11:05:48 -0800309 std::string actualSrcType(PrettyTypeOf(o));
Elliott Hughes54e7df12011-09-16 11:47:04 -0700310 std::string dstType(PrettyTypeOf(dstArray));
Ian Rogers62d6c772013-02-27 08:32:07 -0800311 ThrowLocation throw_location = soa.Self()->GetCurrentLocationForThrow();
312 soa.Self()->ThrowNewExceptionF(throw_location, "Ljava/lang/ArrayStoreException;",
313 "source[%d] of type %s cannot be stored in destination array of type %s",
314 srcPos + i, actualSrcType.c_str(), dstType.c_str());
Elliott Hughesbf86d042011-08-31 17:53:14 -0700315 return;
316 }
317}
318
Hiroshi Yamauchif38ea802013-08-27 13:04:26 -0700319static void System_arraycopyCharUnchecked(JNIEnv* env, jclass, jobject javaSrc, jint srcPos, jobject javaDst, jint dstPos, jint length) {
Ian Rogers1eb512d2013-10-18 15:42:20 -0700320 ScopedFastNativeObjectAccess soa(env);
Hiroshi Yamauchif38ea802013-08-27 13:04:26 -0700321 DCHECK(javaSrc != NULL);
322 DCHECK(javaDst != NULL);
323 mirror::Object* srcObject = soa.Decode<mirror::Object*>(javaSrc);
324 mirror::Object* dstObject = soa.Decode<mirror::Object*>(javaDst);
325 DCHECK(srcObject->IsArrayInstance());
326 DCHECK(dstObject->IsArrayInstance());
327 mirror::Array* srcArray = srcObject->AsArray();
328 mirror::Array* dstArray = dstObject->AsArray();
329 DCHECK(srcPos >= 0 && dstPos >= 0 && length >= 0 &&
330 srcPos + length <= srcArray->GetLength() && dstPos + length <= dstArray->GetLength());
331 DCHECK_EQ(srcArray->GetClass()->GetComponentType(), dstArray->GetClass()->GetComponentType());
332 DCHECK(srcArray->GetClass()->GetComponentType()->IsPrimitive());
333 DCHECK(dstArray->GetClass()->GetComponentType()->IsPrimitive());
334 DCHECK_EQ(srcArray->GetClass()->GetComponentSize(), static_cast<size_t>(2));
335 DCHECK_EQ(dstArray->GetClass()->GetComponentSize(), static_cast<size_t>(2));
336 uint8_t* dstBytes = reinterpret_cast<uint8_t*>(dstArray->GetRawData(2));
337 const uint8_t* srcBytes = reinterpret_cast<const uint8_t*>(srcArray->GetRawData(2));
338 move16(dstBytes + dstPos * 2, srcBytes + srcPos * 2, length * 2);
339}
340
Elliott Hughes0512f022012-03-15 22:10:52 -0700341static jint System_identityHashCode(JNIEnv* env, jclass, jobject javaObject) {
Ian Rogers1eb512d2013-10-18 15:42:20 -0700342 ScopedFastNativeObjectAccess soa(env);
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800343 mirror::Object* o = soa.Decode<mirror::Object*>(javaObject);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700344 return static_cast<jint>(o->IdentityHashCode());
Elliott Hughesbf86d042011-08-31 17:53:14 -0700345}
346
Elliott Hughes0512f022012-03-15 22:10:52 -0700347static JNINativeMethod gMethods[] = {
Ian Rogers1eb512d2013-10-18 15:42:20 -0700348 NATIVE_METHOD(System, arraycopy, "!(Ljava/lang/Object;ILjava/lang/Object;II)V"),
349 NATIVE_METHOD(System, arraycopyCharUnchecked, "!([CI[CII)V"),
350 NATIVE_METHOD(System, identityHashCode, "!(Ljava/lang/Object;)I"),
Elliott Hughesbf86d042011-08-31 17:53:14 -0700351};
352
Elliott Hughesbf86d042011-08-31 17:53:14 -0700353void register_java_lang_System(JNIEnv* env) {
Elliott Hugheseac76672012-05-24 21:56:51 -0700354 REGISTER_NATIVE_METHODS("java/lang/System");
Elliott Hughesbf86d042011-08-31 17:53:14 -0700355}
356
357} // namespace art