java_lang_System.cc revision 54e7df1896a4066cbb9fe6f72249829f0b8c49c6
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) {
57bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  DCHECK((((uintptr_t) dst | (uintptr_t) src | n) & 0x01) == 0);
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) {
80bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  DCHECK((((uintptr_t) dst | (uintptr_t) src | n) & 0x03) == 0);
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));
109bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  Thread::Current()->ThrowNewException("Ljava/lang/ArrayStoreException;", "%s is not an array: %s", identifier, actualType.c_str());
110bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes}
111bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes
112bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughesvoid System_arraycopy(JNIEnv* env, jclass, jobject javaSrc, jint srcPos, jobject javaDst, jint dstPos, jint length) {
113bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  Thread* self = Thread::Current();
114bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes
115bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  // Null pointer checks.
116bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  if (javaSrc == NULL) {
117bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes    self->ThrowNewException("Ljava/lang/NullPointerException;", "src == null");
118bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes    return;
119bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  }
120bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  if (javaDst == NULL) {
121bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes    self->ThrowNewException("Ljava/lang/NullPointerException;", "dst == null");
122bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes    return;
123bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  }
124bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes
125bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  // Make sure source and destination are both arrays.
126bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  Object* srcObject = Decode<Object*>(env, javaSrc);
127bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  Object* dstObject = Decode<Object*>(env, javaDst);
128bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  if (!srcObject->IsArrayInstance()) {
129bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes    ThrowArrayStoreException_NotAnArray("src", srcObject);
130bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes    return;
131bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  }
132bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  if (!dstObject->IsArrayInstance()) {
133bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes    ThrowArrayStoreException_NotAnArray("dst", dstObject);
134bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes    return;
135bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  }
136bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  Array* srcArray = srcObject->AsArray();
137bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  Array* dstArray = dstObject->AsArray();
138bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  Class* srcComponentType = srcArray->GetClass()->GetComponentType();
139bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  Class* dstComponentType = dstArray->GetClass()->GetComponentType();
140bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes
141bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  // Bounds checking.
142bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  if (srcPos < 0 || dstPos < 0 || length < 0 || srcPos > srcArray->GetLength() - length || dstPos > dstArray->GetLength() - length) {
143bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes    self->ThrowNewException("Ljava/lang/ArrayIndexOutOfBoundsException;",
144bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes        "src.length=%d srcPos=%d dst.length=%d dstPos=%d length=%d",
145bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes        srcArray->GetLength(), srcPos, dstArray->GetLength(), dstPos, length);
146bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes    return;
147bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  }
148bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes
149bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  uint8_t* dstBytes = reinterpret_cast<uint8_t*>(dstArray->GetRawData());
150bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  const uint8_t* srcBytes = reinterpret_cast<const uint8_t*>(srcArray->GetRawData());
151bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes
152bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  // Handle primitive arrays.
153bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  if (srcComponentType->IsPrimitive() || dstComponentType->IsPrimitive()) {
154bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes    // If one of the arrays holds a primitive type the other array must hold the exact same type.
155bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes    if (srcComponentType->IsPrimitive() != dstComponentType->IsPrimitive() || srcComponentType != dstComponentType) {
15654e7df1896a4066cbb9fe6f72249829f0b8c49c6Elliott Hughes      std::string srcType(PrettyTypeOf(srcArray));
15754e7df1896a4066cbb9fe6f72249829f0b8c49c6Elliott Hughes      std::string dstType(PrettyTypeOf(dstArray));
158bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes      self->ThrowNewException("Ljava/lang/ArrayStoreException;",
159bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes          "Incompatible types: src=%s, dst=%s", srcType.c_str(), dstType.c_str());
160bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes      return;
161bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes    }
162bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes
163bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes    switch (srcArray->GetClass()->GetComponentSize()) {
164bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes    case 1:
165bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes      memmove(dstBytes + dstPos, srcBytes + srcPos, length);
166bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes      break;
167bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes    case 2:
168bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes      move16(dstBytes + dstPos * 2, srcBytes + srcPos * 2, length * 2);
169bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes      break;
170bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes    case 4:
171bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes      move32(dstBytes + dstPos * 4, srcBytes + srcPos * 4, length * 4);
172bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes      break;
173bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes    case 8:
174bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes      // We don't need to guarantee atomicity of the entire 64-bit word.
175bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes      move32(dstBytes + dstPos * 8, srcBytes + srcPos * 8, length * 8);
176bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes      break;
177bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes    default:
17854e7df1896a4066cbb9fe6f72249829f0b8c49c6Elliott Hughes      LOG(FATAL) << "Unknown primitive array type: " << PrettyTypeOf(srcArray);
179bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes    }
180bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes
181bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes    return;
182bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  }
183bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes
184bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  // Neither class is primitive. Are the types trivially compatible?
185bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  const int width = sizeof(Object*);
1860cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers  bool sameDimensions = srcArray->GetClass()->GetArrayRank() == dstArray->GetClass()->GetArrayRank();
187bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  if (sameDimensions && srcComponentType->InstanceOf(dstComponentType)) {
188bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes    // Yes. Bulk copy.
189bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes    move32(dstBytes + dstPos * width, srcBytes + srcPos * width, length * width);
1903a4f8df8f75cbb9495b84a96c60e12fcce65ccf9Elliott Hughes    Heap::WriteBarrier(dstArray);
191bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes    return;
192bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  }
193bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes
194bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  // The arrays are not trivially compatible.  However, we
195bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  // may still be able to do this if the destination object is
196bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  // compatible (e.g. copy Object[] to String[], but the Object
197bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  // being copied is actually a String).  We need to copy elements
198bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  // one by one until something goes wrong.
199bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  //
200bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  // Because of overlapping moves, what we really want to do
201bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  // is compare the types and count up how many we can move,
202bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  // then call move32() to shift the actual data.  If we just
203bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  // start from the front we could do a smear rather than a move.
204bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes
205bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  // TODO: this idea is flawed. a malicious caller could exploit the check-use
206bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  // race by modifying the source array after we check but before we copy,
207bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  // and cause us to copy incompatible elements.
208bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes
2090cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers  Object* const * srcObj = reinterpret_cast<Object* const *>(srcBytes + srcPos * width);
210bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  Class* dstClass = dstArray->GetClass();
211bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes
212bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  Class* initialElementClass = NULL;
213bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  if (length > 0 && srcObj[0] != NULL) {
214bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes    initialElementClass = srcObj[0]->GetClass();
2150f4c41d75c821162184501cd4b510a93f6eb580fElliott Hughes    if (!Class::CanPutArrayElement(initialElementClass, dstClass)) {
216bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes      initialElementClass = NULL;
217bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes    }
218bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  }
219bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes
220bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  int copyCount;
221bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  for (copyCount = 0; copyCount < length; copyCount++) {
2220f4c41d75c821162184501cd4b510a93f6eb580fElliott Hughes    if (srcObj[copyCount] != NULL && srcObj[copyCount]->GetClass() != initialElementClass && !Class::CanPutArrayElement(srcObj[copyCount]->GetClass(), dstClass)) {
223bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes      // Can't put this element into the array.
224bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes      // We'll copy up to this point, then throw.
225bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes      break;
226bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes    }
227bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  }
228bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes
229bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  move32(dstBytes + dstPos * width, srcBytes + srcPos * width, copyCount * width);
2303a4f8df8f75cbb9495b84a96c60e12fcce65ccf9Elliott Hughes  Heap::WriteBarrier(dstArray);
231bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  if (copyCount != length) {
23254e7df1896a4066cbb9fe6f72249829f0b8c49c6Elliott Hughes    std::string actualSrcType(PrettyTypeOf(srcObj[copyCount]));
23354e7df1896a4066cbb9fe6f72249829f0b8c49c6Elliott Hughes    std::string dstType(PrettyTypeOf(dstArray));
234bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes    self->ThrowNewException("Ljava/lang/ArrayStoreException;",
235bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes        "source[%d] of type %s cannot be stored in destination array of type %s",
236bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes        srcPos + copyCount, actualSrcType.c_str(), dstType.c_str());
237bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes    return;
238bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  }
239bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes}
240bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes
241bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughesjint System_identityHashCode(JNIEnv* env, jclass, jobject javaObject) {
242bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  Object* o = Decode<Object*>(env, javaObject);
243bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  return static_cast<jint>(reinterpret_cast<uintptr_t>(o));
244bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes}
245bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes
246bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott HughesJNINativeMethod gMethods[] = {
247bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  NATIVE_METHOD(System, arraycopy, "(Ljava/lang/Object;ILjava/lang/Object;II)V"),
248bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  NATIVE_METHOD(System, identityHashCode, "(Ljava/lang/Object;)I"),
249bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes};
250bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes
251bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes}  // namespace
252bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes
253bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughesvoid register_java_lang_System(JNIEnv* env) {
254bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes    jniRegisterNativeMethods(env, "java/lang/System", gMethods, NELEM(gMethods));
255bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes}
256bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes
257bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes}  // namespace art
258