Skip to content

Commit

Permalink
8292818: replace 96-bit representation for field metadata with variab…
Browse files Browse the repository at this point in the history
…le-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
  • Loading branch information
3 people committed Mar 17, 2023
1 parent 932be35 commit bfb812a
Show file tree
Hide file tree
Showing 54 changed files with 1,305 additions and 861 deletions.
2 changes: 1 addition & 1 deletion src/hotspot/share/ci/ciField.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@ static bool trust_final_non_static_fields(ciInstanceKlass* holder) {

void ciField::initialize_from(fieldDescriptor* fd) {
// Get the flags, offset, and canonical holder of the field.
_flags = ciFlags(fd->access_flags());
_flags = ciFlags(fd->access_flags(), fd->field_flags().is_stable(), fd->field_status().is_initialized_final_update());
_offset = fd->offset();
Klass* field_holder = fd->field_holder();
assert(field_holder != nullptr, "null field_holder");
Expand Down
13 changes: 8 additions & 5 deletions src/hotspot/share/ci/ciFlags.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2023, 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
Expand Down Expand Up @@ -40,9 +40,12 @@ class ciFlags {
friend class ciMethod;

jint _flags;
bool _stable;
bool _intialized_final_update;

ciFlags() { _flags = 0; }
ciFlags(AccessFlags flags) { _flags = flags.as_int(); }
ciFlags() :_flags(0), _stable(false), _intialized_final_update(false) { }
ciFlags(AccessFlags flags, bool is_stable = false, bool is_initialized_final_update = false) :
_flags(flags.as_int()), _stable(is_stable), _intialized_final_update(is_initialized_final_update) { }

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

// Conversion
jint as_int() { return _flags; }
Expand Down
141 changes: 57 additions & 84 deletions src/hotspot/share/classfile/classFileParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
#include "memory/universe.hpp"
#include "oops/annotations.hpp"
#include "oops/constantPool.inline.hpp"
#include "oops/fieldInfo.hpp"
#include "oops/fieldStreams.inline.hpp"
#include "oops/instanceKlass.inline.hpp"
#include "oops/instanceMirrorKlass.hpp"
Expand Down Expand Up @@ -1471,7 +1472,6 @@ void ClassFileParser::parse_fields(const ClassFileStream* const cfs,
assert(cp != nullptr, "invariant");
assert(java_fields_count_ptr != nullptr, "invariant");

assert(nullptr == _fields, "invariant");
assert(nullptr == _fields_annotations, "invariant");
assert(nullptr == _fields_type_annotations, "invariant");

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

// The field array starts with tuples of shorts
// [access, name index, sig index, initial value index, byte offset].
// A generic signature slot only exists for field with generic
// signature attribute. And the access flag is set with
// JVM_ACC_FIELD_HAS_GENERIC_SIGNATURE for that field. The generic
// signature slots are at the end of the field array and after all
// other fields data.
//
// f1: [access, name index, sig index, initial value index, low_offset, high_offset]
// f2: [access, name index, sig index, initial value index, low_offset, high_offset]
// ...
// fn: [access, name index, sig index, initial value index, low_offset, high_offset]
// [generic signature index]
// [generic signature index]
// ...
//
// Allocate a temporary resource array for field data. For each field,
// a slot is reserved in the temporary array for the generic signature
// index. After parsing all fields, the data are copied to a permanent
// array and any unused slots will be discarded.
ResourceMark rm(THREAD);
u2* const fa = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD,
u2,
total_fields * (FieldInfo::field_slots + 1));
// Allocate a temporary resource array to collect field data.
// After parsing all fields, data are stored in a UNSIGNED5 compressed stream.
_temp_field_info = new GrowableArray<FieldInfo>(total_fields);

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

const u2 name_index = cfs->get_u2_fast();
check_property(valid_symbol_at(name_index),
Expand Down Expand Up @@ -1578,31 +1556,27 @@ void ClassFileParser::parse_fields(const ClassFileStream* const cfs,
access_flags.set_is_synthetic();
}
if (generic_signature_index != 0) {
access_flags.set_field_has_generic_signature();
fa[generic_signature_slot] = generic_signature_index;
generic_signature_slot ++;
num_generic_signature ++;
fieldFlags.update_generic(true);
}
}

FieldInfo* const field = FieldInfo::from_field_array(fa, n);
field->initialize(access_flags.as_short(),
name_index,
signature_index,
constantvalue_index);
const BasicType type = cp->basic_type_for_signature_at(signature_index);

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

// After field is initialized with type, we can augment it with aux info
if (parsed_annotations.has_any_annotations()) {
parsed_annotations.apply_to(field);
if (field->is_contended()) {
_has_contended_fields = true;
}
FieldInfo fi(access_flags, name_index, signature_index, constantvalue_index, fieldFlags);
fi.set_index(n);
if (fieldFlags.is_generic()) {
fi.set_generic_signature_index(generic_signature_index);
}
parsed_annotations.apply_to(&fi);
if (fi.field_flags().is_contended()) {
_has_contended_fields = true;
}
_temp_field_info->append(fi);
}
assert(_temp_field_info->length() == length, "Must be");

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

// Injected field
FieldInfo* const field = FieldInfo::from_field_array(fa, index);
field->initialize((u2)JVM_ACC_FIELD_INTERNAL,
(u2)(injected[n].name_index),
(u2)(injected[n].signature_index),
0);

const BasicType type = Signature::basic_type(injected[n].signature());
FieldInfo::FieldFlags fflags(0);
fflags.update_injected(true);
AccessFlags aflags;
FieldInfo fi(aflags, (u2)(injected[n].name_index), (u2)(injected[n].signature_index), 0, fflags);
fi.set_index(index);
_temp_field_info->append(fi);

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

assert(nullptr == _fields, "invariant");

_fields =
MetadataFactory::new_array<u2>(_loader_data,
index * FieldInfo::field_slots + num_generic_signature,
CHECK);
// Sometimes injected fields already exist in the Java source so
// the fields array could be too long. In that case the
// fields array is trimmed. Also unused slots that were reserved
// for generic signature indexes are discarded.
{
int i = 0;
for (; i < index * FieldInfo::field_slots; i++) {
_fields->at_put(i, fa[i]);
}
for (int j = total_fields * FieldInfo::field_slots;
j < generic_signature_slot; j++) {
_fields->at_put(i++, fa[j]);
}
assert(_fields->length() == i, "");
}
assert(_temp_field_info->length() == index, "Must be");

if (_need_verify && length > 1) {
// Check duplicated fields
Expand All @@ -1675,9 +1629,9 @@ void ClassFileParser::parse_fields(const ClassFileStream* const cfs,
const Symbol* sig = nullptr;
{
debug_only(NoSafepointVerifier nsv;)
for (AllFieldStream fs(_fields, cp); !fs.done(); fs.next()) {
name = fs.name();
sig = fs.signature();
for (int i = 0; i < _temp_field_info->length(); i++) {
name = _temp_field_info->adr_at(i)->name(_cp);
sig = _temp_field_info->adr_at(i)->signature(_cp);
// If no duplicates, add name/signature in hashtable names_and_sigs.
if (!put_after_lookup(name, sig, names_and_sigs)) {
dup = true;
Expand Down Expand Up @@ -2055,9 +2009,10 @@ AnnotationCollector::annotation_index(const ClassLoaderData* loader_data,

void ClassFileParser::FieldAnnotationCollector::apply_to(FieldInfo* f) {
if (is_contended())
// Setting the contended group also sets the contended bit in field flags
f->set_contended_group(contended_group());
if (is_stable())
f->set_stable(true);
(f->field_flags_addr())->update_stable(true);
}

ClassFileParser::FieldAnnotationCollector::~FieldAnnotationCollector() {
Expand Down Expand Up @@ -3969,7 +3924,8 @@ void ClassFileParser::apply_parsed_class_metadata(

_cp->set_pool_holder(this_klass);
this_klass->set_constants(_cp);
this_klass->set_fields(_fields, java_fields_count);
this_klass->set_fieldinfo_stream(_fieldinfo_stream);
this_klass->set_fields_status(_fields_status);
this_klass->set_methods(_methods);
this_klass->set_inner_classes(_inner_classes);
this_klass->set_nest_members(_nest_members);
Expand Down Expand Up @@ -5316,7 +5272,8 @@ void ClassFileParser::fill_instance_klass(InstanceKlass* ik,

// note that is not safe to use the fields in the parser from this point on
assert(nullptr == _cp, "invariant");
assert(nullptr == _fields, "invariant");
assert(nullptr == _fieldinfo_stream, "invariant");
assert(nullptr == _fields_status, "invariant");
assert(nullptr == _methods, "invariant");
assert(nullptr == _inner_classes, "invariant");
assert(nullptr == _nest_members, "invariant");
Expand Down Expand Up @@ -5548,7 +5505,8 @@ ClassFileParser::ClassFileParser(ClassFileStream* stream,
_orig_cp_size(0),
_super_klass(),
_cp(nullptr),
_fields(nullptr),
_fieldinfo_stream(nullptr),
_fields_status(nullptr),
_methods(nullptr),
_inner_classes(nullptr),
_nest_members(nullptr),
Expand All @@ -5567,6 +5525,7 @@ ClassFileParser::ClassFileParser(ClassFileStream* stream,
_parsed_annotations(nullptr),
_fac(nullptr),
_field_info(nullptr),
_temp_field_info(nullptr),
_method_ordering(nullptr),
_all_mirandas(nullptr),
_vtable_size(0),
Expand Down Expand Up @@ -5638,7 +5597,8 @@ void ClassFileParser::clear_class_metadata() {
// metadata created before the instance klass is created. Must be
// deallocated if classfile parsing returns an error.
_cp = nullptr;
_fields = nullptr;
_fieldinfo_stream = nullptr;
_fields_status = nullptr;
_methods = nullptr;
_inner_classes = nullptr;
_nest_members = nullptr;
Expand All @@ -5656,8 +5616,13 @@ ClassFileParser::~ClassFileParser() {
if (_cp != nullptr) {
MetadataFactory::free_metadata(_loader_data, _cp);
}
if (_fields != nullptr) {
MetadataFactory::free_array<u2>(_loader_data, _fields);

if (_fieldinfo_stream != nullptr) {
MetadataFactory::free_array<u1>(_loader_data, _fieldinfo_stream);
}

if (_fields_status != nullptr) {
MetadataFactory::free_array<FieldStatus>(_loader_data, _fields_status);
}

if (_methods != nullptr) {
Expand Down Expand Up @@ -5894,7 +5859,7 @@ void ClassFileParser::parse_stream(const ClassFileStream* const stream,
&_java_fields_count,
CHECK);

assert(_fields != nullptr, "invariant");
assert(_temp_field_info != nullptr, "invariant");

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

_field_info = new FieldLayoutInfo();
FieldLayoutBuilder lb(class_name(), super_klass(), _cp, _fields,
FieldLayoutBuilder lb(class_name(), super_klass(), _cp, /*_fields*/ _temp_field_info,
_parsed_annotations->is_contended(), _field_info);
lb.build_layout();

int injected_fields_count = _temp_field_info->length() - _java_fields_count;
_fieldinfo_stream =
FieldInfoStream::create_FieldInfoStream(_temp_field_info, _java_fields_count,
injected_fields_count, loader_data(), CHECK);
_fields_status =
MetadataFactory::new_array<FieldStatus>(_loader_data, _temp_field_info->length(),
FieldStatus(0), CHECK);
}

void ClassFileParser::set_klass(InstanceKlass* klass) {
Expand Down
5 changes: 4 additions & 1 deletion src/hotspot/share/classfile/classFileParser.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include "memory/referenceType.hpp"
#include "oops/annotations.hpp"
#include "oops/constantPool.hpp"
#include "oops/fieldInfo.hpp"
#include "oops/instanceKlass.hpp"
#include "oops/typeArrayOop.hpp"
#include "utilities/accessFlags.hpp"
Expand Down Expand Up @@ -121,7 +122,8 @@ class ClassFileParser {
// in which case these pointers have been set to null.
const InstanceKlass* _super_klass;
ConstantPool* _cp;
Array<u2>* _fields;
Array<u1>* _fieldinfo_stream;
Array<FieldStatus>* _fields_status;
Array<Method*>* _methods;
Array<u2>* _inner_classes;
Array<u2>* _nest_members;
Expand All @@ -141,6 +143,7 @@ class ClassFileParser {
ClassAnnotationCollector* _parsed_annotations;
FieldAllocationCount* _fac;
FieldLayoutInfo* _field_info;
GrowableArray<FieldInfo>* _temp_field_info;
const intArray* _method_ordering;
GrowableArray<Method*>* _all_mirandas;

Expand Down
Loading

1 comment on commit bfb812a

@openjdk-notifier
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.