History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/sun/invoke/util/Wrapper.java (1 of 18352 files). Show all

Unified · Split

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