Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/java/nio/Bits.java
38829 views
/*1* Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package java.nio;2627import java.security.AccessController;28import java.util.concurrent.atomic.AtomicLong;29import java.util.concurrent.atomic.LongAdder;3031import sun.misc.JavaLangRefAccess;32import sun.misc.SharedSecrets;33import sun.misc.Unsafe;34import sun.misc.VM;3536/**37* Access to bits, native and otherwise.38*/3940class Bits { // package-private4142private Bits() { }434445// -- Swapping --4647static short swap(short x) {48return Short.reverseBytes(x);49}5051static char swap(char x) {52return Character.reverseBytes(x);53}5455static int swap(int x) {56return Integer.reverseBytes(x);57}5859static long swap(long x) {60return Long.reverseBytes(x);61}626364// -- get/put char --6566static private char makeChar(byte b1, byte b0) {67return (char)((b1 << 8) | (b0 & 0xff));68}6970static char getCharL(ByteBuffer bb, int bi) {71return makeChar(bb._get(bi + 1),72bb._get(bi ));73}7475static char getCharL(long a) {76return makeChar(_get(a + 1),77_get(a ));78}7980static char getCharB(ByteBuffer bb, int bi) {81return makeChar(bb._get(bi ),82bb._get(bi + 1));83}8485static char getCharB(long a) {86return makeChar(_get(a ),87_get(a + 1));88}8990static char getChar(ByteBuffer bb, int bi, boolean bigEndian) {91return bigEndian ? getCharB(bb, bi) : getCharL(bb, bi);92}9394static char getChar(long a, boolean bigEndian) {95return bigEndian ? getCharB(a) : getCharL(a);96}9798private static byte char1(char x) { return (byte)(x >> 8); }99private static byte char0(char x) { return (byte)(x ); }100101static void putCharL(ByteBuffer bb, int bi, char x) {102bb._put(bi , char0(x));103bb._put(bi + 1, char1(x));104}105106static void putCharL(long a, char x) {107_put(a , char0(x));108_put(a + 1, char1(x));109}110111static void putCharB(ByteBuffer bb, int bi, char x) {112bb._put(bi , char1(x));113bb._put(bi + 1, char0(x));114}115116static void putCharB(long a, char x) {117_put(a , char1(x));118_put(a + 1, char0(x));119}120121static void putChar(ByteBuffer bb, int bi, char x, boolean bigEndian) {122if (bigEndian)123putCharB(bb, bi, x);124else125putCharL(bb, bi, x);126}127128static void putChar(long a, char x, boolean bigEndian) {129if (bigEndian)130putCharB(a, x);131else132putCharL(a, x);133}134135136// -- get/put short --137138static private short makeShort(byte b1, byte b0) {139return (short)((b1 << 8) | (b0 & 0xff));140}141142static short getShortL(ByteBuffer bb, int bi) {143return makeShort(bb._get(bi + 1),144bb._get(bi ));145}146147static short getShortL(long a) {148return makeShort(_get(a + 1),149_get(a ));150}151152static short getShortB(ByteBuffer bb, int bi) {153return makeShort(bb._get(bi ),154bb._get(bi + 1));155}156157static short getShortB(long a) {158return makeShort(_get(a ),159_get(a + 1));160}161162static short getShort(ByteBuffer bb, int bi, boolean bigEndian) {163return bigEndian ? getShortB(bb, bi) : getShortL(bb, bi);164}165166static short getShort(long a, boolean bigEndian) {167return bigEndian ? getShortB(a) : getShortL(a);168}169170private static byte short1(short x) { return (byte)(x >> 8); }171private static byte short0(short x) { return (byte)(x ); }172173static void putShortL(ByteBuffer bb, int bi, short x) {174bb._put(bi , short0(x));175bb._put(bi + 1, short1(x));176}177178static void putShortL(long a, short x) {179_put(a , short0(x));180_put(a + 1, short1(x));181}182183static void putShortB(ByteBuffer bb, int bi, short x) {184bb._put(bi , short1(x));185bb._put(bi + 1, short0(x));186}187188static void putShortB(long a, short x) {189_put(a , short1(x));190_put(a + 1, short0(x));191}192193static void putShort(ByteBuffer bb, int bi, short x, boolean bigEndian) {194if (bigEndian)195putShortB(bb, bi, x);196else197putShortL(bb, bi, x);198}199200static void putShort(long a, short x, boolean bigEndian) {201if (bigEndian)202putShortB(a, x);203else204putShortL(a, x);205}206207208// -- get/put int --209210static private int makeInt(byte b3, byte b2, byte b1, byte b0) {211return (((b3 ) << 24) |212((b2 & 0xff) << 16) |213((b1 & 0xff) << 8) |214((b0 & 0xff) ));215}216217static int getIntL(ByteBuffer bb, int bi) {218return makeInt(bb._get(bi + 3),219bb._get(bi + 2),220bb._get(bi + 1),221bb._get(bi ));222}223224static int getIntL(long a) {225return makeInt(_get(a + 3),226_get(a + 2),227_get(a + 1),228_get(a ));229}230231static int getIntB(ByteBuffer bb, int bi) {232return makeInt(bb._get(bi ),233bb._get(bi + 1),234bb._get(bi + 2),235bb._get(bi + 3));236}237238static int getIntB(long a) {239return makeInt(_get(a ),240_get(a + 1),241_get(a + 2),242_get(a + 3));243}244245static int getInt(ByteBuffer bb, int bi, boolean bigEndian) {246return bigEndian ? getIntB(bb, bi) : getIntL(bb, bi) ;247}248249static int getInt(long a, boolean bigEndian) {250return bigEndian ? getIntB(a) : getIntL(a) ;251}252253private static byte int3(int x) { return (byte)(x >> 24); }254private static byte int2(int x) { return (byte)(x >> 16); }255private static byte int1(int x) { return (byte)(x >> 8); }256private static byte int0(int x) { return (byte)(x ); }257258static void putIntL(ByteBuffer bb, int bi, int x) {259bb._put(bi + 3, int3(x));260bb._put(bi + 2, int2(x));261bb._put(bi + 1, int1(x));262bb._put(bi , int0(x));263}264265static void putIntL(long a, int x) {266_put(a + 3, int3(x));267_put(a + 2, int2(x));268_put(a + 1, int1(x));269_put(a , int0(x));270}271272static void putIntB(ByteBuffer bb, int bi, int x) {273bb._put(bi , int3(x));274bb._put(bi + 1, int2(x));275bb._put(bi + 2, int1(x));276bb._put(bi + 3, int0(x));277}278279static void putIntB(long a, int x) {280_put(a , int3(x));281_put(a + 1, int2(x));282_put(a + 2, int1(x));283_put(a + 3, int0(x));284}285286static void putInt(ByteBuffer bb, int bi, int x, boolean bigEndian) {287if (bigEndian)288putIntB(bb, bi, x);289else290putIntL(bb, bi, x);291}292293static void putInt(long a, int x, boolean bigEndian) {294if (bigEndian)295putIntB(a, x);296else297putIntL(a, x);298}299300301// -- get/put long --302303static private long makeLong(byte b7, byte b6, byte b5, byte b4,304byte b3, byte b2, byte b1, byte b0)305{306return ((((long)b7 ) << 56) |307(((long)b6 & 0xff) << 48) |308(((long)b5 & 0xff) << 40) |309(((long)b4 & 0xff) << 32) |310(((long)b3 & 0xff) << 24) |311(((long)b2 & 0xff) << 16) |312(((long)b1 & 0xff) << 8) |313(((long)b0 & 0xff) ));314}315316static long getLongL(ByteBuffer bb, int bi) {317return makeLong(bb._get(bi + 7),318bb._get(bi + 6),319bb._get(bi + 5),320bb._get(bi + 4),321bb._get(bi + 3),322bb._get(bi + 2),323bb._get(bi + 1),324bb._get(bi ));325}326327static long getLongL(long a) {328return makeLong(_get(a + 7),329_get(a + 6),330_get(a + 5),331_get(a + 4),332_get(a + 3),333_get(a + 2),334_get(a + 1),335_get(a ));336}337338static long getLongB(ByteBuffer bb, int bi) {339return makeLong(bb._get(bi ),340bb._get(bi + 1),341bb._get(bi + 2),342bb._get(bi + 3),343bb._get(bi + 4),344bb._get(bi + 5),345bb._get(bi + 6),346bb._get(bi + 7));347}348349static long getLongB(long a) {350return makeLong(_get(a ),351_get(a + 1),352_get(a + 2),353_get(a + 3),354_get(a + 4),355_get(a + 5),356_get(a + 6),357_get(a + 7));358}359360static long getLong(ByteBuffer bb, int bi, boolean bigEndian) {361return bigEndian ? getLongB(bb, bi) : getLongL(bb, bi);362}363364static long getLong(long a, boolean bigEndian) {365return bigEndian ? getLongB(a) : getLongL(a);366}367368private static byte long7(long x) { return (byte)(x >> 56); }369private static byte long6(long x) { return (byte)(x >> 48); }370private static byte long5(long x) { return (byte)(x >> 40); }371private static byte long4(long x) { return (byte)(x >> 32); }372private static byte long3(long x) { return (byte)(x >> 24); }373private static byte long2(long x) { return (byte)(x >> 16); }374private static byte long1(long x) { return (byte)(x >> 8); }375private static byte long0(long x) { return (byte)(x ); }376377static void putLongL(ByteBuffer bb, int bi, long x) {378bb._put(bi + 7, long7(x));379bb._put(bi + 6, long6(x));380bb._put(bi + 5, long5(x));381bb._put(bi + 4, long4(x));382bb._put(bi + 3, long3(x));383bb._put(bi + 2, long2(x));384bb._put(bi + 1, long1(x));385bb._put(bi , long0(x));386}387388static void putLongL(long a, long x) {389_put(a + 7, long7(x));390_put(a + 6, long6(x));391_put(a + 5, long5(x));392_put(a + 4, long4(x));393_put(a + 3, long3(x));394_put(a + 2, long2(x));395_put(a + 1, long1(x));396_put(a , long0(x));397}398399static void putLongB(ByteBuffer bb, int bi, long x) {400bb._put(bi , long7(x));401bb._put(bi + 1, long6(x));402bb._put(bi + 2, long5(x));403bb._put(bi + 3, long4(x));404bb._put(bi + 4, long3(x));405bb._put(bi + 5, long2(x));406bb._put(bi + 6, long1(x));407bb._put(bi + 7, long0(x));408}409410static void putLongB(long a, long x) {411_put(a , long7(x));412_put(a + 1, long6(x));413_put(a + 2, long5(x));414_put(a + 3, long4(x));415_put(a + 4, long3(x));416_put(a + 5, long2(x));417_put(a + 6, long1(x));418_put(a + 7, long0(x));419}420421static void putLong(ByteBuffer bb, int bi, long x, boolean bigEndian) {422if (bigEndian)423putLongB(bb, bi, x);424else425putLongL(bb, bi, x);426}427428static void putLong(long a, long x, boolean bigEndian) {429if (bigEndian)430putLongB(a, x);431else432putLongL(a, x);433}434435436// -- get/put float --437438static float getFloatL(ByteBuffer bb, int bi) {439return Float.intBitsToFloat(getIntL(bb, bi));440}441442static float getFloatL(long a) {443return Float.intBitsToFloat(getIntL(a));444}445446static float getFloatB(ByteBuffer bb, int bi) {447return Float.intBitsToFloat(getIntB(bb, bi));448}449450static float getFloatB(long a) {451return Float.intBitsToFloat(getIntB(a));452}453454static float getFloat(ByteBuffer bb, int bi, boolean bigEndian) {455return bigEndian ? getFloatB(bb, bi) : getFloatL(bb, bi);456}457458static float getFloat(long a, boolean bigEndian) {459return bigEndian ? getFloatB(a) : getFloatL(a);460}461462static void putFloatL(ByteBuffer bb, int bi, float x) {463putIntL(bb, bi, Float.floatToRawIntBits(x));464}465466static void putFloatL(long a, float x) {467putIntL(a, Float.floatToRawIntBits(x));468}469470static void putFloatB(ByteBuffer bb, int bi, float x) {471putIntB(bb, bi, Float.floatToRawIntBits(x));472}473474static void putFloatB(long a, float x) {475putIntB(a, Float.floatToRawIntBits(x));476}477478static void putFloat(ByteBuffer bb, int bi, float x, boolean bigEndian) {479if (bigEndian)480putFloatB(bb, bi, x);481else482putFloatL(bb, bi, x);483}484485static void putFloat(long a, float x, boolean bigEndian) {486if (bigEndian)487putFloatB(a, x);488else489putFloatL(a, x);490}491492493// -- get/put double --494495static double getDoubleL(ByteBuffer bb, int bi) {496return Double.longBitsToDouble(getLongL(bb, bi));497}498499static double getDoubleL(long a) {500return Double.longBitsToDouble(getLongL(a));501}502503static double getDoubleB(ByteBuffer bb, int bi) {504return Double.longBitsToDouble(getLongB(bb, bi));505}506507static double getDoubleB(long a) {508return Double.longBitsToDouble(getLongB(a));509}510511static double getDouble(ByteBuffer bb, int bi, boolean bigEndian) {512return bigEndian ? getDoubleB(bb, bi) : getDoubleL(bb, bi);513}514515static double getDouble(long a, boolean bigEndian) {516return bigEndian ? getDoubleB(a) : getDoubleL(a);517}518519static void putDoubleL(ByteBuffer bb, int bi, double x) {520putLongL(bb, bi, Double.doubleToRawLongBits(x));521}522523static void putDoubleL(long a, double x) {524putLongL(a, Double.doubleToRawLongBits(x));525}526527static void putDoubleB(ByteBuffer bb, int bi, double x) {528putLongB(bb, bi, Double.doubleToRawLongBits(x));529}530531static void putDoubleB(long a, double x) {532putLongB(a, Double.doubleToRawLongBits(x));533}534535static void putDouble(ByteBuffer bb, int bi, double x, boolean bigEndian) {536if (bigEndian)537putDoubleB(bb, bi, x);538else539putDoubleL(bb, bi, x);540}541542static void putDouble(long a, double x, boolean bigEndian) {543if (bigEndian)544putDoubleB(a, x);545else546putDoubleL(a, x);547}548549550// -- Unsafe access --551552private static final Unsafe unsafe = Unsafe.getUnsafe();553554private static byte _get(long a) {555return unsafe.getByte(a);556}557558private static void _put(long a, byte b) {559unsafe.putByte(a, b);560}561562static Unsafe unsafe() {563return unsafe;564}565566567// -- Processor and memory-system properties --568569private static final ByteOrder byteOrder;570571static ByteOrder byteOrder() {572if (byteOrder == null)573throw new Error("Unknown byte order");574return byteOrder;575}576577static {578long a = unsafe.allocateMemory(8);579try {580unsafe.putLong(a, 0x0102030405060708L);581byte b = unsafe.getByte(a);582switch (b) {583case 0x01: byteOrder = ByteOrder.BIG_ENDIAN; break;584case 0x08: byteOrder = ByteOrder.LITTLE_ENDIAN; break;585default:586assert false;587byteOrder = null;588}589} finally {590unsafe.freeMemory(a);591}592}593594595private static int pageSize = -1;596597static int pageSize() {598if (pageSize == -1)599pageSize = unsafe().pageSize();600return pageSize;601}602603static int pageCount(long size) {604return (int)(size + (long)pageSize() - 1L) / pageSize();605}606607private static boolean unaligned;608private static boolean unalignedKnown = false;609610static boolean unaligned() {611if (unalignedKnown)612return unaligned;613String arch = AccessController.doPrivileged(614new sun.security.action.GetPropertyAction("os.arch"));615unaligned = arch.equals("i386") || arch.equals("x86")616|| arch.equals("amd64") || arch.equals("x86_64")617|| arch.equals("ppc64") || arch.equals("ppc64le")618|| arch.equals("aarch64");619unalignedKnown = true;620return unaligned;621}622623624// -- Direct memory management --625626// A user-settable upper limit on the maximum amount of allocatable627// direct buffer memory. This value may be changed during VM628// initialization if it is launched with "-XX:MaxDirectMemorySize=<size>".629private static volatile long maxMemory = VM.maxDirectMemory();630private static final AtomicLong reservedMemory = new AtomicLong();631private static final AtomicLong totalCapacity = new AtomicLong();632private static final AtomicLong count = new AtomicLong();633private static volatile boolean memoryLimitSet = false;634// max. number of sleeps during try-reserving with exponentially635// increasing delay before throwing OutOfMemoryError:636// 1, 2, 4, 8, 16, 32, 64, 128, 256 (total 511 ms ~ 0.5 s)637// which means that OOME will be thrown after 0.5 s of trying638private static final int MAX_SLEEPS = 9;639640// These methods should be called whenever direct memory is allocated or641// freed. They allow the user to control the amount of direct memory642// which a process may access. All sizes are specified in bytes.643static void reserveMemory(long size, int cap) {644645if (!memoryLimitSet && VM.isBooted()) {646maxMemory = VM.maxDirectMemory();647memoryLimitSet = true;648}649650// optimist!651if (tryReserveMemory(size, cap)) {652return;653}654655final JavaLangRefAccess jlra = SharedSecrets.getJavaLangRefAccess();656657// retry while helping enqueue pending Reference objects658// which includes executing pending Cleaner(s) which includes659// Cleaner(s) that free direct buffer memory660while (jlra.tryHandlePendingReference()) {661if (tryReserveMemory(size, cap)) {662return;663}664}665666// trigger VM's Reference processing667System.gc();668669// a retry loop with exponential back-off delays670// (this gives VM some time to do it's job)671boolean interrupted = false;672try {673long sleepTime = 1;674int sleeps = 0;675while (true) {676if (tryReserveMemory(size, cap)) {677return;678}679if (sleeps >= MAX_SLEEPS) {680break;681}682if (!jlra.tryHandlePendingReference()) {683try {684Thread.sleep(sleepTime);685sleepTime <<= 1;686sleeps++;687} catch (InterruptedException e) {688interrupted = true;689}690}691}692693// no luck694throw new OutOfMemoryError("Direct buffer memory");695696} finally {697if (interrupted) {698// don't swallow interrupts699Thread.currentThread().interrupt();700}701}702}703704private static boolean tryReserveMemory(long size, int cap) {705706// -XX:MaxDirectMemorySize limits the total capacity rather than the707// actual memory usage, which will differ when buffers are page708// aligned.709long totalCap;710while (cap <= maxMemory - (totalCap = totalCapacity.get())) {711if (totalCapacity.compareAndSet(totalCap, totalCap + cap)) {712reservedMemory.addAndGet(size);713count.incrementAndGet();714return true;715}716}717718return false;719}720721722static void unreserveMemory(long size, int cap) {723long cnt = count.decrementAndGet();724long reservedMem = reservedMemory.addAndGet(-size);725long totalCap = totalCapacity.addAndGet(-cap);726assert cnt >= 0 && reservedMem >= 0 && totalCap >= 0;727}728729// -- Monitoring of direct buffer usage --730731static {732// setup access to this package in SharedSecrets733sun.misc.SharedSecrets.setJavaNioAccess(734new sun.misc.JavaNioAccess() {735@Override736public sun.misc.JavaNioAccess.BufferPool getDirectBufferPool() {737return new sun.misc.JavaNioAccess.BufferPool() {738@Override739public String getName() {740return "direct";741}742@Override743public long getCount() {744return Bits.count.get();745}746@Override747public long getTotalCapacity() {748return Bits.totalCapacity.get();749}750@Override751public long getMemoryUsed() {752return Bits.reservedMemory.get();753}754};755}756@Override757public ByteBuffer newDirectByteBuffer(long addr, int cap, Object ob) {758return new DirectByteBuffer(addr, cap, ob);759}760@Override761public void truncate(Buffer buf) {762buf.truncate();763}764});765}766767// -- Bulk get/put acceleration --768769// These numbers represent the point at which we have empirically770// determined that the average cost of a JNI call exceeds the expense771// of an element by element copy. These numbers may change over time.772static final int JNI_COPY_TO_ARRAY_THRESHOLD = 6;773static final int JNI_COPY_FROM_ARRAY_THRESHOLD = 6;774775// This number limits the number of bytes to copy per call to Unsafe's776// copyMemory method. A limit is imposed to allow for safepoint polling777// during a large copy778static final long UNSAFE_COPY_THRESHOLD = 1024L * 1024L;779780// These methods do no bounds checking. Verification that the copy will not781// result in memory corruption should be done prior to invocation.782// All positions and lengths are specified in bytes.783784/**785* Copy from given source array to destination address.786*787* @param src788* source array789* @param srcBaseOffset790* offset of first element of storage in source array791* @param srcPos792* offset within source array of the first element to read793* @param dstAddr794* destination address795* @param length796* number of bytes to copy797*/798static void copyFromArray(Object src, long srcBaseOffset, long srcPos,799long dstAddr, long length)800{801long offset = srcBaseOffset + srcPos;802while (length > 0) {803long size = (length > UNSAFE_COPY_THRESHOLD) ? UNSAFE_COPY_THRESHOLD : length;804unsafe.copyMemory(src, offset, null, dstAddr, size);805length -= size;806offset += size;807dstAddr += size;808}809}810811/**812* Copy from source address into given destination array.813*814* @param srcAddr815* source address816* @param dst817* destination array818* @param dstBaseOffset819* offset of first element of storage in destination array820* @param dstPos821* offset within destination array of the first element to write822* @param length823* number of bytes to copy824*/825static void copyToArray(long srcAddr, Object dst, long dstBaseOffset, long dstPos,826long length)827{828long offset = dstBaseOffset + dstPos;829while (length > 0) {830long size = (length > UNSAFE_COPY_THRESHOLD) ? UNSAFE_COPY_THRESHOLD : length;831unsafe.copyMemory(null, srcAddr, dst, offset, size);832length -= size;833srcAddr += size;834offset += size;835}836}837838/**839* Copy and unconditionally byte swap 16 bit elements from a heap array to off-heap memory840*841* @param src842* the source array, must be a 16-bit primitive array type843* @param srcPos844* byte offset within source array of the first element to read845* @param dstAddr846* destination address847* @param length848* number of bytes to copy849*/850static void copyFromCharArray(Object src, long srcPos, long dstAddr, long length) {851copySwapMemory(src, unsafe.arrayBaseOffset(src.getClass()) + srcPos, null, dstAddr, length, 2);852}853854/**855* Copy and unconditionally byte swap 16 bit elements from off-heap memory to a heap array856*857* @param srcAddr858* source address859* @param dst860* destination array, must be a 16-bit primitive array type861* @param dstPos862* byte offset within the destination array of the first element to write863* @param length864* number of bytes to copy865*/866static void copyToCharArray(long srcAddr, Object dst, long dstPos, long length) {867copySwapMemory(null, srcAddr, dst, unsafe.arrayBaseOffset(dst.getClass()) + dstPos, length, 2);868}869870/**871* Copy and unconditionally byte swap 16 bit elements from a heap array to off-heap memory872*873* @param src874* the source array, must be a 16-bit primitive array type875* @param srcPos876* byte offset within source array of the first element to read877* @param dstAddr878* destination address879* @param length880* number of bytes to copy881*/882static void copyFromShortArray(Object src, long srcPos, long dstAddr, long length) {883copySwapMemory(src, unsafe.arrayBaseOffset(src.getClass()) + srcPos, null, dstAddr, length, 2);884}885886/**887* Copy and unconditionally byte swap 16 bit elements from off-heap memory to a heap array888*889* @param srcAddr890* source address891* @param dst892* destination array, must be a 16-bit primitive array type893* @param dstPos894* byte offset within the destination array of the first element to write895* @param length896* number of bytes to copy897*/898static void copyToShortArray(long srcAddr, Object dst, long dstPos, long length) {899copySwapMemory(null, srcAddr, dst, unsafe.arrayBaseOffset(dst.getClass()) + dstPos, length, 2);900}901902/**903* Copy and unconditionally byte swap 32 bit elements from a heap array to off-heap memory904*905* @param src906* the source array, must be a 32-bit primitive array type907* @param srcPos908* byte offset within source array of the first element to read909* @param dstAddr910* destination address911* @param length912* number of bytes to copy913*/914static void copyFromIntArray(Object src, long srcPos, long dstAddr, long length) {915copySwapMemory(src, unsafe.arrayBaseOffset(src.getClass()) + srcPos, null, dstAddr, length, 4);916}917918/**919* Copy and unconditionally byte swap 32 bit elements from off-heap memory to a heap array920*921* @param srcAddr922* source address923* @param dst924* destination array, must be a 32-bit primitive array type925* @param dstPos926* byte offset within the destination array of the first element to write927* @param length928* number of bytes to copy929*/930static void copyToIntArray(long srcAddr, Object dst, long dstPos, long length) {931copySwapMemory(null, srcAddr, dst, unsafe.arrayBaseOffset(dst.getClass()) + dstPos, length, 4);932}933934/**935* Copy and unconditionally byte swap 64 bit elements from a heap array to off-heap memory936*937* @param src938* the source array, must be a 64-bit primitive array type939* @param srcPos940* byte offset within source array of the first element to read941* @param dstAddr942* destination address943* @param length944* number of bytes to copy945*/946static void copyFromLongArray(Object src, long srcPos, long dstAddr, long length) {947copySwapMemory(src, unsafe.arrayBaseOffset(src.getClass()) + srcPos, null, dstAddr, length, 8);948}949950/**951* Copy and unconditionally byte swap 64 bit elements from off-heap memory to a heap array952*953* @param srcAddr954* source address955* @param dst956* destination array, must be a 64-bit primitive array type957* @param dstPos958* byte offset within the destination array of the first element to write959* @param length960* number of bytes to copy961*/962static void copyToLongArray(long srcAddr, Object dst, long dstPos, long length) {963copySwapMemory(null, srcAddr, dst, unsafe.arrayBaseOffset(dst.getClass()) + dstPos, length, 8);964}965966private static boolean isPrimitiveArray(Class<?> c) {967Class<?> componentType = c.getComponentType();968return componentType != null && componentType.isPrimitive();969}970971private native static void copySwapMemory0(Object srcBase, long srcOffset,972Object destBase, long destOffset,973long bytes, long elemSize);974975/**976* Copies all elements from one block of memory to another block,977* *unconditionally* byte swapping the elements on the fly.978*979* <p>This method determines each block's base address by means of two parameters,980* and so it provides (in effect) a <em>double-register</em> addressing mode,981* as discussed in {@link sun.misc.Unsafe#getInt(Object,long)}. When the982* object reference is null, the offset supplies an absolute base address.983*984* @since 8u201985*/986private static void copySwapMemory(Object srcBase, long srcOffset,987Object destBase, long destOffset,988long bytes, long elemSize) {989if (bytes < 0) {990throw new IllegalArgumentException();991}992if (elemSize != 2 && elemSize != 4 && elemSize != 8) {993throw new IllegalArgumentException();994}995if (bytes % elemSize != 0) {996throw new IllegalArgumentException();997}998if ((srcBase == null && srcOffset == 0) ||999(destBase == null && destOffset == 0)) {1000throw new NullPointerException();1001}10021003// Must be off-heap, or primitive heap arrays1004if (srcBase != null && (srcOffset < 0 || !isPrimitiveArray(srcBase.getClass()))) {1005throw new IllegalArgumentException();1006}1007if (destBase != null && (destOffset < 0 || !isPrimitiveArray(destBase.getClass()))) {1008throw new IllegalArgumentException();1009}10101011// Sanity check size and offsets on 32-bit platforms. Most1012// significant 32 bits must be zero.1013if (unsafe.addressSize() == 4 &&1014(bytes >>> 32 != 0 || srcOffset >>> 32 != 0 || destOffset >>> 32 != 0)) {1015throw new IllegalArgumentException();1016}10171018if (bytes == 0) {1019return;1020}10211022copySwapMemory0(srcBase, srcOffset, destBase, destOffset, bytes, elemSize);1023}10241025}102610271028