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 */ 013package org.jikesrvm.classloader; 014 015import static org.jikesrvm.runtime.UnboxedSizeConstants.BYTES_IN_ADDRESS; 016 017import org.jikesrvm.VM; 018import org.jikesrvm.runtime.ReflectionBase; 019import org.jikesrvm.util.ImmutableEntryHashSetRVM; 020 021import org.vmmagic.pragma.Uninterruptible; 022 023/** 024 * A class to represent the reference in a class file to some 025 * type (class, primitive or array). 026 * A type reference is uniquely defined by 027 * <ul> 028 * <li> an initiating class loader 029 * <li> a type name 030 * </ul> 031 * Resolving a TypeReference to a RVMType can 032 * be an expensive operation. Therefore we canonicalize 033 * TypeReference instances and cache the result of resolution. 034 */ 035public final class TypeReference { 036 /** 037 * The initiating class loader 038 */ 039 final ClassLoader classloader; 040 041 /** 042 * The type name. For example, the primitive type int is "I", the 043 * class java.lang.String is "Ljava/lang/String;" 044 */ 045 final Atom name; 046 047 /** 048 * The id of this type reference. 049 */ 050 final int id; 051 052 /** 053 * The RVMType instance that this type reference resolves to. 054 * Null if the reference has not yet been resolved. 055 */ 056 private RVMType type; 057 058 /** 059 * Used to canonicalize TypeReferences 060 */ 061 private static final ImmutableEntryHashSetRVM<TypeReference> dictionary = 062 new ImmutableEntryHashSetRVM<TypeReference>(); 063 064 private static final ImmutableEntryHashSetRVM<ClassLoader> clDict = new ImmutableEntryHashSetRVM<ClassLoader>(); 065 /** 066 * 2^LOG_ROW_SIZE is the number of elements per row 067 */ 068 private static final int LOG_ROW_SIZE = 10; 069 /** 070 * Mask to ascertain row from id number 071 */ 072 private static final int ROW_MASK = (1 << LOG_ROW_SIZE) - 1; 073 /** 074 * Dictionary of all TypeReference instances. 075 */ 076 private static TypeReference[][] types = new TypeReference[3][1 << LOG_ROW_SIZE]; 077 078 /** 079 * Used to assign Ids. Id 0 is not used. Ids are compressed and 080 * stored in the constant pool (See {@link RVMClass}). 081 */ 082 private static int nextId = 1; 083 084 public static final TypeReference Void = findOrCreate("V"); 085 public static final TypeReference Boolean = findOrCreate("Z"); 086 public static final TypeReference Byte = findOrCreate("B"); 087 public static final TypeReference Char = findOrCreate("C"); 088 public static final TypeReference Short = findOrCreate("S"); 089 public static final TypeReference Int = findOrCreate("I"); 090 public static final TypeReference Long = findOrCreate("J"); 091 public static final TypeReference Float = findOrCreate("F"); 092 public static final TypeReference Double = findOrCreate("D"); 093 094 public static final TypeReference BooleanArray = findOrCreate("[Z"); 095 public static final TypeReference ByteArray = findOrCreate("[B"); 096 public static final TypeReference CharArray = findOrCreate("[C"); 097 public static final TypeReference ShortArray = findOrCreate("[S"); 098 public static final TypeReference IntArray = findOrCreate("[I"); 099 public static final TypeReference LongArray = findOrCreate("[J"); 100 public static final TypeReference FloatArray = findOrCreate("[F"); 101 public static final TypeReference DoubleArray = findOrCreate("[D"); 102 103 public static final TypeReference Word = findOrCreate(org.vmmagic.unboxed.Word.class); 104 public static final TypeReference Address = findOrCreate(org.vmmagic.unboxed.Address.class); 105 public static final TypeReference ObjectReference = findOrCreate(org.vmmagic.unboxed.ObjectReference.class); 106 public static final TypeReference Offset = findOrCreate(org.vmmagic.unboxed.Offset.class); 107 public static final TypeReference Extent = findOrCreate(org.vmmagic.unboxed.Extent.class); 108 public static final TypeReference Code = findOrCreate(org.jikesrvm.compilers.common.Code.class); 109 public static final TypeReference WordArray = findOrCreate(org.vmmagic.unboxed.WordArray.class); 110 public static final TypeReference AddressArray = findOrCreate(org.vmmagic.unboxed.AddressArray.class); 111 public static final TypeReference ObjectReferenceArray = 112 findOrCreate(org.vmmagic.unboxed.ObjectReferenceArray.class); 113 public static final TypeReference OffsetArray = findOrCreate(org.vmmagic.unboxed.OffsetArray.class); 114 public static final TypeReference ExtentArray = findOrCreate(org.vmmagic.unboxed.ExtentArray.class); 115 public static final TypeReference CodeArray = findOrCreate(org.jikesrvm.compilers.common.CodeArray.class); 116 public static final TypeReference Magic = findOrCreate(org.jikesrvm.runtime.Magic.class); 117 public static final TypeReference SysCall = findOrCreate(org.vmmagic.pragma.SysCallNative.class); 118 public static final TypeReference TIB = findOrCreate(org.jikesrvm.objectmodel.TIB.class); 119 public static final TypeReference ITableArray = findOrCreate(org.jikesrvm.objectmodel.ITableArray.class); 120 public static final TypeReference ITable = findOrCreate(org.jikesrvm.objectmodel.ITable.class); 121 public static final TypeReference IMT = findOrCreate(org.jikesrvm.objectmodel.IMT.class); 122 public static final TypeReference Thread = findOrCreate(org.jikesrvm.scheduler.RVMThread.class); 123 public static final TypeReference FunctionTable = findOrCreate(org.jikesrvm.jni.FunctionTable.class); 124 public static final TypeReference LinkageTripletTable = findOrCreate(org.jikesrvm.jni.LinkageTripletTable.class); 125 126 public static final TypeReference JavaLangObject = findOrCreate(java.lang.Object.class); 127 public static final TypeReference JavaLangClass = findOrCreate(java.lang.Class.class); 128 public static final TypeReference JavaLangString = findOrCreate(java.lang.String.class); 129 public static final TypeReference JavaLangCloneable = findOrCreate(java.lang.Cloneable.class); 130 public static final TypeReference JavaIoSerializable = findOrCreate(java.io.Serializable.class); 131 public static final TypeReference JavaLangRefReference = findOrCreate(java.lang.ref.Reference.class); 132 public static final TypeReference JavaLangSystem = findOrCreate(java.lang.System.class); 133 134 public static final TypeReference JavaLangObjectArray = findOrCreate(java.lang.Object[].class); 135 136 public static final TypeReference JavaLangThrowable = findOrCreate(java.lang.Throwable.class); 137 public static final TypeReference JavaLangError = findOrCreate(java.lang.Error.class); 138 public static final TypeReference JavaLangNullPointerException = 139 findOrCreate(java.lang.NullPointerException.class); 140 public static final TypeReference JavaLangArrayIndexOutOfBoundsException = 141 findOrCreate(java.lang.ArrayIndexOutOfBoundsException.class); 142 public static final TypeReference JavaLangArithmeticException = findOrCreate(java.lang.ArithmeticException.class); 143 public static final TypeReference JavaLangArrayStoreException = findOrCreate(java.lang.ArrayStoreException.class); 144 public static final TypeReference JavaLangClassCastException = findOrCreate(java.lang.ClassCastException.class); 145 public static final TypeReference JavaLangNegativeArraySizeException = 146 findOrCreate(java.lang.NegativeArraySizeException.class); 147 public static final TypeReference JavaLangIllegalMonitorStateException = 148 findOrCreate(java.lang.IllegalMonitorStateException.class); 149 150 public static final TypeReference Type = findOrCreate(org.jikesrvm.classloader.RVMType.class); 151 public static final TypeReference Class = findOrCreate(org.jikesrvm.classloader.RVMClass.class); 152 153 public static final TypeReference NativeBridge = findOrCreate(org.vmmagic.pragma.NativeBridge.class); 154 public static final TypeReference DynamicBridge = findOrCreate(org.vmmagic.pragma.DynamicBridge.class); 155 public static final TypeReference SaveVolatile = findOrCreate(org.vmmagic.pragma.SaveVolatile.class); 156 public static final TypeReference Interruptible = findOrCreate(org.vmmagic.pragma.Interruptible.class); 157 public static final TypeReference LogicallyUninterruptible = 158 findOrCreate(org.vmmagic.pragma.LogicallyUninterruptible.class); 159 public static final TypeReference Preemptible = findOrCreate(org.vmmagic.pragma.Preemptible.class); 160 public static final TypeReference UninterruptibleNoWarn = 161 findOrCreate(org.vmmagic.pragma.UninterruptibleNoWarn.class); 162 public static final TypeReference UnpreemptibleNoWarn = 163 findOrCreate(org.vmmagic.pragma.UnpreemptibleNoWarn.class); 164 public static final TypeReference Uninterruptible = findOrCreate(org.vmmagic.pragma.Uninterruptible.class); 165 public static final TypeReference NoCheckStore = findOrCreate(org.vmmagic.pragma.NoCheckStore.class); 166 public static final TypeReference Unpreemptible = findOrCreate(org.vmmagic.pragma.Unpreemptible.class); 167 public static final TypeReference SpecializedMethodInvoke = findOrCreate(org.vmmagic.pragma.SpecializedMethodInvoke.class); 168 public static final TypeReference Untraced = findOrCreate(org.vmmagic.pragma.Untraced.class); 169 public static final TypeReference NonMoving = findOrCreate(org.vmmagic.pragma.NonMoving.class); 170 public static final TypeReference NonMovingAllocation = findOrCreate(org.vmmagic.pragma.NonMovingAllocation.class); 171 public static final TypeReference BaselineNoRegisters = findOrCreate(org.vmmagic.pragma.BaselineNoRegisters.class); 172 public static final TypeReference BaselineSaveLSRegisters = findOrCreate(org.vmmagic.pragma.BaselineSaveLSRegisters.class); 173 public static final TypeReference ReferenceFieldsVary = findOrCreate(org.vmmagic.pragma.ReferenceFieldsVary.class); 174 175 176 public static final TypeReference ReferenceMaps = 177 findOrCreate(org.jikesrvm.compilers.baseline.ReferenceMaps.class); 178 public static final TypeReference JNIFunctions = findOrCreate(org.jikesrvm.jni.JNIFunctions.class); 179 180 public static final TypeReference RVMArray = findOrCreate(org.jikesrvm.classloader.RVMArray.class); 181 /** Abstract base of reflective method invoker classes */ 182 static final TypeReference baseReflectionClass = TypeReference.findOrCreate(ReflectionBase.class); 183 184 // Synthetic types used by the opt compiler 185 public static final TypeReference NULL_TYPE = 186 (VM.BuildForOptCompiler) ? findOrCreate("Lorg/jikesrvm/classloader/TypeReference$NULL;") : null; 187 public static final TypeReference VALIDATION_TYPE = 188 (VM.BuildForOptCompiler) ? findOrCreate("Lorg/jikesrvm/classloader/TypeReference$VALIDATION;") : null; 189 190 public static final TypeReference ExceptionTable = 191 (VM.BuildForOptCompiler) ? findOrCreate(org.jikesrvm.compilers.common.ExceptionTable.class) : null; 192 193 public static final TypeReference OptimizationPlanner = 194 (VM.BuildForAdaptiveSystem) ? findOrCreate(org.jikesrvm.compilers.opt.driver.OptimizationPlanner.class) : null; 195 196 /** 197 * Hash value based on name, used for canonical type dictionary 198 */ 199 @Override 200 public int hashCode() { 201 return name.hashCode(); 202 } 203 204 /** 205 * Are two keys equivalent? Used for canonical type dictionary. 206 * NB ignores id value 207 */ 208 @Override 209 public boolean equals(Object other) { 210 if (other instanceof TypeReference) { 211 TypeReference that = (TypeReference) other; 212 return name == that.name && classloader.equals(that.classloader); 213 } else { 214 return false; 215 } 216 } 217 218 /** 219 * Find or create the canonical TypeReference instance for 220 * the given pair. 221 * 222 * @param cl the classloader (defining/initiating depending on usage) 223 * @param tn the name of the type 224 * @return the canonical type reference 225 * @throws IllegalArgumentException Needs to throw some kind of error in 226 * the case of a Atom that does not represent a type name. 227 */ 228 public static synchronized TypeReference findOrCreate(ClassLoader cl, Atom tn) throws IllegalArgumentException { 229 TypeDescriptorParsing.validateAsTypeDescriptor(tn); 230 // Primitives, arrays of primitives, system classes and arrays of system 231 // classes must use the bootstrap classloader. Force that here so we don't 232 // have to worry about it anywhere else in the VM. 233 ClassLoader bootstrapCL = BootstrapClassLoader.getBootstrapClassLoader(); 234 if (cl == null) { 235 cl = bootstrapCL; 236 } else if (cl != bootstrapCL) { 237 if (tn.isClassDescriptor()) { 238 if (tn.isBootstrapClassDescriptor()) { 239 cl = bootstrapCL; 240 } 241 } else if (tn.isArrayDescriptor()) { 242 Atom innermostElementType = tn.parseForInnermostArrayElementDescriptor(); 243 if (innermostElementType.isClassDescriptor()) { 244 if (innermostElementType.isBootstrapClassDescriptor()) { 245 cl = bootstrapCL; 246 } 247 } else { 248 cl = bootstrapCL; 249 } 250 } else { 251 cl = bootstrapCL; 252 } 253 } 254 return findOrCreateInternal(cl, tn); 255 } 256 257 /** 258 * Shorthand for doing a find or create for a type reference that should 259 * be created using the bootstrap classloader. 260 * @return the canonical type reference 261 * @param tn type name 262 */ 263 public static TypeReference findOrCreate(String tn) { 264 return findOrCreate(BootstrapClassLoader.getBootstrapClassLoader(), Atom.findOrCreateAsciiAtom(tn)); 265 } 266 267 /** 268 * Convert a java.lang.Class into a type reference the slow way. For 269 * use in boot image writing 270 * @param klass java.lang.Class to convert to type reference 271 * @return the canonical type reference 272 */ 273 public static TypeReference findOrCreate(Class<?> klass) { 274 if (VM.runningVM) { 275 return java.lang.JikesRVMSupport.getTypeForClass(klass).getTypeRef(); 276 } else { 277 String className = klass.getName(); 278 if (className.startsWith("[")) { 279 // an array 280 Atom classAtom = Atom.findOrCreateAsciiAtom(className.replace('.', '/')); 281 return findOrCreate(BootstrapClassLoader.getBootstrapClassLoader(), classAtom); 282 } else { 283 // a class 284 Atom classAtom; 285 if (className.equals("int")) { 286 return TypeReference.Int; 287 } else if (className.equals("boolean")) { 288 return TypeReference.Boolean; 289 } else if (className.equals("byte")) { 290 return TypeReference.Byte; 291 } else if (className.equals("char")) { 292 return TypeReference.Char; 293 } else if (className.equals("double")) { 294 return TypeReference.Double; 295 } else if (className.equals("float")) { 296 return TypeReference.Float; 297 } else if (className.equals("long")) { 298 return TypeReference.Long; 299 } else if (className.equals("short")) { 300 return TypeReference.Short; 301 } else if (className.equals("void")) { 302 return TypeReference.Void; 303 } else { 304 classAtom = Atom.findOrCreateAsciiAtom(className.replace('.', '/')); 305 } 306 Atom classDescriptor = classAtom.descriptorFromClassName(); 307 return findOrCreate(BootstrapClassLoader.getBootstrapClassLoader(), classDescriptor); 308 } 309 } 310 } 311 312 /** 313 * Find or create the canonical TypeReference instance for 314 * the given pair without type descriptor parsing. 315 * 316 * @param cl the classloader (defining/initiating depending on usage) 317 * @param tn the name of the type 318 * @return the canonical type reference 319 */ 320 public static synchronized TypeReference findOrCreateInternal(ClassLoader cl, Atom tn) { 321 // Next actually findOrCreate the type reference using the proper classloader. 322 TypeReference key = new TypeReference(cl, tn, nextId); 323 TypeReference val = dictionary.get(key); 324 if (val == null) { 325 // Create type reference 326 val = key; 327 nextId++; // id of val is the nextId, move it along 328 int column = val.id >> LOG_ROW_SIZE; 329 if (column == types.length) { 330 // Grow the array of types if necessary 331 TypeReference[][] tmp = new TypeReference[column + 1][]; 332 for (int i = 0; i < column; i++) { 333 tmp[i] = types[i]; 334 } 335 types = tmp; 336 types[column] = new TypeReference[1 << LOG_ROW_SIZE]; 337 } 338 types[column][val.id & ROW_MASK] = val; 339 dictionary.add(val); 340 } 341 return val; 342 } 343 private static void canonicalizeCL(ClassLoader cl) { 344 clDict.add(cl); 345 } 346 public static ImmutableEntryHashSetRVM<ClassLoader> getCLDict() { 347 return clDict; 348 } 349 350 /** 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 * @return 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 * @return 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 * @return {@code true} if 'this' refers to a class 466 */ 467 @Uninterruptible 468 public boolean isClassType() { 469 return name.isClassDescriptor() && !(isUnboxedArrayType() || isUnboxedType()); 470 } 471 472 /** 473 * @return {@code true} if 'this' refers to an array 474 */ 475 @Uninterruptible 476 public boolean isArrayType() { 477 return name.isArrayDescriptor() || isUnboxedArrayType(); 478 } 479 480 /** 481 * @return {@code true} if 'this' refers to a primitive type 482 */ 483 @Uninterruptible 484 public boolean isPrimitiveType() { 485 return !(isArrayType() || isClassType()); 486 } 487 488 /** 489 * @return {@code true} if 'this' refers to a reference type 490 */ 491 @Uninterruptible 492 public boolean isReferenceType() { 493 return !isPrimitiveType(); 494 } 495 496 /** 497 * @return {@code true} if 'this' refers 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 * @return {@code true} if 'this' refers to Word 506 */ 507 @Uninterruptible 508 public boolean isWordType() { 509 return this == Word; 510 } 511 512 /** 513 * @return {@code true} if 'this' refers to Address 514 */ 515 @Uninterruptible 516 public boolean isAddressType() { 517 return this == Address; 518 } 519 520 /** 521 * @return {@code true} if 'this' refers to Offset 522 */ 523 @Uninterruptible 524 public boolean isOffsetType() { 525 return this == Offset; 526 } 527 528 /** 529 * @return {@code true} if 'this' refers to Extent 530 */ 531 @Uninterruptible 532 public boolean isExtentType() { 533 return this == Extent; 534 } 535 536 /** 537 * @return {@code true} if 'this' refers to an unboxed type. 538 */ 539 @Uninterruptible 540 public boolean isUnboxedType() { 541 return isWordLikeType() || isCodeType(); 542 } 543 544 /** 545 * @return {@code true} if 'this' refers to Code 546 */ 547 @Uninterruptible 548 public boolean isCodeType() { 549 return this == Code; 550 } 551 552 /** 553 * @return {@code true} if 'this' refers 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 * @return {@code true} if 'this' refers to WordArray, AddressArray, OffsetArray or ExtentArray 565 */ 566 @Uninterruptible 567 public boolean isUnboxedArrayType() { 568 return isWordArrayType() || isCodeArrayType() || this == ObjectReferenceArray; 569 } 570 571 /** 572 * @return {@code true} if 'this' refers 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 * @return {@code true} if 'this' refers to CodeArray 582 */ 583 @Uninterruptible 584 public boolean isCodeArrayType() { 585 return this == CodeArray; 586 } 587 588 /** 589 * @return {@code true} if 'this' refers to Magic 590 */ 591 @Uninterruptible 592 public boolean isMagicType() { 593 return this == Magic || isUnboxedType() || isUnboxedArrayType() || this == ObjectReference || isRuntimeTable(); 594 } 595 596 /** 597 * @return number of java stack/local words that values 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 * @return number of bytes that 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 * @return {@code true} if this is the type reference for the void primitive type 634 */ 635 @Uninterruptible 636 public boolean isVoidType() { 637 return this == Void; 638 } 639 640 /** 641 * @return {@code true} if this is the type reference for the boolean primitive type 642 */ 643 @Uninterruptible 644 public boolean isBooleanType() { 645 return this == Boolean; 646 } 647 648 /** 649 * @return {@code true} if this is the type reference for the byte primitive type 650 */ 651 @Uninterruptible 652 public boolean isByteType() { 653 return this == Byte; 654 } 655 656 /** 657 * @return {@code true} if this is the type reference for the short primitive type 658 */ 659 @Uninterruptible 660 public boolean isShortType() { 661 return this == Short; 662 } 663 664 /** 665 * @return {@code true} if this is the type reference for the char primitive type 666 */ 667 @Uninterruptible 668 public boolean isCharType() { 669 return this == Char; 670 } 671 672 /** 673 * @return {@code true} if this is the type reference for the int primitive type 674 */ 675 @Uninterruptible 676 public boolean isIntType() { 677 return this == Int; 678 } 679 680 /** 681 * @return {@code true} if this is the type reference for the long primitive type 682 */ 683 @Uninterruptible 684 public boolean isLongType() { 685 return this == Long; 686 } 687 688 /** 689 * @return {@code true} if this is the type reference for the float primitive type 690 */ 691 @Uninterruptible 692 public boolean isFloatType() { 693 return this == Float; 694 } 695 696 /** 697 * @return {@code true} if this is the type reference for the double primitive type 698 */ 699 @Uninterruptible 700 public boolean isDoubleType() { 701 return this == Double; 702 } 703 704 /** 705 * @return {@code true} if {@code this} is 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 * @param that other type 717 * @return {@code true} if this and the other type are definitely 718 * different, {@code false} if it's not known (e.g. because a 719 * type reference is not yet resolved) 720 */ 721 public boolean definitelyDifferent(TypeReference that) { 722 if (this == that) return false; 723 if (name != that.name) return true; 724 RVMType mine = peekType(); 725 RVMType theirs = that.peekType(); 726 if (mine == null || theirs == null) return false; 727 return mine != theirs; 728 } 729 730 /** 731 * Do {@code this} and that definitely refer to the same type? 732 * 733 * @param that other type 734 * @return {@code true} if this and the other type are definitely 735 * the same, {@code false} if it's not known (e.g. because a 736 * type reference is not yet resolved) 737 */ 738 public boolean definitelySame(TypeReference that) { 739 if (VM.VerifyAssertions) VM._assert(that != null); 740 if (this == that) return true; 741 if (name != that.name) return false; 742 RVMType mine = peekType(); 743 RVMType theirs = that.peekType(); 744 if (mine == null || theirs == null) return false; 745 return mine == theirs; 746 } 747 748 /** 749 * @return {@code true} if the type for type reference has been loaded. 750 */ 751 @Uninterruptible 752 public boolean isLoaded() { 753 return type != null; 754 } 755 756 /** 757 * @return {@code true} if the type for type reference has been loaded and 758 * it is resolved. 759 */ 760 @Uninterruptible 761 public boolean isResolved() { 762 return isLoaded() && type.isResolved(); 763 } 764 765 /** 766 * @return the current value of resolvedType -- null if not yet resolved. 767 */ 768 @Uninterruptible 769 public RVMType peekType() { 770 return type; 771 } 772 773 void setType(RVMType rt) { 774 type = rt; 775 if (type.isClassType()) { 776 type.asClass().setResolvedMembers(); 777 } 778 } 779 780 /** 781 * Force the resolution of the type reference. May cause class loading 782 * if a required class file hasn't been loaded before. 783 * 784 * @return the RVMType instance that this references resolves to. 785 * 786 * @throws NoClassDefFoundError When it cannot resolve a class. 787 * we go to the trouble of converting the class loader's 788 * <code>ClassNotFoundException</code> into this error, 789 * since we need to be able to throw 790 * <code>NoClassDefFoundError</code> for classes 791 * that we're loading whose existence was compile-time checked. 792 * 793 * @throws IllegalArgumentException In case of a malformed class name 794 * (should never happen, since the right thing to do is probably to 795 * validate them as soon as we insert them into a TypeReference. 796 * This stinks. XXX) 797 */ 798 public RVMType resolve() throws NoClassDefFoundError, IllegalArgumentException { 799 /* 800 * Lock the classloader instead of this to avoid conflicting locking order. 801 * Suppose we locked this, then one thread could call resolve(), locking this, 802 * call classloader.loadClass(), trying to lock the classloader. Meanwhile, 803 * another thread could call loadClass(), locking the classloader, then 804 * try to resolve() the TypeReference, resulting in a deadlock 805 */ 806 synchronized (classloader) { 807 return resolveInternal(); 808 } 809 } 810 811 private RVMType resolveInternal() throws NoClassDefFoundError, IllegalArgumentException { 812 if (type != null) return type; 813 if (isClassType()) { 814 RVMType ans; 815 if (VM.runningVM) { 816 Class<?> klass; 817 String myName = name.classNameFromDescriptor(); 818 try { 819 klass = classloader.loadClass(myName); 820 } catch (ClassNotFoundException cnf) { 821 NoClassDefFoundError ncdfe = 822 new NoClassDefFoundError("Could not find the class " + myName + ":\n\t" + cnf.getMessage()); 823 ncdfe.initCause(cnf); // in dubious taste, but helps us debug Jikes RVM 824 throw ncdfe; 825 } 826 827 ans = java.lang.JikesRVMSupport.getTypeForClass(klass); 828 } else { 829 // Use a special purpose backdoor to avoid creating java.lang.Class 830 // objects when not running the VM (we get host JDK Class objects 831 // and that just doesn't work). 832 ans = ((BootstrapClassLoader) classloader).loadVMClass(name.classNameFromDescriptor()); 833 } 834 if (VM.VerifyAssertions) { 835 VM._assert(type == null || type == ans); 836 } 837 setType(ans); 838 } else if (isArrayType()) { 839 if (isUnboxedArrayType()) { 840 // Ensure that we only create one RVMArray object for each pair of 841 // names for this type. 842 // Do this by resolving AddressArray to [Address 843 setType(getArrayElementType().getArrayTypeForElementType().resolve()); 844 } else { 845 RVMType elementType = getArrayElementType().resolve(); 846 if (elementType.getClassLoader() != classloader) { 847 // We aren't the canonical type reference because the element type 848 // was loaded using a different classloader. 849 // Find the canonical type reference and ask it to resolve itself. 850 TypeReference canonical = TypeReference.findOrCreate(elementType.getClassLoader(), name); 851 setType(canonical.resolve()); 852 } else { 853 setType(new RVMArray(this, elementType)); 854 } 855 } 856 } else { 857 if (isUnboxedType()) { 858 setType(UnboxedType.createUnboxedType(this)); 859 } else { 860 setType(Primitive.createPrimitive(this)); 861 } 862 } 863 return type; 864 } 865 866 @Override 867 public String toString() { 868 return "< " + classloader + ", " + name + " >"; 869 } 870}