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