--- /dev/null 2019-07-19 10:38:42.000000000 -0400 +++ new/src/hotspot/share/classfile/fieldLayoutBuilder.hpp 2019-07-19 10:38:42.000000000 -0400 @@ -0,0 +1,267 @@ +/* + * Copyright (c) 2019, 2019, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef SHARE_CLASSFILE_FIELDLAYOUTBUILDER_HPP +#define SHARE_CLASSFILE_FIELDLAYOUTBUILDER_HPP + +#include "classfile/classFileParser.hpp" +#include "classfile/classLoaderData.inline.hpp" +#include "utilities/growableArray.hpp" + +/* Classes below are used to compute the field layout of classes. */ + + +/* A RawBlock describes an element of a layout. + * Each field is represented by a RawBlock. + * RawBlocks can also represent elements injected by the JVM: + * padding, empty blocks, inherited fields, etc. + * All RawBlock must have a size and a alignment. The size is the + * exact size of the field expressed in bytes. The alignment is + * the alignment constraint of the field (1 for byte, 2 for short, + * 4 for int, 8 for long, etc.) + * + * RawBlock are designed to be inserted in two linked list: + * - a field group (using _next_field, _prev_field) + * - a layout (using _next_block, _prev_block) + * + * next/prev pointers are included in the RawBlock class to narrow + * the number of allocation required during the computation of a layout. + */ +class RawBlock : public ResourceObj { + public: + enum Kind { + EMPTY, // empty slot, space is taken from this to allocate fields + RESERVED, // reserved for JVM usage (for instance object header) + PADDING, // padding (because of alignment constraints or @Contended) + REGULAR, // primitive or oop field (including non-flattened inline fields) + FLATTENED, // flattened field + INHERITED // field(s) inherited from super classes + }; + + private: + RawBlock* _next_field; + RawBlock* _prev_field; + RawBlock* _next_block; + RawBlock* _prev_block; + Kind _kind; + int _offset; + int _alignment; + int _size; + int _field_index; + bool _is_reference; + ValueKlass* _value_klass; + + public: + RawBlock(Kind kind, int size = -1, int alignment = 1); + RawBlock(int index, Kind kind, int size = -1, int alignment = -1, bool is_reference = false); + RawBlock* next_field() const { return _next_field; } + void set_next_field(RawBlock* next) { _next_field = next; } + RawBlock* prev_field() const { return _prev_field; } + void set_prev_field(RawBlock* prev) { _prev_field = prev; } + RawBlock* next_block() const { return _next_block; } + void set_next_block(RawBlock* next) { _next_block = next; } + RawBlock* prev_block() const { return _prev_block; } + void set_prev_block(RawBlock* prev) { _prev_block = prev; } + Kind kind() const { return _kind; } + int offset() const { + assert(_offset >= 0, "Mut be initialized"); + return _offset; + } + void set_offset(int offset) { _offset = offset; } + int alignment() const { return _alignment; } + int size() const { return _size; } + void set_size(int size) { _size = size; } + int field_index() const { + assert(_field_index != -1, "Must be initialized"); + return _field_index; + } + bool is_reference() const { return _is_reference; } + ValueKlass* value_klass() const { + assert(_value_klass != NULL, "Must be initialized"); + return _value_klass; + } + void set_value_klass(ValueKlass* value_klass) { _value_klass = value_klass; } + + bool fit(int size, int alignment); + +}; + +/* A Field group represents a set of fields that have to be allocated together, + * this is the way the @Contended annotation is supported. + * Inside a FieldGroup, fields are sorted based on their kind: primitive, + * oop, or flattened. + * + */ +class FieldGroup : public ResourceObj { + + private: + FieldGroup* _next; + RawBlock* _primitive_fields; + RawBlock* _oop_fields; + RawBlock* _flattened_fields; + int _contended_group; + int _oop_count; + + public: + FieldGroup(int contended_group = -1); + + FieldGroup* next() const { return _next; } + void set_next(FieldGroup* next) { _next = next; } + RawBlock* primitive_fields() const { return _primitive_fields; } + RawBlock* oop_fields() const { return _oop_fields; } + RawBlock* flattened_fields() const { return _flattened_fields; } + int contended_group() const { return _contended_group; } + int oop_count() const { return _oop_count; } + + void add_primitive_field(AllFieldStream fs, BasicType type); + void add_oop_field(AllFieldStream fs); + void add_flattened_field(AllFieldStream fs, ValueKlass* vk); + void add_block(RawBlock** list, RawBlock* block); +}; + +/* The FieldLayout class represents a set of fields organized + * in a layout. + * An instance of FieldLayout can either represent the layout + * of non-static fields (used in an instance object) or the + * layout of static fields (to be included in the class mirror). + * + * _block is a pointer to a list of RawBlock ordered by increasing + * offsets. + * _start points to the RawBlock with the first offset that can + * be used to allocate fields of the current class + * _last points to the last RawBlock of the list. In order to + * simplify the code, the RawBlock list always ends with an + * EMPTY block (the kind of RawBlock from which space is taken + * to allocate fields) with a size big enough to satisfy all + * field allocations. + */ +class FieldLayout : public ResourceObj { + private: + Array* _fields; + ConstantPool* _cp; + RawBlock* _blocks; + RawBlock* _start; + RawBlock* _last; + + public: + FieldLayout(Array* fields, ConstantPool* cp); + void initialize_static_layout(); + void initialize_instance_layout(const InstanceKlass* ik); + + RawBlock* first_empty_block() { + RawBlock* block = _start; + while (block->kind() != RawBlock::EMPTY) { + block = block->next_block(); + } + return block; + } + + RawBlock* start() { return _start; } + void set_start(RawBlock* start) { _start = start; } + RawBlock* last_block() { return _last; } + + RawBlock* first_field_block(); + void add(RawBlock* blocks, RawBlock* start = NULL); + void add_contiguously(RawBlock* blocks, RawBlock* start = NULL); + RawBlock* insert_field_block(RawBlock* slot, RawBlock* block); + void reconstruct_layout(const InstanceKlass* ik); + void fill_holes(const InstanceKlass* ik); + RawBlock* insert(RawBlock* slot, RawBlock* block); + void insert_per_offset(RawBlock* block); + void remove(RawBlock* block); + void print(outputStream* output); +}; + + +/* FieldLayoutBuilder is the main entry point for layout computation. + * This class has two methods to generate layout: one for identity classes + * and one for inline classes. The rational for having two methods + * is that each kind of classes has a different set goals regarding + * its layout, so instead of mixing two layout strategies into a + * single method, each kind has its own method (see comments below + * for more details about the allocation strategies). + * + * Computing the layout of a class always goes through 4 steps: + * 1 - Prologue: preparation of data structure and gathering of + * layout information inherited from super classes + * 2 - Field sorting: fields are sorted out according to their + * kind (oop, primitive, inline class) and their contention + * annotation (if any) + * 3 - Layout is computed from the set of lists generated during + * step 2 + * 4 - Epilogue: oopmaps are generated, layout information are + * prepared so other VM components can use them (instance size, + * static field size, non-static field size, etc.) + * + * Steps 1 and 4 are common to all layout computations. Step 2 and 3 + * differ for inline classes and identity classes. + */ +class FieldLayoutBuilder : public ResourceObj { + private: + ClassFileParser* _cfp; + FieldLayoutInfo* _info; + RawBlock* _fields; + FieldGroup* _root_group; + FieldGroup* _contended_groups; + FieldGroup* _static_fields; + FieldLayout* _layout; + FieldLayout* _static_layout; + int _nonstatic_oopmap_count; + int _alignment; + int _first_field_offset; + int _exact_size_in_bytes; + bool _has_nonstatic_fields; + bool _has_flattening_information; + + FieldGroup* get_contended_group(int g); + + public: + FieldLayoutBuilder(ClassFileParser* cfp, FieldLayoutInfo* info); + + int get_alignment() { + assert(_alignment != -1, "Uninitialized"); + return _alignment; + } + + int get_first_field_offset() { + assert(_first_field_offset != -1, "Uninitialized"); + return _first_field_offset; + } + + int get_exact_size_in_byte() { + assert(_exact_size_in_bytes != -1, "Uninitialized"); + return _exact_size_in_bytes; + } + + void compute_regular_layout(TRAPS); + void compute_inline_class_layout(TRAPS); + + protected: + void prologue(); + void epilogue(); + void regular_field_sorting(TRAPS); + void inline_class_field_sorting(TRAPS); +}; + +#endif // SHARE_CLASSFILE_FIELDLAYOUTBUILDER_HPP