1579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson/*
2579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Copyright (C) 2007 The Android Open Source Project
3579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson *
4579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Licensed under the Apache License, Version 2.0 (the "License");
5579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * you may not use this file except in compliance with the License.
6579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * You may obtain a copy of the License at
7579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson *
8579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson *      http://www.apache.org/licenses/LICENSE-2.0
9579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson *
10579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Unless required by applicable law or agreed to in writing, software
11579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * distributed under the License is distributed on an "AS IS" BASIS,
12579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * See the License for the specific language governing permissions and
14579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * limitations under the License.
15579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */
16579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
17579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonpackage com.android.dx.rop.type;
18579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
19579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport com.android.dx.util.Hex;
20579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
21579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport java.util.HashMap;
22579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
23579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson/**
24579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Representation of a value type, such as may appear in a field, in a
25579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * local, on a stack, or in a method descriptor. Instances of this
26579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * class are generally interned and may be usefully compared with each
27579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * other using {@code ==}.
28579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */
29579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonpublic final class Type implements TypeBearer, Comparable<Type> {
30579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /**
31579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * {@code non-null;} intern table mapping string descriptors to
32579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * instances
33579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     */
34579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    private static final HashMap<String, Type> internTable =
35579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        new HashMap<String, Type>(500);
36579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
37579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /** basic type constant for {@code void} */
38579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public static final int BT_VOID = 0;
39579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
40579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /** basic type constant for {@code boolean} */
41579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public static final int BT_BOOLEAN = 1;
42579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
43579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /** basic type constant for {@code byte} */
44579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public static final int BT_BYTE = 2;
45579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
46579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /** basic type constant for {@code char} */
47579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public static final int BT_CHAR = 3;
48579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
49579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /** basic type constant for {@code double} */
50579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public static final int BT_DOUBLE = 4;
51579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
52579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /** basic type constant for {@code float} */
53579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public static final int BT_FLOAT = 5;
54579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
55579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /** basic type constant for {@code int} */
56579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public static final int BT_INT = 6;
57579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
58579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /** basic type constant for {@code long} */
59579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public static final int BT_LONG = 7;
60579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
61579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /** basic type constant for {@code short} */
62579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public static final int BT_SHORT = 8;
63579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
64579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /** basic type constant for {@code Object} */
65579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public static final int BT_OBJECT = 9;
66579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
67579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /** basic type constant for a return address */
68579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public static final int BT_ADDR = 10;
69579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
70579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /** count of basic type constants */
71579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public static final int BT_COUNT = 11;
72579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
73579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /** {@code non-null;} instance representing {@code boolean} */
74579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public static final Type BOOLEAN = new Type("Z", BT_BOOLEAN);
75579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
76579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /** {@code non-null;} instance representing {@code byte} */
77579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public static final Type BYTE = new Type("B", BT_BYTE);
78579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
79579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /** {@code non-null;} instance representing {@code char} */
80579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public static final Type CHAR = new Type("C", BT_CHAR);
81579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
82579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /** {@code non-null;} instance representing {@code double} */
83579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public static final Type DOUBLE = new Type("D", BT_DOUBLE);
84579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
85579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /** {@code non-null;} instance representing {@code float} */
86579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public static final Type FLOAT = new Type("F", BT_FLOAT);
87579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
88579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /** {@code non-null;} instance representing {@code int} */
89579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public static final Type INT = new Type("I", BT_INT);
90579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
91579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /** {@code non-null;} instance representing {@code long} */
92579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public static final Type LONG = new Type("J", BT_LONG);
93579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
94579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /** {@code non-null;} instance representing {@code short} */
95579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public static final Type SHORT = new Type("S", BT_SHORT);
96579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
97579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /** {@code non-null;} instance representing {@code void} */
98579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public static final Type VOID = new Type("V", BT_VOID);
99579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
100579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /** {@code non-null;} instance representing a known-{@code null} */
101579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public static final Type KNOWN_NULL = new Type("<null>", BT_OBJECT);
102579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
103579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /** {@code non-null;} instance representing a subroutine return address */
104579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public static final Type RETURN_ADDRESS = new Type("<addr>", BT_ADDR);
105579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
106579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    static {
107579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        /*
108579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson         * Put all the primitive types into the intern table. This needs
109579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson         * to happen before the array types below get interned.
110579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson         */
111579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        putIntern(BOOLEAN);
112579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        putIntern(BYTE);
113579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        putIntern(CHAR);
114579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        putIntern(DOUBLE);
115579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        putIntern(FLOAT);
116579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        putIntern(INT);
117579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        putIntern(LONG);
118579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        putIntern(SHORT);
119579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        /*
120579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson         * Note: VOID isn't put in the intern table, since it's special and
121579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson         * shouldn't be found by a normal call to intern().
122579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson         */
123579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
124579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
125579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /**
126579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * {@code non-null;} instance representing
127579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * {@code java.lang.annotation.Annotation}
128579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     */
129579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public static final Type ANNOTATION =
130579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        intern("Ljava/lang/annotation/Annotation;");
131579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
132579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /** {@code non-null;} instance representing {@code java.lang.Class} */
133579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public static final Type CLASS = intern("Ljava/lang/Class;");
134579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
135579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /** {@code non-null;} instance representing {@code java.lang.Cloneable} */
136579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public static final Type CLONEABLE = intern("Ljava/lang/Cloneable;");
137579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
138579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /** {@code non-null;} instance representing {@code java.lang.Object} */
139579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public static final Type OBJECT = intern("Ljava/lang/Object;");
140579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
141579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /** {@code non-null;} instance representing {@code java.io.Serializable} */
142579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public static final Type SERIALIZABLE = intern("Ljava/io/Serializable;");
143579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
144579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /** {@code non-null;} instance representing {@code java.lang.String} */
145579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public static final Type STRING = intern("Ljava/lang/String;");
146579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
147579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /** {@code non-null;} instance representing {@code java.lang.Throwable} */
148579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public static final Type THROWABLE = intern("Ljava/lang/Throwable;");
149579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
150579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /**
151579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * {@code non-null;} instance representing {@code java.lang.Boolean}; the
152579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * suffix on the name helps disambiguate this from the instance
153579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * representing a primitive type
154579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     */
155579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public static final Type BOOLEAN_CLASS = intern("Ljava/lang/Boolean;");
156579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
157579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /**
158579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * {@code non-null;} instance representing {@code java.lang.Byte}; the
159579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * suffix on the name helps disambiguate this from the instance
160579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * representing a primitive type
161579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     */
162579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public static final Type BYTE_CLASS = intern("Ljava/lang/Byte;");
163579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
164579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /**
165579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * {@code non-null;} instance representing {@code java.lang.Character}; the
166579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * suffix on the name helps disambiguate this from the instance
167579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * representing a primitive type
168579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     */
169579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public static final Type CHARACTER_CLASS = intern("Ljava/lang/Character;");
170579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
171579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /**
172579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * {@code non-null;} instance representing {@code java.lang.Double}; the
173579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * suffix on the name helps disambiguate this from the instance
174579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * representing a primitive type
175579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     */
176579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public static final Type DOUBLE_CLASS = intern("Ljava/lang/Double;");
177579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
178579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /**
179579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * {@code non-null;} instance representing {@code java.lang.Float}; the
180579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * suffix on the name helps disambiguate this from the instance
181579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * representing a primitive type
182579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     */
183579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public static final Type FLOAT_CLASS = intern("Ljava/lang/Float;");
184579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
185579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /**
186579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * {@code non-null;} instance representing {@code java.lang.Integer}; the
187579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * suffix on the name helps disambiguate this from the instance
188579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * representing a primitive type
189579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     */
190579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public static final Type INTEGER_CLASS = intern("Ljava/lang/Integer;");
191579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
192579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /**
193579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * {@code non-null;} instance representing {@code java.lang.Long}; the
194579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * suffix on the name helps disambiguate this from the instance
195579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * representing a primitive type
196579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     */
197579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public static final Type LONG_CLASS = intern("Ljava/lang/Long;");
198579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
199579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /**
200579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * {@code non-null;} instance representing {@code java.lang.Short}; the
201579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * suffix on the name helps disambiguate this from the instance
202579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * representing a primitive type
203579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     */
204579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public static final Type SHORT_CLASS = intern("Ljava/lang/Short;");
205579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
206579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /**
207579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * {@code non-null;} instance representing {@code java.lang.Void}; the
208579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * suffix on the name helps disambiguate this from the instance
209579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * representing a primitive type
210579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     */
211579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public static final Type VOID_CLASS = intern("Ljava/lang/Void;");
212579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
213579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /** {@code non-null;} instance representing {@code boolean[]} */
214579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public static final Type BOOLEAN_ARRAY = BOOLEAN.getArrayType();
215579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
216579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /** {@code non-null;} instance representing {@code byte[]} */
217579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public static final Type BYTE_ARRAY = BYTE.getArrayType();
218579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
219579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /** {@code non-null;} instance representing {@code char[]} */
220579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public static final Type CHAR_ARRAY = CHAR.getArrayType();
221579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
222579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /** {@code non-null;} instance representing {@code double[]} */
223579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public static final Type DOUBLE_ARRAY = DOUBLE.getArrayType();
224579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
225579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /** {@code non-null;} instance representing {@code float[]} */
226579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public static final Type FLOAT_ARRAY = FLOAT.getArrayType();
227579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
228579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /** {@code non-null;} instance representing {@code int[]} */
229579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public static final Type INT_ARRAY = INT.getArrayType();
230579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
231579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /** {@code non-null;} instance representing {@code long[]} */
232579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public static final Type LONG_ARRAY = LONG.getArrayType();
233579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
234579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /** {@code non-null;} instance representing {@code Object[]} */
235579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public static final Type OBJECT_ARRAY = OBJECT.getArrayType();
236579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
237579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /** {@code non-null;} instance representing {@code short[]} */
238579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public static final Type SHORT_ARRAY = SHORT.getArrayType();
239579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
240579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /** {@code non-null;} field descriptor for the type */
241579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    private final String descriptor;
242579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
243579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /**
244579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * basic type corresponding to this type; one of the
245579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * {@code BT_*} constants
246579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     */
247579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    private final int basicType;
248579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
249579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /**
250579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * {@code >= -1;} for an uninitialized type, bytecode index that this
251579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * instance was allocated at; {@code Integer.MAX_VALUE} if it
252579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * was an incoming uninitialized instance; {@code -1} if this
253579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * is an <i>inititialized</i> instance
254579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     */
255579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    private final int newAt;
256579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
257579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /**
258579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * {@code null-ok;} the internal-form class name corresponding to
259579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * this type, if calculated; only valid if {@code this} is a
260579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * reference type and additionally not a return address
261579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     */
262579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    private String className;
263579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
264579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /**
265579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * {@code null-ok;} the type corresponding to an array of this type, if
266579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * calculated
267579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     */
268579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    private Type arrayType;
269579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
270579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /**
271579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * {@code null-ok;} the type corresponding to elements of this type, if
272579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * calculated; only valid if {@code this} is an array type
273579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     */
274579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    private Type componentType;
275579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
276579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /**
277579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * {@code null-ok;} the type corresponding to the initialized version of
278579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * this type, if this instance is in fact an uninitialized type
279579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     */
280579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    private Type initializedType;
281579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
282579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /**
283579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * Returns the unique instance corresponding to the type with the
284579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * given descriptor. See vmspec-2 sec4.3.2 for details on the
285579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * field descriptor syntax. This method does <i>not</i> allow
286579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * {@code "V"} (that is, type {@code void}) as a valid
287579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * descriptor.
288579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     *
289579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @param descriptor {@code non-null;} the descriptor
290579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @return {@code non-null;} the corresponding instance
291579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @throws IllegalArgumentException thrown if the descriptor has
292579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * invalid syntax
293579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     */
294579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public static Type intern(String descriptor) {
295579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        Type result;
296579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        synchronized (internTable) {
297579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            result = internTable.get(descriptor);
298579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
299579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        if (result != null) {
300579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            return result;
301579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
302579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
303579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        char firstChar;
304579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        try {
305579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            firstChar = descriptor.charAt(0);
306579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        } catch (IndexOutOfBoundsException ex) {
307579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            // Translate the exception.
308579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            throw new IllegalArgumentException("descriptor is empty");
309579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        } catch (NullPointerException ex) {
310579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            // Elucidate the exception.
311579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            throw new NullPointerException("descriptor == null");
312579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
313579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
314579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        if (firstChar == '[') {
315579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            /*
316579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson             * Recursively strip away array markers to get at the underlying
317579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson             * type, and build back on to form the result.
318579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson             */
319579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            result = intern(descriptor.substring(1));
320579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            return result.getArrayType();
321579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
322579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
323579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        /*
324579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson         * If the first character isn't '[' and it wasn't found in the
325579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson         * intern cache, then it had better be the descriptor for a class.
326579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson         */
327579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
328579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        int length = descriptor.length();
329579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        if ((firstChar != 'L') ||
330579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            (descriptor.charAt(length - 1) != ';')) {
331579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            throw new IllegalArgumentException("bad descriptor: " + descriptor);
332579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
333579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
334579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        /*
335579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson         * Validate the characters of the class name itself. Note that
336579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson         * vmspec-2 does not have a coherent definition for valid
337579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson         * internal-form class names, and the definition here is fairly
338579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson         * liberal: A name is considered valid as long as it doesn't
339579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson         * contain any of '[' ';' '.' '(' ')', and it has no more than one
340579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson         * '/' in a row, and no '/' at either end.
341579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson         */
342579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
343579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        int limit = (length - 1); // Skip the final ';'.
344579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        for (int i = 1; i < limit; i++) {
345579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            char c = descriptor.charAt(i);
346579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            switch (c) {
347579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                case '[':
348579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                case ';':
349579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                case '.':
350579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                case '(':
351579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                case ')': {
352579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                    throw new IllegalArgumentException("bad descriptor: " + descriptor);
353579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                }
354579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                case '/': {
355579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                    if ((i == 1) ||
356579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                        (i == (length - 1)) ||
357579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                        (descriptor.charAt(i - 1) == '/')) {
358579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                        throw new IllegalArgumentException("bad descriptor: " + descriptor);
359579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                    }
360579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                    break;
361579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                }
362579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            }
363579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
364579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
365579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        result = new Type(descriptor, BT_OBJECT);
366579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        return putIntern(result);
367579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
368579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
369579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /**
370579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * Returns the unique instance corresponding to the type with the
371579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * given descriptor, allowing {@code "V"} to return the type
372579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * for {@code void}. Other than that one caveat, this method
373579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * is identical to {@link #intern}.
374579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     *
375579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @param descriptor {@code non-null;} the descriptor
376579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @return {@code non-null;} the corresponding instance
377579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @throws IllegalArgumentException thrown if the descriptor has
378579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * invalid syntax
379579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     */
380579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public static Type internReturnType(String descriptor) {
381579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        try {
382579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            if (descriptor.equals("V")) {
383579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                // This is the one special case where void may be returned.
384579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                return VOID;
385579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            }
386579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        } catch (NullPointerException ex) {
387579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            // Elucidate the exception.
388579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            throw new NullPointerException("descriptor == null");
389579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
390579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
391579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        return intern(descriptor);
392579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
393579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
394579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /**
395579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * Returns the unique instance corresponding to the type of the
396579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * class with the given name. Calling this method is equivalent to
397579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * calling {@code intern(name)} if {@code name} begins
398579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * with {@code "["} and calling {@code intern("L" + name + ";")}
399579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * in all other cases.
400579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     *
401579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @param name {@code non-null;} the name of the class whose type
402579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * is desired
403579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @return {@code non-null;} the corresponding type
404579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @throws IllegalArgumentException thrown if the name has
405579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * invalid syntax
406579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     */
407579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public static Type internClassName(String name) {
408579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        if (name == null) {
409579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            throw new NullPointerException("name == null");
410579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
411579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
412579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        if (name.startsWith("[")) {
413579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            return intern(name);
414579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
415579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
416579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        return intern('L' + name + ';');
417579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
418579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
419579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /**
420579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * Constructs an instance corresponding to an "uninitialized type."
421579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * This is a private constructor; use one of the public static
422579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * methods to get instances.
423579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     *
424579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @param descriptor {@code non-null;} the field descriptor for the type
425579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @param basicType basic type corresponding to this type; one of the
426579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * {@code BT_*} constants
427579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @param newAt {@code >= -1;} allocation bytecode index
428579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     */
429579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    private Type(String descriptor, int basicType, int newAt) {
430579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        if (descriptor == null) {
431579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            throw new NullPointerException("descriptor == null");
432579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
433579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
434579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        if ((basicType < 0) || (basicType >= BT_COUNT)) {
435579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            throw new IllegalArgumentException("bad basicType");
436579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
437579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
438579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        if (newAt < -1) {
439579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            throw new IllegalArgumentException("newAt < -1");
440579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
441579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
442579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        this.descriptor = descriptor;
443579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        this.basicType = basicType;
444579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        this.newAt = newAt;
445579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        this.arrayType = null;
446579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        this.componentType = null;
447579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        this.initializedType = null;
448579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
449579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
450579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /**
451579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * Constructs an instance corresponding to an "initialized type."
452579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * This is a private constructor; use one of the public static
453579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * methods to get instances.
454579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     *
455579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @param descriptor {@code non-null;} the field descriptor for the type
456579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @param basicType basic type corresponding to this type; one of the
457579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * {@code BT_*} constants
458579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     */
459579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    private Type(String descriptor, int basicType) {
460579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        this(descriptor, basicType, -1);
461579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
462579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
463579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /** {@inheritDoc} */
464579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    @Override
465579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public boolean equals(Object other) {
466579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        if (this == other) {
467579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            /*
468579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson             * Since externally-visible types are interned, this check
469579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson             * helps weed out some easy cases.
470579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson             */
471579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            return true;
472579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
473579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
474579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        if (!(other instanceof Type)) {
475579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            return false;
476579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
477579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
478579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        return descriptor.equals(((Type) other).descriptor);
479579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
480579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
481579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /** {@inheritDoc} */
482579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    @Override
483579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public int hashCode() {
484579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        return descriptor.hashCode();
485579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
486579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
487579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /** {@inheritDoc} */
488579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public int compareTo(Type other) {
489579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        return descriptor.compareTo(other.descriptor);
490579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
491579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
492579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /** {@inheritDoc} */
493579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    @Override
494579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public String toString() {
495579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        return descriptor;
496579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
497579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
498579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /** {@inheritDoc} */
499579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public String toHuman() {
500579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        switch (basicType) {
501579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            case BT_VOID:    return "void";
502579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            case BT_BOOLEAN: return "boolean";
503579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            case BT_BYTE:    return "byte";
504579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            case BT_CHAR:    return "char";
505579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            case BT_DOUBLE:  return "double";
506579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            case BT_FLOAT:   return "float";
507579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            case BT_INT:     return "int";
508579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            case BT_LONG:    return "long";
509579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            case BT_SHORT:   return "short";
510579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            case BT_OBJECT:  break;
511579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            default:         return descriptor;
512579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
513579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
514579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        if (isArray()) {
515579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            return getComponentType().toHuman() + "[]";
516579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
517579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
518579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        // Remove the "L...;" around the type and convert "/" to ".".
519579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        return getClassName().replace("/", ".");
520579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
521579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
522579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /** {@inheritDoc} */
523579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public Type getType() {
524579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        return this;
525579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
526579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
527579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /** {@inheritDoc} */
528579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public Type getFrameType() {
529579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        switch (basicType) {
530579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            case BT_BOOLEAN:
531579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            case BT_BYTE:
532579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            case BT_CHAR:
533579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            case BT_INT:
534579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            case BT_SHORT: {
535579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                return INT;
536579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            }
537579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
538579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
539579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        return this;
540579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
541579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
542579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /** {@inheritDoc} */
543579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public int getBasicType() {
544579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        return basicType;
545579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
546579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
547579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /** {@inheritDoc} */
548579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public int getBasicFrameType() {
549579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        switch (basicType) {
550579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            case BT_BOOLEAN:
551579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            case BT_BYTE:
552579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            case BT_CHAR:
553579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            case BT_INT:
554579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            case BT_SHORT: {
555579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                return BT_INT;
556579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            }
557579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
558579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
559579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        return basicType;
560579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
561579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
562579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /** {@inheritDoc} */
563579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public boolean isConstant() {
564579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        return false;
565579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
566579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
567579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /**
568579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * Gets the descriptor.
569579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     *
570579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @return {@code non-null;} the descriptor
571579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     */
572579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public String getDescriptor() {
573579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        return descriptor;
574579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
575579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
576579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /**
577579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * Gets the name of the class this type corresponds to, in internal
578579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * form. This method is only valid if this instance is for a
579579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * normal reference type (that is, a reference type and
580579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * additionally not a return address).
581579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     *
582579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @return {@code non-null;} the internal-form class name
583579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     */
584579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public String getClassName() {
585579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        if (className == null) {
586579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            if (!isReference()) {
587579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                throw new IllegalArgumentException("not an object type: " +
588579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                                                   descriptor);
589579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            }
590579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
591579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            if (descriptor.charAt(0) == '[') {
592579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                className = descriptor;
593579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            } else {
594579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                className = descriptor.substring(1, descriptor.length() - 1);
595579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            }
596579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
597579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
598579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        return className;
599579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
600579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
601579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /**
602579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * Gets the category. Most instances are category 1. {@code long}
603579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * and {@code double} are the only category 2 types.
604579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     *
605579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @see #isCategory1
606579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @see #isCategory2
607579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @return the category
608579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     */
609579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public int getCategory() {
610579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        switch (basicType) {
611579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            case BT_LONG:
612579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            case BT_DOUBLE: {
613579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                return 2;
614579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            }
615579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
616579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
617579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        return 1;
618579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
619579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
620579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /**
621579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * Returns whether or not this is a category 1 type.
622579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     *
623579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @see #getCategory
624579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @see #isCategory2
625579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @return whether or not this is a category 1 type
626579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     */
627579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public boolean isCategory1() {
628579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        switch (basicType) {
629579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            case BT_LONG:
630579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            case BT_DOUBLE: {
631579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                return false;
632579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            }
633579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
634579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
635579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        return true;
636579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
637579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
638579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /**
639579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * Returns whether or not this is a category 2 type.
640579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     *
641579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @see #getCategory
642579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @see #isCategory1
643579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @return whether or not this is a category 2 type
644579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     */
645579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public boolean isCategory2() {
646579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        switch (basicType) {
647579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            case BT_LONG:
648579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            case BT_DOUBLE: {
649579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                return true;
650579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            }
651579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
652579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
653579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        return false;
654579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
655579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
656579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /**
657579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * Gets whether this type is "intlike." An intlike type is one which, when
658579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * placed on a stack or in a local, is automatically converted to an
659579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * {@code int}.
660579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     *
661579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @return whether this type is "intlike"
662579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     */
663579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public boolean isIntlike() {
664579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        switch (basicType) {
665579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            case BT_BOOLEAN:
666579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            case BT_BYTE:
667579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            case BT_CHAR:
668579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            case BT_INT:
669579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            case BT_SHORT: {
670579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                return true;
671579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            }
672579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
673579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
674579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        return false;
675579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
676579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
677579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /**
678579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * Gets whether this type is a primitive type. All types are either
679579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * primitive or reference types.
680579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     *
681579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @return whether this type is primitive
682579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     */
683579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public boolean isPrimitive() {
684579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        switch (basicType) {
685579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            case BT_BOOLEAN:
686579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            case BT_BYTE:
687579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            case BT_CHAR:
688579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            case BT_DOUBLE:
689579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            case BT_FLOAT:
690579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            case BT_INT:
691579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            case BT_LONG:
692579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            case BT_SHORT:
693579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            case BT_VOID: {
694579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                return true;
695579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            }
696579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
697579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
698579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        return false;
699579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
700579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
701579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /**
702579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * Gets whether this type is a normal reference type. A normal
703579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * reference type is a reference type that is not a return
704579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * address. This method is just convenient shorthand for
705579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * {@code getBasicType() == Type.BT_OBJECT}.
706579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     *
707579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @return whether this type is a normal reference type
708579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     */
709579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public boolean isReference() {
710579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        return (basicType == BT_OBJECT);
711579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
712579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
713579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /**
714579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * Gets whether this type is an array type. If this method returns
715579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * {@code true}, then it is safe to use {@link #getComponentType}
716579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * to determine the component type.
717579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     *
718579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @return whether this type is an array type
719579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     */
720579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public boolean isArray() {
721579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        return (descriptor.charAt(0) == '[');
722579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
723579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
724579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /**
725579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * Gets whether this type is an array type or is a known-null, and
726579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * hence is compatible with array types.
727579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     *
728579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @return whether this type is an array type
729579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     */
730579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public boolean isArrayOrKnownNull() {
731579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        return isArray() || equals(KNOWN_NULL);
732579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
733579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
734579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /**
735579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * Gets whether this type represents an uninitialized instance. An
736579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * uninitialized instance is what one gets back from the {@code new}
737579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * opcode, and remains uninitialized until a valid constructor is
738579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * invoked on it.
739579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     *
740579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @return whether this type is "uninitialized"
741579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     */
742579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public boolean isUninitialized() {
743579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        return (newAt >= 0);
744579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
745579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
746579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /**
747579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * Gets the bytecode index at which this uninitialized type was
748579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * allocated.  This returns {@code Integer.MAX_VALUE} if this
749579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * type is an uninitialized incoming parameter (i.e., the
750579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * {@code this} of an {@code <init>} method) or
751579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * {@code -1} if this type is in fact <i>initialized</i>.
752579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     *
753579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @return {@code >= -1;} the allocation bytecode index
754579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     */
755579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public int getNewAt() {
756579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        return newAt;
757579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
758579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
759579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /**
760579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * Gets the initialized type corresponding to this instance, but only
761579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * if this instance is in fact an uninitialized object type.
762579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     *
763579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @return {@code non-null;} the initialized type
764579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     */
765579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public Type getInitializedType() {
766579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        if (initializedType == null) {
767579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            throw new IllegalArgumentException("initialized type: " +
768579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                                               descriptor);
769579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
770579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
771579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        return initializedType;
772579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
773579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
774579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /**
775579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * Gets the type corresponding to an array of this type.
776579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     *
777579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @return {@code non-null;} the array type
778579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     */
779579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public Type getArrayType() {
780579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        if (arrayType == null) {
781579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            arrayType = putIntern(new Type('[' + descriptor, BT_OBJECT));
782579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
783579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
784579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        return arrayType;
785579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
786579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
787579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /**
788579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * Gets the component type of this type. This method is only valid on
789579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * array types.
790579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     *
791579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @return {@code non-null;} the component type
792579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     */
793579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public Type getComponentType() {
794579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        if (componentType == null) {
795579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            if (descriptor.charAt(0) != '[') {
796579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                throw new IllegalArgumentException("not an array type: " +
797579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                                                   descriptor);
798579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            }
799579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            componentType = intern(descriptor.substring(1));
800579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
801579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
802579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        return componentType;
803579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
804579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
805579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /**
806579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * Returns a new interned instance which is identical to this one, except
807579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * it is indicated as uninitialized and allocated at the given bytecode
808579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * index. This instance must be an initialized object type.
809579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     *
810579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @param newAt {@code >= 0;} the allocation bytecode index
811579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @return {@code non-null;} an appropriately-constructed instance
812579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     */
813579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public Type asUninitialized(int newAt) {
814579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        if (newAt < 0) {
815579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            throw new IllegalArgumentException("newAt < 0");
816579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
817579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
818579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        if (!isReference()) {
819579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            throw new IllegalArgumentException("not a reference type: " +
820579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                                               descriptor);
821579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
822579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
823579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        if (isUninitialized()) {
824579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            /*
825579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson             * Dealing with uninitialized types as a starting point is
826579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson             * a pain, and it's not clear that it'd ever be used, so
827579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson             * just disallow it.
828579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson             */
829579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            throw new IllegalArgumentException("already uninitialized: " +
830579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                                               descriptor);
831579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
832579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
833579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        /*
834579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson         * Create a new descriptor that is unique and shouldn't conflict
835579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson         * with "normal" type descriptors
836579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson         */
837579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        String newDesc = 'N' + Hex.u2(newAt) + descriptor;
838579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        Type result = new Type(newDesc, BT_OBJECT, newAt);
839579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        result.initializedType = this;
840579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        return putIntern(result);
841579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
842579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
843579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /**
844579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * Puts the given instance in the intern table if it's not already
845579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * there. If a conflicting value is already in the table, then leave it.
846579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * Return the interned value.
847579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     *
848579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @param type {@code non-null;} instance to make interned
849579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @return {@code non-null;} the actual interned object
850579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     */
851579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    private static Type putIntern(Type type) {
852579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        synchronized (internTable) {
853579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            String descriptor = type.getDescriptor();
854579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            Type already = internTable.get(descriptor);
855579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            if (already != null) {
856579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                return already;
857579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            }
858579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            internTable.put(descriptor, type);
859579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            return type;
860579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
861579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
862579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson}
863