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