--- old/src/share/vm/classfile/classFileParser.cpp 2017-09-14 10:45:43.000000000 -0400 +++ new/src/share/vm/classfile/classFileParser.cpp 2017-09-14 10:45:43.000000000 -0400 @@ -3961,6 +3961,7 @@ int static_value_type_count = 0; int nonstatic_value_type_count = 0; + int nonstatic_nonflattened_value_types_count = 0; int* nonstatic_value_type_indexes = NULL; Klass** nonstatic_value_type_klasses = NULL; unsigned int value_type_oop_map_count = 0; @@ -3985,13 +3986,23 @@ _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(); + ValueKlass* vk = ValueKlass::cast(klass); + // Conditions to apply flattening or not should be defined + //in a single place + if (vk->size_helper() <= ValueArrayElemMaxFlatSize) { + 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(); + } + fs.set_flattening(true); + } else { + nonstatic_nonflattened_value_types_count++; + value_type_oop_map_count++; + fs.set_flattening(false); } } } @@ -4075,7 +4086,7 @@ // Fields order: oops, longs/doubles, ints, shorts/chars, bytes, padded fields next_nonstatic_oop_offset = next_nonstatic_field_offset; next_nonstatic_double_offset = next_nonstatic_oop_offset + - (nonstatic_oop_count * heapOopSize); + ((nonstatic_oop_count + nonstatic_nonflattened_value_types_count) * heapOopSize); } else if( allocation_style == 1 ) { // Fields order: longs/doubles, ints, shorts/chars, bytes, oops, padded fields next_nonstatic_double_offset = next_nonstatic_field_offset; @@ -4086,7 +4097,7 @@ allocation_style = 0; // allocate oops first next_nonstatic_oop_offset = next_nonstatic_field_offset; next_nonstatic_double_offset = next_nonstatic_oop_offset + - (nonstatic_oop_count * heapOopSize); + ((nonstatic_oop_count + nonstatic_nonflattened_value_types_count)* heapOopSize); } } if( allocation_style == 2 ) { @@ -4159,10 +4170,11 @@ // let oops jump before padding with this allocation style if( allocation_style == 1 ) { next_nonstatic_oop_offset = next_nonstatic_padded_offset; - if( nonstatic_oop_count > 0 ) { + if( (nonstatic_oop_count + nonstatic_nonflattened_value_types_count) > 0 ) { next_nonstatic_oop_offset = align_up(next_nonstatic_oop_offset, heapOopSize); } - next_nonstatic_padded_offset = next_nonstatic_oop_offset + (nonstatic_oop_count * heapOopSize); + next_nonstatic_padded_offset = next_nonstatic_oop_offset + + ((nonstatic_oop_count + nonstatic_nonflattened_value_types_count) * heapOopSize); } // Aligning embedded value types @@ -4214,28 +4226,30 @@ next_static_double_offset += BytesPerLong; 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_up(next_nonstatic_valuetype_offset, BytesPerLong); - next_value_type_index += 1; - - 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(); - const OopMapBlock* const last_map = map + vklass->nonstatic_oop_map_count(); - while (map < last_map) { - nonstatic_oop_maps->add(map->offset() + diff, map->count()); - map++; + if (fs.is_flatten()) { + 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_up(next_nonstatic_valuetype_offset, BytesPerLong); + next_value_type_index += 1; + + 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(); + const OopMapBlock* const last_map = map + vklass->nonstatic_oop_map_count(); + while (map < last_map) { + nonstatic_oop_maps->add(map->offset() + diff, map->count()); + map++; + } } + break; + } else { + // Fall through } - } - break; case NONSTATIC_OOP: if( nonstatic_oop_space_count > 0 ) { real_offset = nonstatic_oop_space_offset; @@ -4404,7 +4418,7 @@ } int notaligned_nonstatic_fields_end; - if (nonstatic_value_type_count != 0) { + if ((nonstatic_value_type_count - nonstatic_nonflattened_value_types_count) != 0) { notaligned_nonstatic_fields_end = next_nonstatic_valuetype_offset; } else { notaligned_nonstatic_fields_end = next_nonstatic_padded_offset;