1 /* 2 * Copyright (c) 2019, 2019, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 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.inline.hpp" 30 #include "utilities/growableArray.hpp" 31 32 /* Classes below are used to compute the field layout of classes. */ 33 34 35 /* A RawBlock describes an element of a layout. 36 * Each field is represented by a RawBlock. 37 * RawBlocks can also represent elements injected by the JVM: 38 * padding, empty blocks, inherited fields, etc. 39 * All RawBlock must have a size and a alignment. The size is the 40 * exact size of the field expressed in bytes. The alignment is 41 * the alignment constraint of the field (1 for byte, 2 for short, 42 * 4 for int, 8 for long, etc.) 43 * 44 * RawBlock are designed to be inserted in two linked list: 45 * - a field group (using _next_field, _prev_field) 46 * - a layout (using _next_block, _prev_block) 47 * 48 * next/prev pointers are included in the RawBlock class to narrow 49 * the number of allocation required during the computation of a layout. 50 */ 51 class RawBlock : public ResourceObj { 52 public: 53 // Some code relies on the order of values below. 54 enum Kind { 55 EMPTY, // empty slot, space is taken from this to allocate fields 56 RESERVED, // reserved for JVM usage (for instance object header) 57 PADDING, // padding (because of alignment constraints or @Contended) 58 REGULAR, // primitive or oop field (including non-flattened inline fields) 59 FLATTENED, // flattened field 60 INHERITED // field(s) inherited from super classes 61 }; 62 63 private: 64 RawBlock* _next_field; 65 RawBlock* _prev_field; 66 RawBlock* _next_block; 67 RawBlock* _prev_block; 68 Kind _kind; 69 int _offset; 70 int _alignment; 71 int _size; 72 int _field_index; 73 bool _is_reference; 74 ValueKlass* _value_klass; 75 76 public: 77 RawBlock(Kind kind, int size); 78 RawBlock(int index, Kind kind, int size, int alignment, bool is_reference); 79 RawBlock* next_field() const { return _next_field; } 80 void set_next_field(RawBlock* next) { _next_field = next; } 81 RawBlock* prev_field() const { return _prev_field; } 82 void set_prev_field(RawBlock* prev) { _prev_field = prev; } 83 RawBlock* next_block() const { return _next_block; } 84 void set_next_block(RawBlock* next) { _next_block = next; } 85 RawBlock* prev_block() const { return _prev_block; } 86 void set_prev_block(RawBlock* prev) { _prev_block = prev; } 87 Kind kind() const { return _kind; } 88 int offset() const { 89 assert(_offset >= 0, "Mut 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 bool is_reference() const { return _is_reference; } 101 ValueKlass* value_klass() const { 102 assert(_value_klass != NULL, "Must be initialized"); 103 return _value_klass; 104 } 105 void set_value_klass(ValueKlass* value_klass) { _value_klass = value_klass; } 106 107 bool fit(int size, int alignment); 108 109 }; 110 111 /* A Field group represents a set of fields that have to be allocated together, 112 * this is the way the @Contended annotation is supported. 113 * Inside a FieldGroup, fields are sorted based on their kind: primitive, 114 * oop, or flattened. 115 * 116 */ 117 class FieldGroup : public ResourceObj { 118 119 private: 120 FieldGroup* _next; 121 RawBlock* _primitive_fields; 122 RawBlock* _oop_fields; 123 RawBlock* _flattened_fields; 124 int _contended_group; 125 int _oop_count; 126 127 public: 128 FieldGroup(int contended_group = -1); 129 130 FieldGroup* next() const { return _next; } 131 void set_next(FieldGroup* next) { _next = next; } 132 RawBlock* primitive_fields() const { return _primitive_fields; } 133 RawBlock* oop_fields() const { return _oop_fields; } 134 RawBlock* flattened_fields() const { return _flattened_fields; } 135 int contended_group() const { return _contended_group; } 136 int oop_count() const { return _oop_count; } 137 138 void add_primitive_field(AllFieldStream fs, BasicType type); 139 void add_oop_field(AllFieldStream fs); 140 void add_flattened_field(AllFieldStream fs, ValueKlass* vk); 141 void add_block(RawBlock** list, RawBlock* block); 142 }; 143 144 /* The FieldLayout class represents a set of fields organized 145 * in a layout. 146 * An instance of FieldLayout can either represent the layout 147 * of non-static fields (used in an instance object) or the 148 * layout of static fields (to be included in the class mirror). 149 * 150 * _block is a pointer to a list of RawBlock ordered by increasing 151 * offsets. 152 * _start points to the RawBlock with the first offset that can 153 * be used to allocate fields of the current class 154 * _last points to the last RawBlock of the list. In order to 155 * simplify the code, the RawBlock list always ends with an 156 * EMPTY block (the kind of RawBlock from which space is taken 157 * to allocate fields) with a size big enough to satisfy all 158 * field allocations. 159 */ 160 class FieldLayout : public ResourceObj { 161 private: 162 Array<u2>* _fields; 163 ConstantPool* _cp; 164 RawBlock* _blocks; 165 RawBlock* _start; 166 RawBlock* _last; 167 168 public: 169 FieldLayout(Array<u2>* fields, ConstantPool* cp); 170 void initialize_static_layout(); 171 void initialize_instance_layout(const InstanceKlass* ik); 172 173 RawBlock* first_empty_block() { 174 RawBlock* block = _start; 175 while (block->kind() != RawBlock::EMPTY) { 176 block = block->next_block(); 177 } 178 return block; 179 } 180 181 RawBlock* start() { return _start; } 182 void set_start(RawBlock* start) { _start = start; } 183 RawBlock* last_block() { return _last; } 184 185 RawBlock* first_field_block(); 186 void add(RawBlock* blocks, RawBlock* start = NULL); 187 void add_contiguously(RawBlock* blocks, RawBlock* start = NULL); 188 RawBlock* insert_field_block(RawBlock* slot, RawBlock* block); 189 void reconstruct_layout(const InstanceKlass* ik); 190 void fill_holes(const InstanceKlass* ik); 191 RawBlock* insert(RawBlock* slot, RawBlock* block); 192 void insert_per_offset(RawBlock* block); 193 void remove(RawBlock* block); 194 void print(outputStream* output); 195 }; 196 197 198 /* FieldLayoutBuilder is the main entry point for layout computation. 199 * This class has two methods to generate layout: one for identity classes 200 * and one for inline classes. The rational for having two methods 201 * is that each kind of classes has a different set goals regarding 202 * its layout, so instead of mixing two layout strategies into a 203 * single method, each kind has its own method (see comments below 204 * for more details about the allocation strategies). 205 * 206 * Computing the layout of a class always goes through 4 steps: 207 * 1 - Prologue: preparation of data structure and gathering of 208 * layout information inherited from super classes 209 * 2 - Field sorting: fields are sorted out according to their 210 * kind (oop, primitive, inline class) and their contention 211 * annotation (if any) 212 * 3 - Layout is computed from the set of lists generated during 213 * step 2 214 * 4 - Epilogue: oopmaps are generated, layout information are 215 * prepared so other VM components can use them (instance size, 216 * static field size, non-static field size, etc.) 217 * 218 * Steps 1 and 4 are common to all layout computations. Step 2 and 3 219 * differ for inline classes and identity classes. 220 */ 221 class FieldLayoutBuilder : public ResourceObj { 222 private: 223 ClassFileParser* _cfp; 224 FieldLayoutInfo* _info; 225 RawBlock* _fields; 226 FieldGroup* _root_group; 227 FieldGroup* _contended_groups; 228 FieldGroup* _static_fields; 229 FieldLayout* _layout; 230 FieldLayout* _static_layout; 231 int _nonstatic_oopmap_count; 232 int _alignment; 233 int _first_field_offset; 234 int _exact_size_in_bytes; 235 bool _has_nonstatic_fields; 236 bool _has_flattening_information; 237 238 FieldGroup* get_or_create_contended_group(int g); 239 240 public: 241 FieldLayoutBuilder(ClassFileParser* cfp, FieldLayoutInfo* info); 242 243 int get_alignment() { 244 assert(_alignment != -1, "Uninitialized"); 245 return _alignment; 246 } 247 248 int get_first_field_offset() { 249 assert(_first_field_offset != -1, "Uninitialized"); 250 return _first_field_offset; 251 } 252 253 int get_exact_size_in_byte() { 254 assert(_exact_size_in_bytes != -1, "Uninitialized"); 255 return _exact_size_in_bytes; 256 } 257 258 void compute_regular_layout(TRAPS); 259 void compute_inline_class_layout(TRAPS); 260 261 protected: 262 void prologue(); 263 void epilogue(); 264 void regular_field_sorting(TRAPS); 265 void inline_class_field_sorting(TRAPS); 266 void add_flattened_field_oopmap(OopMapBlocksBuilder* nonstatic_oop_map, ValueKlass* vk, int offset); 267 }; 268 269 #endif // SHARE_CLASSFILE_FIELDLAYOUTBUILDER_HPP