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