Path: blob/master/src/hotspot/share/classfile/fieldLayoutBuilder.hpp
40949 views
/*1* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*22*/2324#ifndef SHARE_CLASSFILE_FIELDLAYOUTBUILDER_HPP25#define SHARE_CLASSFILE_FIELDLAYOUTBUILDER_HPP2627#include "classfile/classFileParser.hpp"28#include "classfile/classLoaderData.hpp"29#include "memory/allocation.hpp"30#include "oops/fieldStreams.hpp"31#include "utilities/growableArray.hpp"3233// Classes below are used to compute the field layout of classes.343536// 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 the41// exact size of the field expressed in bytes. The alignment is42// 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 narrow50// the number of allocation required during the computation of a layout.51//52class LayoutRawBlock : public ResourceObj {53public:54// Some code relies on the order of values below.55enum Kind {56EMPTY, // empty slot, space is taken from this to allocate fields57RESERVED, // reserved for JVM usage (for instance object header)58PADDING, // padding (because of alignment constraints or @Contended)59REGULAR, // primitive or oop field (including non-flattened inline fields)60FLATTENED, // flattened field61INHERITED // field(s) inherited from super classes62};6364private:65LayoutRawBlock* _next_block;66LayoutRawBlock* _prev_block;67Kind _kind;68int _offset;69int _alignment;70int _size;71int _field_index;72bool _is_reference;7374public:75LayoutRawBlock(Kind kind, int size);76LayoutRawBlock(int index, Kind kind, int size, int alignment, bool is_reference = false);77LayoutRawBlock* next_block() const { return _next_block; }78void set_next_block(LayoutRawBlock* next) { _next_block = next; }79LayoutRawBlock* prev_block() const { return _prev_block; }80void set_prev_block(LayoutRawBlock* prev) { _prev_block = prev; }81Kind kind() const { return _kind; }82int offset() const {83assert(_offset >= 0, "Must be initialized");84return _offset;85}86void set_offset(int offset) { _offset = offset; }87int alignment() const { return _alignment; }88int size() const { return _size; }89void set_size(int size) { _size = size; }90int field_index() const {91assert(_field_index != -1, "Must be initialized");92return _field_index;93}94bool is_reference() const { return _is_reference; }9596bool fit(int size, int alignment);9798static int compare_offset(LayoutRawBlock** x, LayoutRawBlock** y) { return (*x)->offset() - (*y)->offset(); }99// compare_size_inverted() returns the opposite of a regular compare method in order to100// sort fields in decreasing order.101// Note: with line types, the comparison should include alignment constraint if sizes are equals102static int compare_size_inverted(LayoutRawBlock** x, LayoutRawBlock** y) {103#ifdef _WINDOWS104// qsort() on Windows reverse the order of fields with the same size105// the extension of the comparison function below preserves this order106int diff = (*y)->size() - (*x)->size();107if (diff == 0) {108diff = (*x)->field_index() - (*y)->field_index();109}110return diff;111#else112return (*y)->size() - (*x)->size();113#endif // _WINDOWS114}115116};117118// A Field group represents a set of fields that have to be allocated together,119// this is the way the @Contended annotation is supported.120// Inside a FieldGroup, fields are sorted based on their kind: primitive,121// oop, or flattened.122//123class FieldGroup : public ResourceObj {124125private:126FieldGroup* _next;127GrowableArray<LayoutRawBlock*>* _primitive_fields;128GrowableArray<LayoutRawBlock*>* _oop_fields;129int _contended_group;130int _oop_count;131static const int INITIAL_LIST_SIZE = 16;132133public:134FieldGroup(int contended_group = -1);135136FieldGroup* next() const { return _next; }137void set_next(FieldGroup* next) { _next = next; }138GrowableArray<LayoutRawBlock*>* primitive_fields() const { return _primitive_fields; }139GrowableArray<LayoutRawBlock*>* oop_fields() const { return _oop_fields; }140int contended_group() const { return _contended_group; }141int oop_count() const { return _oop_count; }142143void add_primitive_field(AllFieldStream fs, BasicType type);144void add_oop_field(AllFieldStream fs);145void sort_by_size();146};147148// The FieldLayout class represents a set of fields organized149// in a layout.150// An instance of FieldLayout can either represent the layout151// of non-static fields (used in an instance object) or the152// layout of static fields (to be included in the class mirror).153//154// _block is a pointer to a list of LayoutRawBlock ordered by increasing155// offsets.156// _start points to the LayoutRawBlock with the first offset that can157// be used to allocate fields of the current class158// _last points to the last LayoutRawBlock of the list. In order to159// simplify the code, the LayoutRawBlock list always ends with an160// EMPTY block (the kind of LayoutRawBlock from which space is taken161// to allocate fields) with a size big enough to satisfy all162// field allocations.163//164class FieldLayout : public ResourceObj {165private:166Array<u2>* _fields;167ConstantPool* _cp;168LayoutRawBlock* _blocks; // the layout being computed169LayoutRawBlock* _start; // points to the first block where a field can be inserted170LayoutRawBlock* _last; // points to the last block of the layout (big empty block)171172public:173FieldLayout(Array<u2>* fields, ConstantPool* cp);174void initialize_static_layout();175void initialize_instance_layout(const InstanceKlass* ik);176177LayoutRawBlock* first_empty_block() {178LayoutRawBlock* block = _start;179while (block->kind() != LayoutRawBlock::EMPTY) {180block = block->next_block();181}182return block;183}184185LayoutRawBlock* start() { return _start; }186void set_start(LayoutRawBlock* start) { _start = start; }187LayoutRawBlock* last_block() { return _last; }188189LayoutRawBlock* first_field_block();190void add(GrowableArray<LayoutRawBlock*>* list, LayoutRawBlock* start = NULL);191void add_field_at_offset(LayoutRawBlock* blocks, int offset, LayoutRawBlock* start = NULL);192void add_contiguously(GrowableArray<LayoutRawBlock*>* list, LayoutRawBlock* start = NULL);193LayoutRawBlock* insert_field_block(LayoutRawBlock* slot, LayoutRawBlock* block);194bool reconstruct_layout(const InstanceKlass* ik);195void fill_holes(const InstanceKlass* ik);196LayoutRawBlock* insert(LayoutRawBlock* slot, LayoutRawBlock* block);197void remove(LayoutRawBlock* block);198void print(outputStream* output, bool is_static, const InstanceKlass* super);199};200201202// FieldLayoutBuilder is the main entry point for layout computation.203// This class has three methods to generate layout: one for regular classes204// and two for classes with hard coded offsets (java,lang.ref.Reference205// and the boxing classes). The rationale for having multiple methods206// is that each kind of class has a different set goals regarding207// its layout, so instead of mixing several layout strategies into a208// single method, each kind has its own method (see comments below209// for more details about the allocation strategies).210//211// Computing the layout of a class always goes through 4 steps:212// 1 - Prologue: preparation of data structure and gathering of213// layout information inherited from super classes214// 2 - Field sorting: fields are sorted according to their215// kind (oop, primitive, inline class) and their contention216// annotation (if any)217// 3 - Layout is computed from the set of lists generated during218// step 2219// 4 - Epilogue: oopmaps are generated, layout information is220// prepared so other VM components can use it (instance size,221// static field size, non-static field size, etc.)222//223// Steps 1 and 4 are common to all layout computations. Step 2 and 3224// can vary with the allocation strategy.225//226class FieldLayoutBuilder : public ResourceObj {227private:228229const Symbol* _classname;230const InstanceKlass* _super_klass;231ConstantPool* _constant_pool;232Array<u2>* _fields;233FieldLayoutInfo* _info;234FieldGroup* _root_group;235GrowableArray<FieldGroup*> _contended_groups;236FieldGroup* _static_fields;237FieldLayout* _layout;238FieldLayout* _static_layout;239int _nonstatic_oopmap_count;240int _alignment;241bool _has_nonstatic_fields;242bool _is_contended; // is a contended class?243244public:245FieldLayoutBuilder(const Symbol* classname, const InstanceKlass* super_klass, ConstantPool* constant_pool,246Array<u2>* fields, bool is_contended, FieldLayoutInfo* info);247248int get_alignment() {249assert(_alignment != -1, "Uninitialized");250return _alignment;251}252253void build_layout();254void compute_regular_layout();255void insert_contended_padding(LayoutRawBlock* slot);256257private:258void prologue();259void epilogue();260void regular_field_sorting();261FieldGroup* get_or_create_contended_group(int g);262};263264#endif // SHARE_CLASSFILE_FIELDLAYOUTBUILDER_HPP265266267