7086585: make Java field injection more flexible

Reviewed-by: jrose, twisti, kvn, coleenp
This commit is contained in:
Tom Rodriguez 2011-09-10 17:29:02 -07:00
parent 1ebca30d26
commit e39ba1a5fe
39 changed files with 1073 additions and 991 deletions

View file

@ -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 @@ enum FieldAllocationType {
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
};
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,
};
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;
}
};
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;
};
typeArrayHandle ClassFileParser::parse_fields(constantPoolHandle cp, bool is_interface,
struct FieldAllocationCount *fac,
objArrayHandle* fields_annotations, TRAPS) {
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 @@ typeArrayHandle ClassFileParser::parse_fields(constantPoolHandle cp, bool is_int
}
}
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 @@ typeArrayHandle ClassFileParser::parse_fields(constantPoolHandle cp, bool is_int
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 @@ typeArrayHandle ClassFileParser::assemble_annotations(u1* runtime_visible_annota
}
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 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
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 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
// 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 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
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 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
// 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 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
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 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
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 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
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 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
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();