1adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/* 2adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Copyright (C) 2007 The Android Open Source Project 3adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 4adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 5adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * you may not use this file except in compliance with the License. 6adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * You may obtain a copy of the License at 7adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 8adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 9adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 10adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Unless required by applicable law or agreed to in writing, software 11adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 12adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * See the License for the specific language governing permissions and 14adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * limitations under the License. 15adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 16adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 17f934c3d2c8dd9e6bc5299cef41adace2a671637dElliott Hughes#define LOG_TAG "Memory" 18c08f9fb2a3be82bb1a3f477ca1524ddcf7a1d4b8Elliott Hughes 19adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project#include "JNIHelp.h" 20a9f5c16a864ff63ba63f810410f8a27c086d5d52Elliott Hughes#include "JniConstants.h" 21fa5b565a3f6c6d7cbd6106ee8d360304c3a939a3Igor Murashkin#include "nativehelper/jni_macros.h" 226c1e5f4ad36c1f51687aa2b059e998a7c2db2e36Elliott Hughes#include "Portability.h" 230568a63ba1086a78ffb4cff68dd2eac4f9908e13Elliott Hughes#include "ScopedBytes.h" 24692222b08ff88eb92b523bf4780d7ea17a23aa80Elliott Hughes#include "ScopedPrimitiveArray.h" 25034db7d210969f6e516d347810695633d063eb4bElliott Hughes 26034db7d210969f6e516d347810695633d063eb4bElliott Hughes#include <errno.h> 27adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project#include <stdlib.h> 28adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project#include <string.h> 29034db7d210969f6e516d347810695633d063eb4bElliott Hughes#include <sys/mman.h> 30adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 31b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearman// Use packed structures for access to unaligned data on targets with alignment restrictions. 32b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearman// The compiler will generate appropriate code to access these structures without 33b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearman// generating alignment exceptions. 34b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearmantemplate <typename T> static inline T get_unaligned(const T* address) { 35b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearman struct unaligned { T v; } __attribute__ ((packed)); 36b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearman const unaligned* p = reinterpret_cast<const unaligned*>(address); 37b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearman return p->v; 38b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearman} 39b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearman 40b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearmantemplate <typename T> static inline void put_unaligned(T* address, T v) { 41b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearman struct unaligned { T v; } __attribute__ ((packed)); 42b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearman unaligned* p = reinterpret_cast<unaligned*>(address); 43b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearman p->v = v; 44b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearman} 45b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearman 460121106d9dc1ba713b53822886355e4d9339e852Joel Dicetemplate <typename T> static T cast(jlong address) { 47034db7d210969f6e516d347810695633d063eb4bElliott Hughes return reinterpret_cast<T>(static_cast<uintptr_t>(address)); 48034db7d210969f6e516d347810695633d063eb4bElliott Hughes} 49034db7d210969f6e516d347810695633d063eb4bElliott Hughes 50b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearman// Byte-swap 2 jshort values packed in a jint. 51b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearmanstatic inline jint bswap_2x16(jint v) { 52b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearman // v is initially ABCD 53b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearman#if defined(__mips__) && defined(__mips_isa_rev) && (__mips_isa_rev >= 2) 54b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearman __asm__ volatile ("wsbh %0, %0" : "+r" (v)); // v=BADC 55b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearman#else 567ba6c51277526eb66b328657abdaa85c05791826Chris Dearman v = bswap_32(v); // v=DCBA 57b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearman v = (v << 16) | ((v >> 16) & 0xffff); // v=BADC 58b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearman#endif 59b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearman return v; 60b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearman} 61b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearman 622f85e921e4753cf4e87696014754278eda5f95efElliott Hughesstatic inline void swapShorts(jshort* dstShorts, const jshort* srcShorts, size_t count) { 637d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes // Do 32-bit swaps as long as possible... 647d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes jint* dst = reinterpret_cast<jint*>(dstShorts); 657d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes const jint* src = reinterpret_cast<const jint*>(srcShorts); 6608d97aee56db51f718544562f5b74671be34dfafChristopher Ferris for (size_t i = 0; i < count / 2; ++i) { 6708d97aee56db51f718544562f5b74671be34dfafChristopher Ferris jint v = get_unaligned<jint>(src++); 6808d97aee56db51f718544562f5b74671be34dfafChristopher Ferris put_unaligned<jint>(dst++, bswap_2x16(v)); 6908d97aee56db51f718544562f5b74671be34dfafChristopher Ferris } 7008d97aee56db51f718544562f5b74671be34dfafChristopher Ferris if ((count % 2) != 0) { 7108d97aee56db51f718544562f5b74671be34dfafChristopher Ferris jshort v = get_unaligned<jshort>(reinterpret_cast<const jshort*>(src)); 7208d97aee56db51f718544562f5b74671be34dfafChristopher Ferris put_unaligned<jshort>(reinterpret_cast<jshort*>(dst), bswap_16(v)); 73692222b08ff88eb92b523bf4780d7ea17a23aa80Elliott Hughes } 74692222b08ff88eb92b523bf4780d7ea17a23aa80Elliott Hughes} 75692222b08ff88eb92b523bf4780d7ea17a23aa80Elliott Hughes 762f85e921e4753cf4e87696014754278eda5f95efElliott Hughesstatic inline void swapInts(jint* dstInts, const jint* srcInts, size_t count) { 7708d97aee56db51f718544562f5b74671be34dfafChristopher Ferris for (size_t i = 0; i < count; ++i) { 7808d97aee56db51f718544562f5b74671be34dfafChristopher Ferris jint v = get_unaligned<int>(srcInts++); 7908d97aee56db51f718544562f5b74671be34dfafChristopher Ferris put_unaligned<jint>(dstInts++, bswap_32(v)); 80692222b08ff88eb92b523bf4780d7ea17a23aa80Elliott Hughes } 81692222b08ff88eb92b523bf4780d7ea17a23aa80Elliott Hughes} 82692222b08ff88eb92b523bf4780d7ea17a23aa80Elliott Hughes 832f85e921e4753cf4e87696014754278eda5f95efElliott Hughesstatic inline void swapLongs(jlong* dstLongs, const jlong* srcLongs, size_t count) { 847d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes jint* dst = reinterpret_cast<jint*>(dstLongs); 857d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes const jint* src = reinterpret_cast<const jint*>(srcLongs); 8608d97aee56db51f718544562f5b74671be34dfafChristopher Ferris for (size_t i = 0; i < count; ++i) { 8708d97aee56db51f718544562f5b74671be34dfafChristopher Ferris jint v1 = get_unaligned<jint>(src++); 8808d97aee56db51f718544562f5b74671be34dfafChristopher Ferris jint v2 = get_unaligned<jint>(src++); 8908d97aee56db51f718544562f5b74671be34dfafChristopher Ferris put_unaligned<jint>(dst++, bswap_32(v2)); 9008d97aee56db51f718544562f5b74671be34dfafChristopher Ferris put_unaligned<jint>(dst++, bswap_32(v1)); 91692222b08ff88eb92b523bf4780d7ea17a23aa80Elliott Hughes } 92692222b08ff88eb92b523bf4780d7ea17a23aa80Elliott Hughes} 93692222b08ff88eb92b523bf4780d7ea17a23aa80Elliott Hughes 940568a63ba1086a78ffb4cff68dd2eac4f9908e13Elliott Hughesstatic void Memory_memmove(JNIEnv* env, jclass, jobject dstObject, jint dstOffset, jobject srcObject, jint srcOffset, jlong length) { 950568a63ba1086a78ffb4cff68dd2eac4f9908e13Elliott Hughes ScopedBytesRW dstBytes(env, dstObject); 960568a63ba1086a78ffb4cff68dd2eac4f9908e13Elliott Hughes if (dstBytes.get() == NULL) { 970568a63ba1086a78ffb4cff68dd2eac4f9908e13Elliott Hughes return; 980568a63ba1086a78ffb4cff68dd2eac4f9908e13Elliott Hughes } 990568a63ba1086a78ffb4cff68dd2eac4f9908e13Elliott Hughes ScopedBytesRO srcBytes(env, srcObject); 1000568a63ba1086a78ffb4cff68dd2eac4f9908e13Elliott Hughes if (srcBytes.get() == NULL) { 1010568a63ba1086a78ffb4cff68dd2eac4f9908e13Elliott Hughes return; 1020568a63ba1086a78ffb4cff68dd2eac4f9908e13Elliott Hughes } 1030568a63ba1086a78ffb4cff68dd2eac4f9908e13Elliott Hughes memmove(dstBytes.get() + dstOffset, srcBytes.get() + srcOffset, length); 104adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 105adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1060121106d9dc1ba713b53822886355e4d9339e852Joel Dicestatic jbyte Memory_peekByte(JNIEnv*, jclass, jlong srcAddress) { 107034db7d210969f6e516d347810695633d063eb4bElliott Hughes return *cast<const jbyte*>(srcAddress); 108adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 109adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1100121106d9dc1ba713b53822886355e4d9339e852Joel Dicestatic void Memory_peekByteArray(JNIEnv* env, jclass, jlong srcAddress, jbyteArray dst, jint dstOffset, jint byteCount) { 111692222b08ff88eb92b523bf4780d7ea17a23aa80Elliott Hughes env->SetByteArrayRegion(dst, dstOffset, byteCount, cast<const jbyte*>(srcAddress)); 112692222b08ff88eb92b523bf4780d7ea17a23aa80Elliott Hughes} 113692222b08ff88eb92b523bf4780d7ea17a23aa80Elliott Hughes 1147d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes// Implements the peekXArray methods: 1157d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes// - For unswapped access, we just use the JNI SetXArrayRegion functions. 1167d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes// - For swapped access, we use GetXArrayElements and our own copy-and-swap routines. 1177d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes// GetXArrayElements is disproportionately cheap on Dalvik because it doesn't copy (as opposed 1187d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes// to Hotspot, which always copies). The SWAP_FN copies and swaps in one pass, which is cheaper 1197d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes// than copying and then swapping in a second pass. Depending on future VM/GC changes, the 1207d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes// swapped case might need to be revisited. 1217d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes#define PEEKER(SCALAR_TYPE, JNI_NAME, SWAP_TYPE, SWAP_FN) { \ 1227d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes if (swap) { \ 1237d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes Scoped ## JNI_NAME ## ArrayRW elements(env, dst); \ 1247d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes if (elements.get() == NULL) { \ 1257d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes return; \ 1267d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes } \ 1277d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes const SWAP_TYPE* src = cast<const SWAP_TYPE*>(srcAddress); \ 128a0b3a2c22454fad9026cff3b0173ada828bad280Chih-Hung Hsieh SWAP_FN(reinterpret_cast<SWAP_TYPE*>(elements.get()) + dstOffset, src, count); /*NOLINT*/ \ 1297d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes } else { \ 1307d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes const SCALAR_TYPE* src = cast<const SCALAR_TYPE*>(srcAddress); \ 1317d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes env->Set ## JNI_NAME ## ArrayRegion(dst, dstOffset, count, src); \ 1327d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes } \ 133961da1e7487bdb8ad8ac226d4f2789d003aa87b9Elliott Hughes} 134961da1e7487bdb8ad8ac226d4f2789d003aa87b9Elliott Hughes 1350121106d9dc1ba713b53822886355e4d9339e852Joel Dicestatic void Memory_peekCharArray(JNIEnv* env, jclass, jlong srcAddress, jcharArray dst, jint dstOffset, jint count, jboolean swap) { 1367d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes PEEKER(jchar, Char, jshort, swapShorts); 137961da1e7487bdb8ad8ac226d4f2789d003aa87b9Elliott Hughes} 138961da1e7487bdb8ad8ac226d4f2789d003aa87b9Elliott Hughes 1390121106d9dc1ba713b53822886355e4d9339e852Joel Dicestatic void Memory_peekDoubleArray(JNIEnv* env, jclass, jlong srcAddress, jdoubleArray dst, jint dstOffset, jint count, jboolean swap) { 1407d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes PEEKER(jdouble, Double, jlong, swapLongs); 141961da1e7487bdb8ad8ac226d4f2789d003aa87b9Elliott Hughes} 142961da1e7487bdb8ad8ac226d4f2789d003aa87b9Elliott Hughes 1430121106d9dc1ba713b53822886355e4d9339e852Joel Dicestatic void Memory_peekFloatArray(JNIEnv* env, jclass, jlong srcAddress, jfloatArray dst, jint dstOffset, jint count, jboolean swap) { 1447d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes PEEKER(jfloat, Float, jint, swapInts); 145adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 146adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1470121106d9dc1ba713b53822886355e4d9339e852Joel Dicestatic void Memory_peekIntArray(JNIEnv* env, jclass, jlong srcAddress, jintArray dst, jint dstOffset, jint count, jboolean swap) { 1487d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes PEEKER(jint, Int, jint, swapInts); 149961da1e7487bdb8ad8ac226d4f2789d003aa87b9Elliott Hughes} 150961da1e7487bdb8ad8ac226d4f2789d003aa87b9Elliott Hughes 1510121106d9dc1ba713b53822886355e4d9339e852Joel Dicestatic void Memory_peekLongArray(JNIEnv* env, jclass, jlong srcAddress, jlongArray dst, jint dstOffset, jint count, jboolean swap) { 1527d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes PEEKER(jlong, Long, jlong, swapLongs); 1537d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes} 1547d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes 1550121106d9dc1ba713b53822886355e4d9339e852Joel Dicestatic void Memory_peekShortArray(JNIEnv* env, jclass, jlong srcAddress, jshortArray dst, jint dstOffset, jint count, jboolean swap) { 1567d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes PEEKER(jshort, Short, jshort, swapShorts); 157961da1e7487bdb8ad8ac226d4f2789d003aa87b9Elliott Hughes} 158961da1e7487bdb8ad8ac226d4f2789d003aa87b9Elliott Hughes 1590121106d9dc1ba713b53822886355e4d9339e852Joel Dicestatic void Memory_pokeByte(JNIEnv*, jclass, jlong dstAddress, jbyte value) { 160034db7d210969f6e516d347810695633d063eb4bElliott Hughes *cast<jbyte*>(dstAddress) = value; 161adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 162adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1630121106d9dc1ba713b53822886355e4d9339e852Joel Dicestatic void Memory_pokeByteArray(JNIEnv* env, jclass, jlong dstAddress, jbyteArray src, jint offset, jint length) { 164034db7d210969f6e516d347810695633d063eb4bElliott Hughes env->GetByteArrayRegion(src, offset, length, cast<jbyte*>(dstAddress)); 165adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 166adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1677d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes// Implements the pokeXArray methods: 1687d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes// - For unswapped access, we just use the JNI GetXArrayRegion functions. 1697d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes// - For swapped access, we use GetXArrayElements and our own copy-and-swap routines. 1707d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes// GetXArrayElements is disproportionately cheap on Dalvik because it doesn't copy (as opposed 1717d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes// to Hotspot, which always copies). The SWAP_FN copies and swaps in one pass, which is cheaper 1727d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes// than copying and then swapping in a second pass. Depending on future VM/GC changes, the 1737d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes// swapped case might need to be revisited. 1747d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes#define POKER(SCALAR_TYPE, JNI_NAME, SWAP_TYPE, SWAP_FN) { \ 1757d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes if (swap) { \ 1767d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes Scoped ## JNI_NAME ## ArrayRO elements(env, src); \ 1777d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes if (elements.get() == NULL) { \ 1787d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes return; \ 1797d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes } \ 1807d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes const SWAP_TYPE* src = reinterpret_cast<const SWAP_TYPE*>(elements.get()) + srcOffset; \ 181a0b3a2c22454fad9026cff3b0173ada828bad280Chih-Hung Hsieh SWAP_FN(cast<SWAP_TYPE*>(dstAddress), src, count); /*NOLINT*/ \ 1827d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes } else { \ 183a0b3a2c22454fad9026cff3b0173ada828bad280Chih-Hung Hsieh env->Get ## JNI_NAME ## ArrayRegion(src, srcOffset, count, cast<SCALAR_TYPE*>(dstAddress)); /*NOLINT*/ \ 1847d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes } \ 185adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 186adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1870121106d9dc1ba713b53822886355e4d9339e852Joel Dicestatic void Memory_pokeCharArray(JNIEnv* env, jclass, jlong dstAddress, jcharArray src, jint srcOffset, jint count, jboolean swap) { 1887d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes POKER(jchar, Char, jshort, swapShorts); 189adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 190adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1910121106d9dc1ba713b53822886355e4d9339e852Joel Dicestatic void Memory_pokeDoubleArray(JNIEnv* env, jclass, jlong dstAddress, jdoubleArray src, jint srcOffset, jint count, jboolean swap) { 1927d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes POKER(jdouble, Double, jlong, swapLongs); 193692222b08ff88eb92b523bf4780d7ea17a23aa80Elliott Hughes} 194692222b08ff88eb92b523bf4780d7ea17a23aa80Elliott Hughes 1950121106d9dc1ba713b53822886355e4d9339e852Joel Dicestatic void Memory_pokeFloatArray(JNIEnv* env, jclass, jlong dstAddress, jfloatArray src, jint srcOffset, jint count, jboolean swap) { 1967d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes POKER(jfloat, Float, jint, swapInts); 197692222b08ff88eb92b523bf4780d7ea17a23aa80Elliott Hughes} 198692222b08ff88eb92b523bf4780d7ea17a23aa80Elliott Hughes 1990121106d9dc1ba713b53822886355e4d9339e852Joel Dicestatic void Memory_pokeIntArray(JNIEnv* env, jclass, jlong dstAddress, jintArray src, jint srcOffset, jint count, jboolean swap) { 2007d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes POKER(jint, Int, jint, swapInts); 201692222b08ff88eb92b523bf4780d7ea17a23aa80Elliott Hughes} 202692222b08ff88eb92b523bf4780d7ea17a23aa80Elliott Hughes 2030121106d9dc1ba713b53822886355e4d9339e852Joel Dicestatic void Memory_pokeLongArray(JNIEnv* env, jclass, jlong dstAddress, jlongArray src, jint srcOffset, jint count, jboolean swap) { 2047d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes POKER(jlong, Long, jlong, swapLongs); 2057d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes} 206692222b08ff88eb92b523bf4780d7ea17a23aa80Elliott Hughes 2070121106d9dc1ba713b53822886355e4d9339e852Joel Dicestatic void Memory_pokeShortArray(JNIEnv* env, jclass, jlong dstAddress, jshortArray src, jint srcOffset, jint count, jboolean swap) { 2087d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes POKER(jshort, Short, jshort, swapShorts); 209bfb0099cc4c8eca744eeda0f20e5b3644f1a4cb9Owen Lin} 210bfb0099cc4c8eca744eeda0f20e5b3644f1a4cb9Owen Lin 211329af9cb39b3cd325a6ac6d1bc906af8877eff9fVladimir Markostatic jshort Memory_peekShortNative(JNIEnv*, jclass, jlong srcAddress) { 21208d97aee56db51f718544562f5b74671be34dfafChristopher Ferris return get_unaligned<jshort>(cast<const jshort*>(srcAddress)); 213adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 214adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 215329af9cb39b3cd325a6ac6d1bc906af8877eff9fVladimir Markostatic void Memory_pokeShortNative(JNIEnv*, jclass, jlong dstAddress, jshort value) { 21608d97aee56db51f718544562f5b74671be34dfafChristopher Ferris put_unaligned<jshort>(cast<jshort*>(dstAddress), value); 217adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 218adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 219329af9cb39b3cd325a6ac6d1bc906af8877eff9fVladimir Markostatic jint Memory_peekIntNative(JNIEnv*, jclass, jlong srcAddress) { 22008d97aee56db51f718544562f5b74671be34dfafChristopher Ferris return get_unaligned<jint>(cast<const jint*>(srcAddress)); 221adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 222adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 223329af9cb39b3cd325a6ac6d1bc906af8877eff9fVladimir Markostatic void Memory_pokeIntNative(JNIEnv*, jclass, jlong dstAddress, jint value) { 22408d97aee56db51f718544562f5b74671be34dfafChristopher Ferris put_unaligned<jint>(cast<jint*>(dstAddress), value); 225adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 226adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 227329af9cb39b3cd325a6ac6d1bc906af8877eff9fVladimir Markostatic jlong Memory_peekLongNative(JNIEnv*, jclass, jlong srcAddress) { 22808d97aee56db51f718544562f5b74671be34dfafChristopher Ferris return get_unaligned<jlong>(cast<const jlong*>(srcAddress)); 229adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 230adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 231329af9cb39b3cd325a6ac6d1bc906af8877eff9fVladimir Markostatic void Memory_pokeLongNative(JNIEnv*, jclass, jlong dstAddress, jlong value) { 23208d97aee56db51f718544562f5b74671be34dfafChristopher Ferris put_unaligned<jlong>(cast<jlong*>(dstAddress), value); 233034db7d210969f6e516d347810695633d063eb4bElliott Hughes} 234034db7d210969f6e516d347810695633d063eb4bElliott Hughes 2358fbc397fc09158bee0bc0cb231c609c4c6e9fc15Elliott Hughesstatic void unsafeBulkCopy(jbyte* dst, const jbyte* src, jint byteCount, 2368fbc397fc09158bee0bc0cb231c609c4c6e9fc15Elliott Hughes jint sizeofElement, jboolean swap) { 2378fbc397fc09158bee0bc0cb231c609c4c6e9fc15Elliott Hughes if (!swap) { 2388fbc397fc09158bee0bc0cb231c609c4c6e9fc15Elliott Hughes memcpy(dst, src, byteCount); 2398fbc397fc09158bee0bc0cb231c609c4c6e9fc15Elliott Hughes return; 2408fbc397fc09158bee0bc0cb231c609c4c6e9fc15Elliott Hughes } 2418fbc397fc09158bee0bc0cb231c609c4c6e9fc15Elliott Hughes 2428fbc397fc09158bee0bc0cb231c609c4c6e9fc15Elliott Hughes if (sizeofElement == 2) { 2438fbc397fc09158bee0bc0cb231c609c4c6e9fc15Elliott Hughes jshort* dstShorts = reinterpret_cast<jshort*>(dst); 2448fbc397fc09158bee0bc0cb231c609c4c6e9fc15Elliott Hughes const jshort* srcShorts = reinterpret_cast<const jshort*>(src); 2458fbc397fc09158bee0bc0cb231c609c4c6e9fc15Elliott Hughes swapShorts(dstShorts, srcShorts, byteCount / 2); 2468fbc397fc09158bee0bc0cb231c609c4c6e9fc15Elliott Hughes } else if (sizeofElement == 4) { 2478fbc397fc09158bee0bc0cb231c609c4c6e9fc15Elliott Hughes jint* dstInts = reinterpret_cast<jint*>(dst); 2488fbc397fc09158bee0bc0cb231c609c4c6e9fc15Elliott Hughes const jint* srcInts = reinterpret_cast<const jint*>(src); 2498fbc397fc09158bee0bc0cb231c609c4c6e9fc15Elliott Hughes swapInts(dstInts, srcInts, byteCount / 4); 2508fbc397fc09158bee0bc0cb231c609c4c6e9fc15Elliott Hughes } else if (sizeofElement == 8) { 2518fbc397fc09158bee0bc0cb231c609c4c6e9fc15Elliott Hughes jlong* dstLongs = reinterpret_cast<jlong*>(dst); 2528fbc397fc09158bee0bc0cb231c609c4c6e9fc15Elliott Hughes const jlong* srcLongs = reinterpret_cast<const jlong*>(src); 2538fbc397fc09158bee0bc0cb231c609c4c6e9fc15Elliott Hughes swapLongs(dstLongs, srcLongs, byteCount / 8); 2548fbc397fc09158bee0bc0cb231c609c4c6e9fc15Elliott Hughes } 2558fbc397fc09158bee0bc0cb231c609c4c6e9fc15Elliott Hughes} 2568fbc397fc09158bee0bc0cb231c609c4c6e9fc15Elliott Hughes 257f934c3d2c8dd9e6bc5299cef41adace2a671637dElliott Hughesstatic void Memory_unsafeBulkGet(JNIEnv* env, jclass, jobject dstObject, jint dstOffset, 2588fbc397fc09158bee0bc0cb231c609c4c6e9fc15Elliott Hughes jint byteCount, jbyteArray srcArray, jint srcOffset, jint sizeofElement, jboolean swap) { 2598fbc397fc09158bee0bc0cb231c609c4c6e9fc15Elliott Hughes ScopedByteArrayRO srcBytes(env, srcArray); 2606944bea4a129dc2d4be687c72f2a9f228ec532bcElliott Hughes if (srcBytes.get() == NULL) { 2616944bea4a129dc2d4be687c72f2a9f228ec532bcElliott Hughes return; 2626944bea4a129dc2d4be687c72f2a9f228ec532bcElliott Hughes } 2638fbc397fc09158bee0bc0cb231c609c4c6e9fc15Elliott Hughes jarray dstArray = reinterpret_cast<jarray>(dstObject); 2646944bea4a129dc2d4be687c72f2a9f228ec532bcElliott Hughes jbyte* dstBytes = reinterpret_cast<jbyte*>(env->GetPrimitiveArrayCritical(dstArray, NULL)); 2656944bea4a129dc2d4be687c72f2a9f228ec532bcElliott Hughes if (dstBytes == NULL) { 2666944bea4a129dc2d4be687c72f2a9f228ec532bcElliott Hughes return; 2676944bea4a129dc2d4be687c72f2a9f228ec532bcElliott Hughes } 2688fbc397fc09158bee0bc0cb231c609c4c6e9fc15Elliott Hughes jbyte* dst = dstBytes + dstOffset*sizeofElement; 2698fbc397fc09158bee0bc0cb231c609c4c6e9fc15Elliott Hughes const jbyte* src = srcBytes.get() + srcOffset; 2708fbc397fc09158bee0bc0cb231c609c4c6e9fc15Elliott Hughes unsafeBulkCopy(dst, src, byteCount, sizeofElement, swap); 2716944bea4a129dc2d4be687c72f2a9f228ec532bcElliott Hughes env->ReleasePrimitiveArrayCritical(dstArray, dstBytes, 0); 2726944bea4a129dc2d4be687c72f2a9f228ec532bcElliott Hughes} 2736944bea4a129dc2d4be687c72f2a9f228ec532bcElliott Hughes 274f934c3d2c8dd9e6bc5299cef41adace2a671637dElliott Hughesstatic void Memory_unsafeBulkPut(JNIEnv* env, jclass, jbyteArray dstArray, jint dstOffset, 2758fbc397fc09158bee0bc0cb231c609c4c6e9fc15Elliott Hughes jint byteCount, jobject srcObject, jint srcOffset, jint sizeofElement, jboolean swap) { 2768fbc397fc09158bee0bc0cb231c609c4c6e9fc15Elliott Hughes ScopedByteArrayRW dstBytes(env, dstArray); 2778fbc397fc09158bee0bc0cb231c609c4c6e9fc15Elliott Hughes if (dstBytes.get() == NULL) { 2788fbc397fc09158bee0bc0cb231c609c4c6e9fc15Elliott Hughes return; 2798fbc397fc09158bee0bc0cb231c609c4c6e9fc15Elliott Hughes } 2808fbc397fc09158bee0bc0cb231c609c4c6e9fc15Elliott Hughes jarray srcArray = reinterpret_cast<jarray>(srcObject); 2818fbc397fc09158bee0bc0cb231c609c4c6e9fc15Elliott Hughes jbyte* srcBytes = reinterpret_cast<jbyte*>(env->GetPrimitiveArrayCritical(srcArray, NULL)); 2828fbc397fc09158bee0bc0cb231c609c4c6e9fc15Elliott Hughes if (srcBytes == NULL) { 2838fbc397fc09158bee0bc0cb231c609c4c6e9fc15Elliott Hughes return; 2848fbc397fc09158bee0bc0cb231c609c4c6e9fc15Elliott Hughes } 2858fbc397fc09158bee0bc0cb231c609c4c6e9fc15Elliott Hughes jbyte* dst = dstBytes.get() + dstOffset; 2868fbc397fc09158bee0bc0cb231c609c4c6e9fc15Elliott Hughes const jbyte* src = srcBytes + srcOffset*sizeofElement; 2878fbc397fc09158bee0bc0cb231c609c4c6e9fc15Elliott Hughes unsafeBulkCopy(dst, src, byteCount, sizeofElement, swap); 2888fbc397fc09158bee0bc0cb231c609c4c6e9fc15Elliott Hughes env->ReleasePrimitiveArrayCritical(srcArray, srcBytes, 0); 2898fbc397fc09158bee0bc0cb231c609c4c6e9fc15Elliott Hughes} 2908fbc397fc09158bee0bc0cb231c609c4c6e9fc15Elliott Hughes 291adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectstatic JNINativeMethod gMethods[] = { 2920568a63ba1086a78ffb4cff68dd2eac4f9908e13Elliott Hughes NATIVE_METHOD(Memory, memmove, "(Ljava/lang/Object;ILjava/lang/Object;IJ)V"), 293fa5b565a3f6c6d7cbd6106ee8d360304c3a939a3Igor Murashkin FAST_NATIVE_METHOD(Memory, peekByte, "(J)B"), 2940121106d9dc1ba713b53822886355e4d9339e852Joel Dice NATIVE_METHOD(Memory, peekByteArray, "(J[BII)V"), 2950121106d9dc1ba713b53822886355e4d9339e852Joel Dice NATIVE_METHOD(Memory, peekCharArray, "(J[CIIZ)V"), 2960121106d9dc1ba713b53822886355e4d9339e852Joel Dice NATIVE_METHOD(Memory, peekDoubleArray, "(J[DIIZ)V"), 2970121106d9dc1ba713b53822886355e4d9339e852Joel Dice NATIVE_METHOD(Memory, peekFloatArray, "(J[FIIZ)V"), 298fa5b565a3f6c6d7cbd6106ee8d360304c3a939a3Igor Murashkin FAST_NATIVE_METHOD(Memory, peekIntNative, "(J)I"), 2990121106d9dc1ba713b53822886355e4d9339e852Joel Dice NATIVE_METHOD(Memory, peekIntArray, "(J[IIIZ)V"), 300fa5b565a3f6c6d7cbd6106ee8d360304c3a939a3Igor Murashkin FAST_NATIVE_METHOD(Memory, peekLongNative, "(J)J"), 3010121106d9dc1ba713b53822886355e4d9339e852Joel Dice NATIVE_METHOD(Memory, peekLongArray, "(J[JIIZ)V"), 302fa5b565a3f6c6d7cbd6106ee8d360304c3a939a3Igor Murashkin FAST_NATIVE_METHOD(Memory, peekShortNative, "(J)S"), 3030121106d9dc1ba713b53822886355e4d9339e852Joel Dice NATIVE_METHOD(Memory, peekShortArray, "(J[SIIZ)V"), 304fa5b565a3f6c6d7cbd6106ee8d360304c3a939a3Igor Murashkin FAST_NATIVE_METHOD(Memory, pokeByte, "(JB)V"), 3050121106d9dc1ba713b53822886355e4d9339e852Joel Dice NATIVE_METHOD(Memory, pokeByteArray, "(J[BII)V"), 3060121106d9dc1ba713b53822886355e4d9339e852Joel Dice NATIVE_METHOD(Memory, pokeCharArray, "(J[CIIZ)V"), 3070121106d9dc1ba713b53822886355e4d9339e852Joel Dice NATIVE_METHOD(Memory, pokeDoubleArray, "(J[DIIZ)V"), 3080121106d9dc1ba713b53822886355e4d9339e852Joel Dice NATIVE_METHOD(Memory, pokeFloatArray, "(J[FIIZ)V"), 309fa5b565a3f6c6d7cbd6106ee8d360304c3a939a3Igor Murashkin FAST_NATIVE_METHOD(Memory, pokeIntNative, "(JI)V"), 3100121106d9dc1ba713b53822886355e4d9339e852Joel Dice NATIVE_METHOD(Memory, pokeIntArray, "(J[IIIZ)V"), 311fa5b565a3f6c6d7cbd6106ee8d360304c3a939a3Igor Murashkin FAST_NATIVE_METHOD(Memory, pokeLongNative, "(JJ)V"), 3120121106d9dc1ba713b53822886355e4d9339e852Joel Dice NATIVE_METHOD(Memory, pokeLongArray, "(J[JIIZ)V"), 313fa5b565a3f6c6d7cbd6106ee8d360304c3a939a3Igor Murashkin FAST_NATIVE_METHOD(Memory, pokeShortNative, "(JS)V"), 3140121106d9dc1ba713b53822886355e4d9339e852Joel Dice NATIVE_METHOD(Memory, pokeShortArray, "(J[SIIZ)V"), 315f934c3d2c8dd9e6bc5299cef41adace2a671637dElliott Hughes NATIVE_METHOD(Memory, unsafeBulkGet, "(Ljava/lang/Object;II[BIIZ)V"), 316f934c3d2c8dd9e6bc5299cef41adace2a671637dElliott Hughes NATIVE_METHOD(Memory, unsafeBulkPut, "([BIILjava/lang/Object;IIZ)V"), 317adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}; 3187cd6760f7045d771faae8080a8c6150bf678f679Elliott Hughesvoid register_libcore_io_Memory(JNIEnv* env) { 3197cd6760f7045d771faae8080a8c6150bf678f679Elliott Hughes jniRegisterNativeMethods(env, "libcore/io/Memory", gMethods, NELEM(gMethods)); 320adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 321