提交 315f543a 编写于 作者: J jiangli

7168280: Eliminate the generic signature index slot from field array for field...

7168280: Eliminate the generic signature index slot from field array for field without generic signature.
Summary: Only allocate the generic signature index slot in the field array for field with generic signature attribute.
Reviewed-by: coleenp, dlong
上级 719bff5c
......@@ -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
......
......@@ -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); }
......
......@@ -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;
......
......@@ -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) {
......
......@@ -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();
}
}
......
......@@ -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);
......
......@@ -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) {}
};
......
......@@ -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) {
......
......@@ -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();
......
......@@ -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;
......
......@@ -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) \
\
/************************************************/ \
......
......@@ -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; }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册