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