Bug Summary

File:jdk/src/hotspot/share/classfile/fieldLayoutBuilder.cpp
Warning:line 284, column 22
Division by zero

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name fieldLayoutBuilder.cpp -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -mthread-model posix -fno-delete-null-pointer-checks -mframe-pointer=all -relaxed-aliasing -fmath-errno -fno-rounding-math -masm-verbose -mconstructor-aliases -munwind-tables -target-cpu x86-64 -dwarf-column-info -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib/llvm-10/lib/clang/10.0.0 -I /home/daniel/Projects/java/jdk/build/linux-x86_64-server-fastdebug/hotspot/variant-server/libjvm/objs/precompiled -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -D __STDC_CONSTANT_MACROS -D _GNU_SOURCE -D _REENTRANT -D LIBC=gnu -D LINUX -D VM_LITTLE_ENDIAN -D _LP64=1 -D ASSERT -D CHECK_UNHANDLED_OOPS -D TARGET_ARCH_x86 -D INCLUDE_SUFFIX_OS=_linux -D INCLUDE_SUFFIX_CPU=_x86 -D INCLUDE_SUFFIX_COMPILER=_gcc -D TARGET_COMPILER_gcc -D AMD64 -D HOTSPOT_LIB_ARCH="amd64" -D COMPILER1 -D COMPILER2 -I /home/daniel/Projects/java/jdk/build/linux-x86_64-server-fastdebug/hotspot/variant-server/gensrc/adfiles -I /home/daniel/Projects/java/jdk/src/hotspot/share -I /home/daniel/Projects/java/jdk/src/hotspot/os/linux -I /home/daniel/Projects/java/jdk/src/hotspot/os/posix -I /home/daniel/Projects/java/jdk/src/hotspot/cpu/x86 -I /home/daniel/Projects/java/jdk/src/hotspot/os_cpu/linux_x86 -I /home/daniel/Projects/java/jdk/build/linux-x86_64-server-fastdebug/hotspot/variant-server/gensrc -I /home/daniel/Projects/java/jdk/src/hotspot/share/precompiled -I /home/daniel/Projects/java/jdk/src/hotspot/share/include -I /home/daniel/Projects/java/jdk/src/hotspot/os/posix/include -I /home/daniel/Projects/java/jdk/build/linux-x86_64-server-fastdebug/support/modules_include/java.base -I /home/daniel/Projects/java/jdk/build/linux-x86_64-server-fastdebug/support/modules_include/java.base/linux -I /home/daniel/Projects/java/jdk/src/java.base/share/native/libjimage -I /home/daniel/Projects/java/jdk/build/linux-x86_64-server-fastdebug/hotspot/variant-server/gensrc/adfiles -I /home/daniel/Projects/java/jdk/src/hotspot/share -I /home/daniel/Projects/java/jdk/src/hotspot/os/linux -I /home/daniel/Projects/java/jdk/src/hotspot/os/posix -I /home/daniel/Projects/java/jdk/src/hotspot/cpu/x86 -I /home/daniel/Projects/java/jdk/src/hotspot/os_cpu/linux_x86 -I /home/daniel/Projects/java/jdk/build/linux-x86_64-server-fastdebug/hotspot/variant-server/gensrc -D _FORTIFY_SOURCE=2 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.5.0/../../../../include/c++/7.5.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.5.0/../../../../include/x86_64-linux-gnu/c++/7.5.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.5.0/../../../../include/x86_64-linux-gnu/c++/7.5.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.5.0/../../../../include/c++/7.5.0/backward -internal-isystem /usr/local/include -internal-isystem /usr/lib/llvm-10/lib/clang/10.0.0/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O3 -Wno-format-zero-length -Wno-unused-parameter -Wno-unused -Wno-parentheses -Wno-comment -Wno-unknown-pragmas -Wno-address -Wno-delete-non-virtual-dtor -Wno-char-subscripts -Wno-array-bounds -Wno-int-in-bool-context -Wno-ignored-qualifiers -Wno-missing-field-initializers -Wno-implicit-fallthrough -Wno-empty-body -Wno-strict-overflow -Wno-sequence-point -Wno-maybe-uninitialized -Wno-misleading-indentation -Wno-cast-function-type -Wno-shift-negative-value -std=c++14 -fdeprecated-macro -fdebug-compilation-dir /home/daniel/Projects/java/jdk/make/hotspot -ferror-limit 19 -fmessage-length 0 -fvisibility hidden -stack-protector 1 -fno-rtti -fgnuc-version=4.2.1 -fobjc-runtime=gcc -fdiagnostics-show-option -vectorize-loops -vectorize-slp -analyzer-output=html -faddrsig -o /home/daniel/Projects/java/scan/2021-12-21-193737-8510-1 -x c++ /home/daniel/Projects/java/jdk/src/hotspot/share/classfile/fieldLayoutBuilder.cpp

/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/fieldLayoutBuilder.cpp

