/*
 * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 *
 */

package sun.jvm.hotspot.oops;

import java.io.*;
import java.util.*;
import sun.jvm.hotspot.classfile.ClassLoaderData;
import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.memory.*;
import sun.jvm.hotspot.runtime.*;
import sun.jvm.hotspot.types.*;
import sun.jvm.hotspot.utilities.*;

// An InstanceKlass is the VM level representation of a Java class.

public class InstanceKlass extends Klass {
  static {
    VM.registerVMInitializedObserver(new Observer() {
        public void update(Observable o, Object data) {
          initialize(VM.getVM().getTypeDataBase());
        }
      });
  }

  // field offset constants
  private static int ACCESS_FLAGS_OFFSET;
  private static int NAME_INDEX_OFFSET;
  private static int SIGNATURE_INDEX_OFFSET;
  private static int INITVAL_INDEX_OFFSET;
  private static int LOW_OFFSET;
  private static int HIGH_OFFSET;
  private static int FIELD_SLOTS;
  private static short FIELDINFO_TAG_SIZE;
  private static short FIELDINFO_TAG_MASK;
  private static short FIELDINFO_TAG_OFFSET;

  // ClassState constants
  private static int CLASS_STATE_ALLOCATED;
  private static int CLASS_STATE_LOADED;
  private static int CLASS_STATE_LINKED;
  private static int CLASS_STATE_BEING_INITIALIZED;
  private static int CLASS_STATE_FULLY_INITIALIZED;
  private static int CLASS_STATE_INITIALIZATION_ERROR;

  private static synchronized void initialize(TypeDataBase db) throws WrongTypeException {
    Type type            = db.lookupType("InstanceKlass");
    arrayKlasses         = new MetadataField(type.getAddressField("_array_klasses"), 0);
    methods              = type.getAddressField("_methods");
    methodOrdering       = type.getAddressField("_method_ordering");
    localInterfaces      = type.getAddressField("_local_interfaces");
    transitiveInterfaces = type.getAddressField("_transitive_interfaces");
    fields               = type.getAddressField("_fields");
    javaFieldsCount      = new CIntField(type.getCIntegerField("_java_fields_count"), 0);
    constants            = new MetadataField(type.getAddressField("_constants"), 0);
    classLoaderData      = type.getAddressField("_class_loader_data");
    sourceDebugExtension = type.getAddressField("_source_debug_extension");
    innerClasses         = type.getAddressField("_inner_classes");
    sourceFileNameIndex  = new CIntField(type.getCIntegerField("_source_file_name_index"), 0);
    nonstaticFieldSize   = new CIntField(type.getCIntegerField("_nonstatic_field_size"), 0);
    staticFieldSize      = new CIntField(type.getCIntegerField("_static_field_size"), 0);
    staticOopFieldCount  = new CIntField(type.getCIntegerField("_static_oop_field_count"), 0);
    nonstaticOopMapSize  = new CIntField(type.getCIntegerField("_nonstatic_oop_map_size"), 0);
    isMarkedDependent    = new CIntField(type.getCIntegerField("_is_marked_dependent"), 0);
    initState            = new CIntField(type.getCIntegerField("_init_state"), 0);
    vtableLen            = new CIntField(type.getCIntegerField("_vtable_len"), 0);
    itableLen            = new CIntField(type.getCIntegerField("_itable_len"), 0);
    breakpoints          = type.getAddressField("_breakpoints");
    genericSignatureIndex = new CIntField(type.getCIntegerField("_generic_signature_index"), 0);
    majorVersion         = new CIntField(type.getCIntegerField("_major_version"), 0);
    minorVersion         = new CIntField(type.getCIntegerField("_minor_version"), 0);
    headerSize           = Oop.alignObjectOffset(type.getSize());

    // read field offset constants
    ACCESS_FLAGS_OFFSET            = db.lookupIntConstant("FieldInfo::access_flags_offset").intValue();
    NAME_INDEX_OFFSET              = db.lookupIntConstant("FieldInfo::name_index_offset").intValue();
    SIGNATURE_INDEX_OFFSET         = db.lookupIntConstant("FieldInfo::signature_index_offset").intValue();
    INITVAL_INDEX_OFFSET           = db.lookupIntConstant("FieldInfo::initval_index_offset").intValue();
    LOW_OFFSET                     = db.lookupIntConstant("FieldInfo::low_packed_offset").intValue();
    HIGH_OFFSET                    = db.lookupIntConstant("FieldInfo::high_packed_offset").intValue();
    FIELD_SLOTS                    = db.lookupIntConstant("FieldInfo::field_slots").intValue();
    FIELDINFO_TAG_SIZE             = db.lookupIntConstant("FIELDINFO_TAG_SIZE").shortValue();
    FIELDINFO_TAG_MASK             = db.lookupIntConstant("FIELDINFO_TAG_MASK").shortValue();
    FIELDINFO_TAG_OFFSET           = db.lookupIntConstant("FIELDINFO_TAG_OFFSET").shortValue();

    // read ClassState constants
    CLASS_STATE_ALLOCATED = db.lookupIntConstant("InstanceKlass::allocated").intValue();
    CLASS_STATE_LOADED = db.lookupIntConstant("InstanceKlass::loaded").intValue();
    CLASS_STATE_LINKED = db.lookupIntConstant("InstanceKlass::linked").intValue();
    CLASS_STATE_BEING_INITIALIZED = db.lookupIntConstant("InstanceKlass::being_initialized").intValue();
    CLASS_STATE_FULLY_INITIALIZED = db.lookupIntConstant("InstanceKlass::fully_initialized").intValue();
    CLASS_STATE_INITIALIZATION_ERROR = db.lookupIntConstant("InstanceKlass::initialization_error").intValue();

  }

