agent/src/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java

Sun, 11 Sep 2011 14:48:24 -0700

author
never
date
Sun, 11 Sep 2011 14:48:24 -0700
changeset 3138
f6f3bb0ee072
parent 3137
e6b1331a51d2
child 3143
35c656d0b685
permissions
-rw-r--r--

7088955: add C2 IR support to the SA
Reviewed-by: kvn

duke@435 1 /*
never@2658 2 * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
duke@435 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
duke@435 4 *
duke@435 5 * This code is free software; you can redistribute it and/or modify it
duke@435 6 * under the terms of the GNU General Public License version 2 only, as
duke@435 7 * published by the Free Software Foundation.
duke@435 8 *
duke@435 9 * This code is distributed in the hope that it will be useful, but WITHOUT
duke@435 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
duke@435 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
duke@435 12 * version 2 for more details (a copy is included in the LICENSE file that
duke@435 13 * accompanied this code).
duke@435 14 *
duke@435 15 * You should have received a copy of the GNU General Public License version
duke@435 16 * 2 along with this work; if not, write to the Free Software Foundation,
duke@435 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
duke@435 18 *
trims@1907 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
trims@1907 20 * or visit www.oracle.com if you need additional information or have any
trims@1907 21 * questions.
duke@435 22 *
duke@435 23 */
duke@435 24
duke@435 25 package sun.jvm.hotspot.oops;
duke@435 26
duke@435 27 import java.io.*;
duke@435 28 import java.util.*;
duke@435 29 import sun.jvm.hotspot.debugger.*;
duke@435 30 import sun.jvm.hotspot.memory.*;
duke@435 31 import sun.jvm.hotspot.runtime.*;
duke@435 32 import sun.jvm.hotspot.types.*;
duke@435 33 import sun.jvm.hotspot.utilities.*;
duke@435 34
duke@435 35 // An InstanceKlass is the VM level representation of a Java class.
duke@435 36
duke@435 37 public class InstanceKlass extends Klass {
duke@435 38 static {
duke@435 39 VM.registerVMInitializedObserver(new Observer() {
duke@435 40 public void update(Observable o, Object data) {
duke@435 41 initialize(VM.getVM().getTypeDataBase());
duke@435 42 }
duke@435 43 });
duke@435 44 }
duke@435 45
duke@435 46 // field offset constants
duke@435 47 public static int ACCESS_FLAGS_OFFSET;
duke@435 48 public static int NAME_INDEX_OFFSET;
duke@435 49 public static int SIGNATURE_INDEX_OFFSET;
duke@435 50 public static int INITVAL_INDEX_OFFSET;
duke@435 51 public static int LOW_OFFSET;
duke@435 52 public static int HIGH_OFFSET;
duke@435 53 public static int GENERIC_SIGNATURE_INDEX_OFFSET;
never@3137 54 public static int FIELD_SLOTS;
duke@435 55 public static int IMPLEMENTORS_LIMIT;
duke@435 56
duke@435 57 // ClassState constants
duke@435 58 private static int CLASS_STATE_UNPARSABLE_BY_GC;
duke@435 59 private static int CLASS_STATE_ALLOCATED;
duke@435 60 private static int CLASS_STATE_LOADED;
duke@435 61 private static int CLASS_STATE_LINKED;
duke@435 62 private static int CLASS_STATE_BEING_INITIALIZED;
duke@435 63 private static int CLASS_STATE_FULLY_INITIALIZED;
duke@435 64 private static int CLASS_STATE_INITIALIZATION_ERROR;
duke@435 65
duke@435 66 private static synchronized void initialize(TypeDataBase db) throws WrongTypeException {
duke@435 67 Type type = db.lookupType("instanceKlass");
duke@435 68 arrayKlasses = new OopField(type.getOopField("_array_klasses"), Oop.getHeaderSize());
duke@435 69 methods = new OopField(type.getOopField("_methods"), Oop.getHeaderSize());
duke@435 70 methodOrdering = new OopField(type.getOopField("_method_ordering"), Oop.getHeaderSize());
duke@435 71 localInterfaces = new OopField(type.getOopField("_local_interfaces"), Oop.getHeaderSize());
duke@435 72 transitiveInterfaces = new OopField(type.getOopField("_transitive_interfaces"), Oop.getHeaderSize());
duke@435 73 nofImplementors = new CIntField(type.getCIntegerField("_nof_implementors"), Oop.getHeaderSize());
duke@435 74 IMPLEMENTORS_LIMIT = db.lookupIntConstant("instanceKlass::implementors_limit").intValue();
duke@435 75 implementors = new OopField[IMPLEMENTORS_LIMIT];
duke@435 76 for (int i = 0; i < IMPLEMENTORS_LIMIT; i++) {
duke@435 77 long arrayOffset = Oop.getHeaderSize() + (i * db.getAddressSize());
duke@435 78 implementors[i] = new OopField(type.getOopField("_implementors[0]"), arrayOffset);
duke@435 79 }
duke@435 80 fields = new OopField(type.getOopField("_fields"), Oop.getHeaderSize());
never@3137 81 javaFieldsCount = new CIntField(type.getCIntegerField("_java_fields_count"), Oop.getHeaderSize());
duke@435 82 constants = new OopField(type.getOopField("_constants"), Oop.getHeaderSize());
duke@435 83 classLoader = new OopField(type.getOopField("_class_loader"), Oop.getHeaderSize());
duke@435 84 protectionDomain = new OopField(type.getOopField("_protection_domain"), Oop.getHeaderSize());
duke@435 85 signers = new OopField(type.getOopField("_signers"), Oop.getHeaderSize());
coleenp@2497 86 sourceFileName = type.getAddressField("_source_file_name");
coleenp@2497 87 sourceDebugExtension = type.getAddressField("_source_debug_extension");
duke@435 88 innerClasses = new OopField(type.getOopField("_inner_classes"), Oop.getHeaderSize());
duke@435 89 nonstaticFieldSize = new CIntField(type.getCIntegerField("_nonstatic_field_size"), Oop.getHeaderSize());
duke@435 90 staticFieldSize = new CIntField(type.getCIntegerField("_static_field_size"), Oop.getHeaderSize());
never@2658 91 staticOopFieldCount = new CIntField(type.getCIntegerField("_static_oop_field_count"), Oop.getHeaderSize());
duke@435 92 nonstaticOopMapSize = new CIntField(type.getCIntegerField("_nonstatic_oop_map_size"), Oop.getHeaderSize());
duke@435 93 isMarkedDependent = new CIntField(type.getCIntegerField("_is_marked_dependent"), Oop.getHeaderSize());
duke@435 94 initState = new CIntField(type.getCIntegerField("_init_state"), Oop.getHeaderSize());
duke@435 95 vtableLen = new CIntField(type.getCIntegerField("_vtable_len"), Oop.getHeaderSize());
duke@435 96 itableLen = new CIntField(type.getCIntegerField("_itable_len"), Oop.getHeaderSize());
duke@435 97 breakpoints = type.getAddressField("_breakpoints");
coleenp@2497 98 genericSignature = type.getAddressField("_generic_signature");
duke@435 99 majorVersion = new CIntField(type.getCIntegerField("_major_version"), Oop.getHeaderSize());
duke@435 100 minorVersion = new CIntField(type.getCIntegerField("_minor_version"), Oop.getHeaderSize());
duke@435 101 headerSize = alignObjectOffset(Oop.getHeaderSize() + type.getSize());
duke@435 102
duke@435 103 // read field offset constants
never@3137 104 ACCESS_FLAGS_OFFSET = db.lookupIntConstant("FieldInfo::access_flags_offset").intValue();
never@3137 105 NAME_INDEX_OFFSET = db.lookupIntConstant("FieldInfo::name_index_offset").intValue();
never@3137 106 SIGNATURE_INDEX_OFFSET = db.lookupIntConstant("FieldInfo::signature_index_offset").intValue();
never@3137 107 INITVAL_INDEX_OFFSET = db.lookupIntConstant("FieldInfo::initval_index_offset").intValue();
never@3137 108 LOW_OFFSET = db.lookupIntConstant("FieldInfo::low_offset").intValue();
never@3137 109 HIGH_OFFSET = db.lookupIntConstant("FieldInfo::high_offset").intValue();
never@3137 110 GENERIC_SIGNATURE_INDEX_OFFSET = db.lookupIntConstant("FieldInfo::generic_signature_offset").intValue();
never@3137 111 FIELD_SLOTS = db.lookupIntConstant("FieldInfo::field_slots").intValue();
duke@435 112 // read ClassState constants
duke@435 113 CLASS_STATE_UNPARSABLE_BY_GC = db.lookupIntConstant("instanceKlass::unparsable_by_gc").intValue();
duke@435 114 CLASS_STATE_ALLOCATED = db.lookupIntConstant("instanceKlass::allocated").intValue();
duke@435 115 CLASS_STATE_LOADED = db.lookupIntConstant("instanceKlass::loaded").intValue();
duke@435 116 CLASS_STATE_LINKED = db.lookupIntConstant("instanceKlass::linked").intValue();
duke@435 117 CLASS_STATE_BEING_INITIALIZED = db.lookupIntConstant("instanceKlass::being_initialized").intValue();
duke@435 118 CLASS_STATE_FULLY_INITIALIZED = db.lookupIntConstant("instanceKlass::fully_initialized").intValue();
duke@435 119 CLASS_STATE_INITIALIZATION_ERROR = db.lookupIntConstant("instanceKlass::initialization_error").intValue();
duke@435 120
duke@435 121 }
duke@435 122
duke@435 123 InstanceKlass(OopHandle handle, ObjectHeap heap) {
duke@435 124 super(handle, heap);
duke@435 125 }
duke@435 126
duke@435 127 private static OopField arrayKlasses;
duke@435 128 private static OopField methods;
duke@435 129 private static OopField methodOrdering;
duke@435 130 private static OopField localInterfaces;
duke@435 131 private static OopField transitiveInterfaces;
duke@435 132 private static CIntField nofImplementors;
duke@435 133 private static OopField[] implementors;
duke@435 134 private static OopField fields;
never@3137 135 private static CIntField javaFieldsCount;
duke@435 136 private static OopField constants;
duke@435 137 private static OopField classLoader;
duke@435 138 private static OopField protectionDomain;
duke@435 139 private static OopField signers;
coleenp@2497 140 private static AddressField sourceFileName;
coleenp@2497 141 private static AddressField sourceDebugExtension;
duke@435 142 private static OopField innerClasses;
duke@435 143 private static CIntField nonstaticFieldSize;
duke@435 144 private static CIntField staticFieldSize;
never@2658 145 private static CIntField staticOopFieldCount;
duke@435 146 private static CIntField nonstaticOopMapSize;
duke@435 147 private static CIntField isMarkedDependent;
duke@435 148 private static CIntField initState;
duke@435 149 private static CIntField vtableLen;
duke@435 150 private static CIntField itableLen;
duke@435 151 private static AddressField breakpoints;
coleenp@2497 152 private static AddressField genericSignature;
duke@435 153 private static CIntField majorVersion;
duke@435 154 private static CIntField minorVersion;
duke@435 155
duke@435 156 // type safe enum for ClassState from instanceKlass.hpp
duke@435 157 public static class ClassState {
duke@435 158 public static final ClassState UNPARSABLE_BY_GC = new ClassState("unparsable_by_gc");
duke@435 159 public static final ClassState ALLOCATED = new ClassState("allocated");
duke@435 160 public static final ClassState LOADED = new ClassState("loaded");
duke@435 161 public static final ClassState LINKED = new ClassState("linked");
duke@435 162 public static final ClassState BEING_INITIALIZED = new ClassState("beingInitialized");
duke@435 163 public static final ClassState FULLY_INITIALIZED = new ClassState("fullyInitialized");
duke@435 164 public static final ClassState INITIALIZATION_ERROR = new ClassState("initializationError");
duke@435 165
duke@435 166 private ClassState(String value) {
duke@435 167 this.value = value;
duke@435 168 }
duke@435 169
duke@435 170 public String toString() {
duke@435 171 return value;
duke@435 172 }
duke@435 173
duke@435 174 private String value;
duke@435 175 }
duke@435 176
never@3138 177 public int getInitStateAsInt() { return (int) initState.getValue(this); }
duke@435 178 public ClassState getInitState() {
duke@435 179 int state = getInitStateAsInt();
duke@435 180 if (state == CLASS_STATE_UNPARSABLE_BY_GC) {
duke@435 181 return ClassState.UNPARSABLE_BY_GC;
duke@435 182 } else if (state == CLASS_STATE_ALLOCATED) {
duke@435 183 return ClassState.ALLOCATED;
duke@435 184 } else if (state == CLASS_STATE_LOADED) {
duke@435 185 return ClassState.LOADED;
duke@435 186 } else if (state == CLASS_STATE_LINKED) {
duke@435 187 return ClassState.LINKED;
duke@435 188 } else if (state == CLASS_STATE_BEING_INITIALIZED) {
duke@435 189 return ClassState.BEING_INITIALIZED;
duke@435 190 } else if (state == CLASS_STATE_FULLY_INITIALIZED) {
duke@435 191 return ClassState.FULLY_INITIALIZED;
duke@435 192 } else if (state == CLASS_STATE_INITIALIZATION_ERROR) {
duke@435 193 return ClassState.INITIALIZATION_ERROR;
duke@435 194 } else {
duke@435 195 throw new RuntimeException("should not reach here");
duke@435 196 }
duke@435 197 }
duke@435 198
duke@435 199 // initialization state quaries
duke@435 200 public boolean isLoaded() {
duke@435 201 return getInitStateAsInt() >= CLASS_STATE_LOADED;
duke@435 202 }
duke@435 203
duke@435 204 public boolean isLinked() {
duke@435 205 return getInitStateAsInt() >= CLASS_STATE_LINKED;
duke@435 206 }
duke@435 207
duke@435 208 public boolean isInitialized() {
duke@435 209 return getInitStateAsInt() == CLASS_STATE_FULLY_INITIALIZED;
duke@435 210 }
duke@435 211
duke@435 212 public boolean isNotInitialized() {
duke@435 213 return getInitStateAsInt() < CLASS_STATE_BEING_INITIALIZED;
duke@435 214 }
duke@435 215
duke@435 216 public boolean isBeingInitialized() {
duke@435 217 return getInitStateAsInt() == CLASS_STATE_BEING_INITIALIZED;
duke@435 218 }
duke@435 219
duke@435 220 public boolean isInErrorState() {
duke@435 221 return getInitStateAsInt() == CLASS_STATE_INITIALIZATION_ERROR;
duke@435 222 }
duke@435 223
duke@435 224 public int getClassStatus() {
duke@435 225 int result = 0;
duke@435 226 if (isLinked()) {
duke@435 227 result |= JVMDIClassStatus.VERIFIED | JVMDIClassStatus.PREPARED;
duke@435 228 }
duke@435 229
duke@435 230 if (isInitialized()) {
duke@435 231 if (Assert.ASSERTS_ENABLED) {
duke@435 232 Assert.that(isLinked(), "Class status is not consistent");
duke@435 233 }
duke@435 234 result |= JVMDIClassStatus.INITIALIZED;
duke@435 235 }
duke@435 236
duke@435 237 if (isInErrorState()) {
duke@435 238 result |= JVMDIClassStatus.ERROR;
duke@435 239 }
duke@435 240 return result;
duke@435 241 }
duke@435 242
duke@435 243 // Byteside of the header
duke@435 244 private static long headerSize;
duke@435 245
never@2693 246 public long getObjectSize(Oop object) {
never@2693 247 return getSizeHelper() * VM.getVM().getAddressSize();
never@2693 248 }
never@2693 249
duke@435 250 public static long getHeaderSize() { return headerSize; }
duke@435 251
never@3137 252 public short getFieldAccessFlags(int index) {
never@3137 253 return getFields().getShortAt(index * FIELD_SLOTS + ACCESS_FLAGS_OFFSET);
never@3137 254 }
never@3137 255
never@3137 256 public Symbol getFieldName(int index) {
never@3137 257 int nameIndex = getFields().getShortAt(index * FIELD_SLOTS + NAME_INDEX_OFFSET);
never@3137 258 return getConstants().getSymbolAt(nameIndex);
never@3137 259 }
never@3137 260
never@3137 261 public Symbol getFieldSignature(int index) {
never@3137 262 int signatureIndex = getFields().getShortAt(index * FIELD_SLOTS + SIGNATURE_INDEX_OFFSET);
never@3137 263 return getConstants().getSymbolAt(signatureIndex);
never@3137 264 }
never@3137 265
never@3137 266 public Symbol getFieldGenericSignature(int index) {
never@3137 267 short genericSignatureIndex = getFields().getShortAt(index * FIELD_SLOTS + GENERIC_SIGNATURE_INDEX_OFFSET);
never@3137 268 if (genericSignatureIndex != 0) {
never@3137 269 return getConstants().getSymbolAt(genericSignatureIndex);
never@3137 270 }
never@3137 271 return null;
never@3137 272 }
never@3137 273
never@3137 274 public int getFieldOffset(int index) {
never@3137 275 TypeArray fields = getFields();
never@3137 276 return VM.getVM().buildIntFromShorts(fields.getShortAt(index * FIELD_SLOTS + LOW_OFFSET),
never@3137 277 fields.getShortAt(index * FIELD_SLOTS + HIGH_OFFSET));
never@3137 278 }
never@3137 279
duke@435 280 // Accessors for declared fields
duke@435 281 public Klass getArrayKlasses() { return (Klass) arrayKlasses.getValue(this); }
duke@435 282 public ObjArray getMethods() { return (ObjArray) methods.getValue(this); }
duke@435 283 public TypeArray getMethodOrdering() { return (TypeArray) methodOrdering.getValue(this); }
duke@435 284 public ObjArray getLocalInterfaces() { return (ObjArray) localInterfaces.getValue(this); }
duke@435 285 public ObjArray getTransitiveInterfaces() { return (ObjArray) transitiveInterfaces.getValue(this); }
duke@435 286 public long nofImplementors() { return nofImplementors.getValue(this); }
duke@435 287 public Klass getImplementor() { return (Klass) implementors[0].getValue(this); }
duke@435 288 public Klass getImplementor(int i) { return (Klass) implementors[i].getValue(this); }
duke@435 289 public TypeArray getFields() { return (TypeArray) fields.getValue(this); }
never@3137 290 public int getJavaFieldsCount() { return (int) javaFieldsCount.getValue(this); }
never@3137 291 public int getAllFieldsCount() { return (int)getFields().getLength(); }
duke@435 292 public ConstantPool getConstants() { return (ConstantPool) constants.getValue(this); }
duke@435 293 public Oop getClassLoader() { return classLoader.getValue(this); }
duke@435 294 public Oop getProtectionDomain() { return protectionDomain.getValue(this); }
duke@435 295 public ObjArray getSigners() { return (ObjArray) signers.getValue(this); }
coleenp@2497 296 public Symbol getSourceFileName() { return getSymbol(sourceFileName); }
coleenp@2497 297 public Symbol getSourceDebugExtension(){ return getSymbol(sourceDebugExtension); }
duke@435 298 public TypeArray getInnerClasses() { return (TypeArray) innerClasses.getValue(this); }
duke@435 299 public long getNonstaticFieldSize() { return nonstaticFieldSize.getValue(this); }
never@2658 300 public long getStaticOopFieldCount() { return staticOopFieldCount.getValue(this); }
duke@435 301 public long getNonstaticOopMapSize() { return nonstaticOopMapSize.getValue(this); }
duke@435 302 public boolean getIsMarkedDependent() { return isMarkedDependent.getValue(this) != 0; }
duke@435 303 public long getVtableLen() { return vtableLen.getValue(this); }
duke@435 304 public long getItableLen() { return itableLen.getValue(this); }
coleenp@2497 305 public Symbol getGenericSignature() { return getSymbol(genericSignature); }
duke@435 306 public long majorVersion() { return majorVersion.getValue(this); }
duke@435 307 public long minorVersion() { return minorVersion.getValue(this); }
duke@435 308
duke@435 309 // "size helper" == instance size in words
duke@435 310 public long getSizeHelper() {
duke@435 311 int lh = getLayoutHelper();
duke@435 312 if (Assert.ASSERTS_ENABLED) {
duke@435 313 Assert.that(lh > 0, "layout helper initialized for instance class");
duke@435 314 }
duke@435 315 return lh / VM.getVM().getAddressSize();
duke@435 316 }
duke@435 317
duke@435 318 // same as enum InnerClassAttributeOffset in VM code.
duke@435 319 public static interface InnerClassAttributeOffset {
duke@435 320 // from JVM spec. "InnerClasses" attribute
duke@435 321 public static final int innerClassInnerClassInfoOffset = 0;
duke@435 322 public static final int innerClassOuterClassInfoOffset = 1;
duke@435 323 public static final int innerClassInnerNameOffset = 2;
duke@435 324 public static final int innerClassAccessFlagsOffset = 3;
duke@435 325 public static final int innerClassNextOffset = 4;
duke@435 326 };
duke@435 327
duke@435 328 // refer to compute_modifier_flags in VM code.
duke@435 329 public long computeModifierFlags() {
duke@435 330 long access = getAccessFlags();
duke@435 331 // But check if it happens to be member class.
duke@435 332 TypeArray innerClassList = getInnerClasses();
duke@435 333 int length = ( innerClassList == null)? 0 : (int) innerClassList.getLength();
duke@435 334 if (length > 0) {
duke@435 335 if (Assert.ASSERTS_ENABLED) {
duke@435 336 Assert.that(length % InnerClassAttributeOffset.innerClassNextOffset == 0, "just checking");
duke@435 337 }
duke@435 338 for (int i = 0; i < length; i += InnerClassAttributeOffset.innerClassNextOffset) {
duke@435 339 int ioff = innerClassList.getShortAt(i +
duke@435 340 InnerClassAttributeOffset.innerClassInnerClassInfoOffset);
duke@435 341 // 'ioff' can be zero.
duke@435 342 // refer to JVM spec. section 4.7.5.
duke@435 343 if (ioff != 0) {
duke@435 344 // only look at classes that are already loaded
duke@435 345 // since we are looking for the flags for our self.
coleenp@2497 346 ConstantPool.CPSlot classInfo = getConstants().getSlotAt(ioff);
duke@435 347 Symbol name = null;
coleenp@2497 348 if (classInfo.isOop()) {
coleenp@2497 349 name = ((Klass) classInfo.getOop()).getName();
coleenp@2497 350 } else if (classInfo.isMetaData()) {
coleenp@2497 351 name = classInfo.getSymbol();
duke@435 352 } else {
duke@435 353 throw new RuntimeException("should not reach here");
duke@435 354 }
duke@435 355
duke@435 356 if (name.equals(getName())) {
duke@435 357 // This is really a member class
duke@435 358 access = innerClassList.getShortAt(i +
duke@435 359 InnerClassAttributeOffset.innerClassAccessFlagsOffset);
duke@435 360 break;
duke@435 361 }
duke@435 362 }
duke@435 363 } // for inner classes
duke@435 364 }
duke@435 365
duke@435 366 // Remember to strip ACC_SUPER bit
duke@435 367 return (access & (~JVM_ACC_SUPER)) & JVM_ACC_WRITTEN_FLAGS;
duke@435 368 }
duke@435 369
duke@435 370
duke@435 371 // whether given Symbol is name of an inner/nested Klass of this Klass?
duke@435 372 // anonymous and local classes are excluded.
duke@435 373 public boolean isInnerClassName(Symbol sym) {
duke@435 374 return isInInnerClasses(sym, false);
duke@435 375 }
duke@435 376
duke@435 377 // whether given Symbol is name of an inner/nested Klass of this Klass?
duke@435 378 // anonymous classes excluded, but local classes are included.
duke@435 379 public boolean isInnerOrLocalClassName(Symbol sym) {
duke@435 380 return isInInnerClasses(sym, true);
duke@435 381 }
duke@435 382
duke@435 383 private boolean isInInnerClasses(Symbol sym, boolean includeLocals) {
duke@435 384 TypeArray innerClassList = getInnerClasses();
duke@435 385 int length = ( innerClassList == null)? 0 : (int) innerClassList.getLength();
duke@435 386 if (length > 0) {
duke@435 387 if (Assert.ASSERTS_ENABLED) {
duke@435 388 Assert.that(length % InnerClassAttributeOffset.innerClassNextOffset == 0, "just checking");
duke@435 389 }
duke@435 390 for (int i = 0; i < length; i += InnerClassAttributeOffset.innerClassNextOffset) {
duke@435 391 int ioff = innerClassList.getShortAt(i +
duke@435 392 InnerClassAttributeOffset.innerClassInnerClassInfoOffset);
duke@435 393 // 'ioff' can be zero.
duke@435 394 // refer to JVM spec. section 4.7.5.
duke@435 395 if (ioff != 0) {
coleenp@2497 396 ConstantPool.CPSlot iclassInfo = getConstants().getSlotAt(ioff);
duke@435 397 Symbol innerName = null;
coleenp@2497 398 if (iclassInfo.isOop()) {
coleenp@2497 399 innerName = ((Klass) iclassInfo.getOop()).getName();
coleenp@2497 400 } else if (iclassInfo.isMetaData()) {
coleenp@2497 401 innerName = iclassInfo.getSymbol();
duke@435 402 } else {
duke@435 403 throw new RuntimeException("should not reach here");
duke@435 404 }
duke@435 405
duke@435 406 Symbol myname = getName();
duke@435 407 int ooff = innerClassList.getShortAt(i +
duke@435 408 InnerClassAttributeOffset.innerClassOuterClassInfoOffset);
duke@435 409 // for anonymous classes inner_name_index of InnerClasses
duke@435 410 // attribute is zero.
duke@435 411 int innerNameIndex = innerClassList.getShortAt(i +
duke@435 412 InnerClassAttributeOffset.innerClassInnerNameOffset);
duke@435 413 // if this is not a member (anonymous, local etc.), 'ooff' will be zero
duke@435 414 // refer to JVM spec. section 4.7.5.
duke@435 415 if (ooff == 0) {
duke@435 416 if (includeLocals) {
duke@435 417 // does it looks like my local class?
duke@435 418 if (innerName.equals(sym) &&
duke@435 419 innerName.asString().startsWith(myname.asString())) {
duke@435 420 // exclude anonymous classes.
duke@435 421 return (innerNameIndex != 0);
duke@435 422 }
duke@435 423 }
duke@435 424 } else {
coleenp@2497 425 ConstantPool.CPSlot oclassInfo = getConstants().getSlotAt(ooff);
duke@435 426 Symbol outerName = null;
coleenp@2497 427 if (oclassInfo.isOop()) {
coleenp@2497 428 outerName = ((Klass) oclassInfo.getOop()).getName();
coleenp@2497 429 } else if (oclassInfo.isMetaData()) {
coleenp@2497 430 outerName = oclassInfo.getSymbol();
duke@435 431 } else {
duke@435 432 throw new RuntimeException("should not reach here");
duke@435 433 }
duke@435 434
duke@435 435 // include only if current class is outer class.
duke@435 436 if (outerName.equals(myname) && innerName.equals(sym)) {
duke@435 437 return true;
duke@435 438 }
duke@435 439 }
duke@435 440 }
duke@435 441 } // for inner classes
duke@435 442 return false;
duke@435 443 } else {
duke@435 444 return false;
duke@435 445 }
duke@435 446 }
duke@435 447
duke@435 448 public boolean implementsInterface(Klass k) {
duke@435 449 if (Assert.ASSERTS_ENABLED) {
duke@435 450 Assert.that(k.isInterface(), "should not reach here");
duke@435 451 }
duke@435 452 ObjArray interfaces = getTransitiveInterfaces();
duke@435 453 final int len = (int) interfaces.getLength();
duke@435 454 for (int i = 0; i < len; i++) {
duke@435 455 if (interfaces.getObjAt(i).equals(k)) return true;
duke@435 456 }
duke@435 457 return false;
duke@435 458 }
duke@435 459
duke@435 460 boolean computeSubtypeOf(Klass k) {
duke@435 461 if (k.isInterface()) {
duke@435 462 return implementsInterface(k);
duke@435 463 } else {
duke@435 464 return super.computeSubtypeOf(k);
duke@435 465 }
duke@435 466 }
duke@435 467
duke@435 468 public void printValueOn(PrintStream tty) {
duke@435 469 tty.print("InstanceKlass for " + getName().asString());
duke@435 470 }
duke@435 471
duke@435 472 public void iterateFields(OopVisitor visitor, boolean doVMFields) {
duke@435 473 super.iterateFields(visitor, doVMFields);
duke@435 474 if (doVMFields) {
duke@435 475 visitor.doOop(arrayKlasses, true);
duke@435 476 visitor.doOop(methods, true);
duke@435 477 visitor.doOop(methodOrdering, true);
duke@435 478 visitor.doOop(localInterfaces, true);
duke@435 479 visitor.doOop(transitiveInterfaces, true);
duke@435 480 visitor.doCInt(nofImplementors, true);
duke@435 481 for (int i = 0; i < IMPLEMENTORS_LIMIT; i++)
duke@435 482 visitor.doOop(implementors[i], true);
duke@435 483 visitor.doOop(fields, true);
duke@435 484 visitor.doOop(constants, true);
duke@435 485 visitor.doOop(classLoader, true);
duke@435 486 visitor.doOop(protectionDomain, true);
duke@435 487 visitor.doOop(signers, true);
duke@435 488 visitor.doOop(innerClasses, true);
duke@435 489 visitor.doCInt(nonstaticFieldSize, true);
duke@435 490 visitor.doCInt(staticFieldSize, true);
never@2658 491 visitor.doCInt(staticOopFieldCount, true);
duke@435 492 visitor.doCInt(nonstaticOopMapSize, true);
duke@435 493 visitor.doCInt(isMarkedDependent, true);
duke@435 494 visitor.doCInt(initState, true);
duke@435 495 visitor.doCInt(vtableLen, true);
duke@435 496 visitor.doCInt(itableLen, true);
duke@435 497 }
never@2693 498 }
duke@435 499
never@2693 500 /*
never@2693 501 * Visit the static fields of this InstanceKlass with the obj of
never@2693 502 * the visitor set to the oop holding the fields, which is
never@2693 503 * currently the java mirror.
never@2693 504 */
never@2693 505 public void iterateStaticFields(OopVisitor visitor) {
never@2693 506 visitor.setObj(getJavaMirror());
never@2693 507 visitor.prologue();
never@2693 508 iterateStaticFieldsInternal(visitor);
never@2693 509 visitor.epilogue();
never@2693 510
never@2693 511 }
never@2693 512
never@2693 513 void iterateStaticFieldsInternal(OopVisitor visitor) {
duke@435 514 TypeArray fields = getFields();
never@3137 515 int length = getJavaFieldsCount();
never@3137 516 for (int index = 0; index < length; index += FIELD_SLOTS) {
duke@435 517 short accessFlags = fields.getShortAt(index + ACCESS_FLAGS_OFFSET);
duke@435 518 short signatureIndex = fields.getShortAt(index + SIGNATURE_INDEX_OFFSET);
coleenp@2497 519 FieldType type = new FieldType(getConstants().getSymbolAt(signatureIndex));
duke@435 520 AccessFlags access = new AccessFlags(accessFlags);
duke@435 521 if (access.isStatic()) {
duke@435 522 visitField(visitor, type, index);
duke@435 523 }
duke@435 524 }
duke@435 525 }
duke@435 526
duke@435 527 public Klass getJavaSuper() {
duke@435 528 return getSuper();
duke@435 529 }
duke@435 530
never@3138 531 public static class StaticField {
never@3138 532 public AccessFlags flags;
never@3138 533 public Field field;
never@3138 534
never@3138 535 StaticField(Field field, AccessFlags flags) {
never@3138 536 this.field = field;
never@3138 537 this.flags = flags;
never@3138 538 }
never@3138 539 }
never@3138 540
never@2693 541 public void iterateNonStaticFields(OopVisitor visitor, Oop obj) {
duke@435 542 if (getSuper() != null) {
never@2693 543 ((InstanceKlass) getSuper()).iterateNonStaticFields(visitor, obj);
duke@435 544 }
duke@435 545 TypeArray fields = getFields();
duke@435 546
never@3137 547 int length = getJavaFieldsCount();
never@3137 548 for (int index = 0; index < length; index += FIELD_SLOTS) {
duke@435 549 short accessFlags = fields.getShortAt(index + ACCESS_FLAGS_OFFSET);
duke@435 550 short signatureIndex = fields.getShortAt(index + SIGNATURE_INDEX_OFFSET);
duke@435 551
coleenp@2497 552 FieldType type = new FieldType(getConstants().getSymbolAt(signatureIndex));
duke@435 553 AccessFlags access = new AccessFlags(accessFlags);
duke@435 554 if (!access.isStatic()) {
duke@435 555 visitField(visitor, type, index);
duke@435 556 }
duke@435 557 }
duke@435 558 }
duke@435 559
duke@435 560 /** Field access by name. */
duke@435 561 public Field findLocalField(Symbol name, Symbol sig) {
duke@435 562 TypeArray fields = getFields();
never@3137 563 int length = (int) fields.getLength();
duke@435 564 ConstantPool cp = getConstants();
never@3137 565 for (int i = 0; i < length; i += FIELD_SLOTS) {
duke@435 566 int nameIndex = fields.getShortAt(i + NAME_INDEX_OFFSET);
duke@435 567 int sigIndex = fields.getShortAt(i + SIGNATURE_INDEX_OFFSET);
duke@435 568 Symbol f_name = cp.getSymbolAt(nameIndex);
duke@435 569 Symbol f_sig = cp.getSymbolAt(sigIndex);
duke@435 570 if (name.equals(f_name) && sig.equals(f_sig)) {
duke@435 571 return newField(i);
duke@435 572 }
duke@435 573 }
duke@435 574
duke@435 575 return null;
duke@435 576 }
duke@435 577
duke@435 578 /** Find field in direct superinterfaces. */
duke@435 579 public Field findInterfaceField(Symbol name, Symbol sig) {
duke@435 580 ObjArray interfaces = getLocalInterfaces();
duke@435 581 int n = (int) interfaces.getLength();
duke@435 582 for (int i = 0; i < n; i++) {
duke@435 583 InstanceKlass intf1 = (InstanceKlass) interfaces.getObjAt(i);
duke@435 584 if (Assert.ASSERTS_ENABLED) {
duke@435 585 Assert.that(intf1.isInterface(), "just checking type");
duke@435 586 }
duke@435 587 // search for field in current interface
duke@435 588 Field f = intf1.findLocalField(name, sig);
duke@435 589 if (f != null) {
duke@435 590 if (Assert.ASSERTS_ENABLED) {
duke@435 591 Assert.that(f.getAccessFlagsObj().isStatic(), "interface field must be static");
duke@435 592 }
duke@435 593 return f;
duke@435 594 }
duke@435 595 // search for field in direct superinterfaces
duke@435 596 f = intf1.findInterfaceField(name, sig);
duke@435 597 if (f != null) return f;
duke@435 598 }
duke@435 599 // otherwise field lookup fails
duke@435 600 return null;
duke@435 601 }
duke@435 602
duke@435 603 /** Find field according to JVM spec 5.4.3.2, returns the klass in
duke@435 604 which the field is defined. */
duke@435 605 public Field findField(Symbol name, Symbol sig) {
duke@435 606 // search order according to newest JVM spec (5.4.3.2, p.167).
duke@435 607 // 1) search for field in current klass
duke@435 608 Field f = findLocalField(name, sig);
duke@435 609 if (f != null) return f;
duke@435 610
duke@435 611 // 2) search for field recursively in direct superinterfaces
duke@435 612 f = findInterfaceField(name, sig);
duke@435 613 if (f != null) return f;
duke@435 614
duke@435 615 // 3) apply field lookup recursively if superclass exists
duke@435 616 InstanceKlass supr = (InstanceKlass) getSuper();
duke@435 617 if (supr != null) return supr.findField(name, sig);
duke@435 618
duke@435 619 // 4) otherwise field lookup fails
duke@435 620 return null;
duke@435 621 }
duke@435 622
duke@435 623 /** Find field according to JVM spec 5.4.3.2, returns the klass in
duke@435 624 which the field is defined (convenience routine) */
duke@435 625 public Field findField(String name, String sig) {
duke@435 626 SymbolTable symbols = VM.getVM().getSymbolTable();
duke@435 627 Symbol nameSym = symbols.probe(name);
duke@435 628 Symbol sigSym = symbols.probe(sig);
duke@435 629 if (nameSym == null || sigSym == null) {
duke@435 630 return null;
duke@435 631 }
duke@435 632 return findField(nameSym, sigSym);
duke@435 633 }
duke@435 634
duke@435 635 /** Find field according to JVM spec 5.4.3.2, returns the klass in
duke@435 636 which the field is defined (retained only for backward
duke@435 637 compatibility with jdbx) */
duke@435 638 public Field findFieldDbg(String name, String sig) {
duke@435 639 return findField(name, sig);
duke@435 640 }
duke@435 641
duke@435 642 /** Get field by its index in the fields array. Only designed for
duke@435 643 use in a debugging system. */
duke@435 644 public Field getFieldByIndex(int fieldArrayIndex) {
duke@435 645 return newField(fieldArrayIndex);
duke@435 646 }
duke@435 647
duke@435 648
duke@435 649 /** Return a List of SA Fields for the fields declared in this class.
duke@435 650 Inherited fields are not included.
duke@435 651 Return an empty list if there are no fields declared in this class.
duke@435 652 Only designed for use in a debugging system. */
duke@435 653 public List getImmediateFields() {
duke@435 654 // A list of Fields for each field declared in this class/interface,
duke@435 655 // not including inherited fields.
duke@435 656 TypeArray fields = getFields();
duke@435 657
never@3137 658 int length = getJavaFieldsCount();
never@3137 659 List immediateFields = new ArrayList(length);
never@3137 660 for (int index = 0; index < length; index += FIELD_SLOTS) {
duke@435 661 immediateFields.add(getFieldByIndex(index));
duke@435 662 }
duke@435 663
duke@435 664 return immediateFields;
duke@435 665 }
duke@435 666
duke@435 667 /** Return a List of SA Fields for all the java fields in this class,
duke@435 668 including all inherited fields. This includes hidden
duke@435 669 fields. Thus the returned list can contain fields with
duke@435 670 the same name.
duke@435 671 Return an empty list if there are no fields.
duke@435 672 Only designed for use in a debugging system. */
duke@435 673 public List getAllFields() {
duke@435 674 // Contains a Field for each field in this class, including immediate
duke@435 675 // fields and inherited fields.
duke@435 676 List allFields = getImmediateFields();
duke@435 677
duke@435 678 // transitiveInterfaces contains all interfaces implemented
duke@435 679 // by this class and its superclass chain with no duplicates.
duke@435 680
duke@435 681 ObjArray interfaces = getTransitiveInterfaces();
duke@435 682 int n = (int) interfaces.getLength();
duke@435 683 for (int i = 0; i < n; i++) {
duke@435 684 InstanceKlass intf1 = (InstanceKlass) interfaces.getObjAt(i);
duke@435 685 if (Assert.ASSERTS_ENABLED) {
duke@435 686 Assert.that(intf1.isInterface(), "just checking type");
duke@435 687 }
duke@435 688 allFields.addAll(intf1.getImmediateFields());
duke@435 689 }
duke@435 690
duke@435 691 // Get all fields in the superclass, recursively. But, don't
duke@435 692 // include fields in interfaces implemented by superclasses;
duke@435 693 // we already have all those.
duke@435 694 if (!isInterface()) {
duke@435 695 InstanceKlass supr;
duke@435 696 if ( (supr = (InstanceKlass) getSuper()) != null) {
duke@435 697 allFields.addAll(supr.getImmediateFields());
duke@435 698 }
duke@435 699 }
duke@435 700
duke@435 701 return allFields;
duke@435 702 }
duke@435 703
duke@435 704
duke@435 705 /** Return a List of SA Methods declared directly in this class/interface.
duke@435 706 Return an empty list if there are none, or if this isn't a class/
duke@435 707 interface.
duke@435 708 */
duke@435 709 public List getImmediateMethods() {
duke@435 710 // Contains a Method for each method declared in this class/interface
duke@435 711 // not including inherited methods.
duke@435 712
duke@435 713 ObjArray methods = getMethods();
duke@435 714 int length = (int)methods.getLength();
duke@435 715 Object[] tmp = new Object[length];
duke@435 716
duke@435 717 TypeArray methodOrdering = getMethodOrdering();
duke@435 718 if (methodOrdering.getLength() != length) {
duke@435 719 // no ordering info present
duke@435 720 for (int index = 0; index < length; index++) {
duke@435 721 tmp[index] = methods.getObjAt(index);
duke@435 722 }
duke@435 723 } else {
duke@435 724 for (int index = 0; index < length; index++) {
duke@435 725 int originalIndex = getMethodOrdering().getIntAt(index);
duke@435 726 tmp[originalIndex] = methods.getObjAt(index);
duke@435 727 }
duke@435 728 }
duke@435 729
duke@435 730 return Arrays.asList(tmp);
duke@435 731 }
duke@435 732
duke@435 733 /** Return a List containing an SA InstanceKlass for each
duke@435 734 interface named in this class's 'implements' clause.
duke@435 735 */
duke@435 736 public List getDirectImplementedInterfaces() {
duke@435 737 // Contains an InstanceKlass for each interface in this classes
duke@435 738 // 'implements' clause.
duke@435 739
duke@435 740 ObjArray interfaces = getLocalInterfaces();
duke@435 741 int length = (int) interfaces.getLength();
duke@435 742 List directImplementedInterfaces = new ArrayList(length);
duke@435 743
duke@435 744 for (int index = 0; index < length; index ++) {
duke@435 745 directImplementedInterfaces.add(interfaces.getObjAt(index));
duke@435 746 }
duke@435 747
duke@435 748 return directImplementedInterfaces;
duke@435 749 }
duke@435 750
duke@435 751
duke@435 752 public long getObjectSize() {
duke@435 753 long bodySize = alignObjectOffset(getVtableLen() * getHeap().getOopSize())
duke@435 754 + alignObjectOffset(getItableLen() * getHeap().getOopSize())
never@2658 755 + (getNonstaticOopMapSize()) * getHeap().getOopSize();
duke@435 756 return alignObjectSize(headerSize + bodySize);
duke@435 757 }
duke@435 758
duke@435 759 public Klass arrayKlassImpl(boolean orNull, int n) {
duke@435 760 // FIXME: in reflective system this would need to change to
duke@435 761 // actually allocate
duke@435 762 if (getArrayKlasses() == null) { return null; }
duke@435 763 ObjArrayKlass oak = (ObjArrayKlass) getArrayKlasses();
duke@435 764 if (orNull) {
duke@435 765 return oak.arrayKlassOrNull(n);
duke@435 766 }
duke@435 767 return oak.arrayKlass(n);
duke@435 768 }
duke@435 769
duke@435 770 public Klass arrayKlassImpl(boolean orNull) {
duke@435 771 return arrayKlassImpl(orNull, 1);
duke@435 772 }
duke@435 773
duke@435 774 public String signature() {
duke@435 775 return "L" + super.signature() + ";";
duke@435 776 }
duke@435 777
duke@435 778 /** Convenience routine taking Strings; lookup is done in
duke@435 779 SymbolTable. */
duke@435 780 public Method findMethod(String name, String sig) {
duke@435 781 SymbolTable syms = VM.getVM().getSymbolTable();
duke@435 782 Symbol nameSym = syms.probe(name);
duke@435 783 Symbol sigSym = syms.probe(sig);
duke@435 784 if (nameSym == null || sigSym == null) {
duke@435 785 return null;
duke@435 786 }
duke@435 787 return findMethod(nameSym, sigSym);
duke@435 788 }
duke@435 789
duke@435 790 /** Find method in vtable. */
duke@435 791 public Method findMethod(Symbol name, Symbol sig) {
duke@435 792 return findMethod(getMethods(), name, sig);
duke@435 793 }
duke@435 794
duke@435 795 /** Breakpoint support (see methods on methodOop for details) */
duke@435 796 public BreakpointInfo getBreakpoints() {
duke@435 797 Address addr = getHandle().getAddressAt(Oop.getHeaderSize() + breakpoints.getOffset());
duke@435 798 return (BreakpointInfo) VMObjectFactory.newObject(BreakpointInfo.class, addr);
duke@435 799 }
duke@435 800
duke@435 801 //----------------------------------------------------------------------
duke@435 802 // Internals only below this point
duke@435 803 //
duke@435 804
duke@435 805 private void visitField(OopVisitor visitor, FieldType type, int index) {
duke@435 806 Field f = newField(index);
duke@435 807 if (type.isOop()) {
duke@435 808 visitor.doOop((OopField) f, false);
duke@435 809 return;
duke@435 810 }
duke@435 811 if (type.isByte()) {
duke@435 812 visitor.doByte((ByteField) f, false);
duke@435 813 return;
duke@435 814 }
duke@435 815 if (type.isChar()) {
duke@435 816 visitor.doChar((CharField) f, false);
duke@435 817 return;
duke@435 818 }
duke@435 819 if (type.isDouble()) {
duke@435 820 visitor.doDouble((DoubleField) f, false);
duke@435 821 return;
duke@435 822 }
duke@435 823 if (type.isFloat()) {
duke@435 824 visitor.doFloat((FloatField) f, false);
duke@435 825 return;
duke@435 826 }
duke@435 827 if (type.isInt()) {
duke@435 828 visitor.doInt((IntField) f, false);
duke@435 829 return;
duke@435 830 }
duke@435 831 if (type.isLong()) {
duke@435 832 visitor.doLong((LongField) f, false);
duke@435 833 return;
duke@435 834 }
duke@435 835 if (type.isShort()) {
duke@435 836 visitor.doShort((ShortField) f, false);
duke@435 837 return;
duke@435 838 }
duke@435 839 if (type.isBoolean()) {
duke@435 840 visitor.doBoolean((BooleanField) f, false);
duke@435 841 return;
duke@435 842 }
duke@435 843 }
duke@435 844
duke@435 845 // Creates new field from index in fields TypeArray
duke@435 846 private Field newField(int index) {
duke@435 847 TypeArray fields = getFields();
duke@435 848 short signatureIndex = fields.getShortAt(index + SIGNATURE_INDEX_OFFSET);
coleenp@2497 849 FieldType type = new FieldType(getConstants().getSymbolAt(signatureIndex));
duke@435 850 if (type.isOop()) {
coleenp@548 851 if (VM.getVM().isCompressedOopsEnabled()) {
coleenp@548 852 return new NarrowOopField(this, index);
coleenp@548 853 } else {
coleenp@548 854 return new OopField(this, index);
coleenp@548 855 }
duke@435 856 }
duke@435 857 if (type.isByte()) {
duke@435 858 return new ByteField(this, index);
duke@435 859 }
duke@435 860 if (type.isChar()) {
duke@435 861 return new CharField(this, index);
duke@435 862 }
duke@435 863 if (type.isDouble()) {
duke@435 864 return new DoubleField(this, index);
duke@435 865 }
duke@435 866 if (type.isFloat()) {
duke@435 867 return new FloatField(this, index);
duke@435 868 }
duke@435 869 if (type.isInt()) {
duke@435 870 return new IntField(this, index);
duke@435 871 }
duke@435 872 if (type.isLong()) {
duke@435 873 return new LongField(this, index);
duke@435 874 }
duke@435 875 if (type.isShort()) {
duke@435 876 return new ShortField(this, index);
duke@435 877 }
duke@435 878 if (type.isBoolean()) {
duke@435 879 return new BooleanField(this, index);
duke@435 880 }
duke@435 881 throw new RuntimeException("Illegal field type at index " + index);
duke@435 882 }
duke@435 883
duke@435 884 private static Method findMethod(ObjArray methods, Symbol name, Symbol signature) {
duke@435 885 int len = (int) methods.getLength();
duke@435 886 // methods are sorted, so do binary search
duke@435 887 int l = 0;
duke@435 888 int h = len - 1;
duke@435 889 while (l <= h) {
duke@435 890 int mid = (l + h) >> 1;
duke@435 891 Method m = (Method) methods.getObjAt(mid);
duke@435 892 int res = m.getName().fastCompare(name);
duke@435 893 if (res == 0) {
duke@435 894 // found matching name; do linear search to find matching signature
duke@435 895 // first, quick check for common case
duke@435 896 if (m.getSignature().equals(signature)) return m;
duke@435 897 // search downwards through overloaded methods
duke@435 898 int i;
duke@435 899 for (i = mid - 1; i >= l; i--) {
duke@435 900 Method m1 = (Method) methods.getObjAt(i);
duke@435 901 if (!m1.getName().equals(name)) break;
duke@435 902 if (m1.getSignature().equals(signature)) return m1;
duke@435 903 }
duke@435 904 // search upwards
duke@435 905 for (i = mid + 1; i <= h; i++) {
duke@435 906 Method m1 = (Method) methods.getObjAt(i);
duke@435 907 if (!m1.getName().equals(name)) break;
duke@435 908 if (m1.getSignature().equals(signature)) return m1;
duke@435 909 }
duke@435 910 // not found
duke@435 911 if (Assert.ASSERTS_ENABLED) {
duke@435 912 int index = linearSearch(methods, name, signature);
duke@435 913 if (index != -1) {
duke@435 914 throw new DebuggerException("binary search bug: should have found entry " + index);
duke@435 915 }
duke@435 916 }
duke@435 917 return null;
duke@435 918 } else if (res < 0) {
duke@435 919 l = mid + 1;
duke@435 920 } else {
duke@435 921 h = mid - 1;
duke@435 922 }
duke@435 923 }
duke@435 924 if (Assert.ASSERTS_ENABLED) {
duke@435 925 int index = linearSearch(methods, name, signature);
duke@435 926 if (index != -1) {
duke@435 927 throw new DebuggerException("binary search bug: should have found entry " + index);
duke@435 928 }
duke@435 929 }
duke@435 930 return null;
duke@435 931 }
duke@435 932
duke@435 933 private static int linearSearch(ObjArray methods, Symbol name, Symbol signature) {
duke@435 934 int len = (int) methods.getLength();
duke@435 935 for (int index = 0; index < len; index++) {
duke@435 936 Method m = (Method) methods.getObjAt(index);
duke@435 937 if (m.getSignature().equals(signature) && m.getName().equals(name)) {
duke@435 938 return index;
duke@435 939 }
duke@435 940 }
duke@435 941 return -1;
duke@435 942 }
duke@435 943 }

mercurial