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
1762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers#include "common_throws.h"
181d54e73444e017d3a65234e0f193846f3e27472bIan Rogers#include "gc/accounting/card_table-inl.h"
19bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes#include "jni_internal.h"
202dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/array.h"
212dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/class.h"
222dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/class-inl.h"
232dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/object-inl.h"
24693ff61274cd2c9b8eb7e68c370f84a911b8ca52Ian Rogers#include "mirror/object_array-inl.h"
2500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers#include "scoped_thread_state_change.h"
26bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes
27bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes/*
28bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes * We make guarantees about the atomicity of accesses to primitive
29bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes * variables.  These guarantees also apply to elements of arrays.
30bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes * In particular, 8-bit, 16-bit, and 32-bit accesses must be atomic and
31bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes * must not cause "word tearing".  Accesses to 64-bit array elements must
32bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes * either be atomic or treated as two 32-bit operations.  References are
33bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes * always read and written atomically, regardless of the number of bits
34bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes * used to represent them.
35bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes *
36bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes * We can't rely on standard libc functions like memcpy(3) and memmove(3)
37bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes * in our implementation of System.arraycopy, because they may copy
38bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes * byte-by-byte (either for the full run or for "unaligned" parts at the
39bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes * start or end).  We need to use functions that guarantee 16-bit or 32-bit
40bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes * atomicity as appropriate.
41bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes *
42bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes * System.arraycopy() is heavily used, so having an efficient implementation
43bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes * is important.  The bionic libc provides a platform-optimized memory move
44bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes * function that should be used when possible.  If it's not available,
45bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes * the trivial "reference implementation" versions below can be used until
46bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes * a proper version can be written.
47bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes *
48bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes * For these functions, The caller must guarantee that dst/src are aligned
49bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes * appropriately for the element type, and that n is a multiple of the
50bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes * element size.
51bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes */
52bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes
536324e2174e60e951f4e7dab22dc65bafd730e097Elliott Hughes/*
546324e2174e60e951f4e7dab22dc65bafd730e097Elliott Hughes * Works like memmove(), except:
556324e2174e60e951f4e7dab22dc65bafd730e097Elliott Hughes * - if all arguments are at least 32-bit aligned, we guarantee that we
566324e2174e60e951f4e7dab22dc65bafd730e097Elliott Hughes *   will use operations that preserve atomicity of 32-bit values
576324e2174e60e951f4e7dab22dc65bafd730e097Elliott Hughes * - if not, we guarantee atomicity of 16-bit values
586324e2174e60e951f4e7dab22dc65bafd730e097Elliott Hughes *
596324e2174e60e951f4e7dab22dc65bafd730e097Elliott Hughes * If all three arguments are not at least 16-bit aligned, the behavior
606324e2174e60e951f4e7dab22dc65bafd730e097Elliott Hughes * of this function is undefined.  (We could remove this restriction by
616324e2174e60e951f4e7dab22dc65bafd730e097Elliott Hughes * testing for unaligned values and punting to memmove(), but that's
626324e2174e60e951f4e7dab22dc65bafd730e097Elliott Hughes * not currently useful.)
636324e2174e60e951f4e7dab22dc65bafd730e097Elliott Hughes *
646324e2174e60e951f4e7dab22dc65bafd730e097Elliott Hughes * TODO: add loop for 64-bit alignment
656324e2174e60e951f4e7dab22dc65bafd730e097Elliott Hughes * TODO: use __builtin_prefetch
666324e2174e60e951f4e7dab22dc65bafd730e097Elliott Hughes * TODO: write ARM/MIPS/x86 optimized versions
676324e2174e60e951f4e7dab22dc65bafd730e097Elliott Hughes */
686324e2174e60e951f4e7dab22dc65bafd730e097Elliott Hughesvoid MemmoveWords(void* dst, const void* src, size_t n) {
696324e2174e60e951f4e7dab22dc65bafd730e097Elliott Hughes  DCHECK_EQ((((uintptr_t) dst | (uintptr_t) src | n) & 0x01), 0U);
70bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes
716324e2174e60e951f4e7dab22dc65bafd730e097Elliott Hughes  char* d = reinterpret_cast<char*>(dst);
726324e2174e60e951f4e7dab22dc65bafd730e097Elliott Hughes  const char* s = reinterpret_cast<const char*>(src);
736324e2174e60e951f4e7dab22dc65bafd730e097Elliott Hughes  size_t copyCount;
74bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes
756324e2174e60e951f4e7dab22dc65bafd730e097Elliott Hughes  // If the source and destination pointers are the same, this is
766324e2174e60e951f4e7dab22dc65bafd730e097Elliott Hughes  // an expensive no-op.  Testing for an empty move now allows us
776324e2174e60e951f4e7dab22dc65bafd730e097Elliott Hughes  // to skip a check later.
786324e2174e60e951f4e7dab22dc65bafd730e097Elliott Hughes  if (n == 0 || d == s) {
796324e2174e60e951f4e7dab22dc65bafd730e097Elliott Hughes    return;
80bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  }
81bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes
826324e2174e60e951f4e7dab22dc65bafd730e097Elliott Hughes  // Determine if the source and destination buffers will overlap if
836324e2174e60e951f4e7dab22dc65bafd730e097Elliott Hughes  // we copy data forward (i.e. *dst++ = *src++).
846324e2174e60e951f4e7dab22dc65bafd730e097Elliott Hughes  //
856324e2174e60e951f4e7dab22dc65bafd730e097Elliott Hughes  // It's okay if the destination buffer starts before the source and
866324e2174e60e951f4e7dab22dc65bafd730e097Elliott Hughes  // there is some overlap, because the reader is always ahead of the
876324e2174e60e951f4e7dab22dc65bafd730e097Elliott Hughes  // writer.
886324e2174e60e951f4e7dab22dc65bafd730e097Elliott Hughes  if (LIKELY((d < s) || ((size_t)(d - s) >= n))) {
896324e2174e60e951f4e7dab22dc65bafd730e097Elliott Hughes    // Copy forward.  We prefer 32-bit loads and stores even for 16-bit
906324e2174e60e951f4e7dab22dc65bafd730e097Elliott Hughes    // data, so sort that out.
916324e2174e60e951f4e7dab22dc65bafd730e097Elliott Hughes    if (((reinterpret_cast<uintptr_t>(d) | reinterpret_cast<uintptr_t>(s)) & 0x03) != 0) {
926324e2174e60e951f4e7dab22dc65bafd730e097Elliott Hughes      // Not 32-bit aligned.  Two possibilities:
936324e2174e60e951f4e7dab22dc65bafd730e097Elliott Hughes      // (1) Congruent, we can align to 32-bit by copying one 16-bit val
946324e2174e60e951f4e7dab22dc65bafd730e097Elliott Hughes      // (2) Non-congruent, we can do one of:
956324e2174e60e951f4e7dab22dc65bafd730e097Elliott Hughes      //   a. copy whole buffer as a series of 16-bit values
966324e2174e60e951f4e7dab22dc65bafd730e097Elliott Hughes      //   b. load/store 32 bits, using shifts to ensure alignment
976324e2174e60e951f4e7dab22dc65bafd730e097Elliott Hughes      //   c. just copy the as 32-bit values and assume the CPU
986324e2174e60e951f4e7dab22dc65bafd730e097Elliott Hughes      //      will do a reasonable job
996324e2174e60e951f4e7dab22dc65bafd730e097Elliott Hughes      //
1006324e2174e60e951f4e7dab22dc65bafd730e097Elliott Hughes      // We're currently using (a), which is suboptimal.
1016324e2174e60e951f4e7dab22dc65bafd730e097Elliott Hughes      if (((reinterpret_cast<uintptr_t>(d) ^ reinterpret_cast<uintptr_t>(s)) & 0x03) != 0) {
1026324e2174e60e951f4e7dab22dc65bafd730e097Elliott Hughes        copyCount = n;
1036324e2174e60e951f4e7dab22dc65bafd730e097Elliott Hughes      } else {
1046324e2174e60e951f4e7dab22dc65bafd730e097Elliott Hughes        copyCount = 2;
1056324e2174e60e951f4e7dab22dc65bafd730e097Elliott Hughes      }
1066324e2174e60e951f4e7dab22dc65bafd730e097Elliott Hughes      n -= copyCount;
1076324e2174e60e951f4e7dab22dc65bafd730e097Elliott Hughes      copyCount /= sizeof(uint16_t);
108bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes
1096324e2174e60e951f4e7dab22dc65bafd730e097Elliott Hughes      while (copyCount--) {
1106324e2174e60e951f4e7dab22dc65bafd730e097Elliott Hughes        *reinterpret_cast<uint16_t*>(d) = *reinterpret_cast<const uint16_t*>(s);
1116324e2174e60e951f4e7dab22dc65bafd730e097Elliott Hughes        d += sizeof(uint16_t);
1126324e2174e60e951f4e7dab22dc65bafd730e097Elliott Hughes        s += sizeof(uint16_t);
1136324e2174e60e951f4e7dab22dc65bafd730e097Elliott Hughes      }
1146324e2174e60e951f4e7dab22dc65bafd730e097Elliott Hughes    }
115bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes
1166324e2174e60e951f4e7dab22dc65bafd730e097Elliott Hughes    // Copy 32-bit aligned words.
1176324e2174e60e951f4e7dab22dc65bafd730e097Elliott Hughes    copyCount = n / sizeof(uint32_t);
1186324e2174e60e951f4e7dab22dc65bafd730e097Elliott Hughes    while (copyCount--) {
1196324e2174e60e951f4e7dab22dc65bafd730e097Elliott Hughes      *reinterpret_cast<uint32_t*>(d) = *reinterpret_cast<const uint32_t*>(s);
1206324e2174e60e951f4e7dab22dc65bafd730e097Elliott Hughes      d += sizeof(uint32_t);
1216324e2174e60e951f4e7dab22dc65bafd730e097Elliott Hughes      s += sizeof(uint32_t);
1226324e2174e60e951f4e7dab22dc65bafd730e097Elliott Hughes    }
123bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes
1246324e2174e60e951f4e7dab22dc65bafd730e097Elliott Hughes    // Check for leftovers.  Either we finished exactly, or we have one remaining 16-bit chunk.
1256324e2174e60e951f4e7dab22dc65bafd730e097Elliott Hughes    if ((n & 0x02) != 0) {
1262d88862f0752a7a0e65145b088f49dabd49d4284Brian Carlstrom      *reinterpret_cast<uint16_t*>(d) = *reinterpret_cast<const uint16_t*>(s);
127bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes    }
128bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  } else {
1296324e2174e60e951f4e7dab22dc65bafd730e097Elliott Hughes    // Copy backward, starting at the end.
130bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes    d += n;
131bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes    s += n;
1326324e2174e60e951f4e7dab22dc65bafd730e097Elliott Hughes
1336324e2174e60e951f4e7dab22dc65bafd730e097Elliott Hughes    if (((reinterpret_cast<uintptr_t>(d) | reinterpret_cast<uintptr_t>(s)) & 0x03) != 0) {
1346324e2174e60e951f4e7dab22dc65bafd730e097Elliott Hughes      // try for 32-bit alignment.
1356324e2174e60e951f4e7dab22dc65bafd730e097Elliott Hughes      if (((reinterpret_cast<uintptr_t>(d) ^ reinterpret_cast<uintptr_t>(s)) & 0x03) != 0) {
1366324e2174e60e951f4e7dab22dc65bafd730e097Elliott Hughes        copyCount = n;
1376324e2174e60e951f4e7dab22dc65bafd730e097Elliott Hughes      } else {
1386324e2174e60e951f4e7dab22dc65bafd730e097Elliott Hughes        copyCount = 2;
1396324e2174e60e951f4e7dab22dc65bafd730e097Elliott Hughes      }
1406324e2174e60e951f4e7dab22dc65bafd730e097Elliott Hughes      n -= copyCount;
1416324e2174e60e951f4e7dab22dc65bafd730e097Elliott Hughes      copyCount /= sizeof(uint16_t);
1426324e2174e60e951f4e7dab22dc65bafd730e097Elliott Hughes
1436324e2174e60e951f4e7dab22dc65bafd730e097Elliott Hughes      while (copyCount--) {
1446324e2174e60e951f4e7dab22dc65bafd730e097Elliott Hughes        d -= sizeof(uint16_t);
1456324e2174e60e951f4e7dab22dc65bafd730e097Elliott Hughes        s -= sizeof(uint16_t);
1466324e2174e60e951f4e7dab22dc65bafd730e097Elliott Hughes        *reinterpret_cast<uint16_t*>(d) = *reinterpret_cast<const uint16_t*>(s);
1476324e2174e60e951f4e7dab22dc65bafd730e097Elliott Hughes      }
1486324e2174e60e951f4e7dab22dc65bafd730e097Elliott Hughes    }
1496324e2174e60e951f4e7dab22dc65bafd730e097Elliott Hughes
1506324e2174e60e951f4e7dab22dc65bafd730e097Elliott Hughes    // Copy 32-bit aligned words.
1516324e2174e60e951f4e7dab22dc65bafd730e097Elliott Hughes    copyCount = n / sizeof(uint32_t);
1526324e2174e60e951f4e7dab22dc65bafd730e097Elliott Hughes    while (copyCount--) {
1536324e2174e60e951f4e7dab22dc65bafd730e097Elliott Hughes      d -= sizeof(uint32_t);
1546324e2174e60e951f4e7dab22dc65bafd730e097Elliott Hughes      s -= sizeof(uint32_t);
1556324e2174e60e951f4e7dab22dc65bafd730e097Elliott Hughes      *reinterpret_cast<uint32_t*>(d) = *reinterpret_cast<const uint32_t*>(s);
1566324e2174e60e951f4e7dab22dc65bafd730e097Elliott Hughes    }
1576324e2174e60e951f4e7dab22dc65bafd730e097Elliott Hughes
1586324e2174e60e951f4e7dab22dc65bafd730e097Elliott Hughes    // Copy leftovers.
1596324e2174e60e951f4e7dab22dc65bafd730e097Elliott Hughes    if ((n & 0x02) != 0) {
1606324e2174e60e951f4e7dab22dc65bafd730e097Elliott Hughes      d -= sizeof(uint16_t);
1616324e2174e60e951f4e7dab22dc65bafd730e097Elliott Hughes      s -= sizeof(uint16_t);
1626324e2174e60e951f4e7dab22dc65bafd730e097Elliott Hughes      *reinterpret_cast<uint16_t*>(d) = *reinterpret_cast<const uint16_t*>(s);
163bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes    }
164bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  }
165bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes}
1666324e2174e60e951f4e7dab22dc65bafd730e097Elliott Hughes
1676324e2174e60e951f4e7dab22dc65bafd730e097Elliott Hughes#define move16 MemmoveWords
1686324e2174e60e951f4e7dab22dc65bafd730e097Elliott Hughes#define move32 MemmoveWords
169bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes
170bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughesnamespace art {
171bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes
1722dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogersstatic void ThrowArrayStoreException_NotAnArray(const char* identifier, mirror::Object* array)
173b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
17454e7df1896a4066cbb9fe6f72249829f0b8c49c6Elliott Hughes  std::string actualType(PrettyTypeOf(array));
17562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  Thread* self = Thread::Current();
17662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  ThrowLocation throw_location = self->GetCurrentLocationForThrow();
17762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  self->ThrowNewExceptionF(throw_location, "Ljava/lang/ArrayStoreException;",
17862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers                           "%s of type %s is not an array", identifier, actualType.c_str());
179bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes}
180bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes
1810512f02dd6623c0870c11fbf3274d7462f732136Elliott Hughesstatic void System_arraycopy(JNIEnv* env, jclass, jobject javaSrc, jint srcPos, jobject javaDst, jint dstPos, jint length) {
18200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  ScopedObjectAccess soa(env);
183bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes
184bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  // Null pointer checks.
18562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  if (UNLIKELY(javaSrc == NULL)) {
18662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    ThrowNullPointerException(NULL, "src == null");
187bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes    return;
188bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  }
18962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  if (UNLIKELY(javaDst == NULL)) {
19062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    ThrowNullPointerException(NULL, "dst == null");
191bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes    return;
192bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  }
193bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes
194bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  // Make sure source and destination are both arrays.
1952dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers  mirror::Object* srcObject = soa.Decode<mirror::Object*>(javaSrc);
1962dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers  mirror::Object* dstObject = soa.Decode<mirror::Object*>(javaDst);
19762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  if (UNLIKELY(!srcObject->IsArrayInstance())) {
19881aa5b312a843faf8f20e777cb49b2e5d278df74Elliott Hughes    ThrowArrayStoreException_NotAnArray("source", srcObject);
199bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes    return;
200bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  }
20162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  if (UNLIKELY(!dstObject->IsArrayInstance())) {
20281aa5b312a843faf8f20e777cb49b2e5d278df74Elliott Hughes    ThrowArrayStoreException_NotAnArray("destination", dstObject);
203bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes    return;
204bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  }
2052dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers  mirror::Array* srcArray = srcObject->AsArray();
2062dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers  mirror::Array* dstArray = dstObject->AsArray();
2072dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers  mirror::Class* srcComponentType = srcArray->GetClass()->GetComponentType();
2082dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers  mirror::Class* dstComponentType = dstArray->GetClass()->GetComponentType();
209bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes
210bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  // Bounds checking.
21162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  if (UNLIKELY(srcPos < 0 || dstPos < 0 || length < 0 || srcPos > srcArray->GetLength() - length || dstPos > dstArray->GetLength() - length)) {
21262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    ThrowLocation throw_location = soa.Self()->GetCurrentLocationForThrow();
21362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    soa.Self()->ThrowNewExceptionF(throw_location, "Ljava/lang/ArrayIndexOutOfBoundsException;",
21462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers                                   "src.length=%d srcPos=%d dst.length=%d dstPos=%d length=%d",
21562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers                                   srcArray->GetLength(), srcPos, dstArray->GetLength(), dstPos, length);
216bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes    return;
217bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  }
218bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes
219bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  // Handle primitive arrays.
220bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  if (srcComponentType->IsPrimitive() || dstComponentType->IsPrimitive()) {
221bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes    // If one of the arrays holds a primitive type the other array must hold the exact same type.
22262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    if (UNLIKELY(srcComponentType != dstComponentType)) {
22354e7df1896a4066cbb9fe6f72249829f0b8c49c6Elliott Hughes      std::string srcType(PrettyTypeOf(srcArray));
22454e7df1896a4066cbb9fe6f72249829f0b8c49c6Elliott Hughes      std::string dstType(PrettyTypeOf(dstArray));
22562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      ThrowLocation throw_location = soa.Self()->GetCurrentLocationForThrow();
22662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers      soa.Self()->ThrowNewExceptionF(throw_location, "Ljava/lang/ArrayStoreException;",
22762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers                                     "Incompatible types: src=%s, dst=%s",
22862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers                                     srcType.c_str(), dstType.c_str());
229bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes      return;
230bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes    }
231bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes
232a15e67d5ee5aa9615596cee2be42c2b2caf128c6Ian Rogers    size_t width = srcArray->GetClass()->GetComponentSize();
233a15e67d5ee5aa9615596cee2be42c2b2caf128c6Ian Rogers    uint8_t* dstBytes = reinterpret_cast<uint8_t*>(dstArray->GetRawData(width));
234a15e67d5ee5aa9615596cee2be42c2b2caf128c6Ian Rogers    const uint8_t* srcBytes = reinterpret_cast<const uint8_t*>(srcArray->GetRawData(width));
235a15e67d5ee5aa9615596cee2be42c2b2caf128c6Ian Rogers
236a15e67d5ee5aa9615596cee2be42c2b2caf128c6Ian Rogers    switch (width) {
237bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes    case 1:
238bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes      memmove(dstBytes + dstPos, srcBytes + srcPos, length);
239bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes      break;
240bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes    case 2:
241bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes      move16(dstBytes + dstPos * 2, srcBytes + srcPos * 2, length * 2);
242bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes      break;
243bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes    case 4:
244bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes      move32(dstBytes + dstPos * 4, srcBytes + srcPos * 4, length * 4);
245bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes      break;
246bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes    case 8:
247bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes      // We don't need to guarantee atomicity of the entire 64-bit word.
248bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes      move32(dstBytes + dstPos * 8, srcBytes + srcPos * 8, length * 8);
249bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes      break;
250bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes    default:
25154e7df1896a4066cbb9fe6f72249829f0b8c49c6Elliott Hughes      LOG(FATAL) << "Unknown primitive array type: " << PrettyTypeOf(srcArray);
252bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes    }
253bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes
254bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes    return;
255bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  }
256bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes
257bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  // Neither class is primitive. Are the types trivially compatible?
2582dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers  const size_t width = sizeof(mirror::Object*);
259a15e67d5ee5aa9615596cee2be42c2b2caf128c6Ian Rogers  uint8_t* dstBytes = reinterpret_cast<uint8_t*>(dstArray->GetRawData(width));
260a15e67d5ee5aa9615596cee2be42c2b2caf128c6Ian Rogers  const uint8_t* srcBytes = reinterpret_cast<const uint8_t*>(srcArray->GetRawData(width));
261ab3530dce2119432ce076e2499743cc7ee358e67Elliott Hughes  if (dstArray == srcArray || dstComponentType->IsAssignableFrom(srcComponentType)) {
262bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes    // Yes. Bulk copy.
263b6db9d29038a0e8dea8a399b155bd60448ec5e97Brian Carlstrom    COMPILE_ASSERT(sizeof(width) == sizeof(uint32_t), move32_assumes_Object_references_are_32_bit);
264bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes    move32(dstBytes + dstPos * width, srcBytes + srcPos * width, length * width);
265b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes    Runtime::Current()->GetHeap()->WriteBarrierArray(dstArray, dstPos, length);
266bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes    return;
267bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  }
268bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes
269ab3530dce2119432ce076e2499743cc7ee358e67Elliott Hughes  // The arrays are not trivially compatible. However, we may still be able to copy some or all of
270ab3530dce2119432ce076e2499743cc7ee358e67Elliott Hughes  // the elements if the source objects are compatible (for example, copying an Object[] to
271ab3530dce2119432ce076e2499743cc7ee358e67Elliott Hughes  // String[], the Objects being copied might actually be Strings).
272ab3530dce2119432ce076e2499743cc7ee358e67Elliott Hughes  // We can't do a bulk move because that would introduce a check-use race condition, so we copy
273ab3530dce2119432ce076e2499743cc7ee358e67Elliott Hughes  // elements one by one.
274bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes
275ab3530dce2119432ce076e2499743cc7ee358e67Elliott Hughes  // We already dealt with overlapping copies, so we don't need to cope with that case below.
276ab3530dce2119432ce076e2499743cc7ee358e67Elliott Hughes  CHECK_NE(dstArray, srcArray);
277bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes
2782dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers  mirror::Object* const * srcObjects =
2792dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers      reinterpret_cast<mirror::Object* const *>(srcBytes + srcPos * width);
2802dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers  mirror::Object** dstObjects = reinterpret_cast<mirror::Object**>(dstBytes + dstPos * width);
2812dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers  mirror::Class* dstClass = dstArray->GetClass()->GetComponentType();
282ab3530dce2119432ce076e2499743cc7ee358e67Elliott Hughes
283ab3530dce2119432ce076e2499743cc7ee358e67Elliott Hughes  // We want to avoid redundant IsAssignableFrom checks where possible, so we cache a class that
284ab3530dce2119432ce076e2499743cc7ee358e67Elliott Hughes  // we know is assignable to the destination array's component type.
2852dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers  mirror::Class* lastAssignableElementClass = dstClass;
286ab3530dce2119432ce076e2499743cc7ee358e67Elliott Hughes
2872dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers  mirror::Object* o = NULL;
288ab3530dce2119432ce076e2499743cc7ee358e67Elliott Hughes  int i = 0;
289ab3530dce2119432ce076e2499743cc7ee358e67Elliott Hughes  for (; i < length; ++i) {
290025c5de6aab0719c77a19d62b2df80291ec225e6Elliott Hughes    o = srcObjects[i];
291ab3530dce2119432ce076e2499743cc7ee358e67Elliott Hughes    if (o != NULL) {
2922dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers      mirror::Class* oClass = o->GetClass();
293ab3530dce2119432ce076e2499743cc7ee358e67Elliott Hughes      if (lastAssignableElementClass == oClass) {
294ab3530dce2119432ce076e2499743cc7ee358e67Elliott Hughes        dstObjects[i] = o;
295ab3530dce2119432ce076e2499743cc7ee358e67Elliott Hughes      } else if (dstClass->IsAssignableFrom(oClass)) {
296ab3530dce2119432ce076e2499743cc7ee358e67Elliott Hughes        lastAssignableElementClass = oClass;
297ab3530dce2119432ce076e2499743cc7ee358e67Elliott Hughes        dstObjects[i] = o;
298ab3530dce2119432ce076e2499743cc7ee358e67Elliott Hughes      } else {
299ab3530dce2119432ce076e2499743cc7ee358e67Elliott Hughes        // Can't put this element into the array.
300ab3530dce2119432ce076e2499743cc7ee358e67Elliott Hughes        break;
301ab3530dce2119432ce076e2499743cc7ee358e67Elliott Hughes      }
302ab3530dce2119432ce076e2499743cc7ee358e67Elliott Hughes    } else {
303ab3530dce2119432ce076e2499743cc7ee358e67Elliott Hughes      dstObjects[i] = NULL;
304bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes    }
305bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  }
306bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes
307b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes  Runtime::Current()->GetHeap()->WriteBarrierArray(dstArray, dstPos, length);
30862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers  if (UNLIKELY(i != length)) {
309025c5de6aab0719c77a19d62b2df80291ec225e6Elliott Hughes    std::string actualSrcType(PrettyTypeOf(o));
31054e7df1896a4066cbb9fe6f72249829f0b8c49c6Elliott Hughes    std::string dstType(PrettyTypeOf(dstArray));
31162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    ThrowLocation throw_location = soa.Self()->GetCurrentLocationForThrow();
31262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers    soa.Self()->ThrowNewExceptionF(throw_location, "Ljava/lang/ArrayStoreException;",
31362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers                                   "source[%d] of type %s cannot be stored in destination array of type %s",
31462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers                                   srcPos + i, actualSrcType.c_str(), dstType.c_str());
315bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes    return;
316bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  }
317bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes}
318bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes
3190512f02dd6623c0870c11fbf3274d7462f732136Elliott Hughesstatic jint System_identityHashCode(JNIEnv* env, jclass, jobject javaObject) {
32000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  ScopedObjectAccess soa(env);
3212dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers  mirror::Object* o = soa.Decode<mirror::Object*>(javaObject);
32200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  return static_cast<jint>(o->IdentityHashCode());
323bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes}
324bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes
3250512f02dd6623c0870c11fbf3274d7462f732136Elliott Hughesstatic JNINativeMethod gMethods[] = {
326bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  NATIVE_METHOD(System, arraycopy, "(Ljava/lang/Object;ILjava/lang/Object;II)V"),
327bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes  NATIVE_METHOD(System, identityHashCode, "(Ljava/lang/Object;)I"),
328bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes};
329bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes
330bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughesvoid register_java_lang_System(JNIEnv* env) {
331eac766769e3114a078c188ea26776a81f0edb3cfElliott Hughes  REGISTER_NATIVE_METHODS("java/lang/System");
332bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes}
333bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes
334bf86d0438e9ef9c145ebcf16a2e74c4efaa2686aElliott Hughes}  // namespace art
335