Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/java/nio/Bits.java
38829 views
1
/*
2
* Copyright (c) 2000, 2018, Oracle and/or its affiliates. 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. Oracle designates this
8
* particular file as subject to the "Classpath" exception as provided
9
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22
* or visit www.oracle.com if you need additional information or have any
23
* questions.
24
*/
25
26
package java.nio;
27
28
import java.security.AccessController;
29
import java.util.concurrent.atomic.AtomicLong;
30
import java.util.concurrent.atomic.LongAdder;
31
32
import sun.misc.JavaLangRefAccess;
33
import sun.misc.SharedSecrets;
34
import sun.misc.Unsafe;
35
import sun.misc.VM;
36
37
/**
38
* Access to bits, native and otherwise.
39
*/
40
41
class Bits { // package-private
42
43
private Bits() { }
44
45
46
// -- Swapping --
47
48
static short swap(short x) {
49
return Short.reverseBytes(x);
50
}
51
52
static char swap(char x) {
53
return Character.reverseBytes(x);
54
}
55
56
static int swap(int x) {
57
return Integer.reverseBytes(x);
58
}
59
60
static long swap(long x) {
61
return Long.reverseBytes(x);
62
}
63
64
65
// -- get/put char --
66
67
static private char makeChar(byte b1, byte b0) {
68
return (char)((b1 << 8) | (b0 & 0xff));
69
}
70
71
static char getCharL(ByteBuffer bb, int bi) {
72
return makeChar(bb._get(bi + 1),
73
bb._get(bi ));
74
}
75
76
static char getCharL(long a) {
77
return makeChar(_get(a + 1),
78
_get(a ));
79
}
80
81
static char getCharB(ByteBuffer bb, int bi) {
82
return makeChar(bb._get(bi ),
83
bb._get(bi + 1));
84
}
85
86
static char getCharB(long a) {
87
return makeChar(_get(a ),
88
_get(a + 1));
89
}
90
91
static char getChar(ByteBuffer bb, int bi, boolean bigEndian) {
92
return bigEndian ? getCharB(bb, bi) : getCharL(bb, bi);
93
}
94
95
static char getChar(long a, boolean bigEndian) {
96
return bigEndian ? getCharB(a) : getCharL(a);
97
}
98
99
private static byte char1(char x) { return (byte)(x >> 8); }
100
private static byte char0(char x) { return (byte)(x ); }
101
102
static void putCharL(ByteBuffer bb, int bi, char x) {
103
bb._put(bi , char0(x));
104
bb._put(bi + 1, char1(x));
105
}
106
107
static void putCharL(long a, char x) {
108
_put(a , char0(x));
109
_put(a + 1, char1(x));
110
}
111
112
static void putCharB(ByteBuffer bb, int bi, char x) {
113
bb._put(bi , char1(x));
114
bb._put(bi + 1, char0(x));
115
}
116
117
static void putCharB(long a, char x) {
118
_put(a , char1(x));
119
_put(a + 1, char0(x));
120
}
121
122
static void putChar(ByteBuffer bb, int bi, char x, boolean bigEndian) {
123
if (bigEndian)
124
putCharB(bb, bi, x);
125
else
126
putCharL(bb, bi, x);
127
}
128
129
static void putChar(long a, char x, boolean bigEndian) {
130
if (bigEndian)
131
putCharB(a, x);
132
else
133
putCharL(a, x);
134
}
135
136
137
// -- get/put short --
138
139
static private short makeShort(byte b1, byte b0) {
140
return (short)((b1 << 8) | (b0 & 0xff));
141
}
142
143
static short getShortL(ByteBuffer bb, int bi) {
144
return makeShort(bb._get(bi + 1),
145
bb._get(bi ));
146
}
147
148
static short getShortL(long a) {
149
return makeShort(_get(a + 1),
150
_get(a ));
151
}
152
153
static short getShortB(ByteBuffer bb, int bi) {
154
return makeShort(bb._get(bi ),
155
bb._get(bi + 1));
156
}
157
158
static short getShortB(long a) {
159
return makeShort(_get(a ),
160
_get(a + 1));
161
}
162
163
static short getShort(ByteBuffer bb, int bi, boolean bigEndian) {
164
return bigEndian ? getShortB(bb, bi) : getShortL(bb, bi);
165
}
166
167
static short getShort(long a, boolean bigEndian) {
168
return bigEndian ? getShortB(a) : getShortL(a);
169
}
170
171
private static byte short1(short x) { return (byte)(x >> 8); }
172
private static byte short0(short x) { return (byte)(x ); }
173
174
static void putShortL(ByteBuffer bb, int bi, short x) {
175
bb._put(bi , short0(x));
176
bb._put(bi + 1, short1(x));
177
}
178
179
static void putShortL(long a, short x) {
180
_put(a , short0(x));
181
_put(a + 1, short1(x));
182
}
183
184
static void putShortB(ByteBuffer bb, int bi, short x) {
185
bb._put(bi , short1(x));
186
bb._put(bi + 1, short0(x));
187
}
188
189
static void putShortB(long a, short x) {
190
_put(a , short1(x));
191
_put(a + 1, short0(x));
192
}
193
194
static void putShort(ByteBuffer bb, int bi, short x, boolean bigEndian) {
195
if (bigEndian)
196
putShortB(bb, bi, x);
197
else
198
putShortL(bb, bi, x);
199
}
200
201
static void putShort(long a, short x, boolean bigEndian) {
202
if (bigEndian)
203
putShortB(a, x);
204
else
205
putShortL(a, x);
206
}
207
208
209
// -- get/put int --
210
211
static private int makeInt(byte b3, byte b2, byte b1, byte b0) {
212
return (((b3 ) << 24) |
213
((b2 & 0xff) << 16) |
214
((b1 & 0xff) << 8) |
215
((b0 & 0xff) ));
216
}
217
218
static int getIntL(ByteBuffer bb, int bi) {
219
return makeInt(bb._get(bi + 3),
220
bb._get(bi + 2),
221
bb._get(bi + 1),
222
bb._get(bi ));
223
}
224
225
static int getIntL(long a) {
226
return makeInt(_get(a + 3),
227
_get(a + 2),
228
_get(a + 1),
229
_get(a ));
230
}
231
232
static int getIntB(ByteBuffer bb, int bi) {
233
return makeInt(bb._get(bi ),
234
bb._get(bi + 1),
235
bb._get(bi + 2),
236
bb._get(bi + 3));
237
}
238
239
static int getIntB(long a) {
240
return makeInt(_get(a ),
241
_get(a + 1),
242
_get(a + 2),
243
_get(a + 3));
244
}
245
246
static int getInt(ByteBuffer bb, int bi, boolean bigEndian) {
247
return bigEndian ? getIntB(bb, bi) : getIntL(bb, bi) ;
248
}
249
250
static int getInt(long a, boolean bigEndian) {
251
return bigEndian ? getIntB(a) : getIntL(a) ;
252
}
253
254
private static byte int3(int x) { return (byte)(x >> 24); }
255
private static byte int2(int x) { return (byte)(x >> 16); }
256
private static byte int1(int x) { return (byte)(x >> 8); }
257
private static byte int0(int x) { return (byte)(x ); }
258
259
static void putIntL(ByteBuffer bb, int bi, int x) {
260
bb._put(bi + 3, int3(x));
261
bb._put(bi + 2, int2(x));
262
bb._put(bi + 1, int1(x));
263
bb._put(bi , int0(x));
264
}
265
266
static void putIntL(long a, int x) {
267
_put(a + 3, int3(x));
268
_put(a + 2, int2(x));
269
_put(a + 1, int1(x));
270
_put(a , int0(x));
271
}
272
273
static void putIntB(ByteBuffer bb, int bi, int x) {
274
bb._put(bi , int3(x));
275
bb._put(bi + 1, int2(x));
276
bb._put(bi + 2, int1(x));
277
bb._put(bi + 3, int0(x));
278
}
279
280
static void putIntB(long a, int x) {
281
_put(a , int3(x));
282
_put(a + 1, int2(x));
283
_put(a + 2, int1(x));
284
_put(a + 3, int0(x));
285
}
286
287
static void putInt(ByteBuffer bb, int bi, int x, boolean bigEndian) {
288
if (bigEndian)
289
putIntB(bb, bi, x);
290
else
291
putIntL(bb, bi, x);
292
}
293
294
static void putInt(long a, int x, boolean bigEndian) {
295
if (bigEndian)
296
putIntB(a, x);
297
else
298
putIntL(a, x);
299
}
300
301
302
// -- get/put long --
303
304
static private long makeLong(byte b7, byte b6, byte b5, byte b4,
305
byte b3, byte b2, byte b1, byte b0)
306
{
307
return ((((long)b7 ) << 56) |
308
(((long)b6 & 0xff) << 48) |
309
(((long)b5 & 0xff) << 40) |
310
(((long)b4 & 0xff) << 32) |
311
(((long)b3 & 0xff) << 24) |
312
(((long)b2 & 0xff) << 16) |
313
(((long)b1 & 0xff) << 8) |
314
(((long)b0 & 0xff) ));
315
}
316
317
static long getLongL(ByteBuffer bb, int bi) {
318
return makeLong(bb._get(bi + 7),
319
bb._get(bi + 6),
320
bb._get(bi + 5),
321
bb._get(bi + 4),
322
bb._get(bi + 3),
323
bb._get(bi + 2),
324
bb._get(bi + 1),
325
bb._get(bi ));
326
}
327
328
static long getLongL(long a) {
329
return makeLong(_get(a + 7),
330
_get(a + 6),
331
_get(a + 5),
332
_get(a + 4),
333
_get(a + 3),
334
_get(a + 2),
335
_get(a + 1),
336
_get(a ));
337
}
338
339
static long getLongB(ByteBuffer bb, int bi) {
340
return makeLong(bb._get(bi ),
341
bb._get(bi + 1),
342
bb._get(bi + 2),
343
bb._get(bi + 3),
344
bb._get(bi + 4),
345
bb._get(bi + 5),
346
bb._get(bi + 6),
347
bb._get(bi + 7));
348
}
349
350
static long getLongB(long a) {
351
return makeLong(_get(a ),
352
_get(a + 1),
353
_get(a + 2),
354
_get(a + 3),
355
_get(a + 4),
356
_get(a + 5),
357
_get(a + 6),
358
_get(a + 7));
359
}
360
361
static long getLong(ByteBuffer bb, int bi, boolean bigEndian) {
362
return bigEndian ? getLongB(bb, bi) : getLongL(bb, bi);
363
}
364
365
static long getLong(long a, boolean bigEndian) {
366
return bigEndian ? getLongB(a) : getLongL(a);
367
}
368
369
private static byte long7(long x) { return (byte)(x >> 56); }
370
private static byte long6(long x) { return (byte)(x >> 48); }
371
private static byte long5(long x) { return (byte)(x >> 40); }
372
private static byte long4(long x) { return (byte)(x >> 32); }
373
private static byte long3(long x) { return (byte)(x >> 24); }
374
private static byte long2(long x) { return (byte)(x >> 16); }
375
private static byte long1(long x) { return (byte)(x >> 8); }
376
private static byte long0(long x) { return (byte)(x ); }
377
378
static void putLongL(ByteBuffer bb, int bi, long x) {
379
bb._put(bi + 7, long7(x));
380
bb._put(bi + 6, long6(x));
381
bb._put(bi + 5, long5(x));
382
bb._put(bi + 4, long4(x));
383
bb._put(bi + 3, long3(x));
384
bb._put(bi + 2, long2(x));
385
bb._put(bi + 1, long1(x));
386
bb._put(bi , long0(x));
387
}
388
389
static void putLongL(long a, long x) {
390
_put(a + 7, long7(x));
391
_put(a + 6, long6(x));
392
_put(a + 5, long5(x));
393
_put(a + 4, long4(x));
394
_put(a + 3, long3(x));
395
_put(a + 2, long2(x));
396
_put(a + 1, long1(x));
397
_put(a , long0(x));
398
}
399
400
static void putLongB(ByteBuffer bb, int bi, long x) {
401
bb._put(bi , long7(x));
402
bb._put(bi + 1, long6(x));
403
bb._put(bi + 2, long5(x));
404
bb._put(bi + 3, long4(x));
405
bb._put(bi + 4, long3(x));
406
bb._put(bi + 5, long2(x));
407
bb._put(bi + 6, long1(x));
408
bb._put(bi + 7, long0(x));
409
}
410
411
static void putLongB(long a, long x) {
412
_put(a , long7(x));
413
_put(a + 1, long6(x));
414
_put(a + 2, long5(x));
415
_put(a + 3, long4(x));
416
_put(a + 4, long3(x));
417
_put(a + 5, long2(x));
418
_put(a + 6, long1(x));
419
_put(a + 7, long0(x));
420
}
421
422
static void putLong(ByteBuffer bb, int bi, long x, boolean bigEndian) {
423
if (bigEndian)
424
putLongB(bb, bi, x);
425
else
426
putLongL(bb, bi, x);
427
}
428
429
static void putLong(long a, long x, boolean bigEndian) {
430
if (bigEndian)
431
putLongB(a, x);
432
else
433
putLongL(a, x);
434
}
435
436
437
// -- get/put float --
438
439
static float getFloatL(ByteBuffer bb, int bi) {
440
return Float.intBitsToFloat(getIntL(bb, bi));
441
}
442
443
static float getFloatL(long a) {
444
return Float.intBitsToFloat(getIntL(a));
445
}
446
447
static float getFloatB(ByteBuffer bb, int bi) {
448
return Float.intBitsToFloat(getIntB(bb, bi));
449
}
450
451
static float getFloatB(long a) {
452
return Float.intBitsToFloat(getIntB(a));
453
}
454
455
static float getFloat(ByteBuffer bb, int bi, boolean bigEndian) {
456
return bigEndian ? getFloatB(bb, bi) : getFloatL(bb, bi);
457
}
458
459
static float getFloat(long a, boolean bigEndian) {
460
return bigEndian ? getFloatB(a) : getFloatL(a);
461
}
462
463
static void putFloatL(ByteBuffer bb, int bi, float x) {
464
putIntL(bb, bi, Float.floatToRawIntBits(x));
465
}
466
467
static void putFloatL(long a, float x) {
468
putIntL(a, Float.floatToRawIntBits(x));
469
}
470
471
static void putFloatB(ByteBuffer bb, int bi, float x) {
472
putIntB(bb, bi, Float.floatToRawIntBits(x));
473
}
474
475
static void putFloatB(long a, float x) {
476
putIntB(a, Float.floatToRawIntBits(x));
477
}
478
479
static void putFloat(ByteBuffer bb, int bi, float x, boolean bigEndian) {
480
if (bigEndian)
481
putFloatB(bb, bi, x);
482
else
483
putFloatL(bb, bi, x);
484
}
485
486
static void putFloat(long a, float x, boolean bigEndian) {
487
if (bigEndian)
488
putFloatB(a, x);
489
else
490
putFloatL(a, x);
491
}
492
493
494
// -- get/put double --
495
496
static double getDoubleL(ByteBuffer bb, int bi) {
497
return Double.longBitsToDouble(getLongL(bb, bi));
498
}
499
500
static double getDoubleL(long a) {
501
return Double.longBitsToDouble(getLongL(a));
502
}
503
504
static double getDoubleB(ByteBuffer bb, int bi) {
505
return Double.longBitsToDouble(getLongB(bb, bi));
506
}
507
508
static double getDoubleB(long a) {
509
return Double.longBitsToDouble(getLongB(a));
510
}
511
512
static double getDouble(ByteBuffer bb, int bi, boolean bigEndian) {
513
return bigEndian ? getDoubleB(bb, bi) : getDoubleL(bb, bi);
514
}
515
516
static double getDouble(long a, boolean bigEndian) {
517
return bigEndian ? getDoubleB(a) : getDoubleL(a);
518
}
519
520
static void putDoubleL(ByteBuffer bb, int bi, double x) {
521
putLongL(bb, bi, Double.doubleToRawLongBits(x));
522
}
523
524
static void putDoubleL(long a, double x) {
525
putLongL(a, Double.doubleToRawLongBits(x));
526
}
527
528
static void putDoubleB(ByteBuffer bb, int bi, double x) {
529
putLongB(bb, bi, Double.doubleToRawLongBits(x));
530
}
531
532
static void putDoubleB(long a, double x) {
533
putLongB(a, Double.doubleToRawLongBits(x));
534
}
535
536
static void putDouble(ByteBuffer bb, int bi, double x, boolean bigEndian) {
537
if (bigEndian)
538
putDoubleB(bb, bi, x);
539
else
540
putDoubleL(bb, bi, x);
541
}
542
543
static void putDouble(long a, double x, boolean bigEndian) {
544
if (bigEndian)
545
putDoubleB(a, x);
546
else
547
putDoubleL(a, x);
548
}
549
550
551
// -- Unsafe access --
552
553
private static final Unsafe unsafe = Unsafe.getUnsafe();
554
555
private static byte _get(long a) {
556
return unsafe.getByte(a);
557
}
558
559
private static void _put(long a, byte b) {
560
unsafe.putByte(a, b);
561
}
562
563
static Unsafe unsafe() {
564
return unsafe;
565
}
566
567
568
// -- Processor and memory-system properties --
569
570
private static final ByteOrder byteOrder;
571
572
static ByteOrder byteOrder() {
573
if (byteOrder == null)
574
throw new Error("Unknown byte order");
575
return byteOrder;
576
}
577
578
static {
579
long a = unsafe.allocateMemory(8);
580
try {
581
unsafe.putLong(a, 0x0102030405060708L);
582
byte b = unsafe.getByte(a);
583
switch (b) {
584
case 0x01: byteOrder = ByteOrder.BIG_ENDIAN; break;
585
case 0x08: byteOrder = ByteOrder.LITTLE_ENDIAN; break;
586
default:
587
assert false;
588
byteOrder = null;
589
}
590
} finally {
591
unsafe.freeMemory(a);
592
}
593
}
594
595
596
private static int pageSize = -1;
597
598
static int pageSize() {
599
if (pageSize == -1)
600
pageSize = unsafe().pageSize();
601
return pageSize;
602
}
603
604
static int pageCount(long size) {
605
return (int)(size + (long)pageSize() - 1L) / pageSize();
606
}
607
608
private static boolean unaligned;
609
private static boolean unalignedKnown = false;
610
611
static boolean unaligned() {
612
if (unalignedKnown)
613
return unaligned;
614
String arch = AccessController.doPrivileged(
615
new sun.security.action.GetPropertyAction("os.arch"));
616
unaligned = arch.equals("i386") || arch.equals("x86")
617
|| arch.equals("amd64") || arch.equals("x86_64")
618
|| arch.equals("ppc64") || arch.equals("ppc64le")
619
|| arch.equals("aarch64");
620
unalignedKnown = true;
621
return unaligned;
622
}
623
624
625
// -- Direct memory management --
626
627
// A user-settable upper limit on the maximum amount of allocatable
628
// direct buffer memory. This value may be changed during VM
629
// initialization if it is launched with "-XX:MaxDirectMemorySize=<size>".
630
private static volatile long maxMemory = VM.maxDirectMemory();
631
private static final AtomicLong reservedMemory = new AtomicLong();
632
private static final AtomicLong totalCapacity = new AtomicLong();
633
private static final AtomicLong count = new AtomicLong();
634
private static volatile boolean memoryLimitSet = false;
635
// max. number of sleeps during try-reserving with exponentially
636
// increasing delay before throwing OutOfMemoryError:
637
// 1, 2, 4, 8, 16, 32, 64, 128, 256 (total 511 ms ~ 0.5 s)
638
// which means that OOME will be thrown after 0.5 s of trying
639
private static final int MAX_SLEEPS = 9;
640
641
// These methods should be called whenever direct memory is allocated or
642
// freed. They allow the user to control the amount of direct memory
643
// which a process may access. All sizes are specified in bytes.
644
static void reserveMemory(long size, int cap) {
645
646
if (!memoryLimitSet && VM.isBooted()) {
647
maxMemory = VM.maxDirectMemory();
648
memoryLimitSet = true;
649
}
650
651
// optimist!
652
if (tryReserveMemory(size, cap)) {
653
return;
654
}
655
656
final JavaLangRefAccess jlra = SharedSecrets.getJavaLangRefAccess();
657
658
// retry while helping enqueue pending Reference objects
659
// which includes executing pending Cleaner(s) which includes
660
// Cleaner(s) that free direct buffer memory
661
while (jlra.tryHandlePendingReference()) {
662
if (tryReserveMemory(size, cap)) {
663
return;
664
}
665
}
666
667
// trigger VM's Reference processing
668
System.gc();
669
670
// a retry loop with exponential back-off delays
671
// (this gives VM some time to do it's job)
672
boolean interrupted = false;
673
try {
674
long sleepTime = 1;
675
int sleeps = 0;
676
while (true) {
677
if (tryReserveMemory(size, cap)) {
678
return;
679
}
680
if (sleeps >= MAX_SLEEPS) {
681
break;
682
}
683
if (!jlra.tryHandlePendingReference()) {
684
try {
685
Thread.sleep(sleepTime);
686
sleepTime <<= 1;
687
sleeps++;
688
} catch (InterruptedException e) {
689
interrupted = true;
690
}
691
}
692
}
693
694
// no luck
695
throw new OutOfMemoryError("Direct buffer memory");
696
697
} finally {
698
if (interrupted) {
699
// don't swallow interrupts
700
Thread.currentThread().interrupt();
701
}
702
}
703
}
704
705
private static boolean tryReserveMemory(long size, int cap) {
706
707
// -XX:MaxDirectMemorySize limits the total capacity rather than the
708
// actual memory usage, which will differ when buffers are page
709
// aligned.
710
long totalCap;
711
while (cap <= maxMemory - (totalCap = totalCapacity.get())) {
712
if (totalCapacity.compareAndSet(totalCap, totalCap + cap)) {
713
reservedMemory.addAndGet(size);
714
count.incrementAndGet();
715
return true;
716
}
717
}
718
719
return false;
720
}
721
722
723
static void unreserveMemory(long size, int cap) {
724
long cnt = count.decrementAndGet();
725
long reservedMem = reservedMemory.addAndGet(-size);
726
long totalCap = totalCapacity.addAndGet(-cap);
727
assert cnt >= 0 && reservedMem >= 0 && totalCap >= 0;
728
}
729
730
// -- Monitoring of direct buffer usage --
731
732
static {
733
// setup access to this package in SharedSecrets
734
sun.misc.SharedSecrets.setJavaNioAccess(
735
new sun.misc.JavaNioAccess() {
736
@Override
737
public sun.misc.JavaNioAccess.BufferPool getDirectBufferPool() {
738
return new sun.misc.JavaNioAccess.BufferPool() {
739
@Override
740
public String getName() {
741
return "direct";
742
}
743
@Override
744
public long getCount() {
745
return Bits.count.get();
746
}
747
@Override
748
public long getTotalCapacity() {
749
return Bits.totalCapacity.get();
750
}
751
@Override
752
public long getMemoryUsed() {
753
return Bits.reservedMemory.get();
754
}
755
};
756
}
757
@Override
758
public ByteBuffer newDirectByteBuffer(long addr, int cap, Object ob) {
759
return new DirectByteBuffer(addr, cap, ob);
760
}
761
@Override
762
public void truncate(Buffer buf) {
763
buf.truncate();
764
}
765
});
766
}
767
768
// -- Bulk get/put acceleration --
769
770
// These numbers represent the point at which we have empirically
771
// determined that the average cost of a JNI call exceeds the expense
772
// of an element by element copy. These numbers may change over time.
773
static final int JNI_COPY_TO_ARRAY_THRESHOLD = 6;
774
static final int JNI_COPY_FROM_ARRAY_THRESHOLD = 6;
775
776
// This number limits the number of bytes to copy per call to Unsafe's
777
// copyMemory method. A limit is imposed to allow for safepoint polling
778
// during a large copy
779
static final long UNSAFE_COPY_THRESHOLD = 1024L * 1024L;
780
781
// These methods do no bounds checking. Verification that the copy will not
782
// result in memory corruption should be done prior to invocation.
783
// All positions and lengths are specified in bytes.
784
785
/**
786
* Copy from given source array to destination address.
787
*
788
* @param src
789
* source array
790
* @param srcBaseOffset
791
* offset of first element of storage in source array
792
* @param srcPos
793
* offset within source array of the first element to read
794
* @param dstAddr
795
* destination address
796
* @param length
797
* number of bytes to copy
798
*/
799
static void copyFromArray(Object src, long srcBaseOffset, long srcPos,
800
long dstAddr, long length)
801
{
802
long offset = srcBaseOffset + srcPos;
803
while (length > 0) {
804
long size = (length > UNSAFE_COPY_THRESHOLD) ? UNSAFE_COPY_THRESHOLD : length;
805
unsafe.copyMemory(src, offset, null, dstAddr, size);
806
length -= size;
807
offset += size;
808
dstAddr += size;
809
}
810
}
811
812
/**
813
* Copy from source address into given destination array.
814
*
815
* @param srcAddr
816
* source address
817
* @param dst
818
* destination array
819
* @param dstBaseOffset
820
* offset of first element of storage in destination array
821
* @param dstPos
822
* offset within destination array of the first element to write
823
* @param length
824
* number of bytes to copy
825
*/
826
static void copyToArray(long srcAddr, Object dst, long dstBaseOffset, long dstPos,
827
long length)
828
{
829
long offset = dstBaseOffset + dstPos;
830
while (length > 0) {
831
long size = (length > UNSAFE_COPY_THRESHOLD) ? UNSAFE_COPY_THRESHOLD : length;
832
unsafe.copyMemory(null, srcAddr, dst, offset, size);
833
length -= size;
834
srcAddr += size;
835
offset += size;
836
}
837
}
838
839
/**
840
* Copy and unconditionally byte swap 16 bit elements from a heap array to off-heap memory
841
*
842
* @param src
843
* the source array, must be a 16-bit primitive array type
844
* @param srcPos
845
* byte offset within source array of the first element to read
846
* @param dstAddr
847
* destination address
848
* @param length
849
* number of bytes to copy
850
*/
851
static void copyFromCharArray(Object src, long srcPos, long dstAddr, long length) {
852
copySwapMemory(src, unsafe.arrayBaseOffset(src.getClass()) + srcPos, null, dstAddr, length, 2);
853
}
854
855
/**
856
* Copy and unconditionally byte swap 16 bit elements from off-heap memory to a heap array
857
*
858
* @param srcAddr
859
* source address
860
* @param dst
861
* destination array, must be a 16-bit primitive array type
862
* @param dstPos
863
* byte offset within the destination array of the first element to write
864
* @param length
865
* number of bytes to copy
866
*/
867
static void copyToCharArray(long srcAddr, Object dst, long dstPos, long length) {
868
copySwapMemory(null, srcAddr, dst, unsafe.arrayBaseOffset(dst.getClass()) + dstPos, length, 2);
869
}
870
871
/**
872
* Copy and unconditionally byte swap 16 bit elements from a heap array to off-heap memory
873
*
874
* @param src
875
* the source array, must be a 16-bit primitive array type
876
* @param srcPos
877
* byte offset within source array of the first element to read
878
* @param dstAddr
879
* destination address
880
* @param length
881
* number of bytes to copy
882
*/
883
static void copyFromShortArray(Object src, long srcPos, long dstAddr, long length) {
884
copySwapMemory(src, unsafe.arrayBaseOffset(src.getClass()) + srcPos, null, dstAddr, length, 2);
885
}
886
887
/**
888
* Copy and unconditionally byte swap 16 bit elements from off-heap memory to a heap array
889
*
890
* @param srcAddr
891
* source address
892
* @param dst
893
* destination array, must be a 16-bit primitive array type
894
* @param dstPos
895
* byte offset within the destination array of the first element to write
896
* @param length
897
* number of bytes to copy
898
*/
899
static void copyToShortArray(long srcAddr, Object dst, long dstPos, long length) {
900
copySwapMemory(null, srcAddr, dst, unsafe.arrayBaseOffset(dst.getClass()) + dstPos, length, 2);
901
}
902
903
/**
904
* Copy and unconditionally byte swap 32 bit elements from a heap array to off-heap memory
905
*
906
* @param src
907
* the source array, must be a 32-bit primitive array type
908
* @param srcPos
909
* byte offset within source array of the first element to read
910
* @param dstAddr
911
* destination address
912
* @param length
913
* number of bytes to copy
914
*/
915
static void copyFromIntArray(Object src, long srcPos, long dstAddr, long length) {
916
copySwapMemory(src, unsafe.arrayBaseOffset(src.getClass()) + srcPos, null, dstAddr, length, 4);
917
}
918
919
/**
920
* Copy and unconditionally byte swap 32 bit elements from off-heap memory to a heap array
921
*
922
* @param srcAddr
923
* source address
924
* @param dst
925
* destination array, must be a 32-bit primitive array type
926
* @param dstPos
927
* byte offset within the destination array of the first element to write
928
* @param length
929
* number of bytes to copy
930
*/
931
static void copyToIntArray(long srcAddr, Object dst, long dstPos, long length) {
932
copySwapMemory(null, srcAddr, dst, unsafe.arrayBaseOffset(dst.getClass()) + dstPos, length, 4);
933
}
934
935
/**
936
* Copy and unconditionally byte swap 64 bit elements from a heap array to off-heap memory
937
*
938
* @param src
939
* the source array, must be a 64-bit primitive array type
940
* @param srcPos
941
* byte offset within source array of the first element to read
942
* @param dstAddr
943
* destination address
944
* @param length
945
* number of bytes to copy
946
*/
947
static void copyFromLongArray(Object src, long srcPos, long dstAddr, long length) {
948
copySwapMemory(src, unsafe.arrayBaseOffset(src.getClass()) + srcPos, null, dstAddr, length, 8);
949
}
950
951
/**
952
* Copy and unconditionally byte swap 64 bit elements from off-heap memory to a heap array
953
*
954
* @param srcAddr
955
* source address
956
* @param dst
957
* destination array, must be a 64-bit primitive array type
958
* @param dstPos
959
* byte offset within the destination array of the first element to write
960
* @param length
961
* number of bytes to copy
962
*/
963
static void copyToLongArray(long srcAddr, Object dst, long dstPos, long length) {
964
copySwapMemory(null, srcAddr, dst, unsafe.arrayBaseOffset(dst.getClass()) + dstPos, length, 8);
965
}
966
967
private static boolean isPrimitiveArray(Class<?> c) {
968
Class<?> componentType = c.getComponentType();
969
return componentType != null && componentType.isPrimitive();
970
}
971
972
private native static void copySwapMemory0(Object srcBase, long srcOffset,
973
Object destBase, long destOffset,
974
long bytes, long elemSize);
975
976
/**
977
* Copies all elements from one block of memory to another block,
978
* *unconditionally* byte swapping the elements on the fly.
979
*
980
* <p>This method determines each block's base address by means of two parameters,
981
* and so it provides (in effect) a <em>double-register</em> addressing mode,
982
* as discussed in {@link sun.misc.Unsafe#getInt(Object,long)}. When the
983
* object reference is null, the offset supplies an absolute base address.
984
*
985
* @since 8u201
986
*/
987
private static void copySwapMemory(Object srcBase, long srcOffset,
988
Object destBase, long destOffset,
989
long bytes, long elemSize) {
990
if (bytes < 0) {
991
throw new IllegalArgumentException();
992
}
993
if (elemSize != 2 && elemSize != 4 && elemSize != 8) {
994
throw new IllegalArgumentException();
995
}
996
if (bytes % elemSize != 0) {
997
throw new IllegalArgumentException();
998
}
999
if ((srcBase == null && srcOffset == 0) ||
1000
(destBase == null && destOffset == 0)) {
1001
throw new NullPointerException();
1002
}
1003
1004
// Must be off-heap, or primitive heap arrays
1005
if (srcBase != null && (srcOffset < 0 || !isPrimitiveArray(srcBase.getClass()))) {
1006
throw new IllegalArgumentException();
1007
}
1008
if (destBase != null && (destOffset < 0 || !isPrimitiveArray(destBase.getClass()))) {
1009
throw new IllegalArgumentException();
1010
}
1011
1012
// Sanity check size and offsets on 32-bit platforms. Most
1013
// significant 32 bits must be zero.
1014
if (unsafe.addressSize() == 4 &&
1015
(bytes >>> 32 != 0 || srcOffset >>> 32 != 0 || destOffset >>> 32 != 0)) {
1016
throw new IllegalArgumentException();
1017
}
1018
1019
if (bytes == 0) {
1020
return;
1021
}
1022
1023
copySwapMemory0(srcBase, srcOffset, destBase, destOffset, bytes, elemSize);
1024
}
1025
1026
}
1027
1028