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 }
|