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/invoke/util/Wrapper.java
38918 views
1
/*
2
* Copyright (c) 2008, 2012, 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.invoke.util;
27
28
public enum Wrapper {
29
// wrapperType primitiveType char zero emptyArray format
30
BOOLEAN( Boolean.class, boolean.class, 'Z', (Boolean)false, new boolean[0], Format.unsigned( 1)),
31
// These must be in the order defined for widening primitive conversions in JLS 5.1.2
32
BYTE ( Byte.class, byte.class, 'B', (Byte)(byte)0, new byte[0], Format.signed( 8)),
33
SHORT ( Short.class, short.class, 'S', (Short)(short)0, new short[0], Format.signed( 16)),
34
CHAR (Character.class, char.class, 'C', (Character)(char)0, new char[0], Format.unsigned(16)),
35
INT ( Integer.class, int.class, 'I', (Integer)/*(int)*/0, new int[0], Format.signed( 32)),
36
LONG ( Long.class, long.class, 'J', (Long)(long)0, new long[0], Format.signed( 64)),
37
FLOAT ( Float.class, float.class, 'F', (Float)(float)0, new float[0], Format.floating(32)),
38
DOUBLE ( Double.class, double.class, 'D', (Double)(double)0, new double[0], Format.floating(64)),
39
OBJECT ( Object.class, Object.class, 'L', null, new Object[0], Format.other( 1)),
40
// VOID must be the last type, since it is "assignable" from any other type:
41
VOID ( Void.class, void.class, 'V', null, null, Format.other( 0)),
42
;
43
44
private final Class<?> wrapperType;
45
private final Class<?> primitiveType;
46
private final char basicTypeChar;
47
private final Object zero;
48
private final Object emptyArray;
49
private final int format;
50
private final String wrapperSimpleName;
51
private final String primitiveSimpleName;
52
53
private Wrapper(Class<?> wtype, Class<?> ptype, char tchar, Object zero, Object emptyArray, int format) {
54
this.wrapperType = wtype;
55
this.primitiveType = ptype;
56
this.basicTypeChar = tchar;
57
this.zero = zero;
58
this.emptyArray = emptyArray;
59
this.format = format;
60
this.wrapperSimpleName = wtype.getSimpleName();
61
this.primitiveSimpleName = ptype.getSimpleName();
62
}
63
64
/** For debugging, give the details of this wrapper. */
65
public String detailString() {
66
return wrapperSimpleName+
67
java.util.Arrays.asList(wrapperType, primitiveType,
68
basicTypeChar, zero,
69
"0x"+Integer.toHexString(format));
70
}
71
72
private static abstract class Format {
73
static final int SLOT_SHIFT = 0, SIZE_SHIFT = 2, KIND_SHIFT = 12;
74
static final int
75
SIGNED = (-1) << KIND_SHIFT,
76
UNSIGNED = 0 << KIND_SHIFT,
77
FLOATING = 1 << KIND_SHIFT;
78
static final int
79
SLOT_MASK = ((1<<(SIZE_SHIFT-SLOT_SHIFT))-1),
80
SIZE_MASK = ((1<<(KIND_SHIFT-SIZE_SHIFT))-1);
81
static int format(int kind, int size, int slots) {
82
assert(((kind >> KIND_SHIFT) << KIND_SHIFT) == kind);
83
assert((size & (size-1)) == 0); // power of two
84
assert((kind == SIGNED) ? (size > 0) :
85
(kind == UNSIGNED) ? (size > 0) :
86
(kind == FLOATING) ? (size == 32 || size == 64) :
87
false);
88
assert((slots == 2) ? (size == 64) :
89
(slots == 1) ? (size <= 32) :
90
false);
91
return kind | (size << SIZE_SHIFT) | (slots << SLOT_SHIFT);
92
}
93
static final int
94
INT = SIGNED | (32 << SIZE_SHIFT) | (1 << SLOT_SHIFT),
95
SHORT = SIGNED | (16 << SIZE_SHIFT) | (1 << SLOT_SHIFT),
96
BOOLEAN = UNSIGNED | (1 << SIZE_SHIFT) | (1 << SLOT_SHIFT),
97
CHAR = UNSIGNED | (16 << SIZE_SHIFT) | (1 << SLOT_SHIFT),
98
FLOAT = FLOATING | (32 << SIZE_SHIFT) | (1 << SLOT_SHIFT),
99
VOID = UNSIGNED | (0 << SIZE_SHIFT) | (0 << SLOT_SHIFT),
100
NUM_MASK = (-1) << SIZE_SHIFT;
101
static int signed(int size) { return format(SIGNED, size, (size > 32 ? 2 : 1)); }
102
static int unsigned(int size) { return format(UNSIGNED, size, (size > 32 ? 2 : 1)); }
103
static int floating(int size) { return format(FLOATING, size, (size > 32 ? 2 : 1)); }
104
static int other(int slots) { return slots << SLOT_SHIFT; }
105
}
106
107
/// format queries:
108
109
/** How many bits are in the wrapped value? Returns 0 for OBJECT or VOID. */
110
public int bitWidth() { return (format >> Format.SIZE_SHIFT) & Format.SIZE_MASK; }
111
/** How many JVM stack slots occupied by the wrapped value? Returns 0 for VOID. */
112
public int stackSlots() { return (format >> Format.SLOT_SHIFT) & Format.SLOT_MASK; }
113
/** Does the wrapped value occupy a single JVM stack slot? */
114
public boolean isSingleWord() { return (format & (1 << Format.SLOT_SHIFT)) != 0; }
115
/** Does the wrapped value occupy two JVM stack slots? */
116
public boolean isDoubleWord() { return (format & (2 << Format.SLOT_SHIFT)) != 0; }
117
/** Is the wrapped type numeric (not void or object)? */
118
public boolean isNumeric() { return (format & Format.NUM_MASK) != 0; }
119
/** Is the wrapped type a primitive other than float, double, or void? */
120
public boolean isIntegral() { return isNumeric() && format < Format.FLOAT; }
121
/** Is the wrapped type one of int, boolean, byte, char, or short? */
122
public boolean isSubwordOrInt() { return isIntegral() && isSingleWord(); }
123
/* Is the wrapped value a signed integral type (one of byte, short, int, or long)? */
124
public boolean isSigned() { return format < Format.VOID; }
125
/* Is the wrapped value an unsigned integral type (one of boolean or char)? */
126
public boolean isUnsigned() { return format >= Format.BOOLEAN && format < Format.FLOAT; }
127
/** Is the wrapped type either float or double? */
128
public boolean isFloating() { return format >= Format.FLOAT; }
129
/** Is the wrapped type either void or a reference? */
130
public boolean isOther() { return (format & ~Format.SLOT_MASK) == 0; }
131
132
/** Does the JLS 5.1.2 allow a variable of this wrapper's
133
* primitive type to be assigned from a value of the given wrapper's primitive type?
134
* Cases:
135
* <ul>
136
* <li>unboxing followed by widening primitive conversion
137
* <li>any type converted to {@code void} (i.e., dropping a method call's value)
138
* <li>boxing conversion followed by widening reference conversion to {@code Object}
139
* </ul>
140
* These are the cases allowed by MethodHandle.asType.
141
*/
142
public boolean isConvertibleFrom(Wrapper source) {
143
if (this == source) return true;
144
if (this.compareTo(source) < 0) {
145
// At best, this is a narrowing conversion.
146
return false;
147
}
148
// All conversions are allowed in the enum order between floats and signed ints.
149
// First detect non-signed non-float types (boolean, char, Object, void).
150
boolean floatOrSigned = (((this.format & source.format) & Format.SIGNED) != 0);
151
if (!floatOrSigned) {
152
if (this.isOther()) return true;
153
// can convert char to int or wider, but nothing else
154
if (source.format == Format.CHAR) return true;
155
// no other conversions are classified as widening
156
return false;
157
}
158
// All signed and float conversions in the enum order are widening.
159
assert(this.isFloating() || this.isSigned());
160
assert(source.isFloating() || source.isSigned());
161
return true;
162
}
163
164
static { assert(checkConvertibleFrom()); }
165
private static boolean checkConvertibleFrom() {
166
// Check the matrix for correct classification of widening conversions.
167
for (Wrapper w : values()) {
168
assert(w.isConvertibleFrom(w));
169
assert(VOID.isConvertibleFrom(w));
170
if (w != VOID) {
171
assert(OBJECT.isConvertibleFrom(w));
172
assert(!w.isConvertibleFrom(VOID));
173
}
174
// check relations with unsigned integral types:
175
if (w != CHAR) {
176
assert(!CHAR.isConvertibleFrom(w));
177
if (!w.isConvertibleFrom(INT))
178
assert(!w.isConvertibleFrom(CHAR));
179
}
180
if (w != BOOLEAN) {
181
assert(!BOOLEAN.isConvertibleFrom(w));
182
if (w != VOID && w != OBJECT)
183
assert(!w.isConvertibleFrom(BOOLEAN));
184
}
185
// check relations with signed integral types:
186
if (w.isSigned()) {
187
for (Wrapper x : values()) {
188
if (w == x) continue;
189
if (x.isFloating())
190
assert(!w.isConvertibleFrom(x));
191
else if (x.isSigned()) {
192
if (w.compareTo(x) < 0)
193
assert(!w.isConvertibleFrom(x));
194
else
195
assert(w.isConvertibleFrom(x));
196
}
197
}
198
}
199
// check relations with floating types:
200
if (w.isFloating()) {
201
for (Wrapper x : values()) {
202
if (w == x) continue;
203
if (x.isSigned())
204
assert(w.isConvertibleFrom(x));
205
else if (x.isFloating()) {
206
if (w.compareTo(x) < 0)
207
assert(!w.isConvertibleFrom(x));
208
else
209
assert(w.isConvertibleFrom(x));
210
}
211
}
212
}
213
}
214
return true; // i.e., assert(true)
215
}
216
217
/** Produce a zero value for the given wrapper type.
218
* This will be a numeric zero for a number or character,
219
* false for a boolean, and null for a reference or void.
220
* The common thread is that this is what is contained
221
* in a default-initialized variable of the given primitive
222
* type. (For void, it is what a reflective method returns
223
* instead of no value at all.)
224
*/
225
public Object zero() { return zero; }
226
227
/** Produce a zero value for the given wrapper type T.
228
* The optional argument must a type compatible with this wrapper.
229
* Equivalent to {@code this.cast(this.zero(), type)}.
230
*/
231
public <T> T zero(Class<T> type) { return convert(zero, type); }
232
233
/** Return the wrapper that wraps values of the given type.
234
* The type may be {@code Object}, meaning the {@code OBJECT} wrapper.
235
* Otherwise, the type must be a primitive.
236
* @throws IllegalArgumentException for unexpected types
237
*/
238
public static Wrapper forPrimitiveType(Class<?> type) {
239
Wrapper w = findPrimitiveType(type);
240
if (w != null) return w;
241
if (type.isPrimitive())
242
throw new InternalError(); // redo hash function
243
throw newIllegalArgumentException("not primitive: "+type);
244
}
245
246
static Wrapper findPrimitiveType(Class<?> type) {
247
Wrapper w = FROM_PRIM[hashPrim(type)];
248
if (w != null && w.primitiveType == type) {
249
return w;
250
}
251
return null;
252
}
253
254
/** Return the wrapper that wraps values into the given wrapper type.
255
* If it is {@code Object}, return {@code OBJECT}.
256
* Otherwise, it must be a wrapper type.
257
* The type must not be a primitive type.
258
* @throws IllegalArgumentException for unexpected types
259
*/
260
public static Wrapper forWrapperType(Class<?> type) {
261
Wrapper w = findWrapperType(type);
262
if (w != null) return w;
263
for (Wrapper x : values())
264
if (x.wrapperType == type)
265
throw new InternalError(); // redo hash function
266
throw newIllegalArgumentException("not wrapper: "+type);
267
}
268
269
static Wrapper findWrapperType(Class<?> type) {
270
Wrapper w = FROM_WRAP[hashWrap(type)];
271
if (w != null && w.wrapperType == type) {
272
return w;
273
}
274
return null;
275
}
276
277
/** Return the wrapper that corresponds to the given bytecode
278
* signature character. Return {@code OBJECT} for the character 'L'.
279
* @throws IllegalArgumentException for any non-signature character or {@code '['}.
280
*/
281
public static Wrapper forBasicType(char type) {
282
Wrapper w = FROM_CHAR[hashChar(type)];
283
if (w != null && w.basicTypeChar == type) {
284
return w;
285
}
286
for (Wrapper x : values())
287
if (w.basicTypeChar == type)
288
throw new InternalError(); // redo hash function
289
throw newIllegalArgumentException("not basic type char: "+type);
290
}
291
292
/** Return the wrapper for the given type, if it is
293
* a primitive type, else return {@code OBJECT}.
294
*/
295
public static Wrapper forBasicType(Class<?> type) {
296
if (type.isPrimitive())
297
return forPrimitiveType(type);
298
return OBJECT; // any reference, including wrappers or arrays
299
}
300
301
// Note on perfect hashes:
302
// for signature chars c, do (c + (c >> 1)) % 16
303
// for primitive type names n, do (n[0] + n[2]) % 16
304
// The type name hash works for both primitive and wrapper names.
305
// You can add "java/lang/Object" to the primitive names.
306
// But you add the wrapper name Object, use (n[2] + (3*n[1])) % 16.
307
private static final Wrapper[] FROM_PRIM = new Wrapper[16];
308
private static final Wrapper[] FROM_WRAP = new Wrapper[16];
309
private static final Wrapper[] FROM_CHAR = new Wrapper[16];
310
private static int hashPrim(Class<?> x) {
311
String xn = x.getName();
312
if (xn.length() < 3) return 0;
313
return (xn.charAt(0) + xn.charAt(2)) % 16;
314
}
315
private static int hashWrap(Class<?> x) {
316
String xn = x.getName();
317
final int offset = 10; assert(offset == "java.lang.".length());
318
if (xn.length() < offset+3) return 0;
319
return (3*xn.charAt(offset+1) + xn.charAt(offset+2)) % 16;
320
}
321
private static int hashChar(char x) {
322
return (x + (x >> 1)) % 16;
323
}
324
static {
325
for (Wrapper w : values()) {
326
int pi = hashPrim(w.primitiveType);
327
int wi = hashWrap(w.wrapperType);
328
int ci = hashChar(w.basicTypeChar);
329
assert(FROM_PRIM[pi] == null);
330
assert(FROM_WRAP[wi] == null);
331
assert(FROM_CHAR[ci] == null);
332
FROM_PRIM[pi] = w;
333
FROM_WRAP[wi] = w;
334
FROM_CHAR[ci] = w;
335
}
336
//assert(jdk.sun.invoke.util.WrapperTest.test(false));
337
}
338
339
/** What is the primitive type wrapped by this wrapper? */
340
public Class<?> primitiveType() { return primitiveType; }
341
342
/** What is the wrapper type for this wrapper? */
343
public Class<?> wrapperType() { return wrapperType; }
344
345
/** What is the wrapper type for this wrapper?
346
* Otherwise, the example type must be the wrapper type,
347
* or the corresponding primitive type.
348
* (For {@code OBJECT}, the example type can be any non-primitive,
349
* and is normalized to {@code Object.class}.)
350
* The resulting class type has the same type parameter.
351
*/
352
public <T> Class<T> wrapperType(Class<T> exampleType) {
353
if (exampleType == wrapperType) {
354
return exampleType;
355
} else if (exampleType == primitiveType ||
356
wrapperType == Object.class ||
357
exampleType.isInterface()) {
358
return forceType(wrapperType, exampleType);
359
}
360
throw newClassCastException(exampleType, primitiveType);
361
}
362
363
private static ClassCastException newClassCastException(Class<?> actual, Class<?> expected) {
364
return new ClassCastException(actual + " is not compatible with " + expected);
365
}
366
367
/** If {@code type} is a primitive type, return the corresponding
368
* wrapper type, else return {@code type} unchanged.
369
*/
370
public static <T> Class<T> asWrapperType(Class<T> type) {
371
if (type.isPrimitive()) {
372
return forPrimitiveType(type).wrapperType(type);
373
}
374
return type;
375
}
376
377
/** If {@code type} is a wrapper type, return the corresponding
378
* primitive type, else return {@code type} unchanged.
379
*/
380
public static <T> Class<T> asPrimitiveType(Class<T> type) {
381
Wrapper w = findWrapperType(type);
382
if (w != null) {
383
return forceType(w.primitiveType(), type);
384
}
385
return type;
386
}
387
388
/** Query: Is the given type a wrapper, such as {@code Integer} or {@code Void}? */
389
public static boolean isWrapperType(Class<?> type) {
390
return findWrapperType(type) != null;
391
}
392
393
/** Query: Is the given type a primitive, such as {@code int} or {@code void}? */
394
public static boolean isPrimitiveType(Class<?> type) {
395
return type.isPrimitive();
396
}
397
398
/** What is the bytecode signature character for this type?
399
* All non-primitives, including array types, report as 'L', the signature character for references.
400
*/
401
public static char basicTypeChar(Class<?> type) {
402
if (!type.isPrimitive())
403
return 'L';
404
else
405
return forPrimitiveType(type).basicTypeChar();
406
}
407
408
/** What is the bytecode signature character for this wrapper's
409
* primitive type?
410
*/
411
public char basicTypeChar() { return basicTypeChar; }
412
413
/** What is the simple name of the wrapper type?
414
*/
415
public String wrapperSimpleName() { return wrapperSimpleName; }
416
417
/** What is the simple name of the primitive type?
418
*/
419
public String primitiveSimpleName() { return primitiveSimpleName; }
420
421
// /** Wrap a value in the given type, which may be either a primitive or wrapper type.
422
// * Performs standard primitive conversions, including truncation and float conversions.
423
// */
424
// public static <T> T wrap(Object x, Class<T> type) {
425
// return Wrapper.valueOf(type).cast(x, type);
426
// }
427
428
/** Cast a wrapped value to the given type, which may be either a primitive or wrapper type.
429
* The given target type must be this wrapper's primitive or wrapper type.
430
* If this wrapper is OBJECT, the target type may also be an interface, perform no runtime check.
431
* Performs standard primitive conversions, including truncation and float conversions.
432
* The given type must be compatible with this wrapper. That is, it must either
433
* be the wrapper type (or a subtype, in the case of {@code OBJECT}) or else
434
* it must be the wrapper's primitive type.
435
* Primitive conversions are only performed if the given type is itself a primitive.
436
* @throws ClassCastException if the given type is not compatible with this wrapper
437
*/
438
public <T> T cast(Object x, Class<T> type) {
439
return convert(x, type, true);
440
}
441
442
/** Convert a wrapped value to the given type.
443
* The given target type must be this wrapper's primitive or wrapper type.
444
* This is equivalent to {@link #cast}, except that it refuses to perform
445
* narrowing primitive conversions.
446
*/
447
public <T> T convert(Object x, Class<T> type) {
448
return convert(x, type, false);
449
}
450
451
private <T> T convert(Object x, Class<T> type, boolean isCast) {
452
if (this == OBJECT) {
453
// If the target wrapper is OBJECT, just do a reference cast.
454
// If the target type is an interface, perform no runtime check.
455
// (This loophole is safe, and is allowed by the JVM verifier.)
456
// If the target type is a primitive, change it to a wrapper.
457
assert(!type.isPrimitive());
458
if (!type.isInterface())
459
type.cast(x);
460
@SuppressWarnings("unchecked")
461
T result = (T) x; // unchecked warning is expected here
462
return result;
463
}
464
Class<T> wtype = wrapperType(type);
465
if (wtype.isInstance(x)) {
466
return wtype.cast(x);
467
}
468
if (!isCast) {
469
Class<?> sourceType = x.getClass(); // throw NPE if x is null
470
Wrapper source = findWrapperType(sourceType);
471
if (source == null || !this.isConvertibleFrom(source)) {
472
throw newClassCastException(wtype, sourceType);
473
}
474
} else if (x == null) {
475
@SuppressWarnings("unchecked")
476
T z = (T) zero;
477
return z;
478
}
479
@SuppressWarnings("unchecked")
480
T result = (T) wrap(x); // unchecked warning is expected here
481
assert (result == null ? Void.class : result.getClass()) == wtype;
482
return result;
483
}
484
485
/** Cast a reference type to another reference type.
486
* If the target type is an interface, perform no runtime check.
487
* (This loophole is safe, and is allowed by the JVM verifier.)
488
* If the target type is a primitive, change it to a wrapper.
489
*/
490
static <T> Class<T> forceType(Class<?> type, Class<T> exampleType) {
491
boolean z = (type == exampleType ||
492
type.isPrimitive() && forPrimitiveType(type) == findWrapperType(exampleType) ||
493
exampleType.isPrimitive() && forPrimitiveType(exampleType) == findWrapperType(type) ||
494
type == Object.class && !exampleType.isPrimitive());
495
if (!z)
496
System.out.println(type+" <= "+exampleType);
497
assert(type == exampleType ||
498
type.isPrimitive() && forPrimitiveType(type) == findWrapperType(exampleType) ||
499
exampleType.isPrimitive() && forPrimitiveType(exampleType) == findWrapperType(type) ||
500
type == Object.class && !exampleType.isPrimitive());
501
@SuppressWarnings("unchecked")
502
Class<T> result = (Class<T>) type; // unchecked warning is expected here
503
return result;
504
}
505
506
/** Wrap a value in this wrapper's type.
507
* Performs standard primitive conversions, including truncation and float conversions.
508
* Performs returns the unchanged reference for {@code OBJECT}.
509
* Returns null for {@code VOID}.
510
* Returns a zero value for a null input.
511
* @throws ClassCastException if this wrapper is numeric and the operand
512
* is not a number, character, boolean, or null
513
*/
514
public Object wrap(Object x) {
515
// do non-numeric wrappers first
516
switch (basicTypeChar) {
517
case 'L': return x;
518
case 'V': return null;
519
}
520
Number xn = numberValue(x);
521
switch (basicTypeChar) {
522
case 'I': return Integer.valueOf(xn.intValue());
523
case 'J': return Long.valueOf(xn.longValue());
524
case 'F': return Float.valueOf(xn.floatValue());
525
case 'D': return Double.valueOf(xn.doubleValue());
526
case 'S': return Short.valueOf((short) xn.intValue());
527
case 'B': return Byte.valueOf((byte) xn.intValue());
528
case 'C': return Character.valueOf((char) xn.intValue());
529
case 'Z': return Boolean.valueOf(boolValue(xn.byteValue()));
530
}
531
throw new InternalError("bad wrapper");
532
}
533
534
/** Wrap a value (an int or smaller value) in this wrapper's type.
535
* Performs standard primitive conversions, including truncation and float conversions.
536
* Produces an {@code Integer} for {@code OBJECT}, although the exact type
537
* of the operand is not known.
538
* Returns null for {@code VOID}.
539
*/
540
public Object wrap(int x) {
541
if (basicTypeChar == 'L') return (Integer)x;
542
switch (basicTypeChar) {
543
case 'L': throw newIllegalArgumentException("cannot wrap to object type");
544
case 'V': return null;
545
case 'I': return Integer.valueOf(x);
546
case 'J': return Long.valueOf(x);
547
case 'F': return Float.valueOf(x);
548
case 'D': return Double.valueOf(x);
549
case 'S': return Short.valueOf((short) x);
550
case 'B': return Byte.valueOf((byte) x);
551
case 'C': return Character.valueOf((char) x);
552
case 'Z': return Boolean.valueOf(boolValue((byte) x));
553
}
554
throw new InternalError("bad wrapper");
555
}
556
557
private static Number numberValue(Object x) {
558
if (x instanceof Number) return (Number)x;
559
if (x instanceof Character) return (int)(Character)x;
560
if (x instanceof Boolean) return (Boolean)x ? 1 : 0;
561
// Remaining allowed case of void: Must be a null reference.
562
return (Number)x;
563
}
564
565
// Parameter type of boolValue must be byte, because
566
// MethodHandles.explicitCastArguments defines boolean
567
// conversion as first converting to byte.
568
private static boolean boolValue(byte bits) {
569
bits &= 1; // simple 31-bit zero extension
570
return (bits != 0);
571
}
572
573
private static RuntimeException newIllegalArgumentException(String message, Object x) {
574
return newIllegalArgumentException(message + x);
575
}
576
private static RuntimeException newIllegalArgumentException(String message) {
577
return new IllegalArgumentException(message);
578
}
579
580
// primitive array support
581
public Object makeArray(int len) {
582
return java.lang.reflect.Array.newInstance(primitiveType, len);
583
}
584
public Class<?> arrayType() {
585
return emptyArray.getClass();
586
}
587
public void copyArrayUnboxing(Object[] values, int vpos, Object a, int apos, int length) {
588
if (a.getClass() != arrayType())
589
arrayType().cast(a); // throw NPE or CCE if bad type
590
for (int i = 0; i < length; i++) {
591
Object value = values[i+vpos];
592
value = convert(value, primitiveType);
593
java.lang.reflect.Array.set(a, i+apos, value);
594
}
595
}
596
public void copyArrayBoxing(Object a, int apos, Object[] values, int vpos, int length) {
597
if (a.getClass() != arrayType())
598
arrayType().cast(a); // throw NPE or CCE if bad type
599
for (int i = 0; i < length; i++) {
600
Object value = java.lang.reflect.Array.get(a, i+apos);
601
//Already done: value = convert(value, primitiveType);
602
assert(value.getClass() == wrapperType);
603
values[i+vpos] = value;
604
}
605
}
606
}
607
608