Skip to content

Commit bfb812a

Browse files
fparainJohn R Roseplummercj
committed
8292818: replace 96-bit representation for field metadata with variable-sized streams
Co-authored-by: John R Rose <jrose@openjdk.org> Co-authored-by: Chris Plummer <cjplummer@openjdk.org> Reviewed-by: dholmes, coleenp, cjplummer, dnsimon
1 parent 932be35 commit bfb812a

File tree

54 files changed

+1305
-861
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

54 files changed

+1305
-861
lines changed

src/hotspot/share/ci/ciField.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,7 @@ static bool trust_final_non_static_fields(ciInstanceKlass* holder) {
255255

256256
void ciField::initialize_from(fieldDescriptor* fd) {
257257
// Get the flags, offset, and canonical holder of the field.
258-
_flags = ciFlags(fd->access_flags());
258+
_flags = ciFlags(fd->access_flags(), fd->field_flags().is_stable(), fd->field_status().is_initialized_final_update());
259259
_offset = fd->offset();
260260
Klass* field_holder = fd->field_holder();
261261
assert(field_holder != nullptr, "null field_holder");

src/hotspot/share/ci/ciFlags.hpp

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -40,9 +40,12 @@ class ciFlags {
4040
friend class ciMethod;
4141

4242
jint _flags;
43+
bool _stable;
44+
bool _intialized_final_update;
4345

44-
ciFlags() { _flags = 0; }
45-
ciFlags(AccessFlags flags) { _flags = flags.as_int(); }
46+
ciFlags() :_flags(0), _stable(false), _intialized_final_update(false) { }
47+
ciFlags(AccessFlags flags, bool is_stable = false, bool is_initialized_final_update = false) :
48+
_flags(flags.as_int()), _stable(is_stable), _intialized_final_update(is_initialized_final_update) { }
4649

4750
public:
4851
// Java access flags
@@ -58,12 +61,12 @@ class ciFlags {
5861
bool is_native () const { return (_flags & JVM_ACC_NATIVE ) != 0; }
5962
bool is_interface () const { return (_flags & JVM_ACC_INTERFACE ) != 0; }
6063
bool is_abstract () const { return (_flags & JVM_ACC_ABSTRACT ) != 0; }
61-
bool is_stable () const { return (_flags & JVM_ACC_FIELD_STABLE ) != 0; }
64+
bool is_stable () const { return _stable; }
6265
// In case the current object represents a field, return true if
6366
// the field is modified outside of instance initializer methods
6467
// (or class/initializer methods if the field is static) and false
6568
// otherwise.
66-
bool has_initialized_final_update() const { return (_flags & JVM_ACC_FIELD_INITIALIZED_FINAL_UPDATE) != 0; };
69+
bool has_initialized_final_update() const { return _intialized_final_update; };
6770

6871
// Conversion
6972
jint as_int() { return _flags; }

src/hotspot/share/classfile/classFileParser.cpp

Lines changed: 57 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
#include "memory/universe.hpp"
4949
#include "oops/annotations.hpp"
5050
#include "oops/constantPool.inline.hpp"
51+
#include "oops/fieldInfo.hpp"
5152
#include "oops/fieldStreams.inline.hpp"
5253
#include "oops/instanceKlass.inline.hpp"
5354
#include "oops/instanceMirrorKlass.hpp"
@@ -1471,7 +1472,6 @@ void ClassFileParser::parse_fields(const ClassFileStream* const cfs,
14711472
assert(cp != nullptr, "invariant");
14721473
assert(java_fields_count_ptr != nullptr, "invariant");
14731474

1474-
assert(nullptr == _fields, "invariant");
14751475
assert(nullptr == _fields_annotations, "invariant");
14761476
assert(nullptr == _fields_type_annotations, "invariant");
14771477

@@ -1484,34 +1484,11 @@ void ClassFileParser::parse_fields(const ClassFileStream* const cfs,
14841484
&num_injected);
14851485
const int total_fields = length + num_injected;
14861486

1487-
// The field array starts with tuples of shorts
1488-
// [access, name index, sig index, initial value index, byte offset].
1489-
// A generic signature slot only exists for field with generic
1490-
// signature attribute. And the access flag is set with
1491-
// JVM_ACC_FIELD_HAS_GENERIC_SIGNATURE for that field. The generic
1492-
// signature slots are at the end of the field array and after all
1493-
// other fields data.
1494-
//
1495-
// f1: [access, name index, sig index, initial value index, low_offset, high_offset]
1496-
// f2: [access, name index, sig index, initial value index, low_offset, high_offset]
1497-
// ...
1498-
// fn: [access, name index, sig index, initial value index, low_offset, high_offset]
1499-
// [generic signature index]
1500-
// [generic signature index]
1501-
// ...
1502-
//
1503-
// Allocate a temporary resource array for field data. For each field,
1504-
// a slot is reserved in the temporary array for the generic signature
1505-
// index. After parsing all fields, the data are copied to a permanent
1506-
// array and any unused slots will be discarded.
1507-
ResourceMark rm(THREAD);
1508-
u2* const fa = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD,
1509-
u2,
1510-
total_fields * (FieldInfo::field_slots + 1));
1487+
// Allocate a temporary resource array to collect field data.
1488+
// After parsing all fields, data are stored in a UNSIGNED5 compressed stream.
1489+
_temp_field_info = new GrowableArray<FieldInfo>(total_fields);
15111490

1512-
// The generic signature slots start after all other fields' data.
1513-
int generic_signature_slot = total_fields * FieldInfo::field_slots;
1514-
int num_generic_signature = 0;
1491+
ResourceMark rm(THREAD);
15151492
for (int n = 0; n < length; n++) {
15161493
// access_flags, name_index, descriptor_index, attributes_count
15171494
cfs->guarantee_more(8, CHECK);
@@ -1520,6 +1497,7 @@ void ClassFileParser::parse_fields(const ClassFileStream* const cfs,
15201497
const jint flags = cfs->get_u2_fast() & JVM_RECOGNIZED_FIELD_MODIFIERS;
15211498
verify_legal_field_modifiers(flags, is_interface, CHECK);
15221499
access_flags.set_flags(flags);
1500+
FieldInfo::FieldFlags fieldFlags(0);
15231501

15241502
const u2 name_index = cfs->get_u2_fast();
15251503
check_property(valid_symbol_at(name_index),
@@ -1578,31 +1556,27 @@ void ClassFileParser::parse_fields(const ClassFileStream* const cfs,
15781556
access_flags.set_is_synthetic();
15791557
}
15801558
if (generic_signature_index != 0) {
1581-
access_flags.set_field_has_generic_signature();
1582-
fa[generic_signature_slot] = generic_signature_index;
1583-
generic_signature_slot ++;
1584-
num_generic_signature ++;
1559+
fieldFlags.update_generic(true);
15851560
}
15861561
}
15871562

1588-
FieldInfo* const field = FieldInfo::from_field_array(fa, n);
1589-
field->initialize(access_flags.as_short(),
1590-
name_index,
1591-
signature_index,
1592-
constantvalue_index);
15931563
const BasicType type = cp->basic_type_for_signature_at(signature_index);
15941564

15951565
// Update FieldAllocationCount for this kind of field
15961566
fac->update(is_static, type);
15971567

1598-
// After field is initialized with type, we can augment it with aux info
1599-
if (parsed_annotations.has_any_annotations()) {
1600-
parsed_annotations.apply_to(field);
1601-
if (field->is_contended()) {
1602-
_has_contended_fields = true;
1603-
}
1568+
FieldInfo fi(access_flags, name_index, signature_index, constantvalue_index, fieldFlags);
1569+
fi.set_index(n);
1570+
if (fieldFlags.is_generic()) {
1571+
fi.set_generic_signature_index(generic_signature_index);
16041572
}
1573+
parsed_annotations.apply_to(&fi);
1574+
if (fi.field_flags().is_contended()) {
1575+
_has_contended_fields = true;
1576+
}
1577+
_temp_field_info->append(fi);
16051578
}
1579+
assert(_temp_field_info->length() == length, "Must be");
16061580

16071581
int index = length;
16081582
if (num_injected != 0) {
@@ -1613,7 +1587,7 @@ void ClassFileParser::parse_fields(const ClassFileStream* const cfs,
16131587
const Symbol* const signature = injected[n].signature();
16141588
bool duplicate = false;
16151589
for (int i = 0; i < length; i++) {
1616-
const FieldInfo* const f = FieldInfo::from_field_array(fa, i);
1590+
const FieldInfo* const f = _temp_field_info->adr_at(i);
16171591
if (name == cp->symbol_at(f->name_index()) &&
16181592
signature == cp->symbol_at(f->signature_index())) {
16191593
// Symbol is desclared in Java so skip this one
@@ -1628,41 +1602,21 @@ void ClassFileParser::parse_fields(const ClassFileStream* const cfs,
16281602
}
16291603

16301604
// Injected field
1631-
FieldInfo* const field = FieldInfo::from_field_array(fa, index);
1632-
field->initialize((u2)JVM_ACC_FIELD_INTERNAL,
1633-
(u2)(injected[n].name_index),
1634-
(u2)(injected[n].signature_index),
1635-
0);
1636-
1637-
const BasicType type = Signature::basic_type(injected[n].signature());
1605+
FieldInfo::FieldFlags fflags(0);
1606+
fflags.update_injected(true);
1607+
AccessFlags aflags;
1608+
FieldInfo fi(aflags, (u2)(injected[n].name_index), (u2)(injected[n].signature_index), 0, fflags);
1609+
fi.set_index(index);
1610+
_temp_field_info->append(fi);
16381611

16391612
// Update FieldAllocationCount for this kind of field
1613+
const BasicType type = Signature::basic_type(injected[n].signature());
16401614
fac->update(false, type);
16411615
index++;
16421616
}
16431617
}
16441618

1645-
assert(nullptr == _fields, "invariant");
1646-
1647-
_fields =
1648-
MetadataFactory::new_array<u2>(_loader_data,
1649-
index * FieldInfo::field_slots + num_generic_signature,
1650-
CHECK);
1651-
// Sometimes injected fields already exist in the Java source so
1652-
// the fields array could be too long. In that case the
1653-
// fields array is trimmed. Also unused slots that were reserved
1654-
// for generic signature indexes are discarded.
1655-
{
1656-
int i = 0;
1657-
for (; i < index * FieldInfo::field_slots; i++) {
1658-
_fields->at_put(i, fa[i]);
1659-
}
1660-
for (int j = total_fields * FieldInfo::field_slots;
1661-
j < generic_signature_slot; j++) {
1662-
_fields->at_put(i++, fa[j]);
1663-
}
1664-
assert(_fields->length() == i, "");
1665-
}
1619+
assert(_temp_field_info->length() == index, "Must be");
16661620

16671621
if (_need_verify && length > 1) {
16681622
// Check duplicated fields
@@ -1675,9 +1629,9 @@ void ClassFileParser::parse_fields(const ClassFileStream* const cfs,
16751629
const Symbol* sig = nullptr;
16761630
{
16771631
debug_only(NoSafepointVerifier nsv;)
1678-
for (AllFieldStream fs(_fields, cp); !fs.done(); fs.next()) {
1679-
name = fs.name();
1680-
sig = fs.signature();
1632+
for (int i = 0; i < _temp_field_info->length(); i++) {
1633+
name = _temp_field_info->adr_at(i)->name(_cp);
1634+
sig = _temp_field_info->adr_at(i)->signature(_cp);
16811635
// If no duplicates, add name/signature in hashtable names_and_sigs.
16821636
if (!put_after_lookup(name, sig, names_and_sigs)) {
16831637
dup = true;
@@ -2055,9 +2009,10 @@ AnnotationCollector::annotation_index(const ClassLoaderData* loader_data,
20552009

20562010
void ClassFileParser::FieldAnnotationCollector::apply_to(FieldInfo* f) {
20572011
if (is_contended())
2012+
// Setting the contended group also sets the contended bit in field flags
20582013
f->set_contended_group(contended_group());
20592014
if (is_stable())
2060-
f->set_stable(true);
2015+
(f->field_flags_addr())->update_stable(true);
20612016
}
20622017

20632018
ClassFileParser::FieldAnnotationCollector::~FieldAnnotationCollector() {
@@ -3969,7 +3924,8 @@ void ClassFileParser::apply_parsed_class_metadata(
39693924

39703925
_cp->set_pool_holder(this_klass);
39713926
this_klass->set_constants(_cp);
3972-
this_klass->set_fields(_fields, java_fields_count);
3927+
this_klass->set_fieldinfo_stream(_fieldinfo_stream);
3928+
this_klass->set_fields_status(_fields_status);
39733929
this_klass->set_methods(_methods);
39743930
this_klass->set_inner_classes(_inner_classes);
39753931
this_klass->set_nest_members(_nest_members);
@@ -5316,7 +5272,8 @@ void ClassFileParser::fill_instance_klass(InstanceKlass* ik,
53165272

53175273
// note that is not safe to use the fields in the parser from this point on
53185274
assert(nullptr == _cp, "invariant");
5319-
assert(nullptr == _fields, "invariant");
5275+
assert(nullptr == _fieldinfo_stream, "invariant");
5276+
assert(nullptr == _fields_status, "invariant");
53205277
assert(nullptr == _methods, "invariant");
53215278
assert(nullptr == _inner_classes, "invariant");
53225279
assert(nullptr == _nest_members, "invariant");
@@ -5548,7 +5505,8 @@ ClassFileParser::ClassFileParser(ClassFileStream* stream,
55485505
_orig_cp_size(0),
55495506
_super_klass(),
55505507
_cp(nullptr),
5551-
_fields(nullptr),
5508+
_fieldinfo_stream(nullptr),
5509+
_fields_status(nullptr),
55525510
_methods(nullptr),
55535511
_inner_classes(nullptr),
55545512
_nest_members(nullptr),
@@ -5567,6 +5525,7 @@ ClassFileParser::ClassFileParser(ClassFileStream* stream,
55675525
_parsed_annotations(nullptr),
55685526
_fac(nullptr),
55695527
_field_info(nullptr),
5528+
_temp_field_info(nullptr),
55705529
_method_ordering(nullptr),
55715530
_all_mirandas(nullptr),
55725531
_vtable_size(0),
@@ -5638,7 +5597,8 @@ void ClassFileParser::clear_class_metadata() {
56385597
// metadata created before the instance klass is created. Must be
56395598
// deallocated if classfile parsing returns an error.
56405599
_cp = nullptr;
5641-
_fields = nullptr;
5600+
_fieldinfo_stream = nullptr;
5601+
_fields_status = nullptr;
56425602
_methods = nullptr;
56435603
_inner_classes = nullptr;
56445604
_nest_members = nullptr;
@@ -5656,8 +5616,13 @@ ClassFileParser::~ClassFileParser() {
56565616
if (_cp != nullptr) {
56575617
MetadataFactory::free_metadata(_loader_data, _cp);
56585618
}
5659-
if (_fields != nullptr) {
5660-
MetadataFactory::free_array<u2>(_loader_data, _fields);
5619+
5620+
if (_fieldinfo_stream != nullptr) {
5621+
MetadataFactory::free_array<u1>(_loader_data, _fieldinfo_stream);
5622+
}
5623+
5624+
if (_fields_status != nullptr) {
5625+
MetadataFactory::free_array<FieldStatus>(_loader_data, _fields_status);
56615626
}
56625627

56635628
if (_methods != nullptr) {
@@ -5894,7 +5859,7 @@ void ClassFileParser::parse_stream(const ClassFileStream* const stream,
58945859
&_java_fields_count,
58955860
CHECK);
58965861

5897-
assert(_fields != nullptr, "invariant");
5862+
assert(_temp_field_info != nullptr, "invariant");
58985863

58995864
// Methods
59005865
parse_methods(stream,
@@ -6050,9 +6015,17 @@ void ClassFileParser::post_process_parsed_stream(const ClassFileStream* const st
60506015
assert(_parsed_annotations != nullptr, "invariant");
60516016

60526017
_field_info = new FieldLayoutInfo();
6053-
FieldLayoutBuilder lb(class_name(), super_klass(), _cp, _fields,
6018+
FieldLayoutBuilder lb(class_name(), super_klass(), _cp, /*_fields*/ _temp_field_info,
60546019
_parsed_annotations->is_contended(), _field_info);
60556020
lb.build_layout();
6021+
6022+
int injected_fields_count = _temp_field_info->length() - _java_fields_count;
6023+
_fieldinfo_stream =
6024+
FieldInfoStream::create_FieldInfoStream(_temp_field_info, _java_fields_count,
6025+
injected_fields_count, loader_data(), CHECK);
6026+
_fields_status =
6027+
MetadataFactory::new_array<FieldStatus>(_loader_data, _temp_field_info->length(),
6028+
FieldStatus(0), CHECK);
60566029
}
60576030

60586031
void ClassFileParser::set_klass(InstanceKlass* klass) {

src/hotspot/share/classfile/classFileParser.hpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include "memory/referenceType.hpp"
2929
#include "oops/annotations.hpp"
3030
#include "oops/constantPool.hpp"
31+
#include "oops/fieldInfo.hpp"
3132
#include "oops/instanceKlass.hpp"
3233
#include "oops/typeArrayOop.hpp"
3334
#include "utilities/accessFlags.hpp"
@@ -121,7 +122,8 @@ class ClassFileParser {
121122
// in which case these pointers have been set to null.
122123
const InstanceKlass* _super_klass;
123124
ConstantPool* _cp;
124-
Array<u2>* _fields;
125+
Array<u1>* _fieldinfo_stream;
126+
Array<FieldStatus>* _fields_status;
125127
Array<Method*>* _methods;
126128
Array<u2>* _inner_classes;
127129
Array<u2>* _nest_members;
@@ -141,6 +143,7 @@ class ClassFileParser {
141143
ClassAnnotationCollector* _parsed_annotations;
142144
FieldAllocationCount* _fac;
143145
FieldLayoutInfo* _field_info;
146+
GrowableArray<FieldInfo>* _temp_field_info;
144147
const intArray* _method_ordering;
145148
GrowableArray<Method*>* _all_mirandas;
146149

0 commit comments

Comments
 (0)