  public InstanceKlass(Address addr) {
    super(addr);
    if (getJavaFieldsCount() != getAllFieldsCount()) {
      // Exercise the injected field logic
      for (int i = getJavaFieldsCount(); i < getAllFieldsCount(); i++) {
        getFieldName(i);
        getFieldSignature(i);
      }
    }
  }

  private static MetadataField arrayKlasses;
  private static AddressField  methods;
  private static AddressField  methodOrdering;
  private static AddressField  localInterfaces;
  private static AddressField  transitiveInterfaces;
  private static AddressField fields;
  private static CIntField javaFieldsCount;
  private static MetadataField constants;
  private static AddressField  classLoaderData;
  private static AddressField  sourceDebugExtension;
  private static AddressField  innerClasses;
  private static CIntField sourceFileNameIndex;
  private static CIntField nonstaticFieldSize;
  private static CIntField staticFieldSize;
  private static CIntField staticOopFieldCount;
  private static CIntField nonstaticOopMapSize;
  private static CIntField isMarkedDependent;
  private static CIntField initState;
  private static CIntField vtableLen;
  private static CIntField itableLen;
  private static AddressField breakpoints;
  private static CIntField genericSignatureIndex;
  private static CIntField majorVersion;
  private static CIntField minorVersion;

  // type safe enum for ClassState from instanceKlass.hpp
  public static class ClassState {
     public static final ClassState ALLOCATED    = new ClassState("allocated");
     public static final ClassState LOADED       = new ClassState("loaded");
     public static final ClassState LINKED       = new ClassState("linked");
     public static final ClassState BEING_INITIALIZED      = new ClassState("beingInitialized");
     public static final ClassState FULLY_INITIALIZED    = new ClassState("fullyInitialized");
     public static final ClassState INITIALIZATION_ERROR = new ClassState("initializationError");

     private ClassState(String value) {
        this.value = value;
     }

     public String toString() {
        return value;
     }

     private String value;
  }

  public int  getInitStateAsInt() { return (int) initState.getValue(this); }
  public ClassState getInitState() {
     int state = getInitStateAsInt();
     if (state == CLASS_STATE_ALLOCATED) {
        return ClassState.ALLOCATED;
     } else if (state == CLASS_STATE_LOADED) {
        return ClassState.LOADED;
     } else if (state == CLASS_STATE_LINKED) {
        return ClassState.LINKED;
     } else if (state == CLASS_STATE_BEING_INITIALIZED) {
        return ClassState.BEING_INITIALIZED;
     } else if (state == CLASS_STATE_FULLY_INITIALIZED) {
        return ClassState.FULLY_INITIALIZED;
     } else if (state == CLASS_STATE_INITIALIZATION_ERROR) {
        return ClassState.INITIALIZATION_ERROR;
     } else {
        throw new RuntimeException("should not reach here");
     }
  }

  // initialization state quaries
  public boolean isLoaded() {
     return getInitStateAsInt() >= CLASS_STATE_LOADED;
  }

  public boolean isLinked() {
     return getInitStateAsInt() >= CLASS_STATE_LINKED;
  }

  public boolean isInitialized() {
     return getInitStateAsInt() == CLASS_STATE_FULLY_INITIALIZED;
  }

  public boolean isNotInitialized() {
     return getInitStateAsInt() < CLASS_STATE_BEING_INITIALIZED;
  }

  public boolean isBeingInitialized() {
     return getInitStateAsInt() == CLASS_STATE_BEING_INITIALIZED;
  }

  public boolean isInErrorState() {
     return getInitStateAsInt() == CLASS_STATE_INITIALIZATION_ERROR;
  }

  public int getClassStatus() {
     int result = 0;
     if (isLinked()) {
        result |= JVMDIClassStatus.VERIFIED | JVMDIClassStatus.PREPARED;
     }

     if (isInitialized()) {
        if (Assert.ASSERTS_ENABLED) {
           Assert.that(isLinked(), "Class status is not consistent");
        }
        result |= JVMDIClassStatus.INITIALIZED;
     }

     if (isInErrorState()) {
        result |= JVMDIClassStatus.ERROR;
     }
     return result;
  }

  // Byteside of the header
  private static long headerSize;

  public long getObjectSize(Oop object) {
    return getSizeHelper() * VM.getVM().getAddressSize();
  }

