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/sun/security/provider/ByteArrayAccess.java
38830 views
1
/*
2
* Copyright (c) 2006, 2016, 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 sun.security.provider;
27
28
import static java.lang.Integer.reverseBytes;
29
import static java.lang.Long.reverseBytes;
30
31
import java.nio.ByteOrder;
32
33
import sun.misc.Unsafe;
34
35
/**
36
* Optimized methods for converting between byte[] and int[]/long[], both for
37
* big endian and little endian byte orders.
38
*
39
* Currently, it includes a default code path plus two optimized code paths.
40
* One is for little endian architectures that support full speed int/long
41
* access at unaligned addresses (i.e. x86/amd64). The second is for big endian
42
* architectures (that only support correctly aligned access), such as SPARC.
43
* These are the only platforms we currently support, but other optimized
44
* variants could be added as needed.
45
*
46
* NOTE that ArrayIndexOutOfBoundsException will be thrown if the bounds checks
47
* failed.
48
*
49
* This class may also be helpful in improving the performance of the
50
* crypto code in the SunJCE provider. However, for now it is only accessible by
51
* the message digest implementation in the SUN provider.
52
*
53
* @since 1.6
54
* @author Andreas Sterbenz
55
*/
56
final class ByteArrayAccess {
57
58
private ByteArrayAccess() {
59
// empty
60
}
61
62
private static final Unsafe unsafe = Unsafe.getUnsafe();
63
64
// whether to use the optimized path for little endian platforms that
65
// support full speed unaligned memory access.
66
private static final boolean littleEndianUnaligned;
67
68
// whether to use the optimzied path for big endian platforms that
69
// support only correctly aligned full speed memory access.
70
// (Note that on SPARC unaligned memory access is possible, but it is
71
// implemented using a software trap and therefore very slow)
72
private static final boolean bigEndian;
73
74
private final static int byteArrayOfs = unsafe.arrayBaseOffset(byte[].class);
75
76
static {
77
boolean scaleOK = ((unsafe.arrayIndexScale(byte[].class) == 1)
78
&& (unsafe.arrayIndexScale(int[].class) == 4)
79
&& (unsafe.arrayIndexScale(long[].class) == 8)
80
&& ((byteArrayOfs & 3) == 0));
81
82
ByteOrder byteOrder = ByteOrder.nativeOrder();
83
littleEndianUnaligned =
84
scaleOK && unaligned() && (byteOrder == ByteOrder.LITTLE_ENDIAN);
85
bigEndian =
86
scaleOK && (byteOrder == ByteOrder.BIG_ENDIAN);
87
}
88
89
// Return whether this platform supports full speed int/long memory access
90
// at unaligned addresses.
91
// This code was copied from java.nio.Bits because there is no equivalent
92
// public API.
93
private static boolean unaligned() {
94
String arch = java.security.AccessController.doPrivileged
95
(new sun.security.action.GetPropertyAction("os.arch", ""));
96
return arch.equals("i386") || arch.equals("x86") || arch.equals("amd64")
97
|| arch.equals("x86_64") || arch.equals("ppc64") || arch.equals("ppc64le")
98
|| arch.equals("aarch64");
99
}
100
101
/**
102
* byte[] to int[] conversion, little endian byte order.
103
*/
104
static void b2iLittle(byte[] in, int inOfs, int[] out, int outOfs, int len) {
105
if ((inOfs < 0) || ((in.length - inOfs) < len) ||
106
(outOfs < 0) || ((out.length - outOfs) < len/4)) {
107
throw new ArrayIndexOutOfBoundsException();
108
}
109
if (littleEndianUnaligned) {
110
inOfs += byteArrayOfs;
111
len += inOfs;
112
while (inOfs < len) {
113
out[outOfs++] = unsafe.getInt(in, (long)inOfs);
114
inOfs += 4;
115
}
116
} else if (bigEndian && ((inOfs & 3) == 0)) {
117
inOfs += byteArrayOfs;
118
len += inOfs;
119
while (inOfs < len) {
120
out[outOfs++] = reverseBytes(unsafe.getInt(in, (long)inOfs));
121
inOfs += 4;
122
}
123
} else {
124
len += inOfs;
125
while (inOfs < len) {
126
out[outOfs++] = ((in[inOfs ] & 0xff) )
127
| ((in[inOfs + 1] & 0xff) << 8)
128
| ((in[inOfs + 2] & 0xff) << 16)
129
| ((in[inOfs + 3] ) << 24);
130
inOfs += 4;
131
}
132
}
133
}
134
135
// Special optimization of b2iLittle(in, inOfs, out, 0, 64)
136
static void b2iLittle64(byte[] in, int inOfs, int[] out) {
137
if ((inOfs < 0) || ((in.length - inOfs) < 64) ||
138
(out.length < 16)) {
139
throw new ArrayIndexOutOfBoundsException();
140
}
141
if (littleEndianUnaligned) {
142
inOfs += byteArrayOfs;
143
out[ 0] = unsafe.getInt(in, (long)(inOfs ));
144
out[ 1] = unsafe.getInt(in, (long)(inOfs + 4));
145
out[ 2] = unsafe.getInt(in, (long)(inOfs + 8));
146
out[ 3] = unsafe.getInt(in, (long)(inOfs + 12));
147
out[ 4] = unsafe.getInt(in, (long)(inOfs + 16));
148
out[ 5] = unsafe.getInt(in, (long)(inOfs + 20));
149
out[ 6] = unsafe.getInt(in, (long)(inOfs + 24));
150
out[ 7] = unsafe.getInt(in, (long)(inOfs + 28));
151
out[ 8] = unsafe.getInt(in, (long)(inOfs + 32));
152
out[ 9] = unsafe.getInt(in, (long)(inOfs + 36));
153
out[10] = unsafe.getInt(in, (long)(inOfs + 40));
154
out[11] = unsafe.getInt(in, (long)(inOfs + 44));
155
out[12] = unsafe.getInt(in, (long)(inOfs + 48));
156
out[13] = unsafe.getInt(in, (long)(inOfs + 52));
157
out[14] = unsafe.getInt(in, (long)(inOfs + 56));
158
out[15] = unsafe.getInt(in, (long)(inOfs + 60));
159
} else if (bigEndian && ((inOfs & 3) == 0)) {
160
inOfs += byteArrayOfs;
161
out[ 0] = reverseBytes(unsafe.getInt(in, (long)(inOfs )));
162
out[ 1] = reverseBytes(unsafe.getInt(in, (long)(inOfs + 4)));
163
out[ 2] = reverseBytes(unsafe.getInt(in, (long)(inOfs + 8)));
164
out[ 3] = reverseBytes(unsafe.getInt(in, (long)(inOfs + 12)));
165
out[ 4] = reverseBytes(unsafe.getInt(in, (long)(inOfs + 16)));
166
out[ 5] = reverseBytes(unsafe.getInt(in, (long)(inOfs + 20)));
167
out[ 6] = reverseBytes(unsafe.getInt(in, (long)(inOfs + 24)));
168
out[ 7] = reverseBytes(unsafe.getInt(in, (long)(inOfs + 28)));
169
out[ 8] = reverseBytes(unsafe.getInt(in, (long)(inOfs + 32)));
170
out[ 9] = reverseBytes(unsafe.getInt(in, (long)(inOfs + 36)));
171
out[10] = reverseBytes(unsafe.getInt(in, (long)(inOfs + 40)));
172
out[11] = reverseBytes(unsafe.getInt(in, (long)(inOfs + 44)));
173
out[12] = reverseBytes(unsafe.getInt(in, (long)(inOfs + 48)));
174
out[13] = reverseBytes(unsafe.getInt(in, (long)(inOfs + 52)));
175
out[14] = reverseBytes(unsafe.getInt(in, (long)(inOfs + 56)));
176
out[15] = reverseBytes(unsafe.getInt(in, (long)(inOfs + 60)));
177
} else {
178
b2iLittle(in, inOfs, out, 0, 64);
179
}
180
}
181
182
/**
183
* int[] to byte[] conversion, little endian byte order.
184
*/
185
static void i2bLittle(int[] in, int inOfs, byte[] out, int outOfs, int len) {
186
if ((inOfs < 0) || ((in.length - inOfs) < len/4) ||
187
(outOfs < 0) || ((out.length - outOfs) < len)) {
188
throw new ArrayIndexOutOfBoundsException();
189
}
190
if (littleEndianUnaligned) {
191
outOfs += byteArrayOfs;
192
len += outOfs;
193
while (outOfs < len) {
194
unsafe.putInt(out, (long)outOfs, in[inOfs++]);
195
outOfs += 4;
196
}
197
} else if (bigEndian && ((outOfs & 3) == 0)) {
198
outOfs += byteArrayOfs;
199
len += outOfs;
200
while (outOfs < len) {
201
unsafe.putInt(out, (long)outOfs, reverseBytes(in[inOfs++]));
202
outOfs += 4;
203
}
204
} else {
205
len += outOfs;
206
while (outOfs < len) {
207
int i = in[inOfs++];
208
out[outOfs++] = (byte)(i );
209
out[outOfs++] = (byte)(i >> 8);
210
out[outOfs++] = (byte)(i >> 16);
211
out[outOfs++] = (byte)(i >> 24);
212
}
213
}
214
}
215
216
// Store one 32-bit value into out[outOfs..outOfs+3] in little endian order.
217
static void i2bLittle4(int val, byte[] out, int outOfs) {
218
if ((outOfs < 0) || ((out.length - outOfs) < 4)) {
219
throw new ArrayIndexOutOfBoundsException();
220
}
221
if (littleEndianUnaligned) {
222
unsafe.putInt(out, (long)(byteArrayOfs + outOfs), val);
223
} else if (bigEndian && ((outOfs & 3) == 0)) {
224
unsafe.putInt(out, (long)(byteArrayOfs + outOfs), reverseBytes(val));
225
} else {
226
out[outOfs ] = (byte)(val );
227
out[outOfs + 1] = (byte)(val >> 8);
228
out[outOfs + 2] = (byte)(val >> 16);
229
out[outOfs + 3] = (byte)(val >> 24);
230
}
231
}
232
233
/**
234
* byte[] to int[] conversion, big endian byte order.
235
*/
236
static void b2iBig(byte[] in, int inOfs, int[] out, int outOfs, int len) {
237
if ((inOfs < 0) || ((in.length - inOfs) < len) ||
238
(outOfs < 0) || ((out.length - outOfs) < len/4)) {
239
throw new ArrayIndexOutOfBoundsException();
240
}
241
if (littleEndianUnaligned) {
242
inOfs += byteArrayOfs;
243
len += inOfs;
244
while (inOfs < len) {
245
out[outOfs++] = reverseBytes(unsafe.getInt(in, (long)inOfs));
246
inOfs += 4;
247
}
248
} else if (bigEndian && ((inOfs & 3) == 0)) {
249
inOfs += byteArrayOfs;
250
len += inOfs;
251
while (inOfs < len) {
252
out[outOfs++] = unsafe.getInt(in, (long)inOfs);
253
inOfs += 4;
254
}
255
} else {
256
len += inOfs;
257
while (inOfs < len) {
258
out[outOfs++] = ((in[inOfs + 3] & 0xff) )
259
| ((in[inOfs + 2] & 0xff) << 8)
260
| ((in[inOfs + 1] & 0xff) << 16)
261
| ((in[inOfs ] ) << 24);
262
inOfs += 4;
263
}
264
}
265
}
266
267
// Special optimization of b2iBig(in, inOfs, out, 0, 64)
268
static void b2iBig64(byte[] in, int inOfs, int[] out) {
269
if ((inOfs < 0) || ((in.length - inOfs) < 64) ||
270
(out.length < 16)) {
271
throw new ArrayIndexOutOfBoundsException();
272
}
273
if (littleEndianUnaligned) {
274
inOfs += byteArrayOfs;
275
out[ 0] = reverseBytes(unsafe.getInt(in, (long)(inOfs )));
276
out[ 1] = reverseBytes(unsafe.getInt(in, (long)(inOfs + 4)));
277
out[ 2] = reverseBytes(unsafe.getInt(in, (long)(inOfs + 8)));
278
out[ 3] = reverseBytes(unsafe.getInt(in, (long)(inOfs + 12)));
279
out[ 4] = reverseBytes(unsafe.getInt(in, (long)(inOfs + 16)));
280
out[ 5] = reverseBytes(unsafe.getInt(in, (long)(inOfs + 20)));
281
out[ 6] = reverseBytes(unsafe.getInt(in, (long)(inOfs + 24)));
282
out[ 7] = reverseBytes(unsafe.getInt(in, (long)(inOfs + 28)));
283
out[ 8] = reverseBytes(unsafe.getInt(in, (long)(inOfs + 32)));
284
out[ 9] = reverseBytes(unsafe.getInt(in, (long)(inOfs + 36)));
285
out[10] = reverseBytes(unsafe.getInt(in, (long)(inOfs + 40)));
286
out[11] = reverseBytes(unsafe.getInt(in, (long)(inOfs + 44)));
287
out[12] = reverseBytes(unsafe.getInt(in, (long)(inOfs + 48)));
288
out[13] = reverseBytes(unsafe.getInt(in, (long)(inOfs + 52)));
289
out[14] = reverseBytes(unsafe.getInt(in, (long)(inOfs + 56)));
290
out[15] = reverseBytes(unsafe.getInt(in, (long)(inOfs + 60)));
291
} else if (bigEndian && ((inOfs & 3) == 0)) {
292
inOfs += byteArrayOfs;
293
out[ 0] = unsafe.getInt(in, (long)(inOfs ));
294
out[ 1] = unsafe.getInt(in, (long)(inOfs + 4));
295
out[ 2] = unsafe.getInt(in, (long)(inOfs + 8));
296
out[ 3] = unsafe.getInt(in, (long)(inOfs + 12));
297
out[ 4] = unsafe.getInt(in, (long)(inOfs + 16));
298
out[ 5] = unsafe.getInt(in, (long)(inOfs + 20));
299
out[ 6] = unsafe.getInt(in, (long)(inOfs + 24));
300
out[ 7] = unsafe.getInt(in, (long)(inOfs + 28));
301
out[ 8] = unsafe.getInt(in, (long)(inOfs + 32));
302
out[ 9] = unsafe.getInt(in, (long)(inOfs + 36));
303
out[10] = unsafe.getInt(in, (long)(inOfs + 40));
304
out[11] = unsafe.getInt(in, (long)(inOfs + 44));
305
out[12] = unsafe.getInt(in, (long)(inOfs + 48));
306
out[13] = unsafe.getInt(in, (long)(inOfs + 52));
307
out[14] = unsafe.getInt(in, (long)(inOfs + 56));
308
out[15] = unsafe.getInt(in, (long)(inOfs + 60));
309
} else {
310
b2iBig(in, inOfs, out, 0, 64);
311
}
312
}
313
314
/**
315
* int[] to byte[] conversion, big endian byte order.
316
*/
317
static void i2bBig(int[] in, int inOfs, byte[] out, int outOfs, int len) {
318
if ((inOfs < 0) || ((in.length - inOfs) < len/4) ||
319
(outOfs < 0) || ((out.length - outOfs) < len)) {
320
throw new ArrayIndexOutOfBoundsException();
321
}
322
if (littleEndianUnaligned) {
323
outOfs += byteArrayOfs;
324
len += outOfs;
325
while (outOfs < len) {
326
unsafe.putInt(out, (long)outOfs, reverseBytes(in[inOfs++]));
327
outOfs += 4;
328
}
329
} else if (bigEndian && ((outOfs & 3) == 0)) {
330
outOfs += byteArrayOfs;
331
len += outOfs;
332
while (outOfs < len) {
333
unsafe.putInt(out, (long)outOfs, in[inOfs++]);
334
outOfs += 4;
335
}
336
} else {
337
len += outOfs;
338
while (outOfs < len) {
339
int i = in[inOfs++];
340
out[outOfs++] = (byte)(i >> 24);
341
out[outOfs++] = (byte)(i >> 16);
342
out[outOfs++] = (byte)(i >> 8);
343
out[outOfs++] = (byte)(i );
344
}
345
}
346
}
347
348
// Store one 32-bit value into out[outOfs..outOfs+3] in big endian order.
349
static void i2bBig4(int val, byte[] out, int outOfs) {
350
if ((outOfs < 0) || ((out.length - outOfs) < 4)) {
351
throw new ArrayIndexOutOfBoundsException();
352
}
353
if (littleEndianUnaligned) {
354
unsafe.putInt(out, (long)(byteArrayOfs + outOfs), reverseBytes(val));
355
} else if (bigEndian && ((outOfs & 3) == 0)) {
356
unsafe.putInt(out, (long)(byteArrayOfs + outOfs), val);
357
} else {
358
out[outOfs ] = (byte)(val >> 24);
359
out[outOfs + 1] = (byte)(val >> 16);
360
out[outOfs + 2] = (byte)(val >> 8);
361
out[outOfs + 3] = (byte)(val );
362
}
363
}
364
365
/**
366
* byte[] to long[] conversion, big endian byte order.
367
*/
368
static void b2lBig(byte[] in, int inOfs, long[] out, int outOfs, int len) {
369
if ((inOfs < 0) || ((in.length - inOfs) < len) ||
370
(outOfs < 0) || ((out.length - outOfs) < len/8)) {
371
throw new ArrayIndexOutOfBoundsException();
372
}
373
if (littleEndianUnaligned) {
374
inOfs += byteArrayOfs;
375
len += inOfs;
376
while (inOfs < len) {
377
out[outOfs++] = reverseBytes(unsafe.getLong(in, (long)inOfs));
378
inOfs += 8;
379
}
380
} else if (bigEndian && ((inOfs & 3) == 0)) {
381
// In the current HotSpot memory layout, the first element of a
382
// byte[] is only 32-bit aligned, not 64-bit.
383
// That means we could use getLong() only for offset 4, 12, etc.,
384
// which would rarely occur in practice. Instead, we use an
385
// optimization that uses getInt() so that it works for offset 0.
386
inOfs += byteArrayOfs;
387
len += inOfs;
388
while (inOfs < len) {
389
out[outOfs++] =
390
((long)unsafe.getInt(in, (long)inOfs) << 32)
391
| (unsafe.getInt(in, (long)(inOfs + 4)) & 0xffffffffL);
392
inOfs += 8;
393
}
394
} else {
395
len += inOfs;
396
while (inOfs < len) {
397
int i1 = ((in[inOfs + 3] & 0xff) )
398
| ((in[inOfs + 2] & 0xff) << 8)
399
| ((in[inOfs + 1] & 0xff) << 16)
400
| ((in[inOfs ] ) << 24);
401
inOfs += 4;
402
int i2 = ((in[inOfs + 3] & 0xff) )
403
| ((in[inOfs + 2] & 0xff) << 8)
404
| ((in[inOfs + 1] & 0xff) << 16)
405
| ((in[inOfs ] ) << 24);
406
out[outOfs++] = ((long)i1 << 32) | (i2 & 0xffffffffL);
407
inOfs += 4;
408
}
409
}
410
}
411
412
// Special optimization of b2lBig(in, inOfs, out, 0, 128)
413
static void b2lBig128(byte[] in, int inOfs, long[] out) {
414
if ((inOfs < 0) || ((in.length - inOfs) < 128) ||
415
(out.length < 16)) {
416
throw new ArrayIndexOutOfBoundsException();
417
}
418
if (littleEndianUnaligned) {
419
inOfs += byteArrayOfs;
420
out[ 0] = reverseBytes(unsafe.getLong(in, (long)(inOfs )));
421
out[ 1] = reverseBytes(unsafe.getLong(in, (long)(inOfs + 8)));
422
out[ 2] = reverseBytes(unsafe.getLong(in, (long)(inOfs + 16)));
423
out[ 3] = reverseBytes(unsafe.getLong(in, (long)(inOfs + 24)));
424
out[ 4] = reverseBytes(unsafe.getLong(in, (long)(inOfs + 32)));
425
out[ 5] = reverseBytes(unsafe.getLong(in, (long)(inOfs + 40)));
426
out[ 6] = reverseBytes(unsafe.getLong(in, (long)(inOfs + 48)));
427
out[ 7] = reverseBytes(unsafe.getLong(in, (long)(inOfs + 56)));
428
out[ 8] = reverseBytes(unsafe.getLong(in, (long)(inOfs + 64)));
429
out[ 9] = reverseBytes(unsafe.getLong(in, (long)(inOfs + 72)));
430
out[10] = reverseBytes(unsafe.getLong(in, (long)(inOfs + 80)));
431
out[11] = reverseBytes(unsafe.getLong(in, (long)(inOfs + 88)));
432
out[12] = reverseBytes(unsafe.getLong(in, (long)(inOfs + 96)));
433
out[13] = reverseBytes(unsafe.getLong(in, (long)(inOfs + 104)));
434
out[14] = reverseBytes(unsafe.getLong(in, (long)(inOfs + 112)));
435
out[15] = reverseBytes(unsafe.getLong(in, (long)(inOfs + 120)));
436
} else {
437
// no optimization for big endian, see comments in b2lBig
438
b2lBig(in, inOfs, out, 0, 128);
439
}
440
}
441
442
/**
443
* long[] to byte[] conversion, big endian byte order.
444
*/
445
static void l2bBig(long[] in, int inOfs, byte[] out, int outOfs, int len) {
446
if ((inOfs < 0) || ((in.length - inOfs) < len/8) ||
447
(outOfs < 0) || ((out.length - outOfs) < len)) {
448
throw new ArrayIndexOutOfBoundsException();
449
}
450
len += outOfs;
451
while (outOfs < len) {
452
long i = in[inOfs++];
453
out[outOfs++] = (byte)(i >> 56);
454
out[outOfs++] = (byte)(i >> 48);
455
out[outOfs++] = (byte)(i >> 40);
456
out[outOfs++] = (byte)(i >> 32);
457
out[outOfs++] = (byte)(i >> 24);
458
out[outOfs++] = (byte)(i >> 16);
459
out[outOfs++] = (byte)(i >> 8);
460
out[outOfs++] = (byte)(i );
461
}
462
}
463
}
464
465