InstanceKlass.java 37.3 KB
Newer Older
D
duke 已提交
1
/*
2
 * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
D
duke 已提交
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
 * 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.
 *
19 20 21
 * 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.
D
duke 已提交
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
 *
 */

package sun.jvm.hotspot.oops;

import java.io.*;
import java.util.*;
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
N
never 已提交
47 48 49 50 51 52 53 54
  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 GENERIC_SIGNATURE_INDEX_OFFSET;
  private static int FIELD_SLOTS;
D
duke 已提交
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
  public static int IMPLEMENTORS_LIMIT;

  // ClassState constants
  private static int CLASS_STATE_UNPARSABLE_BY_GC;
  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 OopField(type.getOopField("_array_klasses"), Oop.getHeaderSize());
    methods              = new OopField(type.getOopField("_methods"), Oop.getHeaderSize());
    methodOrdering       = new OopField(type.getOopField("_method_ordering"), Oop.getHeaderSize());
    localInterfaces      = new OopField(type.getOopField("_local_interfaces"), Oop.getHeaderSize());
    transitiveInterfaces = new OopField(type.getOopField("_transitive_interfaces"), Oop.getHeaderSize());
    nofImplementors      = new CIntField(type.getCIntegerField("_nof_implementors"), Oop.getHeaderSize());
    IMPLEMENTORS_LIMIT   = db.lookupIntConstant("instanceKlass::implementors_limit").intValue();
    implementors         = new OopField[IMPLEMENTORS_LIMIT];
    for (int i = 0; i < IMPLEMENTORS_LIMIT; i++) {
      long arrayOffset = Oop.getHeaderSize() + (i * db.getAddressSize());
      implementors[i]    = new OopField(type.getOopField("_implementors[0]"), arrayOffset);
    }
    fields               = new OopField(type.getOopField("_fields"), Oop.getHeaderSize());
81
    javaFieldsCount      = new CIntField(type.getCIntegerField("_java_fields_count"), Oop.getHeaderSize());
D
duke 已提交
82 83 84 85
    constants            = new OopField(type.getOopField("_constants"), Oop.getHeaderSize());
    classLoader          = new OopField(type.getOopField("_class_loader"), Oop.getHeaderSize());
    protectionDomain     = new OopField(type.getOopField("_protection_domain"), Oop.getHeaderSize());
    signers              = new OopField(type.getOopField("_signers"), Oop.getHeaderSize());
86 87
    sourceFileName       = type.getAddressField("_source_file_name");
    sourceDebugExtension = type.getAddressField("_source_debug_extension");
D
duke 已提交
88 89 90
    innerClasses         = new OopField(type.getOopField("_inner_classes"), Oop.getHeaderSize());
    nonstaticFieldSize   = new CIntField(type.getCIntegerField("_nonstatic_field_size"), Oop.getHeaderSize());
    staticFieldSize      = new CIntField(type.getCIntegerField("_static_field_size"), Oop.getHeaderSize());
91
    staticOopFieldCount   = new CIntField(type.getCIntegerField("_static_oop_field_count"), Oop.getHeaderSize());
D
duke 已提交
92 93 94 95 96 97
    nonstaticOopMapSize  = new CIntField(type.getCIntegerField("_nonstatic_oop_map_size"), Oop.getHeaderSize());
    isMarkedDependent    = new CIntField(type.getCIntegerField("_is_marked_dependent"), Oop.getHeaderSize());
    initState            = new CIntField(type.getCIntegerField("_init_state"), Oop.getHeaderSize());
    vtableLen            = new CIntField(type.getCIntegerField("_vtable_len"), Oop.getHeaderSize());
    itableLen            = new CIntField(type.getCIntegerField("_itable_len"), Oop.getHeaderSize());
    breakpoints          = type.getAddressField("_breakpoints");
98
    genericSignature     = type.getAddressField("_generic_signature");
