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

Wed, 16 Jan 2013 16:30:04 +0100

author
sla
date
Wed, 16 Jan 2013 16:30:04 +0100
changeset 4462
e94ed1591b42
parent 4430
4a916f2ce331
child 5176
6bd680e9ea35
permissions
-rw-r--r--

8006403: Regression: jstack failed due to the FieldInfo regression in SA
Reviewed-by: sla, dholmes
Contributed-by: Aleksey Shipilev <aleksey.shipilev@oracle.com>

duke@435 1 /*
jiangli@3701 2 * Copyright (c) 2000, 2012, 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.*;
coleenp@4037 29 import sun.jvm.hotspot.classfile.ClassLoaderData;
duke@435 30 import sun.jvm.hotspot.debugger.*;
duke@435 31 import sun.jvm.hotspot.memory.*;
duke@435 32 import sun.jvm.hotspot.runtime.*;
duke@435 33 import sun.jvm.hotspot.types.*;
duke@435 34 import sun.jvm.hotspot.utilities.*;
duke@435 35
duke@435 36 // An InstanceKlass is the VM level representation of a Java class.
duke@435 37
duke@435 38 public class InstanceKlass extends Klass {
duke@435 39 static {
duke@435 40 VM.registerVMInitializedObserver(new Observer() {
duke@435 41 public void update(Observable o, Object data) {
duke@435 42 initialize(VM.getVM().getTypeDataBase());
duke@435 43 }
duke@435 44 });
duke@435 45 }
duke@435 46
duke@435 47 // field offset constants
never@3158 48 private static int ACCESS_FLAGS_OFFSET;
never@3158 49 private static int NAME_INDEX_OFFSET;
never@3158 50 private static int SIGNATURE_INDEX_OFFSET;
never@3158 51 private static int INITVAL_INDEX_OFFSET;
never@3158 52 private static int LOW_OFFSET;
never@3158 53 private static int HIGH_OFFSET;
never@3158 54 private static int FIELD_SLOTS;
jwilhelm@4430 55 private static short FIELDINFO_TAG_SIZE;
sla@4462 56 private static short FIELDINFO_TAG_MASK;
jwilhelm@4430 57 private static short FIELDINFO_TAG_OFFSET;
duke@435 58
duke@435 59 // ClassState constants
duke@435 60 private static int CLASS_STATE_ALLOCATED;
duke@435 61 private static int CLASS_STATE_LOADED;
duke@435 62 private static int CLASS_STATE_LINKED;
duke@435 63 private static int CLASS_STATE_BEING_INITIALIZED;
duke@435 64 private static int CLASS_STATE_FULLY_INITIALIZED;
duke@435 65 private static int CLASS_STATE_INITIALIZATION_ERROR;
duke@435 66
duke@435 67 private static synchronized void initialize(TypeDataBase db) throws WrongTypeException {
coleenp@4037 68 Type type = db.lookupType("InstanceKlass");
coleenp@4037 69 arrayKlasses = new MetadataField(type.getAddressField("_array_klasses"), 0);
coleenp@4037 70 methods = type.getAddressField("_methods");
coleenp@4037 71 methodOrdering = type.getAddressField("_method_ordering");
coleenp@4037 72 localInterfaces = type.getAddressField("_local_interfaces");
coleenp@4037 73 transitiveInterfaces = type.getAddressField("_transitive_interfaces");
coleenp@4037 74 fields = type.getAddressField("_fields");
coleenp@4037 75 javaFieldsCount = new CIntField(type.getCIntegerField("_java_fields_count"), 0);
coleenp@4037 76 constants = new MetadataField(type.getAddressField("_constants"), 0);
coleenp@4037 77 classLoaderData = type.getAddressField("_class_loader_data");
coleenp@4037 78 protectionDomain = new OopField(type.getOopField("_protection_domain"), 0);
coleenp@4037 79 signers = new OopField(type.getOopField("_signers"), 0);
coleenp@2497 80 sourceFileName = type.getAddressField("_source_file_name");
coleenp@2497 81 sourceDebugExtension = type.getAddressField("_source_debug_extension");
coleenp@4037 82 innerClasses = type.getAddressField("_inner_classes");
coleenp@4037 83 nonstaticFieldSize = new CIntField(type.getCIntegerField("_nonstatic_field_size"), 0);
coleenp@4037 84 staticFieldSize = new CIntField(type.getCIntegerField("_static_field_size"), 0);
coleenp@4037 85 staticOopFieldCount = new CIntField(type.getCIntegerField("_static_oop_field_count"), 0);
coleenp@4037 86 nonstaticOopMapSize = new CIntField(type.getCIntegerField("_nonstatic_oop_map_size"), 0);
coleenp@4037 87 isMarkedDependent = new CIntField(type.getCIntegerField("_is_marked_dependent"), 0);
coleenp@4037 88 initState = new CIntField(type.getCIntegerField("_init_state"), 0);
coleenp@4037 89 vtableLen = new CIntField(type.getCIntegerField("_vtable_len"), 0);
coleenp@4037 90 itableLen = new CIntField(type.getCIntegerField("_itable_len"), 0);
duke@435 91 breakpoints = type.getAddressField("_breakpoints");
coleenp@2497 92 genericSignature = type.getAddressField("_generic_signature");
coleenp@4037 93 majorVersion = new CIntField(type.getCIntegerField("_major_version"), 0);
coleenp@4037 94 minorVersion = new CIntField(type.getCIntegerField("_minor_version"), 0);
coleenp@4037 95 headerSize = Oop.alignObjectOffset(type.getSize());
duke@435 96
duke@435 97 // read field offset constants
never@3137 98 ACCESS_FLAGS_OFFSET = db.lookupIntConstant("FieldInfo::access_flags_offset").intValue();
never@3137 99 NAME_INDEX_OFFSET = db.lookupIntConstant("FieldInfo::name_index_offset").intValue();
never@3137 100 SIGNATURE_INDEX_OFFSET = db.lookupIntConstant("FieldInfo::signature_index_offset").intValue();
never@3137 101 INITVAL_INDEX_OFFSET = db.lookupIntConstant("FieldInfo::initval_index_offset").intValue();
jwilhelm@4430 102 LOW_OFFSET = db.lookupIntConstant("FieldInfo::low_packed_offset").intValue();
jwilhelm@4430 103 HIGH_OFFSET = db.lookupIntConstant("FieldInfo::high_packed_offset").intValue();
never@3137 104 FIELD_SLOTS = db.lookupIntConstant("FieldInfo::field_slots").intValue();
jwilhelm@4430 105 FIELDINFO_TAG_SIZE = db.lookupIntConstant("FIELDINFO_TAG_SIZE").shortValue();
sla@4462 106 FIELDINFO_TAG_MASK = db.lookupIntConstant("FIELDINFO_TAG_MASK").shortValue();
jwilhelm@4430 107 FIELDINFO_TAG_OFFSET = db.lookupIntConstant("FIELDINFO_TAG_OFFSET").shortValue();
jwilhelm@4430 108
duke@435 109 // read ClassState constants
coleenp@4037 110 CLASS_STATE_ALLOCATED = db.lookupIntConstant("InstanceKlass::allocated").intValue();
coleenp@4037 111 CLASS_STATE_LOADED = db.lookupIntConstant("InstanceKlass::loaded").intValue();
coleenp@4037 112 CLASS_STATE_LINKED = db.lookupIntConstant("InstanceKlass::linked").intValue();
coleenp@4037 113 CLASS_STATE_BEING_INITIALIZED = db.lookupIntConstant("InstanceKlass::being_initialized").intValue();
coleenp@4037 114 CLASS_STATE_FULLY_INITIALIZED = db.lookupIntConstant("InstanceKlass::fully_initialized").intValue();
coleenp@4037 115 CLASS_STATE_INITIALIZATION_ERROR = db.lookupIntConstant("InstanceKlass::initialization_error").intValue();
duke@435 116
duke@435 117 }
duke@435 118
coleenp@4037 119 public InstanceKlass(Address addr) {
coleenp@4037 120 super(addr);
never@3158 121 if (getJavaFieldsCount() != getAllFieldsCount()) {
never@3158 122 // Exercise the injected field logic
never@3158 123 for (int i = getJavaFieldsCount(); i < getAllFieldsCount(); i++) {
never@3158 124 getFieldName(i);
never@3158 125 getFieldSignature(i);
never@3158 126 }
never@3158 127 }
duke@435 128 }
duke@435 129
coleenp@4037 130 private static MetadataField arrayKlasses;
coleenp@4037 131 private static AddressField methods;
coleenp@4037 132 private static AddressField methodOrdering;
coleenp@4037 133 private static AddressField localInterfaces;
coleenp@4037 134 private static AddressField transitiveInterfaces;
coleenp@4037 135 private static AddressField fields;
never@3137 136 private static CIntField javaFieldsCount;
coleenp@4037 137 private static MetadataField constants;
coleenp@4037 138 private static AddressField classLoaderData;
duke@435 139 private static OopField protectionDomain;
duke@435 140 private static OopField signers;
coleenp@2497 141 private static AddressField sourceFileName;
coleenp@2497 142 private static AddressField sourceDebugExtension;
coleenp@4037 143 private static AddressField innerClasses;
duke@435 144 private static CIntField nonstaticFieldSize;
duke@435 145 private static CIntField staticFieldSize;
never@2658 146 private static CIntField staticOopFieldCount;
duke@435 147 private static CIntField nonstaticOopMapSize;
dcubed@3401 148 private static CIntField isMarkedDependent;
duke@435 149 private static CIntField initState;
duke@435 150 private static CIntField vtableLen;
duke@435 151 private static CIntField itableLen;
duke@435 152 private static AddressField breakpoints;
coleenp@2497 153 private static AddressField genericSignature;
duke@435 154 private static CIntField majorVersion;
duke@435 155 private static CIntField minorVersion;
duke@435 156
duke@435 157 // type safe enum for ClassState from instanceKlass.hpp
duke@435 158 public static class ClassState {
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();
coleenp@4037 180 if (state == CLASS_STATE_ALLOCATED) {
duke@435 181 return ClassState.ALLOCATED;
duke@435 182 } else if (state == CLASS_STATE_LOADED) {
duke@435 183 return ClassState.LOADED;
duke@435 184 } else if (state == CLASS_STATE_LINKED) {
duke@435 185 return ClassState.LINKED;
duke@435 186 } else if (state == CLASS_STATE_BEING_INITIALIZED) {
duke@435 187 return ClassState.BEING_INITIALIZED;
duke@435 188 } else if (state == CLASS_STATE_FULLY_INITIALIZED) {
duke@435 189 return ClassState.FULLY_INITIALIZED;
duke@435 190 } else if (state == CLASS_STATE_INITIALIZATION_ERROR) {
duke@435 191 return ClassState.INITIALIZATION_ERROR;
duke@435 192 } else {
duke@435 193 throw new RuntimeException("should not reach here");
duke@435 194 }
duke@435 195 }
duke@435 196
duke@435 197 // initialization state quaries
duke@435 198 public boolean isLoaded() {
duke@435 199 return getInitStateAsInt() >= CLASS_STATE_LOADED;
duke@435 200 }
duke@435 201
duke@435 202 public boolean isLinked() {
duke@435 203 return getInitStateAsInt() >= CLASS_STATE_LINKED;
duke@435 204 }
duke@435 205
duke@435 206 public boolean isInitialized() {
duke@435 207 return getInitStateAsInt() == CLASS_STATE_FULLY_INITIALIZED;
duke@435 208 }
duke@435 209
duke@435 210 public boolean isNotInitialized() {
duke@435 211 return getInitStateAsInt() < CLASS_STATE_BEING_INITIALIZED;
duke@435 212 }
duke@435 213
duke@435 214 public boolean isBeingInitialized() {
duke@435 215 return getInitStateAsInt() == CLASS_STATE_BEING_INITIALIZED;
duke@435 216 }
duke@435 217
duke@435 218 public boolean isInErrorState() {
duke@435 219 return getInitStateAsInt() == CLASS_STATE_INITIALIZATION_ERROR;
duke@435 220 }
duke@435 221
duke@435 222 public int getClassStatus() {
duke@435 223 int result = 0;
duke@435 224 if (isLinked()) {
duke@435 225 result |= JVMDIClassStatus.VERIFIED | JVMDIClassStatus.PREPARED;
duke@435 226 }
duke@435 227
duke@435 228 if (isInitialized()) {
duke@435 229 if (Assert.ASSERTS_ENABLED) {
duke@435 230 Assert.that(isLinked(), "Class status is not consistent");
duke@435 231 }
duke@435 232 result |= JVMDIClassStatus.INITIALIZED;
duke@435 233 }
duke@435 234
duke@435 235 if (isInErrorState()) {
duke@435 236 result |= JVMDIClassStatus.ERROR;
duke@435 237 }
duke@435 238 return result;
duke@435 239 }
duke@435 240
duke@435 241 // Byteside of the header
duke@435 242 private static long headerSize;
duke@435 243
never@2693 244 public long getObjectSize(Oop object) {
never@2693 245 return getSizeHelper() * VM.getVM().getAddressSize();
never@2693 246 }
never@2693 247
coleenp@4037 248 public long getSize() {
coleenp@4037 249 return Oop.alignObjectSize(getHeaderSize() + Oop.alignObjectOffset(getVtableLen()) +
coleenp@4037 250 Oop.alignObjectOffset(getItableLen()) + Oop.alignObjectOffset(getNonstaticOopMapSize()));
coleenp@4037 251 }
coleenp@4037 252
duke@435 253 public static long getHeaderSize() { return headerSize; }
duke@435 254
never@3137 255 public short getFieldAccessFlags(int index) {
coleenp@4037 256 return getFields().at(index * FIELD_SLOTS + ACCESS_FLAGS_OFFSET);
never@3137 257 }
never@3137 258
never@3158 259 public short getFieldNameIndex(int index) {
never@3158 260 if (index >= getJavaFieldsCount()) throw new IndexOutOfBoundsException("not a Java field;");
coleenp@4037 261 return getFields().at(index * FIELD_SLOTS + NAME_INDEX_OFFSET);
never@3158 262 }
never@3158 263
never@3137 264 public Symbol getFieldName(int index) {
coleenp@4037 265 int nameIndex = getFields().at(index * FIELD_SLOTS + NAME_INDEX_OFFSET);
never@3158 266 if (index < getJavaFieldsCount()) {
never@3158 267 return getConstants().getSymbolAt(nameIndex);
never@3158 268 } else {
never@3158 269 return vmSymbols.symbolAt(nameIndex);
never@3158 270 }
never@3158 271 }
never@3158 272
never@3158 273 public short getFieldSignatureIndex(int index) {
never@3158 274 if (index >= getJavaFieldsCount()) throw new IndexOutOfBoundsException("not a Java field;");
coleenp@4037 275 return getFields().at(index * FIELD_SLOTS + SIGNATURE_INDEX_OFFSET);
never@3137 276 }
never@3137 277
never@3137 278 public Symbol getFieldSignature(int index) {
coleenp@4037 279 int signatureIndex = getFields().at(index * FIELD_SLOTS + SIGNATURE_INDEX_OFFSET);
never@3158 280 if (index < getJavaFieldsCount()) {
never@3158 281 return getConstants().getSymbolAt(signatureIndex);
never@3158 282 } else {
never@3158 283 return vmSymbols.symbolAt(signatureIndex);
never@3158 284 }
never@3158 285 }
never@3158 286
never@3158 287 public short getFieldGenericSignatureIndex(int index) {
minqi@4267 288 // int len = getFields().length();
jiangli@3803 289 int allFieldsCount = getAllFieldsCount();
jiangli@3803 290 int generic_signature_slot = allFieldsCount * FIELD_SLOTS;
jiangli@3803 291 for (int i = 0; i < allFieldsCount; i++) {
jiangli@3803 292 short flags = getFieldAccessFlags(i);
jiangli@3803 293 AccessFlags access = new AccessFlags(flags);
jiangli@3803 294 if (i == index) {
jiangli@3803 295 if (access.fieldHasGenericSignature()) {
coleenp@4037 296 return getFields().at(generic_signature_slot);
jiangli@3803 297 } else {
jiangli@3803 298 return 0;
jiangli@3803 299 }
jiangli@3803 300 } else {
jiangli@3803 301 if (access.fieldHasGenericSignature()) {
jiangli@3803 302 generic_signature_slot ++;
jiangli@3803 303 }
jiangli@3803 304 }
jiangli@3803 305 }
jiangli@3803 306 return 0;
never@3137 307 }
never@3137 308
never@3137 309 public Symbol getFieldGenericSignature(int index) {
never@3158 310 short genericSignatureIndex = getFieldGenericSignatureIndex(index);
never@3137 311 if (genericSignatureIndex != 0) {
never@3137 312 return getConstants().getSymbolAt(genericSignatureIndex);
never@3137 313 }
never@3137 314 return null;
never@3137 315 }
never@3137 316
never@3158 317 public short getFieldInitialValueIndex(int index) {
never@3158 318 if (index >= getJavaFieldsCount()) throw new IndexOutOfBoundsException("not a Java field;");
coleenp@4037 319 return getFields().at(index * FIELD_SLOTS + INITVAL_INDEX_OFFSET);
never@3158 320 }
never@3158 321
never@3137 322 public int getFieldOffset(int index) {
coleenp@4037 323 U2Array fields = getFields();
jwilhelm@4430 324 short lo = fields.at(index * FIELD_SLOTS + LOW_OFFSET);
jwilhelm@4430 325 short hi = fields.at(index * FIELD_SLOTS + HIGH_OFFSET);
sla@4462 326 if ((lo & FIELDINFO_TAG_MASK) == FIELDINFO_TAG_OFFSET) {
jwilhelm@4430 327 return VM.getVM().buildIntFromShorts(lo, hi) >> FIELDINFO_TAG_SIZE;
jwilhelm@4430 328 }
jwilhelm@4430 329 throw new RuntimeException("should not reach here");
never@3137 330 }
never@3137 331
duke@435 332 // Accessors for declared fields
duke@435 333 public Klass getArrayKlasses() { return (Klass) arrayKlasses.getValue(this); }
coleenp@4037 334 public MethodArray getMethods() { return new MethodArray(methods.getValue(getAddress())); }
coleenp@4037 335 public KlassArray getLocalInterfaces() { return new KlassArray(localInterfaces.getValue(getAddress())); }
coleenp@4037 336 public KlassArray getTransitiveInterfaces() { return new KlassArray(transitiveInterfaces.getValue(getAddress())); }
never@3137 337 public int getJavaFieldsCount() { return (int) javaFieldsCount.getValue(this); }
jiangli@3803 338 public int getAllFieldsCount() {
minqi@4267 339 int len = getFields().length();
jiangli@3803 340 int allFieldsCount = 0;
jiangli@3803 341 for (; allFieldsCount*FIELD_SLOTS < len; allFieldsCount++) {
jiangli@3803 342 short flags = getFieldAccessFlags(allFieldsCount);
jiangli@3803 343 AccessFlags access = new AccessFlags(flags);
jiangli@3803 344 if (access.fieldHasGenericSignature()) {
jiangli@3803 345 len --;
jiangli@3803 346 }
jiangli@3803 347 }
jiangli@3803 348 return allFieldsCount;
jiangli@3803 349 }
duke@435 350 public ConstantPool getConstants() { return (ConstantPool) constants.getValue(this); }
coleenp@4037 351 public ClassLoaderData getClassLoaderData() { return ClassLoaderData.instantiateWrapperFor(classLoaderData.getValue(getAddress())); }
coleenp@4037 352 public Oop getClassLoader() { return getClassLoaderData().getClassLoader(); }
duke@435 353 public Oop getProtectionDomain() { return protectionDomain.getValue(this); }
duke@435 354 public ObjArray getSigners() { return (ObjArray) signers.getValue(this); }
coleenp@2497 355 public Symbol getSourceFileName() { return getSymbol(sourceFileName); }
coleenp@4037 356 public String getSourceDebugExtension(){ return CStringUtilities.getString(sourceDebugExtension.getValue(getAddress())); }
duke@435 357 public long getNonstaticFieldSize() { return nonstaticFieldSize.getValue(this); }
never@2658 358 public long getStaticOopFieldCount() { return staticOopFieldCount.getValue(this); }
duke@435 359 public long getNonstaticOopMapSize() { return nonstaticOopMapSize.getValue(this); }
dcubed@3401 360 public boolean getIsMarkedDependent() { return isMarkedDependent.getValue(this) != 0; }
duke@435 361 public long getVtableLen() { return vtableLen.getValue(this); }
duke@435 362 public long getItableLen() { return itableLen.getValue(this); }
coleenp@2497 363 public Symbol getGenericSignature() { return getSymbol(genericSignature); }
duke@435 364 public long majorVersion() { return majorVersion.getValue(this); }
duke@435 365 public long minorVersion() { return minorVersion.getValue(this); }
duke@435 366
duke@435 367 // "size helper" == instance size in words
duke@435 368 public long getSizeHelper() {
duke@435 369 int lh = getLayoutHelper();
duke@435 370 if (Assert.ASSERTS_ENABLED) {
duke@435 371 Assert.that(lh > 0, "layout helper initialized for instance class");
duke@435 372 }
duke@435 373 return lh / VM.getVM().getAddressSize();
duke@435 374 }
duke@435 375
duke@435 376 // same as enum InnerClassAttributeOffset in VM code.
duke@435 377 public static interface InnerClassAttributeOffset {
duke@435 378 // from JVM spec. "InnerClasses" attribute
duke@435 379 public static final int innerClassInnerClassInfoOffset = 0;
duke@435 380 public static final int innerClassOuterClassInfoOffset = 1;
duke@435 381 public static final int innerClassInnerNameOffset = 2;
duke@435 382 public static final int innerClassAccessFlagsOffset = 3;
duke@435 383 public static final int innerClassNextOffset = 4;
duke@435 384 };
duke@435 385
jiangli@3670 386 public static interface EnclosingMethodAttributeOffset {
jiangli@3670 387 public static final int enclosing_method_class_index_offset = 0;
jiangli@3670 388 public static final int enclosing_method_method_index_offset = 1;
jiangli@3670 389 public static final int enclosing_method_attribute_size = 2;
jiangli@3670 390 };
jiangli@3670 391
duke@435 392 // refer to compute_modifier_flags in VM code.
duke@435 393 public long computeModifierFlags() {
duke@435 394 long access = getAccessFlags();
duke@435 395 // But check if it happens to be member class.
coleenp@4037 396 U2Array innerClassList = getInnerClasses();
coleenp@4037 397 int length = (innerClassList == null)? 0 : (int) innerClassList.length();
duke@435 398 if (length > 0) {
duke@435 399 if (Assert.ASSERTS_ENABLED) {
jiangli@3670 400 Assert.that(length % InnerClassAttributeOffset.innerClassNextOffset == 0 ||
jiangli@3670 401 length % InnerClassAttributeOffset.innerClassNextOffset == EnclosingMethodAttributeOffset.enclosing_method_attribute_size,
jiangli@3670 402 "just checking");
duke@435 403 }
duke@435 404 for (int i = 0; i < length; i += InnerClassAttributeOffset.innerClassNextOffset) {
jiangli@3670 405 if (i == length - EnclosingMethodAttributeOffset.enclosing_method_attribute_size) {
jiangli@3670 406 break;
jiangli@3670 407 }
coleenp@4037 408 int ioff = innerClassList.at(i +
duke@435 409 InnerClassAttributeOffset.innerClassInnerClassInfoOffset);
duke@435 410 // 'ioff' can be zero.
duke@435 411 // refer to JVM spec. section 4.7.5.
duke@435 412 if (ioff != 0) {
duke@435 413 // only look at classes that are already loaded
duke@435 414 // since we are looking for the flags for our self.
coleenp@2497 415 ConstantPool.CPSlot classInfo = getConstants().getSlotAt(ioff);
duke@435 416 Symbol name = null;
coleenp@4037 417 if (classInfo.isResolved()) {
coleenp@4037 418 name = classInfo.getKlass().getName();
coleenp@4037 419 } else if (classInfo.isUnresolved()) {
coleenp@2497 420 name = classInfo.getSymbol();
duke@435 421 } else {
duke@435 422 throw new RuntimeException("should not reach here");
duke@435 423 }
duke@435 424
duke@435 425 if (name.equals(getName())) {
duke@435 426 // This is really a member class
coleenp@4037 427 access = innerClassList.at(i +
duke@435 428 InnerClassAttributeOffset.innerClassAccessFlagsOffset);
duke@435 429 break;
duke@435 430 }
duke@435 431 }
duke@435 432 } // for inner classes
duke@435 433 }
duke@435 434
duke@435 435 // Remember to strip ACC_SUPER bit
duke@435 436 return (access & (~JVM_ACC_SUPER)) & JVM_ACC_WRITTEN_FLAGS;
duke@435 437 }
duke@435 438
duke@435 439
duke@435 440 // whether given Symbol is name of an inner/nested Klass of this Klass?
duke@435 441 // anonymous and local classes are excluded.
duke@435 442 public boolean isInnerClassName(Symbol sym) {
duke@435 443 return isInInnerClasses(sym, false);
duke@435 444 }
duke@435 445
duke@435 446 // whether given Symbol is name of an inner/nested Klass of this Klass?
duke@435 447 // anonymous classes excluded, but local classes are included.
duke@435 448 public boolean isInnerOrLocalClassName(Symbol sym) {
duke@435 449 return isInInnerClasses(sym, true);
duke@435 450 }
duke@435 451
duke@435 452 private boolean isInInnerClasses(Symbol sym, boolean includeLocals) {
coleenp@4037 453 U2Array innerClassList = getInnerClasses();
coleenp@4037 454 int length = ( innerClassList == null)? 0 : (int) innerClassList.length();
duke@435 455 if (length > 0) {
duke@435 456 if (Assert.ASSERTS_ENABLED) {
jiangli@3670 457 Assert.that(length % InnerClassAttributeOffset.innerClassNextOffset == 0 ||
jiangli@3670 458 length % InnerClassAttributeOffset.innerClassNextOffset == EnclosingMethodAttributeOffset.enclosing_method_attribute_size,
jiangli@3670 459 "just checking");
duke@435 460 }
duke@435 461 for (int i = 0; i < length; i += InnerClassAttributeOffset.innerClassNextOffset) {
jiangli@3670 462 if (i == length - EnclosingMethodAttributeOffset.enclosing_method_attribute_size) {
jiangli@3670 463 break;
jiangli@3670 464 }
coleenp@4037 465 int ioff = innerClassList.at(i +
duke@435 466 InnerClassAttributeOffset.innerClassInnerClassInfoOffset);
duke@435 467 // 'ioff' can be zero.
duke@435 468 // refer to JVM spec. section 4.7.5.
duke@435 469 if (ioff != 0) {
coleenp@2497 470 ConstantPool.CPSlot iclassInfo = getConstants().getSlotAt(ioff);
coleenp@4037 471 Symbol innerName = getConstants().getKlassNameAt(ioff);
duke@435 472 Symbol myname = getName();
coleenp@4037 473 int ooff = innerClassList.at(i +
duke@435 474 InnerClassAttributeOffset.innerClassOuterClassInfoOffset);
duke@435 475 // for anonymous classes inner_name_index of InnerClasses
duke@435 476 // attribute is zero.
coleenp@4037 477 int innerNameIndex = innerClassList.at(i +
duke@435 478 InnerClassAttributeOffset.innerClassInnerNameOffset);
duke@435 479 // if this is not a member (anonymous, local etc.), 'ooff' will be zero
duke@435 480 // refer to JVM spec. section 4.7.5.
duke@435 481 if (ooff == 0) {
duke@435 482 if (includeLocals) {
duke@435 483 // does it looks like my local class?
duke@435 484 if (innerName.equals(sym) &&
duke@435 485 innerName.asString().startsWith(myname.asString())) {
duke@435 486 // exclude anonymous classes.
duke@435 487 return (innerNameIndex != 0);
duke@435 488 }
duke@435 489 }
duke@435 490 } else {
coleenp@2497 491 ConstantPool.CPSlot oclassInfo = getConstants().getSlotAt(ooff);
duke@435 492 Symbol outerName = null;
coleenp@4037 493 if (oclassInfo.isResolved()) {
coleenp@4037 494 outerName = oclassInfo.getKlass().getName();
coleenp@4037 495 } else if (oclassInfo.isUnresolved()) {
coleenp@2497 496 outerName = oclassInfo.getSymbol();
duke@435 497 } else {
duke@435 498 throw new RuntimeException("should not reach here");
duke@435 499 }
duke@435 500
duke@435 501 // include only if current class is outer class.
duke@435 502 if (outerName.equals(myname) && innerName.equals(sym)) {
duke@435 503 return true;
duke@435 504 }
duke@435 505 }
duke@435 506 }
duke@435 507 } // for inner classes
duke@435 508 return false;
duke@435 509 } else {
duke@435 510 return false;
duke@435 511 }
duke@435 512 }
duke@435 513
duke@435 514 public boolean implementsInterface(Klass k) {
duke@435 515 if (Assert.ASSERTS_ENABLED) {
duke@435 516 Assert.that(k.isInterface(), "should not reach here");
duke@435 517 }
coleenp@4037 518 KlassArray interfaces = getTransitiveInterfaces();
coleenp@4037 519 final int len = interfaces.length();
duke@435 520 for (int i = 0; i < len; i++) {
coleenp@4037 521 if (interfaces.getAt(i).equals(k)) return true;
duke@435 522 }
duke@435 523 return false;
duke@435 524 }
duke@435 525
duke@435 526 boolean computeSubtypeOf(Klass k) {
duke@435 527 if (k.isInterface()) {
duke@435 528 return implementsInterface(k);
duke@435 529 } else {
duke@435 530 return super.computeSubtypeOf(k);
duke@435 531 }
duke@435 532 }
duke@435 533
duke@435 534 public void printValueOn(PrintStream tty) {
duke@435 535 tty.print("InstanceKlass for " + getName().asString());
duke@435 536 }
duke@435 537
coleenp@4037 538 public void iterateFields(MetadataVisitor visitor) {
coleenp@4037 539 super.iterateFields(visitor);
coleenp@4037 540 visitor.doMetadata(arrayKlasses, true);
coleenp@4037 541 // visitor.doOop(methods, true);
coleenp@4037 542 // visitor.doOop(localInterfaces, true);
coleenp@4037 543 // visitor.doOop(transitiveInterfaces, true);
duke@435 544 visitor.doOop(protectionDomain, true);
duke@435 545 visitor.doOop(signers, true);
duke@435 546 visitor.doCInt(nonstaticFieldSize, true);
duke@435 547 visitor.doCInt(staticFieldSize, true);
never@2658 548 visitor.doCInt(staticOopFieldCount, true);
duke@435 549 visitor.doCInt(nonstaticOopMapSize, true);
dcubed@3401 550 visitor.doCInt(isMarkedDependent, true);
duke@435 551 visitor.doCInt(initState, true);
duke@435 552 visitor.doCInt(vtableLen, true);
duke@435 553 visitor.doCInt(itableLen, true);
duke@435 554 }
duke@435 555
never@2693 556 /*
never@2693 557 * Visit the static fields of this InstanceKlass with the obj of
never@2693 558 * the visitor set to the oop holding the fields, which is
never@2693 559 * currently the java mirror.
never@2693 560 */
never@2693 561 public void iterateStaticFields(OopVisitor visitor) {
never@2693 562 visitor.setObj(getJavaMirror());
never@2693 563 visitor.prologue();
never@2693 564 iterateStaticFieldsInternal(visitor);
never@2693 565 visitor.epilogue();
never@2693 566
never@2693 567 }
never@2693 568
never@2693 569 void iterateStaticFieldsInternal(OopVisitor visitor) {
never@3137 570 int length = getJavaFieldsCount();
never@3143 571 for (int index = 0; index < length; index++) {
never@3143 572 short accessFlags = getFieldAccessFlags(index);
never@3143 573 FieldType type = new FieldType(getFieldSignature(index));
duke@435 574 AccessFlags access = new AccessFlags(accessFlags);
duke@435 575 if (access.isStatic()) {
duke@435 576 visitField(visitor, type, index);
duke@435 577 }
duke@435 578 }
duke@435 579 }
duke@435 580
duke@435 581 public Klass getJavaSuper() {
duke@435 582 return getSuper();
duke@435 583 }
duke@435 584
never@3138 585 public static class StaticField {
never@3138 586 public AccessFlags flags;
never@3138 587 public Field field;
never@3138 588
never@3138 589 StaticField(Field field, AccessFlags flags) {
never@3138 590 this.field = field;
never@3138 591 this.flags = flags;
never@3138 592 }
never@3138 593 }
never@3138 594
minqi@4267 595 public Field[] getStaticFields() {
minqi@4267 596 U2Array fields = getFields();
minqi@4267 597 int length = getJavaFieldsCount();
minqi@4267 598 ArrayList result = new ArrayList();
minqi@4267 599 for (int index = 0; index < length; index++) {
minqi@4267 600 Field f = newField(index);
minqi@4267 601 if (f.isStatic()) {
minqi@4267 602 result.add(f);
minqi@4267 603 }
minqi@4267 604 }
minqi@4267 605 return (Field[])result.toArray(new Field[result.size()]);
minqi@4267 606 }
minqi@4267 607
never@2693 608 public void iterateNonStaticFields(OopVisitor visitor, Oop obj) {
duke@435 609 if (getSuper() != null) {
never@2693 610 ((InstanceKlass) getSuper()).iterateNonStaticFields(visitor, obj);
duke@435 611 }
never@3137 612 int length = getJavaFieldsCount();
never@3143 613 for (int index = 0; index < length; index++) {
never@3143 614 short accessFlags = getFieldAccessFlags(index);
never@3143 615 FieldType type = new FieldType(getFieldSignature(index));
duke@435 616 AccessFlags access = new AccessFlags(accessFlags);
duke@435 617 if (!access.isStatic()) {
duke@435 618 visitField(visitor, type, index);
duke@435 619 }
duke@435 620 }
duke@435 621 }
duke@435 622
duke@435 623 /** Field access by name. */
duke@435 624 public Field findLocalField(Symbol name, Symbol sig) {
never@3158 625 int length = getJavaFieldsCount();
never@3143 626 for (int i = 0; i < length; i++) {
never@3143 627 Symbol f_name = getFieldName(i);
never@3143 628 Symbol f_sig = getFieldSignature(i);
duke@435 629 if (name.equals(f_name) && sig.equals(f_sig)) {
duke@435 630 return newField(i);
duke@435 631 }
duke@435 632 }
duke@435 633
duke@435 634 return null;
duke@435 635 }
duke@435 636
duke@435 637 /** Find field in direct superinterfaces. */
duke@435 638 public Field findInterfaceField(Symbol name, Symbol sig) {
coleenp@4037 639 KlassArray interfaces = getLocalInterfaces();
coleenp@4037 640 int n = interfaces.length();
duke@435 641 for (int i = 0; i < n; i++) {
coleenp@4037 642 InstanceKlass intf1 = (InstanceKlass) interfaces.getAt(i);
duke@435 643 if (Assert.ASSERTS_ENABLED) {
duke@435 644 Assert.that(intf1.isInterface(), "just checking type");
duke@435 645 }
duke@435 646 // search for field in current interface
duke@435 647 Field f = intf1.findLocalField(name, sig);
duke@435 648 if (f != null) {
duke@435 649 if (Assert.ASSERTS_ENABLED) {
duke@435 650 Assert.that(f.getAccessFlagsObj().isStatic(), "interface field must be static");
duke@435 651 }
duke@435 652 return f;
duke@435 653 }
duke@435 654 // search for field in direct superinterfaces
duke@435 655 f = intf1.findInterfaceField(name, sig);
duke@435 656 if (f != null) return f;
duke@435 657 }
duke@435 658 // otherwise field lookup fails
duke@435 659 return null;
duke@435 660 }
duke@435 661
duke@435 662 /** Find field according to JVM spec 5.4.3.2, returns the klass in
duke@435 663 which the field is defined. */
duke@435 664 public Field findField(Symbol name, Symbol sig) {
duke@435 665 // search order according to newest JVM spec (5.4.3.2, p.167).
duke@435 666 // 1) search for field in current klass
duke@435 667 Field f = findLocalField(name, sig);
duke@435 668 if (f != null) return f;
duke@435 669
duke@435 670 // 2) search for field recursively in direct superinterfaces
duke@435 671 f = findInterfaceField(name, sig);
duke@435 672 if (f != null) return f;
duke@435 673
duke@435 674 // 3) apply field lookup recursively if superclass exists
duke@435 675 InstanceKlass supr = (InstanceKlass) getSuper();
duke@435 676 if (supr != null) return supr.findField(name, sig);
duke@435 677
duke@435 678 // 4) otherwise field lookup fails
duke@435 679 return null;
duke@435 680 }
duke@435 681
duke@435 682 /** Find field according to JVM spec 5.4.3.2, returns the klass in
duke@435 683 which the field is defined (convenience routine) */
duke@435 684 public Field findField(String name, String sig) {
duke@435 685 SymbolTable symbols = VM.getVM().getSymbolTable();
duke@435 686 Symbol nameSym = symbols.probe(name);
duke@435 687 Symbol sigSym = symbols.probe(sig);
duke@435 688 if (nameSym == null || sigSym == null) {
duke@435 689 return null;
duke@435 690 }
duke@435 691 return findField(nameSym, sigSym);
duke@435 692 }
duke@435 693
duke@435 694 /** Find field according to JVM spec 5.4.3.2, returns the klass in
duke@435 695 which the field is defined (retained only for backward
duke@435 696 compatibility with jdbx) */
duke@435 697 public Field findFieldDbg(String name, String sig) {
duke@435 698 return findField(name, sig);
duke@435 699 }
duke@435 700
duke@435 701 /** Get field by its index in the fields array. Only designed for
duke@435 702 use in a debugging system. */
never@3143 703 public Field getFieldByIndex(int fieldIndex) {
never@3143 704 return newField(fieldIndex);
duke@435 705 }
duke@435 706
duke@435 707
duke@435 708 /** Return a List of SA Fields for the fields declared in this class.
duke@435 709 Inherited fields are not included.
duke@435 710 Return an empty list if there are no fields declared in this class.
duke@435 711 Only designed for use in a debugging system. */
duke@435 712 public List getImmediateFields() {
duke@435 713 // A list of Fields for each field declared in this class/interface,
duke@435 714 // not including inherited fields.
never@3137 715 int length = getJavaFieldsCount();
never@3137 716 List immediateFields = new ArrayList(length);
never@3143 717 for (int index = 0; index < length; index++) {
duke@435 718 immediateFields.add(getFieldByIndex(index));
duke@435 719 }
duke@435 720
duke@435 721 return immediateFields;
duke@435 722 }
duke@435 723
duke@435 724 /** Return a List of SA Fields for all the java fields in this class,
duke@435 725 including all inherited fields. This includes hidden
duke@435 726 fields. Thus the returned list can contain fields with
duke@435 727 the same name.
duke@435 728 Return an empty list if there are no fields.
duke@435 729 Only designed for use in a debugging system. */
duke@435 730 public List getAllFields() {
duke@435 731 // Contains a Field for each field in this class, including immediate
duke@435 732 // fields and inherited fields.
duke@435 733 List allFields = getImmediateFields();
duke@435 734
duke@435 735 // transitiveInterfaces contains all interfaces implemented
duke@435 736 // by this class and its superclass chain with no duplicates.
duke@435 737
coleenp@4037 738 KlassArray interfaces = getTransitiveInterfaces();
coleenp@4037 739 int n = interfaces.length();
duke@435 740 for (int i = 0; i < n; i++) {
coleenp@4037 741 InstanceKlass intf1 = (InstanceKlass) interfaces.getAt(i);
duke@435 742 if (Assert.ASSERTS_ENABLED) {
duke@435 743 Assert.that(intf1.isInterface(), "just checking type");
duke@435 744 }
duke@435 745 allFields.addAll(intf1.getImmediateFields());
duke@435 746 }
duke@435 747
duke@435 748 // Get all fields in the superclass, recursively. But, don't
duke@435 749 // include fields in interfaces implemented by superclasses;
duke@435 750 // we already have all those.
duke@435 751 if (!isInterface()) {
duke@435 752 InstanceKlass supr;
duke@435 753 if ( (supr = (InstanceKlass) getSuper()) != null) {
duke@435 754 allFields.addAll(supr.getImmediateFields());
duke@435 755 }
duke@435 756 }
duke@435 757
duke@435 758 return allFields;
duke@435 759 }
duke@435 760
duke@435 761
duke@435 762 /** Return a List of SA Methods declared directly in this class/interface.
duke@435 763 Return an empty list if there are none, or if this isn't a class/
duke@435 764 interface.
duke@435 765 */
duke@435 766 public List getImmediateMethods() {
duke@435 767 // Contains a Method for each method declared in this class/interface
duke@435 768 // not including inherited methods.
duke@435 769
coleenp@4037 770 MethodArray methods = getMethods();
coleenp@4037 771 int length = methods.length();
duke@435 772 Object[] tmp = new Object[length];
duke@435 773
coleenp@4037 774 IntArray methodOrdering = getMethodOrdering();
coleenp@4037 775 if (methodOrdering.length() != length) {
duke@435 776 // no ordering info present
duke@435 777 for (int index = 0; index < length; index++) {
coleenp@4037 778 tmp[index] = methods.at(index);
duke@435 779 }
duke@435 780 } else {
duke@435 781 for (int index = 0; index < length; index++) {
coleenp@4037 782 int originalIndex = methodOrdering.at(index);
coleenp@4037 783 tmp[originalIndex] = methods.at(index);
duke@435 784 }
duke@435 785 }
duke@435 786
duke@435 787 return Arrays.asList(tmp);
duke@435 788 }
duke@435 789
duke@435 790 /** Return a List containing an SA InstanceKlass for each
duke@435 791 interface named in this class's 'implements' clause.
duke@435 792 */
duke@435 793 public List getDirectImplementedInterfaces() {
duke@435 794 // Contains an InstanceKlass for each interface in this classes
duke@435 795 // 'implements' clause.
duke@435 796
coleenp@4037 797 KlassArray interfaces = getLocalInterfaces();
coleenp@4037 798 int length = interfaces.length();
duke@435 799 List directImplementedInterfaces = new ArrayList(length);
duke@435 800
duke@435 801 for (int index = 0; index < length; index ++) {
coleenp@4037 802 directImplementedInterfaces.add(interfaces.getAt(index));
duke@435 803 }
duke@435 804
duke@435 805 return directImplementedInterfaces;
duke@435 806 }
duke@435 807
duke@435 808 public Klass arrayKlassImpl(boolean orNull, int n) {
duke@435 809 // FIXME: in reflective system this would need to change to
duke@435 810 // actually allocate
duke@435 811 if (getArrayKlasses() == null) { return null; }
duke@435 812 ObjArrayKlass oak = (ObjArrayKlass) getArrayKlasses();
duke@435 813 if (orNull) {
duke@435 814 return oak.arrayKlassOrNull(n);
duke@435 815 }
duke@435 816 return oak.arrayKlass(n);
duke@435 817 }
duke@435 818
duke@435 819 public Klass arrayKlassImpl(boolean orNull) {
duke@435 820 return arrayKlassImpl(orNull, 1);
duke@435 821 }
duke@435 822
duke@435 823 public String signature() {
duke@435 824 return "L" + super.signature() + ";";
duke@435 825 }
duke@435 826
duke@435 827 /** Convenience routine taking Strings; lookup is done in
duke@435 828 SymbolTable. */
duke@435 829 public Method findMethod(String name, String sig) {
duke@435 830 SymbolTable syms = VM.getVM().getSymbolTable();
duke@435 831 Symbol nameSym = syms.probe(name);
duke@435 832 Symbol sigSym = syms.probe(sig);
duke@435 833 if (nameSym == null || sigSym == null) {
duke@435 834 return null;
duke@435 835 }
duke@435 836 return findMethod(nameSym, sigSym);
duke@435 837 }
duke@435 838
duke@435 839 /** Find method in vtable. */
duke@435 840 public Method findMethod(Symbol name, Symbol sig) {
duke@435 841 return findMethod(getMethods(), name, sig);
duke@435 842 }
duke@435 843
coleenp@4037 844 /** Breakpoint support (see methods on Method* for details) */
duke@435 845 public BreakpointInfo getBreakpoints() {
coleenp@4037 846 Address addr = getAddress().getAddressAt(breakpoints.getOffset());
duke@435 847 return (BreakpointInfo) VMObjectFactory.newObject(BreakpointInfo.class, addr);
duke@435 848 }
duke@435 849
coleenp@4037 850 public IntArray getMethodOrdering() {
coleenp@4037 851 Address addr = getAddress().getAddressAt(methodOrdering.getOffset());
coleenp@4037 852 return (IntArray) VMObjectFactory.newObject(IntArray.class, addr);
coleenp@4037 853 }
coleenp@4037 854
coleenp@4037 855 public U2Array getFields() {
coleenp@4037 856 Address addr = getAddress().getAddressAt(fields.getOffset());
coleenp@4037 857 return (U2Array) VMObjectFactory.newObject(U2Array.class, addr);
coleenp@4037 858 }
coleenp@4037 859
coleenp@4037 860 public U2Array getInnerClasses() {
coleenp@4037 861 Address addr = getAddress().getAddressAt(innerClasses.getOffset());
coleenp@4037 862 return (U2Array) VMObjectFactory.newObject(U2Array.class, addr);
coleenp@4037 863 }
coleenp@4037 864
coleenp@4037 865
duke@435 866 //----------------------------------------------------------------------
duke@435 867 // Internals only below this point
duke@435 868 //
duke@435 869
duke@435 870 private void visitField(OopVisitor visitor, FieldType type, int index) {
duke@435 871 Field f = newField(index);
duke@435 872 if (type.isOop()) {
duke@435 873 visitor.doOop((OopField) f, false);
duke@435 874 return;
duke@435 875 }
duke@435 876 if (type.isByte()) {
duke@435 877 visitor.doByte((ByteField) f, false);
duke@435 878 return;
duke@435 879 }
duke@435 880 if (type.isChar()) {
duke@435 881 visitor.doChar((CharField) f, false);
duke@435 882 return;
duke@435 883 }
duke@435 884 if (type.isDouble()) {
duke@435 885 visitor.doDouble((DoubleField) f, false);
duke@435 886 return;
duke@435 887 }
duke@435 888 if (type.isFloat()) {
duke@435 889 visitor.doFloat((FloatField) f, false);
duke@435 890 return;
duke@435 891 }
duke@435 892 if (type.isInt()) {
duke@435 893 visitor.doInt((IntField) f, false);
duke@435 894 return;
duke@435 895 }
duke@435 896 if (type.isLong()) {
duke@435 897 visitor.doLong((LongField) f, false);
duke@435 898 return;
duke@435 899 }
duke@435 900 if (type.isShort()) {
duke@435 901 visitor.doShort((ShortField) f, false);
duke@435 902 return;
duke@435 903 }
duke@435 904 if (type.isBoolean()) {
duke@435 905 visitor.doBoolean((BooleanField) f, false);
duke@435 906 return;
duke@435 907 }
duke@435 908 }
duke@435 909
duke@435 910 // Creates new field from index in fields TypeArray
duke@435 911 private Field newField(int index) {
never@3143 912 FieldType type = new FieldType(getFieldSignature(index));
duke@435 913 if (type.isOop()) {
coleenp@548 914 if (VM.getVM().isCompressedOopsEnabled()) {
coleenp@548 915 return new NarrowOopField(this, index);
coleenp@548 916 } else {
coleenp@548 917 return new OopField(this, index);
coleenp@548 918 }
duke@435 919 }
duke@435 920 if (type.isByte()) {
duke@435 921 return new ByteField(this, index);
duke@435 922 }
duke@435 923 if (type.isChar()) {
duke@435 924 return new CharField(this, index);
duke@435 925 }
duke@435 926 if (type.isDouble()) {
duke@435 927 return new DoubleField(this, index);
duke@435 928 }
duke@435 929 if (type.isFloat()) {
duke@435 930 return new FloatField(this, index);
duke@435 931 }
duke@435 932 if (type.isInt()) {
duke@435 933 return new IntField(this, index);
duke@435 934 }
duke@435 935 if (type.isLong()) {
duke@435 936 return new LongField(this, index);
duke@435 937 }
duke@435 938 if (type.isShort()) {
duke@435 939 return new ShortField(this, index);
duke@435 940 }
duke@435 941 if (type.isBoolean()) {
duke@435 942 return new BooleanField(this, index);
duke@435 943 }
duke@435 944 throw new RuntimeException("Illegal field type at index " + index);
duke@435 945 }
duke@435 946
coleenp@4037 947 private static Method findMethod(MethodArray methods, Symbol name, Symbol signature) {
coleenp@4037 948 int len = methods.length();
duke@435 949 // methods are sorted, so do binary search
duke@435 950 int l = 0;
duke@435 951 int h = len - 1;
duke@435 952 while (l <= h) {
duke@435 953 int mid = (l + h) >> 1;
coleenp@4037 954 Method m = methods.at(mid);
duke@435 955 int res = m.getName().fastCompare(name);
duke@435 956 if (res == 0) {
duke@435 957 // found matching name; do linear search to find matching signature
duke@435 958 // first, quick check for common case
duke@435 959 if (m.getSignature().equals(signature)) return m;
duke@435 960 // search downwards through overloaded methods
duke@435 961 int i;
duke@435 962 for (i = mid - 1; i >= l; i--) {
coleenp@4037 963 Method m1 = methods.at(i);
duke@435 964 if (!m1.getName().equals(name)) break;
duke@435 965 if (m1.getSignature().equals(signature)) return m1;
duke@435 966 }
duke@435 967 // search upwards
duke@435 968 for (i = mid + 1; i <= h; i++) {
coleenp@4037 969 Method m1 = methods.at(i);
duke@435 970 if (!m1.getName().equals(name)) break;
duke@435 971 if (m1.getSignature().equals(signature)) return m1;
duke@435 972 }
duke@435 973 // not found
duke@435 974 if (Assert.ASSERTS_ENABLED) {
duke@435 975 int index = linearSearch(methods, name, signature);
duke@435 976 if (index != -1) {
duke@435 977 throw new DebuggerException("binary search bug: should have found entry " + index);
duke@435 978 }
duke@435 979 }
duke@435 980 return null;
duke@435 981 } else if (res < 0) {
duke@435 982 l = mid + 1;
duke@435 983 } else {
duke@435 984 h = mid - 1;
duke@435 985 }
duke@435 986 }
duke@435 987 if (Assert.ASSERTS_ENABLED) {
duke@435 988 int index = linearSearch(methods, name, signature);
duke@435 989 if (index != -1) {
duke@435 990 throw new DebuggerException("binary search bug: should have found entry " + index);
duke@435 991 }
duke@435 992 }
duke@435 993 return null;
duke@435 994 }
duke@435 995
coleenp@4037 996 private static int linearSearch(MethodArray methods, Symbol name, Symbol signature) {
coleenp@4037 997 int len = (int) methods.length();
duke@435 998 for (int index = 0; index < len; index++) {
coleenp@4037 999 Method m = methods.at(index);
duke@435 1000 if (m.getSignature().equals(signature) && m.getName().equals(name)) {
duke@435 1001 return index;
duke@435 1002 }
duke@435 1003 }
duke@435 1004 return -1;
duke@435 1005 }
minqi@4267 1006
minqi@4267 1007 public void dumpReplayData(PrintStream out) {
minqi@4267 1008 ConstantPool cp = getConstants();
minqi@4267 1009
minqi@4267 1010 // Try to record related loaded classes
minqi@4267 1011 Klass sub = getSubklassKlass();
minqi@4267 1012 while (sub != null) {
minqi@4267 1013 if (sub instanceof InstanceKlass) {
minqi@4267 1014 out.println("instanceKlass " + sub.getName().asString());
minqi@4267 1015 }
minqi@4267 1016 sub = sub.getNextSiblingKlass();
minqi@4267 1017 }
minqi@4267 1018
minqi@4267 1019 final int length = (int) cp.getLength();
minqi@4267 1020 out.print("ciInstanceKlass " + getName().asString() + " " + (isLinked() ? 1 : 0) + " " + (isInitialized() ? 1 : 0) + " " + length);
minqi@4267 1021 for (int index = 1; index < length; index++) {
minqi@4267 1022 out.print(" " + cp.getTags().at(index));
minqi@4267 1023 }
minqi@4267 1024 out.println();
minqi@4267 1025 if (isInitialized()) {
minqi@4267 1026 Field[] staticFields = getStaticFields();
minqi@4267 1027 for (int i = 0; i < staticFields.length; i++) {
minqi@4267 1028 Field f = staticFields[i];
minqi@4267 1029 Oop mirror = getJavaMirror();
minqi@4267 1030 if (f.isFinal() && !f.hasInitialValue()) {
minqi@4267 1031 out.print("staticfield " + getName().asString() + " " +
minqi@4267 1032 OopUtilities.escapeString(f.getID().getName()) + " " +
minqi@4267 1033 f.getFieldType().getSignature().asString() + " ");
minqi@4267 1034 if (f instanceof ByteField) {
minqi@4267 1035 ByteField bf = (ByteField)f;
minqi@4267 1036 out.println(bf.getValue(mirror));
minqi@4267 1037 } else if (f instanceof BooleanField) {
minqi@4267 1038 BooleanField bf = (BooleanField)f;
minqi@4267 1039 out.println(bf.getValue(mirror) ? 1 : 0);
minqi@4267 1040 } else if (f instanceof ShortField) {
minqi@4267 1041 ShortField bf = (ShortField)f;
minqi@4267 1042 out.println(bf.getValue(mirror));
minqi@4267 1043 } else if (f instanceof CharField) {
minqi@4267 1044 CharField bf = (CharField)f;
minqi@4267 1045 out.println(bf.getValue(mirror) & 0xffff);
minqi@4267 1046 } else if (f instanceof IntField) {
minqi@4267 1047 IntField bf = (IntField)f;
minqi@4267 1048 out.println(bf.getValue(mirror));
minqi@4267 1049 } else if (f instanceof LongField) {
minqi@4267 1050 LongField bf = (LongField)f;
minqi@4267 1051 out.println(bf.getValue(mirror));
minqi@4267 1052 } else if (f instanceof FloatField) {
minqi@4267 1053 FloatField bf = (FloatField)f;
minqi@4267 1054 out.println(Float.floatToRawIntBits(bf.getValue(mirror)));
minqi@4267 1055 } else if (f instanceof DoubleField) {
minqi@4267 1056 DoubleField bf = (DoubleField)f;
minqi@4267 1057 out.println(Double.doubleToRawLongBits(bf.getValue(mirror)));
minqi@4267 1058 } else if (f instanceof OopField) {
minqi@4267 1059 OopField bf = (OopField)f;
minqi@4267 1060
minqi@4267 1061 Oop value = bf.getValue(mirror);
minqi@4267 1062 if (value == null) {
minqi@4267 1063 out.println("null");
minqi@4267 1064 } else if (value.isInstance()) {
minqi@4267 1065 Instance inst = (Instance)value;
minqi@4267 1066 if (inst.isA(SystemDictionary.getStringKlass())) {
minqi@4267 1067 out.println("\"" + OopUtilities.stringOopToEscapedString(inst) + "\"");
minqi@4267 1068 } else {
minqi@4267 1069 out.println(inst.getKlass().getName().asString());
minqi@4267 1070 }
minqi@4267 1071 } else if (value.isObjArray()) {
minqi@4267 1072 ObjArray oa = (ObjArray)value;
minqi@4267 1073 Klass ek = (ObjArrayKlass)oa.getKlass();
minqi@4267 1074 out.println(oa.getLength() + " " + ek.getName().asString());
minqi@4267 1075 } else if (value.isTypeArray()) {
minqi@4267 1076 TypeArray ta = (TypeArray)value;
minqi@4267 1077 out.println(ta.getLength());
minqi@4267 1078 } else {
minqi@4267 1079 out.println(value);
minqi@4267 1080 }
minqi@4267 1081 }
minqi@4267 1082 }
minqi@4267 1083 }
minqi@4267 1084 }
minqi@4267 1085 }
duke@435 1086 }

mercurial