001 /* 002 * This file is part of the Jikes RVM project (http://jikesrvm.org). 003 * 004 * This file is licensed to You under the Eclipse Public License (EPL); 005 * You may not use this file except in compliance with the License. You 006 * may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/eclipse-1.0.php 009 * 010 * See the COPYRIGHT.txt file distributed with this work for information 011 * regarding copyright ownership. 012 */ 013 package org.jikesrvm.classloader; 014 015 import org.jikesrvm.VM; 016 import static org.jikesrvm.SizeConstants.BYTES_IN_ADDRESS; 017 018 import org.jikesrvm.runtime.ReflectionBase; 019 import org.jikesrvm.util.ImmutableEntryHashSetRVM; 020 021 // TODO: The following is due to a bug in checkstyle 4.3 022 // CHECKSTYLE:OFF 023 import org.vmmagic.pragma.Uninterruptible; 024 // CHECKSTYLE:ON 025 026 /** 027 * A class to represent the reference in a class file to some 028 * type (class, primitive or array). 029 * A type reference is uniquely defined by 030 * <ul> 031 * <li> an initiating class loader 032 * <li> a type name 033 * </ul> 034 * Resolving a TypeReference to a RVMType can 035 * be an expensive operation. Therefore we canonicalize 036 * TypeReference instances and cache the result of resolution. 037 */ 038 public final class TypeReference { 039 /** 040 * The initiating class loader 041 */ 042 final ClassLoader classloader; 043 044 /** 045 * The type name. For example, the primitive type int is "I", the 046 * class java.lang.String is "Ljava/lang/String;" 047 */ 048 final Atom name; 049 050 /** 051 * The id of this type reference. 052 */ 053 final int id; 054 055 /** 056 * The RVMType instance that this type reference resolves to. 057 * Null if the reference has not yet been resolved. 058 */ 059 private RVMType type; 060 061 /** 062 * Used to canonicalize TypeReferences 063 */ 064 private static final ImmutableEntryHashSetRVM<TypeReference> dictionary = 065 new ImmutableEntryHashSetRVM<TypeReference>(); 066 067 private static final ImmutableEntryHashSetRVM<ClassLoader> clDict = new ImmutableEntryHashSetRVM<ClassLoader>(); 068 /** 069 * 2^LOG_ROW_SIZE is the number of elements per row 070 */ 071 private static final int LOG_ROW_SIZE = 10; 072 /** 073 * Mask to ascertain row from id number 074 */ 075 private static final int ROW_MASK = (1 << LOG_ROW_SIZE)-1; 076 /** 077 * Dictionary of all TypeReference instances. 078 */ 079 private static TypeReference[][] types = new TypeReference[3][1<<LOG_ROW_SIZE]; 080 081 /** 082 * Used to assign Ids. Id 0 is not used. Ids are compressed and 083 * stored in the constant pool (See {@link RVMClass}). 084 */ 085 private static int nextId = 1; 086 087 public static final TypeReference Void = findOrCreate("V"); 088 public static final TypeReference Boolean = findOrCreate("Z"); 089 public static final TypeReference Byte = findOrCreate("B"); 090 public static final TypeReference Char = findOrCreate("C"); 091 public static final TypeReference Short = findOrCreate("S"); 092 public static final TypeReference Int = findOrCreate("I"); 093 public static final TypeReference Long = findOrCreate("J"); 094 public static final TypeReference Float = findOrCreate("F"); 095 public static final TypeReference Double = findOrCreate("D"); 096 097 public static final TypeReference BooleanArray = findOrCreate("[Z"); 098 public static final TypeReference ByteArray = findOrCreate("[B"); 099 public static final TypeReference CharArray = findOrCreate("[C"); 100 public static final TypeReference ShortArray = findOrCreate("[S"); 101 public static final TypeReference IntArray = findOrCreate("[I"); 102 public static final TypeReference LongArray = findOrCreate("[J"); 103 public static final TypeReference FloatArray = findOrCreate("[F"); 104 public static final TypeReference DoubleArray = findOrCreate("[D"); 105 106 public static final TypeReference Word = findOrCreate(org.vmmagic.unboxed.Word.class); 107 public static final TypeReference Address = findOrCreate(org.vmmagic.unboxed.Address.class); 108 public static final TypeReference ObjectReference = findOrCreate(org.vmmagic.unboxed.ObjectReference.class); 109 public static final TypeReference Offset = findOrCreate(org.vmmagic.unboxed.Offset.class); 110 public static final TypeReference Extent = findOrCreate(org.vmmagic.unboxed.Extent.class); 111 public static final TypeReference Code = 112 findOrCreate(VM.BuildForIA32 ? "Lorg/jikesrvm/ia32/Code;" : "Lorg/jikesrvm/ppc/Code;"); 113 public static final TypeReference WordArray = findOrCreate(org.vmmagic.unboxed.WordArray.class); 114 public static final TypeReference AddressArray = findOrCreate(org.vmmagic.unboxed.AddressArray.class); 115 public static final TypeReference ObjectReferenceArray = 116 findOrCreate(org.vmmagic.unboxed.ObjectReferenceArray.class); 117 public static final TypeReference OffsetArray = findOrCreate(org.vmmagic.unboxed.OffsetArray.class); 118 public static final TypeReference ExtentArray = findOrCreate(org.vmmagic.unboxed.ExtentArray.class); 119 public static final TypeReference CodeArray = findOrCreate(org.jikesrvm.ArchitectureSpecific.CodeArray.class); 120 public static final TypeReference Magic = findOrCreate(org.jikesrvm.runtime.Magic.class); 121 public static final TypeReference SysCall = findOrCreate(org.vmmagic.pragma.SysCallNative.class); 122 public static final TypeReference TIB = findOrCreate(org.jikesrvm.objectmodel.TIB.class); 123 public static final TypeReference ITableArray = findOrCreate(org.jikesrvm.objectmodel.ITableArray.class); 124 public static final TypeReference ITable = findOrCreate(org.jikesrvm.objectmodel.ITable.class); 125 public static final TypeReference IMT = findOrCreate(org.jikesrvm.objectmodel.IMT.class); 126 public static final TypeReference Thread = findOrCreate(org.jikesrvm.scheduler.RVMThread.class); 127 public static final TypeReference FunctionTable = findOrCreate(org.jikesrvm.jni.FunctionTable.class); 128 public static final TypeReference LinkageTripletTable = findOrCreate(org.jikesrvm.jni.LinkageTripletTable.class); 129 130 public static final TypeReference JavaLangObject = findOrCreate(java.lang.Object.class); 131 public static final TypeReference JavaLangClass = findOrCreate(java.lang.Class.class); 132 public static final TypeReference JavaLangString = findOrCreate(java.lang.String.class); 133 public static final TypeReference JavaLangCloneable = findOrCreate(java.lang.Cloneable.class); 134 public static final TypeReference JavaIoSerializable = findOrCreate(java.io.Serializable.class); 135 public static final TypeReference JavaLangRefReference = findOrCreate(java.lang.ref.Reference.class); 136 public static final TypeReference JavaLangSystem = findOrCreate(java.lang.System.class); 137 138 public static final TypeReference JavaLangObjectArray = findOrCreate(java.lang.Object[].class); 139 140 public static final TypeReference JavaLangThrowable = findOrCreate(java.lang.Throwable.class); 141 public static final TypeReference JavaLangError = findOrCreate(java.lang.Error.class); 142 public static final TypeReference JavaLangNullPointerException = 143 findOrCreate(java.lang.NullPointerException.class); 144 public static final TypeReference JavaLangArrayIndexOutOfBoundsException = 145 findOrCreate(java.lang.ArrayIndexOutOfBoundsException.class); 146 public static final TypeReference JavaLangArithmeticException = findOrCreate(java.lang.ArithmeticException.class); 147 public static final TypeReference JavaLangArrayStoreException = findOrCreate(java.lang.ArrayStoreException.class); 148 public static final TypeReference JavaLangClassCastException = findOrCreate(java.lang.ClassCastException.class); 149 public static final TypeReference JavaLangNegativeArraySizeException = 150 findOrCreate(java.lang.NegativeArraySizeException.class); 151 public static final TypeReference JavaLangIllegalMonitorStateException = 152 findOrCreate(java.lang.IllegalMonitorStateException.class); 153 154 public static final TypeReference Type = findOrCreate(org.jikesrvm.classloader.RVMType.class); 155 public static final TypeReference Class = findOrCreate(org.jikesrvm.classloader.RVMClass.class); 156 157 public static final TypeReference NativeBridge = findOrCreate(org.vmmagic.pragma.NativeBridge.class); 158 public static final TypeReference DynamicBridge = findOrCreate(org.vmmagic.pragma.DynamicBridge.class); 159 public static final TypeReference SaveVolatile = findOrCreate(org.vmmagic.pragma.SaveVolatile.class); 160 public static final TypeReference Interruptible = findOrCreate(org.vmmagic.pragma.Interruptible.class); 161 public static final TypeReference LogicallyUninterruptible = 162 findOrCreate(org.vmmagic.pragma.LogicallyUninterruptible.class); 163 public static final TypeReference Preemptible = findOrCreate(org.vmmagic.pragma.Preemptible.class); 164 public static final TypeReference UninterruptibleNoWarn = 165 findOrCreate(org.vmmagic.pragma.UninterruptibleNoWarn.class); 166 public static final TypeReference UnpreemptibleNoWarn = 167 findOrCreate(org.vmmagic.pragma.UnpreemptibleNoWarn.class); 168 public static final TypeReference Uninterruptible = findOrCreate(org.vmmagic.pragma.Uninterruptible.class); 169 public static final TypeReference NoCheckStore = findOrCreate(org.vmmagic.pragma.NoCheckStore.class); 170 public static final TypeReference Unpreemptible = findOrCreate(org.vmmagic.pragma.Unpreemptible.class); 171 public static final TypeReference SpecializedMethodInvoke = findOrCreate(org.vmmagic.pragma.SpecializedMethodInvoke.class); 172 public static final TypeReference Untraced = findOrCreate(org.vmmagic.pragma.Untraced.class); 173 public static final TypeReference NonMoving = findOrCreate(org.vmmagic.pragma.NonMoving.class); 174 public static final TypeReference NonMovingAllocation = findOrCreate(org.vmmagic.pragma.NonMovingAllocation.class); 175 public static final TypeReference BaselineNoRegisters = findOrCreate(org.vmmagic.pragma.BaselineNoRegisters.class); 176 public static final TypeReference BaselineSaveLSRegisters = findOrCreate(org.vmmagic.pragma.BaselineSaveLSRegisters.class); 177 public static final TypeReference ReferenceFieldsVary = findOrCreate(org.vmmagic.pragma.ReferenceFieldsVary.class); 178 179 180 public static final TypeReference ReferenceMaps = 181 findOrCreate(org.jikesrvm.compilers.baseline.ReferenceMaps.class); 182 public static final TypeReference JNIFunctions = findOrCreate(org.jikesrvm.jni.JNIFunctions.class); 183 184 public static final TypeReference RVMArray = findOrCreate(org.jikesrvm.classloader.RVMArray.class); 185 /** Abstract base of reflective method invoker classes */ 186 static final TypeReference baseReflectionClass = TypeReference.findOrCreate(ReflectionBase.class); 187 188 // Synthetic types used by the opt compiler 189 public static final TypeReference NULL_TYPE = 190 (VM.BuildForOptCompiler) ? findOrCreate("Lorg/jikesrvm/classloader/TypeReference$NULL;") : null; 191 public static final TypeReference VALIDATION_TYPE = 192 (VM.BuildForOptCompiler) ? findOrCreate("Lorg/jikesrvm/classloader/TypeReference$VALIDATION;") : null; 193 194 public static final TypeReference ExceptionTable = 195 (VM.BuildForOptCompiler) ? findOrCreate(org.jikesrvm.compilers.common.ExceptionTable.class) : null; 196 197 public static final TypeReference OptimizationPlanner = 198 (VM.BuildForAdaptiveSystem) ? findOrCreate(org.jikesrvm.compilers.opt.driver.OptimizationPlanner.class) : null; 199 200 /** 201 * Hash value based on name, used for canonical type dictionary 202 */ 203 @Override 204 public int hashCode() { 205 return name.hashCode(); 206 } 207 208 /** 209 * Are two keys equivalent? Used for canonical type dictionary. 210 * NB ignores id value 211 */ 212 @Override 213 public boolean equals(Object other) { 214 if (other instanceof TypeReference) { 215 TypeReference that = (TypeReference) other; 216 return name == that.name && classloader.equals(that.classloader); 217 } else { 218 return false; 219 } 220 } 221 222 /** 223 * Find or create the canonical TypeReference instance for 224 * the given pair. 225 * 226 * @param cl the classloader (defining/initiating depending on usage) 227 * @param tn the name of the type 228 * 229 * @throws IllegalArgumentException Needs to throw some kind of error in 230 * the case of a Atom that does not represent a type name. 231 */ 232 public static synchronized TypeReference findOrCreate(ClassLoader cl, Atom tn) throws IllegalArgumentException { 233 TypeDescriptorParsing.validateAsTypeDescriptor(tn); 234 // Primitives, arrays of primitives, system classes and arrays of system 235 // classes must use the bootstrap classloader. Force that here so we don't 236 // have to worry about it anywhere else in the VM. 237 ClassLoader bootstrapCL = BootstrapClassLoader.getBootstrapClassLoader(); 238 if (cl == null) { 239 cl = bootstrapCL; 240 } else if (cl != bootstrapCL) { 241 if (tn.isClassDescriptor()) { 242 if (tn.isBootstrapClassDescriptor()) { 243 cl = bootstrapCL; 244 } 245 } else if (tn.isArrayDescriptor()) { 246 Atom innermostElementType = tn.parseForInnermostArrayElementDescriptor(); 247 if (innermostElementType.isClassDescriptor()) { 248 if (innermostElementType.isBootstrapClassDescriptor()) { 249 cl = bootstrapCL; 250 } 251 } else { 252 cl = bootstrapCL; 253 } 254 } else { 255 cl = bootstrapCL; 256 } 257 } 258 return findOrCreateInternal(cl, tn); 259 } 260 261 /** 262 * Shorthand for doing a find or create for a type reference that should 263 * be created using the bootstrap classloader. 264 * @param tn type name 265 */ 266 public static TypeReference findOrCreate(String tn) { 267 return findOrCreate(BootstrapClassLoader.getBootstrapClassLoader(), Atom.findOrCreateAsciiAtom(tn)); 268 } 269 270 /** 271 * Convert a java.lang.Class into a type reference the slow way. For 272 * use in boot image writing 273 * @param klass java.lang.Class to convert to type reference 274 */ 275 public static TypeReference findOrCreate(Class<?> klass) { 276 if (VM.runningVM) { 277 return java.lang.JikesRVMSupport.getTypeForClass(klass).getTypeRef(); 278 } else { 279 String className = klass.getName(); 280 if (className.startsWith("[")) { 281 // an array 282 Atom classAtom = Atom.findOrCreateAsciiAtom(className.replace('.', '/')); 283 return findOrCreate(BootstrapClassLoader.getBootstrapClassLoader(), classAtom); 284 } else { 285 // a class 286 Atom classAtom; 287 if (className.equals("int")) { 288 return TypeReference.Int; 289 } else if (className.equals("boolean")) { 290 return TypeReference.Boolean; 291 } else if (className.equals("byte")) { 292 return TypeReference.Byte; 293 } else if (className.equals("char")) { 294 return TypeReference.Char; 295 } else if (className.equals("double")) { 296 return TypeReference.Double; 297 } else if (className.equals("float")) { 298 return TypeReference.Float; 299 } else if (className.equals("long")) { 300 return TypeReference.Long; 301 } else if (className.equals("short")) { 302 return TypeReference.Short; 303 } else if (className.equals("void")) { 304 return TypeReference.Void; 305 } else { 306 classAtom = Atom.findOrCreateAsciiAtom(className.replace('.', '/')); 307 } 308 Atom classDescriptor = classAtom.descriptorFromClassName(); 309 return findOrCreate(BootstrapClassLoader.getBootstrapClassLoader(), classDescriptor); 310 } 311 } 312 } 313 314 /** 315 * Find or create the canonical TypeReference instance for 316 * the given pair without type descriptor parsing. 317 * 318 * @param cl the classloader (defining/initiating depending on usage) 319 * @param tn the name of the type 320 */ 321 public static synchronized TypeReference findOrCreateInternal(ClassLoader cl, Atom tn) { 322 // Next actually findOrCreate the type reference using the proper classloader. 323 TypeReference key = new TypeReference(cl, tn, nextId); 324 TypeReference val = dictionary.get(key); 325 if (val == null) { 326 // Create type reference 327 val = key; 328 nextId++; // id of val is the nextId, move it along 329 int column = val.id >> LOG_ROW_SIZE; 330 if (column == types.length) { 331 // Grow the array of types if necessary 332 TypeReference[][] tmp = new TypeReference[column+1][]; 333 for (int i=0; i < column; i++) { 334 tmp[i] = types[i]; 335 } 336 types = tmp; 337 types[column] = new TypeReference[1 << LOG_ROW_SIZE]; 338 } 339 types[column][val.id & ROW_MASK] = val; 340 dictionary.add(val); 341 } 342 return val; 343 } 344 private static void canonicalizeCL(ClassLoader cl) { 345 clDict.add(cl); 346 } 347 public static ImmutableEntryHashSetRVM<ClassLoader> getCLDict() { return clDict; } 348 349 /** 350 * Constructor 351 * @param cl the classloader 352 * @param tn the type name 353 * @param id the numeric identifier 354 */ 355 private TypeReference(ClassLoader cl, Atom tn, int id) { 356 canonicalizeCL(cl); 357 classloader = cl; 358 name = tn; 359 this.id = id; 360 } 361 362 /** 363 * Get the canonical type reference given its id. The unused id of 0 will return null. 364 * @param id the type references id 365 * @return the type reference 366 */ 367 @Uninterruptible 368 public static TypeReference getTypeRef(int id) { 369 return types[id >> LOG_ROW_SIZE][id & ROW_MASK]; 370 } 371 372 /** 373 * @return the classloader component of this type reference 374 */ 375 @Uninterruptible 376 public ClassLoader getClassLoader() { 377 return classloader; 378 } 379 380 /** 381 * @return the type name component of this type reference 382 */ 383 @Uninterruptible 384 public Atom getName() { 385 return name; 386 } 387 388 /** 389 * Get the element type of for this array type 390 */ 391 public TypeReference getArrayElementType() { 392 if (VM.VerifyAssertions) VM._assert(isArrayType()); 393 394 if (isUnboxedArrayType()) { 395 if (this == AddressArray) { 396 return Address; 397 } else if (this == ObjectReferenceArray) { 398 return ObjectReference; 399 } else if (this == WordArray) { 400 return Word; 401 } else if (this == OffsetArray) { 402 return Offset; 403 } else if (this == ExtentArray) { 404 return Extent; 405 } else if (this == CodeArray) { 406 return Code; 407 } else { 408 if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED, "Unexpected case of Magic arrays!"); 409 return null; 410 } 411 } else { 412 return findOrCreate(classloader, name.parseForArrayElementDescriptor()); 413 } 414 } 415 416 /** 417 * Get array type corresponding to "this" array element type. 418 */ 419 public TypeReference getArrayTypeForElementType() { 420 Atom arrayDescriptor = name.arrayDescriptorFromElementDescriptor(); 421 return findOrCreate(classloader, arrayDescriptor); 422 } 423 424 /** 425 * Return the dimensionality of the type. 426 * By convention, class types have dimensionality 0, 427 * primitives -1, and arrays the number of [ in their descriptor. 428 */ 429 public int getDimensionality() { 430 if (isArrayType()) { 431 TypeReference elem = getArrayElementType(); 432 if (elem.isArrayType()) { 433 // NOTE: we must recur instead of attempting to parse 434 // the array descriptor for ['s so we correctly handle 435 // [AddressArray etc. which actually has dimensionality 2! 436 return 1 + elem.getDimensionality(); 437 } else { 438 return 1; 439 } 440 } else if (isUnboxedType()) { 441 return -1; 442 } else if (isClassType()) { 443 return 0; 444 } else { 445 return -1; 446 } 447 } 448 449 /** 450 * Return the innermost element type reference for an array 451 */ 452 public TypeReference getInnermostElementType() { 453 TypeReference elem = getArrayElementType(); 454 if (elem.isArrayType()) { 455 // NOTE: we must recur instead of attempting to parse 456 // the array descriptor for ['s so we correctly handle 457 // [AddressArray and similar evil VMMagic 458 return elem.getInnermostElementType(); 459 } else { 460 return elem; 461 } 462 } 463 464 /** 465 * Does 'this' refer to a class? 466 */ 467 @Uninterruptible 468 public boolean isClassType() { 469 return name.isClassDescriptor() && !(isUnboxedArrayType() || isUnboxedType()); 470 } 471 472 /** 473 * Does 'this' refer to an array? 474 */ 475 @Uninterruptible 476 public boolean isArrayType() { 477 return name.isArrayDescriptor() || isUnboxedArrayType(); 478 } 479 480 /** 481 * Does 'this' refer to a primitive type 482 */ 483 @Uninterruptible 484 public boolean isPrimitiveType() { 485 return !(isArrayType() || isClassType()); 486 } 487 488 /** 489 * Does 'this' refer to a reference type 490 */ 491 @Uninterruptible 492 public boolean isReferenceType() { 493 return !isPrimitiveType(); 494 } 495 496 /** 497 * Does 'this' refer to Word, Address, Offset or Extent 498 */ 499 @Uninterruptible 500 public boolean isWordLikeType() { 501 return this == Word || this == Offset || this == Address || this == Extent; 502 } 503 504 /** 505 * Does 'this' refer to Word 506 */ 507 @Uninterruptible 508 public boolean isWordType() { 509 return this == Word; 510 } 511 512 /** 513 * Does 'this' refer to Address 514 */ 515 @Uninterruptible 516 public boolean isAddressType() { 517 return this == Address; 518 } 519 520 /** 521 * Does 'this' refer to Offset 522 */ 523 @Uninterruptible 524 public boolean isOffsetType() { 525 return this == Offset; 526 } 527 528 /** 529 * Does 'this' refer to Extent 530 */ 531 @Uninterruptible 532 public boolean isExtentType() { 533 return this == Extent; 534 } 535 536 /** 537 * Does 'this' refer to an unboxed type. 538 */ 539 @Uninterruptible 540 public boolean isUnboxedType() { 541 return isWordLikeType() || isCodeType(); 542 } 543 544 /** 545 * Does 'this' refer to Code 546 */ 547 @Uninterruptible 548 public boolean isCodeType() { 549 return this == Code; 550 } 551 552 /** 553 * Does 'this' refer to WordArray, AddressArray, OffsetArray or ExtentArray 554 */ 555 @Uninterruptible 556 public boolean isWordArrayType() { 557 return this == WordArray || 558 this == OffsetArray || 559 this == AddressArray || 560 this == ExtentArray; 561 } 562 563 /** 564 * Does 'this' refer to WordArray, AddressArray, OffsetArray or ExtentArray 565 */ 566 @Uninterruptible 567 public boolean isUnboxedArrayType() { 568 return isWordArrayType() || isCodeArrayType() || this == ObjectReferenceArray; 569 } 570 571 /** 572 * Does 'this' refer to a runtime table type? 573 */ 574 @Uninterruptible 575 public boolean isRuntimeTable() { 576 return this == IMT || this == TIB || this == ITable || this == ITableArray || 577 this == FunctionTable || this == LinkageTripletTable; 578 } 579 580 /** 581 * Does 'this' refer to CodeArray 582 */ 583 @Uninterruptible 584 public boolean isCodeArrayType() { 585 return this == CodeArray; 586 } 587 588 /** 589 * Does 'this' refer to Magic? 590 */ 591 @Uninterruptible 592 public boolean isMagicType() { 593 return this == Magic || isUnboxedType() || isUnboxedArrayType() || this == ObjectReference || isRuntimeTable(); 594 } 595 596 /** 597 * How many java stack/local words do value of this type take? 598 */ 599 @Uninterruptible 600 public int getStackWords() { 601 if (isLoaded()) { 602 // all primitive and magic types are resolved immediately 603 return type.getStackWords(); 604 } else { 605 // anything remaining must be a reference 606 return 1; 607 } 608 } 609 610 /** 611 * How many bytes do values of this type take? 612 */ 613 @Uninterruptible 614 public int getMemoryBytes() { 615 if (isLoaded()) { 616 // all primitive and magic types are resolved immediately 617 return type.getMemoryBytes(); 618 } else { 619 // anything remaining must be a reference 620 return BYTES_IN_ADDRESS; 621 } 622 } 623 624 /** 625 * @return the id to use for this type 626 */ 627 @Uninterruptible 628 public int getId() { 629 return id; 630 } 631 632 /** 633 * Is this the type reference for the void primitive type? 634 */ 635 @Uninterruptible 636 public boolean isVoidType() { 637 return this == Void; 638 } 639 640 /** 641 * Is this the type reference for the boolean primitive type? 642 */ 643 @Uninterruptible 644 public boolean isBooleanType() { 645 return this == Boolean; 646 } 647 648 /** 649 * Is this the type reference for the byte primitive type? 650 */ 651 @Uninterruptible 652 public boolean isByteType() { 653 return this == Byte; 654 } 655 656 /** 657 * Is this the type reference for the short primitive type? 658 */ 659 @Uninterruptible 660 public boolean isShortType() { 661 return this == Short; 662 } 663 664 /** 665 * Is this the type reference for the char primitive type? 666 */ 667 @Uninterruptible 668 public boolean isCharType() { 669 return this == Char; 670 } 671 672 /** 673 * Is this the type reference for the int primitive type? 674 */ 675 @Uninterruptible 676 public boolean isIntType() { 677 return this == Int; 678 } 679 680 /** 681 * Is this the type reference for the long primitive type? 682 */ 683 @Uninterruptible 684 public boolean isLongType() { 685 return this == Long; 686 } 687 688 /** 689 * Is this the type reference for the float primitive type? 690 */ 691 @Uninterruptible 692 public boolean isFloatType() { 693 return this == Float; 694 } 695 696 /** 697 * Is this the type reference for the double primitive type? 698 */ 699 @Uninterruptible 700 public boolean isDoubleType() { 701 return this == Double; 702 } 703 704 /** 705 * Is <code>this</code> the type reference for an 706 * int-like (1, 8, 16, or 32 bit integral) primitive type? 707 */ 708 @Uninterruptible 709 public boolean isIntLikeType() { 710 return isBooleanType() || isByteType() || isCharType() || isShortType() || isIntType(); 711 } 712 713 /** 714 * Do this and that definitely refer to the different types? 715 */ 716 public boolean definitelyDifferent(TypeReference that) { 717 if (this == that) return false; 718 if (name != that.name) return true; 719 RVMType mine = peekType(); 720 RVMType theirs = that.peekType(); 721 if (mine == null || theirs == null) return false; 722 return mine != theirs; 723 } 724 725 /** 726 * Do {@code this} and that definitely refer to the same type? 727 */ 728 public boolean definitelySame(TypeReference that) { 729 if (VM.VerifyAssertions) VM._assert(that != null); 730 if (this == that) return true; 731 if (name != that.name) return false; 732 RVMType mine = peekType(); 733 RVMType theirs = that.peekType(); 734 if (mine == null || theirs == null) return false; 735 return mine == theirs; 736 } 737 738 /** 739 * Return true if the type for type reference has been loaded. 740 */ 741 @Uninterruptible 742 public boolean isLoaded() { 743 return type != null; 744 } 745 746 /** 747 * Return true if the type for type reference has been loaded and it is resolved. 748 */ 749 @Uninterruptible 750 public boolean isResolved() { 751 return isLoaded() && type.isResolved(); 752 } 753 754 /** 755 * @return the current value of resolvedType -- null if not yet resolved. 756 */ 757 @Uninterruptible 758 public RVMType peekType() { 759 return type; 760 } 761 762 /* 763 * for use by RVMClassLoader.defineClassInternal 764 */ 765 void setType(RVMType rt) { 766 type = rt; 767 if (type.isClassType()) { 768 type.asClass().setResolvedMembers(); 769 } 770 } 771 772 /** 773 * Force the resolution of the type reference. May cause class loading 774 * if a required class file hasn't been loaded before. 775 * 776 * @return the RVMType instance that this references resolves to. 777 * 778 * @throws NoClassDefFoundError When it cannot resolve a class. 779 * we go to the trouble of converting the class loader's 780 * <code>ClassNotFoundException</code> into this error, 781 * since we need to be able to throw 782 * <code>NoClassDefFoundError</code> for classes 783 * that we're loading whose existence was compile-time checked. 784 * 785 * @throws IllegalArgumentException In case of a malformed class name 786 * (should never happen, since the right thing to do is probably to 787 * validate them as soon as we insert them into a TypeReference. 788 * This stinks. XXX) 789 */ 790 public RVMType resolve() throws NoClassDefFoundError, IllegalArgumentException { 791 /* 792 * Lock the classloader instead of this to avoid conflicting locking order. 793 * Suppose we locked this, then one thread could call resolve(), locking this, 794 * call classloader.loadClass(), trying to lock the classloader. Meanwhile, 795 * another thread could call loadClass(), locking the classloader, then 796 * try to resolve() the TypeReference, resulting in a deadlock 797 */ 798 synchronized (classloader) { 799 return resolveInternal(); 800 } 801 } 802 803 private RVMType resolveInternal() throws NoClassDefFoundError, IllegalArgumentException { 804 if (type != null) return type; 805 if (isClassType()) { 806 RVMType ans; 807 if (VM.runningVM) { 808 Class<?> klass; 809 String myName = name.classNameFromDescriptor(); 810 try { 811 klass = classloader.loadClass(myName); 812 } catch (ClassNotFoundException cnf) { 813 NoClassDefFoundError ncdfe = 814 new NoClassDefFoundError("Could not find the class " + myName + ":\n\t" + cnf.getMessage()); 815 ncdfe.initCause(cnf); // in dubious taste, but helps us debug Jikes RVM 816 throw ncdfe; 817 } 818 819 ans = java.lang.JikesRVMSupport.getTypeForClass(klass); 820 } else { 821 // Use a special purpose backdoor to avoid creating java.lang.Class 822 // objects when not running the VM (we get host JDK Class objects 823 // and that just doesn't work). 824 ans = ((BootstrapClassLoader) classloader).loadVMClass(name.classNameFromDescriptor()); 825 } 826 if (VM.VerifyAssertions) { 827 VM._assert(type == null || type == ans); 828 } 829 setType(ans); 830 } else if (isArrayType()) { 831 if (isUnboxedArrayType()) { 832 // Ensure that we only create one RVMArray object for each pair of 833 // names for this type. 834 // Do this by resolving AddressArray to [Address 835 setType(getArrayElementType().getArrayTypeForElementType().resolve()); 836 } else { 837 RVMType elementType = getArrayElementType().resolve(); 838 if (elementType.getClassLoader() != classloader) { 839 // We aren't the canonical type reference because the element type 840 // was loaded using a different classloader. 841 // Find the canonical type reference and ask it to resolve itself. 842 TypeReference canonical = TypeReference.findOrCreate(elementType.getClassLoader(), name); 843 setType(canonical.resolve()); 844 } else { 845 setType(new RVMArray(this, elementType)); 846 } 847 } 848 } else { 849 if (isUnboxedType()) { 850 setType(UnboxedType.createUnboxedType(this)); 851 } else { 852 setType(Primitive.createPrimitive(this)); 853 } 854 } 855 return type; 856 } 857 858 @Override 859 public String toString() { 860 return "< " + classloader + ", " + name + " >"; 861 } 862 }