D
duke 已提交
99 100 101 102 103
    majorVersion         = new CIntField(type.getCIntegerField("_major_version"), Oop.getHeaderSize());
    minorVersion         = new CIntField(type.getCIntegerField("_minor_version"), Oop.getHeaderSize());
    headerSize           = alignObjectOffset(Oop.getHeaderSize() + type.getSize());

    // read field offset constants
104 105 106 107 108 109 110 111
    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_offset").intValue();
    HIGH_OFFSET                    = db.lookupIntConstant("FieldInfo::high_offset").intValue();
    GENERIC_SIGNATURE_INDEX_OFFSET = db.lookupIntConstant("FieldInfo::generic_signature_offset").intValue();
    FIELD_SLOTS                    = db.lookupIntConstant("FieldInfo::field_slots").intValue();
D
duke 已提交
112 113 114 115 116 117 118 119 120 121 122 123 124
    // read ClassState constants
    CLASS_STATE_UNPARSABLE_BY_GC = db.lookupIntConstant("instanceKlass::unparsable_by_gc").intValue();
    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();

  }

  InstanceKlass(OopHandle handle, ObjectHeap heap) {
    super(handle, heap);
N
never 已提交
125 126 127 128 129 130 131
    if (getJavaFieldsCount() != getAllFieldsCount()) {
      // Exercise the injected field logic
      for (int i = getJavaFieldsCount(); i < getAllFieldsCount(); i++) {
        getFieldName(i);
        getFieldSignature(i);
      }
    }
D
duke 已提交
132 133 134 135 136 137 138 139 140 141
  }

  private static OopField  arrayKlasses;
  private static OopField  methods;
  private static OopField  methodOrdering;
  private static OopField  localInterfaces;
  private static OopField  transitiveInterfaces;
  private static CIntField nofImplementors;
  private static OopField[] implementors;
  private static OopField  fields;
142
  private static CIntField javaFieldsCount;
D
duke 已提交
143 144 145 146
  private static OopField  constants;
  private static OopField  classLoader;
  private static OopField  protectionDomain;
  private static OopField  signers;
147 148
  private static AddressField  sourceFileName;
  private static AddressField  sourceDebugExtension;
D
duke 已提交
149 150 151
  private static OopField  innerClasses;
  private static CIntField nonstaticFieldSize;
  private static CIntField staticFieldSize;
152
  private static CIntField staticOopFieldCount;
D
duke 已提交
153 154 155 156 157 158
  private static CIntField nonstaticOopMapSize;
  private static CIntField isMarkedDependent;
  private static CIntField initState;
  private static CIntField vtableLen;
  private static CIntField itableLen;
  private static AddressField breakpoints;
159
  private static AddressField  genericSignature;
D
duke 已提交
160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183
  private static CIntField majorVersion;
  private static CIntField minorVersion;

  // type safe enum for ClassState from instanceKlass.hpp
  public static class ClassState {
     public static final ClassState UNPARSABLE_BY_GC = new ClassState("unparsable_by_gc");
     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;
  }

N
never 已提交
184
  public int  getInitStateAsInt() { return (int) initState.getValue(this); }
