java_lang_System.cc revision 81aa5b312a843faf8f20e777cb49b2e5d278df74
1bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes/*
2bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes * Copyright (C) 2008 The Android Open Source Project
3bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes *
4bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes * Licensed under the Apache License, Version 2.0 (the "License");
5bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes * you may not use this file except in compliance with the License.
6bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes * You may obtain a copy of the License at
7bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes *
8bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes *      http://www.apache.org/licenses/LICENSE-2.0
9bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes *
10bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes * Unless required by applicable law or agreed to in writing, software
11bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes * distributed under the License is distributed on an "AS IS" BASIS,
12bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes * See the License for the specific language governing permissions and
14bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes * limitations under the License.
15bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes */
16bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes
17bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes#include "jni_internal.h"
18bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes#include "object.h"
19bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes
20bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes#include "JniConstants.h" // Last to avoid problems with LOG redefinition.
21bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes
22bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes/*
23bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes * We make guarantees about the atomicity of accesses to primitive
24bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes * variables.  These guarantees also apply to elements of arrays.
25bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes * In particular, 8-bit, 16-bit, and 32-bit accesses must be atomic and
26bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes * must not cause "word tearing".  Accesses to 64-bit array elements must
27bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes * either be atomic or treated as two 32-bit operations.  References are
28bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes * always read and written atomically, regardless of the number of bits
29bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes * used to represent them.
30bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes *
31bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes * We can't rely on standard libc functions like memcpy(3) and memmove(3)
32bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes * in our implementation of System.arraycopy, because they may copy
33bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes * byte-by-byte (either for the full run or for "unaligned" parts at the
34bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes * start or end).  We need to use functions that guarantee 16-bit or 32-bit
35bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes * atomicity as appropriate.
36bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes *
37bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes * System.arraycopy() is heavily used, so having an efficient implementation
38bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes * is important.  The bionic libc provides a platform-optimized memory move
39bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes * function that should be used when possible.  If it's not available,
40bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes * the trivial "reference implementation" versions below can be used until
41bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes * a proper version can be written.
42bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes *
43bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes * For these functions, The caller must guarantee that dst/src are aligned
44bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes * appropriately for the element type, and that n is a multiple of the
45bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes * element size.
46bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes */
47bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes#ifdef __BIONIC__
48bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes#define HAVE_MEMMOVE_WORDS
49bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes#endif
50bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes
51bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes#ifdef HAVE_MEMMOVE_WORDS
52bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughesextern "C" void _memmove_words(void* dst, const void* src, size_t n);
53bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes#define move16 _memmove_words
54bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes#define move32 _memmove_words
55bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes#else
56bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughesstatic void move16(void* dst, const void* src, size_t n) {
57cc607471d301e468ac0d84deacd1f60667331f67Elliott Hughes  DCHECK_EQ((((uintptr_t) dst | (uintptr_t) src | n) & 0x01), 0U);
58bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes
59bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  uint16_t* d = reinterpret_cast<uint16_t*>(dst);
60bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  const uint16_t* s = reinterpret_cast<const uint16_t*>(src);
61bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes
62bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  n /= sizeof(uint16_t);
63bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes
64bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  if (d < s) {
65bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes    // Copy forwards.
66bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes    while (n--) {
67bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes      *d++ = *s++;
68bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes    }
69bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  } else {
70bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes    // Copy backwards.
71bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes    d += n;
72bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes    s += n;
73bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes    while (n--) {
74bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes      *--d = *--s;
75bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes    }
76bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  }
77bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes}
78bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes
79bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughesstatic void move32(void* dst, const void* src, size_t n) {
80cc607471d301e468ac0d84deacd1f60667331f67Elliott Hughes  DCHECK_EQ((((uintptr_t) dst | (uintptr_t) src | n) & 0x03), 0U);
81bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes
82bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  uint32_t* d = reinterpret_cast<uint32_t*>(dst);
83bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  const uint32_t* s = reinterpret_cast<const uint32_t*>(src);
84bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes
85bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  n /= sizeof(uint32_t);
86bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes
87bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  if (d < s) {
88bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes    // Copy forwards.
89bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes    while (n--) {
90bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes      *d++ = *s++;
91bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes    }
92bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  } else {
93bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes    // Copy backwards.
94bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes    d += n;
95bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes    s += n;
96bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes    while (n--) {
97bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes      *--d = *--s;
98bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes    }
99bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  }
100bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes}
101bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes#endif // HAVE_MEMMOVE_WORDS
102bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes
103bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughesnamespace art {
104bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes
105bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughesnamespace {
106bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes
107bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughesvoid ThrowArrayStoreException_NotAnArray(const char* identifier, Object* array) {
10854e7df1896a4066cbb9fe6f72249829f0b8c49c6Elliott Hughes  std::string actualType(PrettyTypeOf(array));
1095cb5ad27944efb08d4556b3c0d362302e37e832bElliott Hughes  Thread::Current()->ThrowNewExceptionF("Ljava/lang/ArrayStoreException;",
11081aa5b312a843faf8f20e777cb49b2e5d278df74Elliott Hughes      "%s of type %s is not an array", identifier, actualType.c_str());
111bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes}
112bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes
113bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughesvoid System_arraycopy(JNIEnv* env, jclass, jobject javaSrc, jint srcPos, jobject javaDst, jint dstPos, jint length) {
114b82b6878fb000d4731063b1bf15c39ff7c50b61fBrian Carlstrom  ScopedThreadStateChange tsc(Thread::Current(), Thread::kRunnable);
115bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  Thread* self = Thread::Current();
116bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes
117bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  // Null pointer checks.
118bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  if (javaSrc == NULL) {
119bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes    self->ThrowNewException("Ljava/lang/NullPointerException;", "src == null");
120bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes    return;
121bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  }
122bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  if (javaDst == NULL) {
123bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes    self->ThrowNewException("Ljava/lang/NullPointerException;", "dst == null");
124bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes    return;
125bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  }
126bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes
127bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  // Make sure source and destination are both arrays.
128bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  Object* srcObject = Decode<Object*>(env, javaSrc);
129bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  Object* dstObject = Decode<Object*>(env, javaDst);
130bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  if (!srcObject->IsArrayInstance()) {
13181aa5b312a843faf8f20e777cb49b2e5d278df74Elliott Hughes    ThrowArrayStoreException_NotAnArray("source", srcObject);
132bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes    return;
133bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  }
134bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  if (!dstObject->IsArrayInstance()) {
13581aa5b312a843faf8f20e777cb49b2e5d278df74Elliott Hughes    ThrowArrayStoreException_NotAnArray("destination", dstObject);
136bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes    return;
137bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  }
138bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  Array* srcArray = srcObject->AsArray();
139bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  Array* dstArray = dstObject->AsArray();
140bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  Class* srcComponentType = srcArray->GetClass()->GetComponentType();
141bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  Class* dstComponentType = dstArray->GetClass()->GetComponentType();
142bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes
143bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  // Bounds checking.
144bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  if (srcPos < 0 || dstPos < 0 || length < 0 || srcPos > srcArray->GetLength() - length || dstPos > dstArray->GetLength() - length) {
1455cb5ad27944efb08d4556b3c0d362302e37e832bElliott Hughes    self->ThrowNewExceptionF("Ljava/lang/ArrayIndexOutOfBoundsException;",
146bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes        "src.length=%d srcPos=%d dst.length=%d dstPos=%d length=%d",
147bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes        srcArray->GetLength(), srcPos, dstArray->GetLength(), dstPos, length);
148bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes    return;
149bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  }
150bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes
151bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  uint8_t* dstBytes = reinterpret_cast<uint8_t*>(dstArray->GetRawData());
152bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  const uint8_t* srcBytes = reinterpret_cast<const uint8_t*>(srcArray->GetRawData());
153bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes
154bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  // Handle primitive arrays.
155bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  if (srcComponentType->IsPrimitive() || dstComponentType->IsPrimitive()) {
156bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes    // If one of the arrays holds a primitive type the other array must hold the exact same type.
157bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes    if (srcComponentType->IsPrimitive() != dstComponentType->IsPrimitive() || srcComponentType != dstComponentType) {
15854e7df1896a4066cbb9fe6f72249829f0b8c49c6Elliott Hughes      std::string srcType(PrettyTypeOf(srcArray));
15954e7df1896a4066cbb9fe6f72249829f0b8c49c6Elliott Hughes      std::string dstType(PrettyTypeOf(dstArray));
1605cb5ad27944efb08d4556b3c0d362302e37e832bElliott Hughes      self->ThrowNewExceptionF("Ljava/lang/ArrayStoreException;",
161bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes          "Incompatible types: src=%s, dst=%s", srcType.c_str(), dstType.c_str());
162bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes      return;
163bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes    }
164bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes
165bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes    switch (srcArray->GetClass()->GetComponentSize()) {
166bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes    case 1:
167bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes      memmove(dstBytes + dstPos, srcBytes + srcPos, length);
168bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes      break;
169bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes    case 2:
170bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes      move16(dstBytes + dstPos * 2, srcBytes + srcPos * 2, length * 2);
171bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes      break;
172bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes    case 4:
173bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes      move32(dstBytes + dstPos * 4, srcBytes + srcPos * 4, length * 4);
174bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes      break;
175bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes    case 8:
176bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes      // We don't need to guarantee atomicity of the entire 64-bit word.
177bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes      move32(dstBytes + dstPos * 8, srcBytes + srcPos * 8, length * 8);
178bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes      break;
179bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes    default:
18054e7df1896a4066cbb9fe6f72249829f0b8c49c6Elliott Hughes      LOG(FATAL) << "Unknown primitive array type: " << PrettyTypeOf(srcArray);
181bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes    }
182bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes
183bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes    return;
184bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  }
185bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes
186bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  // Neither class is primitive. Are the types trivially compatible?
1875b8e4c810a97c9dc417142b8c6e07871ae15c797Brian Carlstrom  const size_t width = sizeof(Object*);
188ab3530dce2119432ce076e2499743cc7ee358e67Elliott Hughes  if (dstArray == srcArray || dstComponentType->IsAssignableFrom(srcComponentType)) {
189bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes    // Yes. Bulk copy.
190b6db9d29038a0e8dea8a399b155bd60448ec5e97Brian Carlstrom    COMPILE_ASSERT(sizeof(width) == sizeof(uint32_t), move32_assumes_Object_references_are_32_bit);
191bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes    move32(dstBytes + dstPos * width, srcBytes + srcPos * width, length * width);
1925d76c435082332ef79a22962386fa92a0870e378Ian Rogers    Heap::WriteBarrierArray(dstArray, dstPos, length);
193bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes    return;
194bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  }
195bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes
196ab3530dce2119432ce076e2499743cc7ee358e67Elliott Hughes  // The arrays are not trivially compatible. However, we may still be able to copy some or all of
197ab3530dce2119432ce076e2499743cc7ee358e67Elliott Hughes  // the elements if the source objects are compatible (for example, copying an Object[] to
198ab3530dce2119432ce076e2499743cc7ee358e67Elliott Hughes  // String[], the Objects being copied might actually be Strings).
199ab3530dce2119432ce076e2499743cc7ee358e67Elliott Hughes  // We can't do a bulk move because that would introduce a check-use race condition, so we copy
200ab3530dce2119432ce076e2499743cc7ee358e67Elliott Hughes  // elements one by one.
201bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes
202ab3530dce2119432ce076e2499743cc7ee358e67Elliott Hughes  // We already dealt with overlapping copies, so we don't need to cope with that case below.
203ab3530dce2119432ce076e2499743cc7ee358e67Elliott Hughes  CHECK_NE(dstArray, srcArray);
204bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes
205ab3530dce2119432ce076e2499743cc7ee358e67Elliott Hughes  Object* const * srcObjects = reinterpret_cast<Object* const *>(srcBytes + srcPos * width);
206ab3530dce2119432ce076e2499743cc7ee358e67Elliott Hughes  Object** dstObjects = reinterpret_cast<Object**>(dstBytes + dstPos * width);
207ab3530dce2119432ce076e2499743cc7ee358e67Elliott Hughes  Class* dstClass = dstArray->GetClass()->GetComponentType();
208ab3530dce2119432ce076e2499743cc7ee358e67Elliott Hughes
209ab3530dce2119432ce076e2499743cc7ee358e67Elliott Hughes  // We want to avoid redundant IsAssignableFrom checks where possible, so we cache a class that
210ab3530dce2119432ce076e2499743cc7ee358e67Elliott Hughes  // we know is assignable to the destination array's component type.
211ab3530dce2119432ce076e2499743cc7ee358e67Elliott Hughes  Class* lastAssignableElementClass = dstClass;
212ab3530dce2119432ce076e2499743cc7ee358e67Elliott Hughes
213025c5de6aab0719c77a19d62b2df80291ec225e6Elliott Hughes  Object* o = NULL;
214ab3530dce2119432ce076e2499743cc7ee358e67Elliott Hughes  int i = 0;
215ab3530dce2119432ce076e2499743cc7ee358e67Elliott Hughes  for (; i < length; ++i) {
216025c5de6aab0719c77a19d62b2df80291ec225e6Elliott Hughes    o = srcObjects[i];
217ab3530dce2119432ce076e2499743cc7ee358e67Elliott Hughes    if (o != NULL) {
218ab3530dce2119432ce076e2499743cc7ee358e67Elliott Hughes      Class* oClass = o->GetClass();
219ab3530dce2119432ce076e2499743cc7ee358e67Elliott Hughes      if (lastAssignableElementClass == oClass) {
220ab3530dce2119432ce076e2499743cc7ee358e67Elliott Hughes        dstObjects[i] = o;
221ab3530dce2119432ce076e2499743cc7ee358e67Elliott Hughes      } else if (dstClass->IsAssignableFrom(oClass)) {
222ab3530dce2119432ce076e2499743cc7ee358e67Elliott Hughes        lastAssignableElementClass = oClass;
223ab3530dce2119432ce076e2499743cc7ee358e67Elliott Hughes        dstObjects[i] = o;
224ab3530dce2119432ce076e2499743cc7ee358e67Elliott Hughes      } else {
225ab3530dce2119432ce076e2499743cc7ee358e67Elliott Hughes        // Can't put this element into the array.
226ab3530dce2119432ce076e2499743cc7ee358e67Elliott Hughes        break;
227ab3530dce2119432ce076e2499743cc7ee358e67Elliott Hughes      }
228ab3530dce2119432ce076e2499743cc7ee358e67Elliott Hughes    } else {
229ab3530dce2119432ce076e2499743cc7ee358e67Elliott Hughes      dstObjects[i] = NULL;
230bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes    }
231bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  }
232bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes
2335d76c435082332ef79a22962386fa92a0870e378Ian Rogers  Heap::WriteBarrierArray(dstArray, dstPos, length);
234ab3530dce2119432ce076e2499743cc7ee358e67Elliott Hughes  if (i != length) {
235025c5de6aab0719c77a19d62b2df80291ec225e6Elliott Hughes    std::string actualSrcType(PrettyTypeOf(o));
23654e7df1896a4066cbb9fe6f72249829f0b8c49c6Elliott Hughes    std::string dstType(PrettyTypeOf(dstArray));
2375cb5ad27944efb08d4556b3c0d362302e37e832bElliott Hughes    self->ThrowNewExceptionF("Ljava/lang/ArrayStoreException;",
238bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes        "source[%d] of type %s cannot be stored in destination array of type %s",
239ab3530dce2119432ce076e2499743cc7ee358e67Elliott Hughes        srcPos + i, actualSrcType.c_str(), dstType.c_str());
240bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes    return;
241bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  }
242bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes}
243bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes
244bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughesjint System_identityHashCode(JNIEnv* env, jclass, jobject javaObject) {
245bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  Object* o = Decode<Object*>(env, javaObject);
246bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  return static_cast<jint>(reinterpret_cast<uintptr_t>(o));
247bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes}
248bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes
249bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott HughesJNINativeMethod gMethods[] = {
250bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  NATIVE_METHOD(System, arraycopy, "(Ljava/lang/Object;ILjava/lang/Object;II)V"),
251bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  NATIVE_METHOD(System, identityHashCode, "(Ljava/lang/Object;)I"),
252bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes};
253bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes
254bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes}  // namespace
255bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes
256bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughesvoid register_java_lang_System(JNIEnv* env) {
257bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes    jniRegisterNativeMethods(env, "java/lang/System", gMethods, NELEM(gMethods));
258bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes}
259bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes
260bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes}  // namespace art
261