Mercurial > hg > truffle
diff src/share/vm/classfile/classFileParser.cpp @ 4137:04b9a2566eec
Merge with hsx23/hotspot.
author | Thomas Wuerthinger <thomas.wuerthinger@oracle.com> |
---|---|
date | Sat, 17 Dec 2011 21:40:27 +0100 |
parents | e6b1331a51d2 |
children | 4ceaf61479fc cd5d8cafcc84 |
line wrap: on
line diff
--- a/src/share/vm/classfile/classFileParser.cpp Sat Dec 17 20:50:09 2011 +0100 +++ b/src/share/vm/classfile/classFileParser.cpp Sat Dec 17 21:40:27 2011 +0100 @@ -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 ) { @@ -3287,9 +3077,9 @@ // Fields allocation: oops fields in super and sub classes are together. if( nonstatic_field_size > 0 && super_klass() != NULL && super_klass->nonstatic_oop_map_size() > 0 ) { - int map_size = super_klass->nonstatic_oop_map_size(); + int map_count = super_klass->nonstatic_oop_map_count(); OopMapBlock* first_map = super_klass->start_of_nonstatic_oop_maps(); - OopMapBlock* last_map = first_map + map_size - 1; + OopMapBlock* last_map = first_map + map_count - 1; int next_offset = last_map->offset() + (last_map->count() * heapOopSize); if (next_offset == next_nonstatic_field_offset) { allocation_style = 0; // allocate oops first @@ -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();