D
duke 已提交
185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252
  public ClassState getInitState() {
     int state = getInitStateAsInt();
     if (state == CLASS_STATE_UNPARSABLE_BY_GC) {
        return ClassState.UNPARSABLE_BY_GC;
     } else 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;

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

D
duke 已提交
257 258
  public static long getHeaderSize() { return headerSize; }

259 260 261 262
  public short getFieldAccessFlags(int index) {
    return getFields().getShortAt(index * FIELD_SLOTS + ACCESS_FLAGS_OFFSET);
  }

N
never 已提交
263 264 265 266 267
  public short getFieldNameIndex(int index) {
    if (index >= getJavaFieldsCount()) throw new IndexOutOfBoundsException("not a Java field;");
    return getFields().getShortAt(index * FIELD_SLOTS + NAME_INDEX_OFFSET);
  }

268 269
  public Symbol getFieldName(int index) {
    int nameIndex = getFields().getShortAt(index * FIELD_SLOTS + NAME_INDEX_OFFSET);
N
never 已提交
270 271 272 273 274 275 276 277 278 279
    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().getShortAt(index * FIELD_SLOTS + SIGNATURE_INDEX_OFFSET);
280 281 282 283
  }

  public Symbol getFieldSignature(int index) {
    int signatureIndex = getFields().getShortAt(index * FIELD_SLOTS + SIGNATURE_INDEX_OFFSET);
N
never 已提交
284 285 286 287 288 289 290 291 292
    if (index < getJavaFieldsCount()) {
      return getConstants().getSymbolAt(signatureIndex);
    } else {
      return vmSymbols.symbolAt(signatureIndex);
    }
  }

  public short getFieldGenericSignatureIndex(int index) {
    return getFields().getShortAt(index * FIELD_SLOTS + GENERIC_SIGNATURE_INDEX_OFFSET);
293 294 295
  }

  public Symbol getFieldGenericSignature(int index) {
N
never 已提交
296
    short genericSignatureIndex = getFieldGenericSignatureIndex(index);
297 298 299 300 301 302
    if (genericSignatureIndex != 0)  {
      return getConstants().getSymbolAt(genericSignatureIndex);
    }
    return null;
  }

N
never 已提交
303 304 305 306 307
  public short getFieldInitialValueIndex(int index) {
    if (index >= getJavaFieldsCount()) throw new IndexOutOfBoundsException("not a Java field;");
    return getFields().getShortAt(index * FIELD_SLOTS + INITVAL_INDEX_OFFSET);
  }

308 309 310 311 312 313
  public int getFieldOffset(int index) {
    TypeArray fields = getFields();
    return VM.getVM().buildIntFromShorts(fields.getShortAt(index * FIELD_SLOTS + LOW_OFFSET),
                                         fields.getShortAt(index * FIELD_SLOTS + HIGH_OFFSET));
  }

D
duke 已提交
314 315 316 317 318 319 320 321 322 323
  // Accessors for declared fields
  public Klass     getArrayKlasses()        { return (Klass)        arrayKlasses.getValue(this); }
  public ObjArray  getMethods()             { return (ObjArray)     methods.getValue(this); }
  public TypeArray getMethodOrdering()      { return (TypeArray)    methodOrdering.getValue(this); }
  public ObjArray  getLocalInterfaces()     { return (ObjArray)     localInterfaces.getValue(this); }
  public ObjArray  getTransitiveInterfaces() { return (ObjArray)     transitiveInterfaces.getValue(this); }
  public long      nofImplementors()        { return                nofImplementors.getValue(this); }
  public Klass     getImplementor()         { return (Klass)        implementors[0].getValue(this); }
  public Klass     getImplementor(int i)    { return (Klass)        implementors[i].getValue(this); }
  public TypeArray getFields()              { return (TypeArray)    fields.getValue(this); }
324
  public int       getJavaFieldsCount()     { return                (int) javaFieldsCount.getValue(this); }
N
never 已提交
325
  public int       getAllFieldsCount()      { return                (int)getFields().getLength() / FIELD_SLOTS; }
D
duke 已提交
326 327 328 329
  public ConstantPool getConstants()        { return (ConstantPool) constants.getValue(this); }
  public Oop       getClassLoader()         { return                classLoader.getValue(this); }
  public Oop       getProtectionDomain()    { return                protectionDomain.getValue(this); }
  public ObjArray  getSigners()             { return (ObjArray)     signers.getValue(this); }
330 331
  public Symbol    getSourceFileName()      { return getSymbol(sourceFileName); }
  public Symbol    getSourceDebugExtension(){ return getSymbol(sourceDebugExtension); }
D
duke 已提交
332 333
  public TypeArray getInnerClasses()        { return (TypeArray)    innerClasses.getValue(this); }
  public long      getNonstaticFieldSize()  { return                nonstaticFieldSize.getValue(this); }
334
  public long      getStaticOopFieldCount() { return                staticOopFieldCount.getValue(this); }
D
duke 已提交
335 336 337 338
  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); }
