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