  public long getSize() {
    return Oop.alignObjectSize(getHeaderSize() + Oop.alignObjectOffset(getVtableLen()) +
                               Oop.alignObjectOffset(getItableLen()) + Oop.alignObjectOffset(getNonstaticOopMapSize()));
  }

  public static long getHeaderSize() { return headerSize; }

  public short getFieldAccessFlags(int index) {
    return getFields().at(index * FIELD_SLOTS + ACCESS_FLAGS_OFFSET);
  }

  public short getFieldNameIndex(int index) {
    if (index >= getJavaFieldsCount()) throw new IndexOutOfBoundsException("not a Java field;");
    return getFields().at(index * FIELD_SLOTS + NAME_INDEX_OFFSET);
  }

  public Symbol getFieldName(int index) {
    int nameIndex = getFields().at(index * FIELD_SLOTS + NAME_INDEX_OFFSET);
    if (index < getJavaFieldsCount()) {
      return getConstants().getSymbolAt(nameIndex);
    } else {
      return vmSymbols.symbolAt(nameIndex);
    }
  }

  public short getFieldSignatureIndex(int index) {
    if (index >= getJavaFieldsCount()) throw new IndexOutOfBoundsException("not a Java field;");
    return getFields().at(index * FIELD_SLOTS + SIGNATURE_INDEX_OFFSET);
  }

  public Symbol getFieldSignature(int index) {
    int signatureIndex = getFields().at(index * FIELD_SLOTS + SIGNATURE_INDEX_OFFSET);
    if (index < getJavaFieldsCount()) {
      return getConstants().getSymbolAt(signatureIndex);
    } else {
      return vmSymbols.symbolAt(signatureIndex);
    }
  }

  public short getFieldGenericSignatureIndex(int index) {
    // int len = getFields().length();
    int allFieldsCount = getAllFieldsCount();
    int generic_signature_slot = allFieldsCount * FIELD_SLOTS;
    for (int i = 0; i < allFieldsCount; i++) {
      short flags = getFieldAccessFlags(i);
      AccessFlags access = new AccessFlags(flags);
      if (i == index) {
        if (access.fieldHasGenericSignature()) {
           return getFields().at(generic_signature_slot);
        } else {
          return 0;
        }
      } else {
        if (access.fieldHasGenericSignature()) {
          generic_signature_slot ++;
        }
      }
    }
    return 0;
  }

  public Symbol getFieldGenericSignature(int index) {
    short genericSignatureIndex = getFieldGenericSignatureIndex(index);
    if (genericSignatureIndex != 0)  {
      return getConstants().getSymbolAt(genericSignatureIndex);
    }
    return null;
  }

  public short getFieldInitialValueIndex(int index) {
    if (index >= getJavaFieldsCount()) throw new IndexOutOfBoundsException("not a Java field;");
    return getFields().at(index * FIELD_SLOTS + INITVAL_INDEX_OFFSET);
  }

  public int getFieldOffset(int index) {
    U2Array fields = getFields();
    short lo = fields.at(index * FIELD_SLOTS + LOW_OFFSET);
    short hi = fields.at(index * FIELD_SLOTS + HIGH_OFFSET);
    if ((lo & FIELDINFO_TAG_MASK) == FIELDINFO_TAG_OFFSET) {
      return VM.getVM().buildIntFromShorts(lo, hi) >> FIELDINFO_TAG_SIZE;
    }
    throw new RuntimeException("should not reach here");
  }

  // Accessors for declared fields
  public Klass     getArrayKlasses()        { return (Klass)        arrayKlasses.getValue(this); }
  public MethodArray  getMethods()              { return new MethodArray(methods.getValue(getAddress())); }
  public KlassArray   getLocalInterfaces()      { return new KlassArray(localInterfaces.getValue(getAddress())); }
  public KlassArray   getTransitiveInterfaces() { return new KlassArray(transitiveInterfaces.getValue(getAddress())); }
  public int       getJavaFieldsCount()     { return                (int) javaFieldsCount.getValue(this); }
  public int       getAllFieldsCount()      {
    int len = getFields().length();
    int allFieldsCount = 0;
    for (; allFieldsCount*FIELD_SLOTS < len; allFieldsCount++) {
      short flags = getFieldAccessFlags(allFieldsCount);
      AccessFlags access = new AccessFlags(flags);
      if (access.fieldHasGenericSignature()) {
        len --;
      }
    }
    return allFieldsCount;
  }
  public ConstantPool getConstants()        { return (ConstantPool) constants.getValue(this); }
  public ClassLoaderData getClassLoaderData() { return                ClassLoaderData.instantiateWrapperFor(classLoaderData.getValue(getAddress())); }
  public Oop       getClassLoader()         { return                getClassLoaderData().getClassLoader(); }
  public Symbol    getSourceFileName()      { return                getConstants().getSymbolAt(sourceFileNameIndex.getValue(this)); }
  public String    getSourceDebugExtension(){ return                CStringUtilities.getString(sourceDebugExtension.getValue(getAddress())); }
  public long      getNonstaticFieldSize()  { return                nonstaticFieldSize.getValue(this); }
  public long      getStaticOopFieldCount() { return                staticOopFieldCount.getValue(this); }
  public long      getNonstaticOopMapSize() { return                nonstaticOopMapSize.getValue(this); }
  public boolean   getIsMarkedDependent()   { return                isMarkedDependent.getValue(this) != 0; }
  public long      getVtableLen()           { return                vtableLen.getValue(this); }
  public long      getItableLen()           { return                itableLen.getValue(this); }
  public long      majorVersion()           { return                majorVersion.getValue(this); }
  public long      minorVersion()           { return                minorVersion.getValue(this); }
  public Symbol    getGenericSignature()    {
    long index = genericSignatureIndex.getValue(this);
    if (index != 0) {
      return getConstants().getSymbolAt(index);
    } else {
      return null;
    }
  }

