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