Home | History | Annotate | Download | only in type
      1 /*
      2  * Copyright (C) 2007 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.dexgen.rop.type;
     18 
     19 import com.android.dexgen.util.Hex;
     20 
     21 import java.util.HashMap;
     22 
     23 /**
     24  * Representation of a value type, such as may appear in a field, in a
     25  * local, on a stack, or in a method descriptor. Instances of this
     26  * class are generally interned and may be usefully compared with each
     27  * other using {@code ==}.
     28  */
     29 public final class Type implements TypeBearer, Comparable<Type> {
     30     /** {@code non-null;} intern table mapping string descriptors to instances */
     31     private static final HashMap<String, Type> internTable =
     32         new HashMap<String, Type>(500);
     33 
     34     /** {@code non-null;} table mapping types as {@code Class} objects to internal form */
     35     private static final HashMap<Class, Type> CLASS_TYPE_MAP =
     36         new HashMap<Class, Type>();
     37 
     38     /** basic type constant for {@code void} */
     39     public static final int BT_VOID = 0;
     40 
     41     /** basic type constant for {@code boolean} */
     42     public static final int BT_BOOLEAN = 1;
     43 
     44     /** basic type constant for {@code byte} */
     45     public static final int BT_BYTE = 2;
     46 
     47     /** basic type constant for {@code char} */
     48     public static final int BT_CHAR = 3;
     49 
     50     /** basic type constant for {@code double} */
     51     public static final int BT_DOUBLE = 4;
     52 
     53     /** basic type constant for {@code float} */
     54     public static final int BT_FLOAT = 5;
     55 
     56     /** basic type constant for {@code int} */
     57     public static final int BT_INT = 6;
     58 
     59     /** basic type constant for {@code long} */
     60     public static final int BT_LONG = 7;
     61 
     62     /** basic type constant for {@code short} */
     63     public static final int BT_SHORT = 8;
     64 
     65     /** basic type constant for {@code Object} */
     66     public static final int BT_OBJECT = 9;
     67 
     68     /** basic type constant for a return address */
     69     public static final int BT_ADDR = 10;
     70 
     71     /** count of basic type constants */
     72     public static final int BT_COUNT = 11;
     73 
     74     /** {@code non-null;} instance representing {@code boolean} */
     75     public static final Type BOOLEAN = new Type("Z", BT_BOOLEAN);
     76 
     77     /** {@code non-null;} instance representing {@code byte} */
     78     public static final Type BYTE = new Type("B", BT_BYTE);
     79 
     80     /** {@code non-null;} instance representing {@code char} */
     81     public static final Type CHAR = new Type("C", BT_CHAR);
     82 
     83     /** {@code non-null;} instance representing {@code double} */
     84     public static final Type DOUBLE = new Type("D", BT_DOUBLE);
     85 
     86     /** {@code non-null;} instance representing {@code float} */
     87     public static final Type FLOAT = new Type("F", BT_FLOAT);
     88 
     89     /** {@code non-null;} instance representing {@code int} */
     90     public static final Type INT = new Type("I", BT_INT);
     91 
     92     /** {@code non-null;} instance representing {@code long} */
     93     public static final Type LONG = new Type("J", BT_LONG);
     94 
     95     /** {@code non-null;} instance representing {@code short} */
     96     public static final Type SHORT = new Type("S", BT_SHORT);
     97 
     98     /** {@code non-null;} instance representing {@code void} */
     99     public static final Type VOID = new Type("V", BT_VOID);
    100 
    101     /** {@code non-null;} instance representing a known-{@code null} */
    102     public static final Type KNOWN_NULL = new Type("<null>", BT_OBJECT);
    103 
    104     /** {@code non-null;} instance representing a subroutine return address */
    105     public static final Type RETURN_ADDRESS = new Type("<addr>", BT_ADDR);
    106 
    107     static {
    108         /*
    109          * Put all the primitive types into the intern table. This needs
    110          * to happen before the array types below get interned.
    111          */
    112         putIntern(BOOLEAN);
    113         putIntern(BYTE);
    114         putIntern(CHAR);
    115         putIntern(DOUBLE);
    116         putIntern(FLOAT);
    117         putIntern(INT);
    118         putIntern(LONG);
    119         putIntern(SHORT);
    120         /*
    121          * Note: VOID isn't put in the intern table, since it's special and
    122          * shouldn't be found by a normal call to intern().
    123          */
    124 
    125         /*
    126          * Create a mapping between types as Java Class objects
    127          * and types in dx internal format.
    128          */
    129         CLASS_TYPE_MAP.put(boolean.class, BOOLEAN);
    130         CLASS_TYPE_MAP.put(short.class, SHORT);
    131         CLASS_TYPE_MAP.put(int.class, INT);
    132         CLASS_TYPE_MAP.put(long.class, LONG);
    133         CLASS_TYPE_MAP.put(char.class, CHAR);
    134         CLASS_TYPE_MAP.put(byte.class, BYTE);
    135         CLASS_TYPE_MAP.put(float.class, FLOAT);
    136         CLASS_TYPE_MAP.put(double.class, DOUBLE);
    137         CLASS_TYPE_MAP.put(void.class, VOID);
    138     }
    139 
    140     /**
    141      * {@code non-null;} instance representing
    142      * {@code java.lang.annotation.Annotation}
    143      */
    144     public static final Type ANNOTATION =
    145         intern("Ljava/lang/annotation/Annotation;");
    146 
    147     /** {@code non-null;} instance representing {@code java.lang.Class} */
    148     public static final Type CLASS = intern("Ljava/lang/Class;");
    149 
    150     /** {@code non-null;} instance representing {@code java.lang.Cloneable} */
    151     public static final Type CLONEABLE = intern("Ljava/lang/Cloneable;");
    152 
    153     /** {@code non-null;} instance representing {@code java.lang.Object} */
    154     public static final Type OBJECT = intern("Ljava/lang/Object;");
    155 
    156     /** {@code non-null;} instance representing {@code java.io.Serializable} */
    157     public static final Type SERIALIZABLE = intern("Ljava/io/Serializable;");
    158 
    159     /** {@code non-null;} instance representing {@code java.lang.String} */
    160     public static final Type STRING = intern("Ljava/lang/String;");
    161 
    162     /** {@code non-null;} instance representing {@code java.lang.Throwable} */
    163     public static final Type THROWABLE = intern("Ljava/lang/Throwable;");
    164 
    165     /**
    166      * {@code non-null;} instance representing {@code java.lang.Boolean}; the
    167      * suffix on the name helps disambiguate this from the instance
    168      * representing a primitive type
    169      */
    170     public static final Type BOOLEAN_CLASS = intern("Ljava/lang/Boolean;");
    171 
    172     /**
    173      * {@code non-null;} instance representing {@code java.lang.Byte}; the
    174      * suffix on the name helps disambiguate this from the instance
    175      * representing a primitive type
    176      */
    177     public static final Type BYTE_CLASS = intern("Ljava/lang/Byte;");
    178 
    179     /**
    180      * {@code non-null;} instance representing {@code java.lang.Character}; the
    181      * suffix on the name helps disambiguate this from the instance
    182      * representing a primitive type
    183      */
    184     public static final Type CHARACTER_CLASS = intern("Ljava/lang/Character;");
    185 
    186     /**
    187      * {@code non-null;} instance representing {@code java.lang.Double}; the
    188      * suffix on the name helps disambiguate this from the instance
    189      * representing a primitive type
    190      */
    191     public static final Type DOUBLE_CLASS = intern("Ljava/lang/Double;");
    192 
    193     /**
    194      * {@code non-null;} instance representing {@code java.lang.Float}; the
    195      * suffix on the name helps disambiguate this from the instance
    196      * representing a primitive type
    197      */
    198     public static final Type FLOAT_CLASS = intern("Ljava/lang/Float;");
    199 
    200     /**
    201      * {@code non-null;} instance representing {@code java.lang.Integer}; the
    202      * suffix on the name helps disambiguate this from the instance
    203      * representing a primitive type
    204      */
    205     public static final Type INTEGER_CLASS = intern("Ljava/lang/Integer;");
    206 
    207     /**
    208      * {@code non-null;} instance representing {@code java.lang.Long}; the
    209      * suffix on the name helps disambiguate this from the instance
    210      * representing a primitive type
    211      */
    212     public static final Type LONG_CLASS = intern("Ljava/lang/Long;");
    213 
    214     /**
    215      * {@code non-null;} instance representing {@code java.lang.Short}; the
    216      * suffix on the name helps disambiguate this from the instance
    217      * representing a primitive type
    218      */
    219     public static final Type SHORT_CLASS = intern("Ljava/lang/Short;");
    220 
    221     /**
    222      * {@code non-null;} instance representing {@code java.lang.Void}; the
    223      * suffix on the name helps disambiguate this from the instance
    224      * representing a primitive type
    225      */
    226     public static final Type VOID_CLASS = intern("Ljava/lang/Void;");
    227 
    228     /** {@code non-null;} instance representing {@code boolean[]} */
    229     public static final Type BOOLEAN_ARRAY = BOOLEAN.getArrayType();
    230 
    231     /** {@code non-null;} instance representing {@code byte[]} */
    232     public static final Type BYTE_ARRAY = BYTE.getArrayType();
    233 
    234     /** {@code non-null;} instance representing {@code char[]} */
    235     public static final Type CHAR_ARRAY = CHAR.getArrayType();
    236 
    237     /** {@code non-null;} instance representing {@code double[]} */
    238     public static final Type DOUBLE_ARRAY = DOUBLE.getArrayType();
    239 
    240     /** {@code non-null;} instance representing {@code float[]} */
    241     public static final Type FLOAT_ARRAY = FLOAT.getArrayType();
    242 
    243     /** {@code non-null;} instance representing {@code int[]} */
    244     public static final Type INT_ARRAY = INT.getArrayType();
    245 
    246     /** {@code non-null;} instance representing {@code long[]} */
    247     public static final Type LONG_ARRAY = LONG.getArrayType();
    248 
    249     /** {@code non-null;} instance representing {@code Object[]} */
    250     public static final Type OBJECT_ARRAY = OBJECT.getArrayType();
    251 
    252     /** {@code non-null;} instance representing {@code short[]} */
    253     public static final Type SHORT_ARRAY = SHORT.getArrayType();
    254 
    255     /** {@code non-null;} field descriptor for the type */
    256     private final String descriptor;
    257 
    258     /**
    259      * basic type corresponding to this type; one of the
    260      * {@code BT_*} constants
    261      */
    262     private final int basicType;
    263 
    264     /**
    265      * {@code >= -1;} for an uninitialized type, bytecode index that this
    266      * instance was allocated at; {@code Integer.MAX_VALUE} if it
    267      * was an incoming uninitialized instance; {@code -1} if this
    268      * is an <i>inititialized</i> instance
    269      */
    270     private final int newAt;
    271 
    272     /**
    273      * {@code null-ok;} the internal-form class name corresponding to this type, if
    274      * calculated; only valid if {@code this} is a reference type and
    275      * additionally not a return address
    276      */
    277     private String className;
    278 
    279     /**
    280      * {@code null-ok;} the type corresponding to an array of this type, if
    281      * calculated
    282      */
    283     private Type arrayType;
    284 
    285     /**
    286      * {@code null-ok;} the type corresponding to elements of this type, if
    287      * calculated; only valid if {@code this} is an array type
    288      */
    289     private Type componentType;
    290 
    291     /**
    292      * {@code null-ok;} the type corresponding to the initialized version of
    293      * this type, if this instance is in fact an uninitialized type
    294      */
    295     private Type initializedType;
    296 
    297     /**
    298      * Returns the unique instance corresponding to the type represented by
    299      * given {@code Class} object. See vmspec-2 sec4.3.2 for details on the
    300      * field descriptor syntax. This method does <i>not</i> allow
    301      * {@code "V"} (that is, type {@code void}) as a valid
    302      * descriptor.
    303      *
    304      * @param clazz {@code non-null;} class whose descriptor
    305      * will be internalized
    306      * @return {@code non-null;} the corresponding instance
    307      */
    308     public static Type intern(Class clazz) {
    309         return intern(getInternalTypeName(clazz));
    310     }
    311 
    312     /**
    313      * Returns the unique instance corresponding to the type with the
    314      * given descriptor. See vmspec-2 sec4.3.2 for details on the
    315      * field descriptor syntax. This method does <i>not</i> allow
    316      * {@code "V"} (that is, type {@code void}) as a valid
    317      * descriptor.
    318      *
    319      * @param descriptor {@code non-null;} the descriptor
    320      * @return {@code non-null;} the corresponding instance
    321      * @throws IllegalArgumentException thrown if the descriptor has
    322      * invalid syntax
    323      */
    324     public static Type intern(String descriptor) {
    325 
    326         Type result = internTable.get(descriptor);
    327         if (result != null) {
    328             return result;
    329         }
    330 
    331         char firstChar;
    332         try {
    333             firstChar = descriptor.charAt(0);
    334         } catch (IndexOutOfBoundsException ex) {
    335             // Translate the exception.
    336             throw new IllegalArgumentException("descriptor is empty");
    337         } catch (NullPointerException ex) {
    338             // Elucidate the exception.
    339             throw new NullPointerException("descriptor == null");
    340         }
    341 
    342         if (firstChar == '[') {
    343             /*
    344              * Recursively strip away array markers to get at the underlying
    345              * type, and build back on to form the result.
    346              */
    347             result = intern(descriptor.substring(1));
    348             return result.getArrayType();
    349         }
    350 
    351         /*
    352          * If the first character isn't '[' and it wasn't found in the
    353          * intern cache, then it had better be the descriptor for a class.
    354          */
    355 
    356         int length = descriptor.length();
    357         if ((firstChar != 'L') ||
    358             (descriptor.charAt(length - 1) != ';')) {
    359             throw new IllegalArgumentException("bad descriptor" + descriptor);
    360         }
    361 
    362         /*
    363          * Validate the characters of the class name itself. Note that
    364          * vmspec-2 does not have a coherent definition for valid
    365          * internal-form class names, and the definition here is fairly
    366          * liberal: A name is considered valid as long as it doesn't
    367          * contain any of '[' ';' '.' '(' ')', and it has no more than one
    368          * '/' in a row, and no '/' at either end.
    369          */
    370 
    371         int limit = (length - 1); // Skip the final ';'.
    372         for (int i = 1; i < limit; i++) {
    373             char c = descriptor.charAt(i);
    374             switch (c) {
    375                 case '[':
    376                 case ';':
    377                 case '.':
    378                 case '(':
    379                 case ')': {
    380                     throw new IllegalArgumentException("bad descriptor" + descriptor);
    381                 }
    382                 case '/': {
    383                     if ((i == 1) ||
    384                         (i == (length - 1)) ||
    385                         (descriptor.charAt(i - 1) == '/')) {
    386                         throw new IllegalArgumentException("bad descriptor");
    387                     }
    388                     break;
    389                 }
    390             }
    391         }
    392 
    393         result = new Type(descriptor, BT_OBJECT);
    394         return putIntern(result);
    395     }
    396 
    397     /**
    398      * Returns the unique instance corresponding to the type represented by
    399      * given {@code Class} object, allowing {@code "V"} to return the type
    400      * for {@code void}. Other than that one caveat, this method
    401      * is identical to {@link #intern}.
    402      *
    403      * @param clazz {@code non-null;} class which descriptor
    404      * will be internalized
    405      * @return {@code non-null;} the corresponding instance
    406      */
    407     public static Type internReturnType(Class clazz) {
    408         return internReturnType(getInternalTypeName(clazz));
    409     }
    410 
    411     /**
    412      * Returns the unique instance corresponding to the type with the
    413      * given descriptor, allowing {@code "V"} to return the type
    414      * for {@code void}. Other than that one caveat, this method
    415      * is identical to {@link #intern}.
    416      *
    417      * @param descriptor {@code non-null;} the descriptor
    418      * @return {@code non-null;} the corresponding instance
    419      * @throws IllegalArgumentException thrown if the descriptor has
    420      * invalid syntax
    421      */
    422     public static Type internReturnType(String descriptor) {
    423         try {
    424             if (descriptor.equals("V")) {
    425                 // This is the one special case where void may be returned.
    426                 return VOID;
    427             }
    428         } catch (NullPointerException ex) {
    429             // Elucidate the exception.
    430             throw new NullPointerException("descriptor == null");
    431         }
    432 
    433         return intern(descriptor);
    434     }
    435 
    436     /**
    437      * Returns the unique instance corresponding to the type of the
    438      * class with the given name. Calling this method is equivalent to
    439      * calling {@code intern(name)} if {@code name} begins
    440      * with {@code "["} and calling {@code intern("L" + name + ";")}
    441      * in all other cases.
    442      *
    443      * @param name {@code non-null;} the name of the class whose type is desired
    444      * @return {@code non-null;} the corresponding type
    445      * @throws IllegalArgumentException thrown if the name has
    446      * invalid syntax
    447      */
    448     public static Type internClassName(String name) {
    449         if (name == null) {
    450             throw new NullPointerException("name == null");
    451         }
    452 
    453         if (name.startsWith("[")) {
    454             return intern(name);
    455         }
    456 
    457         return intern('L' + name + ';');
    458     }
    459 
    460     /**
    461      * Converts type name in the format as returned by reflection
    462      * into dex internal form.
    463      *
    464      * @param clazz {@code non-null;} class whose name will be internalized
    465      * @return string with the type name in dex internal format
    466      */
    467     public static String getInternalTypeName(Class clazz) {
    468         if (clazz == null) {
    469             throw new NullPointerException("clazz == null");
    470         }
    471 
    472         if (clazz.isPrimitive()) {
    473             return CLASS_TYPE_MAP.get(clazz).getDescriptor();
    474         }
    475 
    476         String slashed = clazz.getName().replace('.', '/');
    477 
    478         if (clazz.isArray()) {
    479             return slashed;
    480         }
    481 
    482         return 'L' + slashed + ';';
    483     }
    484 
    485     /**
    486      * Constructs an instance corresponding to an "uninitialized type."
    487      * This is a private constructor; use one of the public static
    488      * methods to get instances.
    489      *
    490      * @param descriptor {@code non-null;} the field descriptor for the type
    491      * @param basicType basic type corresponding to this type; one of the
    492      * {@code BT_*} constants
    493      * @param newAt {@code >= -1;} allocation bytecode index
    494      */
    495     private Type(String descriptor, int basicType, int newAt) {
    496         if (descriptor == null) {
    497             throw new NullPointerException("descriptor == null");
    498         }
    499 
    500         if ((basicType < 0) || (basicType >= BT_COUNT)) {
    501             throw new IllegalArgumentException("bad basicType");
    502         }
    503 
    504         if (newAt < -1) {
    505             throw new IllegalArgumentException("newAt < -1");
    506         }
    507 
    508         this.descriptor = descriptor;
    509         this.basicType = basicType;
    510         this.newAt = newAt;
    511         this.arrayType = null;
    512         this.componentType = null;
    513         this.initializedType = null;
    514     }
    515 
    516     /**
    517      * Constructs an instance corresponding to an "initialized type."
    518      * This is a private constructor; use one of the public static
    519      * methods to get instances.
    520      *
    521      * @param descriptor {@code non-null;} the field descriptor for the type
    522      * @param basicType basic type corresponding to this type; one of the
    523      * {@code BT_*} constants
    524      */
    525     private Type(String descriptor, int basicType) {
    526         this(descriptor, basicType, -1);
    527     }
    528 
    529     /** {@inheritDoc} */
    530     @Override
    531     public boolean equals(Object other) {
    532         if (this == other) {
    533             /*
    534              * Since externally-visible types are interned, this check
    535              * helps weed out some easy cases.
    536              */
    537             return true;
    538         }
    539 
    540         if (!(other instanceof Type)) {
    541             return false;
    542         }
    543 
    544         return descriptor.equals(((Type) other).descriptor);
    545     }
    546 
    547     /** {@inheritDoc} */
    548     @Override
    549     public int hashCode() {
    550         return descriptor.hashCode();
    551     }
    552 
    553     /** {@inheritDoc} */
    554     public int compareTo(Type other) {
    555         return descriptor.compareTo(other.descriptor);
    556     }
    557 
    558     /** {@inheritDoc} */
    559     @Override
    560     public String toString() {
    561         return descriptor;
    562     }
    563 
    564     /** {@inheritDoc} */
    565     public String toHuman() {
    566         switch (basicType) {
    567             case BT_VOID:    return "void";
    568             case BT_BOOLEAN: return "boolean";
    569             case BT_BYTE:    return "byte";
    570             case BT_CHAR:    return "char";
    571             case BT_DOUBLE:  return "double";
    572             case BT_FLOAT:   return "float";
    573             case BT_INT:     return "int";
    574             case BT_LONG:    return "long";
    575             case BT_SHORT:   return "short";
    576             case BT_OBJECT:  break;
    577             default:         return descriptor;
    578         }
    579 
    580         if (isArray()) {
    581             return getComponentType().toHuman() + "[]";
    582         }
    583 
    584         // Remove the "L...;" around the type and convert "/" to ".".
    585         return getClassName().replace("/", ".");
    586     }
    587 
    588     /** {@inheritDoc} */
    589     public Type getType() {
    590         return this;
    591     }
    592 
    593     /** {@inheritDoc} */
    594     public Type getFrameType() {
    595         switch (basicType) {
    596             case BT_BOOLEAN:
    597             case BT_BYTE:
    598             case BT_CHAR:
    599             case BT_INT:
    600             case BT_SHORT: {
    601                 return INT;
    602             }
    603         }
    604 
    605         return this;
    606     }
    607 
    608     /** {@inheritDoc} */
    609     public int getBasicType() {
    610         return basicType;
    611     }
    612 
    613     /** {@inheritDoc} */
    614     public int getBasicFrameType() {
    615         switch (basicType) {
    616             case BT_BOOLEAN:
    617             case BT_BYTE:
    618             case BT_CHAR:
    619             case BT_INT:
    620             case BT_SHORT: {
    621                 return BT_INT;
    622             }
    623         }
    624 
    625         return basicType;
    626     }
    627 
    628     /** {@inheritDoc} */
    629     public boolean isConstant() {
    630         return false;
    631     }
    632 
    633     /**
    634      * Gets the descriptor.
    635      *
    636      * @return {@code non-null;} the descriptor
    637      */
    638     public String getDescriptor() {
    639         return descriptor;
    640     }
    641 
    642     /**
    643      * Gets the name of the class this type corresponds to, in internal
    644      * form. This method is only valid if this instance is for a
    645      * normal reference type (that is, a reference type and
    646      * additionally not a return address).
    647      *
    648      * @return {@code non-null;} the internal-form class name
    649      */
    650     public String getClassName() {
    651         if (className == null) {
    652             if (!isReference()) {
    653                 throw new IllegalArgumentException("not an object type: " +
    654                                                    descriptor);
    655             }
    656 
    657             if (descriptor.charAt(0) == '[') {
    658                 className = descriptor;
    659             } else {
    660                 className = descriptor.substring(1, descriptor.length() - 1);
    661             }
    662         }
    663 
    664         return className;
    665     }
    666 
    667     /**
    668      * Gets the category. Most instances are category 1. {@code long}
    669      * and {@code double} are the only category 2 types.
    670      *
    671      * @see #isCategory1
    672      * @see #isCategory2
    673      * @return the category
    674      */
    675     public int getCategory() {
    676         switch (basicType) {
    677             case BT_LONG:
    678             case BT_DOUBLE: {
    679                 return 2;
    680             }
    681         }
    682 
    683         return 1;
    684     }
    685 
    686     /**
    687      * Returns whether or not this is a category 1 type.
    688      *
    689      * @see #getCategory
    690      * @see #isCategory2
    691      * @return whether or not this is a category 1 type
    692      */
    693     public boolean isCategory1() {
    694         switch (basicType) {
    695             case BT_LONG:
    696             case BT_DOUBLE: {
    697                 return false;
    698             }
    699         }
    700 
    701         return true;
    702     }
    703 
    704     /**
    705      * Returns whether or not this is a category 2 type.
    706      *
    707      * @see #getCategory
    708      * @see #isCategory1
    709      * @return whether or not this is a category 2 type
    710      */
    711     public boolean isCategory2() {
    712         switch (basicType) {
    713             case BT_LONG:
    714             case BT_DOUBLE: {
    715                 return true;
    716             }
    717         }
    718 
    719         return false;
    720     }
    721 
    722     /**
    723      * Gets whether this type is "intlike." An intlike type is one which, when
    724      * placed on a stack or in a local, is automatically converted to an
    725      * {@code int}.
    726      *
    727      * @return whether this type is "intlike"
    728      */
    729     public boolean isIntlike() {
    730         switch (basicType) {
    731             case BT_BOOLEAN:
    732             case BT_BYTE:
    733             case BT_CHAR:
    734             case BT_INT:
    735             case BT_SHORT: {
    736                 return true;
    737             }
    738         }
    739 
    740         return false;
    741     }
    742 
    743     /**
    744      * Gets whether this type is a primitive type. All types are either
    745      * primitive or reference types.
    746      *
    747      * @return whether this type is primitive
    748      */
    749     public boolean isPrimitive() {
    750         switch (basicType) {
    751             case BT_BOOLEAN:
    752             case BT_BYTE:
    753             case BT_CHAR:
    754             case BT_DOUBLE:
    755             case BT_FLOAT:
    756             case BT_INT:
    757             case BT_LONG:
    758             case BT_SHORT:
    759             case BT_VOID: {
    760                 return true;
    761             }
    762         }
    763 
    764         return false;
    765     }
    766 
    767     /**
    768      * Gets whether this type is a normal reference type. A normal
    769      * reference type is a reference type that is not a return
    770      * address. This method is just convenient shorthand for
    771      * {@code getBasicType() == Type.BT_OBJECT}.
    772      *
    773      * @return whether this type is a normal reference type
    774      */
    775     public boolean isReference() {
    776         return (basicType == BT_OBJECT);
    777     }
    778 
    779     /**
    780      * Gets whether this type is an array type. If this method returns
    781      * {@code true}, then it is safe to use {@link #getComponentType}
    782      * to determine the component type.
    783      *
    784      * @return whether this type is an array type
    785      */
    786     public boolean isArray() {
    787         return (descriptor.charAt(0) == '[');
    788     }
    789 
    790     /**
    791      * Gets whether this type is an array type or is a known-null, and
    792      * hence is compatible with array types.
    793      *
    794      * @return whether this type is an array type
    795      */
    796     public boolean isArrayOrKnownNull() {
    797         return isArray() || equals(KNOWN_NULL);
    798     }
    799 
    800     /**
    801      * Gets whether this type represents an uninitialized instance. An
    802      * uninitialized instance is what one gets back from the {@code new}
    803      * opcode, and remains uninitialized until a valid constructor is
    804      * invoked on it.
    805      *
    806      * @return whether this type is "uninitialized"
    807      */
    808     public boolean isUninitialized() {
    809         return (newAt >= 0);
    810     }
    811 
    812     /**
    813      * Gets the bytecode index at which this uninitialized type was
    814      * allocated.  This returns {@code Integer.MAX_VALUE} if this
    815      * type is an uninitialized incoming parameter (i.e., the
    816      * {@code this} of an {@code <init>} method) or
    817      * {@code -1} if this type is in fact <i>initialized</i>.
    818      *
    819      * @return {@code >= -1;} the allocation bytecode index
    820      */
    821     public int getNewAt() {
    822         return newAt;
    823     }
    824 
    825     /**
    826      * Gets the initialized type corresponding to this instance, but only
    827      * if this instance is in fact an uninitialized object type.
    828      *
    829      * @return {@code non-null;} the initialized type
    830      */
    831     public Type getInitializedType() {
    832         if (initializedType == null) {
    833             throw new IllegalArgumentException("initialized type: " +
    834                                                descriptor);
    835         }
    836 
    837         return initializedType;
    838     }
    839 
    840     /**
    841      * Gets the type corresponding to an array of this type.
    842      *
    843      * @return {@code non-null;} the array type
    844      */
    845     public Type getArrayType() {
    846         if (arrayType == null) {
    847             arrayType = putIntern(new Type('[' + descriptor, BT_OBJECT));
    848         }
    849 
    850         return arrayType;
    851     }
    852 
    853     /**
    854      * Gets the component type of this type. This method is only valid on
    855      * array types.
    856      *
    857      * @return {@code non-null;} the component type
    858      */
    859     public Type getComponentType() {
    860         if (componentType == null) {
    861             if (descriptor.charAt(0) != '[') {
    862                 throw new IllegalArgumentException("not an array type: " +
    863                                                    descriptor);
    864             }
    865             componentType = intern(descriptor.substring(1));
    866         }
    867 
    868         return componentType;
    869     }
    870 
    871     /**
    872      * Returns a new interned instance which is identical to this one, except
    873      * it is indicated as uninitialized and allocated at the given bytecode
    874      * index. This instance must be an initialized object type.
    875      *
    876      * @param newAt {@code >= 0;} the allocation bytecode index
    877      * @return {@code non-null;} an appropriately-constructed instance
    878      */
    879     public Type asUninitialized(int newAt) {
    880         if (newAt < 0) {
    881             throw new IllegalArgumentException("newAt < 0");
    882         }
    883 
    884         if (!isReference()) {
    885             throw new IllegalArgumentException("not a reference type: " +
    886                                                descriptor);
    887         }
    888 
    889         if (isUninitialized()) {
    890             /*
    891              * Dealing with uninitialized types as a starting point is
    892              * a pain, and it's not clear that it'd ever be used, so
    893              * just disallow it.
    894              */
    895             throw new IllegalArgumentException("already uninitialized: " +
    896                                                descriptor);
    897         }
    898 
    899         /*
    900          * Create a new descriptor that is unique and shouldn't conflict
    901          * with "normal" type descriptors
    902          */
    903         String newDesc = 'N' + Hex.u2(newAt) + descriptor;
    904         Type result = new Type(newDesc, BT_OBJECT, newAt);
    905         result.initializedType = this;
    906         return putIntern(result);
    907     }
    908 
    909     /**
    910      * Puts the given instance in the intern table if it's not already
    911      * there. If a conflicting value is already in the table, then leave it.
    912      * Return the interned value.
    913      *
    914      * @param type {@code non-null;} instance to make interned
    915      * @return {@code non-null;} the actual interned object
    916      */
    917     private static Type putIntern(Type type) {
    918         synchronized (internTable) {
    919             String descriptor = type.getDescriptor();
    920             Type already = internTable.get(descriptor);
    921             if (already != null) {
    922                 return already;
    923             }
    924             internTable.put(descriptor, type);
    925             return type;
    926         }
    927     }
    928 }