diff --git a/agent/src/share/classes/sun/jvm/hotspot/oops/AccessFlags.java b/agent/src/share/classes/sun/jvm/hotspot/oops/AccessFlags.java index 02314153e1528ff2f44002c5a9d92972abc061b6..76c73162fa3ee3dcf6c7d54d45e2a64fd4b2a30c 100644 --- a/agent/src/share/classes/sun/jvm/hotspot/oops/AccessFlags.java +++ b/agent/src/share/classes/sun/jvm/hotspot/oops/AccessFlags.java @@ -81,6 +81,7 @@ public class AccessFlags implements /* imports */ ClassConstants { // field flags public boolean fieldAccessWatched () { return (flags & JVM_ACC_FIELD_ACCESS_WATCHED) != 0; } public boolean fieldModificationWatched() { return (flags & JVM_ACC_FIELD_MODIFICATION_WATCHED) != 0; } + public boolean fieldHasGenericSignature() { return (flags & JVM_ACC_FIELD_HAS_GENERIC_SIGNATURE)!= 0; } public void printOn(PrintStream tty) { // prints only .class flags and not the hotspot internal flags diff --git a/agent/src/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java b/agent/src/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java index f342eb72882ae706c906aaf5cb553b7fe2711ed4..9536da39838d3c82499a32faebe6e8a646d84c35 100644 --- a/agent/src/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java +++ b/agent/src/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java @@ -50,7 +50,6 @@ public class InstanceKlass extends Klass { private static int INITVAL_INDEX_OFFSET; private static int LOW_OFFSET; private static int HIGH_OFFSET; - private static int GENERIC_SIGNATURE_INDEX_OFFSET; private static int FIELD_SLOTS; // ClassState constants @@ -99,7 +98,6 @@ public class InstanceKlass extends Klass { 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(); @@ -279,7 +277,25 @@ public class InstanceKlass extends Klass { } public short getFieldGenericSignatureIndex(int index) { - return getFields().getShortAt(index * FIELD_SLOTS + GENERIC_SIGNATURE_INDEX_OFFSET); + int len = (int)getFields().getLength(); + int allFieldsCount = getAllFieldsCount(); + int generic_signature_slot = allFieldsCount * FIELD_SLOTS; + for (int i = 0; i < allFieldsCount; i++) { + short flags = getFieldAccessFlags(i); + AccessFlags access = new AccessFlags(flags); + if (i == index) { + if (access.fieldHasGenericSignature()) { + return getFields().getShortAt(generic_signature_slot); + } else { + return 0; + } + } else { + if (access.fieldHasGenericSignature()) { + generic_signature_slot ++; + } + } + } + return 0; } public Symbol getFieldGenericSignature(int index) { @@ -309,7 +325,18 @@ public class InstanceKlass extends Klass { public ObjArray getTransitiveInterfaces() { return (ObjArray) transitiveInterfaces.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() / FIELD_SLOTS; } + public int getAllFieldsCount() { + int len = (int)getFields().getLength(); + int allFieldsCount = 0; + for (; allFieldsCount*FIELD_SLOTS < len; allFieldsCount++) { + short flags = getFieldAccessFlags(allFieldsCount); + AccessFlags access = new AccessFlags(flags); + if (access.fieldHasGenericSignature()) { + len --; + } + } + return allFieldsCount; + } public ConstantPool getConstants() { return (ConstantPool) constants.getValue(this); } public Oop getClassLoader() { return classLoader.getValue(this); } public Oop getProtectionDomain() { return protectionDomain.getValue(this); } diff --git a/agent/src/share/classes/sun/jvm/hotspot/runtime/ClassConstants.java b/agent/src/share/classes/sun/jvm/hotspot/runtime/ClassConstants.java index 722496e3c278868642f97f7d5cd4f1519fd027c8..e17a75c1f43d072cf529e3dbe6549e4890007ab5 100644 --- a/agent/src/share/classes/sun/jvm/hotspot/runtime/ClassConstants.java +++ b/agent/src/share/classes/sun/jvm/hotspot/runtime/ClassConstants.java @@ -153,6 +153,8 @@ public interface ClassConstants public static final long JVM_ACC_FIELD_ACCESS_WATCHED = 0x00002000; // field modification is watched by JVMTI public static final long JVM_ACC_FIELD_MODIFICATION_WATCHED = 0x00008000; + // field has generic signature + public static final long JVM_ACC_FIELD_HAS_GENERIC_SIGNATURE = 0x00000800; // flags accepted by set_field_flags public static final long JVM_ACC_FIELD_FLAGS = 0x00008000 | JVM_ACC_WRITTEN_FLAGS; diff --git a/src/share/vm/classfile/classFileParser.cpp b/src/share/vm/classfile/classFileParser.cpp index f24610c060cacc9a0ee5c25ad4a243817cc830d7..b2330e61e37c55eb53227eb7096c332ebeeb630f 100644 --- a/src/share/vm/classfile/classFileParser.cpp +++ b/src/share/vm/classfile/classFileParser.cpp @@ -1082,12 +1082,36 @@ typeArrayHandle ClassFileParser::parse_fields(Symbol* class_name, 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 + num_injected) * FieldInfo::field_slots, CHECK_(nullHandle)); - typeArrayHandle fields(THREAD, new_fields); + int total_fields = length + num_injected; + + // The field array starts with tuples of shorts + // [access, name index, sig index, initial value index, byte offset]. + // A generic signature slot only exists for field with generic + // signature attribute. And the access flag is set with + // JVM_ACC_FIELD_HAS_GENERIC_SIGNATURE for that field. The generic + // signature slots are at the end of the field array and after all + // other fields data. + // + // f1: [access, name index, sig index, initial value index, low_offset, high_offset] + // f2: [access, name index, sig index, initial value index, low_offset, high_offset] + // ... + // fn: [access, name index, sig index, initial value index, low_offset, high_offset] + // [generic signature index] + // [generic signature index] + // ... + // + // Allocate a temporary resource array for field data. For each field, + // a slot is reserved in the temporary array for the generic signature + // index. After parsing all fields, the data are copied to a permanent + // array and any unused slots will be discarded. + ResourceMark rm(THREAD); + u2* fa = NEW_RESOURCE_ARRAY_IN_THREAD( + THREAD, u2, total_fields * (FieldInfo::field_slots + 1)); typeArrayHandle field_annotations; + // The generic signature slots start after all other fields' data. + int generic_signature_slot = total_fields * FieldInfo::field_slots; + int num_generic_signature = 0; for (int n = 0; n < length; n++) { cfs->guarantee_more(8, CHECK_(nullHandle)); // access_flags, name_index, descriptor_index, attributes_count @@ -1135,14 +1159,19 @@ typeArrayHandle ClassFileParser::parse_fields(Symbol* class_name, if (is_synthetic) { access_flags.set_is_synthetic(); } + if (generic_signature_index != 0) { + access_flags.set_field_has_generic_signature(); + fa[generic_signature_slot] = generic_signature_index; + generic_signature_slot ++; + num_generic_signature ++; + } } - FieldInfo* field = FieldInfo::from_field_array(fields(), n); + FieldInfo* field = FieldInfo::from_field_array(fa, 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); @@ -1155,8 +1184,8 @@ typeArrayHandle ClassFileParser::parse_fields(Symbol* class_name, field->set_offset(atype); } + int index = length; if (num_injected != 0) { - int index = length; for (int n = 0; n < num_injected; n++) { // Check for duplicates if (injected[n].may_be_java) { @@ -1164,7 +1193,7 @@ typeArrayHandle ClassFileParser::parse_fields(Symbol* class_name, Symbol* signature = injected[n].signature(); bool duplicate = false; for (int i = 0; i < length; i++) { - FieldInfo* f = FieldInfo::from_field_array(fields(), i); + FieldInfo* f = FieldInfo::from_field_array(fa, 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 @@ -1179,12 +1208,11 @@ typeArrayHandle ClassFileParser::parse_fields(Symbol* class_name, } // Injected field - FieldInfo* field = FieldInfo::from_field_array(fields(), index); + FieldInfo* field = FieldInfo::from_field_array(fa, 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()); @@ -1197,17 +1225,27 @@ typeArrayHandle ClassFileParser::parse_fields(Symbol* class_name, 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; + // Now copy the fields' data from the temporary resource array. + // Sometimes injected fields already exist in the Java source so + // the fields array could be too long. In that case the + // fields array is trimed. Also unused slots that were reserved + // for generic signature indexes are discarded. + typeArrayOop new_fields = oopFactory::new_permanent_shortArray( + index * FieldInfo::field_slots + num_generic_signature, + CHECK_(nullHandle)); + typeArrayHandle fields(THREAD, new_fields); + { + int i = 0; + for (; i < index * FieldInfo::field_slots; i++) { + new_fields->short_at_put(i, fa[i]); + } + for (int j = total_fields * FieldInfo::field_slots; + j < generic_signature_slot; j++) { + new_fields->short_at_put(i++, fa[j]); } + assert(i == new_fields->length(), ""); } if (_need_verify && length > 1) { diff --git a/src/share/vm/classfile/systemDictionary.cpp b/src/share/vm/classfile/systemDictionary.cpp index 0bdc16de6ffbb2708f8dbd21b2f1242027454d7e..78c854f3058d10dbef07ad2cfd056e15456c6935 100644 --- a/src/share/vm/classfile/systemDictionary.cpp +++ b/src/share/vm/classfile/systemDictionary.cpp @@ -2763,7 +2763,7 @@ class ClassStatistics: AllStatic { 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->all_fields_count() * FieldInfo::field_slots; + class_size += ik->fields()->length(); } } diff --git a/src/share/vm/oops/fieldInfo.hpp b/src/share/vm/oops/fieldInfo.hpp index 69de3aef110887cd0c87a1801ed71bcace94ad3c..f4cf1a4c40f2bec29c44696edae81620cf55c396 100644 --- a/src/share/vm/oops/fieldInfo.hpp +++ b/src/share/vm/oops/fieldInfo.hpp @@ -50,8 +50,7 @@ class FieldInfo VALUE_OBJ_CLASS_SPEC { initval_index_offset = 3, low_offset = 4, high_offset = 5, - generic_signature_offset = 6, - field_slots = 7 + field_slots = 6 }; private: @@ -60,29 +59,28 @@ class FieldInfo VALUE_OBJ_CLASS_SPEC { 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)); } + static FieldInfo* from_field_array(u2* fields, int index) { + return ((FieldInfo*)(fields + 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); } @@ -105,14 +103,6 @@ class FieldInfo VALUE_OBJ_CLASS_SPEC { 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); diff --git a/src/share/vm/oops/fieldStreams.hpp b/src/share/vm/oops/fieldStreams.hpp index 07c28f32eeecf96312d190c8e2d3c859ebc68844..08127bfb0dfea28d795d3521ce60ab7345139362 100644 --- a/src/share/vm/oops/fieldStreams.hpp +++ b/src/share/vm/oops/fieldStreams.hpp @@ -42,21 +42,57 @@ class FieldStreamBase : public StackObj { constantPoolHandle _constants; int _index; int _limit; + int _generic_signature_slot; FieldInfo* field() const { return FieldInfo::from_field_array(_fields(), _index); } + int init_generic_signature_start_slot() { + int length = _fields->length(); + int num_fields = 0; + int skipped_generic_signature_slots = 0; + FieldInfo* fi; + AccessFlags flags; + /* Scan from 0 to the current _index. Count the number of generic + signature slots for field[0] to field[_index - 1]. */ + for (int i = 0; i < _index; i++) { + fi = FieldInfo::from_field_array(_fields(), i); + flags.set_flags(fi->access_flags()); + if (flags.field_has_generic_signature()) { + length --; + skipped_generic_signature_slots ++; + } + } + /* Scan from the current _index. */ + for (int i = _index; i*FieldInfo::field_slots < length; i++) { + fi = FieldInfo::from_field_array(_fields(), i); + flags.set_flags(fi->access_flags()); + if (flags.field_has_generic_signature()) { + length --; + } + num_fields ++; + } + _generic_signature_slot = length + skipped_generic_signature_slots; + assert(_generic_signature_slot <= _fields->length(), ""); + return num_fields; + } + FieldStreamBase(typeArrayHandle fields, constantPoolHandle constants, int start, int limit) { _fields = fields; _constants = constants; _index = start; - _limit = limit; + int num_fields = init_generic_signature_start_slot(); + if (limit < start) { + _limit = num_fields; + } else { + _limit = limit; + } } FieldStreamBase(typeArrayHandle fields, constantPoolHandle constants) { _fields = fields; _constants = constants; _index = 0; - _limit = fields->length() / FieldInfo::field_slots; + _limit = init_generic_signature_start_slot(); } public: @@ -65,18 +101,26 @@ class FieldStreamBase : public StackObj { _constants = klass->constants(); _index = 0; _limit = klass->java_fields_count(); + init_generic_signature_start_slot(); } FieldStreamBase(instanceKlassHandle klass) { _fields = klass->fields(); _constants = klass->constants(); _index = 0; _limit = klass->java_fields_count(); + init_generic_signature_start_slot(); } // accessors int index() const { return _index; } - void next() { _index += 1; } + void next() { + if (access_flags().field_has_generic_signature()) { + _generic_signature_slot ++; + assert(_generic_signature_slot <= _fields->length(), ""); + } + _index += 1; + } bool done() const { return _index >= _limit; } // Accessors for current field @@ -103,7 +147,13 @@ class FieldStreamBase : public StackObj { } Symbol* generic_signature() const { - return field()->generic_signature(_constants); + if (access_flags().field_has_generic_signature()) { + assert(_generic_signature_slot < _fields->length(), "out of bounds"); + int index = _fields->short_at(_generic_signature_slot); + return _constants->symbol_at(index); + } else { + return NULL; + } } int offset() const { @@ -139,11 +189,19 @@ class JavaFieldStream : public FieldStreamBase { } int generic_signature_index() const { assert(!field()->is_internal(), "regular only"); - return field()->generic_signature_index(); + if (access_flags().field_has_generic_signature()) { + assert(_generic_signature_slot < _fields->length(), "out of bounds"); + return _fields->short_at(_generic_signature_slot); + } else { + return 0; + } } void set_generic_signature_index(int index) { assert(!field()->is_internal(), "regular only"); - field()->set_generic_signature_index(index); + if (access_flags().field_has_generic_signature()) { + assert(_generic_signature_slot < _fields->length(), "out of bounds"); + _fields->short_at_put(_generic_signature_slot, index); + } } int initval_index() const { assert(!field()->is_internal(), "regular only"); @@ -159,8 +217,8 @@ class JavaFieldStream : public FieldStreamBase { // 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()) {} + InternalFieldStream(instanceKlass* k): FieldStreamBase(k->fields(), k->constants(), k->java_fields_count(), 0) {} + InternalFieldStream(instanceKlassHandle k): FieldStreamBase(k->fields(), k->constants(), k->java_fields_count(), 0) {} }; diff --git a/src/share/vm/oops/instanceKlass.hpp b/src/share/vm/oops/instanceKlass.hpp index dd42bce8628528be61f457274d98bf8a39ee544e..229750bce64a5bffbc71ea275ea94425ac3b4e87 100644 --- a/src/share/vm/oops/instanceKlass.hpp +++ b/src/share/vm/oops/instanceKlass.hpp @@ -168,8 +168,19 @@ class instanceKlass: public Klass { objArrayOop _local_interfaces; // Interface (klassOops) this class implements transitively. objArrayOop _transitive_interfaces; - // Instance and static variable information, 5-tuples of shorts [access, name - // index, sig index, initval index, offset]. + // Instance and static variable information, starts with 6-tuples of shorts + // [access, name index, sig index, initval index, low_offset, high_offset] + // for all fields, followed by the generic signature data at the end of + // the array. Only fields with generic signature attributes have the generic + // signature data set in the array. The fields array looks like following: + // + // f1: [access, name index, sig index, initial value index, low_offset, high_offset] + // f2: [access, name index, sig index, initial value index, low_offset, high_offset] + // ... + // fn: [access, name index, sig index, initial value index, low_offset, high_offset] + // [generic signature index] + // [generic signature index] + // ... typeArrayOop _fields; // Constant pool for this class. constantPoolOop _constants; @@ -351,9 +362,6 @@ class instanceKlass: public Klass { // Number of Java declared fields int java_fields_count() const { return (int)_java_fields_count; } - // Number of fields including any injected fields - int all_fields_count() const { return _fields->length() / FieldInfo::field_slots; } - typeArrayOop fields() const { return _fields; } void set_fields(typeArrayOop f, u2 java_fields_count) { diff --git a/src/share/vm/runtime/fieldDescriptor.cpp b/src/share/vm/runtime/fieldDescriptor.cpp index 1fb0ce0c5e8a4eeed7d177eff5a16e8aac208fd0..fc26d9cd09eb861d0dc5e6244b332814eb2d096d 100644 --- a/src/share/vm/runtime/fieldDescriptor.cpp +++ b/src/share/vm/runtime/fieldDescriptor.cpp @@ -28,6 +28,7 @@ #include "memory/resourceArea.hpp" #include "memory/universe.inline.hpp" #include "oops/instanceKlass.hpp" +#include "oops/fieldStreams.hpp" #include "runtime/fieldDescriptor.hpp" #include "runtime/handles.inline.hpp" #include "runtime/signature.hpp" @@ -37,6 +38,20 @@ oop fieldDescriptor::loader() const { return instanceKlass::cast(_cp->pool_holder())->class_loader(); } +Symbol* fieldDescriptor::generic_signature() const { + int idx = 0; + instanceKlass* ik = instanceKlass::cast(field_holder()); + for (AllFieldStream fs(ik); !fs.done(); fs.next()) { + if (idx == _index) { + return fs.generic_signature(); + } else { + idx ++; + } + } + assert(false, "should never happen"); + return NULL; +} + typeArrayOop fieldDescriptor::annotations() const { instanceKlass* ik = instanceKlass::cast(field_holder()); objArrayOop md = ik->fields_annotations(); diff --git a/src/share/vm/runtime/fieldDescriptor.hpp b/src/share/vm/runtime/fieldDescriptor.hpp index e68b5c5f005da4bd5cd2a0f1b43b50f6857ed553..f2cdbadbab9001acc17fe27efbdb507544713e7d 100644 --- a/src/share/vm/runtime/fieldDescriptor.hpp +++ b/src/share/vm/runtime/fieldDescriptor.hpp @@ -67,7 +67,7 @@ class fieldDescriptor VALUE_OBJ_CLASS_SPEC { oop loader() const; // Offset (in words) of field from start of instanceOop / klassOop int offset() const { return field()->offset(); } - Symbol* generic_signature() const { return field()->generic_signature(_cp); } + Symbol* generic_signature() const; int index() const { return _index; } typeArrayOop annotations() const; diff --git a/src/share/vm/runtime/vmStructs.cpp b/src/share/vm/runtime/vmStructs.cpp index cc2d0783430460e66170727fa92ed57343afeb1f..921945a953221b386d094d9cc21825ec19045f69 100644 --- a/src/share/vm/runtime/vmStructs.cpp +++ b/src/share/vm/runtime/vmStructs.cpp @@ -2352,7 +2352,6 @@ static inline uint64_t cast_uint64_t(size_t x) 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) \ \ /************************************************/ \ diff --git a/src/share/vm/utilities/accessFlags.hpp b/src/share/vm/utilities/accessFlags.hpp index 484ce4f3f8d6136f57a5ee1de65d78700010ed3c..2e86497b6829386375ff72c7622f22ca0b635fc4 100644 --- a/src/share/vm/utilities/accessFlags.hpp +++ b/src/share/vm/utilities/accessFlags.hpp @@ -80,10 +80,12 @@ enum { 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_HAS_GENERIC_SIGNATURE = 0x00000800, // field has generic signature JVM_ACC_FIELD_INTERNAL_FLAGS = JVM_ACC_FIELD_ACCESS_WATCHED | JVM_ACC_FIELD_MODIFICATION_WATCHED | - JVM_ACC_FIELD_INTERNAL, + JVM_ACC_FIELD_INTERNAL | + JVM_ACC_FIELD_HAS_GENERIC_SIGNATURE, // flags accepted by set_field_flags() JVM_ACC_FIELD_FLAGS = JVM_RECOGNIZED_FIELD_MODIFIERS | JVM_ACC_FIELD_INTERNAL_FLAGS @@ -156,6 +158,8 @@ class AccessFlags VALUE_OBJ_CLASS_SPEC { 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; } + bool field_has_generic_signature() const + { return (_flags & JVM_ACC_FIELD_HAS_GENERIC_SIGNATURE) != 0; } // get .class file flags jint get_flags () const { return (_flags & JVM_ACC_WRITTEN_FLAGS); } @@ -225,6 +229,10 @@ class AccessFlags VALUE_OBJ_CLASS_SPEC { atomic_clear_bits(JVM_ACC_FIELD_MODIFICATION_WATCHED); } } + void set_field_has_generic_signature() + { + atomic_set_bits(JVM_ACC_FIELD_HAS_GENERIC_SIGNATURE); + } // Conversion jshort as_short() const { return (jshort)_flags; }