  // "size helper" == instance size in words
  public long getSizeHelper() {
    int lh = getLayoutHelper();
    if (Assert.ASSERTS_ENABLED) {
      Assert.that(lh > 0, "layout helper initialized for instance class");
    }
    return lh / VM.getVM().getAddressSize();
  }

  // same as enum InnerClassAttributeOffset in VM code.
  public static interface InnerClassAttributeOffset {
    // from JVM spec. "InnerClasses" attribute
    public static final int innerClassInnerClassInfoOffset = 0;
    public static final int innerClassOuterClassInfoOffset = 1;
    public static final int innerClassInnerNameOffset = 2;
    public static final int innerClassAccessFlagsOffset = 3;
    public static final int innerClassNextOffset = 4;
  };

  public static interface EnclosingMethodAttributeOffset {
    public static final int enclosing_method_class_index_offset = 0;
    public static final int enclosing_method_method_index_offset = 1;
    public static final int enclosing_method_attribute_size = 2;
  };

  // refer to compute_modifier_flags in VM code.
  public long computeModifierFlags() {
    long access = getAccessFlags();
    // But check if it happens to be member class.
    U2Array innerClassList = getInnerClasses();
    int length = (innerClassList == null)? 0 : (int) innerClassList.length();
    if (length > 0) {
       if (Assert.ASSERTS_ENABLED) {
          Assert.that(length % InnerClassAttributeOffset.innerClassNextOffset == 0 ||
                      length % InnerClassAttributeOffset.innerClassNextOffset == EnclosingMethodAttributeOffset.enclosing_method_attribute_size,
                      "just checking");
       }
       for (int i = 0; i < length; i += InnerClassAttributeOffset.innerClassNextOffset) {
          if (i == length - EnclosingMethodAttributeOffset.enclosing_method_attribute_size) {
              break;
          }
          int ioff = innerClassList.at(i +
                         InnerClassAttributeOffset.innerClassInnerClassInfoOffset);
          // 'ioff' can be zero.
          // refer to JVM spec. section 4.7.5.
          if (ioff != 0) {
             // only look at classes that are already loaded
             // since we are looking for the flags for our self.
             ConstantPool.CPSlot classInfo = getConstants().getSlotAt(ioff);
             Symbol name = null;
             if (classInfo.isResolved()) {
               name = classInfo.getKlass().getName();
             } else if (classInfo.isUnresolved()) {
               name = classInfo.getSymbol();
             } else {
                throw new RuntimeException("should not reach here");
             }

             if (name.equals(getName())) {
                // This is really a member class
                access = innerClassList.at(i +
                        InnerClassAttributeOffset.innerClassAccessFlagsOffset);
                break;
             }
          }
       } // for inner classes
    }

    // Remember to strip ACC_SUPER bit
    return (access & (~JVM_ACC_SUPER)) & JVM_ACC_WRITTEN_FLAGS;
  }


  // whether given Symbol is name of an inner/nested Klass of this Klass?
  // anonymous and local classes are excluded.
  public boolean isInnerClassName(Symbol sym) {
    return isInInnerClasses(sym, false);
  }

  // whether given Symbol is name of an inner/nested Klass of this Klass?
  // anonymous classes excluded, but local classes are included.
  public boolean isInnerOrLocalClassName(Symbol sym) {
    return isInInnerClasses(sym, true);
  }

