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