libcore_io_Memory.cpp revision 329af9cb39b3cd325a6ac6d1bc906af8877eff9f
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"
216c1e5f4ad36c1f51687aa2b059e998a7c2db2e36Elliott Hughes#include "Portability.h"
220568a63ba1086a78ffb4cff68dd2eac4f9908e13Elliott Hughes#include "ScopedBytes.h"
23692222b08ff88eb92b523bf4780d7ea17a23aa80Elliott Hughes#include "ScopedPrimitiveArray.h"
24034db7d210969f6e516d347810695633d063eb4bElliott Hughes#include "UniquePtr.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
316116e6265924a0983bb462e3441c8c4a0bb7e47eElliott Hughes#if defined(__arm__)
327d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes// 32-bit ARM has load/store alignment restrictions for longs.
336116e6265924a0983bb462e3441c8c4a0bb7e47eElliott Hughes#define LONG_ALIGNMENT_MASK 0x3
34b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearman#define INT_ALIGNMENT_MASK 0x0
35b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearman#define SHORT_ALIGNMENT_MASK 0x0
36b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearman#elif defined(__mips__)
37b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearman// MIPS has load/store alignment restrictions for longs, ints and shorts.
38b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearman#define LONG_ALIGNMENT_MASK 0x7
39b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearman#define INT_ALIGNMENT_MASK 0x3
40b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearman#define SHORT_ALIGNMENT_MASK 0x1
410121106d9dc1ba713b53822886355e4d9339e852Joel Dice#elif defined(__i386__) || defined(__x86_64__)
426116e6265924a0983bb462e3441c8c4a0bb7e47eElliott Hughes// x86 can load anything at any alignment.
436116e6265924a0983bb462e3441c8c4a0bb7e47eElliott Hughes#define LONG_ALIGNMENT_MASK 0x0
44b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearman#define INT_ALIGNMENT_MASK 0x0
45b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearman#define SHORT_ALIGNMENT_MASK 0x0
466116e6265924a0983bb462e3441c8c4a0bb7e47eElliott Hughes#else
476116e6265924a0983bb462e3441c8c4a0bb7e47eElliott Hughes#error unknown load/store alignment restrictions for this architecture
486116e6265924a0983bb462e3441c8c4a0bb7e47eElliott Hughes#endif
496116e6265924a0983bb462e3441c8c4a0bb7e47eElliott Hughes
50b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearman// Use packed structures for access to unaligned data on targets with alignment restrictions.
51b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearman// The compiler will generate appropriate code to access these structures without
52b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearman// generating alignment exceptions.
53b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearmantemplate <typename T> static inline T get_unaligned(const T* address) {
54b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearman    struct unaligned { T v; } __attribute__ ((packed));
55b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearman    const unaligned* p = reinterpret_cast<const unaligned*>(address);
56b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearman    return p->v;
57b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearman}
58b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearman
59b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearmantemplate <typename T> static inline void put_unaligned(T* address, T v) {
60b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearman    struct unaligned { T v; } __attribute__ ((packed));
61b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearman    unaligned* p = reinterpret_cast<unaligned*>(address);
62b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearman    p->v = v;
63b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearman}
64b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearman
650121106d9dc1ba713b53822886355e4d9339e852Joel Dicetemplate <typename T> static T cast(jlong address) {
66034db7d210969f6e516d347810695633d063eb4bElliott Hughes    return reinterpret_cast<T>(static_cast<uintptr_t>(address));
67034db7d210969f6e516d347810695633d063eb4bElliott Hughes}
68034db7d210969f6e516d347810695633d063eb4bElliott Hughes
69b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearman// Byte-swap 2 jshort values packed in a jint.
70b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearmanstatic inline jint bswap_2x16(jint v) {
71b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearman    // v is initially ABCD
72b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearman#if defined(__mips__) && defined(__mips_isa_rev) && (__mips_isa_rev >= 2)
73b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearman    __asm__ volatile ("wsbh %0, %0" : "+r" (v));  // v=BADC
74b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearman#else
757ba6c51277526eb66b328657abdaa85c05791826Chris Dearman    v = bswap_32(v);                              // v=DCBA
76b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearman    v = (v << 16) | ((v >> 16) & 0xffff);         // v=BADC
77b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearman#endif
78b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearman    return v;
79b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearman}
80b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearman
812f85e921e4753cf4e87696014754278eda5f95efElliott Hughesstatic inline void swapShorts(jshort* dstShorts, const jshort* srcShorts, size_t count) {
827d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes    // Do 32-bit swaps as long as possible...
837d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes    jint* dst = reinterpret_cast<jint*>(dstShorts);
847d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes    const jint* src = reinterpret_cast<const jint*>(srcShorts);
85b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearman
86b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearman    if ((reinterpret_cast<uintptr_t>(dst) & INT_ALIGNMENT_MASK) == 0 &&
87b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearman        (reinterpret_cast<uintptr_t>(src) & INT_ALIGNMENT_MASK) == 0) {
88b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearman        for (size_t i = 0; i < count / 2; ++i) {
89b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearman            jint v = *src++;
90b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearman            *dst++ = bswap_2x16(v);
91b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearman        }
92b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearman        // ...with one last 16-bit swap if necessary.
93b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearman        if ((count % 2) != 0) {
94b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearman            jshort v = *reinterpret_cast<const jshort*>(src);
95b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearman            *reinterpret_cast<jshort*>(dst) = bswap_16(v);
96b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearman        }
97b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearman    } else {
98b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearman        for (size_t i = 0; i < count / 2; ++i) {
99b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearman            jint v = get_unaligned<jint>(src++);
100b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearman            put_unaligned<jint>(dst++, bswap_2x16(v));
101b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearman        }
102b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearman        if ((count % 2) != 0) {
103b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearman          jshort v = get_unaligned<jshort>(reinterpret_cast<const jshort*>(src));
104b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearman          put_unaligned<jshort>(reinterpret_cast<jshort*>(dst), bswap_16(v));
105b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearman        }
106692222b08ff88eb92b523bf4780d7ea17a23aa80Elliott Hughes    }
107692222b08ff88eb92b523bf4780d7ea17a23aa80Elliott Hughes}
108692222b08ff88eb92b523bf4780d7ea17a23aa80Elliott Hughes
1092f85e921e4753cf4e87696014754278eda5f95efElliott Hughesstatic inline void swapInts(jint* dstInts, const jint* srcInts, size_t count) {
110b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearman    if ((reinterpret_cast<uintptr_t>(dstInts) & INT_ALIGNMENT_MASK) == 0 &&
111b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearman        (reinterpret_cast<uintptr_t>(srcInts) & INT_ALIGNMENT_MASK) == 0) {
112b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearman        for (size_t i = 0; i < count; ++i) {
113b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearman            jint v = *srcInts++;
114b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearman            *dstInts++ = bswap_32(v);
115b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearman        }
116b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearman    } else {
117b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearman        for (size_t i = 0; i < count; ++i) {
118b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearman            jint v = get_unaligned<int>(srcInts++);
119b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearman            put_unaligned<jint>(dstInts++, bswap_32(v));
120b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearman        }
121692222b08ff88eb92b523bf4780d7ea17a23aa80Elliott Hughes    }
122692222b08ff88eb92b523bf4780d7ea17a23aa80Elliott Hughes}
123692222b08ff88eb92b523bf4780d7ea17a23aa80Elliott Hughes
1242f85e921e4753cf4e87696014754278eda5f95efElliott Hughesstatic inline void swapLongs(jlong* dstLongs, const jlong* srcLongs, size_t count) {
1257d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes    jint* dst = reinterpret_cast<jint*>(dstLongs);
1267d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes    const jint* src = reinterpret_cast<const jint*>(srcLongs);
127b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearman    if ((reinterpret_cast<uintptr_t>(dstLongs) & INT_ALIGNMENT_MASK) == 0 &&
128b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearman        (reinterpret_cast<uintptr_t>(srcLongs) & INT_ALIGNMENT_MASK) == 0) {
129b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearman        for (size_t i = 0; i < count; ++i) {
130b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearman          jint v1 = *src++;
131b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearman          jint v2 = *src++;
132b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearman          *dst++ = bswap_32(v2);
133b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearman          *dst++ = bswap_32(v1);
134b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearman        }
135b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearman    } else {
136b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearman        for (size_t i = 0; i < count; ++i) {
137b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearman            jint v1 = get_unaligned<jint>(src++);
138b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearman            jint v2 = get_unaligned<jint>(src++);
139b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearman            put_unaligned<jint>(dst++, bswap_32(v2));
140b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearman            put_unaligned<jint>(dst++, bswap_32(v1));
141b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearman        }
142692222b08ff88eb92b523bf4780d7ea17a23aa80Elliott Hughes    }
143692222b08ff88eb92b523bf4780d7ea17a23aa80Elliott Hughes}
144692222b08ff88eb92b523bf4780d7ea17a23aa80Elliott Hughes
1450568a63ba1086a78ffb4cff68dd2eac4f9908e13Elliott Hughesstatic void Memory_memmove(JNIEnv* env, jclass, jobject dstObject, jint dstOffset, jobject srcObject, jint srcOffset, jlong length) {
1460568a63ba1086a78ffb4cff68dd2eac4f9908e13Elliott Hughes    ScopedBytesRW dstBytes(env, dstObject);
1470568a63ba1086a78ffb4cff68dd2eac4f9908e13Elliott Hughes    if (dstBytes.get() == NULL) {
1480568a63ba1086a78ffb4cff68dd2eac4f9908e13Elliott Hughes        return;
1490568a63ba1086a78ffb4cff68dd2eac4f9908e13Elliott Hughes    }
1500568a63ba1086a78ffb4cff68dd2eac4f9908e13Elliott Hughes    ScopedBytesRO srcBytes(env, srcObject);
1510568a63ba1086a78ffb4cff68dd2eac4f9908e13Elliott Hughes    if (srcBytes.get() == NULL) {
1520568a63ba1086a78ffb4cff68dd2eac4f9908e13Elliott Hughes        return;
1530568a63ba1086a78ffb4cff68dd2eac4f9908e13Elliott Hughes    }
1540568a63ba1086a78ffb4cff68dd2eac4f9908e13Elliott Hughes    memmove(dstBytes.get() + dstOffset, srcBytes.get() + srcOffset, length);
155adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
156adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1570121106d9dc1ba713b53822886355e4d9339e852Joel Dicestatic jbyte Memory_peekByte(JNIEnv*, jclass, jlong srcAddress) {
158034db7d210969f6e516d347810695633d063eb4bElliott Hughes    return *cast<const jbyte*>(srcAddress);
159adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
160adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1610121106d9dc1ba713b53822886355e4d9339e852Joel Dicestatic void Memory_peekByteArray(JNIEnv* env, jclass, jlong srcAddress, jbyteArray dst, jint dstOffset, jint byteCount) {
162692222b08ff88eb92b523bf4780d7ea17a23aa80Elliott Hughes    env->SetByteArrayRegion(dst, dstOffset, byteCount, cast<const jbyte*>(srcAddress));
163692222b08ff88eb92b523bf4780d7ea17a23aa80Elliott Hughes}
164692222b08ff88eb92b523bf4780d7ea17a23aa80Elliott Hughes
1657d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes// Implements the peekXArray methods:
1667d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes// - For unswapped access, we just use the JNI SetXArrayRegion functions.
1677d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes// - For swapped access, we use GetXArrayElements and our own copy-and-swap routines.
1687d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes//   GetXArrayElements is disproportionately cheap on Dalvik because it doesn't copy (as opposed
1697d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes//   to Hotspot, which always copies). The SWAP_FN copies and swaps in one pass, which is cheaper
1707d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes//   than copying and then swapping in a second pass. Depending on future VM/GC changes, the
1717d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes//   swapped case might need to be revisited.
1727d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes#define PEEKER(SCALAR_TYPE, JNI_NAME, SWAP_TYPE, SWAP_FN) { \
1737d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes    if (swap) { \
1747d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes        Scoped ## JNI_NAME ## ArrayRW elements(env, dst); \
1757d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes        if (elements.get() == NULL) { \
1767d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes            return; \
1777d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes        } \
1787d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes        const SWAP_TYPE* src = cast<const SWAP_TYPE*>(srcAddress); \
1797d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes        SWAP_FN(reinterpret_cast<SWAP_TYPE*>(elements.get()) + dstOffset, src, count); \
1807d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes    } else { \
1817d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes        const SCALAR_TYPE* src = cast<const SCALAR_TYPE*>(srcAddress); \
1827d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes        env->Set ## JNI_NAME ## ArrayRegion(dst, dstOffset, count, src); \
1837d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes    } \
184961da1e7487bdb8ad8ac226d4f2789d003aa87b9Elliott Hughes}
185961da1e7487bdb8ad8ac226d4f2789d003aa87b9Elliott Hughes
1860121106d9dc1ba713b53822886355e4d9339e852Joel Dicestatic void Memory_peekCharArray(JNIEnv* env, jclass, jlong srcAddress, jcharArray dst, jint dstOffset, jint count, jboolean swap) {
1877d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes    PEEKER(jchar, Char, jshort, swapShorts);
188961da1e7487bdb8ad8ac226d4f2789d003aa87b9Elliott Hughes}
189961da1e7487bdb8ad8ac226d4f2789d003aa87b9Elliott Hughes
1900121106d9dc1ba713b53822886355e4d9339e852Joel Dicestatic void Memory_peekDoubleArray(JNIEnv* env, jclass, jlong srcAddress, jdoubleArray dst, jint dstOffset, jint count, jboolean swap) {
1917d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes    PEEKER(jdouble, Double, jlong, swapLongs);
192961da1e7487bdb8ad8ac226d4f2789d003aa87b9Elliott Hughes}
193961da1e7487bdb8ad8ac226d4f2789d003aa87b9Elliott Hughes
1940121106d9dc1ba713b53822886355e4d9339e852Joel Dicestatic void Memory_peekFloatArray(JNIEnv* env, jclass, jlong srcAddress, jfloatArray dst, jint dstOffset, jint count, jboolean swap) {
1957d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes    PEEKER(jfloat, Float, jint, swapInts);
196adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
197adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1980121106d9dc1ba713b53822886355e4d9339e852Joel Dicestatic void Memory_peekIntArray(JNIEnv* env, jclass, jlong srcAddress, jintArray dst, jint dstOffset, jint count, jboolean swap) {
1997d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes    PEEKER(jint, Int, jint, swapInts);
200961da1e7487bdb8ad8ac226d4f2789d003aa87b9Elliott Hughes}
201961da1e7487bdb8ad8ac226d4f2789d003aa87b9Elliott Hughes
2020121106d9dc1ba713b53822886355e4d9339e852Joel Dicestatic void Memory_peekLongArray(JNIEnv* env, jclass, jlong srcAddress, jlongArray dst, jint dstOffset, jint count, jboolean swap) {
2037d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes    PEEKER(jlong, Long, jlong, swapLongs);
2047d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes}
2057d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes
2060121106d9dc1ba713b53822886355e4d9339e852Joel Dicestatic void Memory_peekShortArray(JNIEnv* env, jclass, jlong srcAddress, jshortArray dst, jint dstOffset, jint count, jboolean swap) {
2077d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes    PEEKER(jshort, Short, jshort, swapShorts);
208961da1e7487bdb8ad8ac226d4f2789d003aa87b9Elliott Hughes}
209961da1e7487bdb8ad8ac226d4f2789d003aa87b9Elliott Hughes
2100121106d9dc1ba713b53822886355e4d9339e852Joel Dicestatic void Memory_pokeByte(JNIEnv*, jclass, jlong dstAddress, jbyte value) {
211034db7d210969f6e516d347810695633d063eb4bElliott Hughes    *cast<jbyte*>(dstAddress) = value;
212adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
213adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
2140121106d9dc1ba713b53822886355e4d9339e852Joel Dicestatic void Memory_pokeByteArray(JNIEnv* env, jclass, jlong dstAddress, jbyteArray src, jint offset, jint length) {
215034db7d210969f6e516d347810695633d063eb4bElliott Hughes    env->GetByteArrayRegion(src, offset, length, cast<jbyte*>(dstAddress));
216adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
217adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
2187d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes// Implements the pokeXArray methods:
2197d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes// - For unswapped access, we just use the JNI GetXArrayRegion functions.
2207d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes// - For swapped access, we use GetXArrayElements and our own copy-and-swap routines.
2217d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes//   GetXArrayElements is disproportionately cheap on Dalvik because it doesn't copy (as opposed
2227d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes//   to Hotspot, which always copies). The SWAP_FN copies and swaps in one pass, which is cheaper
2237d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes//   than copying and then swapping in a second pass. Depending on future VM/GC changes, the
2247d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes//   swapped case might need to be revisited.
2257d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes#define POKER(SCALAR_TYPE, JNI_NAME, SWAP_TYPE, SWAP_FN) { \
2267d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes    if (swap) { \
2277d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes        Scoped ## JNI_NAME ## ArrayRO elements(env, src); \
2287d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes        if (elements.get() == NULL) { \
2297d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes            return; \
2307d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes        } \
2317d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes        const SWAP_TYPE* src = reinterpret_cast<const SWAP_TYPE*>(elements.get()) + srcOffset; \
2327d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes        SWAP_FN(cast<SWAP_TYPE*>(dstAddress), src, count); \
2337d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes    } else { \
2347d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes        env->Get ## JNI_NAME ## ArrayRegion(src, srcOffset, count, cast<SCALAR_TYPE*>(dstAddress)); \
2357d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes    } \
236adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
237adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
2380121106d9dc1ba713b53822886355e4d9339e852Joel Dicestatic void Memory_pokeCharArray(JNIEnv* env, jclass, jlong dstAddress, jcharArray src, jint srcOffset, jint count, jboolean swap) {
2397d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes    POKER(jchar, Char, jshort, swapShorts);
240adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
241adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
2420121106d9dc1ba713b53822886355e4d9339e852Joel Dicestatic void Memory_pokeDoubleArray(JNIEnv* env, jclass, jlong dstAddress, jdoubleArray src, jint srcOffset, jint count, jboolean swap) {
2437d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes    POKER(jdouble, Double, jlong, swapLongs);
244692222b08ff88eb92b523bf4780d7ea17a23aa80Elliott Hughes}
245692222b08ff88eb92b523bf4780d7ea17a23aa80Elliott Hughes
2460121106d9dc1ba713b53822886355e4d9339e852Joel Dicestatic void Memory_pokeFloatArray(JNIEnv* env, jclass, jlong dstAddress, jfloatArray src, jint srcOffset, jint count, jboolean swap) {
2477d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes    POKER(jfloat, Float, jint, swapInts);
248692222b08ff88eb92b523bf4780d7ea17a23aa80Elliott Hughes}
249692222b08ff88eb92b523bf4780d7ea17a23aa80Elliott Hughes
2500121106d9dc1ba713b53822886355e4d9339e852Joel Dicestatic void Memory_pokeIntArray(JNIEnv* env, jclass, jlong dstAddress, jintArray src, jint srcOffset, jint count, jboolean swap) {
2517d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes    POKER(jint, Int, jint, swapInts);
252692222b08ff88eb92b523bf4780d7ea17a23aa80Elliott Hughes}
253692222b08ff88eb92b523bf4780d7ea17a23aa80Elliott Hughes
2540121106d9dc1ba713b53822886355e4d9339e852Joel Dicestatic void Memory_pokeLongArray(JNIEnv* env, jclass, jlong dstAddress, jlongArray src, jint srcOffset, jint count, jboolean swap) {
2557d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes    POKER(jlong, Long, jlong, swapLongs);
2567d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes}
257692222b08ff88eb92b523bf4780d7ea17a23aa80Elliott Hughes
2580121106d9dc1ba713b53822886355e4d9339e852Joel Dicestatic void Memory_pokeShortArray(JNIEnv* env, jclass, jlong dstAddress, jshortArray src, jint srcOffset, jint count, jboolean swap) {
2597d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes    POKER(jshort, Short, jshort, swapShorts);
260bfb0099cc4c8eca744eeda0f20e5b3644f1a4cb9Owen Lin}
261bfb0099cc4c8eca744eeda0f20e5b3644f1a4cb9Owen Lin
262329af9cb39b3cd325a6ac6d1bc906af8877eff9fVladimir Markostatic jshort Memory_peekShortNative(JNIEnv*, jclass, jlong srcAddress) {
263329af9cb39b3cd325a6ac6d1bc906af8877eff9fVladimir Marko    return *cast<const jshort*>(srcAddress);
264adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
265adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
266329af9cb39b3cd325a6ac6d1bc906af8877eff9fVladimir Markostatic void Memory_pokeShortNative(JNIEnv*, jclass, jlong dstAddress, jshort value) {
2677d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes    *cast<jshort*>(dstAddress) = value;
268adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
269adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
270329af9cb39b3cd325a6ac6d1bc906af8877eff9fVladimir Markostatic jint Memory_peekIntNative(JNIEnv*, jclass, jlong srcAddress) {
271329af9cb39b3cd325a6ac6d1bc906af8877eff9fVladimir Marko    return *cast<const jint*>(srcAddress);
272adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
273adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
274329af9cb39b3cd325a6ac6d1bc906af8877eff9fVladimir Markostatic void Memory_pokeIntNative(JNIEnv*, jclass, jlong dstAddress, jint value) {
2757d5299b162863ea898dd863004afe79f7a93fbceElliott Hughes    *cast<jint*>(dstAddress) = value;
276adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
277adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
278329af9cb39b3cd325a6ac6d1bc906af8877eff9fVladimir Markostatic jlong Memory_peekLongNative(JNIEnv*, jclass, jlong srcAddress) {
2796116e6265924a0983bb462e3441c8c4a0bb7e47eElliott Hughes    jlong result;
280b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearman    const jlong* src = cast<const jlong*>(srcAddress);
2816116e6265924a0983bb462e3441c8c4a0bb7e47eElliott Hughes    if ((srcAddress & LONG_ALIGNMENT_MASK) == 0) {
282b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearman        result = *src;
283adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    } else {
284b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearman        result = get_unaligned<jlong>(src);
285adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
2861b9018762e87e3dda69020248817011efd5a40dcElliott Hughes    return result;
287adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
288adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
289329af9cb39b3cd325a6ac6d1bc906af8877eff9fVladimir Markostatic void Memory_pokeLongNative(JNIEnv*, jclass, jlong dstAddress, jlong value) {
290b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearman    jlong* dst = cast<jlong*>(dstAddress);
2916116e6265924a0983bb462e3441c8c4a0bb7e47eElliott Hughes    if ((dstAddress & LONG_ALIGNMENT_MASK) == 0) {
292b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearman        *dst = value;
2936116e6265924a0983bb462e3441c8c4a0bb7e47eElliott Hughes    } else {
294b7e0772d25499ddf5435e53a90cf1a6d753786d7Chris Dearman        put_unaligned<jlong>(dst, value);
2951b9018762e87e3dda69020248817011efd5a40dcElliott Hughes    }
296034db7d210969f6e516d347810695633d063eb4bElliott Hughes}
297034db7d210969f6e516d347810695633d063eb4bElliott Hughes
2988fbc397fc09158bee0bc0cb231c609c4c6e9fc15Elliott Hughesstatic void unsafeBulkCopy(jbyte* dst, const jbyte* src, jint byteCount,
2998fbc397fc09158bee0bc0cb231c609c4c6e9fc15Elliott Hughes        jint sizeofElement, jboolean swap) {
3008fbc397fc09158bee0bc0cb231c609c4c6e9fc15Elliott Hughes    if (!swap) {
3018fbc397fc09158bee0bc0cb231c609c4c6e9fc15Elliott Hughes        memcpy(dst, src, byteCount);
3028fbc397fc09158bee0bc0cb231c609c4c6e9fc15Elliott Hughes        return;
3038fbc397fc09158bee0bc0cb231c609c4c6e9fc15Elliott Hughes    }
3048fbc397fc09158bee0bc0cb231c609c4c6e9fc15Elliott Hughes
3058fbc397fc09158bee0bc0cb231c609c4c6e9fc15Elliott Hughes    if (sizeofElement == 2) {
3068fbc397fc09158bee0bc0cb231c609c4c6e9fc15Elliott Hughes        jshort* dstShorts = reinterpret_cast<jshort*>(dst);
3078fbc397fc09158bee0bc0cb231c609c4c6e9fc15Elliott Hughes        const jshort* srcShorts = reinterpret_cast<const jshort*>(src);
3088fbc397fc09158bee0bc0cb231c609c4c6e9fc15Elliott Hughes        swapShorts(dstShorts, srcShorts, byteCount / 2);
3098fbc397fc09158bee0bc0cb231c609c4c6e9fc15Elliott Hughes    } else if (sizeofElement == 4) {
3108fbc397fc09158bee0bc0cb231c609c4c6e9fc15Elliott Hughes        jint* dstInts = reinterpret_cast<jint*>(dst);
3118fbc397fc09158bee0bc0cb231c609c4c6e9fc15Elliott Hughes        const jint* srcInts = reinterpret_cast<const jint*>(src);
3128fbc397fc09158bee0bc0cb231c609c4c6e9fc15Elliott Hughes        swapInts(dstInts, srcInts, byteCount / 4);
3138fbc397fc09158bee0bc0cb231c609c4c6e9fc15Elliott Hughes    } else if (sizeofElement == 8) {
3148fbc397fc09158bee0bc0cb231c609c4c6e9fc15Elliott Hughes        jlong* dstLongs = reinterpret_cast<jlong*>(dst);
3158fbc397fc09158bee0bc0cb231c609c4c6e9fc15Elliott Hughes        const jlong* srcLongs = reinterpret_cast<const jlong*>(src);
3168fbc397fc09158bee0bc0cb231c609c4c6e9fc15Elliott Hughes        swapLongs(dstLongs, srcLongs, byteCount / 8);
3178fbc397fc09158bee0bc0cb231c609c4c6e9fc15Elliott Hughes    }
3188fbc397fc09158bee0bc0cb231c609c4c6e9fc15Elliott Hughes}
3198fbc397fc09158bee0bc0cb231c609c4c6e9fc15Elliott Hughes
320f934c3d2c8dd9e6bc5299cef41adace2a671637dElliott Hughesstatic void Memory_unsafeBulkGet(JNIEnv* env, jclass, jobject dstObject, jint dstOffset,
3218fbc397fc09158bee0bc0cb231c609c4c6e9fc15Elliott Hughes        jint byteCount, jbyteArray srcArray, jint srcOffset, jint sizeofElement, jboolean swap) {
3228fbc397fc09158bee0bc0cb231c609c4c6e9fc15Elliott Hughes    ScopedByteArrayRO srcBytes(env, srcArray);
3236944bea4a129dc2d4be687c72f2a9f228ec532bcElliott Hughes    if (srcBytes.get() == NULL) {
3246944bea4a129dc2d4be687c72f2a9f228ec532bcElliott Hughes        return;
3256944bea4a129dc2d4be687c72f2a9f228ec532bcElliott Hughes    }
3268fbc397fc09158bee0bc0cb231c609c4c6e9fc15Elliott Hughes    jarray dstArray = reinterpret_cast<jarray>(dstObject);
3276944bea4a129dc2d4be687c72f2a9f228ec532bcElliott Hughes    jbyte* dstBytes = reinterpret_cast<jbyte*>(env->GetPrimitiveArrayCritical(dstArray, NULL));
3286944bea4a129dc2d4be687c72f2a9f228ec532bcElliott Hughes    if (dstBytes == NULL) {
3296944bea4a129dc2d4be687c72f2a9f228ec532bcElliott Hughes        return;
3306944bea4a129dc2d4be687c72f2a9f228ec532bcElliott Hughes    }
3318fbc397fc09158bee0bc0cb231c609c4c6e9fc15Elliott Hughes    jbyte* dst = dstBytes + dstOffset*sizeofElement;
3328fbc397fc09158bee0bc0cb231c609c4c6e9fc15Elliott Hughes    const jbyte* src = srcBytes.get() + srcOffset;
3338fbc397fc09158bee0bc0cb231c609c4c6e9fc15Elliott Hughes    unsafeBulkCopy(dst, src, byteCount, sizeofElement, swap);
3346944bea4a129dc2d4be687c72f2a9f228ec532bcElliott Hughes    env->ReleasePrimitiveArrayCritical(dstArray, dstBytes, 0);
3356944bea4a129dc2d4be687c72f2a9f228ec532bcElliott Hughes}
3366944bea4a129dc2d4be687c72f2a9f228ec532bcElliott Hughes
337f934c3d2c8dd9e6bc5299cef41adace2a671637dElliott Hughesstatic void Memory_unsafeBulkPut(JNIEnv* env, jclass, jbyteArray dstArray, jint dstOffset,
3388fbc397fc09158bee0bc0cb231c609c4c6e9fc15Elliott Hughes        jint byteCount, jobject srcObject, jint srcOffset, jint sizeofElement, jboolean swap) {
3398fbc397fc09158bee0bc0cb231c609c4c6e9fc15Elliott Hughes    ScopedByteArrayRW dstBytes(env, dstArray);
3408fbc397fc09158bee0bc0cb231c609c4c6e9fc15Elliott Hughes    if (dstBytes.get() == NULL) {
3418fbc397fc09158bee0bc0cb231c609c4c6e9fc15Elliott Hughes        return;
3428fbc397fc09158bee0bc0cb231c609c4c6e9fc15Elliott Hughes    }
3438fbc397fc09158bee0bc0cb231c609c4c6e9fc15Elliott Hughes    jarray srcArray = reinterpret_cast<jarray>(srcObject);
3448fbc397fc09158bee0bc0cb231c609c4c6e9fc15Elliott Hughes    jbyte* srcBytes = reinterpret_cast<jbyte*>(env->GetPrimitiveArrayCritical(srcArray, NULL));
3458fbc397fc09158bee0bc0cb231c609c4c6e9fc15Elliott Hughes    if (srcBytes == NULL) {
3468fbc397fc09158bee0bc0cb231c609c4c6e9fc15Elliott Hughes        return;
3478fbc397fc09158bee0bc0cb231c609c4c6e9fc15Elliott Hughes    }
3488fbc397fc09158bee0bc0cb231c609c4c6e9fc15Elliott Hughes    jbyte* dst = dstBytes.get() + dstOffset;
3498fbc397fc09158bee0bc0cb231c609c4c6e9fc15Elliott Hughes    const jbyte* src = srcBytes + srcOffset*sizeofElement;
3508fbc397fc09158bee0bc0cb231c609c4c6e9fc15Elliott Hughes    unsafeBulkCopy(dst, src, byteCount, sizeofElement, swap);
3518fbc397fc09158bee0bc0cb231c609c4c6e9fc15Elliott Hughes    env->ReleasePrimitiveArrayCritical(srcArray, srcBytes, 0);
3528fbc397fc09158bee0bc0cb231c609c4c6e9fc15Elliott Hughes}
3538fbc397fc09158bee0bc0cb231c609c4c6e9fc15Elliott Hughes
354adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectstatic JNINativeMethod gMethods[] = {
3550568a63ba1086a78ffb4cff68dd2eac4f9908e13Elliott Hughes    NATIVE_METHOD(Memory, memmove, "(Ljava/lang/Object;ILjava/lang/Object;IJ)V"),
3560121106d9dc1ba713b53822886355e4d9339e852Joel Dice    NATIVE_METHOD(Memory, peekByte, "!(J)B"),
3570121106d9dc1ba713b53822886355e4d9339e852Joel Dice    NATIVE_METHOD(Memory, peekByteArray, "(J[BII)V"),
3580121106d9dc1ba713b53822886355e4d9339e852Joel Dice    NATIVE_METHOD(Memory, peekCharArray, "(J[CIIZ)V"),
3590121106d9dc1ba713b53822886355e4d9339e852Joel Dice    NATIVE_METHOD(Memory, peekDoubleArray, "(J[DIIZ)V"),
3600121106d9dc1ba713b53822886355e4d9339e852Joel Dice    NATIVE_METHOD(Memory, peekFloatArray, "(J[FIIZ)V"),
361329af9cb39b3cd325a6ac6d1bc906af8877eff9fVladimir Marko    NATIVE_METHOD(Memory, peekIntNative, "!(J)I"),
3620121106d9dc1ba713b53822886355e4d9339e852Joel Dice    NATIVE_METHOD(Memory, peekIntArray, "(J[IIIZ)V"),
363329af9cb39b3cd325a6ac6d1bc906af8877eff9fVladimir Marko    NATIVE_METHOD(Memory, peekLongNative, "!(J)J"),
3640121106d9dc1ba713b53822886355e4d9339e852Joel Dice    NATIVE_METHOD(Memory, peekLongArray, "(J[JIIZ)V"),
365329af9cb39b3cd325a6ac6d1bc906af8877eff9fVladimir Marko    NATIVE_METHOD(Memory, peekShortNative, "!(J)S"),
3660121106d9dc1ba713b53822886355e4d9339e852Joel Dice    NATIVE_METHOD(Memory, peekShortArray, "(J[SIIZ)V"),
3670121106d9dc1ba713b53822886355e4d9339e852Joel Dice    NATIVE_METHOD(Memory, pokeByte, "!(JB)V"),
3680121106d9dc1ba713b53822886355e4d9339e852Joel Dice    NATIVE_METHOD(Memory, pokeByteArray, "(J[BII)V"),
3690121106d9dc1ba713b53822886355e4d9339e852Joel Dice    NATIVE_METHOD(Memory, pokeCharArray, "(J[CIIZ)V"),
3700121106d9dc1ba713b53822886355e4d9339e852Joel Dice    NATIVE_METHOD(Memory, pokeDoubleArray, "(J[DIIZ)V"),
3710121106d9dc1ba713b53822886355e4d9339e852Joel Dice    NATIVE_METHOD(Memory, pokeFloatArray, "(J[FIIZ)V"),
372329af9cb39b3cd325a6ac6d1bc906af8877eff9fVladimir Marko    NATIVE_METHOD(Memory, pokeIntNative, "!(JI)V"),
3730121106d9dc1ba713b53822886355e4d9339e852Joel Dice    NATIVE_METHOD(Memory, pokeIntArray, "(J[IIIZ)V"),
374329af9cb39b3cd325a6ac6d1bc906af8877eff9fVladimir Marko    NATIVE_METHOD(Memory, pokeLongNative, "!(JJ)V"),
3750121106d9dc1ba713b53822886355e4d9339e852Joel Dice    NATIVE_METHOD(Memory, pokeLongArray, "(J[JIIZ)V"),
376329af9cb39b3cd325a6ac6d1bc906af8877eff9fVladimir Marko    NATIVE_METHOD(Memory, pokeShortNative, "!(JS)V"),
3770121106d9dc1ba713b53822886355e4d9339e852Joel Dice    NATIVE_METHOD(Memory, pokeShortArray, "(J[SIIZ)V"),
378f934c3d2c8dd9e6bc5299cef41adace2a671637dElliott Hughes    NATIVE_METHOD(Memory, unsafeBulkGet, "(Ljava/lang/Object;II[BIIZ)V"),
379f934c3d2c8dd9e6bc5299cef41adace2a671637dElliott Hughes    NATIVE_METHOD(Memory, unsafeBulkPut, "([BIILjava/lang/Object;IIZ)V"),
380adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project};
3817cd6760f7045d771faae8080a8c6150bf678f679Elliott Hughesvoid register_libcore_io_Memory(JNIEnv* env) {
3827cd6760f7045d771faae8080a8c6150bf678f679Elliott Hughes    jniRegisterNativeMethods(env, "libcore/io/Memory", gMethods, NELEM(gMethods));
383adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
384