  private boolean isInInnerClasses(Symbol sym, boolean includeLocals) {
    U2Array innerClassList = getInnerClasses();
    int length = ( innerClassList == null)? 0 : (int) innerClassList.length();
    if (length > 0) {
       if (Assert.ASSERTS_ENABLED) {
         Assert.that(length % InnerClassAttributeOffset.innerClassNextOffset == 0 ||
                     length % InnerClassAttributeOffset.innerClassNextOffset == EnclosingMethodAttributeOffset.enclosing_method_attribute_size,
                     "just checking");
       }
       for (int i = 0; i < length; i += InnerClassAttributeOffset.innerClassNextOffset) {
         if (i == length - EnclosingMethodAttributeOffset.enclosing_method_attribute_size) {
             break;
         }
         int ioff = innerClassList.at(i +
                        InnerClassAttributeOffset.innerClassInnerClassInfoOffset);
         // 'ioff' can be zero.
         // refer to JVM spec. section 4.7.5.
         if (ioff != 0) {
            ConstantPool.CPSlot iclassInfo = getConstants().getSlotAt(ioff);
            Symbol innerName = getConstants().getKlassNameAt(ioff);
            Symbol myname = getName();
            int ooff = innerClassList.at(i +
                        InnerClassAttributeOffset.innerClassOuterClassInfoOffset);
            // for anonymous classes inner_name_index of InnerClasses
            // attribute is zero.
            int innerNameIndex = innerClassList.at(i +
                        InnerClassAttributeOffset.innerClassInnerNameOffset);
            // if this is not a member (anonymous, local etc.), 'ooff' will be zero
            // refer to JVM spec. section 4.7.5.
            if (ooff == 0) {
               if (includeLocals) {
                  // does it looks like my local class?
                  if (innerName.equals(sym) &&
                     innerName.asString().startsWith(myname.asString())) {
                     // exclude anonymous classes.
                     return (innerNameIndex != 0);
                  }
               }
            } else {
               ConstantPool.CPSlot oclassInfo = getConstants().getSlotAt(ooff);
               Symbol outerName = null;
               if (oclassInfo.isResolved()) {
                 outerName = oclassInfo.getKlass().getName();
               } else if (oclassInfo.isUnresolved()) {
                 outerName = oclassInfo.getSymbol();
               } else {
                  throw new RuntimeException("should not reach here");
               }

               // include only if current class is outer class.
               if (outerName.equals(myname) && innerName.equals(sym)) {
                  return true;
               }
           }
         }
       } // for inner classes
       return false;
    } else {
       return false;
    }
  }

  public boolean implementsInterface(Klass k) {
    if (Assert.ASSERTS_ENABLED) {
      Assert.that(k.isInterface(), "should not reach here");
    }
    KlassArray interfaces =  getTransitiveInterfaces();
    final int len = interfaces.length();
    for (int i = 0; i < len; i++) {
      if (interfaces.getAt(i).equals(k)) return true;
    }
    return false;
  }

  boolean computeSubtypeOf(Klass k) {
    if (k.isInterface()) {
      return implementsInterface(k);
    } else {
      return super.computeSubtypeOf(k);
    }
  }

  public void printValueOn(PrintStream tty) {
    tty.print("InstanceKlass for " + getName().asString());
  }

  public void iterateFields(MetadataVisitor visitor) {
    super.iterateFields(visitor);
    visitor.doMetadata(arrayKlasses, true);
    // visitor.doOop(methods, true);
    // visitor.doOop(localInterfaces, true);
    // visitor.doOop(transitiveInterfaces, true);
      visitor.doCInt(nonstaticFieldSize, true);
      visitor.doCInt(staticFieldSize, true);
      visitor.doCInt(staticOopFieldCount, true);
      visitor.doCInt(nonstaticOopMapSize, true);
      visitor.doCInt(isMarkedDependent, true);
      visitor.doCInt(initState, true);
      visitor.doCInt(vtableLen, true);
      visitor.doCInt(itableLen, true);
    }

  /*
   *  Visit the static fields of this InstanceKlass with the obj of
   *  the visitor set to the oop holding the fields, which is
   *  currently the java mirror.
   */
  public void iterateStaticFields(OopVisitor visitor) {
    visitor.setObj(getJavaMirror());
    visitor.prologue();
    iterateStaticFieldsInternal(visitor);
    visitor.epilogue();

  }

  void iterateStaticFieldsInternal(OopVisitor visitor) {
    int length = getJavaFieldsCount();
    for (int index = 0; index < length; index++) {
      short accessFlags    = getFieldAccessFlags(index);
      FieldType   type   = new FieldType(getFieldSignature(index));
      AccessFlags access = new AccessFlags(accessFlags);
      if (access.isStatic()) {
        visitField(visitor, type, index);
      }
    }
  }

  public Klass getJavaSuper() {
    return getSuper();
  }

  public static class StaticField {
    public AccessFlags flags;
    public Field field;

    StaticField(Field field, AccessFlags flags) {
      this.field = field;
      this.flags = flags;
    }
  }

  public Field[] getStaticFields() {
    U2Array fields = getFields();
    int length = getJavaFieldsCount();
    ArrayList result = new ArrayList();
    for (int index = 0; index < length; index++) {
      Field f = newField(index);
      if (f.isStatic()) {
        result.add(f);
      }
    }
    return (Field[])result.toArray(new Field[result.size()]);
  }

  public void iterateNonStaticFields(OopVisitor visitor, Oop obj) {
    if (getSuper() != null) {
      ((InstanceKlass) getSuper()).iterateNonStaticFields(visitor, obj);
    }
    int length = getJavaFieldsCount();
    for (int index = 0; index < length; index++) {
      short accessFlags    = getFieldAccessFlags(index);
      FieldType   type   = new FieldType(getFieldSignature(index));
      AccessFlags access = new AccessFlags(accessFlags);
      if (!access.isStatic()) {
        visitField(visitor, type, index);
      }
    }
  }

