1/*
2 * Copyright (C) 2014 The Android Open Source Project
3 * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 *
6 * This code is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License version 2 only, as
8 * published by the Free Software Foundation.  Oracle designates this
9 * particular file as subject to the "Classpath" exception as provided
10 * by Oracle in the LICENSE file that accompanied this code.
11 *
12 * This code is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15 * version 2 for more details (a copy is included in the LICENSE file that
16 * accompanied this code).
17 *
18 * You should have received a copy of the GNU General Public License version
19 * 2 along with this work; if not, write to the Free Software Foundation,
20 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
21 *
22 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
23 * or visit www.oracle.com if you need additional information or have any
24 * questions.
25 */
26
27package java.nio;
28
29import java.security.AccessController;
30
31import sun.misc.Unsafe;
32import sun.misc.VM;
33
34/**
35 * Access to bits, native and otherwise.
36 */
37
38class Bits {                            // package-private
39
40    private Bits() {
41    }
42
43
44    // -- Swapping --
45
46    static short swap(short x) {
47        return Short.reverseBytes(x);
48    }
49
50    static char swap(char x) {
51        return Character.reverseBytes(x);
52    }
53
54    static int swap(int x) {
55        return Integer.reverseBytes(x);
56    }
57
58    static long swap(long x) {
59        return Long.reverseBytes(x);
60    }
61
62
63    // -- get/put char --
64
65    static private char makeChar(byte b1, byte b0) {
66        return (char) ((b1 << 8) | (b0 & 0xff));
67    }
68
69    static char getCharL(ByteBuffer bb, int bi) {
70        return makeChar(bb._get(bi + 1),
71                bb._get(bi));
72    }
73
74    static char getCharL(long a) {
75        return makeChar(_get(a + 1),
76                _get(a));
77    }
78
79    static char getCharB(ByteBuffer bb, int bi) {
80        return makeChar(bb._get(bi),
81                bb._get(bi + 1));
82    }
83
84    static char getCharB(long a) {
85        return makeChar(_get(a),
86                _get(a + 1));
87    }
88
89    static char getChar(ByteBuffer bb, int bi, boolean bigEndian) {
90        return bigEndian ? getCharB(bb, bi) : getCharL(bb, bi);
91    }
92
93    static char getChar(long a, boolean bigEndian) {
94        return bigEndian ? getCharB(a) : getCharL(a);
95    }
96
97    private static byte char1(char x) {
98        return (byte) (x >> 8);
99    }
100
101    private static byte char0(char x) {
102        return (byte) (x);
103    }
104
105    static void putCharL(ByteBuffer bb, int bi, char x) {
106        bb._put(bi, char0(x));
107        bb._put(bi + 1, char1(x));
108    }
109
110    static void putCharL(long a, char x) {
111        _put(a, char0(x));
112        _put(a + 1, char1(x));
113    }
114
115    static void putCharB(ByteBuffer bb, int bi, char x) {
116        bb._put(bi, char1(x));
117        bb._put(bi + 1, char0(x));
118    }
119
120    static void putCharB(long a, char x) {
121        _put(a, char1(x));
122        _put(a + 1, char0(x));
123    }
124
125    static void putChar(ByteBuffer bb, int bi, char x, boolean bigEndian) {
126        if (bigEndian)
127            putCharB(bb, bi, x);
128        else
129            putCharL(bb, bi, x);
130    }
131
132    static void putChar(long a, char x, boolean bigEndian) {
133        if (bigEndian)
134            putCharB(a, x);
135        else
136            putCharL(a, x);
137    }
138
139
140    // -- get/put short --
141
142    static private short makeShort(byte b1, byte b0) {
143        return (short) ((b1 << 8) | (b0 & 0xff));
144    }
145
146    static short getShortL(ByteBuffer bb, int bi) {
147        return makeShort(bb._get(bi + 1),
148                bb._get(bi));
149    }
150
151    static short getShortL(long a) {
152        return makeShort(_get(a + 1),
153                _get(a));
154    }
155
156    static short getShortB(ByteBuffer bb, int bi) {
157        return makeShort(bb._get(bi),
158                bb._get(bi + 1));
159    }
160
161    static short getShortB(long a) {
162        return makeShort(_get(a),
163                _get(a + 1));
164    }
165
166    static short getShort(ByteBuffer bb, int bi, boolean bigEndian) {
167        return bigEndian ? getShortB(bb, bi) : getShortL(bb, bi);
168    }
169
170    static short getShort(long a, boolean bigEndian) {
171        return bigEndian ? getShortB(a) : getShortL(a);
172    }
173
174    private static byte short1(short x) {
175        return (byte) (x >> 8);
176    }
177
178    private static byte short0(short x) {
179        return (byte) (x);
180    }
181
182    static void putShortL(ByteBuffer bb, int bi, short x) {
183        bb._put(bi, short0(x));
184        bb._put(bi + 1, short1(x));
185    }
186
187    static void putShortL(long a, short x) {
188        _put(a, short0(x));
189        _put(a + 1, short1(x));
190    }
191
192    static void putShortB(ByteBuffer bb, int bi, short x) {
193        bb._put(bi, short1(x));
194        bb._put(bi + 1, short0(x));
195    }
196
197    static void putShortB(long a, short x) {
198        _put(a, short1(x));
199        _put(a + 1, short0(x));
200    }
201
202    static void putShort(ByteBuffer bb, int bi, short x, boolean bigEndian) {
203        if (bigEndian)
204            putShortB(bb, bi, x);
205        else
206            putShortL(bb, bi, x);
207    }
208
209    static void putShort(long a, short x, boolean bigEndian) {
210        if (bigEndian)
211            putShortB(a, x);
212        else
213            putShortL(a, x);
214    }
215
216
217    // -- get/put int --
218
219    static private int makeInt(byte b3, byte b2, byte b1, byte b0) {
220        return (((b3) << 24) |
221                ((b2 & 0xff) << 16) |
222                ((b1 & 0xff) << 8) |
223                ((b0 & 0xff)));
224    }
225
226    static int getIntL(ByteBuffer bb, int bi) {
227        return makeInt(bb._get(bi + 3),
228                bb._get(bi + 2),
229                bb._get(bi + 1),
230                bb._get(bi));
231    }
232
233    static int getIntL(long a) {
234        return makeInt(_get(a + 3),
235                _get(a + 2),
236                _get(a + 1),
237                _get(a));
238    }
239
240    static int getIntB(ByteBuffer bb, int bi) {
241        return makeInt(bb._get(bi),
242                bb._get(bi + 1),
243                bb._get(bi + 2),
244                bb._get(bi + 3));
245    }
246
247    static int getIntB(long a) {
248        return makeInt(_get(a),
249                _get(a + 1),
250                _get(a + 2),
251                _get(a + 3));
252    }
253
254    static int getInt(ByteBuffer bb, int bi, boolean bigEndian) {
255        return bigEndian ? getIntB(bb, bi) : getIntL(bb, bi);
256    }
257
258    static int getInt(long a, boolean bigEndian) {
259        return bigEndian ? getIntB(a) : getIntL(a);
260    }
261
262    private static byte int3(int x) {
263        return (byte) (x >> 24);
264    }
265
266    private static byte int2(int x) {
267        return (byte) (x >> 16);
268    }
269
270    private static byte int1(int x) {
271        return (byte) (x >> 8);
272    }
273
274    private static byte int0(int x) {
275        return (byte) (x);
276    }
277
278    static void putIntL(ByteBuffer bb, int bi, int x) {
279        bb._put(bi + 3, int3(x));
280        bb._put(bi + 2, int2(x));
281        bb._put(bi + 1, int1(x));
282        bb._put(bi, int0(x));
283    }
284
285    static void putIntL(long a, int x) {
286        _put(a + 3, int3(x));
287        _put(a + 2, int2(x));
288        _put(a + 1, int1(x));
289        _put(a, int0(x));
290    }
291
292    static void putIntB(ByteBuffer bb, int bi, int x) {
293        bb._put(bi, int3(x));
294        bb._put(bi + 1, int2(x));
295        bb._put(bi + 2, int1(x));
296        bb._put(bi + 3, int0(x));
297    }
298
299    static void putIntB(long a, int x) {
300        _put(a, int3(x));
301        _put(a + 1, int2(x));
302        _put(a + 2, int1(x));
303        _put(a + 3, int0(x));
304    }
305
306    static void putInt(ByteBuffer bb, int bi, int x, boolean bigEndian) {
307        if (bigEndian)
308            putIntB(bb, bi, x);
309        else
310            putIntL(bb, bi, x);
311    }
312
313    static void putInt(long a, int x, boolean bigEndian) {
314        if (bigEndian)
315            putIntB(a, x);
316        else
317            putIntL(a, x);
318    }
319
320
321    // -- get/put long --
322
323    static private long makeLong(byte b7, byte b6, byte b5, byte b4,
324                                 byte b3, byte b2, byte b1, byte b0) {
325        return ((((long) b7) << 56) |
326                (((long) b6 & 0xff) << 48) |
327                (((long) b5 & 0xff) << 40) |
328                (((long) b4 & 0xff) << 32) |
329                (((long) b3 & 0xff) << 24) |
330                (((long) b2 & 0xff) << 16) |
331                (((long) b1 & 0xff) << 8) |
332                (((long) b0 & 0xff)));
333    }
334
335    static long getLongL(ByteBuffer bb, int bi) {
336        return makeLong(bb._get(bi + 7),
337                bb._get(bi + 6),
338                bb._get(bi + 5),
339                bb._get(bi + 4),
340                bb._get(bi + 3),
341                bb._get(bi + 2),
342                bb._get(bi + 1),
343                bb._get(bi));
344    }
345
346    static long getLongL(long a) {
347        return makeLong(_get(a + 7),
348                _get(a + 6),
349                _get(a + 5),
350                _get(a + 4),
351                _get(a + 3),
352                _get(a + 2),
353                _get(a + 1),
354                _get(a));
355    }
356
357    static long getLongB(ByteBuffer bb, int bi) {
358        return makeLong(bb._get(bi),
359                bb._get(bi + 1),
360                bb._get(bi + 2),
361                bb._get(bi + 3),
362                bb._get(bi + 4),
363                bb._get(bi + 5),
364                bb._get(bi + 6),
365                bb._get(bi + 7));
366    }
367
368    static long getLongB(long a) {
369        return makeLong(_get(a),
370                _get(a + 1),
371                _get(a + 2),
372                _get(a + 3),
373                _get(a + 4),
374                _get(a + 5),
375                _get(a + 6),
376                _get(a + 7));
377    }
378
379    static long getLong(ByteBuffer bb, int bi, boolean bigEndian) {
380        return bigEndian ? getLongB(bb, bi) : getLongL(bb, bi);
381    }
382
383    static long getLong(long a, boolean bigEndian) {
384        return bigEndian ? getLongB(a) : getLongL(a);
385    }
386
387    private static byte long7(long x) {
388        return (byte) (x >> 56);
389    }
390
391    private static byte long6(long x) {
392        return (byte) (x >> 48);
393    }
394
395    private static byte long5(long x) {
396        return (byte) (x >> 40);
397    }
398
399    private static byte long4(long x) {
400        return (byte) (x >> 32);
401    }
402
403    private static byte long3(long x) {
404        return (byte) (x >> 24);
405    }
406
407    private static byte long2(long x) {
408        return (byte) (x >> 16);
409    }
410
411    private static byte long1(long x) {
412        return (byte) (x >> 8);
413    }
414
415    private static byte long0(long x) {
416        return (byte) (x);
417    }
418
419    static void putLongL(ByteBuffer bb, int bi, long x) {
420        bb._put(bi + 7, long7(x));
421        bb._put(bi + 6, long6(x));
422        bb._put(bi + 5, long5(x));
423        bb._put(bi + 4, long4(x));
424        bb._put(bi + 3, long3(x));
425        bb._put(bi + 2, long2(x));
426        bb._put(bi + 1, long1(x));
427        bb._put(bi, long0(x));
428    }
429
430    static void putLongL(long a, long x) {
431        _put(a + 7, long7(x));
432        _put(a + 6, long6(x));
433        _put(a + 5, long5(x));
434        _put(a + 4, long4(x));
435        _put(a + 3, long3(x));
436        _put(a + 2, long2(x));
437        _put(a + 1, long1(x));
438        _put(a, long0(x));
439    }
440
441    static void putLongB(ByteBuffer bb, int bi, long x) {
442        bb._put(bi, long7(x));
443        bb._put(bi + 1, long6(x));
444        bb._put(bi + 2, long5(x));
445        bb._put(bi + 3, long4(x));
446        bb._put(bi + 4, long3(x));
447        bb._put(bi + 5, long2(x));
448        bb._put(bi + 6, long1(x));
449        bb._put(bi + 7, long0(x));
450    }
451
452    static void putLongB(long a, long x) {
453        _put(a, long7(x));
454        _put(a + 1, long6(x));
455        _put(a + 2, long5(x));
456        _put(a + 3, long4(x));
457        _put(a + 4, long3(x));
458        _put(a + 5, long2(x));
459        _put(a + 6, long1(x));
460        _put(a + 7, long0(x));
461    }
462
463    static void putLong(ByteBuffer bb, int bi, long x, boolean bigEndian) {
464        if (bigEndian)
465            putLongB(bb, bi, x);
466        else
467            putLongL(bb, bi, x);
468    }
469
470    static void putLong(long a, long x, boolean bigEndian) {
471        if (bigEndian)
472            putLongB(a, x);
473        else
474            putLongL(a, x);
475    }
476
477
478    // -- get/put float --
479
480    static float getFloatL(ByteBuffer bb, int bi) {
481        return Float.intBitsToFloat(getIntL(bb, bi));
482    }
483
484    static float getFloatL(long a) {
485        return Float.intBitsToFloat(getIntL(a));
486    }
487
488    static float getFloatB(ByteBuffer bb, int bi) {
489        return Float.intBitsToFloat(getIntB(bb, bi));
490    }
491
492    static float getFloatB(long a) {
493        return Float.intBitsToFloat(getIntB(a));
494    }
495
496    static float getFloat(ByteBuffer bb, int bi, boolean bigEndian) {
497        return bigEndian ? getFloatB(bb, bi) : getFloatL(bb, bi);
498    }
499
500    static float getFloat(long a, boolean bigEndian) {
501        return bigEndian ? getFloatB(a) : getFloatL(a);
502    }
503
504    static void putFloatL(ByteBuffer bb, int bi, float x) {
505        putIntL(bb, bi, Float.floatToRawIntBits(x));
506    }
507
508    static void putFloatL(long a, float x) {
509        putIntL(a, Float.floatToRawIntBits(x));
510    }
511
512    static void putFloatB(ByteBuffer bb, int bi, float x) {
513        putIntB(bb, bi, Float.floatToRawIntBits(x));
514    }
515
516    static void putFloatB(long a, float x) {
517        putIntB(a, Float.floatToRawIntBits(x));
518    }
519
520    static void putFloat(ByteBuffer bb, int bi, float x, boolean bigEndian) {
521        if (bigEndian)
522            putFloatB(bb, bi, x);
523        else
524            putFloatL(bb, bi, x);
525    }
526
527    static void putFloat(long a, float x, boolean bigEndian) {
528        if (bigEndian)
529            putFloatB(a, x);
530        else
531            putFloatL(a, x);
532    }
533
534
535    // -- get/put double --
536
537    static double getDoubleL(ByteBuffer bb, int bi) {
538        return Double.longBitsToDouble(getLongL(bb, bi));
539    }
540
541    static double getDoubleL(long a) {
542        return Double.longBitsToDouble(getLongL(a));
543    }
544
545    static double getDoubleB(ByteBuffer bb, int bi) {
546        return Double.longBitsToDouble(getLongB(bb, bi));
547    }
548
549    static double getDoubleB(long a) {
550        return Double.longBitsToDouble(getLongB(a));
551    }
552
553    static double getDouble(ByteBuffer bb, int bi, boolean bigEndian) {
554        return bigEndian ? getDoubleB(bb, bi) : getDoubleL(bb, bi);
555    }
556
557    static double getDouble(long a, boolean bigEndian) {
558        return bigEndian ? getDoubleB(a) : getDoubleL(a);
559    }
560
561    static void putDoubleL(ByteBuffer bb, int bi, double x) {
562        putLongL(bb, bi, Double.doubleToRawLongBits(x));
563    }
564
565    static void putDoubleL(long a, double x) {
566        putLongL(a, Double.doubleToRawLongBits(x));
567    }
568
569    static void putDoubleB(ByteBuffer bb, int bi, double x) {
570        putLongB(bb, bi, Double.doubleToRawLongBits(x));
571    }
572
573    static void putDoubleB(long a, double x) {
574        putLongB(a, Double.doubleToRawLongBits(x));
575    }
576
577    static void putDouble(ByteBuffer bb, int bi, double x, boolean bigEndian) {
578        if (bigEndian)
579            putDoubleB(bb, bi, x);
580        else
581            putDoubleL(bb, bi, x);
582    }
583
584    static void putDouble(long a, double x, boolean bigEndian) {
585        if (bigEndian)
586            putDoubleB(a, x);
587        else
588            putDoubleL(a, x);
589    }
590
591
592    // -- Unsafe access --
593
594    private static final Unsafe unsafe = Unsafe.getUnsafe();
595
596    private static byte _get(long a) {
597        return unsafe.getByte(a);
598    }
599
600    private static void _put(long a, byte b) {
601        unsafe.putByte(a, b);
602    }
603
604    static Unsafe unsafe() {
605        return unsafe;
606    }
607
608
609    // -- Processor and memory-system properties --
610
611    /* ----- BEGIN android -----
612    private static final ByteOrder byteOrder;*/
613    private static final ByteOrder byteOrder = ByteOrder.LITTLE_ENDIAN;
614    // ----- END android -----
615
616    static ByteOrder byteOrder() {
617        // Android changed : android is always little endian.
618        return byteOrder;
619
620        /* ----- BEGIN android -----
621        if (byteOrder == null)
622            throw new Error("Unknown byte order");
623        if (byteOrder == null) {
624            long a = unsafe.allocateMemory(8);
625            try {
626                unsafe.putLong(a, 0x0102030405060708L);
627                byte b = unsafe.getByte(a);
628                switch (b) {
629                    case 0x01: byteOrder = ByteOrder.BIG_ENDIAN;     break;
630                    case 0x08: byteOrder = ByteOrder.LITTLE_ENDIAN;  break;
631                    default: throw new Error("Unknown byte order");
632                }
633            } finally {
634                unsafe.freeMemory(a);
635            }
636        }
637        return byteOrder;
638        */
639    }
640
641    /* ----- BEGIN android -----
642    static {
643        long a = unsafe.allocateMemory(8);
644        try {
645            unsafe.putLong(a, 0x0102030405060708L);
646            byte b = unsafe.getByte(a);
647            switch (b) {
648            case 0x01: byteOrder = ByteOrder.BIG_ENDIAN;     break;
649            case 0x08: byteOrder = ByteOrder.LITTLE_ENDIAN;  break;
650            default:
651                assert false;
652                byteOrder = null;
653            }
654        } finally {
655            unsafe.freeMemory(a);
656        }
657    }
658    ----- END android ----- */
659
660
661    private static int pageSize = -1;
662
663    static int pageSize() {
664        if (pageSize == -1)
665            pageSize = unsafe().pageSize();
666        return pageSize;
667    }
668
669    static int pageCount(long size) {
670        return (int) (size + (long) pageSize() - 1L) / pageSize();
671    }
672
673    private static boolean unaligned;
674    private static boolean unalignedKnown = false;
675
676    static boolean unaligned() {
677        if (unalignedKnown)
678            return unaligned;
679        String arch = AccessController.doPrivileged(
680                new sun.security.action.GetPropertyAction("os.arch"));
681        unaligned = arch.equals("i386") || arch.equals("x86")
682                || arch.equals("amd64") || arch.equals("x86_64");
683        unalignedKnown = true;
684        return unaligned;
685    }
686
687
688    // -- Direct memory management --
689
690    // A user-settable upper limit on the maximum amount of allocatable
691    // direct buffer memory.  This value may be changed during VM
692    // initialization if it is launched with "-XX:MaxDirectMemorySize=<size>".
693    private static volatile long maxMemory = VM.maxDirectMemory();
694    private static volatile long reservedMemory;
695    private static volatile long totalCapacity;
696    private static volatile long count;
697    private static boolean memoryLimitSet = false;
698
699    // These methods should be called whenever direct memory is allocated or
700    // freed.  They allow the user to control the amount of direct memory
701    // which a process may access.  All sizes are specified in bytes.
702    static void reserveMemory(long size, int cap) {
703        synchronized (Bits.class) {
704            if (!memoryLimitSet && VM.isBooted()) {
705                maxMemory = VM.maxDirectMemory();
706                memoryLimitSet = true;
707            }
708            // -XX:MaxDirectMemorySize limits the total capacity rather than the
709            // actual memory usage, which will differ when buffers are page
710            // aligned.
711            if (cap <= maxMemory - totalCapacity) {
712                reservedMemory += size;
713                totalCapacity += cap;
714                count++;
715                return;
716            }
717        }
718
719        System.gc();
720        try {
721            Thread.sleep(100);
722        } catch (InterruptedException x) {
723            // Restore interrupt status
724            Thread.currentThread().interrupt();
725        }
726        synchronized (Bits.class) {
727            if (totalCapacity + cap > maxMemory)
728                throw new OutOfMemoryError("Direct buffer memory");
729            reservedMemory += size;
730            totalCapacity += cap;
731            count++;
732        }
733
734    }
735
736    static synchronized void unreserveMemory(long size, int cap) {
737        if (reservedMemory > 0) {
738            reservedMemory -= size;
739            totalCapacity -= cap;
740            count--;
741            assert (reservedMemory > -1);
742        }
743    }
744
745    // -- Monitoring of direct buffer usage --
746
747    /* ----- BEGIN android -----
748    static {
749        // setup access to this package in SharedSecrets
750        sun.misc.SharedSecrets.setJavaNioAccess(
751            new sun.misc.JavaNioAccess() {
752                @Override
753                public sun.misc.JavaNioAccess.BufferPool getDirectBufferPool() {
754                    return new sun.misc.JavaNioAccess.BufferPool() {
755                        @Override
756                        public String getName() {
757                            return "direct";
758                        }
759                        @Override
760                        public long getCount() {
761                            return Bits.count;
762                        }
763                        @Override
764                        public long getTotalCapacity() {
765                            return Bits.totalCapacity;
766                        }
767                        @Override
768                        public long getMemoryUsed() {
769                            return Bits.reservedMemory;
770                        }
771                    };
772                }
773                @Override
774                public ByteBuffer newDirectByteBuffer(long addr, int cap, Object ob) {
775                    return new DirectByteBuffer(addr, cap, ob);
776                }
777                @Override
778                public void truncate(Buffer buf) {
779                    buf.truncate();
780                }
781        });
782    }
783    ----- END android ----- */
784
785    // -- Bulk get/put acceleration --
786
787    // These numbers represent the point at which we have empirically
788    // determined that the average cost of a JNI call exceeds the expense
789    // of an element by element copy.  These numbers may change over time.
790    static final int JNI_COPY_TO_ARRAY_THRESHOLD = 6;
791    static final int JNI_COPY_FROM_ARRAY_THRESHOLD = 6;
792
793    // This number limits the number of bytes to copy per call to Unsafe's
794    // copyMemory method. A limit is imposed to allow for safepoint polling
795    // during a large copy
796    static final long UNSAFE_COPY_THRESHOLD = 1024L * 1024L;
797
798    // These methods do no bounds checking.  Verification that the copy will not
799    // result in memory corruption should be done prior to invocation.
800    // All positions and lengths are specified in bytes.
801
802    /**
803     * Copy from given source array to destination address.
804     *
805     * @param src           source array
806     * @param srcBaseOffset offset of first element of storage in source array
807     * @param srcPos        offset within source array of the first element to read
808     * @param dstAddr       destination address
809     * @param length        number of bytes to copy
810     */
811    static void copyFromArray(Object src, long srcBaseOffset, long srcPos,
812                              long dstAddr, long length) {
813        long offset = srcBaseOffset + srcPos;
814        while (length > 0) {
815            long size = (length > UNSAFE_COPY_THRESHOLD) ? UNSAFE_COPY_THRESHOLD : length;
816            unsafe.copyMemoryFromPrimitiveArray(src, offset, dstAddr, size);
817            length -= size;
818            offset += size;
819            dstAddr += size;
820        }
821    }
822
823    /**
824     * Copy from source address into given destination array.
825     *
826     * @param srcAddr       source address
827     * @param dst           destination array
828     * @param dstBaseOffset offset of first element of storage in destination array
829     * @param dstPos        offset within destination array of the first element to write
830     * @param length        number of bytes to copy
831     */
832    static void copyToArray(long srcAddr, Object dst, long dstBaseOffset, long dstPos,
833                            long length) {
834        long offset = dstBaseOffset + dstPos;
835        while (length > 0) {
836            long size = (length > UNSAFE_COPY_THRESHOLD) ? UNSAFE_COPY_THRESHOLD : length;
837            unsafe.copyMemoryToPrimitiveArray(srcAddr, dst, offset, size);
838            length -= size;
839            srcAddr += size;
840            offset += size;
841        }
842    }
843
844    static void copyFromCharArray(Object src, long srcPos, long dstAddr,
845                                  long length) {
846        copyFromShortArray(src, srcPos, dstAddr, length);
847    }
848
849    static void copyToCharArray(long srcAddr, Object dst, long dstPos,
850                                long length) {
851        copyToShortArray(srcAddr, dst, dstPos, length);
852    }
853
854    static native void copyFromShortArray(Object src, long srcPos, long dstAddr,
855                                          long length);
856
857    static native void copyToShortArray(long srcAddr, Object dst, long dstPos,
858                                        long length);
859
860    static native void copyFromIntArray(Object src, long srcPos, long dstAddr,
861                                        long length);
862
863    static native void copyToIntArray(long srcAddr, Object dst, long dstPos,
864                                      long length);
865
866    static native void copyFromLongArray(Object src, long srcPos, long dstAddr,
867                                         long length);
868
869    static native void copyToLongArray(long srcAddr, Object dst, long dstPos,
870                                       long length);
871
872}
873