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 * >= -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 >= -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><init></code> method) or 744 * <code>-1</code> if this type is in fact <i>initialized</i>. 745 * 746 * @return >= -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 >= 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