  /** Field access by name. */
  public Field findLocalField(Symbol name, Symbol sig) {
    int length = getJavaFieldsCount();
    for (int i = 0; i < length; i++) {
      Symbol f_name = getFieldName(i);
      Symbol f_sig  = getFieldSignature(i);
      if (name.equals(f_name) && sig.equals(f_sig)) {
        return newField(i);
      }
    }

    return null;
  }

  /** Find field in direct superinterfaces. */
  public Field findInterfaceField(Symbol name, Symbol sig) {
    KlassArray interfaces = getLocalInterfaces();
    int n = interfaces.length();
    for (int i = 0; i < n; i++) {
      InstanceKlass intf1 = (InstanceKlass) interfaces.getAt(i);
      if (Assert.ASSERTS_ENABLED) {
        Assert.that(intf1.isInterface(), "just checking type");
      }
      // search for field in current interface
      Field f = intf1.findLocalField(name, sig);
      if (f != null) {
        if (Assert.ASSERTS_ENABLED) {
          Assert.that(f.getAccessFlagsObj().isStatic(), "interface field must be static");
        }
        return f;
      }
      // search for field in direct superinterfaces
      f = intf1.findInterfaceField(name, sig);
      if (f != null) return f;
    }
    // otherwise field lookup fails
    return null;
  }

  /** Find field according to JVM spec 5.4.3.2, returns the klass in
      which the field is defined. */
  public Field findField(Symbol name, Symbol sig) {
    // search order according to newest JVM spec (5.4.3.2, p.167).
    // 1) search for field in current klass
    Field f = findLocalField(name, sig);
    if (f != null) return f;

    // 2) search for field recursively in direct superinterfaces
    f = findInterfaceField(name, sig);
    if (f != null) return f;

    // 3) apply field lookup recursively if superclass exists
    InstanceKlass supr = (InstanceKlass) getSuper();
    if (supr != null) return supr.findField(name, sig);

    // 4) otherwise field lookup fails
    return null;
  }

  /** Find field according to JVM spec 5.4.3.2, returns the klass in
      which the field is defined (convenience routine) */
  public Field findField(String name, String sig) {
    SymbolTable symbols = VM.getVM().getSymbolTable();
    Symbol nameSym = symbols.probe(name);
    Symbol sigSym  = symbols.probe(sig);
    if (nameSym == null || sigSym == null) {
      return null;
    }
    return findField(nameSym, sigSym);
  }

  /** Find field according to JVM spec 5.4.3.2, returns the klass in
      which the field is defined (retained only for backward
      compatibility with jdbx) */
  public Field findFieldDbg(String name, String sig) {
    return findField(name, sig);
  }

  /** Get field by its index in the fields array. Only designed for
      use in a debugging system. */
  public Field getFieldByIndex(int fieldIndex) {
    return newField(fieldIndex);
  }


    /** Return a List of SA Fields for the fields declared in this class.
        Inherited fields are not included.
        Return an empty list if there are no fields declared in this class.
        Only designed for use in a debugging system. */
    public List getImmediateFields() {
        // A list of Fields for each field declared in this class/interface,
        // not including inherited fields.
        int length = getJavaFieldsCount();
        List immediateFields = new ArrayList(length);
        for (int index = 0; index < length; index++) {
            immediateFields.add(getFieldByIndex(index));
        }

        return immediateFields;
    }

    /** Return a List of SA Fields for all the java fields in this class,
        including all inherited fields.  This includes hidden
        fields.  Thus the returned list can contain fields with
        the same name.
        Return an empty list if there are no fields.
        Only designed for use in a debugging system. */
    public List getAllFields() {
        // Contains a Field for each field in this class, including immediate
        // fields and inherited fields.
        List  allFields = getImmediateFields();

        // transitiveInterfaces contains all interfaces implemented
        // by this class and its superclass chain with no duplicates.

        KlassArray interfaces = getTransitiveInterfaces();
        int n = interfaces.length();
        for (int i = 0; i < n; i++) {
            InstanceKlass intf1 = (InstanceKlass) interfaces.getAt(i);
            if (Assert.ASSERTS_ENABLED) {
                Assert.that(intf1.isInterface(), "just checking type");
            }
            allFields.addAll(intf1.getImmediateFields());
        }

        // Get all fields in the superclass, recursively.  But, don't
        // include fields in interfaces implemented by superclasses;
        // we already have all those.
        if (!isInterface()) {
            InstanceKlass supr;
            if  ( (supr = (InstanceKlass) getSuper()) != null) {
                allFields.addAll(supr.getImmediateFields());
            }
        }

        return allFields;
    }


