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 --&gt; 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 --&gt; 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}