1/*
2 * Copyright (c) 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#include "precompiled.hpp"
26#include "jvm.h"
27#include "classfile/classFileParser.hpp"
28#include "classfile/fieldLayoutBuilder.hpp"
29#include "memory/resourceArea.hpp"
30#include "oops/array.hpp"
31#include "oops/fieldStreams.inline.hpp"
32#include "oops/instanceMirrorKlass.hpp"
33#include "oops/instanceKlass.inline.hpp"
34#include "oops/klass.inline.hpp"
35#include "runtime/fieldDescriptor.inline.hpp"
36
37
38LayoutRawBlock::LayoutRawBlock(Kind kind, int size) :
39 _next_block(NULL__null),
40 _prev_block(NULL__null),
41 _kind(kind),
42 _offset(-1),
43 _alignment(1),
44 _size(size),
45 _field_index(-1),
46 _is_reference(false) {
47 assert(kind == EMPTY || kind == RESERVED || kind == PADDING || kind == INHERITED,do { if (!(kind == EMPTY || kind == RESERVED || kind == PADDING
|| kind == INHERITED)) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/fieldLayoutBuilder.cpp"
, 48, "assert(" "kind == EMPTY || kind == RESERVED || kind == PADDING || kind == INHERITED"
") failed", "Otherwise, should use the constructor with a field index argument"
); ::breakpoint(); } } while (0)
48 "Otherwise, should use the constructor with a field index argument")do { if (!(kind == EMPTY || kind == RESERVED || kind == PADDING
|| kind == INHERITED)) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/fieldLayoutBuilder.cpp"
, 48, "assert(" "kind == EMPTY || kind == RESERVED || kind == PADDING || kind == INHERITED"
") failed", "Otherwise, should use the constructor with a field index argument"
); ::breakpoint(); } } while (0)
;
49 assert(size > 0, "Sanity check")do { if (!(size > 0)) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/fieldLayoutBuilder.cpp"
, 49, "assert(" "size > 0" ") failed", "Sanity check"); ::
breakpoint(); } } while (0)
;
50}
51
52
53LayoutRawBlock::LayoutRawBlock(int index, Kind kind, int size, int alignment, bool is_reference) :
54 _next_block(NULL__null),
55 _prev_block(NULL__null),
56 _kind(kind),
57 _offset(-1),
58 _alignment(alignment),
59 _size(size),
60 _field_index(index),
61 _is_reference(is_reference) {
62 assert(kind == REGULAR || kind == FLATTENED || kind == INHERITED,do { if (!(kind == REGULAR || kind == FLATTENED || kind == INHERITED
)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/fieldLayoutBuilder.cpp"
, 63, "assert(" "kind == REGULAR || kind == FLATTENED || kind == INHERITED"
") failed", "Other kind do not have a field index"); ::breakpoint
(); } } while (0)
63 "Other kind do not have a field index")do { if (!(kind == REGULAR || kind == FLATTENED || kind == INHERITED
)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/fieldLayoutBuilder.cpp"
, 63, "assert(" "kind == REGULAR || kind == FLATTENED || kind == INHERITED"
") failed", "Other kind do not have a field index"); ::breakpoint
(); } } while (0)
;
64 assert(size > 0, "Sanity check")do { if (!(size > 0)) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/fieldLayoutBuilder.cpp"
, 64, "assert(" "size > 0" ") failed", "Sanity check"); ::
breakpoint(); } } while (0)
;
65 assert(alignment > 0, "Sanity check")do { if (!(alignment > 0)) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/fieldLayoutBuilder.cpp"
, 65, "assert(" "alignment > 0" ") failed", "Sanity check"
); ::breakpoint(); } } while (0)
;
66}
67
68bool LayoutRawBlock::fit(int size, int alignment) {
69 int adjustment = 0;
70 if ((_offset % alignment) != 0) {
71 adjustment = alignment - (_offset % alignment);
72 }
73 return _size >= size + adjustment;
74}
75
76FieldGroup::FieldGroup(int contended_group) :
77 _next(NULL__null),
78 _primitive_fields(NULL__null),
79 _oop_fields(NULL__null),
80 _contended_group(contended_group), // -1 means no contended group, 0 means default contended group
81 _oop_count(0) {}
82
83void FieldGroup::add_primitive_field(AllFieldStream fs, BasicType type) {
84 int size = type2aelembytes(type);
85 LayoutRawBlock* block = new LayoutRawBlock(fs.index(), LayoutRawBlock::REGULAR, size, size /* alignment == size for primitive types */, false);
86 if (_primitive_fields == NULL__null) {
87 _primitive_fields = new(ResourceObj::RESOURCE_AREA, mtInternal) GrowableArray<LayoutRawBlock*>(INITIAL_LIST_SIZE);
88 }
89 _primitive_fields->append(block);
90}
91
92void FieldGroup::add_oop_field(AllFieldStream fs) {
93 int size = type2aelembytes(T_OBJECT);
94 LayoutRawBlock* block = new LayoutRawBlock(fs.index(), LayoutRawBlock::REGULAR, size, size /* alignment == size for oops */, true);
95 if (_oop_fields == NULL__null) {
96 _oop_fields = new(ResourceObj::RESOURCE_AREA, mtInternal) GrowableArray<LayoutRawBlock*>(INITIAL_LIST_SIZE);
97 }
98 _oop_fields->append(block);
99 _oop_count++;
100}
101
102void FieldGroup::sort_by_size() {
103 if (_primitive_fields != NULL__null) {
104 _primitive_fields->sort(LayoutRawBlock::compare_size_inverted);
105 }
106}
107
108FieldLayout::FieldLayout(Array<u2>* fields, ConstantPool* cp) :
109 _fields(fields),
110 _cp(cp),
111 _blocks(NULL__null),
112 _start(_blocks),
113 _last(_blocks) {}
114
115void FieldLayout::initialize_static_layout() {
116 _blocks = new LayoutRawBlock(LayoutRawBlock::EMPTY, INT_MAX2147483647);
117 _blocks->set_offset(0);
118 _last = _blocks;
119 _start = _blocks;
120 // Note: at this stage, InstanceMirrorKlass::offset_of_static_fields() could be zero, because
121 // during bootstrapping, the size of the java.lang.Class is still not known when layout
122 // of static field is computed. Field offsets are fixed later when the size is known
123 // (see java_lang_Class::fixup_mirror())
124 if (InstanceMirrorKlass::offset_of_static_fields() > 0) {
125 insert(first_empty_block(), new LayoutRawBlock(LayoutRawBlock::RESERVED, InstanceMirrorKlass::offset_of_static_fields()));
126 _blocks->set_offset(0);
127 }
128}
129
130void FieldLayout::initialize_instance_layout(const InstanceKlass* super_klass) {
131 if (super_klass == NULL__null) {
132 _blocks = new LayoutRawBlock(LayoutRawBlock::EMPTY, INT_MAX2147483647);
133 _blocks->set_offset(0);
134 _last = _blocks;
135 _start = _blocks;
136 insert(first_empty_block(), new LayoutRawBlock(LayoutRawBlock::RESERVED, instanceOopDesc::base_offset_in_bytes()));
137 } else {
138 bool has_fields = reconstruct_layout(super_klass);
139 fill_holes(super_klass);
140 if ((UseEmptySlotsInSupers && !super_klass->has_contended_annotations()) || !has_fields) {
141 _start = _blocks; // start allocating fields from the first empty block
142 } else {
143 _start = _last; // append fields at the end of the reconstructed layout
144 }
145 }
146}
147
148LayoutRawBlock* FieldLayout::first_field_block() {
149 LayoutRawBlock* block = _start;
150 while (block->kind() != LayoutRawBlock::INHERITED && block->kind() != LayoutRawBlock::REGULAR
151 && block->kind() != LayoutRawBlock::FLATTENED && block->kind() != LayoutRawBlock::PADDING) {
152 block = block->next_block();
153 }
154 return block;
155}
156
157
158// Insert a set of fields into a layout using a best-fit strategy.
159// For each field, search for the smallest empty slot able to fit the field
160// (satisfying both size and alignment requirements), if none is found,
161// add the field at the end of the layout.
162// Fields cannot be inserted before the block specified in the "start" argument
163void FieldLayout::add(GrowableArray<LayoutRawBlock*>* list, LayoutRawBlock* start) {
164 if (list == NULL__null) return;
5
Assuming 'list' is not equal to NULL
6
Taking false branch
165 if (start
6.1
'start' is equal to NULL
6.1
'start' is equal to NULL
== NULL__null) start = this->_start;
7
Taking true branch
166 bool last_search_success = false;
167 int last_size = 0;
168 int last_alignment = 0;
169 for (int i = 0; i < list->length(); i ++) {
8
Assuming the condition is true
9
Loop condition is true. Entering loop body
170 LayoutRawBlock* b = list->at(i);
171 LayoutRawBlock* cursor = NULL__null;
172 LayoutRawBlock* candidate = NULL__null;
173
174 // if start is the last block, just append the field
175 if (start == last_block()) {
10
Assuming the condition is false
11
Taking false branch
176 candidate = last_block();
177 }
178 // Before iterating over the layout to find an empty slot fitting the field's requirements,
179 // check if the previous field had the same requirements and if the search for a fitting slot
180 // was successful. If the requirements were the same but the search failed, a new search will
181 // fail the same way, so just append the field at the of the layout.
182 else if (b->size() == last_size && b->alignment() == last_alignment && !last_search_success
13.1
'last_search_success' is false
13.1
'last_search_success' is false
) {
12
Assuming the condition is true
13
Assuming the condition is true
14
Taking true branch
183 candidate = last_block();
184 } else {
185 // Iterate over the layout to find an empty slot fitting the field's requirements
186 last_size = b->size();
187 last_alignment = b->alignment();
188 cursor = last_block()->prev_block();
189 assert(cursor != NULL, "Sanity check")do { if (!(cursor != __null)) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/fieldLayoutBuilder.cpp"
, 189, "assert(" "cursor != __null" ") failed", "Sanity check"
); ::breakpoint(); } } while (0)
;
190 last_search_success = true;
191 while (cursor != start) {
192 if (cursor->kind() == LayoutRawBlock::EMPTY && cursor->fit(b->size(), b->alignment())) {
193 if (candidate == NULL__null || cursor->size() < candidate->size()) {
194 candidate = cursor;
195 }
196 }
197 cursor = cursor->prev_block();
198 }
199 if (candidate == NULL__null) {
200 candidate = last_block();
201 last_search_success = false;
202 }
203 assert(candidate != NULL, "Candidate must not be null")do { if (!(candidate != __null)) { (*g_assert_poison) = 'X';;
report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/fieldLayoutBuilder.cpp"
, 203, "assert(" "candidate != __null" ") failed", "Candidate must not be null"
); ::breakpoint(); } } while (0)
;
204 assert(candidate->kind() == LayoutRawBlock::EMPTY, "Candidate must be an empty block")do { if (!(candidate->kind() == LayoutRawBlock::EMPTY)) { (
*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/fieldLayoutBuilder.cpp"
, 204, "assert(" "candidate->kind() == LayoutRawBlock::EMPTY"
") failed", "Candidate must be an empty block"); ::breakpoint
(); } } while (0)
;
205 assert(candidate->fit(b->size(), b->alignment()), "Candidate must be able to store the block")do { if (!(candidate->fit(b->size(), b->alignment())
)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/fieldLayoutBuilder.cpp"
, 205, "assert(" "candidate->fit(b->size(), b->alignment())"
") failed", "Candidate must be able to store the block"); ::
breakpoint(); } } while (0)
;
206 }
207
208 insert_field_block(candidate, b);
15
Calling 'FieldLayout::insert_field_block'
209 }
210}
211
212// Used for classes with hard coded field offsets, insert a field at the specified offset */
213void FieldLayout::add_field_at_offset(LayoutRawBlock* block, int offset, LayoutRawBlock* start) {
214 assert(block != NULL, "Sanity check")do { if (!(block != __null)) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/fieldLayoutBuilder.cpp"
, 214, "assert(" "block != __null" ") failed", "Sanity check"
); ::breakpoint(); } } while (0)
;
215 block->set_offset(offset);
216 if (start == NULL__null) {
217 start = this->_start;
218 }
219 LayoutRawBlock* slot = start;
220 while (slot != NULL__null) {
221 if ((slot->offset() <= block->offset() && (slot->offset() + slot->size()) > block->offset()) ||
222 slot == _last){
223 assert(slot->kind() == LayoutRawBlock::EMPTY, "Matching slot must be an empty slot")do { if (!(slot->kind() == LayoutRawBlock::EMPTY)) { (*g_assert_poison
) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/fieldLayoutBuilder.cpp"
, 223, "assert(" "slot->kind() == LayoutRawBlock::EMPTY" ") failed"
, "Matching slot must be an empty slot"); ::breakpoint(); } }
while (0)
;
224 assert(slot->size() >= block->offset() + block->size() ,"Matching slot must be big enough")do { if (!(slot->size() >= block->offset() + block->
size())) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/fieldLayoutBuilder.cpp"
, 224, "assert(" "slot->size() >= block->offset() + block->size()"
") failed", "Matching slot must be big enough"); ::breakpoint
(); } } while (0)
;
225 if (slot->offset() < block->offset()) {
226 int adjustment = block->offset() - slot->offset();
227 LayoutRawBlock* adj = new LayoutRawBlock(LayoutRawBlock::EMPTY, adjustment);
228 insert(slot, adj);
229 }
230 insert(slot, block);
231 if (slot->size() == 0) {
232 remove(slot);
233 }
234 FieldInfo::from_field_array(_fields, block->field_index())->set_offset(block->offset());
235 return;
236 }
237 slot = slot->next_block();
238 }
239 fatal("Should have found a matching slot above, corrupted layout or invalid offset")do { (*g_assert_poison) = 'X';; report_fatal(INTERNAL_ERROR, "/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/fieldLayoutBuilder.cpp"
, 239, "Should have found a matching slot above, corrupted layout or invalid offset"
); ::breakpoint(); } while (0)
;
240}
241
242// The allocation logic uses a best fit strategy: the set of fields is allocated
243// in the first empty slot big enough to contain the whole set ((including padding
244// to fit alignment constraints).
245void FieldLayout::add_contiguously(GrowableArray<LayoutRawBlock*>* list, LayoutRawBlock* start) {
246 if (list == NULL__null) return;
247 if (start == NULL__null) {
248 start = _start;
249 }
250 // This code assumes that if the first block is well aligned, the following
251 // blocks would naturally be well aligned (no need for adjustment)
252 int size = 0;
253 for (int i = 0; i < list->length(); i++) {
254 size += list->at(i)->size();
255 }
256
257 LayoutRawBlock* candidate = NULL__null;
258 if (start == last_block()) {
259 candidate = last_block();
260 } else {
261 LayoutRawBlock* first = list->at(0);
262 candidate = last_block()->prev_block();
263 while (candidate->kind() != LayoutRawBlock::EMPTY || !candidate->fit(size, first->alignment())) {
264 if (candidate == start) {
265 candidate = last_block();
266 break;
267 }
268 candidate = candidate->prev_block();
269 }
270 assert(candidate != NULL, "Candidate must not be null")do { if (!(candidate != __null)) { (*g_assert_poison) = 'X';;
report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/fieldLayoutBuilder.cpp"
, 270, "assert(" "candidate != __null" ") failed", "Candidate must not be null"
); ::breakpoint(); } } while (0)
;
271 assert(candidate->kind() == LayoutRawBlock::EMPTY, "Candidate must be an empty block")do { if (!(candidate->kind() == LayoutRawBlock::EMPTY)) { (
*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/fieldLayoutBuilder.cpp"
, 271, "assert(" "candidate->kind() == LayoutRawBlock::EMPTY"
") failed", "Candidate must be an empty block"); ::breakpoint
(); } } while (0)
;
272 assert(candidate->fit(size, first->alignment()), "Candidate must be able to store the whole contiguous block")do { if (!(candidate->fit(size, first->alignment()))) {
(*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/fieldLayoutBuilder.cpp"
, 272, "assert(" "candidate->fit(size, first->alignment())"
") failed", "Candidate must be able to store the whole contiguous block"
); ::breakpoint(); } } while (0)
;
273 }
274
275 for (int i = 0; i < list->length(); i++) {
276 LayoutRawBlock* b = list->at(i);
277 insert_field_block(candidate, b);
278 assert((candidate->offset() % b->alignment() == 0), "Contiguous blocks must be naturally well aligned")do { if (!((candidate->offset() % b->alignment() == 0))
) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/fieldLayoutBuilder.cpp"
, 278, "assert(" "(candidate->offset() % b->alignment() == 0)"
") failed", "Contiguous blocks must be naturally well aligned"
); ::breakpoint(); } } while (0)
;
279 }
280}
281
282LayoutRawBlock* FieldLayout::insert_field_block(LayoutRawBlock* slot, LayoutRawBlock* block) {
283 assert(slot->kind() == LayoutRawBlock::EMPTY, "Blocks can only be inserted in empty blocks")do { if (!(slot->kind() == LayoutRawBlock::EMPTY)) { (*g_assert_poison
) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/fieldLayoutBuilder.cpp"
, 283, "assert(" "slot->kind() == LayoutRawBlock::EMPTY" ") failed"
, "Blocks can only be inserted in empty blocks"); ::breakpoint
(); } } while (0)
;
16
Assuming the condition is true
17
Taking false branch
18
Loop condition is false. Exiting loop
284 if (slot->offset() % block->alignment() != 0) {
19
Calling 'LayoutRawBlock::alignment'
21
Returning from 'LayoutRawBlock::alignment'
22
Division by zero
285 int adjustment = block->alignment() - (slot->offset() % block->alignment());
286 LayoutRawBlock* adj = new LayoutRawBlock(LayoutRawBlock::EMPTY, adjustment);
287 insert(slot, adj);
288 }
289 insert(slot, block);
290 if (slot->size() == 0) {
291 remove(slot);
292 }
293 FieldInfo::from_field_array(_fields, block->field_index())->set_offset(block->offset());
294 return block;
295}
296
297bool FieldLayout::reconstruct_layout(const InstanceKlass* ik) {
298 bool has_instance_fields = false;
299 GrowableArray<LayoutRawBlock*>* all_fields = new GrowableArray<LayoutRawBlock*>(32);
300 while (ik != NULL__null) {
301 for (AllFieldStream fs(ik->fields(), ik->constants()); !fs.done(); fs.next()) {
302 BasicType type = Signature::basic_type(fs.signature());
303 // distinction between static and non-static fields is missing
304 if (fs.access_flags().is_static()) continue;
305 has_instance_fields = true;
306 int size = type2aelembytes(type);
307 // INHERITED blocks are marked as non-reference because oop_maps are handled by their holder class
308 LayoutRawBlock* block = new LayoutRawBlock(fs.index(), LayoutRawBlock::INHERITED, size, size, false);
309 block->set_offset(fs.offset());
310 all_fields->append(block);
311 }
312 ik = ik->super() == NULL__null ? NULL__null : InstanceKlass::cast(ik->super());
313 }
314
315 all_fields->sort(LayoutRawBlock::compare_offset);
316 _blocks = new LayoutRawBlock(LayoutRawBlock::RESERVED, instanceOopDesc::base_offset_in_bytes());
317 _blocks->set_offset(0);
318 _last = _blocks;
319
320 for(int i = 0; i < all_fields->length(); i++) {
321 LayoutRawBlock* b = all_fields->at(i);
322 _last->set_next_block(b);
323 b->set_prev_block(_last);
324 _last = b;
325 }
326 _start = _blocks;
327 return has_instance_fields;
328}
329
330// Called during the reconstruction of a layout, after fields from super
331// classes have been inserted. It fills unused slots between inserted fields
332// with EMPTY blocks, so the regular field insertion methods would work.
333// This method handles classes with @Contended annotations differently
334// by inserting PADDING blocks instead of EMPTY block to prevent subclasses'
335// fields to interfere with contended fields/classes.
336void FieldLayout::fill_holes(const InstanceKlass* super_klass) {
337 assert(_blocks != NULL, "Sanity check")do { if (!(_blocks != __null)) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/fieldLayoutBuilder.cpp"
, 337, "assert(" "_blocks != __null" ") failed", "Sanity check"
); ::breakpoint(); } } while (0)
;
338 assert(_blocks->offset() == 0, "first block must be at offset zero")do { if (!(_blocks->offset() == 0)) { (*g_assert_poison) =
'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/fieldLayoutBuilder.cpp"
, 338, "assert(" "_blocks->offset() == 0" ") failed", "first block must be at offset zero"
); ::breakpoint(); } } while (0)
;
339 LayoutRawBlock::Kind filling_type = super_klass->has_contended_annotations() ? LayoutRawBlock::PADDING: LayoutRawBlock::EMPTY;
340 LayoutRawBlock* b = _blocks;
341 while (b->next_block() != NULL__null) {
342 if (b->next_block()->offset() > (b->offset() + b->size())) {
343 int size = b->next_block()->offset() - (b->offset() + b->size());
344 LayoutRawBlock* empty = new LayoutRawBlock(filling_type, size);
345 empty->set_offset(b->offset() + b->size());
346 empty->set_next_block(b->next_block());
347 b->next_block()->set_prev_block(empty);
348 b->set_next_block(empty);
349 empty->set_prev_block(b);
350 }
351 b = b->next_block();
352 }
353 assert(b->next_block() == NULL, "Invariant at this point")do { if (!(b->next_block() == __null)) { (*g_assert_poison
) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/fieldLayoutBuilder.cpp"
, 353, "assert(" "b->next_block() == __null" ") failed", "Invariant at this point"
); ::breakpoint(); } } while (0)
;
354 assert(b->kind() != LayoutRawBlock::EMPTY, "Sanity check")do { if (!(b->kind() != LayoutRawBlock::EMPTY)) { (*g_assert_poison
) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/fieldLayoutBuilder.cpp"
, 354, "assert(" "b->kind() != LayoutRawBlock::EMPTY" ") failed"
, "Sanity check"); ::breakpoint(); } } while (0)
;
355
356 // If the super class has @Contended annotation, a padding block is
357 // inserted at the end to ensure that fields from the subclasses won't share
358 // the cache line of the last field of the contended class
359 if (super_klass->has_contended_annotations() && ContendedPaddingWidth > 0) {
360 LayoutRawBlock* p = new LayoutRawBlock(LayoutRawBlock::PADDING, ContendedPaddingWidth);
361 p->set_offset(b->offset() + b->size());
362 b->set_next_block(p);
363 p->set_prev_block(b);
364 b = p;
365 }
366
367 if (!UseEmptySlotsInSupers) {
368 // Add an empty slots to align fields of the subclass on a heapOopSize boundary
369 // in order to emulate the behavior of the previous algorithm
370 int align = (b->offset() + b->size()) % heapOopSize;
371 if (align != 0) {
372 int sz = heapOopSize - align;
373 LayoutRawBlock* p = new LayoutRawBlock(LayoutRawBlock::EMPTY, sz);
374 p->set_offset(b->offset() + b->size());
375 b->set_next_block(p);
376 p->set_prev_block(b);
377 b = p;
378 }
379 }
380
381 LayoutRawBlock* last = new LayoutRawBlock(LayoutRawBlock::EMPTY, INT_MAX2147483647);
382 last->set_offset(b->offset() + b->size());
383 assert(last->offset() > 0, "Sanity check")do { if (!(last->offset() > 0)) { (*g_assert_poison) = 'X'
;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/fieldLayoutBuilder.cpp"
, 383, "assert(" "last->offset() > 0" ") failed", "Sanity check"
); ::breakpoint(); } } while (0)
;
384 b->set_next_block(last);
385 last->set_prev_block(b);
386 _last = last;
387}
388
389LayoutRawBlock* FieldLayout::insert(LayoutRawBlock* slot, LayoutRawBlock* block) {
390 assert(slot->kind() == LayoutRawBlock::EMPTY, "Blocks can only be inserted in empty blocks")do { if (!(slot->kind() == LayoutRawBlock::EMPTY)) { (*g_assert_poison
) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/fieldLayoutBuilder.cpp"
, 390, "assert(" "slot->kind() == LayoutRawBlock::EMPTY" ") failed"
, "Blocks can only be inserted in empty blocks"); ::breakpoint
(); } } while (0)
;
391 assert(slot->offset() % block->alignment() == 0, "Incompatible alignment")do { if (!(slot->offset() % block->alignment() == 0)) {
(*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/fieldLayoutBuilder.cpp"
, 391, "assert(" "slot->offset() % block->alignment() == 0"
") failed", "Incompatible alignment"); ::breakpoint(); } } while
(0)
;
392 block->set_offset(slot->offset());
393 slot->set_offset(slot->offset() + block->size());
394 assert((slot->size() - block->size()) < slot->size(), "underflow checking")do { if (!((slot->size() - block->size()) < slot->
size())) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/fieldLayoutBuilder.cpp"
, 394, "assert(" "(slot->size() - block->size()) < slot->size()"
") failed", "underflow checking"); ::breakpoint(); } } while
(0)
;
395 assert(slot->size() - block->size() >= 0, "no negative size allowed")do { if (!(slot->size() - block->size() >= 0)) { (*g_assert_poison
) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/fieldLayoutBuilder.cpp"
, 395, "assert(" "slot->size() - block->size() >= 0"
") failed", "no negative size allowed"); ::breakpoint(); } }
while (0)
;
396 slot->set_size(slot->size() - block->size());
397 block->set_prev_block(slot->prev_block());
398 block->set_next_block(slot);
399 slot->set_prev_block(block);
400 if (block->prev_block() != NULL__null) {
401 block->prev_block()->set_next_block(block);
402 }
403 if (_blocks == slot) {
404 _blocks = block;
405 }
406 return block;
407}
408
409void FieldLayout::remove(LayoutRawBlock* block) {
410 assert(block != NULL, "Sanity check")do { if (!(block != __null)) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/fieldLayoutBuilder.cpp"
, 410, "assert(" "block != __null" ") failed", "Sanity check"
); ::breakpoint(); } } while (0)
;
411 assert(block != _last, "Sanity check")do { if (!(block != _last)) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/fieldLayoutBuilder.cpp"
, 411, "assert(" "block != _last" ") failed", "Sanity check")
; ::breakpoint(); } } while (0)
;
412 if (_blocks == block) {
413 _blocks = block->next_block();
414 if (_blocks != NULL__null) {
415 _blocks->set_prev_block(NULL__null);
416 }
417 } else {
418 assert(block->prev_block() != NULL, "_prev should be set for non-head blocks")do { if (!(block->prev_block() != __null)) { (*g_assert_poison
) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/fieldLayoutBuilder.cpp"
, 418, "assert(" "block->prev_block() != __null" ") failed"
, "_prev should be set for non-head blocks"); ::breakpoint();
} } while (0)
;
419 block->prev_block()->set_next_block(block->next_block());
420 block->next_block()->set_prev_block(block->prev_block());
421 }
422 if (block == _start) {
423 _start = block->prev_block();
424 }
425}
426
427void FieldLayout::print(outputStream* output, bool is_static, const InstanceKlass* super) {
428 ResourceMark rm;
429 LayoutRawBlock* b = _blocks;
430 while(b != _last) {
431 switch(b->kind()) {
432 case LayoutRawBlock::REGULAR: {
433 FieldInfo* fi = FieldInfo::from_field_array(_fields, b->field_index());
434 output->print_cr(" @%d \"%s\" %s %d/%d %s",
435 b->offset(),
436 fi->name(_cp)->as_C_string(),
437 fi->signature(_cp)->as_C_string(),
438 b->size(),
439 b->alignment(),
440 "REGULAR");
441 break;
442 }
443 case LayoutRawBlock::FLATTENED: {
444 FieldInfo* fi = FieldInfo::from_field_array(_fields, b->field_index());
445 output->print_cr(" @%d \"%s\" %s %d/%d %s",
446 b->offset(),
447 fi->name(_cp)->as_C_string(),
448 fi->signature(_cp)->as_C_string(),
449 b->size(),
450 b->alignment(),
451 "FLATTENED");
452 break;
453 }
454 case LayoutRawBlock::RESERVED: {
455 output->print_cr(" @%d %d/- %s",
456 b->offset(),
457 b->size(),
458 "RESERVED");
459 break;
460 }
461 case LayoutRawBlock::INHERITED: {
462 assert(!is_static, "Static fields are not inherited in layouts")do { if (!(!is_static)) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/fieldLayoutBuilder.cpp"
, 462, "assert(" "!is_static" ") failed", "Static fields are not inherited in layouts"
); ::breakpoint(); } } while (0)
;
463 assert(super != NULL, "super klass must be provided to retrieve inherited fields info")do { if (!(super != __null)) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/fieldLayoutBuilder.cpp"
, 463, "assert(" "super != __null" ") failed", "super klass must be provided to retrieve inherited fields info"
); ::breakpoint(); } } while (0)
;
464 bool found = false;
465 const InstanceKlass* ik = super;
466 while (!found && ik != NULL__null) {
467 for (AllFieldStream fs(ik->fields(), ik->constants()); !fs.done(); fs.next()) {
468 if (fs.offset() == b->offset()) {
469 output->print_cr(" @%d \"%s\" %s %d/%d %s",
470 b->offset(),
471 fs.name()->as_C_string(),
472 fs.signature()->as_C_string(),
473 b->size(),
474 b->size(), // so far, alignment constraint == size, will change with Valhalla
475 "INHERITED");
476 found = true;
477 break;
478 }
479 }
480 ik = ik->java_super();
481 }
482 break;
483 }
484 case LayoutRawBlock::EMPTY:
485 output->print_cr(" @%d %d/1 %s",
486 b->offset(),
487 b->size(),
488 "EMPTY");
489 break;
490 case LayoutRawBlock::PADDING:
491 output->print_cr(" @%d %d/1 %s",
492 b->offset(),
493 b->size(),
494 "PADDING");
495 break;
496 }
497 b = b->next_block();
498 }
499}
500
501FieldLayoutBuilder::FieldLayoutBuilder(const Symbol* classname, const InstanceKlass* super_klass, ConstantPool* constant_pool,
502 Array<u2>* fields, bool is_contended, FieldLayoutInfo* info) :
503 _classname(classname),
504 _super_klass(super_klass),
505 _constant_pool(constant_pool),
506 _fields(fields),
507 _info(info),
508 _root_group(NULL__null),
509 _contended_groups(GrowableArray<FieldGroup*>(8)),
510 _static_fields(NULL__null),
511 _layout(NULL__null),
512 _static_layout(NULL__null),
513 _nonstatic_oopmap_count(0),
514 _alignment(-1),
515 _has_nonstatic_fields(false),
516 _is_contended(is_contended) {}
517
518
519FieldGroup* FieldLayoutBuilder::get_or_create_contended_group(int g) {
520 assert(g > 0, "must only be called for named contended groups")do { if (!(g > 0)) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/fieldLayoutBuilder.cpp"
, 520, "assert(" "g > 0" ") failed", "must only be called for named contended groups"
); ::breakpoint(); } } while (0)
;
521 FieldGroup* fg = NULL__null;
522 for (int i = 0; i < _contended_groups.length(); i++) {
523 fg = _contended_groups.at(i);
524 if (fg->contended_group() == g) return fg;
525 }
526 fg = new FieldGroup(g);
527 _contended_groups.append(fg);
528 return fg;
529}
530
531void FieldLayoutBuilder::prologue() {
532 _layout = new FieldLayout(_fields, _constant_pool);
533 const InstanceKlass* super_klass = _super_klass;
534 _layout->initialize_instance_layout(super_klass);
535 if (super_klass != NULL__null) {
536 _has_nonstatic_fields = super_klass->has_nonstatic_fields();
537 }
538 _static_layout = new FieldLayout(_fields, _constant_pool);
539 _static_layout->initialize_static_layout();
540 _static_fields = new FieldGroup();
541 _root_group = new FieldGroup();
542}
543
544// Field sorting for regular classes:
545// - fields are sorted in static and non-static fields
546// - non-static fields are also sorted according to their contention group
547// (support of the @Contended annotation)
548// - @Contended annotation is ignored for static fields
549void FieldLayoutBuilder::regular_field_sorting() {
550 for (AllFieldStream fs(_fields, _constant_pool); !fs.done(); fs.next()) {
551 FieldGroup* group = NULL__null;
552 if (fs.access_flags().is_static()) {
553 group = _static_fields;
554 } else {
555 _has_nonstatic_fields = true;
556 if (fs.is_contended()) {
557 int g = fs.contended_group();
558 if (g == 0) {
559 group = new FieldGroup(true);
560 _contended_groups.append(group);
561 } else {
562 group = get_or_create_contended_group(g);
563 }
564 } else {
565 group = _root_group;
566 }
567 }
568 assert(group != NULL, "invariant")do { if (!(group != __null)) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/fieldLayoutBuilder.cpp"
, 568, "assert(" "group != __null" ") failed", "invariant"); ::
breakpoint(); } } while (0)
;
569 BasicType type = Signature::basic_type(fs.signature());
570 switch(type) {
571 case T_BYTE:
572 case T_CHAR:
573 case T_DOUBLE:
574 case T_FLOAT:
575 case T_INT:
576 case T_LONG:
577 case T_SHORT:
578 case T_BOOLEAN:
579 group->add_primitive_field(fs, type);
580 break;
581 case T_OBJECT:
582 case T_ARRAY:
583 if (group != _static_fields) _nonstatic_oopmap_count++;
584 group->add_oop_field(fs);
585 break;
586 default:
587 fatal("Something wrong?")do { (*g_assert_poison) = 'X';; report_fatal(INTERNAL_ERROR, "/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/fieldLayoutBuilder.cpp"
, 587, "Something wrong?"); ::breakpoint(); } while (0)
;
588 }
589 }
590 _root_group->sort_by_size();
591 _static_fields->sort_by_size();
592 if (!_contended_groups.is_empty()) {
593 for (int i = 0; i < _contended_groups.length(); i++) {
594 _contended_groups.at(i)->sort_by_size();
595 }
596 }
597}
598
599void FieldLayoutBuilder::insert_contended_padding(LayoutRawBlock* slot) {
600 if (ContendedPaddingWidth > 0) {
601 LayoutRawBlock* padding = new LayoutRawBlock(LayoutRawBlock::PADDING, ContendedPaddingWidth);
602 _layout->insert(slot, padding);
603 }
604}
605
606// Computation of regular classes layout is an evolution of the previous default layout
607// (FieldAllocationStyle 1):
608// - primitive fields are allocated first (from the biggest to the smallest)
609// - then oop fields are allocated, either in existing gaps or at the end of
610// the layout
611void FieldLayoutBuilder::compute_regular_layout() {
612 bool need_tail_padding = false;
613 prologue();
614 regular_field_sorting();
615
616 if (_is_contended) {
2
Assuming field '_is_contended' is false
3
Taking false branch
617 _layout->set_start(_layout->last_block());
618 // insertion is currently easy because the current strategy doesn't try to fill holes
619 // in super classes layouts => the _start block is by consequence the _last_block
620 insert_contended_padding(_layout->start());
621 need_tail_padding = true;
622 }
623 _layout->add(_root_group->primitive_fields());
4
Calling 'FieldLayout::add'
624 _layout->add(_root_group->oop_fields());
625
626 if (!_contended_groups.is_empty()) {
627 for (int i = 0; i < _contended_groups.length(); i++) {
628 FieldGroup* cg = _contended_groups.at(i);
629 LayoutRawBlock* start = _layout->last_block();
630 insert_contended_padding(start);
631 _layout->add(cg->primitive_fields(), start);
632 _layout->add(cg->oop_fields(), start);
633 need_tail_padding = true;
634 }
635 }
636
637 if (need_tail_padding) {
638 insert_contended_padding(_layout->last_block());
639 }
640
641 _static_layout->add_contiguously(this->_static_fields->oop_fields());
642 _static_layout->add(this->_static_fields->primitive_fields());
643
644 epilogue();
645}
646
647void FieldLayoutBuilder::epilogue() {
648 // Computing oopmaps
649 int super_oop_map_count = (_super_klass == NULL__null) ? 0 :_super_klass->nonstatic_oop_map_count();
650 int max_oop_map_count = super_oop_map_count + _nonstatic_oopmap_count;
651
652 OopMapBlocksBuilder* nonstatic_oop_maps =
653 new OopMapBlocksBuilder(max_oop_map_count);
654 if (super_oop_map_count > 0) {
655 nonstatic_oop_maps->initialize_inherited_blocks(_super_klass->start_of_nonstatic_oop_maps(),
656 _super_klass->nonstatic_oop_map_count());
657 }
658
659 if (_root_group->oop_fields() != NULL__null) {
660 for (int i = 0; i < _root_group->oop_fields()->length(); i++) {
661 LayoutRawBlock* b = _root_group->oop_fields()->at(i);
662 nonstatic_oop_maps->add(b->offset(), 1);
663 }
664 }
665
666 if (!_contended_groups.is_empty()) {
667 for (int i = 0; i < _contended_groups.length(); i++) {
668 FieldGroup* cg = _contended_groups.at(i);
669 if (cg->oop_count() > 0) {
670 assert(cg->oop_fields() != NULL && cg->oop_fields()->at(0) != NULL, "oop_count > 0 but no oop fields found")do { if (!(cg->oop_fields() != __null && cg->oop_fields
()->at(0) != __null)) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/fieldLayoutBuilder.cpp"
, 670, "assert(" "cg->oop_fields() != __null && cg->oop_fields()->at(0) != __null"
") failed", "oop_count > 0 but no oop fields found"); ::breakpoint
(); } } while (0)
;
671 nonstatic_oop_maps->add(cg->oop_fields()->at(0)->offset(), cg->oop_count());
672 }
673 }
674 }
675
676 nonstatic_oop_maps->compact();
677
678 int instance_end = align_up(_layout->last_block()->offset(), wordSize);
679 int static_fields_end = align_up(_static_layout->last_block()->offset(), wordSize);
680 int static_fields_size = (static_fields_end -
681 InstanceMirrorKlass::offset_of_static_fields()) / wordSize;
682 int nonstatic_field_end = align_up(_layout->last_block()->offset(), heapOopSize);
683
684 // Pass back information needed for InstanceKlass creation
685
686 _info->oop_map_blocks = nonstatic_oop_maps;
687 _info->_instance_size = align_object_size(instance_end / wordSize);
688 _info->_static_field_size = static_fields_size;
689 _info->_nonstatic_field_size = (nonstatic_field_end - instanceOopDesc::base_offset_in_bytes()) / heapOopSize;
690 _info->_has_nonstatic_fields = _has_nonstatic_fields;
691
692 if (PrintFieldLayout) {
693 ResourceMark rm;
694 tty->print_cr("Layout of class %s", _classname->as_C_string());
695 tty->print_cr("Instance fields:");
696 _layout->print(tty, false, _super_klass);
697 tty->print_cr("Static fields:");
698 _static_layout->print(tty, true, NULL__null);
699 tty->print_cr("Instance size = %d bytes", _info->_instance_size * wordSize);
700 tty->print_cr("---");
701 }
702}
703
704void FieldLayoutBuilder::build_layout() {
705 compute_regular_layout();
1
Calling 'FieldLayoutBuilder::compute_regular_layout'
706}

