001    /*
002     *  This file is part of the Jikes RVM project (http://jikesrvm.org).
003     *
004     *  This file is licensed to You under the Eclipse Public License (EPL);
005     *  You may not use this file except in compliance with the License. You
006     *  may obtain a copy of the License at
007     *
008     *      http://www.opensource.org/licenses/eclipse-1.0.php
009     *
010     *  See the COPYRIGHT.txt file distributed with this work for information
011     *  regarding copyright ownership.
012     */
013    package org.jikesrvm.classloader;
014    
015    import org.jikesrvm.VM;
016    import org.jikesrvm.Constants;
017    import org.jikesrvm.SizeConstants;
018    import org.jikesrvm.ArchitectureSpecific.CodeArray;
019    import org.jikesrvm.mm.mminterface.AlignmentEncoding;
020    import org.jikesrvm.mm.mminterface.MemoryManager;
021    import org.jikesrvm.objectmodel.TIB;
022    import org.jikesrvm.runtime.RuntimeEntrypoints;
023    import org.jikesrvm.runtime.Statics;
024    import org.vmmagic.pragma.Entrypoint;
025    import org.vmmagic.pragma.Inline;
026    import org.vmmagic.pragma.NonMoving;
027    import org.vmmagic.pragma.Uninterruptible;
028    import org.vmmagic.unboxed.Offset;
029    
030    /**
031     * A description of a java type.
032     * <p>
033     * This class is the base of the java type system.
034     * To the three kinds of java objects
035     * (class-instances, array-instances, primitive-instances)
036     * there are three corresponding
037     * subclasses of RVMType: RVMClass, RVMArray, Primitive.
038     * <p>
039     * A RVMClass is constructed in four phases:
040     * <ul>
041     * <li> A "load" phase reads the ".class" file but does not attempt to
042     *      examine any of the symbolic references present there. This is done
043     *      by the RVMClass constructor as a result of a TypeReference being
044     *      resolved.
045     *
046     * <li> A "resolve" phase follows symbolic references as needed to discover
047     *   ancestry, to measure field sizes, and to allocate space in the JTOC
048     *   for the class's static fields and methods.
049     *
050     * <li>  An "instantiate" phase initializes and
051     * installs the type information block and static methods.
052     *
053     * <li> An "initialize" phase runs the class's static initializer.
054     * </ul>
055     *
056     * RVMArray's are constructed in a similar fashion.
057     *
058     * Primitive's are constructed ab initio.
059     * Their "resolution", "instantiation", and "initialization" phases
060     * are no-ops.
061     */
062    @NonMoving
063    public abstract class RVMType extends AnnotatedElement
064        implements ClassLoaderConstants, SizeConstants, Constants {
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 {@link org.jikesrvm.compilers.opt.hir2lir.DynamicTypeCheckExpansion}).
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 {@link org.jikesrvm.compilers.opt.hir2lir.DynamicTypeCheckExpansion}).
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       * Canonical type reference for this type.
282       */
283      @Uninterruptible
284      public final TypeReference getTypeRef() {
285        return typeRef;
286      }
287    
288      /**
289       * Get the numeric identifier for this type
290       */
291      @Uninterruptible
292      public final int getId() {
293        return id;
294      }
295    
296      /**
297       * Instance of java.lang.Class corresponding to this type.
298       * This is commonly used for reflection.
299       */
300      public final Class<?> getClassForType() {
301        if (VM.runningVM) {
302          // Resolve the class so that we don't need to resolve it
303          // in reflection code
304          if (!isResolved()) {
305            resolve();
306          }
307          return classForType;
308        } else {
309          return createClassForType(this, getTypeRef());
310        }
311      }
312    
313      /**
314       * Instance of java.lang.Class corresponding to this type.
315       * This is commonly used for reflection.
316       */
317      @Uninterruptible
318      public final Class<?> getResolvedClassForType() {
319        // Resolve the class so that we don't need to resolve it
320        // in reflection code
321        if (VM.VerifyAssertions) VM._assert(VM.runningVM && isResolved());
322        return classForType;
323      }
324    
325      /**
326       * Get offset of tib slot from start of jtoc, in bytes.
327       */
328      @Uninterruptible
329      public final Offset getTibOffset() {
330        return Offset.fromIntSignExtend(tibOffset);
331      }
332    
333      /**
334       * Get the class loader for this type
335       */
336      @Uninterruptible
337      public final ClassLoader getClassLoader() {
338        return typeRef.getClassLoader();
339      }
340    
341      /**
342       * Should assertions be enabled on this type?
343       * @return {@code false}
344       */
345      public boolean getDesiredAssertionStatus() {
346        return false;
347      }
348    
349      /**
350       * Descriptor for this type.
351       * <ul>
352       *   <li>For a class, something like "Ljava/lang/String;".
353       *   <li>For an array, something like "[I" or "[Ljava/lang/String;".
354       *   <li>For a primitive, something like "I".
355       * </ul>
356       */
357      @Uninterruptible
358      public final Atom getDescriptor() {
359        return typeRef.getName();
360      }
361    
362      /**
363       * Define hashCode(), to allow use of consistent hash codes during
364       * bootImage writing and run-time
365       */
366      @Override
367      public final int hashCode() {
368        return typeRef.hashCode();
369      }
370    
371      /**
372       * get number of superclasses to Object
373       * <ul>
374       *   <li>0 java.lang.Object, Primitive, and Classes that are interfaces
375       *   <li>1 for RVMArrays and classes that extend Object directly
376       * </ul>
377       */
378      @Uninterruptible
379      public abstract int getTypeDepth();
380    
381      /**
382       * Reference Count GC: Is a reference of this type contained in
383       * another object inherently acyclic (without cycles)?
384       */
385      @Uninterruptible
386      public abstract boolean isAcyclicReference();
387    
388      /**
389       * Number of [ in descriptor for arrays; -1 for primitives; 0 for classes
390       */
391      @Uninterruptible
392      public abstract int getDimensionality();
393    
394      /**
395       * @return this cast to a RVMClass
396       */
397      @Uninterruptible
398      public final RVMClass asClass() {
399        return (RVMClass) this;
400      }
401    
402      /**
403       * @return this cast to a RVMArray
404       */
405      @Uninterruptible
406      public final RVMArray asArray() {
407        return (RVMArray) this;
408      }
409    
410      /**
411       * @return this cast to a Primitive
412       */
413      @Uninterruptible
414      public final Primitive asPrimitive() {
415        return (Primitive) this;
416      }
417    
418      /**
419       * @return this cast to a UnboxedType
420       */
421      @Uninterruptible
422      public final UnboxedType asUnboxedType() {
423        return (UnboxedType) this;
424      }
425      // Convenience methods.
426      //
427      /** @return is this type void? */
428      @Uninterruptible
429      public final boolean isVoidType() {
430        return this == VoidType;
431      }
432    
433      /** @return is this type the primitive boolean? */
434      @Uninterruptible
435      public final boolean isBooleanType() {
436        return this == BooleanType;
437      }
438    
439      /** @return is this type the primitive byte? */
440      @Uninterruptible
441      public final boolean isByteType() {
442        return this == ByteType;
443      }
444    
445      /** @return is this type the primitive short? */
446      @Uninterruptible
447      public final boolean isShortType() {
448        return this == ShortType;
449      }
450    
451      /** @return is this type the primitive int? */
452      @Uninterruptible
453      public final boolean isIntType() {
454        return this == IntType;
455      }
456    
457      /** @return is this type the primitive long? */
458      @Uninterruptible
459      public final boolean isLongType() {
460        return this == LongType;
461      }
462    
463      /** @return is this type the primitive float? */
464      @Uninterruptible
465      public final boolean isFloatType() {
466        return this == FloatType;
467      }
468    
469      /** @return is this type the primitive double? */
470      @Uninterruptible
471      public final boolean isDoubleType() {
472        return this == DoubleType;
473      }
474    
475      /** @return is this type the primitive char? */
476      @Uninterruptible
477      public final boolean isCharType() {
478        return this == CharType;
479      }
480    
481      /**
482       * @return is this type the primitive int like? ie is it held as an
483       * int on the JVM stack
484       */
485      @Uninterruptible
486      public final boolean isIntLikeType() {
487        return isBooleanType() || isByteType() || isShortType() || isIntType() || isCharType();
488      }
489    
490      /** @return is this type the class Object? */
491      @Uninterruptible
492      public final boolean isJavaLangObjectType() {
493        return this == JavaLangObjectType;
494      }
495    
496      /** @return is this type the class Throwable? */
497      @Uninterruptible
498      public final boolean isJavaLangThrowableType() {
499        return this == JavaLangThrowableType;
500      }
501    
502      /** @return is this type the class String? */
503      @Uninterruptible
504      public final boolean isJavaLangStringType() {
505        return this == JavaLangStringType;
506      }
507    
508      /**
509       * Get array type corresponding to "this" array element type.
510       */
511      public final RVMArray getArrayTypeForElementType() {
512        if (cachedElementType == null) {
513          TypeReference tr = typeRef.getArrayTypeForElementType();
514          cachedElementType = tr.resolve().asArray();
515          /*  Can't fail to resolve the type, because the element type already
516              exists (it is 'this') and the VM creates array types itself without
517              any possibility of error if the element type is already loaded. */
518        }
519        return cachedElementType;
520      }
521    
522      /**
523       * get superclass id vector (@see DynamicTypeCheck)
524       */
525      @Uninterruptible
526      public final short[] getSuperclassIds() {
527        return superclassIds;
528      }
529    
530      /**
531       * get doesImplement vector (@see DynamicTypeCheck)
532       */
533      @Uninterruptible
534      public final int[] getDoesImplement() {
535        return doesImplement;
536      }
537    
538      /**
539       * Allocate entry in types array and add it (NB resize array if it's
540       * not long enough)
541       */
542      private static synchronized int nextId(RVMType it) {
543        int ans = nextId++;
544        int column = ans >> LOG_ROW_SIZE;
545        if (column >= types.length) {
546          RVMType[][] newTypes = new RVMType[column+1][];
547          for (int i = 0; i < types.length; i++) {
548            newTypes[i] = types[i];
549          }
550          newTypes[column] = new RVMType[1<<LOG_ROW_SIZE];
551          types = newTypes;
552        }
553        types[ans >> LOG_ROW_SIZE][ans & ROW_MASK] = it;
554        return ans;
555      }
556    
557      /**
558       * How many types have been created?
559       * Only intended to be used by the bootimage writer!
560       */
561      @Uninterruptible
562      public static int numTypes() {
563        return nextId - 1;
564      }
565    
566      /**
567       * Get the type for the given id
568       */
569      @Uninterruptible
570      public static RVMType getType(int id) {
571        return types[id >> LOG_ROW_SIZE][id & ROW_MASK];
572      }
573    
574      /**
575       * Utility to create a java.lang.Class for the given type using the
576       * given type reference
577       */
578      protected static Class<?> createClassForType(RVMType type, TypeReference typeRef) {
579        if (VM.runningVM) {
580          return java.lang.JikesRVMSupport.createClass(type);
581        } else {
582          Exception x;
583          try {
584            Atom className = typeRef.getName();
585            if (className.isAnnotationClass()) {
586              return Class.forName(className.annotationClassToAnnotationInterface(), false, RVMType.class.getClassLoader());
587            } else if (className.isClassDescriptor()) {
588              return Class.forName(className.classNameFromDescriptor(), false, RVMType.class.getClassLoader());
589            } else {
590              String classNameString = className.toString();
591              if (classNameString.equals("V")) {
592                return void.class;
593              } else if(classNameString.equals("I")){
594                return int.class;
595              } else if(classNameString.equals("J")){
596                return long.class;
597              } else if(classNameString.equals("F")){
598                return float.class;
599              } else if(classNameString.equals("D")){
600                return double.class;
601              } else if(classNameString.equals("C")){
602                return char.class;
603              } else if(classNameString.equals("S")){
604                return short.class;
605              } else if(classNameString.equals("Z")){
606                return boolean.class;
607              } else if(classNameString.equals("B")){
608                return byte.class;
609              } else {
610                return Class.forName(classNameString.replace('/', '.'), false, RVMType.class.getClassLoader());
611              }
612            }
613          } catch (ClassNotFoundException e) { x = e; } catch (SecurityException e) { x = e; }
614          if (typeRef.isArrayType() && typeRef.getArrayElementType().isCodeType()) {
615            // fix up class for code array
616            return CodeArray.class;
617          } else if (!VM.runningVM) {
618            // Give a warning as this is probably a protection issue for
619            // the tool and JVM
620            VM.sysWriteln("Warning unable to find Java class for RVM type");
621            x.printStackTrace();
622            return null;
623          } else {
624            throw new Error("Unable to find Java class for RVM type", x);
625          }
626        }
627      }
628    
629      /**
630       * Find specified virtual method description.
631       * @param memberName   method name - something like "foo"
632       * @param memberDescriptor method descriptor - something like "I" or "()I"
633       * @return method description (null --> not found)
634       */
635      public final RVMMethod findVirtualMethod(Atom memberName, Atom memberDescriptor) {
636        if (VM.VerifyAssertions) VM._assert(isResolved());
637        RVMMethod[] methods = getVirtualMethods();
638        for (int i = 0, n = methods.length; i < n; ++i) {
639          RVMMethod method = methods[i];
640          if (method.getName() == memberName && method.getDescriptor() == memberDescriptor) {
641            return method;
642          }
643        }
644        return null;
645      }
646    
647      /**
648       * Return the method at the given TIB slot
649       * @param slot the slot that contains the method
650       * @return the method at that slot
651       */
652      public final RVMMethod getTIBMethodAtSlot(int slot) {
653        int index = TIB.getVirtualMethodIndex(slot);
654        RVMMethod[] methods = getVirtualMethods();
655        if (VM.VerifyAssertions) VM._assert(methods[index].getOffset().toInt() == slot << LOG_BYTES_IN_ADDRESS);
656        return methods[index];
657      }
658      // Methods implemented in Primitive, RVMArray or RVMClass
659    
660      /**
661       * Resolution status.<p>
662       * If the class/array has been "resolved", then size and offset information is
663       * available by which the compiler can generate code to access this
664       * class/array's
665       * fields/methods via direct loads/stores/calls (rather than generating
666       * code to access fields/methods symbolically, via dynamic linking stubs).<p>
667       * Primitives are always treated as "resolved".
668       */
669      @Uninterruptible
670      public abstract boolean isResolved();
671    
672      /**
673       * Instantiation status.<p>
674       * If the class/array has been "instantiated",
675       * then all its methods have been compiled
676       * and its type information block has been placed in the JTOC.<p>
677       * Primitives are always treated as "instantiated".
678       */
679      @Uninterruptible
680      public abstract boolean isInstantiated();
681    
682      /**
683       * Initialization status.<p>
684       * If the class has been "initialized",
685       * then its {@code <clinit>} method has been executed.
686       * Arrays have no {@code <clinit>} methods so they become
687       * "initialized" immediately upon "instantiation".<p>
688       * Primitives are always treated as "initialized".
689       */
690      @Uninterruptible
691      public abstract boolean isInitialized();
692    
693      /**
694       * Only intended to be used by the BootImageWriter
695       */
696      public abstract void markAsBootImageClass();
697    
698      /**
699       * Is this class part of the virtual machine's boot image?
700       */
701      @Uninterruptible
702      public abstract boolean isInBootImage();
703    
704      /**
705       * Get the offset in instances of this type assigned to the thin lock word.
706       * Offset.max() if instances of this type do not have thin lock words.
707       */
708      @Uninterruptible
709      public abstract Offset getThinLockOffset();
710    
711      /**
712       * Is this is an instance of RVMClass?
713       * @return whether or not this is an instance of RVMClass?
714       */
715      @Uninterruptible
716      public abstract boolean isClassType();
717    
718      /**
719       * Is this an instance of RVMArray?
720       * @return whether or not this is an instance of RVMArray?
721       */
722      @Uninterruptible
723      public abstract boolean isArrayType();
724    
725      /**
726       * Is this a primitive type?
727       * @return whether or not this is a primitive type
728       */
729      @Uninterruptible
730      public abstract boolean isPrimitiveType();
731    
732      /**
733       * Is this an unboxed type?
734       * @return whether or not this is an unboxed type
735       */
736      @Uninterruptible
737      public abstract boolean isUnboxedType();
738    
739      /**
740       * Is this a reference type?
741       * @return whether or not this is a reference (ie non-primitive) type.
742       */
743      @Uninterruptible
744      public abstract boolean isReferenceType();
745    
746      /**
747       * @return whether type can be assigned to things of this RVMType
748       */
749      public boolean isAssignableFrom(RVMType type) {
750        return this == type || RuntimeEntrypoints.isAssignableWith(this, type);
751      }
752    
753      /**
754       * Space required when this type is stored on the stack
755       * (or as a field), in words.
756       * Ie. 0, 1, or 2 words:
757       * <ul>
758       * <li> reference types (classes and arrays) require 1 word
759       * <li> void types require 0 words
760       * <li> long and double types require 2 words
761       * <li> all other primitive types require 1 word
762       * </ul>
763       */
764      @Uninterruptible
765      public abstract int getStackWords();
766    
767      /**
768       * Number of bytes in memory required to represent the type
769       */
770      @Uninterruptible
771      public abstract int getMemoryBytes();
772    
773      /**
774       * Cause resolution to take place.
775       * This will cause slots to be allocated in the JTOC.
776       */
777      public abstract void resolve();
778    
779      /**
780       * This method is only called by the bootimage writer.
781       * It is called after {@link #resolve()} has been called on all
782       * bootimage types but before {@link #instantiate()} has been called
783       * on any bootimage type.
784       * This provides a hook to compute various summaries that cannot be computed before types
785       * are resolved.
786       */
787      public abstract void allBootImageTypesResolved();
788    
789      /**
790       * Cause instantiation to take place.
791       * This will cause the class's methods to be compiled and slots in the
792       * JTOC to be filled-in.
793       */
794      public abstract void instantiate();
795    
796      /**
797       * Cause initialization to take place.
798       * This will cause the class's {@code <clinit>} method to be executed.
799       */
800      public abstract void initialize();
801    
802      /**
803       * Does this type override java.lang.Object.finalize()?
804       */
805      @Uninterruptible
806      public abstract boolean hasFinalizer();
807    
808      /**
809       * Static fields of this class/array type.
810       */
811      public abstract RVMField[] getStaticFields();
812    
813      /**
814       * Non-static fields of this class/array type
815       * (composed with supertypes, if any).
816       */
817      public abstract RVMField[] getInstanceFields();
818    
819      /**
820       * Statically dispatched methods of this class/array type.
821       */
822      public abstract RVMMethod[] getStaticMethods();
823    
824      /**
825       * Virtually dispatched methods of this class/array type
826       * (composed with supertypes, if any).
827       */
828      public abstract RVMMethod[] getVirtualMethods();
829    
830      /**
831       * Runtime type information for this class/array type.
832       */
833      @Uninterruptible
834      public abstract TIB getTypeInformationBlock();
835    
836      /**
837       * Set the specialized method for a class or array.
838       */
839      public final void setSpecializedMethod(int id, CodeArray code) {
840        getTypeInformationBlock().setSpecializedMethod(id, code);
841      }
842    
843      /**
844       * The memory manager's allocator id for this type.
845       */
846      private int mmAllocator;
847    
848      /**
849       * GC metadata for this type.
850       *
851       * In a primitive array this field points to a zero-length array.
852       *
853       * In a reference array this field is null.
854       *
855       * In a class with pointers, it contains the offsets of
856       * reference-containing instance fields
857       */
858      protected int[] referenceOffsets;
859    
860      /**
861       * Record the allocator information the memory manager holds about this type.
862       *
863       * @param allocator the allocator to record
864       */
865      public final void setMMAllocator(int allocator) {
866        this.mmAllocator = allocator;
867      }
868    
869      /**
870       * This returns the allocator id as supplied by the memory manager.
871       * The method is located here as this is the only common superclass of RVMArray
872       * and RVMClass, and due to performance reasons this needs to be a non-abstract
873       * method. For Primitive this field is unused.
874       *
875       * @return the allocator id previously recorded.
876       */
877      @Uninterruptible
878      @Inline
879      public final int getMMAllocator() {
880        return mmAllocator;
881      }
882    
883      /**
884       * Is this field a type that must never move?
885       */
886      public boolean isNonMoving() {
887        return hasNonMovingAnnotation();
888      }
889    
890      /**
891       * Offsets of reference-containing instance fields of this class type.
892       * Offsets are with respect to object pointer -- see RVMField.getOffset().
893       */
894      @Uninterruptible
895      public int[] getReferenceOffsets() {
896        if (VM.VerifyAssertions) VM._assert(isResolved());
897        return referenceOffsets;
898      }
899    }