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 };
63
64 private:
65 LayoutRawBlock* _next_block;
66 LayoutRawBlock* _prev_block;
67 InlineKlass* _inline_klass;
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 InlineKlass* inline_klass() const {
97 assert(_inline_klass != nullptr, "Must be initialized");
98 return _inline_klass;
99 }
100 void set_inline_klass(InlineKlass* inline_klass) { _inline_klass = inline_klass; }
101
102 bool fit(int size, int alignment);
103
104 static int compare_offset(LayoutRawBlock** x, LayoutRawBlock** y) { return (*x)->offset() - (*y)->offset(); }
105 // compare_size_inverted() returns the opposite of a regular compare method in order to
106 // sort fields in decreasing order.
107 // Note: with line types, the comparison should include alignment constraint if sizes are equals
108 static int compare_size_inverted(LayoutRawBlock** x, LayoutRawBlock** y) {
109 #ifdef _WINDOWS
110 // qsort() on Windows reverse the order of fields with the same size
111 // the extension of the comparison function below preserves this order
112 int diff = (*y)->size() - (*x)->size();
113 if (diff == 0) {
114 diff = (*x)->field_index() - (*y)->field_index();
115 }
116 return diff;
117 #else
118 return (*y)->size() - (*x)->size();
119 #endif // _WINDOWS
120 }
121 };
122
123 // A Field group represents a set of fields that have to be allocated together,
124 // this is the way the @Contended annotation is supported.
125 // Inside a FieldGroup, fields are sorted based on their kind: primitive,
126 // oop, or flat.
127 //
128 class FieldGroup : public ResourceObj {
129
130 private:
131 FieldGroup* _next;
132
133 GrowableArray<LayoutRawBlock*>* _small_primitive_fields;
134 GrowableArray<LayoutRawBlock*>* _big_primitive_fields;
135 GrowableArray<LayoutRawBlock*>* _oop_fields;
136 int _contended_group;
137 int _oop_count;
138 static const int INITIAL_LIST_SIZE = 16;
139
140 public:
141 FieldGroup(int contended_group = -1);
142
143 FieldGroup* next() const { return _next; }
144 void set_next(FieldGroup* next) { _next = next; }
145 GrowableArray<LayoutRawBlock*>* small_primitive_fields() const { return _small_primitive_fields; }
146 GrowableArray<LayoutRawBlock*>* big_primitive_fields() const { return _big_primitive_fields; }
147 GrowableArray<LayoutRawBlock*>* oop_fields() const { return _oop_fields; }
148 int contended_group() const { return _contended_group; }
149 int oop_count() const { return _oop_count; }
150
151 void add_primitive_field(int idx, BasicType type);
152 void add_oop_field(int idx);
153 void add_flat_field(int idx, InlineKlass* vk);
154 void add_block(LayoutRawBlock** list, LayoutRawBlock* block);
155 void sort_by_size();
156 private:
157 void add_to_small_primitive_list(LayoutRawBlock* block);
158 void add_to_big_primitive_list(LayoutRawBlock* block);
159 };
160
161 // The FieldLayout class represents a set of fields organized
162 // in a layout.
163 // An instance of FieldLayout can either represent the layout
164 // of non-static fields (used in an instance object) or the
165 // layout of static fields (to be included in the class mirror).
166 //
167 // _block is a pointer to a list of LayoutRawBlock ordered by increasing
168 // offsets.
169 // _start points to the LayoutRawBlock with the first offset that can
170 // be used to allocate fields of the current class
171 // _last points to the last LayoutRawBlock of the list. In order to
172 // simplify the code, the LayoutRawBlock list always ends with an
173 // EMPTY block (the kind of LayoutRawBlock from which space is taken
174 // to allocate fields) with a size big enough to satisfy all
175 // field allocations.
176 //
177 class FieldLayout : public ResourceObj {
178 private:
179 GrowableArray<FieldInfo>* _field_info;
180 ConstantPool* _cp;
181 LayoutRawBlock* _blocks; // the layout being computed
182 LayoutRawBlock* _start; // points to the first block where a field can be inserted
183 LayoutRawBlock* _last; // points to the last block of the layout (big empty block)
184
185 public:
186 FieldLayout(GrowableArray<FieldInfo>* field_info, ConstantPool* cp);
187 void initialize_static_layout();
188 void initialize_instance_layout(const InstanceKlass* ik);
189
190 LayoutRawBlock* first_empty_block() {
191 LayoutRawBlock* block = _start;
192 while (block->kind() != LayoutRawBlock::EMPTY) {
193 block = block->next_block();
194 }
195 return block;
196 }
197
198 LayoutRawBlock* blocks() { return _blocks; }
199
200 LayoutRawBlock* start() { return _start; }
201 void set_start(LayoutRawBlock* start) { _start = start; }
202 LayoutRawBlock* last_block() { return _last; }
203
204 LayoutRawBlock* first_field_block();
205 void add(GrowableArray<LayoutRawBlock*>* list, LayoutRawBlock* start = nullptr);
206 void add_field_at_offset(LayoutRawBlock* blocks, int offset, LayoutRawBlock* start = nullptr);
207 void add_contiguously(GrowableArray<LayoutRawBlock*>* list, LayoutRawBlock* start = nullptr);
208 LayoutRawBlock* insert_field_block(LayoutRawBlock* slot, LayoutRawBlock* block);
209 bool reconstruct_layout(const InstanceKlass* ik);
210 void fill_holes(const InstanceKlass* ik);
211 LayoutRawBlock* insert(LayoutRawBlock* slot, LayoutRawBlock* block);
212 void remove(LayoutRawBlock* block);
213 void print(outputStream* output, bool is_static, const InstanceKlass* super);
214 };
215
216
217 // FieldLayoutBuilder is the main entry point for layout computation.
218 // This class has two methods to generate layout: one for identity classes
219 // and one for inline classes. The rational for having two methods
220 // is that each kind of classes has a different set goals regarding
221 // its layout, so instead of mixing two layout strategies into a
222 // single method, each kind has its own method (see comments below
223 // for more details about the allocation strategies).
224 //
225 // Computing the layout of a class always goes through 4 steps:
226 // 1 - Prologue: preparation of data structure and gathering of
227 // layout information inherited from super classes
228 // 2 - Field sorting: fields are sorted according to their
229 // kind (oop, primitive, inline class) and their contention
230 // annotation (if any)
231 // 3 - Layout is computed from the set of lists generated during
232 // step 2
233 // 4 - Epilogue: oopmaps are generated, layout information is
234 // prepared so other VM components can use it (instance size,
235 // static field size, non-static field size, etc.)
236 //
237 // Steps 1 and 4 are common to all layout computations. Step 2 and 3
238 // differ for inline classes and identity classes.
239 //
240 class FieldLayoutBuilder : public ResourceObj {
241 private:
242 const Symbol* _classname;
243 const InstanceKlass* _super_klass;
244 ConstantPool* _constant_pool;
245 GrowableArray<FieldInfo>* _field_info;
246 FieldLayoutInfo* _info;
247 Array<InlineKlass*>* _inline_type_field_klasses;
248 FieldGroup* _root_group;
249 GrowableArray<FieldGroup*> _contended_groups;
250 FieldGroup* _static_fields;
251 FieldLayout* _layout;
252 FieldLayout* _static_layout;
253 int _nonstatic_oopmap_count;
254 int _alignment;
255 int _first_field_offset;
256 int _exact_size_in_bytes;
257 int _atomic_field_count;
258 int _fields_size_sum;
259 bool _has_nonstatic_fields;
260 bool _has_inline_type_fields;
261 bool _is_contended;
262 bool _is_inline_type;
263 bool _has_flattening_information;
264 bool _has_nonatomic_values;
265 bool _nullable_atomic_flat_candidate;
266
267 FieldGroup* get_or_create_contended_group(int g);
268
269 public:
270 FieldLayoutBuilder(const Symbol* classname, const InstanceKlass* super_klass, ConstantPool* constant_pool,
271 GrowableArray<FieldInfo>* field_info, bool is_contended, bool is_inline_type, FieldLayoutInfo* info,
272 Array<InlineKlass*>* inline_type_field_klasses);
273
274 int get_alignment() {
275 assert(_alignment != -1, "Uninitialized");
276 return _alignment;
277 }
278
279 int get_first_field_offset() {
280 assert(_first_field_offset != -1, "Uninitialized");
281 return _first_field_offset;
282 }
283
284 int get_exact_size_in_byte() {
285 assert(_exact_size_in_bytes != -1, "Uninitialized");
286 return _exact_size_in_bytes;
287 }
288
289 void build_layout(TRAPS);
290 void compute_regular_layout(TRAPS);
291 void compute_inline_class_layout(TRAPS);
292 void insert_contended_padding(LayoutRawBlock* slot);
293
294 protected:
295 void prologue();
296 void epilogue();
297 void regular_field_sorting(TRAPS);
298 void inline_class_field_sorting(TRAPS);
299 void add_flat_field_oopmap(OopMapBlocksBuilder* nonstatic_oop_map, InlineKlass* vk, int offset);
300 void register_embedded_oops_from_list(OopMapBlocksBuilder* nonstatic_oop_maps, GrowableArray<LayoutRawBlock*>* list);
301 void register_embedded_oops(OopMapBlocksBuilder* nonstatic_oop_maps, FieldGroup* group);
302 };
303
304 #endif // SHARE_CLASSFILE_FIELDLAYOUTBUILDER_HPP
|