339
  public Symbol    getGenericSignature()    { return getSymbol(genericSignature); }
D
duke 已提交
340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379
  public long      majorVersion()           { return                majorVersion.getValue(this); }
  public long      minorVersion()           { return                minorVersion.getValue(this); }

  // "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;
  };

  // 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.
380
             ConstantPool.CPSlot classInfo = getConstants().getSlotAt(ioff);
D
duke 已提交
381
             Symbol name = null;
382 383 384 385
             if (classInfo.isOop()) {
               name = ((Klass) classInfo.getOop()).getName();
             } else if (classInfo.isMetaData()) {
               name = classInfo.getSymbol();
D
duke 已提交
386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429
             } 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;
  }


  // 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) {
    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) {
430
            ConstantPool.CPSlot iclassInfo = getConstants().getSlotAt(ioff);
D
duke 已提交
431
            Symbol innerName = null;
432 433 434 435
            if (iclassInfo.isOop()) {
              innerName = ((Klass) iclassInfo.getOop()).getName();
            } else if (iclassInfo.isMetaData()) {
              innerName = iclassInfo.getSymbol();
D
duke 已提交
436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458
            } 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 {
459
               ConstantPool.CPSlot oclassInfo = getConstants().getSlotAt(ooff);
D
duke 已提交
460
               Symbol outerName = null;
461 462 463 464
               if (oclassInfo.isOop()) {
                 outerName = ((Klass) oclassInfo.getOop()).getName();
               } else if (oclassInfo.isMetaData()) {
                 outerName = oclassInfo.getSymbol();
D
duke 已提交
465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524
               } 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");
    }
    ObjArray interfaces =  getTransitiveInterfaces();
    final int len = (int) interfaces.getLength();
    for (int i = 0; i < len; i++) {
      if (interfaces.getObjAt(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(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(innerClasses, true);
      visitor.doCInt(nonstaticFieldSize, true);
      visitor.doCInt(staticFieldSize, true);
525
      visitor.doCInt(staticOopFieldCount, true);
D
duke 已提交
526 527 528 529 530 531
      visitor.doCInt(nonstaticOopMapSize, true);
      visitor.doCInt(isMarkedDependent, true);
      visitor.doCInt(initState, true);
      visitor.doCInt(vtableLen, true);
      visitor.doCInt(itableLen, true);
    }
532 533 534 535 536 537 538 539 540 541 542 543 544 545
  }

  /*
   *  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();

  }
D
duke 已提交
546

547
  void iterateStaticFieldsInternal(OopVisitor visitor) {
548
    int length = getJavaFieldsCount();
N
never 已提交
549 550 551
    for (int index = 0; index < length; index++) {
      short accessFlags    = getFieldAccessFlags(index);
      FieldType   type   = new FieldType(getFieldSignature(index));
D
duke 已提交
552 553 554 555 556 557 558 559 560 561 562
      AccessFlags access = new AccessFlags(accessFlags);
      if (access.isStatic()) {
        visitField(visitor, type, index);
      }
    }
  }

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

N
never 已提交
563 564 565 566 567 568 569 570 571 572
  public static class StaticField {
    public AccessFlags flags;
    public Field field;

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

573
  public void iterateNonStaticFields(OopVisitor visitor, Oop obj) {
D
duke 已提交
574
    if (getSuper() != null) {
575
      ((InstanceKlass) getSuper()).iterateNonStaticFields(visitor, obj);
D
duke 已提交
576
    }
577
    int length = getJavaFieldsCount();
N
never 已提交
578 579 580
    for (int index = 0; index < length; index++) {
      short accessFlags    = getFieldAccessFlags(index);
      FieldType   type   = new FieldType(getFieldSignature(index));
D
duke 已提交
581 582 583 584 585 586 587 588 589
      AccessFlags access = new AccessFlags(accessFlags);
      if (!access.isStatic()) {
        visitField(visitor, type, index);
      }
    }
  }

  /** Field access by name. */
  public Field findLocalField(Symbol name, Symbol sig) {
N
never 已提交
590
    int length = getJavaFieldsCount();
N
never 已提交
591 592 593
    for (int i = 0; i < length; i++) {
      Symbol f_name = getFieldName(i);
      Symbol f_sig  = getFieldSignature(i);
D
duke 已提交
594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667
      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) {
    ObjArray interfaces = getLocalInterfaces();
    int n = (int) interfaces.getLength();
    for (int i = 0; i < n; i++) {
      InstanceKlass intf1 = (InstanceKlass) interfaces.getObjAt(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. */
N
never 已提交
668 669
  public Field getFieldByIndex(int fieldIndex) {
    return newField(fieldIndex);
D
duke 已提交
670 671 672 673 674 675 676 677 678 679
  }


    /** 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.
680 681
        int length = getJavaFieldsCount();
        List immediateFields = new ArrayList(length);
N
never 已提交
682
        for (int index = 0; index < length; index++) {
D
duke 已提交
683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776
            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.

        ObjArray interfaces = getTransitiveInterfaces();
        int n = (int) interfaces.getLength();
        for (int i = 0; i < n; i++) {
            InstanceKlass intf1 = (InstanceKlass) interfaces.getObjAt(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.

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

      TypeArray methodOrdering = getMethodOrdering();
      if (methodOrdering.getLength() != length) {
         // no ordering info present
         for (int index = 0; index < length; index++) {
            tmp[index] = methods.getObjAt(index);
         }
      } else {
         for (int index = 0; index < length; index++) {
            int originalIndex = getMethodOrdering().getIntAt(index);
            tmp[originalIndex] = methods.getObjAt(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.

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

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

        return directImplementedInterfaces;
    }


  public long getObjectSize() {
    long bodySize =    alignObjectOffset(getVtableLen() * getHeap().getOopSize())
                     + alignObjectOffset(getItableLen() * getHeap().getOopSize())
777
                     + (getNonstaticOopMapSize()) * getHeap().getOopSize();
D
duke 已提交
778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868
    return alignObjectSize(headerSize + bodySize);
  }

  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 methodOop for details) */
  public BreakpointInfo getBreakpoints() {
    Address addr = getHandle().getAddressAt(Oop.getHeaderSize() + breakpoints.getOffset());
    return (BreakpointInfo) VMObjectFactory.newObject(BreakpointInfo.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) {
N
never 已提交
869
    FieldType type = new FieldType(getFieldSignature(index));
D
duke 已提交
870
    if (type.isOop()) {
871 872 873 874 875
     if (VM.getVM().isCompressedOopsEnabled()) {
        return new NarrowOopField(this, index);
     } else {
        return new OopField(this, index);
     }
D
duke 已提交
876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963
    }
    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(ObjArray methods, Symbol name, Symbol signature) {
    int len = (int) methods.getLength();
    // methods are sorted, so do binary search
    int l = 0;
    int h = len - 1;
    while (l <= h) {
      int mid = (l + h) >> 1;
      Method m = (Method) methods.getObjAt(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 = (Method) methods.getObjAt(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 = (Method) methods.getObjAt(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(ObjArray methods, Symbol name, Symbol signature) {
    int len = (int) methods.getLength();
    for (int index = 0; index < len; index++) {
      Method m = (Method) methods.getObjAt(index);
      if (m.getSignature().equals(signature) && m.getName().equals(name)) {
        return index;
      }
    }
    return -1;
  }
}