# HG changeset patch # User never # Date 1315700942 25200 # Node ID e79347eebbc54c0da7f0a168a9a4adf4c548dd13 # Parent fec876499aaec09769d43efed4a102157e629e76 7086585: make Java field injection more flexible Reviewed-by: jrose, twisti, kvn, coleenp diff -r fec876499aae -r e79347eebbc5 hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/Field.java --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/Field.java Sat Sep 10 00:11:04 2011 -0700 +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/Field.java Sat Sep 10 17:29:02 2011 -0700 @@ -39,28 +39,20 @@ /** Constructor for fields that are named in an InstanceKlass's fields array (i.e., named, non-VM fields) */ - Field(InstanceKlass holder, int fieldArrayIndex) { + Field(InstanceKlass holder, int fieldIndex) { this.holder = holder; - this.fieldArrayIndex = fieldArrayIndex; + this.fieldIndex = fieldIndex; + + offset = holder.getFieldOffset(fieldIndex); + genericSignature = holder.getFieldGenericSignature(fieldIndex); - ConstantPool cp = holder.getConstants(); - TypeArray fields = holder.getFields(); - short access = fields.getShortAt(fieldArrayIndex + InstanceKlass.ACCESS_FLAGS_OFFSET); - short nameIndex = fields.getShortAt(fieldArrayIndex + InstanceKlass.NAME_INDEX_OFFSET); - short signatureIndex = fields.getShortAt(fieldArrayIndex + InstanceKlass.SIGNATURE_INDEX_OFFSET); - offset = VM.getVM().buildIntFromShorts(fields.getShortAt(fieldArrayIndex + InstanceKlass.LOW_OFFSET), - fields.getShortAt(fieldArrayIndex + InstanceKlass.HIGH_OFFSET)); - short genericSignatureIndex = fields.getShortAt(fieldArrayIndex + InstanceKlass.GENERIC_SIGNATURE_INDEX_OFFSET); - Symbol name = cp.getSymbolAt(nameIndex); + Symbol name = holder.getFieldName(fieldIndex); id = new NamedFieldIdentifier(name.asString()); - signature = cp.getSymbolAt(signatureIndex); - if (genericSignatureIndex != 0) { - genericSignature = cp.getSymbolAt(genericSignatureIndex); - } else { - genericSignature = null; - } + signature = holder.getFieldSignature(fieldIndex); fieldType = new FieldType(signature); + + short access = holder.getFieldAccessFlags(fieldIndex); accessFlags = new AccessFlags(access); } @@ -73,7 +65,7 @@ private Symbol signature; private Symbol genericSignature; private AccessFlags accessFlags; - private int fieldArrayIndex; + private int fieldIndex; /** Returns the byte offset of the field within the object or klass */ public long getOffset() { return offset; } @@ -101,8 +93,8 @@ /** (Named, non-VM fields only) Returns the index in the fields TypeArray for this field. Equivalent to the "index" in the VM's fieldDescriptors. */ - public int getFieldArrayIndex() { - return fieldArrayIndex; + public int getFieldIndex() { + return fieldIndex; } /** (Named, non-VM fields only) Retrieves the access flags. */ diff -r fec876499aae -r e79347eebbc5 hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java Sat Sep 10 00:11:04 2011 -0700 +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java Sat Sep 10 17:29:02 2011 -0700 @@ -51,7 +51,7 @@ public static int LOW_OFFSET; public static int HIGH_OFFSET; public static int GENERIC_SIGNATURE_INDEX_OFFSET; - public static int NEXT_OFFSET; + public static int FIELD_SLOTS; public static int IMPLEMENTORS_LIMIT; // ClassState constants @@ -78,6 +78,7 @@ implementors[i] = new OopField(type.getOopField("_implementors[0]"), arrayOffset); } fields = new OopField(type.getOopField("_fields"), Oop.getHeaderSize()); + javaFieldsCount = new CIntField(type.getCIntegerField("_java_fields_count"), Oop.getHeaderSize()); constants = new OopField(type.getOopField("_constants"), Oop.getHeaderSize()); classLoader = new OopField(type.getOopField("_class_loader"), Oop.getHeaderSize()); protectionDomain = new OopField(type.getOopField("_protection_domain"), Oop.getHeaderSize()); @@ -100,14 +101,14 @@ headerSize = alignObjectOffset(Oop.getHeaderSize() + type.getSize()); // read field offset constants - ACCESS_FLAGS_OFFSET = db.lookupIntConstant("instanceKlass::access_flags_offset").intValue(); - NAME_INDEX_OFFSET = db.lookupIntConstant("instanceKlass::name_index_offset").intValue(); - SIGNATURE_INDEX_OFFSET = db.lookupIntConstant("instanceKlass::signature_index_offset").intValue(); - INITVAL_INDEX_OFFSET = db.lookupIntConstant("instanceKlass::initval_index_offset").intValue(); - LOW_OFFSET = db.lookupIntConstant("instanceKlass::low_offset").intValue(); - HIGH_OFFSET = db.lookupIntConstant("instanceKlass::high_offset").intValue(); - GENERIC_SIGNATURE_INDEX_OFFSET = db.lookupIntConstant("instanceKlass::generic_signature_offset").intValue(); - NEXT_OFFSET = db.lookupIntConstant("instanceKlass::next_offset").intValue(); + ACCESS_FLAGS_OFFSET = db.lookupIntConstant("FieldInfo::access_flags_offset").intValue(); + NAME_INDEX_OFFSET = db.lookupIntConstant("FieldInfo::name_index_offset").intValue(); + SIGNATURE_INDEX_OFFSET = db.lookupIntConstant("FieldInfo::signature_index_offset").intValue(); + INITVAL_INDEX_OFFSET = db.lookupIntConstant("FieldInfo::initval_index_offset").intValue(); + LOW_OFFSET = db.lookupIntConstant("FieldInfo::low_offset").intValue(); + HIGH_OFFSET = db.lookupIntConstant("FieldInfo::high_offset").intValue(); + GENERIC_SIGNATURE_INDEX_OFFSET = db.lookupIntConstant("FieldInfo::generic_signature_offset").intValue(); + FIELD_SLOTS = db.lookupIntConstant("FieldInfo::field_slots").intValue(); // read ClassState constants CLASS_STATE_UNPARSABLE_BY_GC = db.lookupIntConstant("instanceKlass::unparsable_by_gc").intValue(); CLASS_STATE_ALLOCATED = db.lookupIntConstant("instanceKlass::allocated").intValue(); @@ -131,6 +132,7 @@ private static CIntField nofImplementors; private static OopField[] implementors; private static OopField fields; + private static CIntField javaFieldsCount; private static OopField constants; private static OopField classLoader; private static OopField protectionDomain; @@ -247,6 +249,34 @@ public static long getHeaderSize() { return headerSize; } + public short getFieldAccessFlags(int index) { + return getFields().getShortAt(index * FIELD_SLOTS + ACCESS_FLAGS_OFFSET); + } + + public Symbol getFieldName(int index) { + int nameIndex = getFields().getShortAt(index * FIELD_SLOTS + NAME_INDEX_OFFSET); + return getConstants().getSymbolAt(nameIndex); + } + + public Symbol getFieldSignature(int index) { + int signatureIndex = getFields().getShortAt(index * FIELD_SLOTS + SIGNATURE_INDEX_OFFSET); + return getConstants().getSymbolAt(signatureIndex); + } + + public Symbol getFieldGenericSignature(int index) { + short genericSignatureIndex = getFields().getShortAt(index * FIELD_SLOTS + GENERIC_SIGNATURE_INDEX_OFFSET); + if (genericSignatureIndex != 0) { + return getConstants().getSymbolAt(genericSignatureIndex); + } + return null; + } + + public int getFieldOffset(int index) { + TypeArray fields = getFields(); + return VM.getVM().buildIntFromShorts(fields.getShortAt(index * FIELD_SLOTS + LOW_OFFSET), + fields.getShortAt(index * FIELD_SLOTS + HIGH_OFFSET)); + } + // Accessors for declared fields public Klass getArrayKlasses() { return (Klass) arrayKlasses.getValue(this); } public ObjArray getMethods() { return (ObjArray) methods.getValue(this); } @@ -257,6 +287,8 @@ public Klass getImplementor() { return (Klass) implementors[0].getValue(this); } public Klass getImplementor(int i) { return (Klass) implementors[i].getValue(this); } public TypeArray getFields() { return (TypeArray) fields.getValue(this); } + public int getJavaFieldsCount() { return (int) javaFieldsCount.getValue(this); } + public int getAllFieldsCount() { return (int)getFields().getLength(); } public ConstantPool getConstants() { return (ConstantPool) constants.getValue(this); } public Oop getClassLoader() { return classLoader.getValue(this); } public Oop getProtectionDomain() { return protectionDomain.getValue(this); } @@ -480,8 +512,8 @@ void iterateStaticFieldsInternal(OopVisitor visitor) { TypeArray fields = getFields(); - int length = (int) fields.getLength(); - for (int index = 0; index < length; index += NEXT_OFFSET) { + int length = getJavaFieldsCount(); + for (int index = 0; index < length; index += FIELD_SLOTS) { short accessFlags = fields.getShortAt(index + ACCESS_FLAGS_OFFSET); short signatureIndex = fields.getShortAt(index + SIGNATURE_INDEX_OFFSET); FieldType type = new FieldType(getConstants().getSymbolAt(signatureIndex)); @@ -502,8 +534,8 @@ } TypeArray fields = getFields(); - int length = (int) fields.getLength(); - for (int index = 0; index < length; index += NEXT_OFFSET) { + int length = getJavaFieldsCount(); + for (int index = 0; index < length; index += FIELD_SLOTS) { short accessFlags = fields.getShortAt(index + ACCESS_FLAGS_OFFSET); short signatureIndex = fields.getShortAt(index + SIGNATURE_INDEX_OFFSET); @@ -518,9 +550,9 @@ /** Field access by name. */ public Field findLocalField(Symbol name, Symbol sig) { TypeArray fields = getFields(); - int n = (int) fields.getLength(); + int length = (int) fields.getLength(); ConstantPool cp = getConstants(); - for (int i = 0; i < n; i += NEXT_OFFSET) { + for (int i = 0; i < length; i += FIELD_SLOTS) { int nameIndex = fields.getShortAt(i + NAME_INDEX_OFFSET); int sigIndex = fields.getShortAt(i + SIGNATURE_INDEX_OFFSET); Symbol f_name = cp.getSymbolAt(nameIndex); @@ -613,9 +645,9 @@ // not including inherited fields. TypeArray fields = getFields(); - int length = (int) fields.getLength(); - List immediateFields = new ArrayList(length / NEXT_OFFSET); - for (int index = 0; index < length; index += NEXT_OFFSET) { + int length = getJavaFieldsCount(); + List immediateFields = new ArrayList(length); + for (int index = 0; index < length; index += FIELD_SLOTS) { immediateFields.add(getFieldByIndex(index)); } diff -r fec876499aae -r e79347eebbc5 hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/java_lang_Class.java --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/java_lang_Class.java Sat Sep 10 00:11:04 2011 -0700 +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/java_lang_Class.java Sat Sep 10 17:29:02 2011 -0700 @@ -55,13 +55,13 @@ // klass and oop_size are HotSpot magic fields and hence we can't // find them from InstanceKlass for java.lang.Class. Type jlc = db.lookupType("java_lang_Class"); - int klassOffset = (int) jlc.getCIntegerField("klass_offset").getValue(); + int klassOffset = (int) jlc.getCIntegerField("_klass_offset").getValue(); if (VM.getVM().isCompressedOopsEnabled()) { klassField = new NarrowOopField(new NamedFieldIdentifier("klass"), klassOffset, true); } else { klassField = new OopField(new NamedFieldIdentifier("klass"), klassOffset, true); } - int oopSizeOffset = (int) jlc.getCIntegerField("oop_size_offset").getValue(); + int oopSizeOffset = (int) jlc.getCIntegerField("_oop_size_offset").getValue(); oopSizeField = new IntField(new NamedFieldIdentifier("oop_size"), oopSizeOffset, true); } diff -r fec876499aae -r e79347eebbc5 hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/jcore/ClassWriter.java --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/jcore/ClassWriter.java Sat Sep 10 00:11:04 2011 -0700 +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/jcore/ClassWriter.java Sat Sep 10 17:29:02 2011 -0700 @@ -380,15 +380,15 @@ protected void writeFields() throws IOException { TypeArray fields = klass.getFields(); - final int length = (int) fields.getLength(); + final int length = klass.getJavaFieldsCount(); // write number of fields - dos.writeShort((short) (length / InstanceKlass.NEXT_OFFSET) ); + dos.writeShort((short) (length / InstanceKlass.FIELD_SLOTS) ); if (DEBUG) debugMessage("number of fields = " - + length/InstanceKlass.NEXT_OFFSET); + + length/InstanceKlass.FIELD_SLOTS); - for (int index = 0; index < length; index += InstanceKlass.NEXT_OFFSET) { + for (int index = 0; index < length; index += InstanceKlass.FIELD_SLOTS) { short accessFlags = fields.getShortAt(index + InstanceKlass.ACCESS_FLAGS_OFFSET); dos.writeShort(accessFlags & (short) JVM_RECOGNIZED_FIELD_MODIFIERS); diff -r fec876499aae -r e79347eebbc5 hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/soql/SOQL.java --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/soql/SOQL.java Sat Sep 10 00:11:04 2011 -0700 +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/soql/SOQL.java Sat Sep 10 17:29:02 2011 -0700 @@ -150,16 +150,13 @@ } // list immediate fields only - TypeArray fields = klass.getFields(); - int numFields = (int) fields.getLength(); + int numFields = klass.getJavaFieldsCount(); ConstantPool cp = klass.getConstants(); out.println("fields"); if (numFields != 0) { - for (int f = 0; f < numFields; f += InstanceKlass.NEXT_OFFSET) { - int nameIndex = fields.getShortAt(f + InstanceKlass.NAME_INDEX_OFFSET); - int sigIndex = fields.getShortAt(f + InstanceKlass.SIGNATURE_INDEX_OFFSET); - Symbol f_name = cp.getSymbolAt(nameIndex); - Symbol f_sig = cp.getSymbolAt(sigIndex); + for (int f = 0; f < numFields; f++){ + Symbol f_name = klass.getFieldName(f); + Symbol f_sig = klass.getFieldSignature(f); StringBuffer sigBuf = new StringBuffer(); new SignatureConverter(f_sig, sigBuf).dispatchField(); out.print('\t'); diff -r fec876499aae -r e79347eebbc5 hotspot/agent/src/share/classes/sun/jvm/hotspot/ui/classbrowser/HTMLGenerator.java --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/ui/classbrowser/HTMLGenerator.java Sat Sep 10 00:11:04 2011 -0700 +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/ui/classbrowser/HTMLGenerator.java Sat Sep 10 17:29:02 2011 -0700 @@ -1116,20 +1116,15 @@ InstanceKlass kls = (InstanceKlass) obj; buf.append(" " + kls.getName().asString() + "={"); int flen = ov.fieldsSize(); - - TypeArray klfields = kls.getFields(); - int klen = (int) klfields.getLength(); - - ConstantPool cp = kls.getConstants(); + int klen = kls.getJavaFieldsCount(); int findex = 0; - for (int index = 0; index < klen; index += kls.NEXT_OFFSET) { - int accsFlags = klfields.getShortAt(index + kls.ACCESS_FLAGS_OFFSET); - int nameIndex = klfields.getShortAt(index + kls.NAME_INDEX_OFFSET); + for (int index = 0; index < klen; index++) { + int accsFlags = kls.getFieldAccessFlags(index); + Symbol f_name = kls.getFieldName(index); AccessFlags access = new AccessFlags(accsFlags); if (!access.isStatic()) { ScopeValue svf = ov.getFieldAt(findex++); String fstr = scopeValueAsString(sd, svf); - Symbol f_name = cp.getSymbolAt(nameIndex); buf.append(" [" + f_name.asString() + " :"+ index + "]=(#" + fstr + ")"); } } @@ -1819,13 +1814,11 @@ protected String genHTMLListForFields(InstanceKlass klass) { Formatter buf = new Formatter(genHTML); - TypeArray fields = klass.getFields(); - int numFields = (int) fields.getLength(); - ConstantPool cp = klass.getConstants(); + int numFields = klass.getJavaFieldsCount(); if (numFields != 0) { buf.h3("Fields"); buf.beginList(); - for (int f = 0; f < numFields; f += InstanceKlass.NEXT_OFFSET) { + for (int f = 0; f < numFields; f++) { sun.jvm.hotspot.oops.Field field = klass.getFieldByIndex(f); String f_name = ((NamedFieldIdentifier)field.getID()).getName(); Symbol f_sig = field.getSignature(); diff -r fec876499aae -r e79347eebbc5 hotspot/agent/test/jdi/sasanity.sh --- a/hotspot/agent/test/jdi/sasanity.sh Sat Sep 10 00:11:04 2011 -0700 +++ b/hotspot/agent/test/jdi/sasanity.sh Sat Sep 10 17:29:02 2011 -0700 @@ -76,5 +76,5 @@ sleep 2 done -$jdk/bin/java -showversion ${OPTIONS} -classpath $javacp SASanityChecker $pid +$jdk/bin/java -showversion ${OPTIONS} -classpath $javacp $* SASanityChecker $pid kill -9 $pid diff -r fec876499aae -r e79347eebbc5 hotspot/src/cpu/sparc/vm/assembler_sparc.cpp --- a/hotspot/src/cpu/sparc/vm/assembler_sparc.cpp Sat Sep 10 00:11:04 2011 -0700 +++ b/hotspot/src/cpu/sparc/vm/assembler_sparc.cpp Sat Sep 10 17:29:02 2011 -0700 @@ -3257,15 +3257,10 @@ Register temp_reg) { assert_different_registers(vmslots_reg, mh_reg, temp_reg); // load mh.type.form.vmslots - if (java_lang_invoke_MethodHandle::vmslots_offset_in_bytes() != 0) { - // hoist vmslots into every mh to avoid dependent load chain - ld( Address(mh_reg, delayed_value(java_lang_invoke_MethodHandle::vmslots_offset_in_bytes, temp_reg)), vmslots_reg); - } else { - Register temp2_reg = vmslots_reg; - load_heap_oop(Address(mh_reg, delayed_value(java_lang_invoke_MethodHandle::type_offset_in_bytes, temp_reg)), temp2_reg); - load_heap_oop(Address(temp2_reg, delayed_value(java_lang_invoke_MethodType::form_offset_in_bytes, temp_reg)), temp2_reg); - ld( Address(temp2_reg, delayed_value(java_lang_invoke_MethodTypeForm::vmslots_offset_in_bytes, temp_reg)), vmslots_reg); - } + Register temp2_reg = vmslots_reg; + load_heap_oop(Address(mh_reg, delayed_value(java_lang_invoke_MethodHandle::type_offset_in_bytes, temp_reg)), temp2_reg); + load_heap_oop(Address(temp2_reg, delayed_value(java_lang_invoke_MethodType::form_offset_in_bytes, temp_reg)), temp2_reg); + ld( Address(temp2_reg, delayed_value(java_lang_invoke_MethodTypeForm::vmslots_offset_in_bytes, temp_reg)), vmslots_reg); } @@ -4966,4 +4961,3 @@ cmp_and_brx_short(to, end, Assembler::lessUnsigned, Assembler::pt, small_loop); nop(); // Separate short branches } - diff -r fec876499aae -r e79347eebbc5 hotspot/src/cpu/x86/vm/assembler_x86.cpp --- a/hotspot/src/cpu/x86/vm/assembler_x86.cpp Sat Sep 10 00:11:04 2011 -0700 +++ b/hotspot/src/cpu/x86/vm/assembler_x86.cpp Sat Sep 10 17:29:02 2011 -0700 @@ -8004,15 +8004,10 @@ Register temp_reg) { assert_different_registers(vmslots_reg, mh_reg, temp_reg); // load mh.type.form.vmslots - if (java_lang_invoke_MethodHandle::vmslots_offset_in_bytes() != 0) { - // hoist vmslots into every mh to avoid dependent load chain - movl(vmslots_reg, Address(mh_reg, delayed_value(java_lang_invoke_MethodHandle::vmslots_offset_in_bytes, temp_reg))); - } else { - Register temp2_reg = vmslots_reg; - load_heap_oop(temp2_reg, Address(mh_reg, delayed_value(java_lang_invoke_MethodHandle::type_offset_in_bytes, temp_reg))); - load_heap_oop(temp2_reg, Address(temp2_reg, delayed_value(java_lang_invoke_MethodType::form_offset_in_bytes, temp_reg))); - movl(vmslots_reg, Address(temp2_reg, delayed_value(java_lang_invoke_MethodTypeForm::vmslots_offset_in_bytes, temp_reg))); - } + Register temp2_reg = vmslots_reg; + load_heap_oop(temp2_reg, Address(mh_reg, delayed_value(java_lang_invoke_MethodHandle::type_offset_in_bytes, temp_reg))); + load_heap_oop(temp2_reg, Address(temp2_reg, delayed_value(java_lang_invoke_MethodType::form_offset_in_bytes, temp_reg))); + movl(vmslots_reg, Address(temp2_reg, delayed_value(java_lang_invoke_MethodTypeForm::vmslots_offset_in_bytes, temp_reg))); } diff -r fec876499aae -r e79347eebbc5 hotspot/src/share/vm/ci/ciInstanceKlass.cpp --- a/hotspot/src/share/vm/ci/ciInstanceKlass.cpp Sat Sep 10 00:11:04 2011 -0700 +++ b/hotspot/src/share/vm/ci/ciInstanceKlass.cpp Sat Sep 10 17:29:02 2011 -0700 @@ -31,6 +31,7 @@ #include "memory/allocation.hpp" #include "memory/allocation.inline.hpp" #include "oops/oop.inline.hpp" +#include "oops/fieldStreams.hpp" #include "runtime/fieldDescriptor.hpp" // ciInstanceKlass @@ -412,7 +413,7 @@ VM_ENTRY_MARK; ciEnv* curEnv = ciEnv::current(); instanceKlass* ik = get_instanceKlass(); - int max_n_fields = ik->fields()->length()/instanceKlass::next_offset; + int max_n_fields = ik->java_fields_count(); Arena* arena = curEnv->arena(); _non_static_fields = @@ -476,23 +477,6 @@ // Now sort them by offset, ascending. // (In principle, they could mix with superclass fields.) fields->sort(sort_field_by_offset); -#ifdef ASSERT - int last_offset = instanceOopDesc::base_offset_in_bytes(); - for (int i = 0; i < fields->length(); i++) { - ciField* field = fields->at(i); - int offset = field->offset_in_bytes(); - int size = (field->_type == NULL) ? heapOopSize : field->size_in_bytes(); - assert(last_offset <= offset, err_msg("no field overlap: %d <= %d", last_offset, offset)); - if (last_offset > (int)sizeof(oopDesc)) - assert((offset - last_offset) < BytesPerLong, "no big holes"); - // Note: Two consecutive T_BYTE fields will be separated by wordSize-1 - // padding bytes if one of them is declared by a superclass. - // This is a minor inefficiency classFileParser.cpp. - last_offset = offset + size; - } - assert(last_offset <= (int)instanceOopDesc::base_offset_in_bytes() + fsize, "no overflow"); -#endif - _nonstatic_fields = fields; return flen; } @@ -505,33 +489,29 @@ int flen = 0; GrowableArray* fields = NULL; instanceKlass* k = get_instanceKlass(); - typeArrayOop fields_array = k->fields(); - for (int pass = 0; pass <= 1; pass++) { - for (int i = 0, alen = fields_array->length(); i < alen; i += instanceKlass::next_offset) { - fieldDescriptor fd; - fd.initialize(k->as_klassOop(), i); - if (fd.is_static()) continue; - if (pass == 0) { - flen += 1; - } else { - ciField* field = new (arena) ciField(&fd); - fields->append(field); - } - } + for (JavaFieldStream fs(k); !fs.done(); fs.next()) { + if (fs.access_flags().is_static()) continue; + flen += 1; + } - // Between passes, allocate the array: - if (pass == 0) { - if (flen == 0) { - return NULL; // return nothing if none are locally declared - } - if (super_fields != NULL) { - flen += super_fields->length(); - } - fields = new (arena) GrowableArray(arena, flen, 0, NULL); - if (super_fields != NULL) { - fields->appendAll(super_fields); - } - } + // allocate the array: + if (flen == 0) { + return NULL; // return nothing if none are locally declared + } + if (super_fields != NULL) { + flen += super_fields->length(); + } + fields = new (arena) GrowableArray(arena, flen, 0, NULL); + if (super_fields != NULL) { + fields->appendAll(super_fields); + } + + for (JavaFieldStream fs(k); !fs.done(); fs.next()) { + if (fs.access_flags().is_static()) continue; + fieldDescriptor fd; + fd.initialize(k->as_klassOop(), fs.index()); + ciField* field = new (arena) ciField(&fd); + fields->append(field); } assert(fields->length() == flen, "sanity"); return fields; diff -r fec876499aae -r e79347eebbc5 hotspot/src/share/vm/classfile/classFileParser.cpp --- a/hotspot/src/share/vm/classfile/classFileParser.cpp Sat Sep 10 00:11:04 2011 -0700 +++ b/hotspot/src/share/vm/classfile/classFileParser.cpp Sat Sep 10 17:29:02 2011 -0700 @@ -36,6 +36,7 @@ #include "memory/oopFactory.hpp" #include "memory/universe.inline.hpp" #include "oops/constantPoolOop.hpp" +#include "oops/fieldStreams.hpp" #include "oops/instanceKlass.hpp" #include "oops/instanceMirrorKlass.hpp" #include "oops/klass.inline.hpp" @@ -991,42 +992,98 @@ STATIC_BYTE, // Boolean, Byte, char STATIC_SHORT, // shorts STATIC_WORD, // ints - STATIC_DOUBLE, // long or double - STATIC_ALIGNED_DOUBLE,// aligned long or double + STATIC_DOUBLE, // aligned long or double NONSTATIC_OOP, NONSTATIC_BYTE, NONSTATIC_SHORT, NONSTATIC_WORD, NONSTATIC_DOUBLE, - NONSTATIC_ALIGNED_DOUBLE + MAX_FIELD_ALLOCATION_TYPE, + BAD_ALLOCATION_TYPE = -1 }; - -struct FieldAllocationCount { - unsigned int static_oop_count; - unsigned int static_byte_count; - unsigned int static_short_count; - unsigned int static_word_count; - unsigned int static_double_count; - unsigned int nonstatic_oop_count; - unsigned int nonstatic_byte_count; - unsigned int nonstatic_short_count; - unsigned int nonstatic_word_count; - unsigned int nonstatic_double_count; +static FieldAllocationType _basic_type_to_atype[2 * (T_CONFLICT + 1)] = { + BAD_ALLOCATION_TYPE, // 0 + BAD_ALLOCATION_TYPE, // 1 + BAD_ALLOCATION_TYPE, // 2 + BAD_ALLOCATION_TYPE, // 3 + NONSTATIC_BYTE , // T_BOOLEAN = 4, + NONSTATIC_SHORT, // T_CHAR = 5, + NONSTATIC_WORD, // T_FLOAT = 6, + NONSTATIC_DOUBLE, // T_DOUBLE = 7, + NONSTATIC_BYTE, // T_BYTE = 8, + NONSTATIC_SHORT, // T_SHORT = 9, + NONSTATIC_WORD, // T_INT = 10, + NONSTATIC_DOUBLE, // T_LONG = 11, + NONSTATIC_OOP, // T_OBJECT = 12, + NONSTATIC_OOP, // T_ARRAY = 13, + BAD_ALLOCATION_TYPE, // T_VOID = 14, + BAD_ALLOCATION_TYPE, // T_ADDRESS = 15, + BAD_ALLOCATION_TYPE, // T_NARROWOOP= 16, + BAD_ALLOCATION_TYPE, // T_CONFLICT = 17, + BAD_ALLOCATION_TYPE, // 0 + BAD_ALLOCATION_TYPE, // 1 + BAD_ALLOCATION_TYPE, // 2 + BAD_ALLOCATION_TYPE, // 3 + STATIC_BYTE , // T_BOOLEAN = 4, + STATIC_SHORT, // T_CHAR = 5, + STATIC_WORD, // T_FLOAT = 6, + STATIC_DOUBLE, // T_DOUBLE = 7, + STATIC_BYTE, // T_BYTE = 8, + STATIC_SHORT, // T_SHORT = 9, + STATIC_WORD, // T_INT = 10, + STATIC_DOUBLE, // T_LONG = 11, + STATIC_OOP, // T_OBJECT = 12, + STATIC_OOP, // T_ARRAY = 13, + BAD_ALLOCATION_TYPE, // T_VOID = 14, + BAD_ALLOCATION_TYPE, // T_ADDRESS = 15, + BAD_ALLOCATION_TYPE, // T_NARROWOOP= 16, + BAD_ALLOCATION_TYPE, // T_CONFLICT = 17, }; -typeArrayHandle ClassFileParser::parse_fields(constantPoolHandle cp, bool is_interface, - struct FieldAllocationCount *fac, - objArrayHandle* fields_annotations, TRAPS) { +static FieldAllocationType basic_type_to_atype(bool is_static, BasicType type) { + assert(type >= T_BOOLEAN && type < T_VOID, "only allowable values"); + FieldAllocationType result = _basic_type_to_atype[type + (is_static ? (T_CONFLICT + 1) : 0)]; + assert(result != BAD_ALLOCATION_TYPE, "bad type"); + return result; +} + +class FieldAllocationCount: public ResourceObj { + public: + unsigned int count[MAX_FIELD_ALLOCATION_TYPE]; + + FieldAllocationCount() { + for (int i = 0; i < MAX_FIELD_ALLOCATION_TYPE; i++) { + count[i] = 0; + } + } + + FieldAllocationType update(bool is_static, BasicType type) { + FieldAllocationType atype = basic_type_to_atype(is_static, type); + count[atype]++; + return atype; + } +}; + + +typeArrayHandle ClassFileParser::parse_fields(Symbol* class_name, + constantPoolHandle cp, bool is_interface, + FieldAllocationCount *fac, + objArrayHandle* fields_annotations, + int* java_fields_count_ptr, TRAPS) { ClassFileStream* cfs = stream(); typeArrayHandle nullHandle; cfs->guarantee_more(2, CHECK_(nullHandle)); // length u2 length = cfs->get_u2_fast(); + *java_fields_count_ptr = length; + + int num_injected = 0; + InjectedField* injected = JavaClasses::get_injected(class_name, &num_injected); + // Tuples of shorts [access, name index, sig index, initial value index, byte offset, generic signature index] - typeArrayOop new_fields = oopFactory::new_permanent_shortArray(length*instanceKlass::next_offset, CHECK_(nullHandle)); + typeArrayOop new_fields = oopFactory::new_permanent_shortArray((length + num_injected) * FieldInfo::field_slots, CHECK_(nullHandle)); typeArrayHandle fields(THREAD, new_fields); - int index = 0; typeArrayHandle field_annotations; for (int n = 0; n < length; n++) { cfs->guarantee_more(8, CHECK_(nullHandle)); // access_flags, name_index, descriptor_index, attributes_count @@ -1077,93 +1134,77 @@ } } - fields->short_at_put(index++, access_flags.as_short()); - fields->short_at_put(index++, name_index); - fields->short_at_put(index++, signature_index); - fields->short_at_put(index++, constantvalue_index); + FieldInfo* field = FieldInfo::from_field_array(fields(), n); + field->initialize(access_flags.as_short(), + name_index, + signature_index, + constantvalue_index, + generic_signature_index, + 0); + + BasicType type = cp->basic_type_for_signature_at(signature_index); // Remember how many oops we encountered and compute allocation type - BasicType type = cp->basic_type_for_signature_at(signature_index); - FieldAllocationType atype; - if ( is_static ) { - switch ( type ) { - case T_BOOLEAN: - case T_BYTE: - fac->static_byte_count++; - atype = STATIC_BYTE; - break; - case T_LONG: - case T_DOUBLE: - if (Universe::field_type_should_be_aligned(type)) { - atype = STATIC_ALIGNED_DOUBLE; - } else { - atype = STATIC_DOUBLE; - } - fac->static_double_count++; - break; - case T_CHAR: - case T_SHORT: - fac->static_short_count++; - atype = STATIC_SHORT; - break; - case T_FLOAT: - case T_INT: - fac->static_word_count++; - atype = STATIC_WORD; - break; - case T_ARRAY: - case T_OBJECT: - fac->static_oop_count++; - atype = STATIC_OOP; - break; - case T_ADDRESS: - case T_VOID: - default: - assert(0, "bad field type"); - } - } else { - switch ( type ) { - case T_BOOLEAN: - case T_BYTE: - fac->nonstatic_byte_count++; - atype = NONSTATIC_BYTE; - break; - case T_LONG: - case T_DOUBLE: - if (Universe::field_type_should_be_aligned(type)) { - atype = NONSTATIC_ALIGNED_DOUBLE; - } else { - atype = NONSTATIC_DOUBLE; - } - fac->nonstatic_double_count++; - break; - case T_CHAR: - case T_SHORT: - fac->nonstatic_short_count++; - atype = NONSTATIC_SHORT; - break; - case T_FLOAT: - case T_INT: - fac->nonstatic_word_count++; - atype = NONSTATIC_WORD; - break; - case T_ARRAY: - case T_OBJECT: - fac->nonstatic_oop_count++; - atype = NONSTATIC_OOP; - break; - case T_ADDRESS: - case T_VOID: - default: - assert(0, "bad field type"); - } - } + FieldAllocationType atype = fac->update(is_static, type); // The correct offset is computed later (all oop fields will be located together) // We temporarily store the allocation type in the offset field - fields->short_at_put(index++, atype); - fields->short_at_put(index++, 0); // Clear out high word of byte offset - fields->short_at_put(index++, generic_signature_index); + field->set_offset(atype); + } + + if (num_injected != 0) { + int index = length; + for (int n = 0; n < num_injected; n++) { + // Check for duplicates + if (injected[n].may_be_java) { + Symbol* name = injected[n].name(); + Symbol* signature = injected[n].signature(); + bool duplicate = false; + for (int i = 0; i < length; i++) { + FieldInfo* f = FieldInfo::from_field_array(fields(), i); + if (name == cp->symbol_at(f->name_index()) && + signature == cp->symbol_at(f->signature_index())) { + // Symbol is desclared in Java so skip this one + duplicate = true; + break; + } + } + if (duplicate) { + // These will be removed from the field array at the end + continue; + } + } + + // Injected field + FieldInfo* field = FieldInfo::from_field_array(fields(), index); + field->initialize(JVM_ACC_FIELD_INTERNAL, + injected[n].name_index, + injected[n].signature_index, + 0, + 0, + 0); + + BasicType type = FieldType::basic_type(injected[n].signature()); + + // Remember how many oops we encountered and compute allocation type + FieldAllocationType atype = fac->update(false, type); + + // The correct offset is computed later (all oop fields will be located together) + // We temporarily store the allocation type in the offset field + field->set_offset(atype); + index++; + } + + if (index < length + num_injected) { + // sometimes injected fields already exist in the Java source so + // the fields array could be too long. In that case trim the + // fields array. + new_fields = oopFactory::new_permanent_shortArray(index * FieldInfo::field_slots, CHECK_(nullHandle)); + for (int i = 0; i < index * FieldInfo::field_slots; i++) { + new_fields->short_at_put(i, fields->short_at(i)); + } + fields = new_fields; + } } if (_need_verify && length > 1) { @@ -1175,11 +1216,9 @@ bool dup = false; { debug_only(No_Safepoint_Verifier nsv;) - for (int i = 0; i < length*instanceKlass::next_offset; i += instanceKlass::next_offset) { - int name_index = fields->ushort_at(i + instanceKlass::name_index_offset); - Symbol* name = cp->symbol_at(name_index); - int sig_index = fields->ushort_at(i + instanceKlass::signature_index_offset); - Symbol* sig = cp->symbol_at(sig_index); + for (AllFieldStream fs(fields, cp); !fs.done(); fs.next()) { + Symbol* name = fs.name(); + Symbol* sig = fs.signature(); // If no duplicates, add name/signature in hashtable names_and_sigs. if (!put_after_lookup(name, sig, names_and_sigs)) { dup = true; @@ -2592,227 +2631,6 @@ } -void ClassFileParser::java_lang_ref_Reference_fix_pre(typeArrayHandle* fields_ptr, - constantPoolHandle cp, FieldAllocationCount *fac_ptr, TRAPS) { - // This code is for compatibility with earlier jdk's that do not - // have the "discovered" field in java.lang.ref.Reference. For 1.5 - // the check for the "discovered" field should issue a warning if - // the field is not found. For 1.6 this code should be issue a - // fatal error if the "discovered" field is not found. - // - // Increment fac.nonstatic_oop_count so that the start of the - // next type of non-static oops leaves room for the fake oop. - // Do not increment next_nonstatic_oop_offset so that the - // fake oop is place after the java.lang.ref.Reference oop - // fields. - // - // Check the fields in java.lang.ref.Reference for the "discovered" - // field. If it is not present, artifically create a field for it. - // This allows this VM to run on early JDK where the field is not - // present. - int reference_sig_index = 0; - int reference_name_index = 0; - int reference_index = 0; - int extra = java_lang_ref_Reference::number_of_fake_oop_fields; - const int n = (*fields_ptr)()->length(); - for (int i = 0; i < n; i += instanceKlass::next_offset ) { - int name_index = - (*fields_ptr)()->ushort_at(i + instanceKlass::name_index_offset); - int sig_index = - (*fields_ptr)()->ushort_at(i + instanceKlass::signature_index_offset); - Symbol* f_name = cp->symbol_at(name_index); - Symbol* f_sig = cp->symbol_at(sig_index); - if (f_sig == vmSymbols::reference_signature() && reference_index == 0) { - // Save the index for reference signature for later use. - // The fake discovered field does not entries in the - // constant pool so the index for its signature cannot - // be extracted from the constant pool. It will need - // later, however. It's signature is vmSymbols::reference_signature() - // so same an index for that signature. - reference_sig_index = sig_index; - reference_name_index = name_index; - reference_index = i; - } - if (f_name == vmSymbols::reference_discovered_name() && - f_sig == vmSymbols::reference_signature()) { - // The values below are fake but will force extra - // non-static oop fields and a corresponding non-static - // oop map block to be allocated. - extra = 0; - break; - } - } - if (extra != 0) { - fac_ptr->nonstatic_oop_count += extra; - // Add the additional entry to "fields" so that the klass - // contains the "discoverd" field and the field will be initialized - // in instances of the object. - int fields_with_fix_length = (*fields_ptr)()->length() + - instanceKlass::next_offset; - typeArrayOop ff = oopFactory::new_permanent_shortArray( - fields_with_fix_length, CHECK); - typeArrayHandle fields_with_fix(THREAD, ff); - - // Take everything from the original but the length. - for (int idx = 0; idx < (*fields_ptr)->length(); idx++) { - fields_with_fix->ushort_at_put(idx, (*fields_ptr)->ushort_at(idx)); - } - - // Add the fake field at the end. - int i = (*fields_ptr)->length(); - // There is no name index for the fake "discovered" field nor - // signature but a signature is needed so that the field will - // be properly initialized. Use one found for - // one of the other reference fields. Be sure the index for the - // name is 0. In fieldDescriptor::initialize() the index of the - // name is checked. That check is by passed for the last nonstatic - // oop field in a java.lang.ref.Reference which is assumed to be - // this artificial "discovered" field. An assertion checks that - // the name index is 0. - assert(reference_index != 0, "Missing signature for reference"); - - int j; - for (j = 0; j < instanceKlass::next_offset; j++) { - fields_with_fix->ushort_at_put(i + j, - (*fields_ptr)->ushort_at(reference_index +j)); - } - // Clear the public access flag and set the private access flag. - short flags; - flags = - fields_with_fix->ushort_at(i + instanceKlass::access_flags_offset); - assert(!(flags & JVM_RECOGNIZED_FIELD_MODIFIERS), "Unexpected access flags set"); - flags = flags & (~JVM_ACC_PUBLIC); - flags = flags | JVM_ACC_PRIVATE; - AccessFlags access_flags; - access_flags.set_flags(flags); - assert(!access_flags.is_public(), "Failed to clear public flag"); - assert(access_flags.is_private(), "Failed to set private flag"); - fields_with_fix->ushort_at_put(i + instanceKlass::access_flags_offset, - flags); - - assert(fields_with_fix->ushort_at(i + instanceKlass::name_index_offset) - == reference_name_index, "The fake reference name is incorrect"); - assert(fields_with_fix->ushort_at(i + instanceKlass::signature_index_offset) - == reference_sig_index, "The fake reference signature is incorrect"); - // The type of the field is stored in the low_offset entry during - // parsing. - assert(fields_with_fix->ushort_at(i + instanceKlass::low_offset) == - NONSTATIC_OOP, "The fake reference type is incorrect"); - - // "fields" is allocated in the permanent generation. Disgard - // it and let it be collected. - (*fields_ptr) = fields_with_fix; - } - return; -} - - -void ClassFileParser::java_lang_Class_fix_pre(int* nonstatic_field_size, - FieldAllocationCount *fac_ptr) { - // Add fake fields for java.lang.Class instances - // - // This is not particularly nice. We should consider adding a - // private transient object field at the Java level to - // java.lang.Class. Alternatively we could add a subclass of - // instanceKlass which provides an accessor and size computer for - // this field, but that appears to be more code than this hack. - // - // NOTE that we wedge these in at the beginning rather than the - // end of the object because the Class layout changed between JDK - // 1.3 and JDK 1.4 with the new reflection implementation; some - // nonstatic oop fields were added at the Java level. The offsets - // of these fake fields can't change between these two JDK - // versions because when the offsets are computed at bootstrap - // time we don't know yet which version of the JDK we're running in. - - // The values below are fake but will force three non-static oop fields and - // a corresponding non-static oop map block to be allocated. - const int extra = java_lang_Class::number_of_fake_oop_fields; - fac_ptr->nonstatic_oop_count += extra; - - // Reserve some leading space for fake ints - *nonstatic_field_size += align_size_up(java_lang_Class::hc_number_of_fake_int_fields * BytesPerInt, heapOopSize) / heapOopSize; -} - - -void ClassFileParser::java_lang_Class_fix_post(int* next_nonstatic_oop_offset_ptr) { - // Cause the extra fake fields in java.lang.Class to show up before - // the Java fields for layout compatibility between 1.3 and 1.4 - // Incrementing next_nonstatic_oop_offset here advances the - // location where the real java fields are placed. - const int extra = java_lang_Class::number_of_fake_oop_fields; - (*next_nonstatic_oop_offset_ptr) += (extra * heapOopSize); -} - - -// Force MethodHandle.vmentry to be an unmanaged pointer. -// There is no way for a classfile to express this, so we must help it. -void ClassFileParser::java_lang_invoke_MethodHandle_fix_pre(constantPoolHandle cp, - typeArrayHandle fields, - FieldAllocationCount *fac_ptr, - TRAPS) { - // Add fake fields for java.lang.invoke.MethodHandle instances - // - // This is not particularly nice, but since there is no way to express - // a native wordSize field in Java, we must do it at this level. - - if (!EnableInvokeDynamic) return; - - int word_sig_index = 0; - const int cp_size = cp->length(); - for (int index = 1; index < cp_size; index++) { - if (cp->tag_at(index).is_utf8() && - cp->symbol_at(index) == vmSymbols::machine_word_signature()) { - word_sig_index = index; - break; - } - } - - if (word_sig_index == 0) - THROW_MSG(vmSymbols::java_lang_VirtualMachineError(), - "missing I or J signature (for vmentry) in java.lang.invoke.MethodHandle"); - - // Find vmentry field and change the signature. - bool found_vmentry = false; - for (int i = 0; i < fields->length(); i += instanceKlass::next_offset) { - int name_index = fields->ushort_at(i + instanceKlass::name_index_offset); - int sig_index = fields->ushort_at(i + instanceKlass::signature_index_offset); - int acc_flags = fields->ushort_at(i + instanceKlass::access_flags_offset); - Symbol* f_name = cp->symbol_at(name_index); - Symbol* f_sig = cp->symbol_at(sig_index); - if (f_name == vmSymbols::vmentry_name() && (acc_flags & JVM_ACC_STATIC) == 0) { - if (f_sig == vmSymbols::machine_word_signature()) { - // If the signature of vmentry is already changed, we're done. - found_vmentry = true; - break; - } - else if (f_sig == vmSymbols::byte_signature()) { - // Adjust the field type from byte to an unmanaged pointer. - assert(fac_ptr->nonstatic_byte_count > 0, ""); - fac_ptr->nonstatic_byte_count -= 1; - - fields->ushort_at_put(i + instanceKlass::signature_index_offset, word_sig_index); - assert(wordSize == longSize || wordSize == jintSize, "ILP32 or LP64"); - if (wordSize == longSize) fac_ptr->nonstatic_double_count += 1; - else fac_ptr->nonstatic_word_count += 1; - - FieldAllocationType atype = (FieldAllocationType) fields->ushort_at(i + instanceKlass::low_offset); - assert(atype == NONSTATIC_BYTE, ""); - FieldAllocationType new_atype = (wordSize == longSize) ? NONSTATIC_DOUBLE : NONSTATIC_WORD; - fields->ushort_at_put(i + instanceKlass::low_offset, new_atype); - - found_vmentry = true; - break; - } - } - } - - if (!found_vmentry) - THROW_MSG(vmSymbols::java_lang_VirtualMachineError(), - "missing vmentry byte field in java.lang.invoke.MethodHandle"); -} - - instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name, Handle class_loader, Handle protection_domain, @@ -3025,10 +2843,13 @@ local_interfaces = parse_interfaces(cp, itfs_len, class_loader, protection_domain, _class_name, CHECK_(nullHandle)); } + int java_fields_count = 0; // Fields (offsets are filled in later) - struct FieldAllocationCount fac = {0,0,0,0,0,0,0,0,0,0}; + FieldAllocationCount fac; objArrayHandle fields_annotations; - typeArrayHandle fields = parse_fields(cp, access_flags.is_interface(), &fac, &fields_annotations, CHECK_(nullHandle)); + typeArrayHandle fields = parse_fields(class_name, cp, access_flags.is_interface(), &fac, &fields_annotations, + &java_fields_count, + CHECK_(nullHandle)); // Methods bool has_final_method = false; AccessFlags promoted_flags; @@ -3146,51 +2967,33 @@ // Calculate the starting byte offsets next_static_oop_offset = instanceMirrorKlass::offset_of_static_fields(); next_static_double_offset = next_static_oop_offset + - (fac.static_oop_count * heapOopSize); - if ( fac.static_double_count && + (fac.count[STATIC_OOP] * heapOopSize); + if ( fac.count[STATIC_DOUBLE] && (Universe::field_type_should_be_aligned(T_DOUBLE) || Universe::field_type_should_be_aligned(T_LONG)) ) { next_static_double_offset = align_size_up(next_static_double_offset, BytesPerLong); } next_static_word_offset = next_static_double_offset + - (fac.static_double_count * BytesPerLong); + (fac.count[STATIC_DOUBLE] * BytesPerLong); next_static_short_offset = next_static_word_offset + - (fac.static_word_count * BytesPerInt); + (fac.count[STATIC_WORD] * BytesPerInt); next_static_byte_offset = next_static_short_offset + - (fac.static_short_count * BytesPerShort); + (fac.count[STATIC_SHORT] * BytesPerShort); next_static_type_offset = align_size_up((next_static_byte_offset + - fac.static_byte_count ), wordSize ); + fac.count[STATIC_BYTE] ), wordSize ); static_field_size = (next_static_type_offset - next_static_oop_offset) / wordSize; - // Add fake fields for java.lang.Class instances (also see below) - if (class_name == vmSymbols::java_lang_Class() && class_loader.is_null()) { - java_lang_Class_fix_pre(&nonstatic_field_size, &fac); - } - first_nonstatic_field_offset = instanceOopDesc::base_offset_in_bytes() + nonstatic_field_size * heapOopSize; next_nonstatic_field_offset = first_nonstatic_field_offset; - // adjust the vmentry field declaration in java.lang.invoke.MethodHandle - if (EnableInvokeDynamic && class_name == vmSymbols::java_lang_invoke_MethodHandle() && class_loader.is_null()) { - java_lang_invoke_MethodHandle_fix_pre(cp, fields, &fac, CHECK_(nullHandle)); - } - - // Add a fake "discovered" field if it is not present - // for compatibility with earlier jdk's. - if (class_name == vmSymbols::java_lang_ref_Reference() - && class_loader.is_null()) { - java_lang_ref_Reference_fix_pre(&fields, cp, &fac, CHECK_(nullHandle)); - } - // end of "discovered" field compactibility fix - - unsigned int nonstatic_double_count = fac.nonstatic_double_count; - unsigned int nonstatic_word_count = fac.nonstatic_word_count; - unsigned int nonstatic_short_count = fac.nonstatic_short_count; - unsigned int nonstatic_byte_count = fac.nonstatic_byte_count; - unsigned int nonstatic_oop_count = fac.nonstatic_oop_count; + unsigned int nonstatic_double_count = fac.count[NONSTATIC_DOUBLE]; + unsigned int nonstatic_word_count = fac.count[NONSTATIC_WORD]; + unsigned int nonstatic_short_count = fac.count[NONSTATIC_SHORT]; + unsigned int nonstatic_byte_count = fac.count[NONSTATIC_BYTE]; + unsigned int nonstatic_oop_count = fac.count[NONSTATIC_OOP]; bool super_has_nonstatic_fields = (super_klass() != NULL && super_klass->has_nonstatic_fields()); @@ -3210,20 +3013,7 @@ nonstatic_oop_counts = NEW_RESOURCE_ARRAY_IN_THREAD( THREAD, unsigned int, nonstatic_oop_count + 1); - // Add fake fields for java.lang.Class instances (also see above). - // FieldsAllocationStyle and CompactFields values will be reset to default. - if(class_name == vmSymbols::java_lang_Class() && class_loader.is_null()) { - java_lang_Class_fix_post(&next_nonstatic_field_offset); - nonstatic_oop_offsets[0] = first_nonstatic_field_offset; - const uint fake_oop_count = (next_nonstatic_field_offset - - first_nonstatic_field_offset) / heapOopSize; - nonstatic_oop_counts[0] = fake_oop_count; - nonstatic_oop_map_count = 1; - nonstatic_oop_count -= fake_oop_count; - first_nonstatic_oop_offset = first_nonstatic_field_offset; - } else { - first_nonstatic_oop_offset = 0; // will be set for first oop field - } + first_nonstatic_oop_offset = 0; // will be set for first oop field #ifndef PRODUCT if( PrintCompactFieldsSavings ) { @@ -3378,10 +3168,9 @@ // Iterate over fields again and compute correct offsets. // The field allocation type was temporarily stored in the offset slot. // oop fields are located before non-oop fields (static and non-static). - int len = fields->length(); - for (int i = 0; i < len; i += instanceKlass::next_offset) { + for (AllFieldStream fs(fields, cp); !fs.done(); fs.next()) { int real_offset; - FieldAllocationType atype = (FieldAllocationType) fields->ushort_at(i + instanceKlass::low_offset); + FieldAllocationType atype = (FieldAllocationType) fs.offset(); switch (atype) { case STATIC_OOP: real_offset = next_static_oop_offset; @@ -3399,7 +3188,6 @@ real_offset = next_static_word_offset; next_static_word_offset += BytesPerInt; break; - case STATIC_ALIGNED_DOUBLE: case STATIC_DOUBLE: real_offset = next_static_double_offset; next_static_double_offset += BytesPerLong; @@ -3461,7 +3249,6 @@ next_nonstatic_word_offset += BytesPerInt; } break; - case NONSTATIC_ALIGNED_DOUBLE: case NONSTATIC_DOUBLE: real_offset = next_nonstatic_double_offset; next_nonstatic_double_offset += BytesPerLong; @@ -3469,8 +3256,7 @@ default: ShouldNotReachHere(); } - fields->short_at_put(i + instanceKlass::low_offset, extract_low_short_from_int(real_offset)); - fields->short_at_put(i + instanceKlass::high_offset, extract_high_short_from_int(real_offset)); + fs.set_offset(real_offset); } // Size of instances @@ -3517,12 +3303,12 @@ this_klass->set_class_loader(class_loader()); this_klass->set_nonstatic_field_size(nonstatic_field_size); this_klass->set_has_nonstatic_fields(has_nonstatic_fields); - this_klass->set_static_oop_field_count(fac.static_oop_count); + this_klass->set_static_oop_field_count(fac.count[STATIC_OOP]); cp->set_pool_holder(this_klass()); error_handler.set_in_error(false); // turn off error handler for cp this_klass->set_constants(cp()); this_klass->set_local_interfaces(local_interfaces()); - this_klass->set_fields(fields()); + this_klass->set_fields(fields(), java_fields_count); this_klass->set_methods(methods()); if (has_final_method) { this_klass->set_has_final_method(); diff -r fec876499aae -r e79347eebbc5 hotspot/src/share/vm/classfile/classFileParser.hpp --- a/hotspot/src/share/vm/classfile/classFileParser.hpp Sat Sep 10 00:11:04 2011 -0700 +++ b/hotspot/src/share/vm/classfile/classFileParser.hpp Sat Sep 10 17:29:02 2011 -0700 @@ -33,6 +33,9 @@ #include "utilities/accessFlags.hpp" class TempNewSymbol; +class FieldAllocationCount; + + // Parser for for .class files // // The bytes describing the class file structure is read from a Stream object @@ -84,9 +87,11 @@ bool* is_synthetic_addr, u2* generic_signature_index_addr, typeArrayHandle* field_annotations, TRAPS); - typeArrayHandle parse_fields(constantPoolHandle cp, bool is_interface, - struct FieldAllocationCount *fac, - objArrayHandle* fields_annotations, TRAPS); + typeArrayHandle parse_fields(Symbol* class_name, + constantPoolHandle cp, bool is_interface, + FieldAllocationCount *fac, + objArrayHandle* fields_annotations, + int* java_fields_count_ptr, TRAPS); // Method parsing methodHandle parse_method(constantPoolHandle cp, bool is_interface, @@ -150,25 +155,6 @@ objArrayHandle compute_transitive_interfaces(instanceKlassHandle super, objArrayHandle local_ifs, TRAPS); - // Special handling for certain classes. - // Add the "discovered" field to java.lang.ref.Reference if - // it does not exist. - void java_lang_ref_Reference_fix_pre(typeArrayHandle* fields_ptr, - constantPoolHandle cp, - FieldAllocationCount *fac_ptr, TRAPS); - // Adjust the field allocation counts for java.lang.Class to add - // fake fields. - void java_lang_Class_fix_pre(int* nonstatic_field_size, - FieldAllocationCount *fac_ptr); - // Adjust the next_nonstatic_oop_offset to place the fake fields - // before any Java fields. - void java_lang_Class_fix_post(int* next_nonstatic_oop_offset); - // Adjust the field allocation counts for java.lang.invoke.MethodHandle to add - // a fake address (void*) field. - void java_lang_invoke_MethodHandle_fix_pre(constantPoolHandle cp, - typeArrayHandle fields, - FieldAllocationCount *fac_ptr, TRAPS); - // Format checker methods void classfile_parse_error(const char* msg, TRAPS); void classfile_parse_error(const char* msg, int index, TRAPS); diff -r fec876499aae -r e79347eebbc5 hotspot/src/share/vm/classfile/javaClasses.cpp --- a/hotspot/src/share/vm/classfile/javaClasses.cpp Sat Sep 10 00:11:04 2011 -0700 +++ b/hotspot/src/share/vm/classfile/javaClasses.cpp Sat Sep 10 17:29:02 2011 -0700 @@ -33,6 +33,7 @@ #include "memory/oopFactory.hpp" #include "memory/resourceArea.hpp" #include "memory/universe.inline.hpp" +#include "oops/fieldStreams.hpp" #include "oops/instanceKlass.hpp" #include "oops/instanceMirrorKlass.hpp" #include "oops/klass.hpp" @@ -58,6 +59,49 @@ # include "thread_windows.inline.hpp" #endif +#define INJECTED_FIELD_COMPUTE_OFFSET(klass, name, signature, may_be_java) \ + klass::_##name##_offset = JavaClasses::compute_injected_offset(JavaClasses::klass##_##name##_enum); + +#define DECLARE_INJECTED_FIELD(klass, name, signature, may_be_java) \ + { SystemDictionary::WK_KLASS_ENUM_NAME(klass), vmSymbols::VM_SYMBOL_ENUM_NAME(name##_name), vmSymbols::VM_SYMBOL_ENUM_NAME(signature), may_be_java }, + +InjectedField JavaClasses::_injected_fields[] = { + ALL_INJECTED_FIELDS(DECLARE_INJECTED_FIELD) +}; + +int JavaClasses::compute_injected_offset(InjectedFieldID id) { + return _injected_fields[id].compute_offset(); +} + + +InjectedField* JavaClasses::get_injected(Symbol* class_name, int* field_count) { + *field_count = 0; + + vmSymbols::SID sid = vmSymbols::find_sid(class_name); + if (sid == vmSymbols::NO_SID) { + // Only well known classes can inject fields + return NULL; + } + + int count = 0; + int start = -1; + +#define LOOKUP_INJECTED_FIELD(klass, name, signature, may_be_java) \ + if (sid == vmSymbols::VM_SYMBOL_ENUM_NAME(klass)) { \ + count++; \ + if (start == -1) start = klass##_##name##_enum; \ + } + ALL_INJECTED_FIELDS(LOOKUP_INJECTED_FIELD); +#undef LOOKUP_INJECTED_FIELD + + if (start != -1) { + *field_count = count; + return _injected_fields + start; + } + return NULL; +} + + static bool find_field(instanceKlass* ik, Symbol* name_symbol, Symbol* signature_symbol, fieldDescriptor* fd, @@ -428,24 +472,19 @@ } -// During bootstrap, java.lang.Class wasn't loaded so static field -// offsets were computed without the size added it. Go back and -// update all the static field offsets to included the size. -static void fixup_static_field(fieldDescriptor* fd, TRAPS) { - if (fd->is_static()) { - int real_offset = fd->offset() + instanceMirrorKlass::offset_of_static_fields(); - typeArrayOop fields = instanceKlass::cast(fd->field_holder())->fields(); - fields->short_at_put(fd->index() + instanceKlass::low_offset, extract_low_short_from_int(real_offset)); - fields->short_at_put(fd->index() + instanceKlass::high_offset, extract_high_short_from_int(real_offset)); - } -} - void java_lang_Class::fixup_mirror(KlassHandle k, TRAPS) { assert(instanceMirrorKlass::offset_of_static_fields() != 0, "must have been computed already"); if (k->oop_is_instance()) { - // Fixup the offsets - instanceKlass::cast(k())->do_local_static_fields(&fixup_static_field, CHECK); + // During bootstrap, java.lang.Class wasn't loaded so static field + // offsets were computed without the size added it. Go back and + // update all the static field offsets to included the size. + for (JavaFieldStream fs(instanceKlass::cast(k())); !fs.done(); fs.next()) { + if (fs.access_flags().is_static()) { + int real_offset = fs.offset() + instanceMirrorKlass::offset_of_static_fields(); + fs.set_offset(real_offset); + } + } } create_mirror(k, CHECK); } @@ -462,7 +501,7 @@ // Allocate mirror (java.lang.Class instance) Handle mirror = instanceMirrorKlass::cast(SystemDictionary::Class_klass())->allocate_instance(k, CHECK_0); // Setup indirections - mirror->obj_field_put(klass_offset, k()); + mirror->obj_field_put(_klass_offset, k()); k->set_java_mirror(mirror()); instanceMirrorKlass* mk = instanceMirrorKlass::cast(mirror->klass()); @@ -504,25 +543,22 @@ int java_lang_Class::oop_size(oop java_class) { - assert(oop_size_offset != 0, "must be set"); - return java_class->int_field(oop_size_offset); + assert(_oop_size_offset != 0, "must be set"); + return java_class->int_field(_oop_size_offset); } void java_lang_Class::set_oop_size(oop java_class, int size) { - assert(oop_size_offset != 0, "must be set"); - java_class->int_field_put(oop_size_offset, size); + assert(_oop_size_offset != 0, "must be set"); + java_class->int_field_put(_oop_size_offset, size); } int java_lang_Class::static_oop_field_count(oop java_class) { - assert(static_oop_field_count_offset != 0, "must be set"); - return java_class->int_field(static_oop_field_count_offset); + assert(_static_oop_field_count_offset != 0, "must be set"); + return java_class->int_field(_static_oop_field_count_offset); } void java_lang_Class::set_static_oop_field_count(oop java_class, int size) { - assert(static_oop_field_count_offset != 0, "must be set"); - java_class->int_field_put(static_oop_field_count_offset, size); + assert(_static_oop_field_count_offset != 0, "must be set"); + java_class->int_field_put(_static_oop_field_count_offset, size); } - - - oop java_lang_Class::create_basic_type_mirror(const char* basic_type_name, BasicType type, TRAPS) { // This should be improved by adding a field at the Java level or by // introducing a new VM klass (see comment in ClassFileParser) @@ -542,7 +578,7 @@ klassOop java_lang_Class::as_klassOop(oop java_class) { //%note memory_2 assert(java_lang_Class::is_instance(java_class), "must be a Class object"); - klassOop k = klassOop(java_class->obj_field(klass_offset)); + klassOop k = klassOop(java_class->obj_field(_klass_offset)); assert(k == NULL || k->is_klass(), "type check"); return k; } @@ -598,7 +634,7 @@ klassOop java_lang_Class::array_klass(oop java_class) { - klassOop k = klassOop(java_class->obj_field(array_klass_offset)); + klassOop k = klassOop(java_class->obj_field(_array_klass_offset)); assert(k == NULL || k->is_klass() && Klass::cast(k)->oop_is_javaArray(), "should be array klass"); return k; } @@ -606,12 +642,12 @@ void java_lang_Class::set_array_klass(oop java_class, klassOop klass) { assert(klass->is_klass() && Klass::cast(klass)->oop_is_javaArray(), "should be array klass"); - java_class->obj_field_put(array_klass_offset, klass); + java_class->obj_field_put(_array_klass_offset, klass); } methodOop java_lang_Class::resolved_constructor(oop java_class) { - oop constructor = java_class->obj_field(resolved_constructor_offset); + oop constructor = java_class->obj_field(_resolved_constructor_offset); assert(constructor == NULL || constructor->is_method(), "should be method"); return methodOop(constructor); } @@ -619,21 +655,21 @@ void java_lang_Class::set_resolved_constructor(oop java_class, methodOop constructor) { assert(constructor->is_method(), "should be method"); - java_class->obj_field_put(resolved_constructor_offset, constructor); + java_class->obj_field_put(_resolved_constructor_offset, constructor); } bool java_lang_Class::is_primitive(oop java_class) { // should assert: //assert(java_lang_Class::is_instance(java_class), "must be a Class object"); - klassOop k = klassOop(java_class->obj_field(klass_offset)); + klassOop k = klassOop(java_class->obj_field(_klass_offset)); return k == NULL; } BasicType java_lang_Class::primitive_type(oop java_class) { assert(java_lang_Class::is_primitive(java_class), "just checking"); - klassOop ak = klassOop(java_class->obj_field(array_klass_offset)); + klassOop ak = klassOop(java_class->obj_field(_array_klass_offset)); BasicType type = T_VOID; if (ak != NULL) { // Note: create_basic_type_mirror above initializes ak to a non-null value. @@ -668,34 +704,18 @@ bool java_lang_Class::offsets_computed = false; int java_lang_Class::classRedefinedCount_offset = -1; -int java_lang_Class::parallelCapable_offset = -1; void java_lang_Class::compute_offsets() { assert(!offsets_computed, "offsets should be initialized only once"); offsets_computed = true; - klassOop k = SystemDictionary::Class_klass(); + klassOop klass_oop = SystemDictionary::Class_klass(); // The classRedefinedCount field is only present starting in 1.5, // so don't go fatal. compute_optional_offset(classRedefinedCount_offset, - k, vmSymbols::classRedefinedCount_name(), vmSymbols::int_signature()); - - // The field indicating parallelCapable (parallelLockMap) is only present starting in 7, - klassOop k1 = SystemDictionary::ClassLoader_klass(); - compute_optional_offset(parallelCapable_offset, - k1, vmSymbols::parallelCapable_name(), vmSymbols::concurrenthashmap_signature()); -} - -// For class loader classes, parallelCapable defined -// based on non-null field -// Written to by java.lang.ClassLoader, vm only reads this field, doesn't set it -bool java_lang_Class::parallelCapable(oop class_loader) { - if (!JDK_Version::is_gte_jdk17x_version() - || parallelCapable_offset == -1) { - // Default for backward compatibility is false - return false; - } - return (class_loader->obj_field(parallelCapable_offset) != NULL); + klass_oop, vmSymbols::classRedefinedCount_name(), vmSymbols::int_signature()); + + CLASS_INJECTED_FIELDS(INJECTED_FIELD_COMPUTE_OFFSET); } int java_lang_Class::classRedefinedCount(oop the_class_mirror) { @@ -2308,7 +2328,6 @@ int java_lang_invoke_MethodHandle::_type_offset; int java_lang_invoke_MethodHandle::_vmtarget_offset; int java_lang_invoke_MethodHandle::_vmentry_offset; -int java_lang_invoke_MethodHandle::_vmslots_offset; int java_lang_invoke_MemberName::_clazz_offset; int java_lang_invoke_MemberName::_name_offset; @@ -2327,35 +2346,30 @@ int java_lang_invoke_CountingMethodHandle::_vmcount_offset; void java_lang_invoke_MethodHandle::compute_offsets() { - klassOop k = SystemDictionary::MethodHandle_klass(); - if (k != NULL && EnableInvokeDynamic) { + klassOop klass_oop = SystemDictionary::MethodHandle_klass(); + if (klass_oop != NULL && EnableInvokeDynamic) { bool allow_super = false; - compute_offset(_type_offset, k, vmSymbols::type_name(), vmSymbols::java_lang_invoke_MethodType_signature(), allow_super); - compute_offset(_vmtarget_offset, k, vmSymbols::vmtarget_name(), vmSymbols::object_signature(), allow_super); - compute_offset(_vmentry_offset, k, vmSymbols::vmentry_name(), vmSymbols::machine_word_signature(), allow_super); - - // Note: MH.vmslots (if it is present) is a hoisted copy of MH.type.form.vmslots. - // It is optional pending experiments to keep or toss. - compute_optional_offset(_vmslots_offset, k, vmSymbols::vmslots_name(), vmSymbols::int_signature(), allow_super); + compute_offset(_type_offset, klass_oop, vmSymbols::type_name(), vmSymbols::java_lang_invoke_MethodType_signature(), allow_super); + METHODHANDLE_INJECTED_FIELDS(INJECTED_FIELD_COMPUTE_OFFSET); } } void java_lang_invoke_MemberName::compute_offsets() { - klassOop k = SystemDictionary::MemberName_klass(); - if (k != NULL && EnableInvokeDynamic) { - compute_offset(_clazz_offset, k, vmSymbols::clazz_name(), vmSymbols::class_signature()); - compute_offset(_name_offset, k, vmSymbols::name_name(), vmSymbols::string_signature()); - compute_offset(_type_offset, k, vmSymbols::type_name(), vmSymbols::object_signature()); - compute_offset(_flags_offset, k, vmSymbols::flags_name(), vmSymbols::int_signature()); - compute_offset(_vmtarget_offset, k, vmSymbols::vmtarget_name(), vmSymbols::object_signature()); - compute_offset(_vmindex_offset, k, vmSymbols::vmindex_name(), vmSymbols::int_signature()); + klassOop klass_oop = SystemDictionary::MemberName_klass(); + if (klass_oop != NULL && EnableInvokeDynamic) { + compute_offset(_clazz_offset, klass_oop, vmSymbols::clazz_name(), vmSymbols::class_signature()); + compute_offset(_name_offset, klass_oop, vmSymbols::name_name(), vmSymbols::string_signature()); + compute_offset(_type_offset, klass_oop, vmSymbols::type_name(), vmSymbols::object_signature()); + compute_offset(_flags_offset, klass_oop, vmSymbols::flags_name(), vmSymbols::int_signature()); + compute_offset(_vmindex_offset, klass_oop, vmSymbols::vmindex_name(), vmSymbols::int_signature()); + MEMBERNAME_INJECTED_FIELDS(INJECTED_FIELD_COMPUTE_OFFSET); } } void java_lang_invoke_DirectMethodHandle::compute_offsets() { klassOop k = SystemDictionary::DirectMethodHandle_klass(); if (k != NULL && EnableInvokeDynamic) { - compute_offset(_vmindex_offset, k, vmSymbols::vmindex_name(), vmSymbols::int_signature(), true); + DIRECTMETHODHANDLE_INJECTED_FIELDS(INJECTED_FIELD_COMPUTE_OFFSET); } } @@ -2399,31 +2413,9 @@ mh->obj_field_put(_type_offset, mtype); } -int java_lang_invoke_MethodHandle::vmslots(oop mh) { - int vmslots_offset = _vmslots_offset; - if (vmslots_offset != 0) { -#ifdef ASSERT - int x = mh->int_field(vmslots_offset); - int y = compute_vmslots(mh); - assert(x == y, "correct hoisted value"); -#endif - return mh->int_field(vmslots_offset); - } else { - return compute_vmslots(mh); - } -} - -// if MH.vmslots exists, hoist into it the value of type.form.vmslots -void java_lang_invoke_MethodHandle::init_vmslots(oop mh) { - int vmslots_offset = _vmslots_offset; - if (vmslots_offset != 0) { - mh->int_field_put(vmslots_offset, compute_vmslots(mh)); - } -} - // fetch type.form.vmslots, which is the number of JVM stack slots // required to carry the arguments of this MH -int java_lang_invoke_MethodHandle::compute_vmslots(oop mh) { +int java_lang_invoke_MethodHandle::vmslots(oop mh) { oop mtype = type(mh); if (mtype == NULL) return 0; // Java code would get NPE oop form = java_lang_invoke_MethodType::form(mtype); @@ -2643,6 +2635,7 @@ compute_optional_offset(_erasedType_offset, k, vmSymbols::erasedType_name(), vmSymbols::java_lang_invoke_MethodType_signature(), true); compute_optional_offset(_genericInvoker_offset, k, vmSymbols::genericInvoker_name(), vmSymbols::java_lang_invoke_MethodHandle_signature(), true); if (_genericInvoker_offset == 0) _genericInvoker_offset = -1; // set to explicit "empty" value + METHODTYPEFORM_INJECTED_FIELDS(INJECTED_FIELD_COMPUTE_OFFSET); } } @@ -2751,6 +2744,18 @@ // Support for java_lang_ClassLoader +bool java_lang_ClassLoader::offsets_computed = false; +int java_lang_ClassLoader::parallelCapable_offset = -1; + +void java_lang_ClassLoader::compute_offsets() { + assert(!offsets_computed, "offsets should be initialized only once"); + offsets_computed = true; + + // The field indicating parallelCapable (parallelLockMap) is only present starting in 7, + klassOop k1 = SystemDictionary::ClassLoader_klass(); + compute_optional_offset(parallelCapable_offset, + k1, vmSymbols::parallelCapable_name(), vmSymbols::concurrenthashmap_signature()); +} oop java_lang_ClassLoader::parent(oop loader) { assert(loader->is_oop(), "loader must be oop"); @@ -2758,6 +2763,18 @@ } +// For class loader classes, parallelCapable defined +// based on non-null field +// Written to by java.lang.ClassLoader, vm only reads this field, doesn't set it +bool java_lang_ClassLoader::parallelCapable(oop class_loader) { + if (!JDK_Version::is_gte_jdk17x_version() + || parallelCapable_offset == -1) { + // Default for backward compatibility is false + return false; + } + return (class_loader->obj_field(parallelCapable_offset) != NULL); +} + bool java_lang_ClassLoader::is_trusted_loader(oop loader) { // Fix for 4474172; see evaluation for more details loader = non_reflection_class_loader(loader); @@ -2807,12 +2824,11 @@ int java_lang_String::offset_offset; int java_lang_String::count_offset; int java_lang_String::hash_offset; -int java_lang_Class::klass_offset; -int java_lang_Class::array_klass_offset; -int java_lang_Class::resolved_constructor_offset; -int java_lang_Class::number_of_fake_oop_fields; -int java_lang_Class::oop_size_offset; -int java_lang_Class::static_oop_field_count_offset; +int java_lang_Class::_klass_offset; +int java_lang_Class::_array_klass_offset; +int java_lang_Class::_resolved_constructor_offset; +int java_lang_Class::_oop_size_offset; +int java_lang_Class::_static_oop_field_count_offset; int java_lang_Throwable::backtrace_offset; int java_lang_Throwable::detailMessage_offset; int java_lang_Throwable::cause_offset; @@ -2925,20 +2941,20 @@ void java_nio_Buffer::compute_offsets() { - klassOop k = SystemDictionary::java_nio_Buffer_klass(); + klassOop k = SystemDictionary::nio_Buffer_klass(); assert(k != NULL, "must be loaded in 1.4+"); compute_offset(_limit_offset, k, vmSymbols::limit_name(), vmSymbols::int_signature()); } // Support for intrinsification of sun.misc.AtomicLongCSImpl.attemptUpdate int sun_misc_AtomicLongCSImpl::value_offset() { - assert(SystemDictionary::sun_misc_AtomicLongCSImpl_klass() != NULL, "can't call this"); + assert(SystemDictionary::AtomicLongCSImpl_klass() != NULL, "can't call this"); return _value_offset; } void sun_misc_AtomicLongCSImpl::compute_offsets() { - klassOop k = SystemDictionary::sun_misc_AtomicLongCSImpl_klass(); + klassOop k = SystemDictionary::AtomicLongCSImpl_klass(); // If this class is not present, its value field offset won't be referenced. if (k != NULL) { compute_offset(_value_offset, k, vmSymbols::value_name(), vmSymbols::long_signature()); @@ -2973,23 +2989,6 @@ java_lang_String::count_offset = java_lang_String::offset_offset + sizeof (jint); java_lang_String::hash_offset = java_lang_String::count_offset + sizeof (jint); - { - // Do the Class Class - int offset = header; - java_lang_Class::oop_size_offset = header; - offset += BytesPerInt; - java_lang_Class::static_oop_field_count_offset = offset; - offset = align_size_up(offset + BytesPerInt, x); - java_lang_Class::klass_offset = offset; - offset += x; - java_lang_Class::array_klass_offset = offset; - offset += x; - java_lang_Class::resolved_constructor_offset = offset; - } - - // This is NOT an offset - java_lang_Class::number_of_fake_oop_fields = java_lang_Class::hc_number_of_fake_oop_fields; - // Throwable Class java_lang_Throwable::backtrace_offset = java_lang_Throwable::hc_backtrace_offset * x + header; java_lang_Throwable::detailMessage_offset = java_lang_Throwable::hc_detailMessage_offset * x + header; @@ -3041,8 +3040,8 @@ // Compute non-hard-coded field offsets of all the classes in this file void JavaClasses::compute_offsets() { - - java_lang_Class::compute_offsets(); + // java_lang_Class::compute_offsets was called earlier in bootstrap + java_lang_ClassLoader::compute_offsets(); java_lang_Thread::compute_offsets(); java_lang_ThreadGroup::compute_offsets(); if (EnableInvokeDynamic) { @@ -3267,6 +3266,23 @@ #endif // PRODUCT +int InjectedField::compute_offset() { + klassOop klass_oop = klass(); + for (AllFieldStream fs(instanceKlass::cast(klass_oop)); !fs.done(); fs.next()) { + if (!may_be_java && !fs.access_flags().is_internal()) { + // Only look at injected fields + continue; + } + if (fs.name() == name() && fs.signature() == signature()) { + return fs.offset(); + } + } + ResourceMark rm; + tty->print_cr("Invalid layout of %s at %s", instanceKlass::cast(klass_oop)->external_name(), name()->as_C_string()); + fatal("Invalid layout of preloaded class"); + return -1; +} + void javaClasses_init() { JavaClasses::compute_offsets(); JavaClasses::check_offsets(); diff -r fec876499aae -r e79347eebbc5 hotspot/src/share/vm/classfile/javaClasses.hpp --- a/hotspot/src/share/vm/classfile/javaClasses.hpp Sat Sep 10 00:11:04 2011 -0700 +++ b/hotspot/src/share/vm/classfile/javaClasses.hpp Sat Sep 10 17:29:02 2011 -0700 @@ -156,30 +156,32 @@ // Interface to java.lang.Class objects +#define CLASS_INJECTED_FIELDS(macro) \ + macro(java_lang_Class, klass, object_signature, false) \ + macro(java_lang_Class, resolved_constructor, object_signature, false) \ + macro(java_lang_Class, array_klass, object_signature, false) \ + macro(java_lang_Class, oop_size, int_signature, false) \ + macro(java_lang_Class, static_oop_field_count, int_signature, false) + class java_lang_Class : AllStatic { - friend class VMStructs; + friend class VMStructs; + private: // The fake offsets are added by the class loader when java.lang.Class is loaded - enum { - hc_number_of_fake_oop_fields = 3, - hc_number_of_fake_int_fields = 2 - }; + static int _klass_offset; + static int _resolved_constructor_offset; + static int _array_klass_offset; - static int klass_offset; - static int resolved_constructor_offset; - static int array_klass_offset; - static int number_of_fake_oop_fields; + static int _oop_size_offset; + static int _static_oop_field_count_offset; - static int oop_size_offset; - static int static_oop_field_count_offset; - - static void compute_offsets(); static bool offsets_computed; static int classRedefinedCount_offset; - static int parallelCapable_offset; public: + static void compute_offsets(); + // Instance creation static oop create_mirror(KlassHandle k, TRAPS); static void fixup_mirror(KlassHandle k, TRAPS); @@ -209,14 +211,12 @@ static klassOop array_klass(oop java_class); static void set_array_klass(oop java_class, klassOop klass); // compiler support for class operations - static int klass_offset_in_bytes() { return klass_offset; } - static int resolved_constructor_offset_in_bytes() { return resolved_constructor_offset; } - static int array_klass_offset_in_bytes() { return array_klass_offset; } + static int klass_offset_in_bytes() { return _klass_offset; } + static int resolved_constructor_offset_in_bytes() { return _resolved_constructor_offset; } + static int array_klass_offset_in_bytes() { return _array_klass_offset; } // Support for classRedefinedCount field static int classRedefinedCount(oop the_class_mirror); static void set_classRedefinedCount(oop the_class_mirror, int value); - // Support for parallelCapable field - static bool parallelCapable(oop the_class_mirror); static int oop_size(oop java_class); static void set_oop_size(oop java_class, int size); @@ -834,16 +834,19 @@ // Interface to java.lang.invoke.MethodHandle objects +#define METHODHANDLE_INJECTED_FIELDS(macro) \ + macro(java_lang_invoke_MethodHandle, vmentry, intptr_signature, false) \ + macro(java_lang_invoke_MethodHandle, vmtarget, object_signature, true) + class MethodHandleEntry; class java_lang_invoke_MethodHandle: AllStatic { friend class JavaClasses; private: - static int _vmentry_offset; // assembly code trampoline for MH - static int _vmtarget_offset; // class-specific target reference + static int _vmentry_offset; // assembly code trampoline for MH + static int _vmtarget_offset; // class-specific target reference static int _type_offset; // the MethodType of this MH - static int _vmslots_offset; // OPTIONAL hoisted type.form.vmslots static void compute_offsets(); @@ -859,8 +862,6 @@ static void set_vmentry(oop mh, MethodHandleEntry* data); static int vmslots(oop mh); - static void init_vmslots(oop mh); - static int compute_vmslots(oop mh); // Testers static bool is_subclass(klassOop klass) { @@ -874,14 +875,15 @@ static int type_offset_in_bytes() { return _type_offset; } static int vmtarget_offset_in_bytes() { return _vmtarget_offset; } static int vmentry_offset_in_bytes() { return _vmentry_offset; } - static int vmslots_offset_in_bytes() { return _vmslots_offset; } }; +#define DIRECTMETHODHANDLE_INJECTED_FIELDS(macro) \ + macro(java_lang_invoke_DirectMethodHandle, vmindex, int_signature, true) + class java_lang_invoke_DirectMethodHandle: public java_lang_invoke_MethodHandle { friend class JavaClasses; private: - // _vmtarget_offset; // method or class or interface static int _vmindex_offset; // negative or vtable idx or itable idx static void compute_offsets(); @@ -1012,6 +1014,9 @@ // Interface to java.lang.invoke.MemberName objects // (These are a private interface for Java code to query the class hierarchy.) +#define MEMBERNAME_INJECTED_FIELDS(macro) \ + macro(java_lang_invoke_MemberName, vmtarget, object_signature, true) + class java_lang_invoke_MemberName: AllStatic { friend class JavaClasses; @@ -1121,6 +1126,10 @@ static int form_offset_in_bytes() { return _form_offset; } }; +#define METHODTYPEFORM_INJECTED_FIELDS(macro) \ + macro(java_lang_invoke_MethodTypeForm, vmslots, int_signature, true) \ + macro(java_lang_invoke_MethodTypeForm, vmlayout, object_signature, true) + class java_lang_invoke_MethodTypeForm: AllStatic { friend class JavaClasses; @@ -1135,6 +1144,8 @@ public: // Accessors static int vmslots(oop mtform); + static void set_vmslots(oop mtform, int vmslots); + static oop erasedType(oop mtform); static oop genericInvoker(oop mtform); @@ -1156,8 +1167,6 @@ private: static int _target_offset; - static int _caller_method_offset; - static int _caller_bci_offset; static void compute_offsets(); @@ -1169,12 +1178,6 @@ static volatile oop target_volatile(oop site) { return site->obj_field_volatile( _target_offset); } static void set_target_volatile(oop site, oop target) { site->obj_field_put_volatile(_target_offset, target); } - static oop caller_method(oop site); - static void set_caller_method(oop site, oop ref); - - static jint caller_bci(oop site); - static void set_caller_bci(oop site, jint bci); - // Testers static bool is_subclass(klassOop klass) { return Klass::cast(klass)->is_subclass_of(SystemDictionary::CallSite_klass()); @@ -1185,8 +1188,6 @@ // Accessors for code generation: static int target_offset_in_bytes() { return _target_offset; } - static int caller_method_offset_in_bytes() { return _caller_method_offset; } - static int caller_bci_offset_in_bytes() { return _caller_bci_offset; } }; @@ -1217,11 +1218,18 @@ hc_parent_offset = 0 }; + static bool offsets_computed; static int parent_offset; + static int parallelCapable_offset; + + static void compute_offsets(); public: static oop parent(oop loader); + // Support for parallelCapable field + static bool parallelCapable(oop the_class_mirror); + static bool is_trusted_loader(oop loader); // Fix for 4474172 @@ -1343,17 +1351,71 @@ static oop get_owner_threadObj(oop obj); }; +// Use to declare fields that need to be injected into Java classes +// for the JVM to use. The name_index and signature_index are +// declared in vmSymbols. The may_be_java flag is used to declare +// fields that might already exist in Java but should be injected if +// they don't. Otherwise the field is unconditionally injected and +// the JVM uses the injected one. This is to ensure that name +// collisions don't occur. In general may_be_java should be false +// unless there's a good reason. + +class InjectedField { + public: + const SystemDictionary::WKID klass_id; + const vmSymbols::SID name_index; + const vmSymbols::SID signature_index; + const bool may_be_java; + + + klassOop klass() const { return SystemDictionary::well_known_klass(klass_id); } + Symbol* name() const { return lookup_symbol(name_index); } + Symbol* signature() const { return lookup_symbol(signature_index); } + + int compute_offset(); + + // Find the Symbol for this index + static Symbol* lookup_symbol(int symbol_index) { + return vmSymbols::symbol_at((vmSymbols::SID)symbol_index); + } +}; + +#define DECLARE_INJECTED_FIELD_ENUM(klass, name, signature, may_be_java) \ + klass##_##name##_enum, + +#define ALL_INJECTED_FIELDS(macro) \ + CLASS_INJECTED_FIELDS(macro) \ + METHODHANDLE_INJECTED_FIELDS(macro) \ + DIRECTMETHODHANDLE_INJECTED_FIELDS(macro) \ + MEMBERNAME_INJECTED_FIELDS(macro) \ + METHODTYPEFORM_INJECTED_FIELDS(macro) + // Interface to hard-coded offset checking class JavaClasses : AllStatic { private: + + static InjectedField _injected_fields[]; + static bool check_offset(const char *klass_name, int offset, const char *field_name, const char* field_sig) PRODUCT_RETURN0; static bool check_static_offset(const char *klass_name, int hardcoded_offset, const char *field_name, const char* field_sig) PRODUCT_RETURN0; static bool check_constant(const char *klass_name, int constant, const char *field_name, const char* field_sig) PRODUCT_RETURN0; + public: + enum InjectedFieldID { + ALL_INJECTED_FIELDS(DECLARE_INJECTED_FIELD_ENUM) + MAX_enum + }; + + static int compute_injected_offset(InjectedFieldID id); + static void compute_hard_coded_offsets(); static void compute_offsets(); static void check_offsets() PRODUCT_RETURN; + + static InjectedField* get_injected(Symbol* class_name, int* field_count); }; +#undef DECLARE_INJECTED_FIELD_ENUM + #endif // SHARE_VM_CLASSFILE_JAVACLASSES_HPP diff -r fec876499aae -r e79347eebbc5 hotspot/src/share/vm/classfile/systemDictionary.cpp --- a/hotspot/src/share/vm/classfile/systemDictionary.cpp Sat Sep 10 00:11:04 2011 -0700 +++ b/hotspot/src/share/vm/classfile/systemDictionary.cpp Sat Sep 10 17:29:02 2011 -0700 @@ -125,13 +125,13 @@ bool SystemDictionary::is_parallelCapable(Handle class_loader) { if (UnsyncloadClass || class_loader.is_null()) return true; if (AlwaysLockClassLoader) return false; - return java_lang_Class::parallelCapable(class_loader()); + return java_lang_ClassLoader::parallelCapable(class_loader()); } // ---------------------------------------------------------------------------- // ParallelDefineClass flag does not apply to bootclass loader bool SystemDictionary::is_parallelDefine(Handle class_loader) { if (class_loader.is_null()) return false; - if (AllowParallelDefineClass && java_lang_Class::parallelCapable(class_loader())) { + if (AllowParallelDefineClass && java_lang_ClassLoader::parallelCapable(class_loader())) { return true; } return false; @@ -1290,7 +1290,7 @@ Symbol* class_name, TRAPS) { - klassOop dlm = SystemDictionary::sun_jkernel_DownloadManager_klass(); + klassOop dlm = SystemDictionary::DownloadManager_klass(); instanceKlassHandle nk; // If download manager class isn't loaded just return. @@ -1953,7 +1953,7 @@ // first do Object, String, Class initialize_wk_klasses_through(WK_KLASS_ENUM_NAME(Class_klass), scan, CHECK); - debug_only(instanceKlass::verify_class_klass_nonstatic_oop_maps(WK_KLASS(Class_klass))); + java_lang_Class::compute_offsets(); // Fixup mirrors for classes loaded before java.lang.Class. // These calls iterate over the objects currently in the perm gen @@ -2001,7 +2001,7 @@ //_box_klasses[T_ARRAY] = WK_KLASS(object_klass); #ifdef KERNEL - if (sun_jkernel_DownloadManager_klass() == NULL) { + if (DownloadManager_klass() == NULL) { warning("Cannot find sun/jkernel/DownloadManager"); } #endif // KERNEL @@ -2736,7 +2736,7 @@ class_size += ik->local_interfaces()->size(); class_size += ik->transitive_interfaces()->size(); // We do not have to count implementors, since we only store one! - class_size += ik->fields()->size(); + class_size += ik->all_fields_count() * FieldInfo::field_slots; } } diff -r fec876499aae -r e79347eebbc5 hotspot/src/share/vm/classfile/systemDictionary.hpp --- a/hotspot/src/share/vm/classfile/systemDictionary.hpp Sat Sep 10 00:11:04 2011 -0700 +++ b/hotspot/src/share/vm/classfile/systemDictionary.hpp Sat Sep 10 17:29:02 2011 -0700 @@ -133,15 +133,15 @@ template(reflect_Method_klass, java_lang_reflect_Method, Pre) \ template(reflect_Constructor_klass, java_lang_reflect_Constructor, Pre) \ \ - /* NOTE: needed too early in bootstrapping process to have checks based on JDK version */ \ - /* Universe::is_gte_jdk14x_version() is not set up by this point. */ \ - /* It's okay if this turns out to be NULL in non-1.4 JDKs. */ \ - template(reflect_MagicAccessorImpl_klass, sun_reflect_MagicAccessorImpl, Opt) \ - template(reflect_MethodAccessorImpl_klass, sun_reflect_MethodAccessorImpl, Opt_Only_JDK14NewRef) \ - template(reflect_ConstructorAccessorImpl_klass, sun_reflect_ConstructorAccessorImpl, Opt_Only_JDK14NewRef) \ - template(reflect_DelegatingClassLoader_klass, sun_reflect_DelegatingClassLoader, Opt) \ - template(reflect_ConstantPool_klass, sun_reflect_ConstantPool, Opt_Only_JDK15) \ - template(reflect_UnsafeStaticFieldAccessorImpl_klass, sun_reflect_UnsafeStaticFieldAccessorImpl, Opt_Only_JDK15) \ + /* NOTE: needed too early in bootstrapping process to have checks based on JDK version */ \ + /* Universe::is_gte_jdk14x_version() is not set up by this point. */ \ + /* It's okay if this turns out to be NULL in non-1.4 JDKs. */ \ + template(reflect_MagicAccessorImpl_klass, sun_reflect_MagicAccessorImpl, Opt) \ + template(reflect_MethodAccessorImpl_klass, sun_reflect_MethodAccessorImpl, Opt_Only_JDK14NewRef) \ + template(reflect_ConstructorAccessorImpl_klass, sun_reflect_ConstructorAccessorImpl, Opt_Only_JDK14NewRef) \ + template(reflect_DelegatingClassLoader_klass, sun_reflect_DelegatingClassLoader, Opt) \ + template(reflect_ConstantPool_klass, sun_reflect_ConstantPool, Opt_Only_JDK15) \ + template(reflect_UnsafeStaticFieldAccessorImpl_klass, sun_reflect_UnsafeStaticFieldAccessorImpl, Opt_Only_JDK15) \ \ /* support for dynamic typing; it's OK if these are NULL in earlier JDKs */ \ template(MethodHandle_klass, java_lang_invoke_MethodHandle, Pre_JSR292) \ @@ -168,14 +168,14 @@ template(StackTraceElement_klass, java_lang_StackTraceElement, Opt) \ /* Universe::is_gte_jdk14x_version() is not set up by this point. */ \ /* It's okay if this turns out to be NULL in non-1.4 JDKs. */ \ - template(java_nio_Buffer_klass, java_nio_Buffer, Opt) \ + template(nio_Buffer_klass, java_nio_Buffer, Opt) \ \ /* If this class isn't present, it won't be referenced. */ \ - template(sun_misc_AtomicLongCSImpl_klass, sun_misc_AtomicLongCSImpl, Opt) \ + template(AtomicLongCSImpl_klass, sun_misc_AtomicLongCSImpl, Opt) \ \ - template(sun_jkernel_DownloadManager_klass, sun_jkernel_DownloadManager, Opt_Kernel) \ + template(DownloadManager_klass, sun_jkernel_DownloadManager, Opt_Kernel) \ \ - template(sun_misc_PostVMInitHook_klass, sun_misc_PostVMInitHook, Opt) \ + template(PostVMInitHook_klass, sun_misc_PostVMInitHook, Opt) \ \ /* Preload boxing klasses */ \ template(Boolean_klass, java_lang_Boolean, Pre) \ @@ -199,7 +199,7 @@ enum WKID { NO_WKID = 0, - #define WK_KLASS_ENUM(name, ignore_s, ignore_o) WK_KLASS_ENUM_NAME(name), + #define WK_KLASS_ENUM(name, symbol, ignore_o) WK_KLASS_ENUM_NAME(name), WK_KLASS_ENUM_NAME(symbol) = WK_KLASS_ENUM_NAME(name), WK_KLASSES_DO(WK_KLASS_ENUM) #undef WK_KLASS_ENUM @@ -426,11 +426,16 @@ } public: - #define WK_KLASS_DECLARE(name, ignore_symbol, option) \ + #define WK_KLASS_DECLARE(name, symbol, option) \ static klassOop name() { return check_klass_##option(_well_known_klasses[WK_KLASS_ENUM_NAME(name)]); } WK_KLASSES_DO(WK_KLASS_DECLARE); #undef WK_KLASS_DECLARE + static klassOop well_known_klass(WKID id) { + assert(id >= (int)FIRST_WKID && id < (int)WKID_LIMIT, "oob"); + return _well_known_klasses[id]; + } + // Local definition for direct access to the private array: #define WK_KLASS(name) _well_known_klasses[SystemDictionary::WK_KLASS_ENUM_NAME(name)] diff -r fec876499aae -r e79347eebbc5 hotspot/src/share/vm/classfile/vmSymbols.hpp --- a/hotspot/src/share/vm/classfile/vmSymbols.hpp Sat Sep 10 00:11:04 2011 -0700 +++ b/hotspot/src/share/vm/classfile/vmSymbols.hpp Sat Sep 10 17:29:02 2011 -0700 @@ -264,8 +264,8 @@ template(setTargetNormal_name, "setTargetNormal") \ template(setTargetVolatile_name, "setTargetVolatile") \ template(setTarget_signature, "(Ljava/lang/invoke/MethodHandle;)V") \ - NOT_LP64( do_alias(machine_word_signature, int_signature) ) \ - LP64_ONLY( do_alias(machine_word_signature, long_signature) ) \ + NOT_LP64( do_alias(intptr_signature, int_signature) ) \ + LP64_ONLY( do_alias(intptr_signature, long_signature) ) \ template(selectAlternative_signature, "(ZLjava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodHandle;)Ljava/lang/invoke/MethodHandle;") \ \ /* common method and field names */ \ @@ -365,6 +365,11 @@ template(erasedType_name, "erasedType") \ template(genericInvoker_name, "genericInvoker") \ template(append_name, "append") \ + template(klass_name, "klass") \ + template(resolved_constructor_name, "resolved_constructor") \ + template(array_klass_name, "array_klass") \ + template(oop_size_name, "oop_size") \ + template(static_oop_field_count_name, "static_oop_field_count") \ \ /* non-intrinsic name/signature pairs: */ \ template(register_method_name, "register") \ diff -r fec876499aae -r e79347eebbc5 hotspot/src/share/vm/interpreter/interpreterRuntime.cpp --- a/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp Sat Sep 10 00:11:04 2011 -0700 +++ b/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp Sat Sep 10 17:29:02 2011 -0700 @@ -984,11 +984,8 @@ // check the access_flags for the field in the klass instanceKlass* ik = instanceKlass::cast(java_lang_Class::as_klassOop(cp_entry->f1())); - typeArrayOop fields = ik->fields(); int index = cp_entry->field_index(); - assert(index < fields->length(), "holders field index is out of range"); - // bail out if field accesses are not watched - if ((fields->ushort_at(index) & JVM_ACC_FIELD_ACCESS_WATCHED) == 0) return; + if ((ik->field_access_flags(index) & JVM_ACC_FIELD_ACCESS_WATCHED) == 0) return; switch(cp_entry->flag_state()) { case btos: // fall through @@ -1021,11 +1018,9 @@ // check the access_flags for the field in the klass instanceKlass* ik = instanceKlass::cast(k); - typeArrayOop fields = ik->fields(); int index = cp_entry->field_index(); - assert(index < fields->length(), "holders field index is out of range"); // bail out if field modifications are not watched - if ((fields->ushort_at(index) & JVM_ACC_FIELD_MODIFICATION_WATCHED) == 0) return; + if ((ik->field_access_flags(index) & JVM_ACC_FIELD_MODIFICATION_WATCHED) == 0) return; char sig_type = '\0'; diff -r fec876499aae -r e79347eebbc5 hotspot/src/share/vm/oops/cpCacheOop.cpp --- a/hotspot/src/share/vm/oops/cpCacheOop.cpp Sat Sep 10 00:11:04 2011 -0700 +++ b/hotspot/src/share/vm/oops/cpCacheOop.cpp Sat Sep 10 17:29:02 2011 -0700 @@ -128,17 +128,13 @@ void ConstantPoolCacheEntry::set_field(Bytecodes::Code get_code, Bytecodes::Code put_code, KlassHandle field_holder, - int orig_field_index, + int field_index, int field_offset, TosState field_type, bool is_final, bool is_volatile) { set_f1(field_holder()->java_mirror()); set_f2(field_offset); - // The field index is used by jvm/ti and is the index into fields() array - // in holder instanceKlass. This is scaled by instanceKlass::next_offset. - assert((orig_field_index % instanceKlass::next_offset) == 0, "wierd index"); - const int field_index = orig_field_index / instanceKlass::next_offset; assert(field_index <= field_index_mask, "field index does not fit in low flag bits"); set_flags(as_flags(field_type, is_final, false, is_volatile, false, false) | @@ -149,7 +145,7 @@ } int ConstantPoolCacheEntry::field_index() const { - return (_flags & field_index_mask) * instanceKlass::next_offset; + return (_flags & field_index_mask); } void ConstantPoolCacheEntry::set_method(Bytecodes::Code invoke_code, diff -r fec876499aae -r e79347eebbc5 hotspot/src/share/vm/oops/fieldInfo.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/src/share/vm/oops/fieldInfo.hpp Sat Sep 10 17:29:02 2011 -0700 @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef SHARE_VM_OOPS_FIELDINFO_HPP +#define SHARE_VM_OOPS_FIELDINFO_HPP + +#include "oops/typeArrayOop.hpp" +#include "classfile/vmSymbols.hpp" + +// This class represents the field information contained in the fields +// array of an instanceKlass. Currently it's laid on top an array of +// Java shorts but in the future it could simply be used as a real +// array type. FieldInfo generally shouldn't be used directly. +// Fields should be queried either through instanceKlass or through +// the various FieldStreams. +class FieldInfo VALUE_OBJ_CLASS_SPEC { + friend class fieldDescriptor; + friend class JavaFieldStream; + friend class ClassFileParser; + + public: + // fields + // Field info extracted from the class file and stored + // as an array of 7 shorts + enum FieldOffset { + access_flags_offset = 0, + name_index_offset = 1, + signature_index_offset = 2, + initval_index_offset = 3, + low_offset = 4, + high_offset = 5, + generic_signature_offset = 6, + field_slots = 7 + }; + + private: + u2 _shorts[field_slots]; + + void set_name_index(u2 val) { _shorts[name_index_offset] = val; } + void set_signature_index(u2 val) { _shorts[signature_index_offset] = val; } + void set_initval_index(u2 val) { _shorts[initval_index_offset] = val; } + void set_generic_signature_index(u2 val) { _shorts[generic_signature_offset] = val; } + + u2 name_index() const { return _shorts[name_index_offset]; } + u2 signature_index() const { return _shorts[signature_index_offset]; } + u2 initval_index() const { return _shorts[initval_index_offset]; } + u2 generic_signature_index() const { return _shorts[generic_signature_offset]; } + + public: + static FieldInfo* from_field_array(typeArrayOop fields, int index) { + return ((FieldInfo*)fields->short_at_addr(index * field_slots)); + } + + void initialize(u2 access_flags, + u2 name_index, + u2 signature_index, + u2 initval_index, + u2 generic_signature_index, + u4 offset) { + _shorts[access_flags_offset] = access_flags; + _shorts[name_index_offset] = name_index; + _shorts[signature_index_offset] = signature_index; + _shorts[initval_index_offset] = initval_index; + _shorts[generic_signature_offset] = generic_signature_index; + set_offset(offset); + } + + u2 access_flags() const { return _shorts[access_flags_offset]; } + u4 offset() const { return build_int_from_shorts(_shorts[low_offset], _shorts[high_offset]); } + + Symbol* name(constantPoolHandle cp) const { + int index = name_index(); + if (is_internal()) { + return lookup_symbol(index); + } + return cp->symbol_at(index); + } + + Symbol* signature(constantPoolHandle cp) const { + int index = signature_index(); + if (is_internal()) { + return lookup_symbol(index); + } + return cp->symbol_at(index); + } + + Symbol* generic_signature(constantPoolHandle cp) const { + int index = generic_signature_index(); + if (index == 0) { + return NULL; + } + return cp->symbol_at(index); + } + + void set_access_flags(u2 val) { _shorts[access_flags_offset] = val; } + void set_offset(u4 val) { + _shorts[low_offset] = extract_low_short_from_int(val); + _shorts[high_offset] = extract_high_short_from_int(val); + } + + bool is_internal() const { + return (access_flags() & JVM_ACC_FIELD_INTERNAL) != 0; + } + + Symbol* lookup_symbol(int symbol_index) const { + assert(is_internal(), "only internal fields"); + return vmSymbols::symbol_at((vmSymbols::SID)symbol_index); + } +}; + +#endif // SHARE_VM_OOPS_FIELDINFO_HPP diff -r fec876499aae -r e79347eebbc5 hotspot/src/share/vm/oops/fieldStreams.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/src/share/vm/oops/fieldStreams.hpp Sat Sep 10 17:29:02 2011 -0700 @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef SHARE_VM_OOPS_FIELDSTREAMS_HPP +#define SHARE_VM_OOPS_FIELDSTREAMS_HPP + +#include "oops/instanceKlass.hpp" +#include "oops/fieldInfo.hpp" + +// The is the base class for iteration over the fields array +// describing the declared fields in the class. Several subclasses +// are provided depending on the kind of iteration required. The +// JavaFieldStream is for iterating over regular Java fields and it +// generally the preferred iterator. InternalFieldStream only +// iterates over fields that have been injected by the JVM. +// AllFieldStream exposes all fields and should only be used in rare +// cases. +class FieldStreamBase : public StackObj { + protected: + typeArrayHandle _fields; + constantPoolHandle _constants; + int _index; + int _limit; + + FieldInfo* field() const { return FieldInfo::from_field_array(_fields(), _index); } + + FieldStreamBase(typeArrayHandle fields, constantPoolHandle constants, int start, int limit) { + _fields = fields; + _constants = constants; + _index = start; + _limit = limit; + } + + FieldStreamBase(typeArrayHandle fields, constantPoolHandle constants) { + _fields = fields; + _constants = constants; + _index = 0; + _limit = fields->length() / FieldInfo::field_slots; + } + + public: + FieldStreamBase(instanceKlass* klass) { + _fields = klass->fields(); + _constants = klass->constants(); + _index = 0; + _limit = klass->java_fields_count(); + } + FieldStreamBase(instanceKlassHandle klass) { + _fields = klass->fields(); + _constants = klass->constants(); + _index = 0; + _limit = klass->java_fields_count(); + } + + // accessors + int index() const { return _index; } + + void next() { _index += 1; } + bool done() const { return _index >= _limit; } + + // Accessors for current field + AccessFlags access_flags() const { + AccessFlags flags; + flags.set_flags(field()->access_flags()); + return flags; + } + + void set_access_flags(u2 flags) const { + field()->set_access_flags(flags); + } + + void set_access_flags(AccessFlags flags) const { + set_access_flags(flags.as_short()); + } + + Symbol* name() const { + return field()->name(_constants); + } + + Symbol* signature() const { + return field()->signature(_constants); + } + + Symbol* generic_signature() const { + return field()->generic_signature(_constants); + } + + int offset() const { + return field()->offset(); + } + + void set_offset(int offset) { + field()->set_offset(offset); + } +}; + +// Iterate over only the internal fields +class JavaFieldStream : public FieldStreamBase { + public: + JavaFieldStream(instanceKlass* k): FieldStreamBase(k->fields(), k->constants(), 0, k->java_fields_count()) {} + JavaFieldStream(instanceKlassHandle k): FieldStreamBase(k->fields(), k->constants(), 0, k->java_fields_count()) {} + + int name_index() const { + assert(!field()->is_internal(), "regular only"); + return field()->name_index(); + } + void set_name_index(int index) { + assert(!field()->is_internal(), "regular only"); + field()->set_name_index(index); + } + int signature_index() const { + assert(!field()->is_internal(), "regular only"); + return field()->signature_index(); + } + void set_signature_index(int index) { + assert(!field()->is_internal(), "regular only"); + field()->set_signature_index(index); + } + int generic_signature_index() const { + assert(!field()->is_internal(), "regular only"); + return field()->generic_signature_index(); + } + void set_generic_signature_index(int index) { + assert(!field()->is_internal(), "regular only"); + field()->set_generic_signature_index(index); + } + int initval_index() const { + assert(!field()->is_internal(), "regular only"); + return field()->initval_index(); + } + void set_initval_index(int index) { + assert(!field()->is_internal(), "regular only"); + return field()->set_initval_index(index); + } +}; + + +// Iterate over only the internal fields +class InternalFieldStream : public FieldStreamBase { + public: + InternalFieldStream(instanceKlass* k): FieldStreamBase(k->fields(), k->constants(), k->java_fields_count(), k->all_fields_count()) {} + InternalFieldStream(instanceKlassHandle k): FieldStreamBase(k->fields(), k->constants(), k->java_fields_count(), k->all_fields_count()) {} +}; + + +class AllFieldStream : public FieldStreamBase { + public: + AllFieldStream(typeArrayHandle fields, constantPoolHandle constants): FieldStreamBase(fields, constants) {} + AllFieldStream(instanceKlass* k): FieldStreamBase(k->fields(), k->constants()) {} + AllFieldStream(instanceKlassHandle k): FieldStreamBase(k->fields(), k->constants()) {} +}; + +#endif // SHARE_VM_OOPS_FIELDSTREAMS_HPP diff -r fec876499aae -r e79347eebbc5 hotspot/src/share/vm/oops/instanceKlass.cpp --- a/hotspot/src/share/vm/oops/instanceKlass.cpp Sat Sep 10 00:11:04 2011 -0700 +++ b/hotspot/src/share/vm/oops/instanceKlass.cpp Sat Sep 10 17:29:02 2011 -0700 @@ -36,6 +36,7 @@ #include "memory/genOopClosures.inline.hpp" #include "memory/oopFactory.hpp" #include "memory/permGen.hpp" +#include "oops/fieldStreams.hpp" #include "oops/instanceKlass.hpp" #include "oops/instanceMirrorKlass.hpp" #include "oops/instanceOop.hpp" @@ -782,14 +783,11 @@ bool instanceKlass::find_local_field(Symbol* name, Symbol* sig, fieldDescriptor* fd) const { - const int n = fields()->length(); - for (int i = 0; i < n; i += next_offset ) { - int name_index = fields()->ushort_at(i + name_index_offset); - int sig_index = fields()->ushort_at(i + signature_index_offset); - Symbol* f_name = constants()->symbol_at(name_index); - Symbol* f_sig = constants()->symbol_at(sig_index); + for (JavaFieldStream fs(as_klassOop()); !fs.done(); fs.next()) { + Symbol* f_name = fs.name(); + Symbol* f_sig = fs.signature(); if (f_name == name && f_sig == sig) { - fd->initialize(as_klassOop(), i); + fd->initialize(as_klassOop(), fs.index()); return true; } } @@ -803,11 +801,10 @@ closure->do_symbol(&_source_file_name); closure->do_symbol(&_source_debug_extension); - const int n = fields()->length(); - for (int i = 0; i < n; i += next_offset ) { - int name_index = fields()->ushort_at(i + name_index_offset); + for (JavaFieldStream fs(this); !fs.done(); fs.next()) { + int name_index = fs.name_index(); closure->do_symbol(constants()->symbol_at_addr(name_index)); - int sig_index = fields()->ushort_at(i + signature_index_offset); + int sig_index = fs.signature_index(); closure->do_symbol(constants()->symbol_at_addr(sig_index)); } } @@ -872,10 +869,9 @@ bool instanceKlass::find_local_field_from_offset(int offset, bool is_static, fieldDescriptor* fd) const { - int length = fields()->length(); - for (int i = 0; i < length; i += next_offset) { - if (offset_from_fields( i ) == offset) { - fd->initialize(as_klassOop(), i); + for (JavaFieldStream fs(as_klassOop()); !fs.done(); fs.next()) { + if (fs.offset() == offset) { + fd->initialize(as_klassOop(), fs.index()); if (fd->is_static() == is_static) return true; } } @@ -906,11 +902,12 @@ void instanceKlass::do_local_static_fields(FieldClosure* cl) { - fieldDescriptor fd; - int length = fields()->length(); - for (int i = 0; i < length; i += next_offset) { - fd.initialize(as_klassOop(), i); - if (fd.is_static()) cl->do_field(&fd); + for (JavaFieldStream fs(this); !fs.done(); fs.next()) { + if (fs.access_flags().is_static()) { + fieldDescriptor fd; + fd.initialize(as_klassOop(), fs.index()); + cl->do_field(&fd); + } } } @@ -922,11 +919,12 @@ void instanceKlass::do_local_static_fields_impl(instanceKlassHandle this_oop, void f(fieldDescriptor* fd, TRAPS), TRAPS) { - fieldDescriptor fd; - int length = this_oop->fields()->length(); - for (int i = 0; i < length; i += next_offset) { - fd.initialize(this_oop(), i); - if (fd.is_static()) { f(&fd, CHECK); } // Do NOT remove {}! (CHECK macro expands into several statements) + for (JavaFieldStream fs(this_oop()); !fs.done(); fs.next()) { + if (fs.access_flags().is_static()) { + fieldDescriptor fd; + fd.initialize(this_oop(), fs.index()); + f(&fd, CHECK); + } } } @@ -941,11 +939,11 @@ super->do_nonstatic_fields(cl); } fieldDescriptor fd; - int length = fields()->length(); + int length = java_fields_count(); // In DebugInfo nonstatic fields are sorted by offset. int* fields_sorted = NEW_C_HEAP_ARRAY(int, 2*(length+1)); int j = 0; - for (int i = 0; i < length; i += next_offset) { + for (int i = 0; i < length; i += 1) { fd.initialize(as_klassOop(), i); if (!fd.is_static()) { fields_sorted[j + 0] = fd.offset(); @@ -2411,43 +2409,6 @@ oop_oop_iterate(obj, &blk); } -#ifndef PRODUCT - -void instanceKlass::verify_class_klass_nonstatic_oop_maps(klassOop k) { - // This verification code is disabled. JDK_Version::is_gte_jdk14x_version() - // cannot be called since this function is called before the VM is - // able to determine what JDK version is running with. - // The check below always is false since 1.4. - return; - - // This verification code temporarily disabled for the 1.4 - // reflection implementation since java.lang.Class now has - // Java-level instance fields. Should rewrite this to handle this - // case. - if (!(JDK_Version::is_gte_jdk14x_version() && UseNewReflection)) { - // Verify that java.lang.Class instances have a fake oop field added. - instanceKlass* ik = instanceKlass::cast(k); - - // Check that we have the right class - static bool first_time = true; - guarantee(k == SystemDictionary::Class_klass() && first_time, "Invalid verify of maps"); - first_time = false; - const int extra = java_lang_Class::number_of_fake_oop_fields; - guarantee(ik->nonstatic_field_size() == extra, "just checking"); - guarantee(ik->nonstatic_oop_map_count() == 1, "just checking"); - guarantee(ik->size_helper() == align_object_size(instanceOopDesc::header_size() + extra), "just checking"); - - // Check that the map is (2,extra) - int offset = java_lang_Class::klass_offset; - - OopMapBlock* map = ik->start_of_nonstatic_oop_maps(); - guarantee(map->offset() == offset && map->count() == (unsigned int) extra, - "sanity"); - } -} - -#endif // ndef PRODUCT - // JNIid class for jfieldIDs only // Note to reviewers: // These JNI functions are just moved over to column 1 and not changed diff -r fec876499aae -r e79347eebbc5 hotspot/src/share/vm/oops/instanceKlass.hpp --- a/hotspot/src/share/vm/oops/instanceKlass.hpp Sat Sep 10 00:11:04 2011 -0700 +++ b/hotspot/src/share/vm/oops/instanceKlass.hpp Sat Sep 10 17:29:02 2011 -0700 @@ -27,6 +27,7 @@ #include "oops/constMethodOop.hpp" #include "oops/constantPoolOop.hpp" +#include "oops/fieldInfo.hpp" #include "oops/instanceOop.hpp" #include "oops/klassOop.hpp" #include "oops/klassVtable.hpp" @@ -228,6 +229,7 @@ int _static_field_size; // number words used by static fields (oop and non-oop) in this klass int _static_oop_field_count;// number of static oop fields in this klass int _nonstatic_oop_map_size;// size in words of nonstatic oop map blocks + int _java_fields_count; // The number of declared Java fields bool _is_marked_dependent; // used for marking during flushing and deoptimization bool _rewritten; // methods rewritten. bool _has_nonstatic_fields; // for sizing with UseCompressedOops @@ -307,28 +309,29 @@ objArrayOop transitive_interfaces() const { return _transitive_interfaces; } void set_transitive_interfaces(objArrayOop a) { oop_store_without_check((oop*) &_transitive_interfaces, (oop) a); } - // fields - // Field info extracted from the class file and stored - // as an array of 7 shorts - enum FieldOffset { - access_flags_offset = 0, - name_index_offset = 1, - signature_index_offset = 2, - initval_index_offset = 3, - low_offset = 4, - high_offset = 5, - generic_signature_offset = 6, - next_offset = 7 - }; + private: + friend class fieldDescriptor; + FieldInfo* field(int index) const { return FieldInfo::from_field_array(_fields, index); } + + public: + int field_offset (int index) const { return field(index)->offset(); } + int field_access_flags(int index) const { return field(index)->access_flags(); } + Symbol* field_name (int index) const { return field(index)->name(constants()); } + Symbol* field_signature (int index) const { return field(index)->signature(constants()); } + + // Number of Java declared fields + int java_fields_count() const { return _java_fields_count; } + + // Number of fields including any injected fields + int all_fields_count() const { return _fields->length() / sizeof(FieldInfo::field_slots); } typeArrayOop fields() const { return _fields; } - int offset_from_fields( int index ) const { - return build_int_from_shorts( fields()->ushort_at(index + low_offset), - fields()->ushort_at(index + high_offset) ); + + void set_fields(typeArrayOop f, int java_fields_count) { + oop_store_without_check((oop*) &_fields, (oop) f); + _java_fields_count = java_fields_count; } - void set_fields(typeArrayOop f) { oop_store_without_check((oop*) &_fields, (oop) f); } - // inner classes typeArrayOop inner_classes() const { return _inner_classes; } void set_inner_classes(typeArrayOop f) { oop_store_without_check((oop*) &_inner_classes, (oop) f); } @@ -842,10 +845,6 @@ // Verification const char* internal_name() const; void oop_verify_on(oop obj, outputStream* st); - -#ifndef PRODUCT - static void verify_class_klass_nonstatic_oop_maps(klassOop k) PRODUCT_RETURN; -#endif }; inline methodOop instanceKlass::method_at_vtable(int index) { diff -r fec876499aae -r e79347eebbc5 hotspot/src/share/vm/oops/instanceKlassKlass.cpp --- a/hotspot/src/share/vm/oops/instanceKlassKlass.cpp Sat Sep 10 00:11:04 2011 -0700 +++ b/hotspot/src/share/vm/oops/instanceKlassKlass.cpp Sat Sep 10 17:29:02 2011 -0700 @@ -386,7 +386,7 @@ ik->set_local_interfaces(NULL); ik->set_transitive_interfaces(NULL); ik->init_implementor(); - ik->set_fields(NULL); + ik->set_fields(NULL, 0); ik->set_constants(NULL); ik->set_class_loader(NULL); ik->set_protection_domain(NULL); diff -r fec876499aae -r e79347eebbc5 hotspot/src/share/vm/prims/jni.cpp --- a/hotspot/src/share/vm/prims/jni.cpp Sat Sep 10 00:11:04 2011 -0700 +++ b/hotspot/src/share/vm/prims/jni.cpp Sat Sep 10 17:29:02 2011 -0700 @@ -492,7 +492,7 @@ // First check if this is a static field if (modifiers & JVM_ACC_STATIC) { - intptr_t offset = instanceKlass::cast(k1())->offset_from_fields( slot ); + intptr_t offset = instanceKlass::cast(k1())->field_offset( slot ); JNIid* id = instanceKlass::cast(k1())->jni_id_for(offset); assert(id != NULL, "corrupt Field object"); debug_only(id->set_is_static_field_id();) @@ -504,7 +504,7 @@ // The slot is the index of the field description in the field-array // The jfieldID is the offset of the field within the object // It may also have hash bits for k, if VerifyJNIFields is turned on. - intptr_t offset = instanceKlass::cast(k1())->offset_from_fields( slot ); + intptr_t offset = instanceKlass::cast(k1())->field_offset( slot ); assert(instanceKlass::cast(k1())->contains_field_offset(offset), "stay within object"); ret = jfieldIDWorkaround::to_instance_jfieldID(k1(), offset); return ret; diff -r fec876499aae -r e79347eebbc5 hotspot/src/share/vm/prims/jvm.cpp --- a/hotspot/src/share/vm/prims/jvm.cpp Sat Sep 10 00:11:04 2011 -0700 +++ b/hotspot/src/share/vm/prims/jvm.cpp Sat Sep 10 17:29:02 2011 -0700 @@ -32,6 +32,7 @@ #include "gc_interface/collectedHeap.inline.hpp" #include "memory/oopFactory.hpp" #include "memory/universe.inline.hpp" +#include "oops/fieldStreams.hpp" #include "oops/instanceKlass.hpp" #include "oops/objArrayKlass.hpp" #include "prims/jvm.h" @@ -1493,7 +1494,7 @@ fieldDescriptor fd; KlassHandle kh(THREAD, k); - intptr_t offset = instanceKlass::cast(kh())->offset_from_fields(slot); + intptr_t offset = instanceKlass::cast(kh())->field_offset(slot); if (modifiers & JVM_ACC_STATIC) { // for static fields we only look in the current class @@ -1593,9 +1594,6 @@ // Ensure class is linked k->link_class(CHECK_NULL); - typeArrayHandle fields(THREAD, k->fields()); - int fields_len = fields->length(); - // 4496456 We need to filter out java.lang.Throwable.backtrace bool skip_backtrace = false; @@ -1604,12 +1602,11 @@ if (publicOnly) { num_fields = 0; - for (int i = 0, j = 0; i < fields_len; i += instanceKlass::next_offset, j++) { - int mods = fields->ushort_at(i + instanceKlass::access_flags_offset) & JVM_RECOGNIZED_FIELD_MODIFIERS; - if (mods & JVM_ACC_PUBLIC) ++num_fields; + for (JavaFieldStream fs(k()); !fs.done(); fs.next()) { + if (fs.access_flags().is_public()) ++num_fields; } } else { - num_fields = fields_len / instanceKlass::next_offset; + num_fields = k->java_fields_count(); if (k() == SystemDictionary::Throwable_klass()) { num_fields--; @@ -1622,16 +1619,15 @@ int out_idx = 0; fieldDescriptor fd; - for (int i = 0; i < fields_len; i += instanceKlass::next_offset) { + for (JavaFieldStream fs(k); !fs.done(); fs.next()) { if (skip_backtrace) { // 4496456 skip java.lang.Throwable.backtrace - int offset = k->offset_from_fields(i); + int offset = fs.offset(); if (offset == java_lang_Throwable::get_backtrace_offset()) continue; } - int mods = fields->ushort_at(i + instanceKlass::access_flags_offset) & JVM_RECOGNIZED_FIELD_MODIFIERS; - if (!publicOnly || (mods & JVM_ACC_PUBLIC)) { - fd.initialize(k(), i); + if (!publicOnly || fs.access_flags().is_public()) { + fd.initialize(k(), fs.index()); oop field = Reflection::new_field(&fd, UseNewReflection, CHECK_NULL); result->obj_at_put(out_idx, field); ++out_idx; @@ -2119,7 +2115,7 @@ k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread); if (!Klass::cast(k)->oop_is_instance()) return 0; - return instanceKlass::cast(k)->fields()->length() / instanceKlass::next_offset; + return instanceKlass::cast(k)->java_fields_count(); JVM_END @@ -2215,8 +2211,7 @@ JVMWrapper("JVM_GetFieldIxModifiers"); klassOop k = java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(cls)); k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread); - typeArrayOop fields = instanceKlass::cast(k)->fields(); - return fields->ushort_at(field_index * instanceKlass::next_offset + instanceKlass::access_flags_offset) & JVM_RECOGNIZED_FIELD_MODIFIERS; + return instanceKlass::cast(k)->field_access_flags(field_index) & JVM_RECOGNIZED_FIELD_MODIFIERS; JVM_END @@ -2399,7 +2394,7 @@ JVM_END -JVM_QUICK_ENTRY(jint, JVM_GetCPFieldModifiers(JNIEnv *env, jclass cls, int cp_index, jclass called_cls)) +JVM_ENTRY(jint, JVM_GetCPFieldModifiers(JNIEnv *env, jclass cls, int cp_index, jclass called_cls)) JVMWrapper("JVM_GetCPFieldModifiers"); klassOop k = java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(cls)); klassOop k_called = java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(called_cls)); @@ -2411,12 +2406,9 @@ case JVM_CONSTANT_Fieldref: { Symbol* name = cp->uncached_name_ref_at(cp_index); Symbol* signature = cp->uncached_signature_ref_at(cp_index); - typeArrayOop fields = instanceKlass::cast(k_called)->fields(); - int fields_count = fields->length(); - for (int i = 0; i < fields_count; i += instanceKlass::next_offset) { - if (cp_called->symbol_at(fields->ushort_at(i + instanceKlass::name_index_offset)) == name && - cp_called->symbol_at(fields->ushort_at(i + instanceKlass::signature_index_offset)) == signature) { - return fields->ushort_at(i + instanceKlass::access_flags_offset) & JVM_RECOGNIZED_FIELD_MODIFIERS; + for (JavaFieldStream fs(k_called); !fs.done(); fs.next()) { + if (fs.name() == name && fs.signature() == signature) { + return fs.access_flags().as_short() & JVM_RECOGNIZED_FIELD_MODIFIERS; } } return -1; diff -r fec876499aae -r e79347eebbc5 hotspot/src/share/vm/prims/jvmtiClassFileReconstituter.cpp --- a/hotspot/src/share/vm/prims/jvmtiClassFileReconstituter.cpp Sat Sep 10 00:11:04 2011 -0700 +++ b/hotspot/src/share/vm/prims/jvmtiClassFileReconstituter.cpp Sat Sep 10 17:29:02 2011 -0700 @@ -25,6 +25,7 @@ #include "precompiled.hpp" #include "classfile/symbolTable.hpp" #include "interpreter/bytecodeStream.hpp" +#include "oops/fieldStreams.hpp" #include "prims/jvmtiClassFileReconstituter.hpp" #include "runtime/signature.hpp" #ifdef TARGET_ARCH_x86 @@ -52,25 +53,22 @@ // JVMSpec| field_info fields[fields_count]; void JvmtiClassFileReconstituter::write_field_infos() { HandleMark hm(thread()); - typeArrayHandle fields(thread(), ikh()->fields()); - int fields_length = fields->length(); - int num_fields = fields_length / instanceKlass::next_offset; objArrayHandle fields_anno(thread(), ikh()->fields_annotations()); - write_u2(num_fields); - for (int index = 0; index < fields_length; index += instanceKlass::next_offset) { - AccessFlags access_flags; - int flags = fields->ushort_at(index + instanceKlass::access_flags_offset); - access_flags.set_flags(flags); - int name_index = fields->ushort_at(index + instanceKlass::name_index_offset); - int signature_index = fields->ushort_at(index + instanceKlass::signature_index_offset); - int initial_value_index = fields->ushort_at(index + instanceKlass::initval_index_offset); + // Compute the real number of Java fields + int java_fields = ikh()->java_fields_count(); + + write_u2(java_fields * FieldInfo::field_slots); + for (JavaFieldStream fs(ikh()); !fs.done(); fs.next()) { + AccessFlags access_flags = fs.access_flags(); + int name_index = fs.name_index(); + int signature_index = fs.signature_index(); + int initial_value_index = fs.initval_index(); guarantee(name_index != 0 && signature_index != 0, "bad constant pool index for field"); - int offset = ikh()->offset_from_fields( index ); - int generic_signature_index = - fields->ushort_at(index + instanceKlass::generic_signature_offset); + // int offset = ikh()->field_offset( index ); + int generic_signature_index = fs.generic_signature_index(); typeArrayHandle anno(thread(), fields_anno.not_null() ? - (typeArrayOop)(fields_anno->obj_at(index / instanceKlass::next_offset)) : + (typeArrayOop)(fields_anno->obj_at(fs.index())) : (typeArrayOop)NULL); // JVMSpec| field_info { @@ -81,7 +79,7 @@ // JVMSpec| attribute_info attributes[attributes_count]; // JVMSpec| } - write_u2(flags & JVM_RECOGNIZED_FIELD_MODIFIERS); + write_u2(access_flags.as_int() & JVM_RECOGNIZED_FIELD_MODIFIERS); write_u2(name_index); write_u2(signature_index); int attr_count = 0; diff -r fec876499aae -r e79347eebbc5 hotspot/src/share/vm/prims/jvmtiEnv.cpp --- a/hotspot/src/share/vm/prims/jvmtiEnv.cpp Sat Sep 10 00:11:04 2011 -0700 +++ b/hotspot/src/share/vm/prims/jvmtiEnv.cpp Sat Sep 10 17:29:02 2011 -0700 @@ -2044,7 +2044,6 @@ // make sure we haven't set this watch before if (fdesc_ptr->is_field_access_watched()) return JVMTI_ERROR_DUPLICATE; fdesc_ptr->set_is_field_access_watched(true); - update_klass_field_access_flag(fdesc_ptr); JvmtiEventController::change_field_watch(JVMTI_EVENT_FIELD_ACCESS, true); @@ -2057,7 +2056,6 @@ // make sure we have a watch to clear if (!fdesc_ptr->is_field_access_watched()) return JVMTI_ERROR_NOT_FOUND; fdesc_ptr->set_is_field_access_watched(false); - update_klass_field_access_flag(fdesc_ptr); JvmtiEventController::change_field_watch(JVMTI_EVENT_FIELD_ACCESS, false); @@ -2070,7 +2068,6 @@ // make sure we haven't set this watch before if (fdesc_ptr->is_field_modification_watched()) return JVMTI_ERROR_DUPLICATE; fdesc_ptr->set_is_field_modification_watched(true); - update_klass_field_access_flag(fdesc_ptr); JvmtiEventController::change_field_watch(JVMTI_EVENT_FIELD_MODIFICATION, true); @@ -2083,7 +2080,6 @@ // make sure we have a watch to clear if (!fdesc_ptr->is_field_modification_watched()) return JVMTI_ERROR_NOT_FOUND; fdesc_ptr->set_is_field_modification_watched(false); - update_klass_field_access_flag(fdesc_ptr); JvmtiEventController::change_field_watch(JVMTI_EVENT_FIELD_MODIFICATION, false); diff -r fec876499aae -r e79347eebbc5 hotspot/src/share/vm/prims/jvmtiEnvBase.cpp --- a/hotspot/src/share/vm/prims/jvmtiEnvBase.cpp Sat Sep 10 00:11:04 2011 -0700 +++ b/hotspot/src/share/vm/prims/jvmtiEnvBase.cpp Sat Sep 10 17:29:02 2011 -0700 @@ -565,15 +565,6 @@ } -// update the access_flags for the field in the klass -void -JvmtiEnvBase::update_klass_field_access_flag(fieldDescriptor *fd) { - instanceKlass* ik = instanceKlass::cast(fd->field_holder()); - typeArrayOop fields = ik->fields(); - fields->ushort_at_put(fd->index(), (jushort)fd->access_flags().as_short()); -} - - // return the vframe on the specified thread and depth, NULL if no such frame vframe* JvmtiEnvBase::vframeFor(JavaThread* java_thread, jint depth) { diff -r fec876499aae -r e79347eebbc5 hotspot/src/share/vm/prims/jvmtiEnvBase.hpp --- a/hotspot/src/share/vm/prims/jvmtiEnvBase.hpp Sat Sep 10 00:11:04 2011 -0700 +++ b/hotspot/src/share/vm/prims/jvmtiEnvBase.hpp Sat Sep 10 17:29:02 2011 -0700 @@ -267,8 +267,6 @@ // convert to a jni jclass from a non-null klassOop jclass get_jni_class_non_null(klassOop k); - void update_klass_field_access_flag(fieldDescriptor *fd); - jint count_locked_objects(JavaThread *java_thread, Handle hobj); jvmtiError get_locked_objects_in_frame(JavaThread *calling_thread, JavaThread* java_thread, diff -r fec876499aae -r e79347eebbc5 hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp --- a/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp Sat Sep 10 00:11:04 2011 -0700 +++ b/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp Sat Sep 10 17:29:02 2011 -0700 @@ -30,6 +30,7 @@ #include "interpreter/rewriter.hpp" #include "memory/gcLocker.hpp" #include "memory/universe.inline.hpp" +#include "oops/fieldStreams.hpp" #include "oops/klassVtable.hpp" #include "prims/jvmtiImpl.hpp" #include "prims/jvmtiRedefineClasses.hpp" @@ -551,41 +552,35 @@ // Check if the number, names, types and order of fields declared in these classes // are the same. - typeArrayOop k_old_fields = the_class->fields(); - typeArrayOop k_new_fields = scratch_class->fields(); - int n_fields = k_old_fields->length(); - if (n_fields != k_new_fields->length()) { - return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_SCHEMA_CHANGED; - } - - for (i = 0; i < n_fields; i += instanceKlass::next_offset) { + JavaFieldStream old_fs(the_class); + JavaFieldStream new_fs(scratch_class); + for (; !old_fs.done() && !new_fs.done(); old_fs.next(), new_fs.next()) { // access - old_flags = k_old_fields->ushort_at(i + instanceKlass::access_flags_offset); - new_flags = k_new_fields->ushort_at(i + instanceKlass::access_flags_offset); + old_flags = old_fs.access_flags().as_short(); + new_flags = new_fs.access_flags().as_short(); if ((old_flags ^ new_flags) & JVM_RECOGNIZED_FIELD_MODIFIERS) { return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_SCHEMA_CHANGED; } // offset - if (k_old_fields->short_at(i + instanceKlass::low_offset) != - k_new_fields->short_at(i + instanceKlass::low_offset) || - k_old_fields->short_at(i + instanceKlass::high_offset) != - k_new_fields->short_at(i + instanceKlass::high_offset)) { + if (old_fs.offset() != new_fs.offset()) { return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_SCHEMA_CHANGED; } // name and signature - jshort name_index = k_old_fields->short_at(i + instanceKlass::name_index_offset); - jshort sig_index = k_old_fields->short_at(i +instanceKlass::signature_index_offset); - Symbol* name_sym1 = the_class->constants()->symbol_at(name_index); - Symbol* sig_sym1 = the_class->constants()->symbol_at(sig_index); - name_index = k_new_fields->short_at(i + instanceKlass::name_index_offset); - sig_index = k_new_fields->short_at(i + instanceKlass::signature_index_offset); - Symbol* name_sym2 = scratch_class->constants()->symbol_at(name_index); - Symbol* sig_sym2 = scratch_class->constants()->symbol_at(sig_index); + Symbol* name_sym1 = the_class->constants()->symbol_at(old_fs.name_index()); + Symbol* sig_sym1 = the_class->constants()->symbol_at(old_fs.signature_index()); + Symbol* name_sym2 = scratch_class->constants()->symbol_at(new_fs.name_index()); + Symbol* sig_sym2 = scratch_class->constants()->symbol_at(new_fs.signature_index()); if (name_sym1 != name_sym2 || sig_sym1 != sig_sym2) { return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_SCHEMA_CHANGED; } } + // If both streams aren't done then we have a differing number of + // fields. + if (!old_fs.done() || !new_fs.done()) { + return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_SCHEMA_CHANGED; + } + // Do a parallel walk through the old and new methods. Detect // cases where they match (exist in both), have been added in // the new methods, or have been deleted (exist only in the @@ -2369,38 +2364,34 @@ int i; // for portability // update each field in klass to use new constant pool indices as needed - typeArrayHandle fields(THREAD, scratch_class->fields()); - int n_fields = fields->length(); - for (i = 0; i < n_fields; i += instanceKlass::next_offset) { - jshort cur_index = fields->short_at(i + instanceKlass::name_index_offset); + for (JavaFieldStream fs(scratch_class); !fs.done(); fs.next()) { + jshort cur_index = fs.name_index(); jshort new_index = find_new_index(cur_index); if (new_index != 0) { RC_TRACE_WITH_THREAD(0x00080000, THREAD, ("field-name_index change: %d to %d", cur_index, new_index)); - fields->short_at_put(i + instanceKlass::name_index_offset, new_index); + fs.set_name_index(new_index); } - cur_index = fields->short_at(i + instanceKlass::signature_index_offset); + cur_index = fs.signature_index(); new_index = find_new_index(cur_index); if (new_index != 0) { RC_TRACE_WITH_THREAD(0x00080000, THREAD, ("field-signature_index change: %d to %d", cur_index, new_index)); - fields->short_at_put(i + instanceKlass::signature_index_offset, - new_index); + fs.set_signature_index(new_index); } - cur_index = fields->short_at(i + instanceKlass::initval_index_offset); + cur_index = fs.initval_index(); new_index = find_new_index(cur_index); if (new_index != 0) { RC_TRACE_WITH_THREAD(0x00080000, THREAD, ("field-initval_index change: %d to %d", cur_index, new_index)); - fields->short_at_put(i + instanceKlass::initval_index_offset, new_index); + fs.set_initval_index(new_index); } - cur_index = fields->short_at(i + instanceKlass::generic_signature_offset); + cur_index = fs.generic_signature_index(); new_index = find_new_index(cur_index); if (new_index != 0) { RC_TRACE_WITH_THREAD(0x00080000, THREAD, ("field-generic_signature change: %d to %d", cur_index, new_index)); - fields->short_at_put(i + instanceKlass::generic_signature_offset, - new_index); + fs.set_generic_signature_index(new_index); } } // end for each field diff -r fec876499aae -r e79347eebbc5 hotspot/src/share/vm/prims/methodHandles.cpp --- a/hotspot/src/share/vm/prims/methodHandles.cpp Sat Sep 10 00:11:04 2011 -0700 +++ b/hotspot/src/share/vm/prims/methodHandles.cpp Sat Sep 10 17:29:02 2011 -0700 @@ -520,7 +520,7 @@ int slot = java_lang_reflect_Field::slot(target_oop); // fd.index() int mods = java_lang_reflect_Field::modifiers(target_oop); klassOop k = java_lang_Class::as_klassOop(clazz); - int offset = instanceKlass::cast(k)->offset_from_fields(slot); + int offset = instanceKlass::cast(k)->field_offset(slot); init_MemberName(mname_oop, k, accessFlags_from(mods), offset); } else { KlassHandle receiver_limit; int decode_flags = 0; @@ -1632,8 +1632,6 @@ THROW(vmSymbols::java_lang_InternalError()); } - java_lang_invoke_MethodHandle::init_vmslots(mh()); - if (VerifyMethodHandles) { // The privileged code which invokes this routine should not make // a mistake about types, but it's better to verify. @@ -1756,7 +1754,6 @@ if (m.is_null()) { THROW(vmSymbols::java_lang_InternalError()); } if (m->is_abstract()) { THROW(vmSymbols::java_lang_AbstractMethodError()); } - java_lang_invoke_MethodHandle::init_vmslots(mh()); int vmargslot = m->size_of_parameters() - 1; assert(java_lang_invoke_BoundMethodHandle::vmargslot(mh()) == vmargslot, ""); @@ -1862,7 +1859,6 @@ THROW(vmSymbols::java_lang_InternalError()); } - java_lang_invoke_MethodHandle::init_vmslots(mh()); int argslot = java_lang_invoke_BoundMethodHandle::vmargslot(mh()); if (VerifyMethodHandles) { @@ -2686,6 +2682,7 @@ java_lang_invoke_MethodTypeForm::init_vmlayout(mtform(), cookie); } } + assert(java_lang_invoke_MethodTypeForm::vmslots(mtform()) == argument_slot_count(mtype()), "must agree"); } #ifdef ASSERT diff -r fec876499aae -r e79347eebbc5 hotspot/src/share/vm/prims/unsafe.cpp --- a/hotspot/src/share/vm/prims/unsafe.cpp Sat Sep 10 00:11:04 2011 -0700 +++ b/hotspot/src/share/vm/prims/unsafe.cpp Sat Sep 10 17:29:02 2011 -0700 @@ -719,7 +719,7 @@ } } - int offset = instanceKlass::cast(k)->offset_from_fields(slot); + int offset = instanceKlass::cast(k)->field_offset(slot); return field_offset_from_byte_offset(offset); } diff -r fec876499aae -r e79347eebbc5 hotspot/src/share/vm/runtime/fieldDescriptor.cpp --- a/hotspot/src/share/vm/runtime/fieldDescriptor.cpp Sat Sep 10 00:11:04 2011 -0700 +++ b/hotspot/src/share/vm/runtime/fieldDescriptor.cpp Sat Sep 10 17:29:02 2011 -0700 @@ -42,59 +42,51 @@ objArrayOop md = ik->fields_annotations(); if (md == NULL) return NULL; - assert((index() % instanceKlass::next_offset) == 0, ""); - return typeArrayOop(md->obj_at(index() / instanceKlass::next_offset)); + return typeArrayOop(md->obj_at(index())); } constantTag fieldDescriptor::initial_value_tag() const { - return constants()->tag_at(_initial_value_index); + return constants()->tag_at(initial_value_index()); } jint fieldDescriptor::int_initial_value() const { - return constants()->int_at(_initial_value_index); + return constants()->int_at(initial_value_index()); } jlong fieldDescriptor::long_initial_value() const { - return constants()->long_at(_initial_value_index); + return constants()->long_at(initial_value_index()); } jfloat fieldDescriptor::float_initial_value() const { - return constants()->float_at(_initial_value_index); + return constants()->float_at(initial_value_index()); } jdouble fieldDescriptor::double_initial_value() const { - return constants()->double_at(_initial_value_index); + return constants()->double_at(initial_value_index()); } oop fieldDescriptor::string_initial_value(TRAPS) const { - return constants()->string_at(_initial_value_index, CHECK_0); + return constants()->string_at(initial_value_index(), CHECK_0); } void fieldDescriptor::initialize(klassOop k, int index) { instanceKlass* ik = instanceKlass::cast(k); _cp = ik->constants(); - typeArrayOop fields = ik->fields(); - - assert(fields->length() % instanceKlass::next_offset == 0, "Illegal size of field array"); - assert(fields->length() >= index + instanceKlass::next_offset, "Illegal size of field array"); + FieldInfo* f = ik->field(index); + assert(!f->is_internal(), "regular Java fields only"); - _access_flags.set_field_flags(fields->ushort_at(index + instanceKlass::access_flags_offset)); - _name_index = fields->ushort_at(index + instanceKlass::name_index_offset); - _signature_index = fields->ushort_at(index + instanceKlass::signature_index_offset); - _initial_value_index = fields->ushort_at(index + instanceKlass::initval_index_offset); - guarantee(_name_index != 0 && _signature_index != 0, "bad constant pool index for fieldDescriptor"); - _offset = ik->offset_from_fields( index ); - _generic_signature_index = fields->ushort_at(index + instanceKlass::generic_signature_offset); + _access_flags = accessFlags_from(f->access_flags()); + guarantee(f->name_index() != 0 && f->signature_index() != 0, "bad constant pool index for fieldDescriptor"); _index = index; } #ifndef PRODUCT void fieldDescriptor::print_on(outputStream* st) const { - _access_flags.print_on(st); - constants()->symbol_at(_name_index)->print_value_on(st); + access_flags().print_on(st); + name()->print_value_on(st); st->print(" "); - constants()->symbol_at(_signature_index)->print_value_on(st); + signature()->print_value_on(st); st->print(" @%d ", offset()); if (WizardMode && has_initial_value()) { st->print("(initval "); diff -r fec876499aae -r e79347eebbc5 hotspot/src/share/vm/runtime/fieldDescriptor.hpp --- a/hotspot/src/share/vm/runtime/fieldDescriptor.hpp Sat Sep 10 00:11:04 2011 -0700 +++ b/hotspot/src/share/vm/runtime/fieldDescriptor.hpp Sat Sep 10 17:29:02 2011 -0700 @@ -40,29 +40,40 @@ class fieldDescriptor VALUE_OBJ_CLASS_SPEC { private: AccessFlags _access_flags; - int _name_index; - int _signature_index; - int _initial_value_index; - int _offset; - int _generic_signature_index; - int _index; // index into fields() array + int _index; // the field index constantPoolHandle _cp; + // update the access_flags for the field in the klass + void update_klass_field_access_flag() { + instanceKlass* ik = instanceKlass::cast(field_holder()); + ik->field(index())->set_access_flags(_access_flags.as_short()); + } + + FieldInfo* field() const { + instanceKlass* ik = instanceKlass::cast(field_holder()); + return ik->field(_index); + } + public: - Symbol* name() const { return _cp->symbol_at(_name_index); } - Symbol* signature() const { return _cp->symbol_at(_signature_index); } + Symbol* name() const { + return field()->name(_cp); + } + Symbol* signature() const { + return field()->signature(_cp); + } klassOop field_holder() const { return _cp->pool_holder(); } constantPoolOop constants() const { return _cp(); } AccessFlags access_flags() const { return _access_flags; } oop loader() const; // Offset (in words) of field from start of instanceOop / klassOop - int offset() const { return _offset; } - Symbol* generic_signature() const { return (_generic_signature_index > 0 ? _cp->symbol_at(_generic_signature_index) : (Symbol*)NULL); } + int offset() const { return field()->offset(); } + Symbol* generic_signature() const { return field()->generic_signature(_cp); } int index() const { return _index; } typeArrayOop annotations() const; // Initial field value - bool has_initial_value() const { return _initial_value_index != 0; } + bool has_initial_value() const { return field()->initval_index() != 0; } + int initial_value_index() const { return field()->initval_index(); } constantTag initial_value_tag() const; // The tag will return true on one of is_int(), is_long(), is_single(), is_double() jint int_initial_value() const; jlong long_initial_value() const; @@ -74,25 +85,31 @@ BasicType field_type() const { return FieldType::basic_type(signature()); } // Access flags - bool is_public() const { return _access_flags.is_public(); } - bool is_private() const { return _access_flags.is_private(); } - bool is_protected() const { return _access_flags.is_protected(); } + bool is_public() const { return access_flags().is_public(); } + bool is_private() const { return access_flags().is_private(); } + bool is_protected() const { return access_flags().is_protected(); } bool is_package_private() const { return !is_public() && !is_private() && !is_protected(); } - bool is_static() const { return _access_flags.is_static(); } - bool is_final() const { return _access_flags.is_final(); } - bool is_volatile() const { return _access_flags.is_volatile(); } - bool is_transient() const { return _access_flags.is_transient(); } + bool is_static() const { return access_flags().is_static(); } + bool is_final() const { return access_flags().is_final(); } + bool is_volatile() const { return access_flags().is_volatile(); } + bool is_transient() const { return access_flags().is_transient(); } - bool is_synthetic() const { return _access_flags.is_synthetic(); } + bool is_synthetic() const { return access_flags().is_synthetic(); } - bool is_field_access_watched() const { return _access_flags.is_field_access_watched(); } + bool is_field_access_watched() const { return access_flags().is_field_access_watched(); } bool is_field_modification_watched() const - { return _access_flags.is_field_modification_watched(); } - void set_is_field_access_watched(const bool value) - { _access_flags.set_is_field_access_watched(value); } - void set_is_field_modification_watched(const bool value) - { _access_flags.set_is_field_modification_watched(value); } + { return access_flags().is_field_modification_watched(); } + + void set_is_field_access_watched(const bool value) { + _access_flags.set_is_field_access_watched(value); + update_klass_field_access_flag(); + } + + void set_is_field_modification_watched(const bool value) { + _access_flags.set_is_field_modification_watched(value); + update_klass_field_access_flag(); + } // Initialization void initialize(klassOop k, int index); diff -r fec876499aae -r e79347eebbc5 hotspot/src/share/vm/runtime/reflectionUtils.hpp --- a/hotspot/src/share/vm/runtime/reflectionUtils.hpp Sat Sep 10 00:11:04 2011 -0700 +++ b/hotspot/src/share/vm/runtime/reflectionUtils.hpp Sat Sep 10 17:29:02 2011 -0700 @@ -107,10 +107,8 @@ class FieldStream : public KlassStream { private: - int length() const { return fields()->length(); } - constantPoolOop constants() const { return _klass->constants(); } - protected: - typeArrayOop fields() const { return _klass->fields(); } + int length() const { return _klass->java_fields_count(); } + public: FieldStream(instanceKlassHandle klass, bool local_only, bool classes_only) : KlassStream(klass, local_only, classes_only) { @@ -118,26 +116,23 @@ next(); } - void next() { _index -= instanceKlass::next_offset; } + void next() { _index -= 1; } // Accessors for current field AccessFlags access_flags() const { AccessFlags flags; - flags.set_flags(fields()->ushort_at(index() + instanceKlass::access_flags_offset)); + flags.set_flags(_klass->field_access_flags(_index)); return flags; } Symbol* name() const { - int name_index = fields()->ushort_at(index() + instanceKlass::name_index_offset); - return constants()->symbol_at(name_index); + return _klass->field_name(_index); } Symbol* signature() const { - int signature_index = fields()->ushort_at(index() + - instanceKlass::signature_index_offset); - return constants()->symbol_at(signature_index); + return _klass->field_signature(_index); } // missing: initval() int offset() const { - return _klass->offset_from_fields( index() ); + return _klass->field_offset( index() ); } }; @@ -213,10 +208,10 @@ } int field_count(); void next() { - _index -= instanceKlass::next_offset; + _index -= 1; if (has_filtered_field()) { while (_index >=0 && FilteredFieldsMap::is_filtered_field((klassOop)_klass(), offset())) { - _index -= instanceKlass::next_offset; + _index -= 1; } } } diff -r fec876499aae -r e79347eebbc5 hotspot/src/share/vm/runtime/thread.cpp --- a/hotspot/src/share/vm/runtime/thread.cpp Sat Sep 10 00:11:04 2011 -0700 +++ b/hotspot/src/share/vm/runtime/thread.cpp Sat Sep 10 17:29:02 2011 -0700 @@ -966,7 +966,7 @@ // General purpose hook into Java code, run once when the VM is initialized. // The Java library method itself may be changed independently from the VM. static void call_postVMInitHook(TRAPS) { - klassOop k = SystemDictionary::sun_misc_PostVMInitHook_klass(); + klassOop k = SystemDictionary::PostVMInitHook_klass(); instanceKlassHandle klass (THREAD, k); if (klass.not_null()) { JavaValue result(T_VOID); diff -r fec876499aae -r e79347eebbc5 hotspot/src/share/vm/runtime/vmStructs.cpp --- a/hotspot/src/share/vm/runtime/vmStructs.cpp Sat Sep 10 00:11:04 2011 -0700 +++ b/hotspot/src/share/vm/runtime/vmStructs.cpp Sat Sep 10 17:29:02 2011 -0700 @@ -261,6 +261,7 @@ nonstatic_field(instanceKlass, _nof_implementors, int) \ nonstatic_field(instanceKlass, _implementors[0], klassOop) \ nonstatic_field(instanceKlass, _fields, typeArrayOop) \ + nonstatic_field(instanceKlass, _java_fields_count, int) \ nonstatic_field(instanceKlass, _constants, constantPoolOop) \ nonstatic_field(instanceKlass, _class_loader, oop) \ nonstatic_field(instanceKlass, _protection_domain, oop) \ @@ -967,11 +968,11 @@ /* java_lang_Class fields */ \ /*********************************/ \ \ - static_field(java_lang_Class, klass_offset, int) \ - static_field(java_lang_Class, resolved_constructor_offset, int) \ - static_field(java_lang_Class, array_klass_offset, int) \ - static_field(java_lang_Class, oop_size_offset, int) \ - static_field(java_lang_Class, static_oop_field_count_offset, int) \ + static_field(java_lang_Class, _klass_offset, int) \ + static_field(java_lang_Class, _resolved_constructor_offset, int) \ + static_field(java_lang_Class, _array_klass_offset, int) \ + static_field(java_lang_Class, _oop_size_offset, int) \ + static_field(java_lang_Class, _static_oop_field_count_offset, int) \ \ /************************/ \ /* Miscellaneous fields */ \ @@ -1662,18 +1663,23 @@ declare_constant(constMethodOopDesc::_has_localvariable_table) \ \ /*************************************/ \ - /* instanceKlass FieldOffset enum */ \ + /* instanceKlass enum */ \ + /*************************************/ \ + \ + declare_constant(instanceKlass::implementors_limit) \ + \ + /*************************************/ \ + /* FieldInfo FieldOffset enum */ \ /*************************************/ \ \ - declare_constant(instanceKlass::access_flags_offset) \ - declare_constant(instanceKlass::name_index_offset) \ - declare_constant(instanceKlass::signature_index_offset) \ - declare_constant(instanceKlass::initval_index_offset) \ - declare_constant(instanceKlass::low_offset) \ - declare_constant(instanceKlass::high_offset) \ - declare_constant(instanceKlass::generic_signature_offset) \ - declare_constant(instanceKlass::next_offset) \ - declare_constant(instanceKlass::implementors_limit) \ + declare_constant(FieldInfo::access_flags_offset) \ + declare_constant(FieldInfo::name_index_offset) \ + declare_constant(FieldInfo::signature_index_offset) \ + declare_constant(FieldInfo::initval_index_offset) \ + declare_constant(FieldInfo::low_offset) \ + declare_constant(FieldInfo::high_offset) \ + declare_constant(FieldInfo::generic_signature_offset) \ + declare_constant(FieldInfo::field_slots) \ \ /************************************************/ \ /* instanceKlass InnerClassAttributeOffset enum */ \ diff -r fec876499aae -r e79347eebbc5 hotspot/src/share/vm/utilities/accessFlags.hpp --- a/hotspot/src/share/vm/utilities/accessFlags.hpp Sat Sep 10 00:11:04 2011 -0700 +++ b/hotspot/src/share/vm/utilities/accessFlags.hpp Sat Sep 10 17:29:02 2011 -0700 @@ -79,9 +79,14 @@ // Note that the class-related ACC_ANNOTATION bit conflicts with these flags. JVM_ACC_FIELD_ACCESS_WATCHED = 0x00002000, // field access is watched by JVMTI JVM_ACC_FIELD_MODIFICATION_WATCHED = 0x00008000, // field modification is watched by JVMTI + JVM_ACC_FIELD_INTERNAL = 0x00000400, // internal field, same as JVM_ACC_ABSTRACT + + JVM_ACC_FIELD_INTERNAL_FLAGS = JVM_ACC_FIELD_ACCESS_WATCHED | + JVM_ACC_FIELD_MODIFICATION_WATCHED | + JVM_ACC_FIELD_INTERNAL, // flags accepted by set_field_flags() - JVM_ACC_FIELD_FLAGS = 0x00008000 | JVM_ACC_WRITTEN_FLAGS + JVM_ACC_FIELD_FLAGS = JVM_RECOGNIZED_FIELD_MODIFIERS | JVM_ACC_FIELD_INTERNAL_FLAGS }; @@ -150,13 +155,17 @@ bool is_field_access_watched() const { return (_flags & JVM_ACC_FIELD_ACCESS_WATCHED) != 0; } bool is_field_modification_watched() const { return (_flags & JVM_ACC_FIELD_MODIFICATION_WATCHED) != 0; } + bool is_internal() const { return (_flags & JVM_ACC_FIELD_INTERNAL) != 0; } // get .class file flags jint get_flags () const { return (_flags & JVM_ACC_WRITTEN_FLAGS); } // Initialization void add_promoted_flags(jint flags) { _flags |= (flags & JVM_ACC_PROMOTED_FLAGS); } - void set_field_flags(jint flags) { _flags = (flags & JVM_ACC_FIELD_FLAGS); } + void set_field_flags(jint flags) { + assert((flags & JVM_ACC_FIELD_FLAGS) == flags, "only recognized flags"); + _flags = (flags & JVM_ACC_FIELD_FLAGS); + } void set_flags(jint flags) { _flags = (flags & JVM_ACC_WRITTEN_FLAGS); } void set_queued_for_compilation() { atomic_set_bits(JVM_ACC_QUEUED); } @@ -218,8 +227,8 @@ } // Conversion - jshort as_short() { return (jshort)_flags; } - jint as_int() { return _flags; } + jshort as_short() const { return (jshort)_flags; } + jint as_int() const { return _flags; } inline friend AccessFlags accessFlags_from(jint flags);