    /** Return a List of SA Methods declared directly in this class/interface.
        Return an empty list if there are none, or if this isn't a class/
        interface.
    */
    public List getImmediateMethods() {
      // Contains a Method for each method declared in this class/interface
      // not including inherited methods.

      MethodArray methods = getMethods();
      int length = methods.length();
      Object[] tmp = new Object[length];

      IntArray methodOrdering = getMethodOrdering();
      if (methodOrdering.length() != length) {
         // no ordering info present
         for (int index = 0; index < length; index++) {
            tmp[index] = methods.at(index);
         }
      } else {
         for (int index = 0; index < length; index++) {
            int originalIndex = methodOrdering.at(index);
            tmp[originalIndex] = methods.at(index);
         }
      }

      return Arrays.asList(tmp);
    }

    /** Return a List containing an SA InstanceKlass for each
        interface named in this class's 'implements' clause.
    */
    public List getDirectImplementedInterfaces() {
        // Contains an InstanceKlass for each interface in this classes
        // 'implements' clause.

        KlassArray interfaces = getLocalInterfaces();
        int length = interfaces.length();
        List directImplementedInterfaces = new ArrayList(length);

        for (int index = 0; index < length; index ++) {
            directImplementedInterfaces.add(interfaces.getAt(index));
        }

        return directImplementedInterfaces;
    }

  public Klass arrayKlassImpl(boolean orNull, int n) {
    // FIXME: in reflective system this would need to change to
    // actually allocate
    if (getArrayKlasses() == null) { return null; }
    ObjArrayKlass oak = (ObjArrayKlass) getArrayKlasses();
    if (orNull) {
      return oak.arrayKlassOrNull(n);
    }
    return oak.arrayKlass(n);
  }

  public Klass arrayKlassImpl(boolean orNull) {
    return arrayKlassImpl(orNull, 1);
  }

  public String signature() {
     return "L" + super.signature() + ";";
  }

  /** Convenience routine taking Strings; lookup is done in
      SymbolTable. */
  public Method findMethod(String name, String sig) {
    SymbolTable syms = VM.getVM().getSymbolTable();
    Symbol nameSym = syms.probe(name);
    Symbol sigSym  = syms.probe(sig);
    if (nameSym == null || sigSym == null) {
      return null;
    }
    return findMethod(nameSym, sigSym);
  }

  /** Find method in vtable. */
  public Method findMethod(Symbol name, Symbol sig) {
    return findMethod(getMethods(), name, sig);
  }

  /** Breakpoint support (see methods on Method* for details) */
  public BreakpointInfo getBreakpoints() {
    Address addr = getAddress().getAddressAt(breakpoints.getOffset());
    return (BreakpointInfo) VMObjectFactory.newObject(BreakpointInfo.class, addr);
  }

  public IntArray  getMethodOrdering() {
    Address addr = getAddress().getAddressAt(methodOrdering.getOffset());
    return (IntArray) VMObjectFactory.newObject(IntArray.class, addr);
  }

  public U2Array getFields() {
    Address addr = getAddress().getAddressAt(fields.getOffset());
    return (U2Array) VMObjectFactory.newObject(U2Array.class, addr);
  }

  public U2Array getInnerClasses() {
    Address addr = getAddress().getAddressAt(innerClasses.getOffset());
    return (U2Array) VMObjectFactory.newObject(U2Array.class, addr);
  }


  //----------------------------------------------------------------------
  // Internals only below this point
  //

  private void visitField(OopVisitor visitor, FieldType type, int index) {
    Field f = newField(index);
    if (type.isOop()) {
      visitor.doOop((OopField) f, false);
      return;
    }
    if (type.isByte()) {
      visitor.doByte((ByteField) f, false);
      return;
    }
    if (type.isChar()) {
      visitor.doChar((CharField) f, false);
      return;
    }
    if (type.isDouble()) {
      visitor.doDouble((DoubleField) f, false);
      return;
    }
    if (type.isFloat()) {
      visitor.doFloat((FloatField) f, false);
      return;
    }
    if (type.isInt()) {
      visitor.doInt((IntField) f, false);
      return;
    }
    if (type.isLong()) {
      visitor.doLong((LongField) f, false);
      return;
    }
    if (type.isShort()) {
      visitor.doShort((ShortField) f, false);
      return;
    }
    if (type.isBoolean()) {
      visitor.doBoolean((BooleanField) f, false);
      return;
    }
  }

  // Creates new field from index in fields TypeArray
  private Field newField(int index) {
    FieldType type = new FieldType(getFieldSignature(index));
    if (type.isOop()) {
     if (VM.getVM().isCompressedOopsEnabled()) {
        return new NarrowOopField(this, index);
     } else {
        return new OopField(this, index);
     }
    }
    if (type.isByte()) {
      return new ByteField(this, index);
    }
    if (type.isChar()) {
      return new CharField(this, index);
    }
    if (type.isDouble()) {
      return new DoubleField(this, index);
    }
    if (type.isFloat()) {
      return new FloatField(this, index);
    }
    if (type.isInt()) {
      return new IntField(this, index);
    }
    if (type.isLong()) {
      return new LongField(this, index);
    }
    if (type.isShort()) {
      return new ShortField(this, index);
    }
    if (type.isBoolean()) {
      return new BooleanField(this, index);
    }
    throw new RuntimeException("Illegal field type at index " + index);
  }

