--- old/hotspot/src/share/vm/classfile/classFileParser.cpp 2017-06-29 10:45:51.998755826 +0200 +++ new/hotspot/src/share/vm/classfile/classFileParser.cpp 2017-06-29 10:45:51.822752644 +0200 @@ -1469,6 +1469,28 @@ } return atype; } + + // Attempt to redistribute NONSTATIC_VALUETYPE alloc type + FieldAllocationType redistribute_value(bool oops, int value_size) { + FieldAllocationType atype = NONSTATIC_VALUETYPE; + switch (value_size) { + case 1: + atype = NONSTATIC_BYTE; + break; + case 2: + atype = NONSTATIC_SHORT; + break; + case 4: + atype = (oops) ? NONSTATIC_OOP : NONSTATIC_WORD; + break; + default: + assert(is_size_aligned(value_size, BytesPerLong), "Unaligned value %d", value_size); + return atype; + } + count[atype]++; + count[NONSTATIC_VALUETYPE]--; // Leave only large variable sized behind + return atype; + } }; // Side-effects: populates the _fields, _fields_annotations, @@ -3812,7 +3834,7 @@ // Layout fields and fill in FieldLayoutInfo. Could use more refactoring! void ClassFileParser::layout_fields(ConstantPool* cp, - const FieldAllocationCount* fac, + FieldAllocationCount* fac, const ClassAnnotationCollector* parsed_annotations, FieldLayoutInfo* info, TRAPS) { @@ -3835,6 +3857,13 @@ // The layout code below will also ignore the static fields. int nonstatic_contended_count = 0; FieldAllocationCount fac_contended; + + // Redistribute value types if possible, gather their klasses, oopmap count... + unsigned int value_type_oop_map_count = 0; + int large_value_count = 0; + ValueKlass** nonstatic_value_type_klasses = + NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, ValueKlass*, fac->count[NONSTATIC_VALUETYPE]); + for (AllFieldStream fs(_fields, cp); !fs.done(); fs.next()) { FieldAllocationType atype = (FieldAllocationType) fs.allocation_type(); if (fs.is_contended()) { @@ -3843,6 +3872,25 @@ nonstatic_contended_count++; } } + else if (atype == NONSTATIC_VALUETYPE) { + Symbol* signature = fs.signature(); + Klass* klass = SystemDictionary::resolve_or_fail(signature, + Handle(THREAD, _loader_data->class_loader()), + _protection_domain, true, CHECK); + assert(klass != NULL && klass->access_flags().is_value_type(), "Sanity check"); + ValueKlass* vklass = ValueKlass::cast(klass); + if (vklass->contains_oops()) { + value_type_oop_map_count += vklass->nonstatic_oop_map_count(); + } + int raw_value_size = vklass->raw_value_byte_size(); + FieldAllocationType atype = fac->redistribute_value(vklass->contains_oops(), raw_value_size); + if (atype == NONSTATIC_VALUETYPE) { + // Failed to slot in with the others, allocate large values last jlong align for safe copy + nonstatic_value_type_klasses[large_value_count++] = vklass; + } else { + fs.coerce_allocation_type(NONSTATIC_VALUETYPE, (int) atype); + } + } } @@ -3903,43 +3951,7 @@ unsigned int nonstatic_short_count = fac->count[NONSTATIC_SHORT] - fac_contended.count[NONSTATIC_SHORT]; unsigned int nonstatic_byte_count = fac->count[NONSTATIC_BYTE] - fac_contended.count[NONSTATIC_BYTE]; unsigned int nonstatic_oop_count = fac->count[NONSTATIC_OOP] - fac_contended.count[NONSTATIC_OOP]; - - int static_value_type_count = 0; - int nonstatic_value_type_count = 0; - int* nonstatic_value_type_indexes = NULL; - Klass** nonstatic_value_type_klasses = NULL; - unsigned int value_type_oop_map_count = 0; - - int max_nonstatic_value_type = fac->count[NONSTATIC_VALUETYPE] + 1; - - nonstatic_value_type_indexes = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, int, - max_nonstatic_value_type); - for (int i = 0; i < max_nonstatic_value_type; i++) { - nonstatic_value_type_indexes[i] = -1; - } - nonstatic_value_type_klasses = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, Klass*, - max_nonstatic_value_type); - - for (AllFieldStream fs(_fields, _cp); !fs.done(); fs.next()) { - if (fs.allocation_type() == STATIC_VALUETYPE) { - static_value_type_count++; - } else if (fs.allocation_type() == NONSTATIC_VALUETYPE) { - Symbol* signature = fs.signature(); - Klass* klass = SystemDictionary::resolve_or_fail(signature, - Handle(THREAD, _loader_data->class_loader()), - _protection_domain, true, CHECK); - assert(klass != NULL, "Sanity check"); - assert(klass->access_flags().is_value_type(), "Value type expected"); - nonstatic_value_type_indexes[nonstatic_value_type_count] = fs.index(); - nonstatic_value_type_klasses[nonstatic_value_type_count] = klass; - nonstatic_value_type_count++; - - ValueKlass* vklass = ValueKlass::cast(klass); - if (vklass->contains_oops()) { - value_type_oop_map_count += vklass->nonstatic_oop_map_count(); - } - } - } + unsigned int nonstatic_value_type_count = fac->count[NONSTATIC_VALUETYPE]; // Total non-static fields count, including every contended field unsigned int nonstatic_fields_count = fac->count[NONSTATIC_DOUBLE] + fac->count[NONSTATIC_WORD] + @@ -4153,16 +4165,10 @@ break; case NONSTATIC_VALUETYPE: { - Klass* klass = nonstatic_value_type_klasses[next_value_type_index]; - assert(klass != NULL, "Klass should have been loaded and resolved earlier"); - assert(klass->access_flags().is_value_type(),"Must be a value type"); - ValueKlass* vklass = ValueKlass::cast(klass); real_offset = next_nonstatic_valuetype_offset; - next_nonstatic_valuetype_offset += (vklass->size_helper()) * wordSize - vklass->first_field_offset(); - // aligning next value type on a 64 bits boundary - next_nonstatic_valuetype_offset = align_size_up(next_nonstatic_valuetype_offset, BytesPerLong); - next_value_type_index += 1; + assert(next_value_type_index < large_value_count, "Incorrect number of value alloc types"); + ValueKlass* vklass = nonstatic_value_type_klasses[next_value_type_index++]; if (vklass->contains_oops()) { // add flatten oop maps int diff = real_offset - vklass->first_field_offset(); const OopMapBlock* map = vklass->start_of_nonstatic_oop_maps(); @@ -4172,6 +4178,7 @@ map++; } } + next_nonstatic_valuetype_offset += vklass->raw_value_byte_size(); } break; case NONSTATIC_OOP: @@ -4342,7 +4349,7 @@ } int notaligned_nonstatic_fields_end; - if (nonstatic_value_type_count != 0) { + if (has_nonstatic_value_fields) { notaligned_nonstatic_fields_end = next_nonstatic_valuetype_offset; } else { notaligned_nonstatic_fields_end = next_nonstatic_padded_offset;