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   enum Kind {
  54     EMPTY,         // empty slot, space is taken from this to allocate fields
  55     RESERVED,      // reserved for JVM usage (for instance object header)
  56     PADDING,       // padding (because of alignment constraints or @Contended)
  57     REGULAR,       // primitive or oop field (including non-flattened inline fields)
  58     FLATTENED,     // flattened field
  59     INHERITED      // field(s) inherited from super classes
  60   };
  61 
  62  private:
  63   RawBlock* _next_field;
  64   RawBlock* _prev_field;
  65   RawBlock* _next_block;
  66   RawBlock* _prev_block;
  67   Kind _kind;
  68   int _offset;
  69   int _alignment;
  70   int _size;
  71   int _field_index;
  72   bool _is_reference;
  73   ValueKlass* _value_klass;
  74 
  75  public:
  76   RawBlock(Kind kind, int size = -1, int alignment = 1);
  77   RawBlock(int index, Kind kind, int size = -1, int alignment = -1, bool is_reference = false);
  78   RawBlock* next_field() const { return _next_field; }
  79   void set_next_field(RawBlock* next) { _next_field = next; }
  80   RawBlock* prev_field() const { return _prev_field; }
  81   void set_prev_field(RawBlock* prev) { _prev_field = prev; }
  82   RawBlock* next_block() const { return _next_block; }
  83   void set_next_block(RawBlock* next) { _next_block = next; }
  84   RawBlock* prev_block() const { return _prev_block; }
  85   void set_prev_block(RawBlock* prev) { _prev_block = prev; }
  86   Kind kind() const { return _kind; }
  87   int offset() const {
  88     assert(_offset >= 0, "Mut be initialized");
  89     return _offset;
  90   }
  91   void set_offset(int offset) { _offset = offset; }
  92   int alignment() const { return _alignment; }
  93   int size() const { return _size; }
  94   void set_size(int size) { _size = size; }
  95   int field_index() const {
  96     assert(_field_index != -1, "Must be initialized");
  97     return _field_index;
  98   }
  99   bool is_reference() const { return _is_reference; }
 100   ValueKlass* value_klass() const {
 101     assert(_value_klass != NULL, "Must be initialized");
 102     return _value_klass;
 103   }
 104   void set_value_klass(ValueKlass* value_klass) { _value_klass = value_klass; }
 105 
 106   bool fit(int size, int alignment);
 107 
 108 };
 109 
 110 /* A Field group represents a set of fields that have to be allocated together,
 111  * this is the way the @Contended annotation is supported.
 112  * Inside a FieldGroup, fields are sorted based on their kind: primitive,
 113  * oop, or flattened.
 114  *
 115  */
 116 class FieldGroup : public ResourceObj {
 117 
 118  private:
 119   FieldGroup* _next;
 120   RawBlock* _primitive_fields;
 121   RawBlock* _oop_fields;
 122   RawBlock* _flattened_fields;
 123   int _contended_group;
 124   int _oop_count;
 125 
 126  public:
 127   FieldGroup(int contended_group = -1);
 128 
 129   FieldGroup* next() const { return _next; }
 130   void set_next(FieldGroup* next) { _next = next; }
 131   RawBlock* primitive_fields() const { return _primitive_fields; }
 132   RawBlock* oop_fields() const { return _oop_fields; }
 133   RawBlock* flattened_fields() const { return _flattened_fields; }
 134   int contended_group() const { return _contended_group; }
 135   int oop_count() const { return _oop_count; }
 136 
 137   void add_primitive_field(AllFieldStream fs, BasicType type);
 138   void add_oop_field(AllFieldStream fs);
 139   void add_flattened_field(AllFieldStream fs, ValueKlass* vk);
 140   void add_block(RawBlock** list, RawBlock* block);
 141 };
 142 
 143 /* The FieldLayout class represents a set of fields organized
 144  * in a layout.
 145  * An instance of FieldLayout can either represent the layout
 146  * of non-static fields (used in an instance object) or the
 147  * layout of static fields (to be included in the class mirror).
 148  *
 149  * _block is a pointer to a list of RawBlock ordered by increasing
 150  * offsets.
 151  * _start points to the RawBlock with the first offset that can
 152  * be used to allocate fields of the current class
 153  * _last points to the last RawBlock of the list. In order to
 154  * simplify the code, the RawBlock list always ends with an
 155  * EMPTY block (the kind of RawBlock from which space is taken
 156  * to allocate fields) with a size big enough to satisfy all
 157  * field allocations.
 158  */
 159 class FieldLayout : public ResourceObj {
 160  private:
 161   Array<u2>* _fields;
 162   ConstantPool* _cp;
 163   RawBlock* _blocks;
 164   RawBlock* _start;
 165   RawBlock* _last;
 166 
 167  public:
 168   FieldLayout(Array<u2>* fields, ConstantPool* cp);
 169   void initialize_static_layout();
 170   void initialize_instance_layout(const InstanceKlass* ik);
 171 
 172   RawBlock* first_empty_block() {
 173     RawBlock* block = _start;
 174     while (block->kind() != RawBlock::EMPTY) {
 175       block = block->next_block();
 176     }
 177     return block;
 178   }
 179 
 180   RawBlock* start() { return _start; }
 181   void set_start(RawBlock* start) { _start = start; }
 182   RawBlock* last_block() { return _last; }
 183 
 184   RawBlock* first_field_block();
 185   void add(RawBlock* blocks, RawBlock* start = NULL);
 186   void add_contiguously(RawBlock* blocks, RawBlock* start = NULL);
 187   RawBlock* insert_field_block(RawBlock* slot, RawBlock* block);
 188   void reconstruct_layout(const InstanceKlass* ik);
 189   void fill_holes(const InstanceKlass* ik);
 190   RawBlock* insert(RawBlock* slot, RawBlock* block);
 191   void insert_per_offset(RawBlock* block);
 192   void remove(RawBlock* block);
 193   void print(outputStream* output);
 194 };
 195 
 196 
 197 /* FieldLayoutBuilder is the main entry point for layout computation.
 198  * This class has two methods to generate layout: one for identity classes
 199  * and one for inline classes. The rational for having two methods
 200  * is that each kind of classes has a different set goals regarding
 201  * its layout, so instead of mixing two layout strategies into a
 202  * single method, each kind has its own method (see comments below
 203  * for more details about the allocation strategies).
 204  *
 205  * Computing the layout of a class always goes through 4 steps:
 206  *   1 - Prologue: preparation of data structure and gathering of
 207  *       layout information inherited from super classes
 208  *   2 - Field sorting: fields are sorted out according to their
 209  *       kind (oop, primitive, inline class) and their contention
 210  *       annotation (if any)
 211  *   3 - Layout is computed from the set of lists generated during
 212  *       step 2
 213  *   4 - Epilogue: oopmaps are generated, layout information are
 214  *       prepared so other VM components can use them (instance size,
 215  *       static field size, non-static field size, etc.)
 216  *
 217  *  Steps 1 and 4 are common to all layout computations. Step 2 and 3
 218  *  differ for inline classes and identity classes.
 219  */
 220 class FieldLayoutBuilder : public ResourceObj {
 221  private:
 222   ClassFileParser* _cfp;
 223   FieldLayoutInfo* _info;
 224   RawBlock* _fields;
 225   FieldGroup* _root_group;
 226   FieldGroup* _contended_groups;
 227   FieldGroup* _static_fields;
 228   FieldLayout* _layout;
 229   FieldLayout* _static_layout;
 230   int _nonstatic_oopmap_count;
 231   int _alignment;
 232   int _first_field_offset;
 233   int _exact_size_in_bytes;
 234   bool _has_nonstatic_fields;
 235   bool _has_flattening_information;
 236 
 237   FieldGroup* get_contended_group(int g);
 238 
 239  public:
 240   FieldLayoutBuilder(ClassFileParser* cfp, FieldLayoutInfo* info);
 241 
 242   int get_alignment() {
 243      assert(_alignment != -1, "Uninitialized");
 244      return _alignment;
 245    }
 246 
 247    int get_first_field_offset() {
 248      assert(_first_field_offset != -1, "Uninitialized");
 249      return _first_field_offset;
 250    }
 251 
 252    int get_exact_size_in_byte() {
 253      assert(_exact_size_in_bytes != -1, "Uninitialized");
 254      return _exact_size_in_bytes;
 255    }
 256 
 257    void compute_regular_layout(TRAPS);
 258    void compute_inline_class_layout(TRAPS);
 259 
 260   protected:
 261    void prologue();
 262    void epilogue();
 263    void regular_field_sorting(TRAPS);
 264    void inline_class_field_sorting(TRAPS);
 265 };
 266 
 267 #endif // SHARE_CLASSFILE_FIELDLAYOUTBUILDER_HPP