  private static Method findMethod(MethodArray methods, Symbol name, Symbol signature) {
    int len = methods.length();
    // methods are sorted, so do binary search
    int l = 0;
    int h = len - 1;
    while (l <= h) {
      int mid = (l + h) >> 1;
      Method m = methods.at(mid);
      int res = m.getName().fastCompare(name);
      if (res == 0) {
        // found matching name; do linear search to find matching signature
        // first, quick check for common case
        if (m.getSignature().equals(signature)) return m;
        // search downwards through overloaded methods
        int i;
        for (i = mid - 1; i >= l; i--) {
          Method m1 = methods.at(i);
          if (!m1.getName().equals(name)) break;
          if (m1.getSignature().equals(signature)) return m1;
        }
        // search upwards
        for (i = mid + 1; i <= h; i++) {
          Method m1 = methods.at(i);
          if (!m1.getName().equals(name)) break;
          if (m1.getSignature().equals(signature)) return m1;
        }
        // not found
        if (Assert.ASSERTS_ENABLED) {
          int index = linearSearch(methods, name, signature);
          if (index != -1) {
            throw new DebuggerException("binary search bug: should have found entry " + index);
          }
        }
        return null;
      } else if (res < 0) {
        l = mid + 1;
      } else {
        h = mid - 1;
      }
    }
    if (Assert.ASSERTS_ENABLED) {
      int index = linearSearch(methods, name, signature);
      if (index != -1) {
        throw new DebuggerException("binary search bug: should have found entry " + index);
      }
    }
    return null;
  }

  private static int linearSearch(MethodArray methods, Symbol name, Symbol signature) {
    int len = (int) methods.length();
    for (int index = 0; index < len; index++) {
      Method m = methods.at(index);
      if (m.getSignature().equals(signature) && m.getName().equals(name)) {
        return index;
      }
    }
    return -1;
  }

  public void dumpReplayData(PrintStream out) {
    ConstantPool cp = getConstants();

    // Try to record related loaded classes
    Klass sub = getSubklassKlass();
    while (sub != null) {
        if (sub instanceof InstanceKlass) {
            out.println("instanceKlass " + sub.getName().asString());
        }
        sub = sub.getNextSiblingKlass();
    }

    final int length = (int) cp.getLength();
    out.print("ciInstanceKlass " + getName().asString() + " " + (isLinked() ? 1 : 0) + " " + (isInitialized() ? 1 : 0) + " " + length);
    for (int index = 1; index < length; index++) {
      out.print(" " + cp.getTags().at(index));
    }
    out.println();
    if (isInitialized()) {
      Field[] staticFields = getStaticFields();
      for (int i = 0; i < staticFields.length; i++) {
        Field f = staticFields[i];
        Oop mirror = getJavaMirror();
        if (f.isFinal() && !f.hasInitialValue()) {
          out.print("staticfield " + getName().asString() + " " +
                    OopUtilities.escapeString(f.getID().getName()) + " " +
                    f.getFieldType().getSignature().asString() + " ");
          if (f instanceof ByteField) {
            ByteField bf = (ByteField)f;
            out.println(bf.getValue(mirror));
          } else if (f instanceof BooleanField) {
            BooleanField bf = (BooleanField)f;
            out.println(bf.getValue(mirror) ? 1 : 0);
          } else if (f instanceof ShortField) {
            ShortField bf = (ShortField)f;
            out.println(bf.getValue(mirror));
          } else if (f instanceof CharField) {
            CharField bf = (CharField)f;
            out.println(bf.getValue(mirror) & 0xffff);
          } else if (f instanceof IntField) {
            IntField bf = (IntField)f;
            out.println(bf.getValue(mirror));
          } else  if (f instanceof LongField) {
            LongField bf = (LongField)f;
            out.println(bf.getValue(mirror));
          } else if (f instanceof FloatField) {
            FloatField bf = (FloatField)f;
            out.println(Float.floatToRawIntBits(bf.getValue(mirror)));
          } else if (f instanceof DoubleField) {
            DoubleField bf = (DoubleField)f;
            out.println(Double.doubleToRawLongBits(bf.getValue(mirror)));
          } else if (f instanceof OopField) {
            OopField bf = (OopField)f;

            Oop value = bf.getValue(mirror);
            if (value == null) {
              out.println("null");
            } else if (value.isInstance()) {
              Instance inst = (Instance)value;
              if (inst.isA(SystemDictionary.getStringKlass())) {
                out.println("\"" + OopUtilities.stringOopToEscapedString(inst) + "\"");
              } else {
                out.println(inst.getKlass().getName().asString());
              }
            } else if (value.isObjArray()) {
              ObjArray oa = (ObjArray)value;
              Klass ek = (ObjArrayKlass)oa.getKlass();
              out.println(oa.getLength() + " " + ek.getName().asString());
            } else if (value.isTypeArray()) {
              TypeArray ta = (TypeArray)value;
              out.println(ta.getLength());
            } else {
              out.println(value);
            }
          }
        }
      }
    }
  }
}
