Skip to content

Commit 743d1c6

Browse files
committed
8353273: Reduce number of oop map entries in instances
Reviewed-by: lmesnik, fparain, jsjolen
1 parent 2a0cf83 commit 743d1c6

File tree

4 files changed

+297
-15
lines changed

4 files changed

+297
-15
lines changed

src/hotspot/share/classfile/fieldLayoutBuilder.cpp

Lines changed: 35 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -126,17 +126,19 @@ void FieldLayout::initialize_static_layout() {
126126
}
127127
}
128128

129-
void FieldLayout::initialize_instance_layout(const InstanceKlass* super_klass) {
129+
void FieldLayout::initialize_instance_layout(const InstanceKlass* super_klass, bool& super_ends_with_oop) {
130130
if (super_klass == nullptr) {
131+
super_ends_with_oop = false;
131132
_blocks = new LayoutRawBlock(LayoutRawBlock::EMPTY, INT_MAX);
132133
_blocks->set_offset(0);
133134
_last = _blocks;
134135
_start = _blocks;
135136
insert(first_empty_block(), new LayoutRawBlock(LayoutRawBlock::RESERVED, instanceOopDesc::base_offset_in_bytes()));
136137
} else {
137-
bool has_fields = reconstruct_layout(super_klass);
138+
bool super_has_instance_fields = false;
139+
reconstruct_layout(super_klass, super_has_instance_fields, super_ends_with_oop);
138140
fill_holes(super_klass);
139-
if (!super_klass->has_contended_annotations() || !has_fields) {
141+
if (!super_klass->has_contended_annotations() || !super_has_instance_fields) {
140142
_start = _blocks; // start allocating fields from the first empty block
141143
} else {
142144
_start = _last; // append fields at the end of the reconstructed layout
@@ -293,15 +295,21 @@ LayoutRawBlock* FieldLayout::insert_field_block(LayoutRawBlock* slot, LayoutRawB
293295
return block;
294296
}
295297

296-
bool FieldLayout::reconstruct_layout(const InstanceKlass* ik) {
297-
bool has_instance_fields = false;
298+
void FieldLayout::reconstruct_layout(const InstanceKlass* ik, bool& has_instance_fields, bool& ends_with_oop) {
299+
has_instance_fields = ends_with_oop = false;
298300
GrowableArray<LayoutRawBlock*>* all_fields = new GrowableArray<LayoutRawBlock*>(32);
301+
BasicType last_type;
302+
int last_offset = -1;
299303
while (ik != nullptr) {
300304
for (AllFieldStream fs(ik->fieldinfo_stream(), ik->constants()); !fs.done(); fs.next()) {
301305
BasicType type = Signature::basic_type(fs.signature());
302306
// distinction between static and non-static fields is missing
303307
if (fs.access_flags().is_static()) continue;
304308
has_instance_fields = true;
309+
if (fs.offset() > last_offset) {
310+
last_offset = fs.offset();
311+
last_type = type;
312+
}
305313
int size = type2aelembytes(type);
306314
// INHERITED blocks are marked as non-reference because oop_maps are handled by their holder class
307315
LayoutRawBlock* block = new LayoutRawBlock(fs.index(), LayoutRawBlock::INHERITED, size, size, false);
@@ -310,6 +318,11 @@ bool FieldLayout::reconstruct_layout(const InstanceKlass* ik) {
310318
}
311319
ik = ik->super() == nullptr ? nullptr : InstanceKlass::cast(ik->super());
312320
}
321+
assert(last_offset == -1 || last_offset > 0, "Sanity");
322+
if (last_offset > 0 &&
323+
(last_type == BasicType::T_ARRAY || last_type == BasicType::T_OBJECT)) {
324+
ends_with_oop = true;
325+
}
313326

314327
all_fields->sort(LayoutRawBlock::compare_offset);
315328
_blocks = new LayoutRawBlock(LayoutRawBlock::RESERVED, instanceOopDesc::base_offset_in_bytes());
@@ -323,7 +336,6 @@ bool FieldLayout::reconstruct_layout(const InstanceKlass* ik) {
323336
_last = b;
324337
}
325338
_start = _blocks;
326-
return has_instance_fields;
327339
}
328340

329341
// Called during the reconstruction of a layout, after fields from super
@@ -516,7 +528,7 @@ FieldGroup* FieldLayoutBuilder::get_or_create_contended_group(int g) {
516528
void FieldLayoutBuilder::prologue() {
517529
_layout = new FieldLayout(_field_info, _constant_pool);
518530
const InstanceKlass* super_klass = _super_klass;
519-
_layout->initialize_instance_layout(super_klass);
531+
_layout->initialize_instance_layout(super_klass, _super_ends_with_oop);
520532
if (super_klass != nullptr) {
521533
_has_nonstatic_fields = super_klass->has_nonstatic_fields();
522534
}
@@ -594,8 +606,14 @@ void FieldLayoutBuilder::insert_contended_padding(LayoutRawBlock* slot) {
594606
// Computation of regular classes layout is an evolution of the previous default layout
595607
// (FieldAllocationStyle 1):
596608
// - primitive fields are allocated first (from the biggest to the smallest)
597-
// - then oop fields are allocated, either in existing gaps or at the end of
598-
// the layout
609+
// - oop fields are allocated, either in existing gaps or at the end of
610+
// the layout. We allocate oops in a single block to have a single oop map entry.
611+
// - if the super class ended with an oop, we lead with oops. That will cause the
612+
// trailing oop map entry of the super class and the oop map entry of this class
613+
// to be folded into a single entry later. Correspondingly, if the super class
614+
// ends with a primitive field, we gain nothing by leading with oops; therefore
615+
// we let oop fields trail, thus giving future derived classes the chance to apply
616+
// the same trick.
599617
void FieldLayoutBuilder::compute_regular_layout() {
600618
bool need_tail_padding = false;
601619
prologue();
@@ -608,8 +626,14 @@ void FieldLayoutBuilder::compute_regular_layout() {
608626
insert_contended_padding(_layout->start());
609627
need_tail_padding = true;
610628
}
611-
_layout->add(_root_group->primitive_fields());
612-
_layout->add(_root_group->oop_fields());
629+
630+
if (_super_ends_with_oop) {
631+
_layout->add(_root_group->oop_fields());
632+
_layout->add(_root_group->primitive_fields());
633+
} else {
634+
_layout->add(_root_group->primitive_fields());
635+
_layout->add(_root_group->oop_fields());
636+
}
613637

614638
if (!_contended_groups.is_empty()) {
615639
for (int i = 0; i < _contended_groups.length(); i++) {

src/hotspot/share/classfile/fieldLayoutBuilder.hpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -169,7 +169,7 @@ class FieldLayout : public ResourceObj {
169169
public:
170170
FieldLayout(GrowableArray<FieldInfo>* field_info, ConstantPool* cp);
171171
void initialize_static_layout();
172-
void initialize_instance_layout(const InstanceKlass* ik);
172+
void initialize_instance_layout(const InstanceKlass* ik, bool& super_ends_with_oop);
173173

174174
LayoutRawBlock* first_empty_block() {
175175
LayoutRawBlock* block = _start;
@@ -188,7 +188,7 @@ class FieldLayout : public ResourceObj {
188188
void add_field_at_offset(LayoutRawBlock* blocks, int offset, LayoutRawBlock* start = nullptr);
189189
void add_contiguously(GrowableArray<LayoutRawBlock*>* list, LayoutRawBlock* start = nullptr);
190190
LayoutRawBlock* insert_field_block(LayoutRawBlock* slot, LayoutRawBlock* block);
191-
bool reconstruct_layout(const InstanceKlass* ik);
191+
void reconstruct_layout(const InstanceKlass* ik, bool& has_instance_fields, bool& ends_with_oop);
192192
void fill_holes(const InstanceKlass* ik);
193193
LayoutRawBlock* insert(LayoutRawBlock* slot, LayoutRawBlock* block);
194194
void remove(LayoutRawBlock* block);
@@ -237,6 +237,7 @@ class FieldLayoutBuilder : public ResourceObj {
237237
int _alignment;
238238
bool _has_nonstatic_fields;
239239
bool _is_contended; // is a contended class?
240+
bool _super_ends_with_oop;
240241

241242
public:
242243
FieldLayoutBuilder(const Symbol* classname, const InstanceKlass* super_klass, ConstantPool* constant_pool,

src/hotspot/share/oops/instanceKlass.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3763,7 +3763,7 @@ void InstanceKlass::print_on(outputStream* st) const {
37633763
InstanceKlass* ik = const_cast<InstanceKlass*>(this);
37643764
ik->print_nonstatic_fields(&print_nonstatic_field);
37653765

3766-
st->print(BULLET"non-static oop maps: ");
3766+
st->print(BULLET"non-static oop maps (%d entries): ", nonstatic_oop_map_count());
37673767
OopMapBlock* map = start_of_nonstatic_oop_maps();
37683768
OopMapBlock* end_map = map + nonstatic_oop_map_count();
37693769
while (map < end_map) {

0 commit comments

Comments
 (0)