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 java.lang.annotation.Annotation;
016    import java.lang.annotation.Inherited;
017    
018    import org.jikesrvm.Callbacks;
019    import org.jikesrvm.Constants;
020    import org.jikesrvm.VM;
021    import org.jikesrvm.compilers.common.CompiledMethod;
022    import org.jikesrvm.compilers.opt.inlining.ClassLoadingDependencyManager;
023    import org.jikesrvm.mm.mminterface.HandInlinedScanning;
024    import org.jikesrvm.mm.mminterface.AlignmentEncoding;
025    import org.jikesrvm.mm.mminterface.MemoryManager;
026    import org.jikesrvm.objectmodel.FieldLayoutContext;
027    import org.jikesrvm.objectmodel.IMT;
028    import org.jikesrvm.objectmodel.ObjectModel;
029    import org.jikesrvm.objectmodel.TIB;
030    import org.jikesrvm.runtime.Magic;
031    import org.jikesrvm.runtime.RuntimeEntrypoints;
032    import org.jikesrvm.runtime.StackBrowser;
033    import org.jikesrvm.runtime.Statics;
034    import org.vmmagic.pragma.NonMoving;
035    import org.vmmagic.pragma.Pure;
036    import org.vmmagic.pragma.Uninterruptible;
037    import org.vmmagic.unboxed.Offset;
038    
039    /**
040     * Description of a java "class" type.<p>
041     *
042     * This description is read from a ".class" file as classes/field/methods
043     * referenced by the running program need to be bound in to the running image.
044     *
045     * @see RVMType
046     * @see RVMArray
047     * @see Primitive
048     * @see UnboxedType
049     */
050    @NonMoving
051    public final class RVMClass extends RVMType implements Constants, ClassLoaderConstants {
052    
053      /** Flag for closed world testing */
054      public static boolean classLoadingDisabled = false;
055    
056      /**
057       * The constant pool holds constants used by the class and the Java
058       * bytecodes in the methods associated with this class. This
059       * constant pool isn't that from the class file, instead it has been
060       * processed during class loading (see {@link ClassFileReader#readClass}). The loaded
061       * class' constant pool has 3 bits of type information (such as
062       * (see {@link ClassLoaderConstants#CP_INT})), the rest of the int holds data as follows:
063       *
064       * <ul>
065       * <li>utf: value is a UTF atom identifier</li>
066       * <li>int, long, float, double, string: value is an offset in the
067       *     JTOC</li>
068       * <li>member: value is a member reference identifier</li>
069       * <li>class: value is a type reference identifier. NB this means
070       *     that class literal bytecodes must first convert the identifier
071       *     in to a JTOC offset.</li>
072       * </ul>
073       */
074      private final int[] constantPool;
075      /** {@link ClassLoaderConstants} */
076      private final short modifiers;
077      /** Super class of this class */
078      private final RVMClass superClass;
079      /**
080       * Non-final list of sub-classes. Classes added as sub-classes are
081       * loaded.
082       */
083      private RVMClass[] subClasses;
084      /** Interfaces supported by this class */
085      private final RVMClass[] declaredInterfaces;
086      /** Fields of this class */
087      private final RVMField[] declaredFields;
088      /** Methods of this class */
089      private final RVMMethod[] declaredMethods;
090      /** Declared inner classes, may be null */
091      private final TypeReference[] declaredClasses;
092      /** The outer class, or null if this is not a inner/nested class */
093      private final TypeReference declaringClass;
094      /** The enclosing class if this is a local class */
095      private final TypeReference enclosingClass;
096      /** The enclosing method if this is a local class */
097      private final MethodReference enclosingMethod;
098      /** Name of file .class file was compiled from, may be null */
099      private final Atom sourceName;
100      /**
101       * The signature is a string representing the generic type for this
102       * class declaration, may be null
103       */
104      private final Atom signature;
105      /**
106       * Class initializer method, null if no method or if class is
107       * initialized (ie class initializer method has been run)
108       */
109      private RVMMethod classInitializerMethod;
110    
111      /**
112       * current class-loading stage (loaded, resolved, instantiated,
113       * initializing or initialized)
114       */
115      private byte state;
116    
117      //
118      // The following are valid only when "state >= CLASS_RESOLVED".
119      //
120    
121      // --- Field size and offset information --- //
122    
123      /** fields shared by all instances of class  */
124      private RVMField[] staticFields;
125    
126      /** fields distinct for each instance of class */
127      private RVMField[] instanceFields;
128    
129      /** Total size of per-instance data, in bytes  */
130      private int instanceSize;
131    
132      /** The desired alignment for instances of this type. */
133      private int alignment;
134    
135      /**
136       * A field layout helper - used to keep context regarding field layouts.
137       * Managed by the field layout objects in the ObjectModel.
138       */
139      private FieldLayoutContext fieldLayoutContext = null;
140    
141      // --- Method-dispatching information --- //
142    
143      /** static methods of class */
144      private RVMMethod[] staticMethods;
145    
146      /** constructor methods of class  */
147      private RVMMethod[] constructorMethods;
148    
149      /** virtual methods of class */
150      private RVMMethod[] virtualMethods;
151    
152      /**
153       * Do objects of this class have a finalizer method?
154       */
155      private boolean hasFinalizer;
156    
157      /** type and virtual method dispatch table for class */
158      private TIB typeInformationBlock;
159    
160      // --- Memory manager support --- //
161    
162      /**
163       * Is this class type in the bootimage? Types in the boot image can
164       * be initialized prior to execution (therefore removing runtime
165       * resolution).
166       */
167      private boolean inBootImage;
168    
169      /**
170       * At what offset is the thin lock word to be found in instances of
171       * objects of this type?  A value of -1 indicates that the instances of
172       * this type do not have inline thin locks.
173       */
174      private Offset thinLockOffset;
175    
176      /** Reference Count GC: is this type acyclic?  */
177      private boolean acyclic;
178    
179      /** Cached set of inherited and declared annotations. */
180      private Annotation[] annotations;
181    
182      /** Set of objects that are cached here to ensure they are not collected by GC **/
183      private Object[] objectCache;
184    
185      /** The imt for this class **/
186      @SuppressWarnings("unused")
187      private IMT imt;
188    
189      // --- Assertion support --- //
190      /**
191       * Are assertions enabled on this class?
192       */
193      private final boolean desiredAssertionStatus;
194    
195      // --- General purpose functions --- //
196    
197      /**
198       * Name - something like "java.lang.String".
199       */
200      @Override
201      @Pure
202      public String toString() {
203        return getDescriptor().classNameFromDescriptor();
204      }
205    
206      /**
207       * Package name - something like "java.lang".
208       * @return package name or the empty string if the class is a member of the unnamed package
209       */
210      public String getPackageName() {
211        String className = toString();
212        int lastDot = className.lastIndexOf(".");
213        return (lastDot >= 0) ? className.substring(0, lastDot) : "";
214      }
215    
216      /**
217       * @return 1
218       */
219      @Override
220      @Pure
221      @Uninterruptible
222      public int getStackWords() {
223        return 1;
224      }
225    
226      @Override
227      @Pure
228      @Uninterruptible
229      public int getMemoryBytes() {
230        return BYTES_IN_ADDRESS;
231      }
232    
233      /**
234       * An "interface" description rather than a "class" description?
235       */
236      @Uninterruptible
237      public boolean isInterface() {
238        return (modifiers & ACC_INTERFACE) != 0;
239      }
240    
241      /**
242       * Usable from other packages?
243       */
244      @Uninterruptible
245      public boolean isPublic() {
246        return (modifiers & ACC_PUBLIC) != 0;
247      }
248    
249      /**
250       * Non-subclassable?
251       */
252      @Uninterruptible
253      public boolean isFinal() {
254        return (modifiers & ACC_FINAL) != 0;
255      }
256    
257      /**
258       * Non-instantiable?
259       */
260      @Uninterruptible
261      public boolean isAbstract() {
262        return (modifiers & ACC_ABSTRACT) != 0;
263      }
264    
265      /**
266       * Use new-style "invokespecial" semantics for method calls in this class?
267       */
268      @Uninterruptible
269      public boolean isSpecial() {
270        return (modifiers & ACC_SUPER) != 0;
271      }
272    
273      /**
274       * Not present in source code file?
275       */
276      public boolean isSynthetic() {
277        return (modifiers & ACC_SYNTHETIC) != 0;
278      }
279    
280      /**
281       * Is enumeration?
282       */
283      public boolean isEnum() {
284        return (modifiers & ACC_ENUM) != 0;
285      }
286    
287      /**
288       * Annotation type
289       */
290      public boolean isAnnotation() {
291        return (modifiers & ACC_ANNOTATION) != 0;
292      }
293    
294      /**
295       * @return true if this is a representation of an anonymous class
296       */
297      public boolean isAnonymousClass() {
298        if (enclosingClass == null || enclosingClass.peekType() == null) return false;
299        for(TypeReference t: enclosingClass.peekType().asClass().getDeclaredClasses()) {
300          if (t == typeRef) return false;
301        }
302        return true;
303      }
304    
305      /**
306       * @return {@code true} if this is a representation of a local class, ie
307       * local to a block of code.
308       */
309      public boolean isLocalClass() {
310        return enclosingMethod != null;
311      }
312    
313      /**
314       * @return {@code true} if this is a representation of a member class
315       */
316      public boolean isMemberClass() {
317        return ((declaringClass != null) && ((modifiers & ACC_STATIC) == 0));
318      }
319      /**
320       * @return {@code true} if this an object of this class could be assigned to Throwable
321       */
322      public boolean isThrowable() {
323        return (getTypeRef() == TypeReference.JavaLangThrowable) ||
324        RuntimeEntrypoints.isAssignableWith(TypeReference.JavaLangThrowable.resolve(), this);
325      }
326      /**
327       * Get the modifiers associated with this class {@link
328       * ClassLoaderConstants}.
329       */
330      public int getModifiers() {
331        return modifiers & APPLICABLE_TO_CLASSES;
332      }
333    
334      /**
335       * Generic type information for class
336       */
337      public Atom getSignature() {
338        return signature;
339      }
340    
341      /**
342       * Name of source file from which class was compiled -
343       * something like "c:\java\src\java\lang\Object.java".
344       * ({@code null} --> "unknown - wasn't recorded by compiler").
345       */
346      public Atom getSourceName() {
347        return sourceName;
348      }
349    
350      /**
351       * Superclass of this class ({@code null} means "no superclass",
352       * i.e. class is "java/lang/Object").
353       */
354      @Uninterruptible
355      public RVMClass getSuperClass() {
356        return superClass;
357      }
358    
359      /**
360       * Currently loaded classes that "extend" this class.
361       */
362      @Uninterruptible
363      public RVMClass[] getSubClasses() {
364        return subClasses;
365      }
366    
367      /**
368       * Interfaces implemented directly by this class
369       * (ie. not including superclasses).
370       */
371      @Uninterruptible
372      public RVMClass[] getDeclaredInterfaces() {
373        return declaredInterfaces;
374      }
375    
376      /**
377       * Fields defined directly by this class (i.e. not including superclasses).
378       */
379      @Uninterruptible
380      public RVMField[] getDeclaredFields() {
381        return declaredFields;
382      }
383    
384      /**
385       * Does this class directly define a final instance field (has implications for JMM).
386       */
387      public boolean declaresFinalInstanceField() {
388        for (RVMField f : declaredFields) {
389          if (f.isFinal() && !f.isStatic()) return true;
390        }
391        return false;
392      }
393    
394      /**
395       * Methods defined directly by this class (i.e. not including superclasses).
396       */
397      @Uninterruptible
398      public RVMMethod[] getDeclaredMethods() {
399        return declaredMethods;
400      }
401    
402      /**
403       * Declared inner and static member classes.
404       */
405      public TypeReference[] getDeclaredClasses() {
406        return declaredClasses;
407      }
408    
409      /**
410       * Class that declared this class, or null if this is not an
411       * inner/nested class.
412       */
413      public TypeReference getDeclaringClass() {
414        return declaringClass;
415      }
416    
417      /**
418       * Class that immediately encloses this class, or null if this is not an
419       * inner/nested class.
420       */
421      public TypeReference getEnclosingClass() {
422        return enclosingClass;
423      }
424    
425      /**
426       * Set the resolvedMember in all declared members.
427       */
428      void setResolvedMembers() {
429        for(RVMField field: declaredFields) {
430          /* Make all declared fields appear resolved */
431          field.getMemberRef().asFieldReference().setResolvedMember(field);
432        }
433        for(RVMMethod method: declaredMethods) {
434          /* Make all declared methods appear resolved */
435          method.getMemberRef().asMethodReference().setResolvedMember(method);
436        }
437        if (virtualMethods != null) {
438          /* Possibly created Miranda methods */
439          for(RVMMethod method: virtualMethods) {
440            if (method.getDeclaringClass() == this) {
441              method.getMemberRef().asMethodReference().setResolvedMember(method);
442            }
443          }
444        }
445      }
446    
447      /**
448       * Static initializer method for this class ({@code null} -> no static initializer
449       *  or initializer already been run).
450       */
451      @Uninterruptible
452      public RVMMethod getClassInitializerMethod() {
453        return classInitializerMethod;
454      }
455    
456      @Override
457      Annotation[] getAnnotationsInternal() {
458        final RVMClass parent = getSuperClass();
459        if (parent == null) {
460          return super.getAnnotationsInternal();
461        }
462        if (annotations == null) {
463          final Annotation[] declared = getDeclaredAnnotations();
464          // Not synchronized as it does not matter if occasionally we create two cached copies
465          final Annotation[] parentAnnotations = parent.getAnnotations();
466          int rejected = 0;
467          for (int i = 0; i < parentAnnotations.length; i++) {
468            final Annotation pa = parentAnnotations[i];
469            final Class<? extends Annotation> paType = pa.annotationType();
470            if (!paType.isAnnotationPresent(Inherited.class)) {
471              parentAnnotations[i] = null;
472              rejected++;
473            } else {
474              for (final Annotation a : declared) {
475                if (a.annotationType().equals(paType)) {
476                  parentAnnotations[i] = null;
477                  rejected++;
478                  break;
479                }
480              }
481            }
482          }
483          final Annotation[] cache = new Annotation[declared.length + parentAnnotations.length - rejected];
484          System.arraycopy(declared, 0, cache, 0, declared.length);
485          int index = declared.length;
486          for (final Annotation pa : parentAnnotations) {
487            if (pa != null) cache[index++] = pa;
488          }
489          annotations = cache;
490        }
491        return annotations;
492      }
493    
494      /**
495       * Find description of a field of this class.
496       * @param fieldName field name - something like "foo"
497       * @param fieldDescriptor field descriptor - something like "I"
498       * @return description ({@code null} --> not found)
499       */
500      public RVMField findDeclaredField(Atom fieldName, Atom fieldDescriptor) {
501        for (RVMField field : declaredFields) {
502          if (field.getName() == fieldName && field.getDescriptor() == fieldDescriptor) {
503            return field;
504          }
505        }
506        return null;
507      }
508    
509      /**
510       * Find description of a field of this class. NB. ignores descriptor.
511       * @param fieldName field name - something like "foo"
512       * @return description ({@code null} --> not found)
513       */
514      public RVMField findDeclaredField(Atom fieldName) {
515        for (RVMField field : declaredFields) {
516          if (field.getName() == fieldName) {
517            return field;
518          }
519        }
520        return null;
521      }
522    
523      /**
524       * Find description of a method of this class.
525       * @param methodName method name - something like "foo"
526       * @param methodDescriptor method descriptor - something like "()I"
527       * @return description (null --> not found)
528       */
529      public RVMMethod findDeclaredMethod(Atom methodName, Atom methodDescriptor) {
530        for (RVMMethod method : declaredMethods) {
531          if (method.getName() == methodName && method.getDescriptor() == methodDescriptor) {
532            return method;
533          }
534        }
535        return null;
536      }
537    
538      /**
539       * Find the first description of a method of this class.
540       * @param methodName method name - something like "foo"
541       * @return description (null --> not found)
542       */
543      public RVMMethod findDeclaredMethod(Atom methodName) {
544        for (RVMMethod method : declaredMethods) {
545          if (method.getName() == methodName) {
546            return method;
547          }
548        }
549        return null;
550      }
551    
552      /**
553       * Find description of "public static void main(String[])"
554       * method of this class.
555       * @return description ({@code null} --> not found)
556       */
557      public RVMMethod findMainMethod() {
558        Atom mainName = Atom.findOrCreateAsciiAtom(("main"));
559        Atom mainDescriptor = Atom.findOrCreateAsciiAtom(("([Ljava/lang/String;)V"));
560        RVMMethod mainMethod = this.findDeclaredMethod(mainName, mainDescriptor);
561    
562        if (mainMethod == null || !mainMethod.isPublic() || !mainMethod.isStatic()) {
563          // no such method
564          return null;
565        }
566        return mainMethod;
567      }
568    
569      /**
570       * Add the given cached object.
571       */
572      public synchronized void addCachedObject(Object o) {
573        Object[] newObjectCache;
574        if (objectCache == null) {
575          newObjectCache = new Object[1];
576        } else {
577          newObjectCache = new Object[objectCache.length + 1];
578          for (int i=0; i < objectCache.length; i++) {
579            newObjectCache[i] = objectCache[i];
580          }
581        }
582        newObjectCache[newObjectCache.length - 1] = o;
583        objectCache = newObjectCache;
584      }
585    
586      /**
587       * Set the imt object.
588       */
589      public void setIMT(IMT imt) {
590        this.imt = imt;
591      }
592    
593      //
594      // Constant pool accessors.
595      //
596      // The constant pool holds literals and external references used by
597      // the bytecodes of this class's methods.
598      // Items are fetched by specifying their "constant pool index".
599      //
600    
601      /**
602       * Get offset of a literal constant, in bytes.
603       * Offset is with respect to virtual machine's "table of contents" (HTOC).
604       */
605      public Offset getLiteralOffset(int constantPoolIndex) {
606        return ClassFileReader.getLiteralOffset(this.constantPool, constantPoolIndex);
607      }
608    
609      /**
610       * Get description of a literal constant.
611       */
612      public byte getLiteralDescription(int constantPoolIndex) {
613        int cpValue = constantPool[constantPoolIndex];
614        byte type = ClassFileReader.unpackCPType(cpValue);
615        return type;
616      }
617    
618      /**
619       * Get contents of a "typeRef" constant pool entry.
620       * @return type that was referenced
621       */
622      @Uninterruptible
623      public TypeReference getTypeRef(int constantPoolIndex) {
624        return ClassFileReader.getTypeRef(constantPool, constantPoolIndex);
625      }
626    
627      /**
628       * Get contents of a "methodRef" constant pool entry.
629       */
630      @Uninterruptible
631      public MethodReference getMethodRef(int constantPoolIndex) {
632        return ClassFileReader.getMethodRef(constantPool, constantPoolIndex);
633      }
634    
635      /**
636       * Get contents of a "fieldRef" constant pool entry.
637       */
638      @Uninterruptible
639      public FieldReference getFieldRef(int constantPoolIndex) {
640        int cpValue = constantPool[constantPoolIndex];
641        if (VM.VerifyAssertions) VM._assert(ClassFileReader.unpackCPType(cpValue) == CP_MEMBER);
642        return (FieldReference) MemberReference.getMemberRef(ClassFileReader.unpackUnsignedCPValue(cpValue));
643      }
644    
645      /**
646       * Get contents of a "utf" constant pool entry.
647       */
648      @Uninterruptible
649      Atom getUtf(int constantPoolIndex) {
650        int cpValue = constantPool[constantPoolIndex];
651        if (VM.VerifyAssertions) VM._assert(ClassFileReader.unpackCPType(cpValue) == CP_UTF);
652        return Atom.getAtom(ClassFileReader.unpackUnsignedCPValue(cpValue));
653      }
654    
655      /**
656       * Should the methods of this class be compiled with special
657       * register save/restore logic?
658       * @see org.vmmagic.pragma.DynamicBridge
659       */
660      @Uninterruptible
661      public boolean hasDynamicBridgeAnnotation() {
662        return isAnnotationDeclared(TypeReference.DynamicBridge);
663      }
664    
665      /**
666       * The methods of this class are only called from native code,
667       * they are compiled with
668       * a special prolog to interface with the native stack frame.
669       */
670      @Uninterruptible
671      public boolean hasBridgeFromNativeAnnotation() {
672        return isAnnotationDeclared(TypeReference.NativeBridge);
673      }
674    
675      /**
676       * Should the methods of this class save incoming registers ?
677       * @see org.vmmagic.pragma.SaveVolatile
678       */
679      public boolean hasSaveVolatileAnnotation() {
680        return isAnnotationDeclared(TypeReference.SaveVolatile);
681      }
682    
683      //--------------------------------------------------------------------//
684      // The following are available after the class has been "resolved".   //
685      //--------------------------------------------------------------------//
686    
687      /**
688       * Does this class override java.lang.Object.finalize()?
689       */
690      @Override
691      @Pure
692      @Uninterruptible
693      public boolean hasFinalizer() {
694        if (VM.VerifyAssertions) VM._assert(isResolved());
695        return hasFinalizer;
696      }
697    
698      /**
699       * Static fields of this class.
700       * Values in these fields are shared by all class instances.
701       */
702      @Override
703      @Pure
704      public RVMField[] getStaticFields() {
705        if (VM.VerifyAssertions) VM._assert(isResolved());
706        return staticFields;
707      }
708    
709      /**
710       * Non-static fields of this class (composed with supertypes, if any).
711       * Values in these fields are distinct for each class instance.
712       */
713      @Override
714      @Pure
715      public RVMField[] getInstanceFields() {
716        if (VM.VerifyAssertions) VM._assert(isResolved());
717        return instanceFields;
718      }
719    
720      /**
721       * Statically dispatched methods of this class.
722       */
723      @Override
724      @Pure
725      public RVMMethod[] getStaticMethods() {
726        if (VM.VerifyAssertions) VM._assert(isResolved());
727        return staticMethods;
728      }
729    
730      /**
731       * Constructors (<init>) methods of this class.
732       */
733      @Pure
734      public RVMMethod[] getConstructorMethods() {
735        if (VM.VerifyAssertions) VM._assert(isResolved(), "Error class " + this + " is not resolved but " + state);
736        return constructorMethods;
737      }
738    
739      /**
740       * Virtually dispatched methods of this class
741       * (composed with supertypes, if any).
742       */
743      @Override
744      @Pure
745      public RVMMethod[] getVirtualMethods() {
746        if (VM.VerifyAssertions) VM._assert(isResolved());
747        return virtualMethods;
748      }
749    
750      /**
751       * @return All of the interfaces implemented by this class either
752       * directly or by inheritance from superclass and superinterfaces
753       * recursively.
754       */
755      @Pure
756      public RVMClass[] getAllImplementedInterfaces() {
757        if (VM.VerifyAssertions) VM._assert(isResolved());
758        int count = 0;
759        int[] doesImplement = getDoesImplement();
760        for (int mask : doesImplement) {
761          while (mask != 0) {
762            count++;
763            mask &= (mask - 1); // clear lsb 1 bit
764          }
765        }
766        if (count == 0) return emptyVMClass;
767        RVMClass[] ans = new RVMClass[count];
768        for (int i = 0, idx = 0; i < doesImplement.length; i++) {
769          int mask = doesImplement[i];
770          if (mask != 0) {
771            for (int j = 0; j < 32; j++) {
772              if ((mask & (1 << j)) != 0) {
773                int id = 32 * i + j;
774                ans[idx++] = RVMClass.getInterface(id);
775              }
776            }
777          }
778        }
779        return ans;
780      }
781    
782      /**
783       * Total size, in bytes, of an instance of this class
784       * (including object header).
785       */
786      @Uninterruptible
787      public int getInstanceSize() {
788        if (VM.VerifyAssertions) VM._assert(isResolved());
789        return instanceSize;
790      }
791    
792      /**
793       * Total size, in bytes, of an instance of this class (including
794       * object header). Doesn't perform any verification.
795       */
796      @Uninterruptible
797      public int getInstanceSizeInternal() {
798        return instanceSize;
799      }
800    
801      /**
802       * Set the size of the instance. Only meant to be called from
803       * ObjectModel et al. must be called when lock on class object
804       * is already held (ie from resolve).
805       */
806      @Uninterruptible
807      public void setInstanceSizeInternal(int size) {
808        instanceSize = size;
809      }
810    
811      /**
812       * @return number of fields that are non-final
813       */
814      public int getNumberOfNonFinalReferences() {
815        int count = 0;
816        for(RVMField field: declaredFields) {
817          if (!field.isFinal()) {
818            count++;
819          }
820        }
821        return count;
822      }
823    
824      /**
825       * Set object representing available holes in the field layout
826       */
827      public FieldLayoutContext getFieldLayoutContext() {
828        return fieldLayoutContext;
829      }
830    
831      /**
832       * Set object representing available holes in the field layout
833       */
834      public void setFieldLayoutContext(FieldLayoutContext newLayout) {
835        fieldLayoutContext = isFinal() ? null : newLayout;
836      }
837    
838      /**
839       * @return alignment for instances of this class type
840       */
841      @Uninterruptible
842      public int getAlignment() {
843        if (BYTES_IN_ADDRESS == BYTES_IN_DOUBLE) {
844          return BYTES_IN_ADDRESS;
845        } else {
846          return alignment;
847        }
848      }
849    
850      /**
851       * Set the alignment for instances of this class type
852       */
853      public void setAlignment(int align) {
854        if (BYTES_IN_ADDRESS != BYTES_IN_DOUBLE) {
855          if (VM.VerifyAssertions) VM._assert(align >= alignment);
856          alignment = align;
857        }
858      }
859    
860      /**
861       * Find specified static method description.
862       * @param memberName method name - something like "foo"
863       * @param memberDescriptor method descriptor - something like "I" or "()I"
864       * @return method description (null --> not found)
865       */
866      @Pure
867      public RVMMethod findStaticMethod(Atom memberName, Atom memberDescriptor) {
868        if (VM.VerifyAssertions) VM._assert(isResolved());
869        for (RVMMethod method : getStaticMethods()) {
870          if (method.getName() == memberName && method.getDescriptor() == memberDescriptor) {
871            return method;
872          }
873        }
874        return null;
875      }
876    
877      /**
878       * Find specified initializer method description.
879       * @param  memberDescriptor  init method descriptor - something like "(I)V"
880       * @return method description (null --> not found)
881       */
882      @Pure
883      public RVMMethod findInitializerMethod(Atom memberDescriptor) {
884        if (VM.VerifyAssertions) VM._assert(isResolved());
885        for (RVMMethod method : getConstructorMethods()) {
886          if (method.getDescriptor() == memberDescriptor) {
887            return method;
888          }
889        }
890        return null;
891      }
892    
893      /**
894       * Runtime type information for this class type.
895       */
896      @Override
897      @Uninterruptible
898      public TIB getTypeInformationBlock() {
899        if (VM.VerifyAssertions) VM._assert(isResolved());
900        return typeInformationBlock;
901      }
902    
903      //--------------------------------------------------------------------//
904      //                     Miscellaneous queries.                         //
905      //---------------------------------------------------------------------//
906    
907      /**
908       * Support for user-written class loaders:
909       * It's required to find the classloader of the class
910       * whose method requires another class to be loaded;
911       * the initiating loader of the required class is the
912       * defining loader of the requiring class.
913       *
914       *
915       * @param skip specifies the number of frames back from the
916       *             caller to the method whose class's loader is required
917       */
918      public static ClassLoader getClassLoaderFromStackFrame(int skip) {
919        skip++; // account for stack frame of this function
920        StackBrowser browser = new StackBrowser();
921        VM.disableGC();
922        browser.init();
923        while (skip-- > 0) browser.up();
924        VM.enableGC();
925        return browser.getClassLoader();
926      }
927    
928      /**
929       * Used for accessibility checks in reflection code.
930       * Find the class of the method that corresponds to the requested frame.
931       *
932       * @param skip   Specifies the number of frames back from the
933       *               caller to the method whose class is required
934       */
935      public static RVMClass getClassFromStackFrame(int skip) {
936        skip++; // account for stack frame of this function
937        StackBrowser browser = new StackBrowser();
938        VM.disableGC();
939        browser.init();
940        while (skip-- > 0) browser.up();
941        VM.enableGC();
942        return browser.getCurrentClass();
943      }
944    
945      /**
946       * @return whether or not assertions should be enabled
947       */
948      @Override
949      @Pure
950      public boolean getDesiredAssertionStatus() {
951        return desiredAssertionStatus;
952      }
953    
954      //--------------------------------------------------------------------//
955      //      Load, Resolve, Instantiate, and Initialize                    //
956      //--------------------------------------------------------------------//
957    
958      /**
959       * Construct a class from its constituent loaded parts
960       *
961       * @param typeRef the type reference that was resolved to this class
962       * @param constantPool array of ints encoding constant value
963       * @param modifiers {@link org.jikesrvm.classloader.ClassLoaderConstants}
964       * @param superClass parent of this class
965       * @param declaredInterfaces array of interfaces this class implements
966       * @param declaredFields fields of the class
967       * @param declaredMethods methods of the class
968       * @param declaredClasses declared inner classes
969       * @param declaringClass outer class if an inner class
970       * @param sourceName source file name
971       * @param classInitializerMethod handle to class initializer method
972       * @param signature the generic type name for this class
973       * @param annotations array of runtime visible annotations
974       */
975      RVMClass(TypeReference typeRef, int[] constantPool, short modifiers, RVMClass superClass,
976               RVMClass[] declaredInterfaces, RVMField[] declaredFields, RVMMethod[] declaredMethods,
977               TypeReference[] declaredClasses, TypeReference declaringClass, TypeReference enclosingClass,
978               MethodReference enclosingMethod, Atom sourceName, RVMMethod classInitializerMethod,
979               Atom signature, RVMAnnotation[] annotations) {
980        super(typeRef, 0, annotations);
981        if (VM.VerifyAssertions) VM._assert(!getTypeRef().isUnboxedType());
982        if (VM.VerifyAssertions && null != superClass) VM._assert(!superClass.getTypeRef().isUnboxedType());
983    
984        // final fields
985        this.constantPool = constantPool;
986        this.modifiers = modifiers;
987        this.superClass = superClass;
988        this.declaredInterfaces = declaredInterfaces;
989        this.declaredFields = declaredFields;
990        this.declaredMethods = declaredMethods;
991        this.declaredClasses = declaredClasses;
992        this.declaringClass = declaringClass;
993        this.enclosingClass = enclosingClass;
994        this.enclosingMethod = enclosingMethod;
995        this.sourceName = sourceName;
996        this.classInitializerMethod = classInitializerMethod;
997        this.signature = signature;
998    
999        // non-final fields
1000        this.subClasses = emptyVMClass;
1001        state = CLASS_LOADED;
1002    
1003        // we're about to leak a reference to 'this' force memory to be
1004        // consistent
1005        Magic.sync();
1006    
1007        if (superClass != null) {
1008          // MUST wait until end of constructor to 'publish' the subclass link.
1009          // If we do this earlier, then people can see an incomplete RVMClass object
1010          // by traversing the subclasses of our superclass!
1011          superClass.addSubClass(this);
1012        }
1013    
1014        this.desiredAssertionStatus = RVMClassLoader.getDesiredAssertionStatus(this);
1015    
1016        Callbacks.notifyClassLoaded(this);
1017    
1018        if (VM.TraceClassLoading && VM.runningVM) {
1019          VM.sysWriteln("RVMClass: (end)   load file " + typeRef.getName());
1020        }
1021        if (VM.verboseClassLoading) VM.sysWrite("[Loaded " + toString() + "]\n");
1022      }
1023    
1024      /**
1025       * {@inheritDoc} Space in the JTOC is allocated for static fields,
1026       * static methods and constructors. Moreover, this method  generates size
1027       * and offset information for members of this class.<p>
1028       *
1029       * Side effects: superclasses and superinterfaces are resolved.
1030       */
1031      @Override
1032      public synchronized void resolve() {
1033        if (isResolved()) return;
1034        if (VM.TraceClassLoading && VM.runningVM) VM.sysWriteln("RVMClass: (begin) resolve " + this);
1035        if (VM.VerifyAssertions) VM._assert(state == CLASS_LOADED);
1036    
1037        // Resolve superclass and super interfaces
1038        //
1039        if (superClass != null) {
1040          superClass.resolve();
1041        }
1042        for (RVMClass declaredInterface : declaredInterfaces) {
1043          declaredInterface.resolve();
1044        }
1045    
1046        if (isInterface()) {
1047          if (VM.VerifyAssertions) VM._assert(superClass == null);
1048          depth = 1;
1049          thinLockOffset = Offset.max();
1050        } else if (superClass == null) {
1051          if (VM.VerifyAssertions) VM._assert(isJavaLangObjectType());
1052          instanceSize = ObjectModel.computeScalarHeaderSize(this);
1053          alignment = BYTES_IN_ADDRESS;
1054          thinLockOffset = ObjectModel.defaultThinLockOffset();
1055          depth=0;
1056        } else {
1057          depth = superClass.depth + 1;
1058          thinLockOffset = superClass.thinLockOffset;
1059          instanceSize = superClass.instanceSize;
1060          fieldLayoutContext = superClass.fieldLayoutContext;
1061          alignment = superClass.alignment;
1062        }
1063    
1064        if (this == RVMType.JavaLangClassType) {
1065          ObjectModel.allocateThinLock(this);
1066        }
1067    
1068        if (superClass != null && superClass.isNonMoving() && !isNonMoving()) {
1069          VM.sysWriteln("WARNING: movable " + this + " extends non-moving " + superClass);
1070        }
1071    
1072        if (VM.verboseClassLoading) VM.sysWrite("[Preparing " + this + "]\n");
1073    
1074        // build field and method lists for this class
1075        //
1076        {
1077          FieldVector staticFields = new FieldVector();
1078          FieldVector instanceFields = new FieldVector();
1079          MethodVector staticMethods = new MethodVector();
1080          MethodVector constructorMethods = new MethodVector();
1081          MethodVector virtualMethods = new MethodVector();
1082    
1083          // start with fields and methods of superclass
1084          //
1085          if (superClass != null) {
1086            for (RVMField field : superClass.getInstanceFields()) {
1087              instanceFields.addElement(field);
1088            }
1089    
1090            for (RVMMethod method : superClass.getVirtualMethods()) {
1091              virtualMethods.addElement(method);
1092            }
1093          }
1094    
1095          // append fields defined by this class
1096          //
1097          for (RVMField field : getDeclaredFields()) {
1098            if (field.isStatic()) {
1099              staticFields.addElement(field);
1100            } else {
1101              instanceFields.addElement(field);
1102            }
1103          }
1104    
1105          // append/overlay methods defined by this class
1106          //
1107          for (RVMMethod method : getDeclaredMethods()) {
1108            if (VM.VerifyUnint) {
1109              if (method.isSynchronized() && method.isUninterruptible()) {
1110                if (VM.ParanoidVerifyUnint || !method.hasLogicallyUninterruptibleAnnotation()) {
1111                  VM.sysWriteln("WARNING: " + method + " cannot be both uninterruptible and synchronized");
1112                }
1113              }
1114            }
1115    
1116            if (method.isObjectInitializer()) {
1117              Callbacks.notifyMethodOverride(method, null);
1118              constructorMethods.addElement(method);
1119            } else if (method.isStatic()) {
1120              if (!method.isClassInitializer()) {
1121                Callbacks.notifyMethodOverride(method, null);
1122                staticMethods.addElement(method);
1123              }
1124            } else { // Virtual method
1125    
1126              if (method.isSynchronized()) {
1127                ObjectModel.allocateThinLock(this);
1128              }
1129    
1130              // method could override something in superclass - check for it
1131              //
1132              int superclassMethodIndex = -1;
1133              for (int j = 0, m = virtualMethods.size(); j < m; ++j) {
1134                RVMMethod alreadyDefinedMethod = virtualMethods.elementAt(j);
1135                if (alreadyDefinedMethod.getName() == method.getName() &&
1136                    alreadyDefinedMethod.getDescriptor() == method.getDescriptor()) {
1137                  // method already defined in superclass
1138                  superclassMethodIndex = j;
1139                  break;
1140                }
1141              }
1142    
1143              if (superclassMethodIndex == -1) {
1144                Callbacks.notifyMethodOverride(method, null);
1145                virtualMethods.addElement(method);                          // append
1146              } else {
1147                RVMMethod superc = virtualMethods.elementAt(superclassMethodIndex);
1148                if (VM.VerifyUnint) {
1149                  if (!superc.isInterruptible() && method.isInterruptible()) {
1150                    VM.sysWriteln("WARNING: interruptible " + method + " overrides uninterruptible " + superc);
1151                  }
1152                }
1153                Callbacks.notifyMethodOverride(method, superc);
1154                virtualMethods.setElementAt(method, superclassMethodIndex); // override
1155              }
1156            }
1157          }
1158    
1159          // Deal with Miranda methods.
1160          // If this is an abstract class, then for each
1161          // interface that this class implements, ensure that a corresponding virtual
1162          // method is declared.  If one is not, then create an abstract method to fill the void.
1163          if (!isInterface() && isAbstract()) {
1164            for (RVMClass I : declaredInterfaces) {
1165              RVMMethod[] iMeths = I.getVirtualMethods();
1166              outer:
1167              for (RVMMethod iMeth : iMeths) {
1168                Atom iName = iMeth.getName();
1169                Atom iDesc = iMeth.getDescriptor();
1170                for (int k = 0; k < virtualMethods.size(); k++) {
1171                  RVMMethod vMeth = virtualMethods.elementAt(k);
1172                  if (vMeth.getName() == iName && vMeth.getDescriptor() == iDesc) continue outer;
1173                }
1174                MemberReference mRef = MemberReference.findOrCreate(typeRef, iName, iDesc);
1175                virtualMethods.addElement(new AbstractMethod(getTypeRef(),
1176                                                                mRef,
1177                                                                (short) (ACC_ABSTRACT | ACC_PUBLIC),
1178                                                                iMeth.getExceptionTypes(),
1179                                                                null,
1180                                                                null,
1181                                                                null,
1182                                                                null));
1183              }
1184            }
1185          }
1186    
1187          // If this is an interface, inherit methods from its superinterfaces
1188          if (isInterface()) {
1189            for (RVMClass declaredInterface : declaredInterfaces) {
1190              RVMMethod[] meths = declaredInterface.getVirtualMethods();
1191              for (RVMMethod meth : meths) {
1192                virtualMethods.addUniqueElement(meth);
1193              }
1194            }
1195          }
1196    
1197          this.staticFields = staticFields.finish();
1198          this.instanceFields = instanceFields.finish();
1199          this.staticMethods = staticMethods.finish();
1200          this.constructorMethods = constructorMethods.finish();
1201          this.virtualMethods = virtualMethods.finish();
1202        }
1203    
1204        // allocate space for class fields
1205        //
1206        for (RVMField field : staticFields) {
1207          if (field.isReferenceType()) {
1208            field.setOffset(Statics.allocateReferenceSlot(true));
1209          } else if (field.getSize() <= BYTES_IN_INT) {
1210            field.setOffset(Statics.allocateNumericSlot(BYTES_IN_INT, true));
1211          } else {
1212            field.setOffset(Statics.allocateNumericSlot(BYTES_IN_LONG, true));
1213          }
1214    
1215          // (SJF): Serialization nastily accesses even final private static
1216          //           fields via pseudo-reflection! So, we must shove the
1217          //           values of final static fields into the JTOC.  Now
1218          //           seems to be a good time.
1219          if (field.isFinal()) {
1220            setFinalStaticJTOCEntry(field, field.getOffset());
1221          }
1222        }
1223    
1224        // lay out instance fields
1225        //
1226        ObjectModel.layoutInstanceFields(this);
1227    
1228        // count reference fields
1229        int referenceFieldCount = 0;
1230        for (RVMField field : instanceFields) {
1231          if (field.isTraced()) {
1232            referenceFieldCount += 1;
1233          }
1234        }
1235    
1236        // record offsets of those instance fields that contain references
1237        //
1238        if (typeRef.isRuntimeTable()) {
1239          referenceOffsets = MemoryManager.newNonMovingIntArray(0);
1240        } else {
1241          referenceOffsets = MemoryManager.newNonMovingIntArray(referenceFieldCount);
1242          int j = 0;
1243          for (RVMField field : instanceFields) {
1244            if (field.isTraced()) {
1245              referenceOffsets[j++] = field.getOffset().toInt();
1246            }
1247          }
1248        }
1249    
1250        // Allocate space for <init> method pointers
1251        //
1252        for (RVMMethod method : constructorMethods) {
1253          method.setOffset(Statics.allocateReferenceSlot(true));
1254        }
1255    
1256        // Allocate space for static method pointers
1257        //
1258        for (RVMMethod method : staticMethods) {
1259          if (method.isClassInitializer()) {
1260            method.setOffset(Offset.fromIntZeroExtend(0xebad0ff5)); // should never be used.
1261          } else {
1262            method.setOffset(Statics.allocateReferenceSlot(true));
1263          }
1264        }
1265    
1266        if (!isInterface()) {
1267          // lay out virtual method section of type information block
1268          // (to be filled in by instantiate)
1269          for (int i = 0, n = virtualMethods.length; i < n; ++i) {
1270            RVMMethod method = virtualMethods[i];
1271            method.setOffset(TIB.getVirtualMethodOffset(i));
1272          }
1273        }
1274    
1275        // RCGC: Determine if class is inherently acyclic
1276        acyclic = false;    // must initially be false for recursive types
1277        boolean foundCyclic = false;
1278        for (RVMField instanceField : instanceFields) {
1279          TypeReference ft = instanceField.getType();
1280          if (!ft.isResolved() || !ft.peekType().isAcyclicReference()) {
1281            foundCyclic = true;
1282            break;
1283          }
1284        }
1285        if (!foundCyclic) {
1286          acyclic = true;
1287        }
1288    
1289        // allocate "type information block"
1290        TIB allocatedTib;
1291        if (isInterface()) {
1292          allocatedTib = MemoryManager.newTIB(0, AlignmentEncoding.ALIGN_CODE_NONE);
1293        } else if (isAnnotationDeclared(TypeReference.ReferenceFieldsVary)) {
1294          allocatedTib = MemoryManager.newTIB(virtualMethods.length, HandInlinedScanning.fallback());
1295        } else {
1296          allocatedTib = MemoryManager.newTIB(virtualMethods.length, HandInlinedScanning.scalar(referenceOffsets));
1297        }
1298    
1299        superclassIds = DynamicTypeCheck.buildSuperclassIds(this);
1300        doesImplement = DynamicTypeCheck.buildDoesImplement(this);
1301    
1302        // can't move this beyond "finalize" code block as findVirtualMethod
1303        // assumes state >= RESOLVED, no allocation occurs until
1304        // state >= CLASS_INITIALIZING
1305        publishResolved(allocatedTib, superclassIds, doesImplement);
1306    
1307        // TODO: Make this into a more general listener interface
1308        if (VM.BuildForOptCompiler && VM.writingBootImage) {
1309          classLoadListener.classInitialized(this, true);
1310        }
1311    
1312        Callbacks.notifyClassResolved(this);
1313        MemoryManager.notifyClassResolved(this);
1314    
1315        // check for a "finalize" method that overrides the one in java.lang.Object
1316        //
1317        if (!isInterface()) {
1318          final RVMMethod method =
1319              findVirtualMethod(RVMClassLoader.StandardObjectFinalizerMethodName,
1320                                RVMClassLoader.StandardObjectFinalizerMethodDescriptor);
1321          if (!method.getDeclaringClass().isJavaLangObjectType()) {
1322            hasFinalizer = true;
1323          }
1324        }
1325    
1326        if (VM.TraceClassLoading && VM.runningVM) VM.sysWriteln("RVMClass: (end)   resolve " + this);
1327      }
1328    
1329      /**
1330       * Atomically initialize the important parts of the TIB and let the world know this type is
1331       * resolved.
1332       *
1333       * @param allocatedTib The TIB that has been allocated for this type
1334       * @param superclassIds The calculated superclass ids array
1335       * @param doesImplement The calculated does implement array
1336       */
1337      @Uninterruptible
1338      private void publishResolved(TIB allocatedTib, short[] superclassIds, int[] doesImplement) {
1339        Statics.setSlotContents(getTibOffset(), allocatedTib);
1340        allocatedTib.setType(this);
1341        allocatedTib.setSuperclassIds(superclassIds);
1342        allocatedTib.setDoesImplement(doesImplement);
1343        typeInformationBlock = allocatedTib;
1344        state = CLASS_RESOLVED;
1345      }
1346    
1347      @Override
1348      public void allBootImageTypesResolved() {
1349        for (RVMMethod method : declaredMethods) {
1350          if (method instanceof NormalMethod) {
1351            ((NormalMethod)method).recomputeSummary(constantPool);
1352          }
1353        }
1354      }
1355    
1356    
1357      /**
1358       * @return <code>true</code> if the class is acyclic and
1359       * final (otherwise the reference could be to a subsequently loaded
1360       * cyclic subclass)
1361       */
1362      @Override
1363      @Uninterruptible
1364      public boolean isAcyclicReference() {
1365        return acyclic && isFinal();
1366      }
1367    
1368      /**
1369       * Insert the value of a final static field into the JTOC
1370       */
1371      private void setFinalStaticJTOCEntry(RVMField field, Offset fieldOffset) {
1372        if (!field.isFinal()) return;
1373    
1374        // value Index: index into the classes constant pool.
1375        int valueIndex = field.getConstantValueIndex();
1376    
1377        // if there's no value in the constant pool, bail out
1378        if (valueIndex <= 0) return;
1379    
1380        Offset literalOffset = field.getDeclaringClass().getLiteralOffset(valueIndex);
1381    
1382        if (Statics.isReference(Statics.offsetAsSlot(fieldOffset))) {
1383          Object obj = Statics.getSlotContentsAsObject(literalOffset);
1384          Statics.setSlotContents(fieldOffset, obj);
1385        } else if (field.getSize() <= BYTES_IN_INT) {
1386          // copy one word from constant pool to JTOC
1387          int value = Statics.getSlotContentsAsInt(literalOffset);
1388          Statics.setSlotContents(fieldOffset, value);
1389        } else {
1390          // copy two words from constant pool to JTOC
1391          long value = Statics.getSlotContentsAsLong(literalOffset);
1392          Statics.setSlotContents(fieldOffset, value);
1393        }
1394      }
1395    
1396      /**
1397       * {@inheritDoc} The TIB will also be built.<p>
1398       *
1399       * Side effects: superclasses are instantiated.
1400       */
1401      @Override
1402      public synchronized void instantiate() {
1403        if (isInstantiated()) {
1404          return;
1405        }
1406    
1407        if (VM.TraceClassLoading && VM.runningVM) VM.sysWriteln("RVMClass: (begin) instantiate " + this);
1408        if (VM.VerifyAssertions) VM._assert(state == CLASS_RESOLVED);
1409    
1410        // instantiate superclass
1411        //
1412        if (superClass != null) {
1413          superClass.instantiate();
1414        }
1415        if (VM.runningVM) {
1416          // can't instantiate if building bootimage, since this can cause
1417          // class initializer to be lost (when interface is not included in bootimage).
1418          // since we don't need to instantiate/initialize for the purposes of
1419          // dynamic type checking and interface invocation, defer it until runtime
1420          // and the class actually refers to a static field of the interface.
1421          for (RVMClass declaredInterface : declaredInterfaces) {
1422            declaredInterface.instantiate();
1423          }
1424        }
1425    
1426        if (!isInterface()) {
1427          // Create the internal lazy method invoker trampoline
1428          typeInformationBlock.initializeInternalLazyCompilationTrampoline();
1429    
1430          // Initialize slots in the TIB for virtual methods
1431          for(int i=0; i < virtualMethods.length; i++) {
1432            RVMMethod method = virtualMethods[i];
1433            if (method.isPrivate() && method.getDeclaringClass() != this) {
1434              typeInformationBlock.setVirtualMethod(i, null); // an inherited private method....will never be invoked via this TIB
1435            } else {
1436              typeInformationBlock.setVirtualMethod(i, method.getCurrentEntryCodeArray());
1437            }
1438          }
1439    
1440          // compile <init> methods and put their addresses into jtoc
1441          for (RVMMethod method : constructorMethods) {
1442            Statics.setSlotContents(method.getOffset(), method.getCurrentEntryCodeArray());
1443          }
1444    
1445          // compile static methods and put their addresses into jtoc
1446          for (RVMMethod method : staticMethods) {
1447            // don't bother compiling <clinit> here;
1448            // compile it right before we invoke it in initialize.
1449            // This also avoids putting <clinit>s in the bootimage.
1450            if (!method.isClassInitializer()) {
1451              Statics.setSlotContents(method.getOffset(), method.getCurrentEntryCodeArray());
1452            }
1453          }
1454        }
1455    
1456        InterfaceInvocation.initializeDispatchStructures(this);
1457        SpecializedMethodManager.notifyTypeInstantiated(this);
1458    
1459        if (VM.writingBootImage) {
1460          state = CLASS_INITIALIZED;
1461          // Mark final fields as literals as class initializer won't have been called
1462          markFinalFieldsAsLiterals();
1463        } else {
1464          state = CLASS_INSTANTIATED;
1465        }
1466    
1467        Callbacks.notifyClassInstantiated(this);
1468        if (VM.writingBootImage) {
1469          Callbacks.notifyClassInitialized(this);
1470        }
1471    
1472        if (VM.TraceClassLoading && VM.runningVM) VM.sysWriteln("RVMClass: (end)   instantiate " + this);
1473      }
1474    
1475      /**
1476       * Make the passed field a traced field by garbage collection. Also affects all
1477       * subclasses.
1478       */
1479      public void makeFieldTraced(RVMField field) {
1480        int[] oldOffsets = referenceOffsets;
1481        int fieldOffset = field.getOffset().toInt();
1482        referenceOffsets = MemoryManager.newNonMovingIntArray(oldOffsets.length + 1);
1483        int i;
1484        for(i=0; i < oldOffsets.length && oldOffsets[i] < fieldOffset; i++) {
1485          referenceOffsets[i] = oldOffsets[i];
1486        }
1487        referenceOffsets[i++] = fieldOffset;
1488        while(i < referenceOffsets.length) {
1489          referenceOffsets[i] = oldOffsets[i-1];
1490          i++;
1491        }
1492        SpecializedMethodManager.refreshSpecializedMethods(this);
1493    
1494        for(RVMClass klass: subClasses) {
1495          klass.makeFieldTraced(field);
1496        }
1497      }
1498    
1499      /**
1500       * {@inheritDoc}<p>
1501       *
1502       * Side effects: superclasses are initialized, static fields receive
1503       * initial values.
1504       */
1505      @Override
1506      public synchronized void initialize() throws ExceptionInInitializerError {
1507        if (isInitialized()) {
1508          return;
1509        }
1510    
1511        if (state == CLASS_INITIALIZING) {
1512          return;
1513        }
1514    
1515        if (state == CLASS_INITIALIZER_FAILED) {
1516          throw new NoClassDefFoundError(this+" (initialization failure)");
1517        }
1518    
1519        if (VM.TraceClassLoading && VM.runningVM) VM.sysWriteln("RVMClass: (begin) initialize " + this);
1520        if (VM.VerifyAssertions) VM._assert(state == CLASS_INSTANTIATED);
1521        state = CLASS_INITIALIZING;
1522        if (VM.verboseClassLoading) VM.sysWrite("[Initializing " + this + "]\n");
1523    
1524        // run super <clinit>
1525        //
1526        if (superClass != null) {
1527          superClass.initialize();
1528        }
1529    
1530        // run <clinit>
1531        //
1532        if (classInitializerMethod != null) {
1533          CompiledMethod cm = classInitializerMethod.getCurrentCompiledMethod();
1534          while (cm == null) {
1535            classInitializerMethod.compile();
1536            cm = classInitializerMethod.getCurrentCompiledMethod();
1537          }
1538    
1539          if (VM.verboseClassLoading) VM.sysWrite("[Running static initializer for " + this + "]\n");
1540    
1541          try {
1542            Magic.invokeClassInitializer(cm.getEntryCodeArray());
1543          } catch (Error e) {
1544            state = CLASS_INITIALIZER_FAILED;
1545            throw e;
1546          } catch (Throwable t) {
1547            ExceptionInInitializerError eieio = new ExceptionInInitializerError("While initializing " + this);
1548            eieio.initCause(t);
1549            state = CLASS_INITIALIZER_FAILED;
1550            if (VM.verboseClassLoading) {
1551              VM.sysWriteln("[Exception in initializer error caused by:");
1552              t.printStackTrace();
1553              VM.sysWriteln("]");
1554            }
1555            throw eieio;
1556          }
1557    
1558          // <clinit> is no longer needed: reclaim space by removing references to it
1559          classInitializerMethod.invalidateCompiledMethod(cm);
1560          classInitializerMethod = null;
1561        }
1562    
1563        if (VM.BuildForOptCompiler) {
1564          // report that a class is about to be marked initialized to
1565          // the opt compiler so it can invalidate speculative CHA optimizations
1566          // before an instance of this class could actually be created.
1567          classLoadListener.classInitialized(this, false);
1568        }
1569    
1570        state = CLASS_INITIALIZED;
1571    
1572        Callbacks.notifyClassInitialized(this);
1573    
1574        markFinalFieldsAsLiterals();
1575    
1576        if (VM.verboseClassLoading) VM.sysWrite("[Initialized " + this + "]\n");
1577        if (VM.TraceClassLoading && VM.runningVM) VM.sysWriteln("RVMClass: (end)   initialize " + this);
1578      }
1579    
1580      /**
1581       * Mark final fields as being available as literals
1582       */
1583      private void markFinalFieldsAsLiterals() {
1584        for (RVMField f : getStaticFields()) {
1585          if (f.isFinal()) {
1586            Offset fieldOffset = f.getOffset();
1587            if (Statics.isReference(Statics.offsetAsSlot(fieldOffset))) {
1588              Statics.markAsReferenceLiteral(fieldOffset);
1589            } else {
1590              Statics.markAsNumericLiteral(f.getSize(), fieldOffset);
1591            }
1592          }
1593        }
1594      }
1595    
1596      /**
1597       * Copy the values of all static final fields into
1598       * the JTOC.  Note: This method should only be run AFTER
1599       * the class initializer has run.
1600       */
1601      public void setAllFinalStaticJTOCEntries() {
1602        if (VM.VerifyAssertions) VM._assert(isInitialized());
1603        for (RVMField f : getStaticFields()) {
1604          if (f.isFinal()) {
1605            setFinalStaticJTOCEntry(f, f.getOffset());
1606          }
1607        }
1608      }
1609    
1610      void resolveNativeMethods() {
1611        if (VM.VerifyAssertions) VM._assert(isInitialized());
1612        resolveNativeMethodsInternal(getStaticMethods());
1613        resolveNativeMethodsInternal(getVirtualMethods());
1614      }
1615    
1616      private void resolveNativeMethodsInternal(RVMMethod[] methods) {
1617        for (RVMMethod m : methods) {
1618          if (m.isNative()) {
1619            m.replaceCompiledMethod(null);
1620          }
1621        }
1622      }
1623    
1624      /**
1625       * Unregisters all native methods
1626       */
1627      public void unregisterNativeMethods() {
1628        if (VM.VerifyAssertions) VM._assert(isInitialized());
1629        for (RVMMethod m : declaredMethods) {
1630          if (m.isNative()) {
1631            NativeMethod nm = (NativeMethod) m;
1632            nm.unregisterNativeSymbol();
1633            m.replaceCompiledMethod(null);
1634          }
1635        }
1636      }
1637    
1638      /**
1639       * Add to list of classes that derive from this one.
1640       */
1641      private void addSubClass(RVMClass sub) {
1642        int n = subClasses.length;
1643        RVMClass[] tmp = new RVMClass[n + 1];
1644    
1645        for (int i = 0; i < n; ++i) {
1646          tmp[i] = subClasses[i];
1647        }
1648        tmp[n] = sub;
1649    
1650        subClasses = tmp;
1651      }
1652    
1653      //------------------------------------------------------------//
1654      // Support for speculative optimizations that may need to
1655      // invalidate compiled code when new classes are loaded.
1656      //
1657      // TODO: Make this into a more general listener API
1658      //------------------------------------------------------------//
1659      public static final ClassLoadingListener classLoadListener =
1660          VM.BuildForOptCompiler ? new ClassLoadingDependencyManager() : null;
1661    
1662      /**
1663       * Given a method declared by this class, update all
1664       * dispatching tables to refer to the current compiled
1665       * code for the method.
1666       */
1667      public void updateMethod(RVMMethod m) {
1668        if (VM.VerifyAssertions) VM._assert(isResolved());
1669        if (VM.VerifyAssertions) VM._assert(m.getDeclaringClass() == this);
1670        if (m.isClassInitializer()) return; // we never put this method in the jtoc anyways!
1671    
1672        if (m.isStatic() || m.isObjectInitializer()) {
1673          updateJTOCEntry(m);
1674        } else {
1675          updateVirtualMethod(m);
1676        }
1677      }
1678    
1679      /**
1680       * Update the JTOC slot for the given static method to point to
1681       * the current compiled code for the given method.
1682       * NOTE: This method is intentionally not synchronized to avoid deadlocks.
1683       *       We instead rely on the fact that we are always updating the JTOC with
1684       *       the most recent instructions for the method.
1685       */
1686      public void updateJTOCEntry(RVMMethod m) {
1687        if (VM.VerifyAssertions) VM._assert(m.getDeclaringClass() == this);
1688        if (VM.VerifyAssertions) VM._assert(isResolved());
1689        if (VM.VerifyAssertions) VM._assert(m.isStatic() || m.isObjectInitializer());
1690        Statics.setSlotContents(m.getOffset(), m.getCurrentEntryCodeArray());
1691      }
1692    
1693      /**
1694       * Update this class's TIB entry for the given method to point to
1695       * the current compiled code for the given method.<p>
1696       * NOTE: This method is intentionally not synchronized to avoid deadlocks.
1697       *       We instead rely on the fact that we are always updating the JTOC with
1698       *       the most recent instructions for the method.
1699       */
1700      public void updateTIBEntry(RVMMethod m) {
1701        if (VM.VerifyAssertions) {
1702          RVMMethod vm = findVirtualMethod(m.getName(), m.getDescriptor());
1703          VM._assert(vm == m);
1704        }
1705        typeInformationBlock.setVirtualMethod(m.getOffset(), m.getCurrentEntryCodeArray());
1706        InterfaceInvocation.updateTIBEntry(this, m);
1707      }
1708    
1709      /**
1710       * Update the TIB entry's for all classes that inherit the given method
1711       * to point to the current compiled code for the given method.<p>
1712       * NOTE: This method is intentionally not synchronized to avoid deadlocks.
1713       *       We instead rely on the fact that we are always updating the JTOC with
1714       *       the most recent instructions for the method.
1715       */
1716      public void updateVirtualMethod(RVMMethod m) {
1717        RVMMethod dm = findDeclaredMethod(m.getName(), m.getDescriptor());
1718        if (dm != null && dm != m) return;  // this method got overridden
1719        updateTIBEntry(m);
1720        if (m.isPrivate()) return; // can't override
1721        for (RVMClass sc : getSubClasses()) {
1722          if (sc.isResolved()) {
1723            sc.updateVirtualMethod(m);
1724          }
1725        }
1726      }
1727    
1728      //------------------------------------------------------------//
1729      // Additional fields and methods for Interfaces               //
1730      //------------------------------------------------------------//
1731    
1732      private static final Object interfaceCountLock = new Object();
1733      private static int interfaceCount = 0;
1734      private static RVMClass[] interfaces;
1735      private int interfaceId = -1;
1736      RVMMethod[] noIMTConflictMap; // used by InterfaceInvocation to support resetTIB
1737    
1738      /**
1739       * Classes used as Interfaces get assigned an interface id.
1740       *   If the class is not an interface, attempting to use this
1741       *   id will cause an IncompatibleClassChangeError to be thrown
1742       */
1743      public int getInterfaceId() {
1744        if (interfaceId == -1) {
1745          assignInterfaceId();
1746        }
1747        return interfaceId;
1748      }
1749    
1750      public int getDoesImplementIndex() {
1751        return getInterfaceId() >>> 5;
1752      }
1753    
1754      public int getDoesImplementBitMask() {
1755        return 1 << (getInterfaceId() & 31);
1756      }
1757    
1758      public static RVMClass getInterface(int id) {
1759        return interfaces[id];
1760      }
1761    
1762      private synchronized void assignInterfaceId() {
1763        if (interfaceId == -1) {
1764          if (interfaceCountLock != null && interfaces != null) {
1765            synchronized (interfaceCountLock) {
1766              interfaceId = interfaceCount++;
1767              if (interfaceId == interfaces.length) {
1768                RVMClass[] tmp = new RVMClass[interfaces.length * 2];
1769                System.arraycopy(interfaces, 0, tmp, 0, interfaces.length);
1770                interfaces = tmp;
1771              }
1772              interfaces[interfaceId] = this;
1773            }
1774          } else {
1775            interfaceId = interfaceCount++;
1776            if (interfaces == null) {
1777              interfaces = new RVMClass[200];
1778            }
1779            interfaces[interfaceId] = this;
1780          }
1781        }
1782      }
1783    
1784      /**
1785       * Number of [ in descriptor for arrays; -1 for primitives; 0 for
1786       * classes
1787       * @return 0
1788       */
1789      @Override
1790      @Pure
1791      @Uninterruptible
1792      public int getDimensionality() {
1793        return 0;
1794      }
1795    
1796      @Override
1797      @Uninterruptible
1798      public boolean isResolved() {
1799        return state >= CLASS_RESOLVED;
1800      }
1801    
1802      @Override
1803      @Uninterruptible
1804      public boolean isInstantiated() {
1805        return state >= CLASS_INSTANTIATED;
1806      }
1807    
1808      @Override
1809      @Uninterruptible
1810      public boolean isInitialized() {
1811        return state == CLASS_INITIALIZED;
1812      }
1813    
1814      @Override
1815      public void markAsBootImageClass() {
1816        inBootImage = true;
1817      }
1818    
1819      @Override
1820      @Uninterruptible
1821      public boolean isInBootImage() {
1822        return inBootImage;
1823      }
1824    
1825      /**
1826       * Get the offset in instances of this type assigned to the thin lock word.
1827       * Is only known after class has been resolved.
1828       */
1829      @Override
1830      @Uninterruptible
1831      public Offset getThinLockOffset() {
1832        if (VM.VerifyAssertions) VM._assert(isResolved());
1833        return thinLockOffset;
1834      }
1835    
1836     /**
1837       * Set the thin lock offset for instances of this type. Can be called at most once.
1838       * and is invoked from ObjectModel.allocateThinLock (in object models which
1839       * do not allocate thin locks for all scalar object types).
1840       */
1841      public void setThinLockOffset(Offset offset) {
1842        if (VM.VerifyAssertions) VM._assert(thinLockOffset.isMax());
1843        if (VM.VerifyAssertions) VM._assert(!offset.isMax());
1844        thinLockOffset = offset;
1845      }
1846    
1847      /**
1848       * Get number of superclasses to Object.
1849       */
1850      @Override
1851      @Pure
1852      @Uninterruptible
1853      public int getTypeDepth() {
1854        return depth;
1855      }
1856    
1857      /**
1858       * @return <code>true</code>
1859       */
1860      @Override
1861      @Pure
1862      @Uninterruptible
1863      public boolean isClassType() {
1864        return true;
1865      }
1866    
1867      /**
1868       * @return <code>false</code>
1869       */
1870      @Override
1871      @Pure
1872      @Uninterruptible
1873      public boolean isArrayType() {
1874        return false;
1875      }
1876    
1877      /**
1878       * @return <code>false</code>
1879       */
1880      @Override
1881      @Pure
1882      @Uninterruptible
1883      public boolean isPrimitiveType() {
1884        return false;
1885      }
1886    
1887      /**
1888       * @return <code>true</code>
1889       */
1890      @Override
1891      @Pure
1892      @Uninterruptible
1893      public boolean isReferenceType() {
1894        return true;
1895      }
1896    
1897      /**
1898       * @return <code>false</code>
1899       */
1900      @Override
1901      @Pure
1902      @Uninterruptible
1903      public boolean isUnboxedType() {
1904        return false;
1905      }
1906    
1907      /**
1908       * Create a synthetic class that extends ReflectionBase and invokes the given method
1909       * @param methodToCall the method we wish to call reflectively
1910       * @return the synthetic class
1911       */
1912      static Class<?> createReflectionClass(RVMMethod methodToCall) {
1913        if (VM.VerifyAssertions) VM._assert(VM.runningVM);
1914        if (DynamicTypeCheck.instanceOfResolved(TypeReference.baseReflectionClass.resolve(), methodToCall.getDeclaringClass())) {
1915          // Avoid reflection on reflection base class
1916          return null;
1917        }
1918        int[] constantPool = new int[methodToCall.getParameterTypes().length+3];
1919        String reflectionClassName = "Lorg/jikesrvm/classloader/ReflectionBase$$Reflect"+methodToCall.getMemberRef().getId()+";";
1920        TypeReference reflectionClass = TypeReference.findOrCreate(reflectionClassName);
1921        RVMType klass = reflectionClass.peekType();
1922        if (klass == null) {
1923          MethodReference reflectionMethodRef = MethodReference.findOrCreate(reflectionClass,
1924              Atom.findOrCreateUnicodeAtom("invokeInternal"),
1925              Atom.findOrCreateUnicodeAtom("(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;")
1926          ).asMethodReference();
1927          MethodReference constructorMethodRef = MethodReference.findOrCreate(reflectionClass,
1928              Atom.findOrCreateUnicodeAtom("<init>"),
1929              Atom.findOrCreateUnicodeAtom("()V")
1930          ).asMethodReference();
1931    
1932          RVMMethod[] reflectionMethods = new RVMMethod[]{
1933              methodToCall.createReflectionMethod(reflectionClass, constantPool, reflectionMethodRef),
1934              RVMMethod.createDefaultConstructor(reflectionClass, constructorMethodRef)};
1935          klass =
1936            new RVMClass(reflectionClass, constantPool, (short) (ACC_SYNTHETIC | ACC_PUBLIC | ACC_FINAL), // modifiers
1937                TypeReference.baseReflectionClass.resolve().asClass(), // superClass
1938                emptyVMClass, // declaredInterfaces
1939                emptyVMField, reflectionMethods,
1940                null, null, null, null, null, null, null, null);
1941          reflectionClass.setType(klass);
1942          RuntimeEntrypoints.initializeClassForDynamicLink(klass.asClass());
1943        }
1944        return klass.getClassForType();
1945      }
1946    }