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