16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
24
25 #ifndef SHARE_CLASSFILE_FIELDLAYOUTBUILDER_HPP
26 #define SHARE_CLASSFILE_FIELDLAYOUTBUILDER_HPP
27
28 #include "classfile/classFileParser.hpp"
29 #include "classfile/classLoaderData.hpp"
30 #include "memory/allocation.hpp"
31 #include "oops/fieldStreams.hpp"
32 #include "utilities/growableArray.hpp"
33
34 // Classes below are used to compute the field layout of classes.
35
36
37 // A LayoutRawBlock describes an element of a layout.
38 // Each field is represented by a LayoutRawBlock.
39 // LayoutRawBlocks can also represent elements injected by the JVM:
40 // padding, empty blocks, inherited fields, etc.
41 // All LayoutRawBlocks must have a size and an alignment. The size is the
42 // exact size of the field expressed in bytes. The alignment is
43 // the alignment constraint of the field (1 for byte, 2 for short,
44 // 4 for int, 8 for long, etc.)
45 //
46 // LayoutRawBlock are designed to be used in two data structures:
47 // - a linked list in a layout (using _next_block, _prev_block)
48 // - a GrowableArray in field group (the growable array contains pointers to LayoutRawBlocks)
49 //
50 // next/prev pointers are included in the LayoutRawBlock class to narrow
51 // the number of allocation required during the computation of a layout.
52 //
53 class LayoutRawBlock : public ResourceObj {
54 public:
55 // Some code relies on the order of values below.
56 enum Kind {
57 EMPTY, // empty slot, space is taken from this to allocate fields
58 RESERVED, // reserved for JVM usage (for instance object header)
59 PADDING, // padding (because of alignment constraints or @Contended)
60 REGULAR, // primitive or oop field (including non-flattened inline fields)
61 FLATTENED, // flattened field
62 INHERITED // field(s) inherited from super classes
63 };
64
65 private:
66 LayoutRawBlock* _next_block;
67 LayoutRawBlock* _prev_block;
68 Kind _kind;
69 int _offset;
70 int _alignment;
71 int _size;
72 int _field_index;
73 bool _is_reference;
74
75 public:
76 LayoutRawBlock(Kind kind, int size);
77 LayoutRawBlock(int index, Kind kind, int size, int alignment, bool is_reference = false);
78 LayoutRawBlock* next_block() const { return _next_block; }
79 void set_next_block(LayoutRawBlock* next) { _next_block = next; }
80 LayoutRawBlock* prev_block() const { return _prev_block; }
81 void set_prev_block(LayoutRawBlock* prev) { _prev_block = prev; }
82 Kind kind() const { return _kind; }
83 int offset() const {
84 assert(_offset >= 0, "Must be initialized");
85 return _offset;
86 }
87 void set_offset(int offset) { _offset = offset; }
88 int alignment() const { return _alignment; }
89 int size() const { return _size; }
90 void set_size(int size) { _size = size; }
91 int field_index() const {
92 assert(_field_index != -1, "Must be initialized");
93 return _field_index;
94 }
95 bool is_reference() const { return _is_reference; }
96
97 bool fit(int size, int alignment);
98
99 static int compare_offset(LayoutRawBlock** x, LayoutRawBlock** y) { return (*x)->offset() - (*y)->offset(); }
100 // compare_size_inverted() returns the opposite of a regular compare method in order to
101 // sort fields in decreasing order.
102 // Note: with line types, the comparison should include alignment constraint if sizes are equals
103 static int compare_size_inverted(LayoutRawBlock** x, LayoutRawBlock** y) {
104 #ifdef _WINDOWS
105 // qsort() on Windows reverse the order of fields with the same size
106 // the extension of the comparison function below preserves this order
107 int diff = (*y)->size() - (*x)->size();
108 if (diff == 0) {
109 diff = (*x)->field_index() - (*y)->field_index();
110 }
111 return diff;
112 #else
113 return (*y)->size() - (*x)->size();
114 #endif // _WINDOWS
115 }
116
117 };
118
119 // A Field group represents a set of fields that have to be allocated together,
120 // this is the way the @Contended annotation is supported.
121 // Inside a FieldGroup, fields are sorted based on their kind: primitive,
122 // oop, or flattened.
123 //
124 class FieldGroup : public ResourceObj {
125
126 private:
127 FieldGroup* _next;
128 GrowableArray<LayoutRawBlock*>* _primitive_fields;
129 GrowableArray<LayoutRawBlock*>* _oop_fields;
130 int _contended_group;
131 int _oop_count;
132 static const int INITIAL_LIST_SIZE = 16;
133
134 public:
135 FieldGroup(int contended_group = -1);
136
137 FieldGroup* next() const { return _next; }
138 void set_next(FieldGroup* next) { _next = next; }
139 GrowableArray<LayoutRawBlock*>* primitive_fields() const { return _primitive_fields; }
140 GrowableArray<LayoutRawBlock*>* oop_fields() const { return _oop_fields; }
141 int contended_group() const { return _contended_group; }
142 int oop_count() const { return _oop_count; }
143
144 void add_primitive_field(int idx, BasicType type);
145 void add_oop_field(int idx);
146 void sort_by_size();
147 };
148
149 // The FieldLayout class represents a set of fields organized
150 // in a layout.
151 // An instance of FieldLayout can either represent the layout
152 // of non-static fields (used in an instance object) or the
153 // layout of static fields (to be included in the class mirror).
154 //
155 // _block is a pointer to a list of LayoutRawBlock ordered by increasing
156 // offsets.
157 // _start points to the LayoutRawBlock with the first offset that can
158 // be used to allocate fields of the current class
159 // _last points to the last LayoutRawBlock of the list. In order to
160 // simplify the code, the LayoutRawBlock list always ends with an
161 // EMPTY block (the kind of LayoutRawBlock from which space is taken
162 // to allocate fields) with a size big enough to satisfy all
163 // field allocations.
164 //
165 class FieldLayout : public ResourceObj {
166 private:
167 GrowableArray<FieldInfo>* _field_info;
168 ConstantPool* _cp;
169 LayoutRawBlock* _blocks; // the layout being computed
170 LayoutRawBlock* _start; // points to the first block where a field can be inserted
171 LayoutRawBlock* _last; // points to the last block of the layout (big empty block)
172
173 public:
174 FieldLayout(GrowableArray<FieldInfo>* field_info, ConstantPool* cp);
175 void initialize_static_layout();
176 void initialize_instance_layout(const InstanceKlass* ik);
177
178 LayoutRawBlock* first_empty_block() {
179 LayoutRawBlock* block = _start;
180 while (block->kind() != LayoutRawBlock::EMPTY) {
181 block = block->next_block();
182 }
183 return block;
184 }
185
186 LayoutRawBlock* start() { return _start; }
187 void set_start(LayoutRawBlock* start) { _start = start; }
188 LayoutRawBlock* last_block() { return _last; }
189
190 LayoutRawBlock* first_field_block();
191 void add(GrowableArray<LayoutRawBlock*>* list, LayoutRawBlock* start = nullptr);
192 void add_field_at_offset(LayoutRawBlock* blocks, int offset, LayoutRawBlock* start = nullptr);
193 void add_contiguously(GrowableArray<LayoutRawBlock*>* list, LayoutRawBlock* start = nullptr);
194 LayoutRawBlock* insert_field_block(LayoutRawBlock* slot, LayoutRawBlock* block);
195 bool reconstruct_layout(const InstanceKlass* ik);
196 void fill_holes(const InstanceKlass* ik);
197 LayoutRawBlock* insert(LayoutRawBlock* slot, LayoutRawBlock* block);
198 void remove(LayoutRawBlock* block);
199 void print(outputStream* output, bool is_static, const InstanceKlass* super);
200 };
201
202
203 // FieldLayoutBuilder is the main entry point for layout computation.
204 // This class has three methods to generate layout: one for regular classes
205 // and two for classes with hard coded offsets (java,lang.ref.Reference
206 // and the boxing classes). The rationale for having multiple methods
207 // is that each kind of class has a different set goals regarding
208 // its layout, so instead of mixing several layout strategies into a
209 // single method, each kind has its own method (see comments below
210 // for more details about the allocation strategies).
211 //
212 // Computing the layout of a class always goes through 4 steps:
213 // 1 - Prologue: preparation of data structure and gathering of
214 // layout information inherited from super classes
215 // 2 - Field sorting: fields are sorted according to their
216 // kind (oop, primitive, inline class) and their contention
217 // annotation (if any)
218 // 3 - Layout is computed from the set of lists generated during
219 // step 2
220 // 4 - Epilogue: oopmaps are generated, layout information is
221 // prepared so other VM components can use it (instance size,
222 // static field size, non-static field size, etc.)
223 //
224 // Steps 1 and 4 are common to all layout computations. Step 2 and 3
225 // can vary with the allocation strategy.
226 //
227 class FieldLayoutBuilder : public ResourceObj {
228 private:
229
230 const Symbol* _classname;
231 const InstanceKlass* _super_klass;
232 ConstantPool* _constant_pool;
233 GrowableArray<FieldInfo>* _field_info;
234 FieldLayoutInfo* _info;
235 FieldGroup* _root_group;
236 GrowableArray<FieldGroup*> _contended_groups;
237 FieldGroup* _static_fields;
238 FieldLayout* _layout;
239 FieldLayout* _static_layout;
240 int _nonstatic_oopmap_count;
241 int _alignment;
242 bool _has_nonstatic_fields;
243 bool _is_contended; // is a contended class?
244
245 public:
246 FieldLayoutBuilder(const Symbol* classname, const InstanceKlass* super_klass, ConstantPool* constant_pool,
247 GrowableArray<FieldInfo>* field_info, bool is_contended, FieldLayoutInfo* info);
248
249 int get_alignment() {
250 assert(_alignment != -1, "Uninitialized");
251 return _alignment;
252 }
253
254 void build_layout();
255 void compute_regular_layout();
256 void insert_contended_padding(LayoutRawBlock* slot);
257
258 private:
259 void prologue();
260 void epilogue();
261 void regular_field_sorting();
262 FieldGroup* get_or_create_contended_group(int g);
263 };
264
265 #endif // SHARE_CLASSFILE_FIELDLAYOUTBUILDER_HPP
|
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
24
25 #ifndef SHARE_CLASSFILE_FIELDLAYOUTBUILDER_HPP
26 #define SHARE_CLASSFILE_FIELDLAYOUTBUILDER_HPP
27
28 #include "classfile/classFileParser.hpp"
29 #include "classfile/classLoaderData.hpp"
30 #include "memory/allocation.hpp"
31 #include "oops/fieldStreams.hpp"
32 #include "utilities/growableArray.hpp"
33
34 // Classes below are used to compute the field layout of classes.
35
36 // A LayoutRawBlock describes an element of a layout.
37 // Each field is represented by a LayoutRawBlock.
38 // LayoutRawBlocks can also represent elements injected by the JVM:
39 // padding, empty blocks, inherited fields, etc.
40 // All LayoutRawBlocks must have a size and an alignment. The size is the
41 // exact size of the field expressed in bytes. The alignment is
42 // the alignment constraint of the field (1 for byte, 2 for short,
43 // 4 for int, 8 for long, etc.)
44 //
45 // LayoutRawBlock are designed to be used in two data structures:
46 // - a linked list in a layout (using _next_block, _prev_block)
47 // - a GrowableArray in field group (the growable array contains pointers to LayoutRawBlocks)
48 //
49 // next/prev pointers are included in the LayoutRawBlock class to narrow
50 // the number of allocation required during the computation of a layout.
51 //
52 class LayoutRawBlock : public ResourceObj {
53 public:
54 // Some code relies on the order of values below.
55 enum Kind {
56 EMPTY, // empty slot, space is taken from this to allocate fields
57 RESERVED, // reserved for JVM usage (for instance object header)
58 PADDING, // padding (because of alignment constraints or @Contended)
59 REGULAR, // primitive or oop field (including not flat inline type fields)
60 FLAT, // flat field
61 INHERITED, // field(s) inherited from super classes
62 NULL_MARKER, // stores the null marker for a flat field
63 INHERITED_NULL_MARKER // a super-class used this slot to store a null marker
64 };
65
66 private:
67 LayoutRawBlock* _next_block;
68 LayoutRawBlock* _prev_block;
69 InlineKlass* _inline_klass;
70 Kind _kind;
71 int _offset;
72 int _alignment;
73 int _size;
74 int _field_index;
75 int _null_marker_offset;
76 bool _is_reference;
77 bool _needs_null_marker;
78
79 public:
80 LayoutRawBlock(Kind kind, int size);
81
82 LayoutRawBlock(int index, Kind kind, int size, int alignment, bool is_reference = false);
83 LayoutRawBlock* next_block() const { return _next_block; }
84 void set_next_block(LayoutRawBlock* next) { _next_block = next; }
85 LayoutRawBlock* prev_block() const { return _prev_block; }
86 void set_prev_block(LayoutRawBlock* prev) { _prev_block = prev; }
87 Kind kind() const { return _kind; }
88 int offset() const {
89 assert(_offset >= 0, "Must be initialized");
90 return _offset;
91 }
92 void set_offset(int offset) { _offset = offset; }
93 int alignment() const { return _alignment; }
94 int size() const { return _size; }
95 void set_size(int size) { _size = size; }
96 int field_index() const {
97 assert(_field_index != -1, "Must be initialized");
98 return _field_index;
99 }
100 void set_field_index(int field_index) {
101 assert(_field_index == -1, "Must not be initialized");
102 _field_index = field_index;
103 }
104 bool is_reference() const { return _is_reference; }
105 InlineKlass* inline_klass() const {
106 assert(_inline_klass != nullptr, "Must be initialized");
107 return _inline_klass;
108 }
109 void set_inline_klass(InlineKlass* inline_klass) { _inline_klass = inline_klass; }
110 void set_needs_null_marker() { _needs_null_marker = true; }
111 bool needs_null_marker() const { return _needs_null_marker; }
112 void set_null_marker_offset(int offset) {
113 assert(_needs_null_marker, "");
114 _null_marker_offset = offset;
115 _needs_null_marker = false;
116 }
117 int null_marker_offset() const { return _null_marker_offset; }
118
119 bool fit(int size, int alignment);
120
121 static int compare_offset(LayoutRawBlock** x, LayoutRawBlock** y) { return (*x)->offset() - (*y)->offset(); }
122 // compare_size_inverted() returns the opposite of a regular compare method in order to
123 // sort fields in decreasing order.
124 // Note: with line types, the comparison should include alignment constraint if sizes are equals
125 static int compare_size_inverted(LayoutRawBlock** x, LayoutRawBlock** y) {
126 #ifdef _WINDOWS
127 // qsort() on Windows reverse the order of fields with the same size
128 // the extension of the comparison function below preserves this order
129 int diff = (*y)->size() - (*x)->size();
130 if (diff == 0) {
131 diff = (*x)->field_index() - (*y)->field_index();
132 }
133 return diff;
134 #else
135 return (*y)->size() - (*x)->size();
136 #endif // _WINDOWS
137 }
138 };
139
140 // A Field group represents a set of fields that have to be allocated together,
141 // this is the way the @Contended annotation is supported.
142 // Inside a FieldGroup, fields are sorted based on their kind: primitive,
143 // oop, or flat.
144 //
145 class FieldGroup : public ResourceObj {
146
147 private:
148 FieldGroup* _next;
149
150 GrowableArray<LayoutRawBlock*>* _small_primitive_fields;
151 GrowableArray<LayoutRawBlock*>* _big_primitive_fields;
152 GrowableArray<LayoutRawBlock*>* _oop_fields;
153 int _contended_group;
154 int _oop_count;
155 static const int INITIAL_LIST_SIZE = 16;
156
157 public:
158 FieldGroup(int contended_group = -1);
159
160 FieldGroup* next() const { return _next; }
161 void set_next(FieldGroup* next) { _next = next; }
162 GrowableArray<LayoutRawBlock*>* small_primitive_fields() const { return _small_primitive_fields; }
163 GrowableArray<LayoutRawBlock*>* big_primitive_fields() const { return _big_primitive_fields; }
164 GrowableArray<LayoutRawBlock*>* oop_fields() const { return _oop_fields; }
165 int contended_group() const { return _contended_group; }
166 int oop_count() const { return _oop_count; }
167
168 void add_primitive_field(int idx, BasicType type);
169 void add_oop_field(int idx);
170 void add_flat_field(int idx, InlineKlass* vk, bool needs_null_marker);
171 void add_block(LayoutRawBlock** list, LayoutRawBlock* block);
172 void sort_by_size();
173 private:
174 void add_to_small_primitive_list(LayoutRawBlock* block);
175 void add_to_big_primitive_list(LayoutRawBlock* block);
176 };
177
178 // The FieldLayout class represents a set of fields organized
179 // in a layout.
180 // An instance of FieldLayout can either represent the layout
181 // of non-static fields (used in an instance object) or the
182 // layout of static fields (to be included in the class mirror).
183 //
184 // _block is a pointer to a list of LayoutRawBlock ordered by increasing
185 // offsets.
186 // _start points to the LayoutRawBlock with the first offset that can
187 // be used to allocate fields of the current class
188 // _last points to the last LayoutRawBlock of the list. In order to
189 // simplify the code, the LayoutRawBlock list always ends with an
190 // EMPTY block (the kind of LayoutRawBlock from which space is taken
191 // to allocate fields) with a size big enough to satisfy all
192 // field allocations.
193 //
194 class FieldLayout : public ResourceObj {
195 private:
196 GrowableArray<FieldInfo>* _field_info;
197 ConstantPool* _cp;
198 LayoutRawBlock* _blocks; // the layout being computed
199 LayoutRawBlock* _start; // points to the first block where a field can be inserted
200 LayoutRawBlock* _last; // points to the last block of the layout (big empty block)
201 int _super_first_field_offset;
202 int _super_alignment;
203 int _super_min_align_required;
204 bool _super_has_fields;
205 bool _has_missing_null_markers;
206
207 public:
208 FieldLayout(GrowableArray<FieldInfo>* field_info, ConstantPool* cp);
209 void initialize_static_layout();
210 void initialize_instance_layout(const InstanceKlass* ik);
211
212 LayoutRawBlock* first_empty_block() {
213 LayoutRawBlock* block = _start;
214 while (block->kind() != LayoutRawBlock::EMPTY) {
215 block = block->next_block();
216 }
217 return block;
218 }
219
220 LayoutRawBlock* blocks() const { return _blocks; }
221
222 LayoutRawBlock* start() const { return _start; }
223 void set_start(LayoutRawBlock* start) { _start = start; }
224 LayoutRawBlock* last_block() const { return _last; }
225 int super_first_field_offset() const { return _super_first_field_offset; }
226 int super_alignment() const { return _super_alignment; }
227 int super_min_align_required() const { return _super_min_align_required; }
228 bool super_has_fields() const { return _super_has_fields; }
229 bool has_missing_null_markers() const { return _has_missing_null_markers; }
230
231 LayoutRawBlock* first_field_block();
232 void add(GrowableArray<LayoutRawBlock*>* list, LayoutRawBlock* start = nullptr);
233 void add_field_at_offset(LayoutRawBlock* blocks, int offset, LayoutRawBlock* start = nullptr);
234 void add_contiguously(GrowableArray<LayoutRawBlock*>* list, LayoutRawBlock* start = nullptr);
235 LayoutRawBlock* insert_field_block(LayoutRawBlock* slot, LayoutRawBlock* block);
236 bool reconstruct_layout(const InstanceKlass* ik);
237 void fill_holes(const InstanceKlass* ik);
238 LayoutRawBlock* insert(LayoutRawBlock* slot, LayoutRawBlock* block);
239 void remove(LayoutRawBlock* block);
240 void print(outputStream* output, bool is_static, const InstanceKlass* super, Array<InlineKlass*>* inline_fields);
241 };
242
243
244 // FieldLayoutBuilder is the main entry point for layout computation.
245 // This class has two methods to generate layout: one for identity classes
246 // and one for inline classes. The rational for having two methods
247 // is that each kind of classes has a different set goals regarding
248 // its layout, so instead of mixing two layout strategies into a
249 // single method, each kind has its own method (see comments below
250 // for more details about the allocation strategies).
251 //
252 // Computing the layout of a class always goes through 4 steps:
253 // 1 - Prologue: preparation of data structure and gathering of
254 // layout information inherited from super classes
255 // 2 - Field sorting: fields are sorted according to their
256 // kind (oop, primitive, inline class) and their contention
257 // annotation (if any)
258 // 3 - Layout is computed from the set of lists generated during
259 // step 2
260 // 4 - Epilogue: oopmaps are generated, layout information is
261 // prepared so other VM components can use it (instance size,
262 // static field size, non-static field size, etc.)
263 //
264 // Steps 1 and 4 are common to all layout computations. Step 2 and 3
265 // differ for inline classes and identity classes.
266 //
267 class FieldLayoutBuilder : public ResourceObj {
268 private:
269 const Symbol* _classname;
270 ClassLoaderData* _loader_data;
271 const InstanceKlass* _super_klass;
272 ConstantPool* _constant_pool;
273 GrowableArray<FieldInfo>* _field_info;
274 FieldLayoutInfo* _info;
275 Array<InlineKlass*>* _inline_type_field_klasses;
276 FieldGroup* _root_group;
277 GrowableArray<FieldGroup*> _contended_groups;
278 FieldGroup* _static_fields;
279 FieldLayout* _layout;
280 FieldLayout* _static_layout;
281 int _nonstatic_oopmap_count;
282 int _alignment;
283 int _first_field_offset;
284 int _internal_null_marker_offset; // if any, -1 means no internal null marker
285 int _payload_size_in_bytes;
286 int _atomic_field_count;
287 int _fields_size_sum;
288 bool _has_nonstatic_fields;
289 bool _has_inline_type_fields;
290 bool _is_contended;
291 bool _is_inline_type;
292 bool _is_abstract_value;
293 bool _has_flattening_information;
294 bool _has_nonatomic_values;
295 bool _nullable_atomic_flat_candidate;
296 bool _has_null_markers;
297
298 FieldGroup* get_or_create_contended_group(int g);
299
300 public:
301 FieldLayoutBuilder(const Symbol* classname, ClassLoaderData* loader_data, const InstanceKlass* super_klass, ConstantPool* constant_pool,
302 GrowableArray<FieldInfo>* field_info, bool is_contended, bool is_inline_type, bool is_abstract_value,
303 FieldLayoutInfo* info, Array<InlineKlass*>* inline_type_field_klasses);
304
305 int get_alignment() {
306 assert(_alignment != -1, "Uninitialized");
307 return _alignment;
308 }
309
310 int get_first_field_offset() {
311 assert(_first_field_offset != -1, "Uninitialized");
312 return _first_field_offset;
313 }
314
315 int get_payload_size_in_byte() {
316 assert(_payload_size_in_bytes != -1, "Uninitialized");
317 return _payload_size_in_bytes;
318 }
319
320 int get_internal_null_marker_offset() {
321 return _internal_null_marker_offset;
322 }
323
324 void build_layout();
325 void compute_regular_layout();
326 void compute_inline_class_layout();
327 void insert_contended_padding(LayoutRawBlock* slot);
328 void insert_null_markers();
329
330 protected:
331 void prologue();
332 void epilogue();
333 void regular_field_sorting();
334 void inline_class_field_sorting();
335 void add_flat_field_oopmap(OopMapBlocksBuilder* nonstatic_oop_map, InlineKlass* vk, int offset);
336 void register_embedded_oops_from_list(OopMapBlocksBuilder* nonstatic_oop_maps, GrowableArray<LayoutRawBlock*>* list);
337 void register_embedded_oops(OopMapBlocksBuilder* nonstatic_oop_maps, FieldGroup* group);
338 };
339
340 #endif // SHARE_CLASSFILE_FIELDLAYOUTBUILDER_HPP
|