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