001: /*
002: * Copyright 2000-2007 Sun Microsystems, Inc. All Rights Reserved.
003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004: *
005: * This code is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU General Public License version 2 only, as
007: * published by the Free Software Foundation. Sun designates this
008: * particular file as subject to the "Classpath" exception as provided
009: * by Sun in the LICENSE file that accompanied this code.
010: *
011: * This code is distributed in the hope that it will be useful, but WITHOUT
012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014: * version 2 for more details (a copy is included in the LICENSE file that
015: * accompanied this code).
016: *
017: * You should have received a copy of the GNU General Public License version
018: * 2 along with this work; if not, write to the Free Software Foundation,
019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022: * CA 95054 USA or visit www.sun.com if you need additional information or
023: * have any questions.
024: */
025:
026: package java.nio;
027:
028: import java.security.AccessController;
029: import java.security.PrivilegedAction;
030: import sun.misc.Unsafe;
031: import sun.misc.VM;
032:
033: /**
034: * Access to bits, native and otherwise.
035: */
036:
037: class Bits { // package-private
038:
039: private Bits() {
040: }
041:
042: // -- Swapping --
043:
044: static short swap(short x) {
045: return (short) ((x << 8) | ((x >> 8) & 0xff));
046: }
047:
048: static char swap(char x) {
049: return (char) ((x << 8) | ((x >> 8) & 0xff));
050: }
051:
052: static int swap(int x) {
053: return (int) ((swap((short) x) << 16) | (swap((short) (x >> 16)) & 0xffff));
054: }
055:
056: static long swap(long x) {
057: return (long) (((long) swap((int) (x)) << 32) | ((long) swap((int) (x >> 32)) & 0xffffffffL));
058: }
059:
060: // -- get/put char --
061:
062: static private char makeChar(byte b1, byte b0) {
063: return (char) ((b1 << 8) | (b0 & 0xff));
064: }
065:
066: static char getCharL(ByteBuffer bb, int bi) {
067: return makeChar(bb._get(bi + 1), bb._get(bi + 0));
068: }
069:
070: static char getCharL(long a) {
071: return makeChar(_get(a + 1), _get(a + 0));
072: }
073:
074: static char getCharB(ByteBuffer bb, int bi) {
075: return makeChar(bb._get(bi + 0), bb._get(bi + 1));
076: }
077:
078: static char getCharB(long a) {
079: return makeChar(_get(a + 0), _get(a + 1));
080: }
081:
082: static char getChar(ByteBuffer bb, int bi, boolean bigEndian) {
083: return (bigEndian ? getCharB(bb, bi) : getCharL(bb, bi));
084: }
085:
086: static char getChar(long a, boolean bigEndian) {
087: return (bigEndian ? getCharB(a) : getCharL(a));
088: }
089:
090: private static byte char1(char x) {
091: return (byte) (x >> 8);
092: }
093:
094: private static byte char0(char x) {
095: return (byte) (x >> 0);
096: }
097:
098: static void putCharL(ByteBuffer bb, int bi, char x) {
099: bb._put(bi + 0, char0(x));
100: bb._put(bi + 1, char1(x));
101: }
102:
103: static void putCharL(long a, char x) {
104: _put(a + 0, char0(x));
105: _put(a + 1, char1(x));
106: }
107:
108: static void putCharB(ByteBuffer bb, int bi, char x) {
109: bb._put(bi + 0, char1(x));
110: bb._put(bi + 1, char0(x));
111: }
112:
113: static void putCharB(long a, char x) {
114: _put(a + 0, char1(x));
115: _put(a + 1, char0(x));
116: }
117:
118: static void putChar(ByteBuffer bb, int bi, char x, boolean bigEndian) {
119: if (bigEndian)
120: putCharB(bb, bi, x);
121: else
122: putCharL(bb, bi, x);
123: }
124:
125: static void putChar(long a, char x, boolean bigEndian) {
126: if (bigEndian)
127: putCharB(a, x);
128: else
129: putCharL(a, x);
130: }
131:
132: // -- get/put short --
133:
134: static private short makeShort(byte b1, byte b0) {
135: return (short) ((b1 << 8) | (b0 & 0xff));
136: }
137:
138: static short getShortL(ByteBuffer bb, int bi) {
139: return makeShort(bb._get(bi + 1), bb._get(bi + 0));
140: }
141:
142: static short getShortL(long a) {
143: return makeShort(_get(a + 1), _get(a));
144: }
145:
146: static short getShortB(ByteBuffer bb, int bi) {
147: return makeShort(bb._get(bi + 0), bb._get(bi + 1));
148: }
149:
150: static short getShortB(long a) {
151: return makeShort(_get(a), _get(a + 1));
152: }
153:
154: static short getShort(ByteBuffer bb, int bi, boolean bigEndian) {
155: return (bigEndian ? getShortB(bb, bi) : getShortL(bb, bi));
156: }
157:
158: static short getShort(long a, boolean bigEndian) {
159: return (bigEndian ? getShortB(a) : getShortL(a));
160: }
161:
162: private static byte short1(short x) {
163: return (byte) (x >> 8);
164: }
165:
166: private static byte short0(short x) {
167: return (byte) (x >> 0);
168: }
169:
170: static void putShortL(ByteBuffer bb, int bi, short x) {
171: bb._put(bi + 0, short0(x));
172: bb._put(bi + 1, short1(x));
173: }
174:
175: static void putShortL(long a, short x) {
176: _put(a, short0(x));
177: _put(a + 1, short1(x));
178: }
179:
180: static void putShortB(ByteBuffer bb, int bi, short x) {
181: bb._put(bi + 0, short1(x));
182: bb._put(bi + 1, short0(x));
183: }
184:
185: static void putShortB(long a, short x) {
186: _put(a, short1(x));
187: _put(a + 1, short0(x));
188: }
189:
190: static void putShort(ByteBuffer bb, int bi, short x,
191: boolean bigEndian) {
192: if (bigEndian)
193: putShortB(bb, bi, x);
194: else
195: putShortL(bb, bi, x);
196: }
197:
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: // -- get/put int --
206:
207: static private int makeInt(byte b3, byte b2, byte b1, byte b0) {
208: return (int) ((((b3 & 0xff) << 24) | ((b2 & 0xff) << 16)
209: | ((b1 & 0xff) << 8) | ((b0 & 0xff) << 0)));
210: }
211:
212: static int getIntL(ByteBuffer bb, int bi) {
213: return makeInt(bb._get(bi + 3), bb._get(bi + 2), bb
214: ._get(bi + 1), bb._get(bi + 0));
215: }
216:
217: static int getIntL(long a) {
218: return makeInt(_get(a + 3), _get(a + 2), _get(a + 1),
219: _get(a + 0));
220: }
221:
222: static int getIntB(ByteBuffer bb, int bi) {
223: return makeInt(bb._get(bi + 0), bb._get(bi + 1), bb
224: ._get(bi + 2), bb._get(bi + 3));
225: }
226:
227: static int getIntB(long a) {
228: return makeInt(_get(a + 0), _get(a + 1), _get(a + 2),
229: _get(a + 3));
230: }
231:
232: static int getInt(ByteBuffer bb, int bi, boolean bigEndian) {
233: return (bigEndian ? getIntB(bb, bi) : getIntL(bb, bi));
234: }
235:
236: static int getInt(long a, boolean bigEndian) {
237: return (bigEndian ? getIntB(a) : getIntL(a));
238: }
239:
240: private static byte int3(int x) {
241: return (byte) (x >> 24);
242: }
243:
244: private static byte int2(int x) {
245: return (byte) (x >> 16);
246: }
247:
248: private static byte int1(int x) {
249: return (byte) (x >> 8);
250: }
251:
252: private static byte int0(int x) {
253: return (byte) (x >> 0);
254: }
255:
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 + 0, int0(x));
261: }
262:
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 + 0, int0(x));
268: }
269:
270: static void putIntB(ByteBuffer bb, int bi, int x) {
271: bb._put(bi + 0, 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:
277: static void putIntB(long a, int x) {
278: _put(a + 0, int3(x));
279: _put(a + 1, int2(x));
280: _put(a + 2, int1(x));
281: _put(a + 3, int0(x));
282: }
283:
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:
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: // -- get/put long --
299:
300: static private long makeLong(byte b7, byte b6, byte b5, byte b4,
301: byte b3, byte b2, byte b1, byte b0) {
302: return ((((long) b7 & 0xff) << 56) | (((long) b6 & 0xff) << 48)
303: | (((long) b5 & 0xff) << 40)
304: | (((long) b4 & 0xff) << 32)
305: | (((long) b3 & 0xff) << 24)
306: | (((long) b2 & 0xff) << 16)
307: | (((long) b1 & 0xff) << 8) | (((long) b0 & 0xff) << 0));
308: }
309:
310: static long getLongL(ByteBuffer bb, int bi) {
311: return makeLong(bb._get(bi + 7), bb._get(bi + 6), bb
312: ._get(bi + 5), bb._get(bi + 4), bb._get(bi + 3), bb
313: ._get(bi + 2), bb._get(bi + 1), bb._get(bi + 0));
314: }
315:
316: static long getLongL(long a) {
317: return makeLong(_get(a + 7), _get(a + 6), _get(a + 5),
318: _get(a + 4), _get(a + 3), _get(a + 2), _get(a + 1),
319: _get(a + 0));
320: }
321:
322: static long getLongB(ByteBuffer bb, int bi) {
323: return makeLong(bb._get(bi + 0), bb._get(bi + 1), bb
324: ._get(bi + 2), bb._get(bi + 3), bb._get(bi + 4), bb
325: ._get(bi + 5), bb._get(bi + 6), bb._get(bi + 7));
326: }
327:
328: static long getLongB(long a) {
329: return makeLong(_get(a + 0), _get(a + 1), _get(a + 2),
330: _get(a + 3), _get(a + 4), _get(a + 5), _get(a + 6),
331: _get(a + 7));
332: }
333:
334: static long getLong(ByteBuffer bb, int bi, boolean bigEndian) {
335: return (bigEndian ? getLongB(bb, bi) : getLongL(bb, bi));
336: }
337:
338: static long getLong(long a, boolean bigEndian) {
339: return (bigEndian ? getLongB(a) : getLongL(a));
340: }
341:
342: private static byte long7(long x) {
343: return (byte) (x >> 56);
344: }
345:
346: private static byte long6(long x) {
347: return (byte) (x >> 48);
348: }
349:
350: private static byte long5(long x) {
351: return (byte) (x >> 40);
352: }
353:
354: private static byte long4(long x) {
355: return (byte) (x >> 32);
356: }
357:
358: private static byte long3(long x) {
359: return (byte) (x >> 24);
360: }
361:
362: private static byte long2(long x) {
363: return (byte) (x >> 16);
364: }
365:
366: private static byte long1(long x) {
367: return (byte) (x >> 8);
368: }
369:
370: private static byte long0(long x) {
371: return (byte) (x >> 0);
372: }
373:
374: static void putLongL(ByteBuffer bb, int bi, long x) {
375: bb._put(bi + 7, long7(x));
376: bb._put(bi + 6, long6(x));
377: bb._put(bi + 5, long5(x));
378: bb._put(bi + 4, long4(x));
379: bb._put(bi + 3, long3(x));
380: bb._put(bi + 2, long2(x));
381: bb._put(bi + 1, long1(x));
382: bb._put(bi + 0, long0(x));
383: }
384:
385: static void putLongL(long a, long x) {
386: _put(a + 7, long7(x));
387: _put(a + 6, long6(x));
388: _put(a + 5, long5(x));
389: _put(a + 4, long4(x));
390: _put(a + 3, long3(x));
391: _put(a + 2, long2(x));
392: _put(a + 1, long1(x));
393: _put(a + 0, long0(x));
394: }
395:
396: static void putLongB(ByteBuffer bb, int bi, long x) {
397: bb._put(bi + 0, long7(x));
398: bb._put(bi + 1, long6(x));
399: bb._put(bi + 2, long5(x));
400: bb._put(bi + 3, long4(x));
401: bb._put(bi + 4, long3(x));
402: bb._put(bi + 5, long2(x));
403: bb._put(bi + 6, long1(x));
404: bb._put(bi + 7, long0(x));
405: }
406:
407: static void putLongB(long a, long x) {
408: _put(a + 0, long7(x));
409: _put(a + 1, long6(x));
410: _put(a + 2, long5(x));
411: _put(a + 3, long4(x));
412: _put(a + 4, long3(x));
413: _put(a + 5, long2(x));
414: _put(a + 6, long1(x));
415: _put(a + 7, long0(x));
416: }
417:
418: static void putLong(ByteBuffer bb, int bi, long x, boolean bigEndian) {
419: if (bigEndian)
420: putLongB(bb, bi, x);
421: else
422: putLongL(bb, bi, x);
423: }
424:
425: static void putLong(long a, long x, boolean bigEndian) {
426: if (bigEndian)
427: putLongB(a, x);
428: else
429: putLongL(a, x);
430: }
431:
432: // -- get/put float --
433:
434: static float getFloatL(ByteBuffer bb, int bi) {
435: return Float.intBitsToFloat(getIntL(bb, bi));
436: }
437:
438: static float getFloatL(long a) {
439: return Float.intBitsToFloat(getIntL(a));
440: }
441:
442: static float getFloatB(ByteBuffer bb, int bi) {
443: return Float.intBitsToFloat(getIntB(bb, bi));
444: }
445:
446: static float getFloatB(long a) {
447: return Float.intBitsToFloat(getIntB(a));
448: }
449:
450: static float getFloat(ByteBuffer bb, int bi, boolean bigEndian) {
451: return (bigEndian ? getFloatB(bb, bi) : getFloatL(bb, bi));
452: }
453:
454: static float getFloat(long a, boolean bigEndian) {
455: return (bigEndian ? getFloatB(a) : getFloatL(a));
456: }
457:
458: static void putFloatL(ByteBuffer bb, int bi, float x) {
459: putIntL(bb, bi, Float.floatToRawIntBits(x));
460: }
461:
462: static void putFloatL(long a, float x) {
463: putIntL(a, Float.floatToRawIntBits(x));
464: }
465:
466: static void putFloatB(ByteBuffer bb, int bi, float x) {
467: putIntB(bb, bi, Float.floatToRawIntBits(x));
468: }
469:
470: static void putFloatB(long a, float x) {
471: putIntB(a, Float.floatToRawIntBits(x));
472: }
473:
474: static void putFloat(ByteBuffer bb, int bi, float x,
475: boolean bigEndian) {
476: if (bigEndian)
477: putFloatB(bb, bi, x);
478: else
479: putFloatL(bb, bi, x);
480: }
481:
482: static void putFloat(long a, float x, boolean bigEndian) {
483: if (bigEndian)
484: putFloatB(a, x);
485: else
486: putFloatL(a, x);
487: }
488:
489: // -- get/put double --
490:
491: static double getDoubleL(ByteBuffer bb, int bi) {
492: return Double.longBitsToDouble(getLongL(bb, bi));
493: }
494:
495: static double getDoubleL(long a) {
496: return Double.longBitsToDouble(getLongL(a));
497: }
498:
499: static double getDoubleB(ByteBuffer bb, int bi) {
500: return Double.longBitsToDouble(getLongB(bb, bi));
501: }
502:
503: static double getDoubleB(long a) {
504: return Double.longBitsToDouble(getLongB(a));
505: }
506:
507: static double getDouble(ByteBuffer bb, int bi, boolean bigEndian) {
508: return (bigEndian ? getDoubleB(bb, bi) : getDoubleL(bb, bi));
509: }
510:
511: static double getDouble(long a, boolean bigEndian) {
512: return (bigEndian ? getDoubleB(a) : getDoubleL(a));
513: }
514:
515: static void putDoubleL(ByteBuffer bb, int bi, double x) {
516: putLongL(bb, bi, Double.doubleToRawLongBits(x));
517: }
518:
519: static void putDoubleL(long a, double x) {
520: putLongL(a, Double.doubleToRawLongBits(x));
521: }
522:
523: static void putDoubleB(ByteBuffer bb, int bi, double x) {
524: putLongB(bb, bi, Double.doubleToRawLongBits(x));
525: }
526:
527: static void putDoubleB(long a, double x) {
528: putLongB(a, Double.doubleToRawLongBits(x));
529: }
530:
531: static void putDouble(ByteBuffer bb, int bi, double x,
532: boolean bigEndian) {
533: if (bigEndian)
534: putDoubleB(bb, bi, x);
535: else
536: putDoubleL(bb, bi, x);
537: }
538:
539: static void putDouble(long a, double x, boolean bigEndian) {
540: if (bigEndian)
541: putDoubleB(a, x);
542: else
543: putDoubleL(a, x);
544: }
545:
546: // -- Unsafe access --
547:
548: private static final Unsafe unsafe = Unsafe.getUnsafe();
549:
550: private static byte _get(long a) {
551: return unsafe.getByte(a);
552: }
553:
554: private static void _put(long a, byte b) {
555: unsafe.putByte(a, b);
556: }
557:
558: static Unsafe unsafe() {
559: return unsafe;
560: }
561:
562: // -- Processor and memory-system properties --
563:
564: private static final ByteOrder byteOrder;
565:
566: static ByteOrder byteOrder() {
567: if (byteOrder == null)
568: throw new Error("Unknown byte order");
569: return byteOrder;
570: }
571:
572: static {
573: long a = unsafe.allocateMemory(8);
574: try {
575: unsafe.putLong(a, 0x0102030405060708L);
576: byte b = unsafe.getByte(a);
577: switch (b) {
578: case 0x01:
579: byteOrder = ByteOrder.BIG_ENDIAN;
580: break;
581: case 0x08:
582: byteOrder = ByteOrder.LITTLE_ENDIAN;
583: break;
584: default:
585: assert false;
586: byteOrder = null;
587: }
588: } finally {
589: unsafe.freeMemory(a);
590: }
591: }
592:
593: private static int pageSize = -1;
594:
595: static int pageSize() {
596: if (pageSize == -1)
597: pageSize = unsafe().pageSize();
598: return pageSize;
599: }
600:
601: private static boolean unaligned;
602: private static boolean unalignedKnown = false;
603:
604: static boolean unaligned() {
605: if (unalignedKnown)
606: return unaligned;
607: PrivilegedAction pa = new sun.security.action.GetPropertyAction(
608: "os.arch");
609: String arch = (String) AccessController.doPrivileged(pa);
610: unaligned = arch.equals("i386") || arch.equals("x86")
611: || arch.equals("amd64");
612: unalignedKnown = true;
613: return unaligned;
614: }
615:
616: // -- Direct memory management --
617:
618: // A user-settable upper limit on the maximum amount of allocatable
619: // direct buffer memory. This value may be changed during VM
620: // initialization if it is launched with "-XX:MaxDirectMemorySize=<size>".
621: private static volatile long maxMemory = VM.maxDirectMemory();
622: private static volatile long reservedMemory = 0;
623: private static boolean memoryLimitSet = false;
624:
625: // These methods should be called whenever direct memory is allocated or
626: // freed. They allow the user to control the amount of direct memory
627: // which a process may access. All sizes are specified in bytes.
628: static void reserveMemory(long size) {
629:
630: synchronized (Bits.class) {
631: if (!memoryLimitSet && VM.isBooted()) {
632: maxMemory = VM.maxDirectMemory();
633: memoryLimitSet = true;
634: }
635: if (size <= maxMemory - reservedMemory) {
636: reservedMemory += size;
637: return;
638: }
639: }
640:
641: System.gc();
642: try {
643: Thread.sleep(100);
644: } catch (InterruptedException x) {
645: // Restore interrupt status
646: Thread.currentThread().interrupt();
647: }
648: synchronized (Bits.class) {
649: if (reservedMemory + size > maxMemory)
650: throw new OutOfMemoryError("Direct buffer memory");
651: reservedMemory += size;
652: }
653:
654: }
655:
656: static synchronized void unreserveMemory(long size) {
657: if (reservedMemory > 0) {
658: reservedMemory -= size;
659: assert (reservedMemory > -1);
660: }
661: }
662:
663: // -- Bulk get/put acceleration --
664:
665: // These numbers represent the point at which we have empirically
666: // determined that the average cost of a JNI call exceeds the expense
667: // of an element by element copy. These numbers may change over time.
668: static final int JNI_COPY_TO_ARRAY_THRESHOLD = 6;
669: static final int JNI_COPY_FROM_ARRAY_THRESHOLD = 6;
670:
671: // These methods do no bounds checking. Verification that the copy will not
672: // result in memory corruption should be done prior to invocation.
673: // All positions and lengths are specified in bytes.
674:
675: static native void copyFromByteArray(Object src, long srcPos,
676: long dstAddr, long length);
677:
678: static native void copyToByteArray(long srcAddr, Object dst,
679: long dstPos, long length);
680:
681: static void copyFromCharArray(Object src, long srcPos,
682: long dstAddr, long length) {
683: copyFromShortArray(src, srcPos, dstAddr, length);
684: }
685:
686: static void copyToCharArray(long srcAddr, Object dst, long dstPos,
687: long length) {
688: copyToShortArray(srcAddr, dst, dstPos, length);
689: }
690:
691: static native void copyFromShortArray(Object src, long srcPos,
692: long dstAddr, long length);
693:
694: static native void copyToShortArray(long srcAddr, Object dst,
695: long dstPos, long length);
696:
697: static native void copyFromIntArray(Object src, long srcPos,
698: long dstAddr, long length);
699:
700: static native void copyToIntArray(long srcAddr, Object dst,
701: long dstPos, long length);
702:
703: static native void copyFromLongArray(Object src, long srcPos,
704: long dstAddr, long length);
705:
706: static native void copyToLongArray(long srcAddr, Object dst,
707: long dstPos, long length);
708:
709: }
|