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   bool _has_nonatomic_values;
 260   int _atomic_field_count;
 261 
 262   FieldGroup* get_or_create_contended_group(int g);
 263 
 264  public:
 265   FieldLayoutBuilder(const Symbol* classname, const InstanceKlass* super_klass, ConstantPool* constant_pool,
 266       Array<u2>* fields, bool is_contended, bool is_value_type, ClassLoaderData* class_loader_data,
 267       Handle protection_domain, FieldLayoutInfo* info);
 268 
 269   int get_alignment() {
 270     assert(_alignment != -1, "Uninitialized");
 271     return _alignment;
 272   }
 273 
 274   int get_first_field_offset() {
 275     assert(_first_field_offset != -1, "Uninitialized");
 276     return _first_field_offset;
 277   }
 278 
 279   int get_exact_size_in_byte() {
 280     assert(_exact_size_in_bytes != -1, "Uninitialized");
 281     return _exact_size_in_bytes;
 282   }
 283 
 284   void build_layout(TRAPS);
 285   void compute_regular_layout();
 286   void compute_java_lang_ref_Reference_layout();
 287   void compute_boxing_class_layout();
 288   void compute_inline_class_layout(TRAPS);
 289   void insert_contended_padding(LayoutRawBlock* slot);
 290 
 291  protected:
 292   void prologue();
 293   void epilogue();
 294   void regular_field_sorting();
 295   void inline_class_field_sorting(TRAPS);
 296   void add_flattened_field_oopmap(OopMapBlocksBuilder* nonstatic_oop_map, ValueKlass* vk, int offset);
 297 };
 298 
 299 #endif // SHARE_CLASSFILE_FIELDLAYOUTBUILDER_HPP