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