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 015 016import static org.jikesrvm.runtime.UnboxedSizeConstants.LOG_BYTES_IN_ADDRESS; 017 018import org.jikesrvm.VM; 019import org.jikesrvm.compilers.common.CodeArray; 020import org.jikesrvm.mm.mminterface.AlignmentEncoding; 021import org.jikesrvm.mm.mminterface.MemoryManager; 022import org.jikesrvm.objectmodel.TIB; 023import org.jikesrvm.runtime.RuntimeEntrypoints; 024import org.jikesrvm.runtime.Statics; 025import org.vmmagic.pragma.Entrypoint; 026import org.vmmagic.pragma.Inline; 027import org.vmmagic.pragma.NonMoving; 028import org.vmmagic.pragma.Uninterruptible; 029import org.vmmagic.unboxed.Offset; 030 031/** 032 * A description of a java type. 033 * <p> 034 * This class is the base of the java type system. 035 * To the three kinds of java objects 036 * (class-instances, array-instances, primitive-instances) 037 * there are three corresponding 038 * subclasses of RVMType: RVMClass, RVMArray, Primitive. 039 * <p> 040 * A RVMClass is constructed in four phases: 041 * <ul> 042 * <li> A "load" phase reads the ".class" file but does not attempt to 043 * examine any of the symbolic references present there. This is done 044 * by the RVMClass constructor as a result of a TypeReference being 045 * resolved. 046 * 047 * <li> A "resolve" phase follows symbolic references as needed to discover 048 * ancestry, to measure field sizes, and to allocate space in the JTOC 049 * for the class's static fields and methods. 050 * 051 * <li> An "instantiate" phase initializes and 052 * installs the type information block and static methods. 053 * 054 * <li> An "initialize" phase runs the class's static initializer. 055 * </ul> 056 * 057 * RVMArray's are constructed in a similar fashion. 058 * 059 * Primitive's are constructed ab initio. 060 * Their "resolution", "instantiation", and "initialization" phases 061 * are no-ops. 062 */ 063@NonMoving 064public abstract class RVMType extends AnnotatedElement { 065 066 /** 067 * A zero-length array, used as GC metadata for primitive 068 * arrays. 069 */ 070 protected static final int[] NOREFS_OFFSET_ARRAY = new int[0]; 071 072 /** 073 * Alias {@code null} for clarity 074 */ 075 public static final int[] REFARRAY_OFFSET_ARRAY = null; 076 077 /** Next space in the the type array */ 078 private static int nextId = 1; 079 080 /** 081 * 2^LOG_ROW_SIZE is the number of elements per row 082 */ 083 private static final int LOG_ROW_SIZE = 10; 084 /** 085 * Mask to ascertain row from id number 086 */ 087 private static final int ROW_MASK = (1 << LOG_ROW_SIZE) - 1; 088 /** All types */ 089 private static RVMType[][] types = new RVMType[1][1 << LOG_ROW_SIZE]; 090 091 /** Canonical representation of no fields */ 092 protected static final RVMField[] emptyVMField = new RVMField[0]; 093 /** Canonical representation of no methods */ 094 protected static final RVMMethod[] emptyVMMethod = new RVMMethod[0]; 095 /** Canonical representation of no VM classes */ 096 protected static final RVMClass[] emptyVMClass = new RVMClass[0]; 097 098 /* 099 * We hold on to a number of special types here for easy access. 100 */ 101 public static final Primitive VoidType; 102 public static final Primitive BooleanType; 103 public static final Primitive ByteType; 104 public static final Primitive ShortType; 105 public static final Primitive IntType; 106 public static final Primitive LongType; 107 public static final Primitive FloatType; 108 public static final Primitive DoubleType; 109 public static final Primitive CharType; 110 public static final RVMClass JavaLangObjectType; 111 public static final RVMArray JavaLangObjectArrayType; 112 public static final RVMClass JavaLangClassType; 113 public static final RVMClass JavaLangThrowableType; 114 public static final RVMClass JavaLangStringType; 115 public static final RVMClass JavaLangCloneableType; 116 public static final RVMClass JavaIoSerializableType; 117 public static final RVMClass JavaLangRefReferenceType; 118 public static final RVMField JavaLangRefReferenceReferenceField; 119 public static final RVMClass MagicType; 120 public static final UnboxedType WordType; 121 public static final RVMArray WordArrayType; 122 public static final UnboxedType AddressType; 123 public static final RVMArray AddressArrayType; 124 public static final RVMClass ObjectReferenceType; 125 public static final RVMArray ObjectReferenceArrayType; 126 public static final UnboxedType OffsetType; 127 public static final RVMArray OffsetArrayType; 128 public static final UnboxedType ExtentType; 129 public static final RVMArray ExtentArrayType; 130 public static final UnboxedType CodeType; 131 public static final RVMArray CodeArrayType; 132 public static final RVMClass TIBType; 133 public static final RVMClass ITableType; 134 public static final RVMClass ITableArrayType; 135 public static final RVMClass IMTType; 136 public static final RVMClass FunctionTableType; 137 public static final RVMClass LinkageTripletTableType; 138 139 static { 140 // Primitive types 141 VoidType = TypeReference.Void.resolve().asPrimitive(); 142 BooleanType = TypeReference.Boolean.resolve().asPrimitive(); 143 ByteType = TypeReference.Byte.resolve().asPrimitive(); 144 ShortType = TypeReference.Short.resolve().asPrimitive(); 145 IntType = TypeReference.Int.resolve().asPrimitive(); 146 LongType = TypeReference.Long.resolve().asPrimitive(); 147 FloatType = TypeReference.Float.resolve().asPrimitive(); 148 DoubleType = TypeReference.Double.resolve().asPrimitive(); 149 CharType = TypeReference.Char.resolve().asPrimitive(); 150 // Jikes RVM primitives 151 AddressType = TypeReference.Address.resolve().asUnboxedType(); 152 WordType = TypeReference.Word.resolve().asUnboxedType(); 153 OffsetType = TypeReference.Offset.resolve().asUnboxedType(); 154 ExtentType = TypeReference.Extent.resolve().asUnboxedType(); 155 CodeType = TypeReference.Code.resolve().asUnboxedType(); 156 ObjectReferenceType = TypeReference.ObjectReference.resolve().asClass(); 157 // Jikes RVM classes 158 MagicType = TypeReference.Magic.resolve().asClass(); 159 // Array types 160 CodeArrayType = TypeReference.CodeArray.resolve().asArray(); 161 WordArrayType = TypeReference.WordArray.resolve().asArray(); 162 AddressArrayType = TypeReference.AddressArray.resolve().asArray(); 163 ObjectReferenceArrayType = TypeReference.ObjectReferenceArray.resolve().asArray(); 164 OffsetArrayType = TypeReference.OffsetArray.resolve().asArray(); 165 ExtentArrayType = TypeReference.ExtentArray.resolve().asArray(); 166 // Runtime Tables 167 TIBType = TypeReference.TIB.resolve().asClass(); 168 ITableType = TypeReference.ITable.resolve().asClass(); 169 ITableArrayType = TypeReference.ITableArray.resolve().asClass(); 170 IMTType = TypeReference.IMT.resolve().asClass(); 171 FunctionTableType = TypeReference.FunctionTable.resolve().asClass(); 172 LinkageTripletTableType = TypeReference.LinkageTripletTable.resolve().asClass(); 173 // Java clases 174 JavaLangObjectType = TypeReference.JavaLangObject.resolve().asClass(); 175 JavaLangObjectArrayType = TypeReference.JavaLangObjectArray.resolve().asArray(); 176 JavaLangClassType = TypeReference.JavaLangClass.resolve().asClass(); 177 JavaLangThrowableType = TypeReference.JavaLangThrowable.resolve().asClass(); 178 JavaLangStringType = TypeReference.JavaLangString.resolve().asClass(); 179 JavaLangCloneableType = TypeReference.JavaLangCloneable.resolve().asClass(); 180 JavaIoSerializableType = TypeReference.JavaIoSerializable.resolve().asClass(); 181 JavaLangRefReferenceType = TypeReference.JavaLangRefReference.resolve().asClass(); 182 JavaLangRefReferenceReferenceField = JavaLangRefReferenceType.findDeclaredField(Atom.findAsciiAtom("_referent")); 183 } 184 185 /** 186 * Canonical type reference for this RVMType instance 187 */ 188 protected final TypeReference typeRef; 189 190 /** 191 * Type id -- used to index into typechecking datastructures 192 */ 193 @Entrypoint 194 protected final int id; 195 196 /** 197 * index of JTOC slot that has type information block for this RVMType 198 */ 199 protected final int tibOffset; 200 201 /** 202 * instance of java.lang.Class corresponding to this type 203 */ 204 private final Class<?> classForType; 205 206 /** 207 * Number of [ in descriptor for arrays; -1 for primitives; 0 for 208 * classes. NB this field must appear in all Types for fast type 209 * checks (See transformation from HIR to LIR for details). 210 */ 211 @Entrypoint 212 protected final int dimension; 213 /** 214 * Number of superclasses to Object. Known immediately for 215 * primitives and arrays, but only after resolving for classes. NB 216 * this field must appear in all Types for fast object array 217 * store checks (See transformation from HIR to LIR for details). 218 */ 219 @Entrypoint 220 protected int depth; 221 /** 222 * cached RVMArray that corresponds to arrays of this type. 223 * (null --> not created yet). 224 */ 225 private RVMArray cachedElementType; 226 227 /** 228 * The superclass ids for this type. 229 */ 230 protected short[] superclassIds; 231 232 /** 233 * The interface implementation array for this type. 234 */ 235 protected int[] doesImplement; 236 237 /** 238 * Create an instance of a {@link RVMType} 239 * @param typeRef The canonical type reference for this type. 240 * @param classForType The java.lang.Class representation 241 * @param dimension The dimensionality 242 * @param annotations array of runtime visible annotations 243 */ 244 protected RVMType(TypeReference typeRef, Class<?> classForType, int dimension, RVMAnnotation[] annotations) { 245 super(annotations); 246 this.typeRef = typeRef; 247 this.tibOffset = Statics.allocateReferenceSlot(false).toInt(); 248 this.id = nextId(this); 249 this.classForType = classForType; 250 this.dimension = dimension; 251 252 253 /* install partial type information block (no method dispatch table) for use in type checking. */ 254 TIB tib = MemoryManager.newTIB(0, AlignmentEncoding.ALIGN_CODE_NONE); 255 tib.setType(this); 256 Statics.setSlotContents(getTibOffset(), tib); 257 } 258 259 /** 260 * Create an instance of a {@link RVMType} 261 * @param typeRef The canonical type reference for this type. 262 * @param dimension The dimensionality 263 * @param annotations array of runtime visible annotations 264 */ 265 protected RVMType(TypeReference typeRef, int dimension, RVMAnnotation[] annotations) { 266 super(annotations); 267 this.typeRef = typeRef; 268 this.tibOffset = Statics.allocateReferenceSlot(false).toInt(); 269 this.id = nextId(this); 270 this.classForType = createClassForType(this, typeRef); 271 this.dimension = dimension; 272 273 274 /* install partial type information block (no method dispatch table) for use in type checking. */ 275 TIB tib = MemoryManager.newTIB(0, AlignmentEncoding.ALIGN_CODE_NONE); 276 tib.setType(this); 277 Statics.setSlotContents(getTibOffset(), tib); 278 } 279 280 /** 281 * @return canonical type reference for this type. 282 */ 283 @Uninterruptible 284 public final TypeReference getTypeRef() { 285 return typeRef; 286 } 287 288 /** 289 * @return the numeric identifier for this type 290 */ 291 @Uninterruptible 292 public final int getId() { 293 return id; 294 } 295 296 /** 297 * @return instance of java.lang.Class corresponding to this type. 298 * This is commonly used for reflection. NB: this method will cause 299 * resolution to take place if necessary. 300 */ 301 public final Class<?> getClassForType() { 302 if (VM.runningVM) { 303 // Resolve the class so that we don't need to resolve it 304 // in reflection code 305 if (!isResolved()) { 306 resolve(); 307 } 308 return classForType; 309 } else { 310 return createClassForType(this, getTypeRef()); 311 } 312 } 313 314 /** 315 * Gets the resolved class for a type. 316 * <p> 317 * Note that this method may only be called when it's clear that the 318 * class has already been resolved. If that is not guaranteed, use 319 * {@link #getClassForType()}. 320 * @return instance of java.lang.Class corresponding to this type. 321 */ 322 @Uninterruptible 323 public final Class<?> getResolvedClassForType() { 324 if (VM.VerifyAssertions) VM._assert(VM.runningVM && isResolved()); 325 return classForType; 326 } 327 328 /** 329 * @return offset of TIB slot from start of JTOC, in bytes. 330 */ 331 @Uninterruptible 332 public final Offset getTibOffset() { 333 return Offset.fromIntSignExtend(tibOffset); 334 } 335 336 /** 337 * @return the class loader for this type 338 */ 339 @Uninterruptible 340 public final ClassLoader getClassLoader() { 341 return typeRef.getClassLoader(); 342 } 343 344 /** 345 * Should assertions be enabled on this type? 346 * @return {@code false} 347 */ 348 public boolean getDesiredAssertionStatus() { 349 return false; 350 } 351 352 /** 353 * Descriptor for this type. 354 * <ul> 355 * <li>For a class, something like "Ljava/lang/String;". 356 * <li>For an array, something like "[I" or "[Ljava/lang/String;". 357 * <li>For a primitive, something like "I". 358 * </ul> 359 * @return descriptor as described above 360 */ 361 @Uninterruptible 362 public final Atom getDescriptor() { 363 return typeRef.getName(); 364 } 365 366 /** 367 * Define hashCode(), to allow use of consistent hash codes during 368 * bootImage writing and run-time 369 */ 370 @Override 371 public final int hashCode() { 372 return typeRef.hashCode(); 373 } 374 375 /** 376 * get number of superclasses to Object 377 * <ul> 378 * <li>0 java.lang.Object, Primitive, and Classes that are interfaces 379 * <li>1 for RVMArrays and classes that extend Object directly 380 * </ul> 381 * @return number of superclasses between this type and object 382 */ 383 @Uninterruptible 384 public abstract int getTypeDepth(); 385 386 /** 387 * Reference Count GC: Is a reference of this type contained in 388 * another object inherently acyclic (without cycles)? 389 * 390 * @return {@code true} if the reference is acyclic 391 */ 392 @Uninterruptible 393 public abstract boolean isAcyclicReference(); 394 395 /** 396 * Number of [ in descriptor for arrays; -1 for primitives; 0 for classes 397 * 398 * @return dimensionality of the type (see above) 399 */ 400 @Uninterruptible 401 public abstract int getDimensionality(); 402 403 /** 404 * @return this cast to a RVMClass 405 */ 406 @Uninterruptible 407 public final RVMClass asClass() { 408 return (RVMClass) this; 409 } 410 411 /** 412 * @return this cast to a RVMArray 413 */ 414 @Uninterruptible 415 public final RVMArray asArray() { 416 return (RVMArray) this; 417 } 418 419 /** 420 * @return this cast to a Primitive 421 */ 422 @Uninterruptible 423 public final Primitive asPrimitive() { 424 return (Primitive) this; 425 } 426 427 /** 428 * @return this cast to a UnboxedType 429 */ 430 @Uninterruptible 431 public final UnboxedType asUnboxedType() { 432 return (UnboxedType) this; 433 } 434 // Convenience methods. 435 // 436 /** @return is this type void? */ 437 @Uninterruptible 438 public final boolean isVoidType() { 439 return this == VoidType; 440 } 441 442 /** @return is this type the primitive boolean? */ 443 @Uninterruptible 444 public final boolean isBooleanType() { 445 return this == BooleanType; 446 } 447 448 /** @return is this type the primitive byte? */ 449 @Uninterruptible 450 public final boolean isByteType() { 451 return this == ByteType; 452 } 453 454 /** @return is this type the primitive short? */ 455 @Uninterruptible 456 public final boolean isShortType() { 457 return this == ShortType; 458 } 459 460 /** @return is this type the primitive int? */ 461 @Uninterruptible 462 public final boolean isIntType() { 463 return this == IntType; 464 } 465 466 /** @return is this type the primitive long? */ 467 @Uninterruptible 468 public final boolean isLongType() { 469 return this == LongType; 470 } 471 472 /** @return is this type the primitive float? */ 473 @Uninterruptible 474 public final boolean isFloatType() { 475 return this == FloatType; 476 } 477 478 /** @return is this type the primitive double? */ 479 @Uninterruptible 480 public final boolean isDoubleType() { 481 return this == DoubleType; 482 } 483 484 /** @return is this type the primitive char? */ 485 @Uninterruptible 486 public final boolean isCharType() { 487 return this == CharType; 488 } 489 490 /** 491 * @return is this type the primitive int like? ie is it held as an 492 * int on the JVM stack 493 */ 494 @Uninterruptible 495 public final boolean isIntLikeType() { 496 return isBooleanType() || isByteType() || isShortType() || isIntType() || isCharType(); 497 } 498 499 /** @return is this type the class Object? */ 500 @Uninterruptible 501 public final boolean isJavaLangObjectType() { 502 return this == JavaLangObjectType; 503 } 504 505 /** @return is this type the class Throwable? */ 506 @Uninterruptible 507 public final boolean isJavaLangThrowableType() { 508 return this == JavaLangThrowableType; 509 } 510 511 /** @return is this type the class String? */ 512 @Uninterruptible 513 public final boolean isJavaLangStringType() { 514 return this == JavaLangStringType; 515 } 516 517 /** 518 * @return array type corresponding to "this" array element type. 519 */ 520 public final RVMArray getArrayTypeForElementType() { 521 if (cachedElementType == null) { 522 TypeReference tr = typeRef.getArrayTypeForElementType(); 523 cachedElementType = tr.resolve().asArray(); 524 /* Can't fail to resolve the type, because the element type already 525 exists (it is 'this') and the VM creates array types itself without 526 any possibility of error if the element type is already loaded. */ 527 } 528 return cachedElementType; 529 } 530 531 /** 532 * @return superclass id vector (@see DynamicTypeCheck) 533 */ 534 @Uninterruptible 535 public final short[] getSuperclassIds() { 536 return superclassIds; 537 } 538 539 /** 540 * @return doesImplement vector (@see DynamicTypeCheck) 541 */ 542 @Uninterruptible 543 public final int[] getDoesImplement() { 544 return doesImplement; 545 } 546 547 /** 548 * Allocate entry in types array and add it (NB resize array if it's 549 * not long enough). 550 * 551 * @param it the type to add 552 * @return the id of the tpye in the types array 553 */ 554 private static synchronized int nextId(RVMType it) { 555 int ans = nextId++; 556 int column = ans >> LOG_ROW_SIZE; 557 if (column >= types.length) { 558 RVMType[][] newTypes = new RVMType[column + 1][]; 559 for (int i = 0; i < types.length; i++) { 560 newTypes[i] = types[i]; 561 } 562 newTypes[column] = new RVMType[1 << LOG_ROW_SIZE]; 563 types = newTypes; 564 } 565 types[ans >> LOG_ROW_SIZE][ans & ROW_MASK] = it; 566 return ans; 567 } 568 569 /** 570 * How many types have been created? 571 * Only intended to be used by the bootimage writer 572 * or members of this class! 573 * 574 * @return number of types that have been created 575 */ 576 @Uninterruptible 577 public static int numTypes() { 578 return nextId - 1; 579 } 580 581 @Uninterruptible 582 public static RVMType getType(int id) { 583 return types[id >> LOG_ROW_SIZE][id & ROW_MASK]; 584 } 585 586 protected static Class<?> createClassForType(RVMType type, TypeReference typeRef) { 587 if (VM.runningVM) { 588 return java.lang.JikesRVMSupport.createClass(type); 589 } else { 590 Exception x; 591 try { 592 Atom className = typeRef.getName(); 593 if (className.isAnnotationClass()) { 594 return Class.forName(className.annotationClassToAnnotationInterface(), false, RVMType.class.getClassLoader()); 595 } else if (className.isClassDescriptor()) { 596 return Class.forName(className.classNameFromDescriptor(), false, RVMType.class.getClassLoader()); 597 } else { 598 String classNameString = className.toString(); 599 if (classNameString.equals("V")) { 600 return void.class; 601 } else if (classNameString.equals("I")) { 602 return int.class; 603 } else if (classNameString.equals("J")) { 604 return long.class; 605 } else if (classNameString.equals("F")) { 606 return float.class; 607 } else if (classNameString.equals("D")) { 608 return double.class; 609 } else if (classNameString.equals("C")) { 610 return char.class; 611 } else if (classNameString.equals("S")) { 612 return short.class; 613 } else if (classNameString.equals("Z")) { 614 return boolean.class; 615 } else if (classNameString.equals("B")) { 616 return byte.class; 617 } else { 618 return Class.forName(classNameString.replace('/', '.'), false, RVMType.class.getClassLoader()); 619 } 620 } 621 } catch (ClassNotFoundException e) { 622 x = e; 623 } catch (SecurityException e) { 624 x = e; 625 } 626 if (typeRef.isArrayType() && typeRef.getArrayElementType().isCodeType()) { 627 // fix up class for code array 628 return CodeArray.class; 629 } else if (!VM.runningVM) { 630 // Give a warning as this is probably a protection issue for 631 // the tool and JVM 632 VM.sysWriteln("Warning unable to find Java class for RVM type"); 633 x.printStackTrace(); 634 return null; 635 } else { 636 throw new Error("Unable to find Java class for RVM type", x); 637 } 638 } 639 } 640 641 /** 642 * Find specified virtual method description. 643 * @param memberName method name - something like "foo" 644 * @param memberDescriptor method descriptor - something like "I" or "()I" 645 * @return method description (null --> not found) 646 */ 647 public final RVMMethod findVirtualMethod(Atom memberName, Atom memberDescriptor) { 648 if (VM.VerifyAssertions) VM._assert(isResolved()); 649 RVMMethod[] methods = getVirtualMethods(); 650 for (int i = 0, n = methods.length; i < n; ++i) { 651 RVMMethod method = methods[i]; 652 if (method.getName() == memberName && method.getDescriptor() == memberDescriptor) { 653 return method; 654 } 655 } 656 return null; 657 } 658 659 /** 660 * Return the method at the given TIB slot 661 * @param slot the slot that contains the method 662 * @return the method at that slot 663 */ 664 public final RVMMethod getTIBMethodAtSlot(int slot) { 665 int index = TIB.getVirtualMethodIndex(slot); 666 RVMMethod[] methods = getVirtualMethods(); 667 if (VM.VerifyAssertions) VM._assert(methods[index].getOffset().toInt() == slot << LOG_BYTES_IN_ADDRESS); 668 return methods[index]; 669 } 670 // Methods implemented in Primitive, RVMArray or RVMClass 671 672 /** 673 * Resolution status.<p> 674 * If the class/array has been "resolved", then size and offset information is 675 * available by which the compiler can generate code to access this 676 * class/array's 677 * fields/methods via direct loads/stores/calls (rather than generating 678 * code to access fields/methods symbolically, via dynamic linking stubs).<p> 679 * Primitives are always treated as "resolved". 680 * 681 * @return {@code true} when the class has been resolved 682 */ 683 @Uninterruptible 684 public abstract boolean isResolved(); 685 686 /** 687 * Instantiation status.<p> 688 * If the class/array has been "instantiated", 689 * then all its methods have been compiled 690 * and its type information block has been placed in the JTOC.<p> 691 * Primitives are always treated as "instantiated". 692 * 693 * @return {@code true} when the class has been instantiated 694 */ 695 @Uninterruptible 696 public abstract boolean isInstantiated(); 697 698 /** 699 * Initialization status.<p> 700 * If the class has been "initialized", 701 * then its {@code <clinit>} method has been executed. 702 * Arrays have no {@code <clinit>} methods so they become 703 * "initialized" immediately upon "instantiation".<p> 704 * Primitives are always treated as "initialized". 705 * 706 * @return {@code true} when the class has been initialized 707 */ 708 @Uninterruptible 709 public abstract boolean isInitialized(); 710 711 /** 712 * Only intended to be used by the BootImageWriter 713 */ 714 public abstract void markAsBootImageClass(); 715 716 /** 717 * Is this class part of the virtual machine's boot image? 718 * 719 * @return {@code true} if the class is in the bootimage 720 */ 721 @Uninterruptible 722 public abstract boolean isInBootImage(); 723 724 /** 725 * @return the offset in instances of this type assigned to the thin lock word. 726 * Offset.max() if instances of this type do not have thin lock words. 727 */ 728 @Uninterruptible 729 public abstract Offset getThinLockOffset(); 730 731 /** 732 * Is this is an instance of RVMClass? 733 * @return whether or not this is an instance of RVMClass? 734 */ 735 @Uninterruptible 736 public abstract boolean isClassType(); 737 738 /** 739 * Is this an instance of RVMArray? 740 * @return whether or not this is an instance of RVMArray? 741 */ 742 @Uninterruptible 743 public abstract boolean isArrayType(); 744 745 /** 746 * Is this a primitive type? 747 * @return whether or not this is a primitive type 748 */ 749 @Uninterruptible 750 public abstract boolean isPrimitiveType(); 751 752 /** 753 * Is this an unboxed type? 754 * @return whether or not this is an unboxed type 755 */ 756 @Uninterruptible 757 public abstract boolean isUnboxedType(); 758 759 /** 760 * Is this a reference type? 761 * @return whether or not this is a reference (ie non-primitive) type. 762 */ 763 @Uninterruptible 764 public abstract boolean isReferenceType(); 765 766 /** 767 * @param type type to checj 768 * @return whether type can be assigned to things of this RVMType 769 */ 770 public boolean isAssignableFrom(RVMType type) { 771 return this == type || RuntimeEntrypoints.isAssignableWith(this, type); 772 } 773 774 /** 775 * Space required when this type is stored on the stack 776 * (or as a field), in words. 777 * Ie. 0, 1, or 2 words: 778 * <ul> 779 * <li> reference types (classes and arrays) require 1 word 780 * <li> void types require 0 words 781 * <li> long and double types require 2 words 782 * <li> all other primitive types require 1 word 783 * </ul> 784 * 785 * @return space in words on the stack 786 */ 787 @Uninterruptible 788 public abstract int getStackWords(); 789 790 /** 791 * @return number of bytes in memory required to represent the type 792 */ 793 @Uninterruptible 794 public abstract int getMemoryBytes(); 795 796 /** 797 * Cause resolution to take place. 798 * This will cause slots to be allocated in the JTOC. 799 */ 800 public abstract void resolve(); 801 802 /** 803 * This method is only called by the bootimage writer. 804 * It is called after {@link #resolve()} has been called on all 805 * bootimage types but before {@link #instantiate()} has been called 806 * on any bootimage type. 807 * This provides a hook to compute various summaries that cannot be computed before types 808 * are resolved. 809 */ 810 public abstract void allBootImageTypesResolved(); 811 812 /** 813 * Cause instantiation to take place. 814 * This will cause the class's methods to be compiled and slots in the 815 * JTOC to be filled-in. 816 */ 817 public abstract void instantiate(); 818 819 /** 820 * Cause initialization to take place. 821 * This will cause the class's {@code <clinit>} method to be executed. 822 */ 823 public abstract void initialize(); 824 825 /** 826 * @return {@code true} if this type overrides {@code java.lang.Object.finalize()} 827 */ 828 @Uninterruptible 829 public abstract boolean hasFinalizer(); 830 831 public abstract RVMField[] getStaticFields(); 832 833 /** 834 * @return non-static fields of this class/array type 835 * (composed with supertypes, if any). 836 */ 837 public abstract RVMField[] getInstanceFields(); 838 839 public abstract RVMMethod[] getStaticMethods(); 840 841 /** 842 * @return virtually dispatched methods of this class/array type 843 * (composed with supertypes, if any). 844 */ 845 public abstract RVMMethod[] getVirtualMethods(); 846 847 /** 848 * @return runtime type information for this class/array type. 849 */ 850 @Uninterruptible 851 public abstract TIB getTypeInformationBlock(); 852 853 public final void setSpecializedMethod(int id, CodeArray code) { 854 getTypeInformationBlock().setSpecializedMethod(id, code); 855 } 856 857 /** 858 * Updates the TIB for all array types with the newly (re)compiled method. 859 * 860 * @param m the method that was recompiled. Must be a virtual method 861 * declared by {@code java.lang.Object}. 862 */ 863 static synchronized void updateArrayMethods(RVMMethod m) { 864 if (VM.VerifyAssertions) VM._assert(m.getDeclaringClass().isJavaLangObjectType()); 865 if (VM.VerifyAssertions) VM._assert(!m.isStatic()); 866 // Start at slot 1 since nextId is initialized to 1 867 for (int i = 1; i <= numTypes(); i++) { 868 RVMType type = RVMType.getType(i); 869 if (type.isArrayType() && type.isResolved()) { 870 TIB arrayTIB = type.getTypeInformationBlock(); 871 TIB objectTIB = RVMType.JavaLangObjectType.getTypeInformationBlock(); 872 Offset virtualMethodOffset = m.getOffset(); 873 CodeArray virtualMethod = objectTIB.getVirtualMethod(virtualMethodOffset); 874 arrayTIB.setVirtualMethod(virtualMethodOffset, virtualMethod); 875 } 876 } 877 } 878 879 /** 880 * The memory manager's allocator id for this type. 881 */ 882 private int mmAllocator; 883 884 /** 885 * GC metadata for this type. 886 * 887 * In a primitive array this field points to a zero-length array. 888 * 889 * In a reference array this field is {@code null}. 890 * 891 * In a class with pointers, it contains the offsets of 892 * reference-containing instance fields 893 */ 894 protected int[] referenceOffsets; 895 896 /** 897 * Records the allocator information the memory manager holds about this type. 898 * 899 * @param allocator the allocator to record 900 */ 901 public final void setMMAllocator(int allocator) { 902 this.mmAllocator = allocator; 903 } 904 905 /** 906 * This returns the allocator id as supplied by the memory manager. 907 * The method is located here as this is the only common superclass of RVMArray 908 * and RVMClass, and due to performance reasons this needs to be a non-abstract 909 * method. For Primitive this field is unused. 910 * 911 * @return the allocator id previously recorded. 912 */ 913 @Uninterruptible 914 @Inline 915 public final int getMMAllocator() { 916 return mmAllocator; 917 } 918 919 /** 920 * @return is this a type that must never move 921 */ 922 public boolean isNonMoving() { 923 return hasNonMovingAnnotation(); 924 } 925 926 /** 927 * @return offsets of reference-containing instance fields of this class type. 928 * Offsets are with respect to object pointer -- see RVMField.getOffset(). 929 */ 930 @Uninterruptible 931 public int[] getReferenceOffsets() { 932 if (VM.VerifyAssertions) VM._assert(isResolved()); 933 return referenceOffsets; 934 } 935 936}