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