blob: 2cef41092d7399f8d76fb296bb1288bad050b0ff [file] [log] [blame]
The Android Open Source Projectadc854b2009-03-03 19:28:47 -08001/*
2 * Copyright (C) 2007 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Elliott Hughesf934c3d2011-03-14 18:24:10 -070017#define LOG_TAG "Memory"
Elliott Hughesc08f9fb2010-04-16 17:44:12 -070018
The Android Open Source Projectadc854b2009-03-03 19:28:47 -080019#include "JNIHelp.h"
Elliott Hughesa9f5c162010-06-16 16:32:18 -070020#include "JniConstants.h"
Elliott Hughes6c1e5f42013-01-25 15:10:58 -080021#include "Portability.h"
Elliott Hughes0568a632011-04-25 18:33:06 -070022#include "ScopedBytes.h"
Elliott Hughes692222b2010-09-09 18:28:08 -070023#include "ScopedPrimitiveArray.h"
Elliott Hughes034db7d2010-07-22 18:10:24 -070024#include "UniquePtr.h"
25
26#include <errno.h>
The Android Open Source Projectadc854b2009-03-03 19:28:47 -080027#include <stdlib.h>
28#include <string.h>
Elliott Hughes034db7d2010-07-22 18:10:24 -070029#include <sys/mman.h>
The Android Open Source Projectadc854b2009-03-03 19:28:47 -080030
Elliott Hughes6116e622010-08-25 16:51:32 -070031#if defined(__arm__)
Elliott Hughes7d5299b2010-09-12 15:51:52 -070032// 32-bit ARM has load/store alignment restrictions for longs.
Elliott Hughes6116e622010-08-25 16:51:32 -070033#define LONG_ALIGNMENT_MASK 0x3
Chris Dearmanb7e07722012-05-01 16:11:58 -070034#define INT_ALIGNMENT_MASK 0x0
35#define SHORT_ALIGNMENT_MASK 0x0
36#elif defined(__mips__)
37// MIPS has load/store alignment restrictions for longs, ints and shorts.
38#define LONG_ALIGNMENT_MASK 0x7
39#define INT_ALIGNMENT_MASK 0x3
40#define SHORT_ALIGNMENT_MASK 0x1
Joel Dice01211062013-02-27 16:20:38 -070041#elif defined(__i386__) || defined(__x86_64__)
Elliott Hughes6116e622010-08-25 16:51:32 -070042// x86 can load anything at any alignment.
Elliott Hughes6116e622010-08-25 16:51:32 -070043#define LONG_ALIGNMENT_MASK 0x0
Chris Dearmanb7e07722012-05-01 16:11:58 -070044#define INT_ALIGNMENT_MASK 0x0
45#define SHORT_ALIGNMENT_MASK 0x0
Elliott Hughes6116e622010-08-25 16:51:32 -070046#else
47#error unknown load/store alignment restrictions for this architecture
48#endif
49
Chris Dearmanb7e07722012-05-01 16:11:58 -070050// Use packed structures for access to unaligned data on targets with alignment restrictions.
51// The compiler will generate appropriate code to access these structures without
52// generating alignment exceptions.
53template <typename T> static inline T get_unaligned(const T* address) {
54 struct unaligned { T v; } __attribute__ ((packed));
55 const unaligned* p = reinterpret_cast<const unaligned*>(address);
56 return p->v;
57}
58
59template <typename T> static inline void put_unaligned(T* address, T v) {
60 struct unaligned { T v; } __attribute__ ((packed));
61 unaligned* p = reinterpret_cast<unaligned*>(address);
62 p->v = v;
63}
64
Joel Dice01211062013-02-27 16:20:38 -070065template <typename T> static T cast(jlong address) {
Elliott Hughes034db7d2010-07-22 18:10:24 -070066 return reinterpret_cast<T>(static_cast<uintptr_t>(address));
67}
68
Chris Dearmanb7e07722012-05-01 16:11:58 -070069// Byte-swap 2 jshort values packed in a jint.
70static inline jint bswap_2x16(jint v) {
71 // v is initially ABCD
Chris Dearmanb7e07722012-05-01 16:11:58 -070072#if defined(__mips__) && defined(__mips_isa_rev) && (__mips_isa_rev >= 2)
73 __asm__ volatile ("wsbh %0, %0" : "+r" (v)); // v=BADC
74#else
Chris Dearman7ba6c512012-08-24 12:42:29 -070075 v = bswap_32(v); // v=DCBA
Chris Dearmanb7e07722012-05-01 16:11:58 -070076 v = (v << 16) | ((v >> 16) & 0xffff); // v=BADC
77#endif
78 return v;
79}
80
Elliott Hughes2f85e922010-09-30 19:30:02 -070081static inline void swapShorts(jshort* dstShorts, const jshort* srcShorts, size_t count) {
Elliott Hughes7d5299b2010-09-12 15:51:52 -070082 // Do 32-bit swaps as long as possible...
83 jint* dst = reinterpret_cast<jint*>(dstShorts);
84 const jint* src = reinterpret_cast<const jint*>(srcShorts);
Chris Dearmanb7e07722012-05-01 16:11:58 -070085
86 if ((reinterpret_cast<uintptr_t>(dst) & INT_ALIGNMENT_MASK) == 0 &&
87 (reinterpret_cast<uintptr_t>(src) & INT_ALIGNMENT_MASK) == 0) {
88 for (size_t i = 0; i < count / 2; ++i) {
89 jint v = *src++;
90 *dst++ = bswap_2x16(v);
91 }
92 // ...with one last 16-bit swap if necessary.
93 if ((count % 2) != 0) {
94 jshort v = *reinterpret_cast<const jshort*>(src);
95 *reinterpret_cast<jshort*>(dst) = bswap_16(v);
96 }
97 } else {
98 for (size_t i = 0; i < count / 2; ++i) {
99 jint v = get_unaligned<jint>(src++);
100 put_unaligned<jint>(dst++, bswap_2x16(v));
101 }
102 if ((count % 2) != 0) {
103 jshort v = get_unaligned<jshort>(reinterpret_cast<const jshort*>(src));
104 put_unaligned<jshort>(reinterpret_cast<jshort*>(dst), bswap_16(v));
105 }
Elliott Hughes692222b2010-09-09 18:28:08 -0700106 }
107}
108
Elliott Hughes2f85e922010-09-30 19:30:02 -0700109static inline void swapInts(jint* dstInts, const jint* srcInts, size_t count) {
Chris Dearmanb7e07722012-05-01 16:11:58 -0700110 if ((reinterpret_cast<uintptr_t>(dstInts) & INT_ALIGNMENT_MASK) == 0 &&
111 (reinterpret_cast<uintptr_t>(srcInts) & INT_ALIGNMENT_MASK) == 0) {
112 for (size_t i = 0; i < count; ++i) {
113 jint v = *srcInts++;
114 *dstInts++ = bswap_32(v);
115 }
116 } else {
117 for (size_t i = 0; i < count; ++i) {
118 jint v = get_unaligned<int>(srcInts++);
119 put_unaligned<jint>(dstInts++, bswap_32(v));
120 }
Elliott Hughes692222b2010-09-09 18:28:08 -0700121 }
122}
123
Elliott Hughes2f85e922010-09-30 19:30:02 -0700124static inline void swapLongs(jlong* dstLongs, const jlong* srcLongs, size_t count) {
Elliott Hughes7d5299b2010-09-12 15:51:52 -0700125 jint* dst = reinterpret_cast<jint*>(dstLongs);
126 const jint* src = reinterpret_cast<const jint*>(srcLongs);
Chris Dearmanb7e07722012-05-01 16:11:58 -0700127 if ((reinterpret_cast<uintptr_t>(dstLongs) & INT_ALIGNMENT_MASK) == 0 &&
128 (reinterpret_cast<uintptr_t>(srcLongs) & INT_ALIGNMENT_MASK) == 0) {
129 for (size_t i = 0; i < count; ++i) {
130 jint v1 = *src++;
131 jint v2 = *src++;
132 *dst++ = bswap_32(v2);
133 *dst++ = bswap_32(v1);
134 }
135 } else {
136 for (size_t i = 0; i < count; ++i) {
137 jint v1 = get_unaligned<jint>(src++);
138 jint v2 = get_unaligned<jint>(src++);
139 put_unaligned<jint>(dst++, bswap_32(v2));
140 put_unaligned<jint>(dst++, bswap_32(v1));
141 }
Elliott Hughes692222b2010-09-09 18:28:08 -0700142 }
143}
144
Elliott Hughes0568a632011-04-25 18:33:06 -0700145static void Memory_memmove(JNIEnv* env, jclass, jobject dstObject, jint dstOffset, jobject srcObject, jint srcOffset, jlong length) {
146 ScopedBytesRW dstBytes(env, dstObject);
147 if (dstBytes.get() == NULL) {
148 return;
149 }
150 ScopedBytesRO srcBytes(env, srcObject);
151 if (srcBytes.get() == NULL) {
152 return;
153 }
154 memmove(dstBytes.get() + dstOffset, srcBytes.get() + srcOffset, length);
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800155}
156
Joel Dice01211062013-02-27 16:20:38 -0700157static jbyte Memory_peekByte(JNIEnv*, jclass, jlong srcAddress) {
Elliott Hughes034db7d2010-07-22 18:10:24 -0700158 return *cast<const jbyte*>(srcAddress);
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800159}
160
Joel Dice01211062013-02-27 16:20:38 -0700161static void Memory_peekByteArray(JNIEnv* env, jclass, jlong srcAddress, jbyteArray dst, jint dstOffset, jint byteCount) {
Elliott Hughes692222b2010-09-09 18:28:08 -0700162 env->SetByteArrayRegion(dst, dstOffset, byteCount, cast<const jbyte*>(srcAddress));
163}
164
Elliott Hughes7d5299b2010-09-12 15:51:52 -0700165// Implements the peekXArray methods:
166// - For unswapped access, we just use the JNI SetXArrayRegion functions.
167// - For swapped access, we use GetXArrayElements and our own copy-and-swap routines.
168// GetXArrayElements is disproportionately cheap on Dalvik because it doesn't copy (as opposed
169// to Hotspot, which always copies). The SWAP_FN copies and swaps in one pass, which is cheaper
170// than copying and then swapping in a second pass. Depending on future VM/GC changes, the
171// swapped case might need to be revisited.
172#define PEEKER(SCALAR_TYPE, JNI_NAME, SWAP_TYPE, SWAP_FN) { \
173 if (swap) { \
174 Scoped ## JNI_NAME ## ArrayRW elements(env, dst); \
175 if (elements.get() == NULL) { \
176 return; \
177 } \
178 const SWAP_TYPE* src = cast<const SWAP_TYPE*>(srcAddress); \
179 SWAP_FN(reinterpret_cast<SWAP_TYPE*>(elements.get()) + dstOffset, src, count); \
180 } else { \
181 const SCALAR_TYPE* src = cast<const SCALAR_TYPE*>(srcAddress); \
182 env->Set ## JNI_NAME ## ArrayRegion(dst, dstOffset, count, src); \
183 } \
Elliott Hughes961da1e2010-09-10 15:46:33 -0700184}
185
Joel Dice01211062013-02-27 16:20:38 -0700186static void Memory_peekCharArray(JNIEnv* env, jclass, jlong srcAddress, jcharArray dst, jint dstOffset, jint count, jboolean swap) {
Elliott Hughes7d5299b2010-09-12 15:51:52 -0700187 PEEKER(jchar, Char, jshort, swapShorts);
Elliott Hughes961da1e2010-09-10 15:46:33 -0700188}
189
Joel Dice01211062013-02-27 16:20:38 -0700190static void Memory_peekDoubleArray(JNIEnv* env, jclass, jlong srcAddress, jdoubleArray dst, jint dstOffset, jint count, jboolean swap) {
Elliott Hughes7d5299b2010-09-12 15:51:52 -0700191 PEEKER(jdouble, Double, jlong, swapLongs);
Elliott Hughes961da1e2010-09-10 15:46:33 -0700192}
193
Joel Dice01211062013-02-27 16:20:38 -0700194static void Memory_peekFloatArray(JNIEnv* env, jclass, jlong srcAddress, jfloatArray dst, jint dstOffset, jint count, jboolean swap) {
Elliott Hughes7d5299b2010-09-12 15:51:52 -0700195 PEEKER(jfloat, Float, jint, swapInts);
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800196}
197
Joel Dice01211062013-02-27 16:20:38 -0700198static void Memory_peekIntArray(JNIEnv* env, jclass, jlong srcAddress, jintArray dst, jint dstOffset, jint count, jboolean swap) {
Elliott Hughes7d5299b2010-09-12 15:51:52 -0700199 PEEKER(jint, Int, jint, swapInts);
Elliott Hughes961da1e2010-09-10 15:46:33 -0700200}
201
Joel Dice01211062013-02-27 16:20:38 -0700202static void Memory_peekLongArray(JNIEnv* env, jclass, jlong srcAddress, jlongArray dst, jint dstOffset, jint count, jboolean swap) {
Elliott Hughes7d5299b2010-09-12 15:51:52 -0700203 PEEKER(jlong, Long, jlong, swapLongs);
204}
205
Joel Dice01211062013-02-27 16:20:38 -0700206static void Memory_peekShortArray(JNIEnv* env, jclass, jlong srcAddress, jshortArray dst, jint dstOffset, jint count, jboolean swap) {
Elliott Hughes7d5299b2010-09-12 15:51:52 -0700207 PEEKER(jshort, Short, jshort, swapShorts);
Elliott Hughes961da1e2010-09-10 15:46:33 -0700208}
209
Joel Dice01211062013-02-27 16:20:38 -0700210static void Memory_pokeByte(JNIEnv*, jclass, jlong dstAddress, jbyte value) {
Elliott Hughes034db7d2010-07-22 18:10:24 -0700211 *cast<jbyte*>(dstAddress) = value;
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800212}
213
Joel Dice01211062013-02-27 16:20:38 -0700214static void Memory_pokeByteArray(JNIEnv* env, jclass, jlong dstAddress, jbyteArray src, jint offset, jint length) {
Elliott Hughes034db7d2010-07-22 18:10:24 -0700215 env->GetByteArrayRegion(src, offset, length, cast<jbyte*>(dstAddress));
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800216}
217
Elliott Hughes7d5299b2010-09-12 15:51:52 -0700218// Implements the pokeXArray methods:
219// - For unswapped access, we just use the JNI GetXArrayRegion functions.
220// - For swapped access, we use GetXArrayElements and our own copy-and-swap routines.
221// GetXArrayElements is disproportionately cheap on Dalvik because it doesn't copy (as opposed
222// to Hotspot, which always copies). The SWAP_FN copies and swaps in one pass, which is cheaper
223// than copying and then swapping in a second pass. Depending on future VM/GC changes, the
224// swapped case might need to be revisited.
225#define POKER(SCALAR_TYPE, JNI_NAME, SWAP_TYPE, SWAP_FN) { \
226 if (swap) { \
227 Scoped ## JNI_NAME ## ArrayRO elements(env, src); \
228 if (elements.get() == NULL) { \
229 return; \
230 } \
231 const SWAP_TYPE* src = reinterpret_cast<const SWAP_TYPE*>(elements.get()) + srcOffset; \
232 SWAP_FN(cast<SWAP_TYPE*>(dstAddress), src, count); \
233 } else { \
234 env->Get ## JNI_NAME ## ArrayRegion(src, srcOffset, count, cast<SCALAR_TYPE*>(dstAddress)); \
235 } \
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800236}
237
Joel Dice01211062013-02-27 16:20:38 -0700238static void Memory_pokeCharArray(JNIEnv* env, jclass, jlong dstAddress, jcharArray src, jint srcOffset, jint count, jboolean swap) {
Elliott Hughes7d5299b2010-09-12 15:51:52 -0700239 POKER(jchar, Char, jshort, swapShorts);
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800240}
241
Joel Dice01211062013-02-27 16:20:38 -0700242static void Memory_pokeDoubleArray(JNIEnv* env, jclass, jlong dstAddress, jdoubleArray src, jint srcOffset, jint count, jboolean swap) {
Elliott Hughes7d5299b2010-09-12 15:51:52 -0700243 POKER(jdouble, Double, jlong, swapLongs);
Elliott Hughes692222b2010-09-09 18:28:08 -0700244}
245
Joel Dice01211062013-02-27 16:20:38 -0700246static void Memory_pokeFloatArray(JNIEnv* env, jclass, jlong dstAddress, jfloatArray src, jint srcOffset, jint count, jboolean swap) {
Elliott Hughes7d5299b2010-09-12 15:51:52 -0700247 POKER(jfloat, Float, jint, swapInts);
Elliott Hughes692222b2010-09-09 18:28:08 -0700248}
249
Joel Dice01211062013-02-27 16:20:38 -0700250static void Memory_pokeIntArray(JNIEnv* env, jclass, jlong dstAddress, jintArray src, jint srcOffset, jint count, jboolean swap) {
Elliott Hughes7d5299b2010-09-12 15:51:52 -0700251 POKER(jint, Int, jint, swapInts);
Elliott Hughes692222b2010-09-09 18:28:08 -0700252}
253
Joel Dice01211062013-02-27 16:20:38 -0700254static void Memory_pokeLongArray(JNIEnv* env, jclass, jlong dstAddress, jlongArray src, jint srcOffset, jint count, jboolean swap) {
Elliott Hughes7d5299b2010-09-12 15:51:52 -0700255 POKER(jlong, Long, jlong, swapLongs);
256}
Elliott Hughes692222b2010-09-09 18:28:08 -0700257
Joel Dice01211062013-02-27 16:20:38 -0700258static void Memory_pokeShortArray(JNIEnv* env, jclass, jlong dstAddress, jshortArray src, jint srcOffset, jint count, jboolean swap) {
Elliott Hughes7d5299b2010-09-12 15:51:52 -0700259 POKER(jshort, Short, jshort, swapShorts);
Elliott Hughes623978a2010-07-28 11:15:46 -0700260}
261
Vladimir Marko329af9c2013-10-31 15:11:13 +0000262static jshort Memory_peekShortNative(JNIEnv*, jclass, jlong srcAddress) {
263 return *cast<const jshort*>(srcAddress);
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800264}
265
Vladimir Marko329af9c2013-10-31 15:11:13 +0000266static void Memory_pokeShortNative(JNIEnv*, jclass, jlong dstAddress, jshort value) {
Elliott Hughes7d5299b2010-09-12 15:51:52 -0700267 *cast<jshort*>(dstAddress) = value;
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800268}
269
Vladimir Marko329af9c2013-10-31 15:11:13 +0000270static jint Memory_peekIntNative(JNIEnv*, jclass, jlong srcAddress) {
271 return *cast<const jint*>(srcAddress);
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800272}
273
Vladimir Marko329af9c2013-10-31 15:11:13 +0000274static void Memory_pokeIntNative(JNIEnv*, jclass, jlong dstAddress, jint value) {
Elliott Hughes7d5299b2010-09-12 15:51:52 -0700275 *cast<jint*>(dstAddress) = value;
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800276}
277
Vladimir Marko329af9c2013-10-31 15:11:13 +0000278static jlong Memory_peekLongNative(JNIEnv*, jclass, jlong srcAddress) {
Elliott Hughes6116e622010-08-25 16:51:32 -0700279 jlong result;
Chris Dearmanb7e07722012-05-01 16:11:58 -0700280 const jlong* src = cast<const jlong*>(srcAddress);
Elliott Hughes6116e622010-08-25 16:51:32 -0700281 if ((srcAddress & LONG_ALIGNMENT_MASK) == 0) {
Chris Dearmanb7e07722012-05-01 16:11:58 -0700282 result = *src;
Elliott Hughes6116e622010-08-25 16:51:32 -0700283 } else {
Chris Dearmanb7e07722012-05-01 16:11:58 -0700284 result = get_unaligned<jlong>(src);
Elliott Hughes6116e622010-08-25 16:51:32 -0700285 }
Elliott Hughes1b901872010-08-19 21:54:24 -0700286 return result;
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800287}
288
Vladimir Marko329af9c2013-10-31 15:11:13 +0000289static void Memory_pokeLongNative(JNIEnv*, jclass, jlong dstAddress, jlong value) {
Chris Dearmanb7e07722012-05-01 16:11:58 -0700290 jlong* dst = cast<jlong*>(dstAddress);
Elliott Hughes6116e622010-08-25 16:51:32 -0700291 if ((dstAddress & LONG_ALIGNMENT_MASK) == 0) {
Chris Dearmanb7e07722012-05-01 16:11:58 -0700292 *dst = value;
Elliott Hughes6116e622010-08-25 16:51:32 -0700293 } else {
Chris Dearmanb7e07722012-05-01 16:11:58 -0700294 put_unaligned<jlong>(dst, value);
Elliott Hughes1b901872010-08-19 21:54:24 -0700295 }
Elliott Hughes034db7d2010-07-22 18:10:24 -0700296}
297
Elliott Hughes8fbc3972010-09-17 18:24:37 -0700298static void unsafeBulkCopy(jbyte* dst, const jbyte* src, jint byteCount,
299 jint sizeofElement, jboolean swap) {
300 if (!swap) {
301 memcpy(dst, src, byteCount);
302 return;
303 }
304
305 if (sizeofElement == 2) {
306 jshort* dstShorts = reinterpret_cast<jshort*>(dst);
307 const jshort* srcShorts = reinterpret_cast<const jshort*>(src);
308 swapShorts(dstShorts, srcShorts, byteCount / 2);
309 } else if (sizeofElement == 4) {
310 jint* dstInts = reinterpret_cast<jint*>(dst);
311 const jint* srcInts = reinterpret_cast<const jint*>(src);
312 swapInts(dstInts, srcInts, byteCount / 4);
313 } else if (sizeofElement == 8) {
314 jlong* dstLongs = reinterpret_cast<jlong*>(dst);
315 const jlong* srcLongs = reinterpret_cast<const jlong*>(src);
316 swapLongs(dstLongs, srcLongs, byteCount / 8);
317 }
318}
319
Elliott Hughesf934c3d2011-03-14 18:24:10 -0700320static void Memory_unsafeBulkGet(JNIEnv* env, jclass, jobject dstObject, jint dstOffset,
Elliott Hughes8fbc3972010-09-17 18:24:37 -0700321 jint byteCount, jbyteArray srcArray, jint srcOffset, jint sizeofElement, jboolean swap) {
322 ScopedByteArrayRO srcBytes(env, srcArray);
Elliott Hughes6944bea2010-09-17 13:52:38 -0700323 if (srcBytes.get() == NULL) {
324 return;
325 }
Elliott Hughes8fbc3972010-09-17 18:24:37 -0700326 jarray dstArray = reinterpret_cast<jarray>(dstObject);
Elliott Hughes6944bea2010-09-17 13:52:38 -0700327 jbyte* dstBytes = reinterpret_cast<jbyte*>(env->GetPrimitiveArrayCritical(dstArray, NULL));
328 if (dstBytes == NULL) {
329 return;
330 }
Elliott Hughes8fbc3972010-09-17 18:24:37 -0700331 jbyte* dst = dstBytes + dstOffset*sizeofElement;
332 const jbyte* src = srcBytes.get() + srcOffset;
333 unsafeBulkCopy(dst, src, byteCount, sizeofElement, swap);
Elliott Hughes6944bea2010-09-17 13:52:38 -0700334 env->ReleasePrimitiveArrayCritical(dstArray, dstBytes, 0);
335}
336
Elliott Hughesf934c3d2011-03-14 18:24:10 -0700337static void Memory_unsafeBulkPut(JNIEnv* env, jclass, jbyteArray dstArray, jint dstOffset,
Elliott Hughes8fbc3972010-09-17 18:24:37 -0700338 jint byteCount, jobject srcObject, jint srcOffset, jint sizeofElement, jboolean swap) {
339 ScopedByteArrayRW dstBytes(env, dstArray);
340 if (dstBytes.get() == NULL) {
341 return;
342 }
343 jarray srcArray = reinterpret_cast<jarray>(srcObject);
344 jbyte* srcBytes = reinterpret_cast<jbyte*>(env->GetPrimitiveArrayCritical(srcArray, NULL));
345 if (srcBytes == NULL) {
346 return;
347 }
348 jbyte* dst = dstBytes.get() + dstOffset;
349 const jbyte* src = srcBytes + srcOffset*sizeofElement;
350 unsafeBulkCopy(dst, src, byteCount, sizeofElement, swap);
351 env->ReleasePrimitiveArrayCritical(srcArray, srcBytes, 0);
352}
353
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800354static JNINativeMethod gMethods[] = {
Elliott Hughes0568a632011-04-25 18:33:06 -0700355 NATIVE_METHOD(Memory, memmove, "(Ljava/lang/Object;ILjava/lang/Object;IJ)V"),
Joel Dice01211062013-02-27 16:20:38 -0700356 NATIVE_METHOD(Memory, peekByte, "!(J)B"),
357 NATIVE_METHOD(Memory, peekByteArray, "(J[BII)V"),
358 NATIVE_METHOD(Memory, peekCharArray, "(J[CIIZ)V"),
359 NATIVE_METHOD(Memory, peekDoubleArray, "(J[DIIZ)V"),
360 NATIVE_METHOD(Memory, peekFloatArray, "(J[FIIZ)V"),
Vladimir Marko329af9c2013-10-31 15:11:13 +0000361 NATIVE_METHOD(Memory, peekIntNative, "!(J)I"),
Joel Dice01211062013-02-27 16:20:38 -0700362 NATIVE_METHOD(Memory, peekIntArray, "(J[IIIZ)V"),
Vladimir Marko329af9c2013-10-31 15:11:13 +0000363 NATIVE_METHOD(Memory, peekLongNative, "!(J)J"),
Joel Dice01211062013-02-27 16:20:38 -0700364 NATIVE_METHOD(Memory, peekLongArray, "(J[JIIZ)V"),
Vladimir Marko329af9c2013-10-31 15:11:13 +0000365 NATIVE_METHOD(Memory, peekShortNative, "!(J)S"),
Joel Dice01211062013-02-27 16:20:38 -0700366 NATIVE_METHOD(Memory, peekShortArray, "(J[SIIZ)V"),
367 NATIVE_METHOD(Memory, pokeByte, "!(JB)V"),
368 NATIVE_METHOD(Memory, pokeByteArray, "(J[BII)V"),
369 NATIVE_METHOD(Memory, pokeCharArray, "(J[CIIZ)V"),
370 NATIVE_METHOD(Memory, pokeDoubleArray, "(J[DIIZ)V"),
371 NATIVE_METHOD(Memory, pokeFloatArray, "(J[FIIZ)V"),
Vladimir Marko329af9c2013-10-31 15:11:13 +0000372 NATIVE_METHOD(Memory, pokeIntNative, "!(JI)V"),
Joel Dice01211062013-02-27 16:20:38 -0700373 NATIVE_METHOD(Memory, pokeIntArray, "(J[IIIZ)V"),
Vladimir Marko329af9c2013-10-31 15:11:13 +0000374 NATIVE_METHOD(Memory, pokeLongNative, "!(JJ)V"),
Joel Dice01211062013-02-27 16:20:38 -0700375 NATIVE_METHOD(Memory, pokeLongArray, "(J[JIIZ)V"),
Vladimir Marko329af9c2013-10-31 15:11:13 +0000376 NATIVE_METHOD(Memory, pokeShortNative, "!(JS)V"),
Joel Dice01211062013-02-27 16:20:38 -0700377 NATIVE_METHOD(Memory, pokeShortArray, "(J[SIIZ)V"),
Elliott Hughesf934c3d2011-03-14 18:24:10 -0700378 NATIVE_METHOD(Memory, unsafeBulkGet, "(Ljava/lang/Object;II[BIIZ)V"),
379 NATIVE_METHOD(Memory, unsafeBulkPut, "([BIILjava/lang/Object;IIZ)V"),
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800380};
Elliott Hughes7cd67602012-05-03 17:21:04 -0700381void register_libcore_io_Memory(JNIEnv* env) {
382 jniRegisterNativeMethods(env, "libcore/io/Memory", gMethods, NELEM(gMethods));
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800383}