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