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