/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/fieldLayoutBuilder.hpp

1/*
2 * Copyright (c) 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
37// A LayoutRawBlock describes an element of a layout.
38// Each field is represented by a LayoutRawBlock.
39// LayoutRawBlocks can also represent elements injected by the JVM:
40// padding, empty blocks, inherited fields, etc.
41// All LayoutRawBlocks must have a size and an alignment. The size is the
42// exact size of the field expressed in bytes. The alignment is
43// the alignment constraint of the field (1 for byte, 2 for short,
44// 4 for int, 8 for long, etc.)
45//
46// LayoutRawBlock are designed to be used in two data structures:
47// - a linked list in a layout (using _next_block, _prev_block)
48// - a GrowableArray in field group (the growable array contains pointers to LayoutRawBlocks)
49//
50// next/prev pointers are included in the LayoutRawBlock class to narrow
51// the number of allocation required during the computation of a layout.
52//
53class LayoutRawBlock : public ResourceObj {
54 public:
55 // Some code relies on the order of values below.
56 enum Kind {
57 EMPTY, // empty slot, space is taken from this to allocate fields
58 RESERVED, // reserved for JVM usage (for instance object header)
59 PADDING, // padding (because of alignment constraints or @Contended)
60 REGULAR, // primitive or oop field (including non-flattened inline fields)
61 FLATTENED, // flattened field
62 INHERITED // field(s) inherited from super classes
63 };
64
65 private:
66 LayoutRawBlock* _next_block;
67 LayoutRawBlock* _prev_block;
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")do { if (!(_offset >= 0)) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/fieldLayoutBuilder.hpp"
, 84, "assert(" "_offset >= 0" ") failed", "Must be initialized"
); ::breakpoint(); } } while (0)
;
85 return _offset;
86 }
87 void set_offset(int offset) { _offset = offset; }
88 int alignment() const { return _alignment; }
20
Returning zero
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")do { if (!(_field_index != -1)) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/fieldLayoutBuilder.hpp"
, 92, "assert(" "_field_index != -1" ") failed", "Must be initialized"
); ::breakpoint(); } } while (0)
;
93 return _field_index;
94 }
95 bool is_reference() const { return _is_reference; }
96
97 bool fit(int size, int alignment);
98
99 static int compare_offset(LayoutRawBlock** x, LayoutRawBlock** y) { return (*x)->offset() - (*y)->offset(); }
100 // compare_size_inverted() returns the opposite of a regular compare method in order to
101 // sort fields in decreasing order.
102 // Note: with line types, the comparison should include alignment constraint if sizes are equals
103 static int compare_size_inverted(LayoutRawBlock** x, LayoutRawBlock** y) {
104#ifdef _WINDOWS
105 // qsort() on Windows reverse the order of fields with the same size
106 // the extension of the comparison function below preserves this order
107 int diff = (*y)->size() - (*x)->size();
108 if (diff == 0) {
109 diff = (*x)->field_index() - (*y)->field_index();
110 }
111 return diff;
112#else
113 return (*y)->size() - (*x)->size();
114#endif // _WINDOWS
115 }
116
117};
118
119// A Field group represents a set of fields that have to be allocated together,
120// this is the way the @Contended annotation is supported.
121// Inside a FieldGroup, fields are sorted based on their kind: primitive,
122// oop, or flattened.
123//
124class FieldGroup : public ResourceObj {
125
126 private:
127 FieldGroup* _next;
128 GrowableArray<LayoutRawBlock*>* _primitive_fields;
129 GrowableArray<LayoutRawBlock*>* _oop_fields;
130 int _contended_group;
131 int _oop_count;
132 static const int INITIAL_LIST_SIZE = 16;
133
134 public:
135 FieldGroup(int contended_group = -1);
136
137 FieldGroup* next() const { return _next; }
138 void set_next(FieldGroup* next) { _next = next; }
139 GrowableArray<LayoutRawBlock*>* primitive_fields() const { return _primitive_fields; }
140 GrowableArray<LayoutRawBlock*>* oop_fields() const { return _oop_fields; }
141 int contended_group() const { return _contended_group; }
142 int oop_count() const { return _oop_count; }
143
144 void add_primitive_field(AllFieldStream fs, BasicType type);
145 void add_oop_field(AllFieldStream fs);
146 void sort_by_size();
147};
148
149// The FieldLayout class represents a set of fields organized
150// in a layout.
151// An instance of FieldLayout can either represent the layout
152// of non-static fields (used in an instance object) or the
153// layout of static fields (to be included in the class mirror).
154//
155// _block is a pointer to a list of LayoutRawBlock ordered by increasing
156// offsets.
157// _start points to the LayoutRawBlock with the first offset that can
158// be used to allocate fields of the current class
159// _last points to the last LayoutRawBlock of the list. In order to
160// simplify the code, the LayoutRawBlock list always ends with an
161// EMPTY block (the kind of LayoutRawBlock from which space is taken
162// to allocate fields) with a size big enough to satisfy all
163// field allocations.
164//
165class FieldLayout : public ResourceObj {
166 private:
167 Array<u2>* _fields;
168 ConstantPool* _cp;
169 LayoutRawBlock* _blocks; // the layout being computed
170 LayoutRawBlock* _start; // points to the first block where a field can be inserted
171 LayoutRawBlock* _last; // points to the last block of the layout (big empty block)
172
173 public:
174 FieldLayout(Array<u2>* fields, ConstantPool* cp);
175 void initialize_static_layout();
176 void initialize_instance_layout(const InstanceKlass* ik);
177
178 LayoutRawBlock* first_empty_block() {
179 LayoutRawBlock* block = _start;
180 while (block->kind() != LayoutRawBlock::EMPTY) {
181 block = block->next_block();
182 }
183 return block;
184 }
185
186 LayoutRawBlock* start() { return _start; }
187 void set_start(LayoutRawBlock* start) { _start = start; }
188 LayoutRawBlock* last_block() { return _last; }
189
190 LayoutRawBlock* first_field_block();
191 void add(GrowableArray<LayoutRawBlock*>* list, LayoutRawBlock* start = NULL__null);
192 void add_field_at_offset(LayoutRawBlock* blocks, int offset, LayoutRawBlock* start = NULL__null);
193 void add_contiguously(GrowableArray<LayoutRawBlock*>* list, LayoutRawBlock* start = NULL__null);
194 LayoutRawBlock* insert_field_block(LayoutRawBlock* slot, LayoutRawBlock* block);
195 bool reconstruct_layout(const InstanceKlass* ik);
196 void fill_holes(const InstanceKlass* ik);
197 LayoutRawBlock* insert(LayoutRawBlock* slot, LayoutRawBlock* block);
198 void remove(LayoutRawBlock* block);
199 void print(outputStream* output, bool is_static, const InstanceKlass* super);
200};
201
202
203// FieldLayoutBuilder is the main entry point for layout computation.
204// This class has three methods to generate layout: one for regular classes
205// and two for classes with hard coded offsets (java,lang.ref.Reference
206// and the boxing classes). The rationale for having multiple methods
207// is that each kind of class has a different set goals regarding
208// its layout, so instead of mixing several layout strategies into a
209// single method, each kind has its own method (see comments below
210// for more details about the allocation strategies).
211//
212// Computing the layout of a class always goes through 4 steps:
213// 1 - Prologue: preparation of data structure and gathering of
214// layout information inherited from super classes
215// 2 - Field sorting: fields are sorted according to their
216// kind (oop, primitive, inline class) and their contention
217// annotation (if any)
218// 3 - Layout is computed from the set of lists generated during
219// step 2
220// 4 - Epilogue: oopmaps are generated, layout information is
221// prepared so other VM components can use it (instance size,
222// static field size, non-static field size, etc.)
223//
224// Steps 1 and 4 are common to all layout computations. Step 2 and 3
225// can vary with the allocation strategy.
226//
227class FieldLayoutBuilder : public ResourceObj {
228 private:
229
230 const Symbol* _classname;
231 const InstanceKlass* _super_klass;
232 ConstantPool* _constant_pool;
233 Array<u2>* _fields;
234 FieldLayoutInfo* _info;
235 FieldGroup* _root_group;
236 GrowableArray<FieldGroup*> _contended_groups;
237 FieldGroup* _static_fields;
238 FieldLayout* _layout;
239 FieldLayout* _static_layout;
240 int _nonstatic_oopmap_count;
241 int _alignment;
242 bool _has_nonstatic_fields;
243 bool _is_contended; // is a contended class?
244
245 public:
246 FieldLayoutBuilder(const Symbol* classname, const InstanceKlass* super_klass, ConstantPool* constant_pool,
247 Array<u2>* fields, bool is_contended, FieldLayoutInfo* info);
248
249 int get_alignment() {
250 assert(_alignment != -1, "Uninitialized")do { if (!(_alignment != -1)) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/fieldLayoutBuilder.hpp"
, 250, "assert(" "_alignment != -1" ") failed", "Uninitialized"
); ::breakpoint(); } } while (0)
;
251 return _alignment;
252 }
253
254 void build_layout();
255 void compute_regular_layout();
256 void insert_contended_padding(LayoutRawBlock* slot);
257
258 private:
259 void prologue();
260 void epilogue();
261 void regular_field_sorting();
262 FieldGroup* get_or_create_contended_group(int g);
263};
264
265#endif // SHARE_CLASSFILE_FIELDLAYOUTBUILDER_HPP