/** Field access by name. */
  public Field findLocalField(Symbol name, Symbol sig) {
    TypeArray fields = getFields();
    int n = (int) fields.getLength();
    ConstantPool cp = getConstants();
    for (int i = 0; i < n; i += NEXT_OFFSET) {
      int nameIndex = fields.getShortAt(i + NAME_INDEX_OFFSET);
      int sigIndex = fields.getShortAt(i + SIGNATURE_INDEX_OFFSET);
      Symbol f_name = cp.getSymbolAt(nameIndex);
      Symbol f_sig = cp.getSymbolAt(sigIndex);
      if (name.equals(f_name) && sig.equals(f_sig)) {
        return newField(i);
      }
    }

    return null;
  }
  public void iterateNonStaticFields(OopVisitor visitor) {
    if (getSuper() != null) {
      ((InstanceKlass) getSuper()).iterateNonStaticFields(visitor);
    }
    TypeArray fields = getFields();

    int length = (int) fields.getLength();
    for (int index = 0; index < length; index += NEXT_OFFSET) {
      short accessFlags = fields.getShortAt(index + ACCESS_FLAGS_OFFSET);
      short signatureIndex = fields.getShortAt(index + SIGNATURE_INDEX_OFFSET);

      FieldType type = new FieldType((Symbol) getConstants().getObjAt(signatureIndex));
      AccessFlags access = new AccessFlags(accessFlags);
      if (!access.isStatic()) {
        visitField(visitor, type, index);
      }
    }
  }
  // refer to compute_modifier_flags in VM code.
  public long computeModifierFlags() {
    long access = getAccessFlags();
    // But check if it happens to be member class.
    TypeArray innerClassList = getInnerClasses();
    int length = (innerClassList == null) ? 0 : (int) innerClassList.getLength();
    if (length > 0) {
      if (Assert.ASSERTS_ENABLED) {
        Assert.that(length % InnerClassAttributeOffset.innerClassNextOffset == 0, "just checking");
      }
      for (int i = 0; i < length; i += InnerClassAttributeOffset.innerClassNextOffset) {
        int ioff =
            innerClassList.getShortAt(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.
          Oop classInfo = getConstants().getObjAt(ioff);
          Symbol name = null;
          if (classInfo instanceof Klass) {
            name = ((Klass) classInfo).getName();
          } else if (classInfo instanceof Symbol) {
            name = (Symbol) classInfo;
          } else {
            throw new RuntimeException("should not reach here");
          }

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

    // Remember to strip ACC_SUPER bit
    return (access & (~JVM_ACC_SUPER)) & JVM_ACC_WRITTEN_FLAGS;
  }
  public void iterateFields(OopVisitor visitor, boolean doVMFields) {
    super.iterateFields(visitor, doVMFields);
    if (doVMFields) {
      visitor.doOop(arrayKlasses, true);
      visitor.doOop(methods, true);
      visitor.doOop(methodOrdering, true);
      visitor.doOop(localInterfaces, true);
      visitor.doOop(transitiveInterfaces, true);
      visitor.doCInt(nofImplementors, true);
      for (int i = 0; i < IMPLEMENTORS_LIMIT; i++) visitor.doOop(implementors[i], true);
      visitor.doOop(fields, true);
      visitor.doOop(constants, true);
      visitor.doOop(classLoader, true);
      visitor.doOop(protectionDomain, true);
      visitor.doOop(signers, true);
      visitor.doOop(sourceFileName, true);
      visitor.doOop(innerClasses, true);
      visitor.doCInt(nonstaticFieldSize, true);
      visitor.doCInt(staticFieldSize, true);
      visitor.doCInt(staticOopFieldSize, true);
      visitor.doCInt(nonstaticOopMapSize, true);
      visitor.doCInt(isMarkedDependent, true);
      visitor.doCInt(initState, true);
      visitor.doCInt(vtableLen, true);
      visitor.doCInt(itableLen, true);
    }

    TypeArray fields = getFields();
    int length = (int) fields.getLength();
    for (int index = 0; index < length; index += NEXT_OFFSET) {
      short accessFlags = fields.getShortAt(index + ACCESS_FLAGS_OFFSET);
      short signatureIndex = fields.getShortAt(index + SIGNATURE_INDEX_OFFSET);
      FieldType type = new FieldType((Symbol) getConstants().getObjAt(signatureIndex));
      AccessFlags access = new AccessFlags(accessFlags);
      if (access.isStatic()) {
        visitField(visitor, type, index);
      }
    }
  }
 // Creates new field from index in fields TypeArray
 private Field newField(int index) {
   TypeArray fields = getFields();
   short signatureIndex = fields.getShortAt(index + SIGNATURE_INDEX_OFFSET);
   FieldType type = new FieldType((Symbol) getConstants().getObjAt(signatureIndex));
   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 boolean isInInnerClasses(Symbol sym, boolean includeLocals) {
    TypeArray innerClassList = getInnerClasses();
    int length = (innerClassList == null) ? 0 : (int) innerClassList.getLength();
    if (length > 0) {
      if (Assert.ASSERTS_ENABLED) {
        Assert.that(length % InnerClassAttributeOffset.innerClassNextOffset == 0, "just checking");
      }
      for (int i = 0; i < length; i += InnerClassAttributeOffset.innerClassNextOffset) {
        int ioff =
            innerClassList.getShortAt(i + InnerClassAttributeOffset.innerClassInnerClassInfoOffset);
        // 'ioff' can be zero.
        // refer to JVM spec. section 4.7.5.
        if (ioff != 0) {
          Oop iclassInfo = getConstants().getObjAt(ioff);
          Symbol innerName = null;
          if (iclassInfo instanceof Klass) {
            innerName = ((Klass) iclassInfo).getName();
          } else if (iclassInfo instanceof Symbol) {
            innerName = (Symbol) iclassInfo;
          } else {
            throw new RuntimeException("should not reach here");
          }

          Symbol myname = getName();
          int ooff =
              innerClassList.getShortAt(
                  i + InnerClassAttributeOffset.innerClassOuterClassInfoOffset);
          // for anonymous classes inner_name_index of InnerClasses
          // attribute is zero.
          int innerNameIndex =
              innerClassList.getShortAt(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 {
            Oop oclassInfo = getConstants().getObjAt(ooff);
            Symbol outerName = null;
            if (oclassInfo instanceof Klass) {
              outerName = ((Klass) oclassInfo).getName();
            } else if (oclassInfo instanceof Symbol) {
              outerName = (Symbol) oclassInfo;
            } 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;
    }
  }