1 /* 2 * Copyright (c) 2019, 2020, 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.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 non-flattened inline fields) 60 FLATTENED, // flattened field 61 INHERITED // field(s) inherited from super classes 62 }; 63 64 private: 65 LayoutRawBlock* _next_block; 66 LayoutRawBlock* _prev_block; 67 ValueKlass* _value_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 ValueKlass* value_klass() const { 97 assert(_value_klass != NULL, "Must be initialized"); 98 return _value_klass; 99 } 100 void set_value_klass(ValueKlass* value_klass) { _value_klass = value_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 flattened. 127 // 128 class FieldGroup : public ResourceObj { 129 130 private: 131 FieldGroup* _next; 132 133 GrowableArray<LayoutRawBlock*>* _primitive_fields; 134 GrowableArray<LayoutRawBlock*>* _oop_fields; 135 GrowableArray<LayoutRawBlock*>* _flattened_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*>* primitive_fields() const { return _primitive_fields; } 146 GrowableArray<LayoutRawBlock*>* oop_fields() const { return _oop_fields; } 147 GrowableArray<LayoutRawBlock*>* flattened_fields() const { return _flattened_fields; } 148 int contended_group() const { return _contended_group; } 149 int oop_count() const { return _oop_count; } 150 151 void add_primitive_field(AllFieldStream fs, BasicType type); 152 void add_oop_field(AllFieldStream fs); 153 void add_flattened_field(AllFieldStream fs, ValueKlass* vk); 154 void add_block(LayoutRawBlock** list, LayoutRawBlock* block); 155 void sort_by_size(); 156 }; 157 158 // The FieldLayout class represents a set of fields organized 159 // in a layout. 160 // An instance of FieldLayout can either represent the layout 161 // of non-static fields (used in an instance object) or the 162 // layout of static fields (to be included in the class mirror). 163 // 164 // _block is a pointer to a list of LayoutRawBlock ordered by increasing 165 // offsets. 166 // _start points to the LayoutRawBlock with the first offset that can 167 // be used to allocate fields of the current class 168 // _last points to the last LayoutRawBlock of the list. In order to 169 // simplify the code, the LayoutRawBlock list always ends with an 170 // EMPTY block (the kind of LayoutRawBlock from which space is taken 171 // to allocate fields) with a size big enough to satisfy all 172 // field allocations. 173 // 174 class FieldLayout : public ResourceObj { 175 private: 176 Array<u2>* _fields; 177 ConstantPool* _cp; 178 LayoutRawBlock* _blocks; // the layout being computed 179 LayoutRawBlock* _start; // points to the first block where a field can be inserted 180 LayoutRawBlock* _last; // points to the last block of the layout (big empty block) 181 182 public: 183 FieldLayout(Array<u2>* fields, ConstantPool* cp); 184 void initialize_static_layout(); 185 void initialize_instance_layout(const InstanceKlass* ik); 186 187 LayoutRawBlock* first_empty_block() { 188 LayoutRawBlock* block = _start; 189 while (block->kind() != LayoutRawBlock::EMPTY) { 190 block = block->next_block(); 191 } 192 return block; 193 } 194 195 LayoutRawBlock* blocks() { return _blocks; } 196 197 LayoutRawBlock* start() { return _start; } 198 void set_start(LayoutRawBlock* start) { _start = start; } 199 LayoutRawBlock* last_block() { return _last; } 200 201 LayoutRawBlock* first_field_block(); 202 void add(GrowableArray<LayoutRawBlock*>* list, LayoutRawBlock* start = NULL); 203 void add_field_at_offset(LayoutRawBlock* blocks, int offset, LayoutRawBlock* start = NULL); 204 void add_contiguously(GrowableArray<LayoutRawBlock*>* list, LayoutRawBlock* start = NULL); 205 LayoutRawBlock* insert_field_block(LayoutRawBlock* slot, LayoutRawBlock* block); 206 bool reconstruct_layout(const InstanceKlass* ik); 207 void fill_holes(const InstanceKlass* ik); 208 LayoutRawBlock* insert(LayoutRawBlock* slot, LayoutRawBlock* block); 209 void remove(LayoutRawBlock* block); 210 void print(outputStream* output, bool is_static, const InstanceKlass* super); 211 }; 212 213 214 // FieldLayoutBuilder is the main entry point for layout computation. 215 // This class has two methods to generate layout: one for identity classes 216 // and one for inline classes. The rational for having two methods 217 // is that each kind of classes has a different set goals regarding 218 // its layout, so instead of mixing two layout strategies into a 219 // single method, each kind has its own method (see comments below 220 // for more details about the allocation strategies). 221 // 222 // Computing the layout of a class always goes through 4 steps: 223 // 1 - Prologue: preparation of data structure and gathering of 224 // layout information inherited from super classes 225 // 2 - Field sorting: fields are sorted according to their 226 // kind (oop, primitive, inline class) and their contention 227 // annotation (if any) 228 // 3 - Layout is computed from the set of lists generated during 229 // step 2 230 // 4 - Epilogue: oopmaps are generated, layout information is 231 // prepared so other VM components can use it (instance size, 232 // static field size, non-static field size, etc.) 233 // 234 // Steps 1 and 4 are common to all layout computations. Step 2 and 3 235 // differ for inline classes and identity classes. 236 // 237 class FieldLayoutBuilder : public ResourceObj { 238 private: 239 const Symbol* _classname; 240 const InstanceKlass* _super_klass; 241 ConstantPool* _constant_pool; 242 Array<u2>* _fields; 243 FieldLayoutInfo* _info; 244 FieldGroup* _root_group; 245 GrowableArray<FieldGroup*> _contended_groups; 246 FieldGroup* _static_fields; 247 FieldLayout* _layout; 248 FieldLayout* _static_layout; 249 ClassLoaderData* _class_loader_data; 250 Handle _protection_domain; 251 int _nonstatic_oopmap_count; 252 int _alignment; 253 int _first_field_offset; 254 int _exact_size_in_bytes; 255 bool _has_nonstatic_fields; 256 bool _is_contended; 257 bool _is_value_type; 258 bool _has_flattening_information; 259 260 FieldGroup* get_or_create_contended_group(int g); 261 262 public: 263 FieldLayoutBuilder(const Symbol* classname, const InstanceKlass* super_klass, ConstantPool* constant_pool, 264 Array<u2>* fields, bool is_contended, bool is_value_type, ClassLoaderData* class_loader_data, 265 Handle protection_domain, FieldLayoutInfo* info); 266 267 int get_alignment() { 268 assert(_alignment != -1, "Uninitialized"); 269 return _alignment; 270 } 271 272 int get_first_field_offset() { 273 assert(_first_field_offset != -1, "Uninitialized"); 274 return _first_field_offset; 275 } 276 277 int get_exact_size_in_byte() { 278 assert(_exact_size_in_bytes != -1, "Uninitialized"); 279 return _exact_size_in_bytes; 280 } 281 282 void build_layout(TRAPS); 283 void compute_regular_layout(); 284 void compute_java_lang_ref_Reference_layout(); 285 void compute_boxing_class_layout(); 286 void compute_inline_class_layout(TRAPS); 287 void insert_contended_padding(LayoutRawBlock* slot); 288 289 protected: 290 void prologue(); 291 void epilogue(); 292 void regular_field_sorting(); 293 void inline_class_field_sorting(TRAPS); 294 void add_flattened_field_oopmap(OopMapBlocksBuilder* nonstatic_oop_map, ValueKlass* vk, int offset); 295 }; 296 297 #endif // SHARE_CLASSFILE_FIELDLAYOUTBUILDER_HPP