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
This commit is contained in:
parent
932be3542d
commit
bfb812a8ff
@ -255,7 +255,7 @@ static bool trust_final_non_static_fields(ciInstanceKlass* holder) {
|
|||||||
|
|
||||||
void ciField::initialize_from(fieldDescriptor* fd) {
|
void ciField::initialize_from(fieldDescriptor* fd) {
|
||||||
// Get the flags, offset, and canonical holder of the field.
|
// 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();
|
_offset = fd->offset();
|
||||||
Klass* field_holder = fd->field_holder();
|
Klass* field_holder = fd->field_holder();
|
||||||
assert(field_holder != nullptr, "null field_holder");
|
assert(field_holder != nullptr, "null field_holder");
|
||||||
|
@ -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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -40,9 +40,12 @@ private:
|
|||||||
friend class ciMethod;
|
friend class ciMethod;
|
||||||
|
|
||||||
jint _flags;
|
jint _flags;
|
||||||
|
bool _stable;
|
||||||
|
bool _intialized_final_update;
|
||||||
|
|
||||||
ciFlags() { _flags = 0; }
|
ciFlags() :_flags(0), _stable(false), _intialized_final_update(false) { }
|
||||||
ciFlags(AccessFlags flags) { _flags = flags.as_int(); }
|
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:
|
public:
|
||||||
// Java access flags
|
// Java access flags
|
||||||
@ -58,12 +61,12 @@ public:
|
|||||||
bool is_native () const { return (_flags & JVM_ACC_NATIVE ) != 0; }
|
bool is_native () const { return (_flags & JVM_ACC_NATIVE ) != 0; }
|
||||||
bool is_interface () const { return (_flags & JVM_ACC_INTERFACE ) != 0; }
|
bool is_interface () const { return (_flags & JVM_ACC_INTERFACE ) != 0; }
|
||||||
bool is_abstract () const { return (_flags & JVM_ACC_ABSTRACT ) != 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
|
// In case the current object represents a field, return true if
|
||||||
// the field is modified outside of instance initializer methods
|
// the field is modified outside of instance initializer methods
|
||||||
// (or class/initializer methods if the field is static) and false
|
// (or class/initializer methods if the field is static) and false
|
||||||
// otherwise.
|
// 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
|
// Conversion
|
||||||
jint as_int() { return _flags; }
|
jint as_int() { return _flags; }
|
||||||
|
@ -48,6 +48,7 @@
|
|||||||
#include "memory/universe.hpp"
|
#include "memory/universe.hpp"
|
||||||
#include "oops/annotations.hpp"
|
#include "oops/annotations.hpp"
|
||||||
#include "oops/constantPool.inline.hpp"
|
#include "oops/constantPool.inline.hpp"
|
||||||
|
#include "oops/fieldInfo.hpp"
|
||||||
#include "oops/fieldStreams.inline.hpp"
|
#include "oops/fieldStreams.inline.hpp"
|
||||||
#include "oops/instanceKlass.inline.hpp"
|
#include "oops/instanceKlass.inline.hpp"
|
||||||
#include "oops/instanceMirrorKlass.hpp"
|
#include "oops/instanceMirrorKlass.hpp"
|
||||||
@ -1471,7 +1472,6 @@ void ClassFileParser::parse_fields(const ClassFileStream* const cfs,
|
|||||||
assert(cp != nullptr, "invariant");
|
assert(cp != nullptr, "invariant");
|
||||||
assert(java_fields_count_ptr != nullptr, "invariant");
|
assert(java_fields_count_ptr != nullptr, "invariant");
|
||||||
|
|
||||||
assert(nullptr == _fields, "invariant");
|
|
||||||
assert(nullptr == _fields_annotations, "invariant");
|
assert(nullptr == _fields_annotations, "invariant");
|
||||||
assert(nullptr == _fields_type_annotations, "invariant");
|
assert(nullptr == _fields_type_annotations, "invariant");
|
||||||
|
|
||||||
@ -1484,34 +1484,11 @@ void ClassFileParser::parse_fields(const ClassFileStream* const cfs,
|
|||||||
&num_injected);
|
&num_injected);
|
||||||
const int total_fields = length + num_injected;
|
const int total_fields = length + num_injected;
|
||||||
|
|
||||||
// The field array starts with tuples of shorts
|
// Allocate a temporary resource array to collect field data.
|
||||||
// [access, name index, sig index, initial value index, byte offset].
|
// After parsing all fields, data are stored in a UNSIGNED5 compressed stream.
|
||||||
// A generic signature slot only exists for field with generic
|
_temp_field_info = new GrowableArray<FieldInfo>(total_fields);
|
||||||
// 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));
|
|
||||||
|
|
||||||
// The generic signature slots start after all other fields' data.
|
ResourceMark rm(THREAD);
|
||||||
int generic_signature_slot = total_fields * FieldInfo::field_slots;
|
|
||||||
int num_generic_signature = 0;
|
|
||||||
for (int n = 0; n < length; n++) {
|
for (int n = 0; n < length; n++) {
|
||||||
// access_flags, name_index, descriptor_index, attributes_count
|
// access_flags, name_index, descriptor_index, attributes_count
|
||||||
cfs->guarantee_more(8, CHECK);
|
cfs->guarantee_more(8, CHECK);
|
||||||
@ -1520,6 +1497,7 @@ void ClassFileParser::parse_fields(const ClassFileStream* const cfs,
|
|||||||
const jint flags = cfs->get_u2_fast() & JVM_RECOGNIZED_FIELD_MODIFIERS;
|
const jint flags = cfs->get_u2_fast() & JVM_RECOGNIZED_FIELD_MODIFIERS;
|
||||||
verify_legal_field_modifiers(flags, is_interface, CHECK);
|
verify_legal_field_modifiers(flags, is_interface, CHECK);
|
||||||
access_flags.set_flags(flags);
|
access_flags.set_flags(flags);
|
||||||
|
FieldInfo::FieldFlags fieldFlags(0);
|
||||||
|
|
||||||
const u2 name_index = cfs->get_u2_fast();
|
const u2 name_index = cfs->get_u2_fast();
|
||||||
check_property(valid_symbol_at(name_index),
|
check_property(valid_symbol_at(name_index),
|
||||||
@ -1578,31 +1556,27 @@ void ClassFileParser::parse_fields(const ClassFileStream* const cfs,
|
|||||||
access_flags.set_is_synthetic();
|
access_flags.set_is_synthetic();
|
||||||
}
|
}
|
||||||
if (generic_signature_index != 0) {
|
if (generic_signature_index != 0) {
|
||||||
access_flags.set_field_has_generic_signature();
|
fieldFlags.update_generic(true);
|
||||||
fa[generic_signature_slot] = generic_signature_index;
|
|
||||||
generic_signature_slot ++;
|
|
||||||
num_generic_signature ++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
const BasicType type = cp->basic_type_for_signature_at(signature_index);
|
||||||
|
|
||||||
// Update FieldAllocationCount for this kind of field
|
// Update FieldAllocationCount for this kind of field
|
||||||
fac->update(is_static, type);
|
fac->update(is_static, type);
|
||||||
|
|
||||||
// After field is initialized with type, we can augment it with aux info
|
FieldInfo fi(access_flags, name_index, signature_index, constantvalue_index, fieldFlags);
|
||||||
if (parsed_annotations.has_any_annotations()) {
|
fi.set_index(n);
|
||||||
parsed_annotations.apply_to(field);
|
if (fieldFlags.is_generic()) {
|
||||||
if (field->is_contended()) {
|
fi.set_generic_signature_index(generic_signature_index);
|
||||||
|
}
|
||||||
|
parsed_annotations.apply_to(&fi);
|
||||||
|
if (fi.field_flags().is_contended()) {
|
||||||
_has_contended_fields = true;
|
_has_contended_fields = true;
|
||||||
}
|
}
|
||||||
|
_temp_field_info->append(fi);
|
||||||
}
|
}
|
||||||
}
|
assert(_temp_field_info->length() == length, "Must be");
|
||||||
|
|
||||||
int index = length;
|
int index = length;
|
||||||
if (num_injected != 0) {
|
if (num_injected != 0) {
|
||||||
@ -1613,7 +1587,7 @@ void ClassFileParser::parse_fields(const ClassFileStream* const cfs,
|
|||||||
const Symbol* const signature = injected[n].signature();
|
const Symbol* const signature = injected[n].signature();
|
||||||
bool duplicate = false;
|
bool duplicate = false;
|
||||||
for (int i = 0; i < length; i++) {
|
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()) &&
|
if (name == cp->symbol_at(f->name_index()) &&
|
||||||
signature == cp->symbol_at(f->signature_index())) {
|
signature == cp->symbol_at(f->signature_index())) {
|
||||||
// Symbol is desclared in Java so skip this one
|
// Symbol is desclared in Java so skip this one
|
||||||
@ -1628,41 +1602,21 @@ void ClassFileParser::parse_fields(const ClassFileStream* const cfs,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Injected field
|
// Injected field
|
||||||
FieldInfo* const field = FieldInfo::from_field_array(fa, index);
|
FieldInfo::FieldFlags fflags(0);
|
||||||
field->initialize((u2)JVM_ACC_FIELD_INTERNAL,
|
fflags.update_injected(true);
|
||||||
(u2)(injected[n].name_index),
|
AccessFlags aflags;
|
||||||
(u2)(injected[n].signature_index),
|
FieldInfo fi(aflags, (u2)(injected[n].name_index), (u2)(injected[n].signature_index), 0, fflags);
|
||||||
0);
|
fi.set_index(index);
|
||||||
|
_temp_field_info->append(fi);
|
||||||
const BasicType type = Signature::basic_type(injected[n].signature());
|
|
||||||
|
|
||||||
// Update FieldAllocationCount for this kind of field
|
// Update FieldAllocationCount for this kind of field
|
||||||
|
const BasicType type = Signature::basic_type(injected[n].signature());
|
||||||
fac->update(false, type);
|
fac->update(false, type);
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(nullptr == _fields, "invariant");
|
assert(_temp_field_info->length() == index, "Must be");
|
||||||
|
|
||||||
_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, "");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_need_verify && length > 1) {
|
if (_need_verify && length > 1) {
|
||||||
// Check duplicated fields
|
// Check duplicated fields
|
||||||
@ -1675,9 +1629,9 @@ void ClassFileParser::parse_fields(const ClassFileStream* const cfs,
|
|||||||
const Symbol* sig = nullptr;
|
const Symbol* sig = nullptr;
|
||||||
{
|
{
|
||||||
debug_only(NoSafepointVerifier nsv;)
|
debug_only(NoSafepointVerifier nsv;)
|
||||||
for (AllFieldStream fs(_fields, cp); !fs.done(); fs.next()) {
|
for (int i = 0; i < _temp_field_info->length(); i++) {
|
||||||
name = fs.name();
|
name = _temp_field_info->adr_at(i)->name(_cp);
|
||||||
sig = fs.signature();
|
sig = _temp_field_info->adr_at(i)->signature(_cp);
|
||||||
// If no duplicates, add name/signature in hashtable names_and_sigs.
|
// If no duplicates, add name/signature in hashtable names_and_sigs.
|
||||||
if (!put_after_lookup(name, sig, names_and_sigs)) {
|
if (!put_after_lookup(name, sig, names_and_sigs)) {
|
||||||
dup = true;
|
dup = true;
|
||||||
@ -2055,9 +2009,10 @@ AnnotationCollector::annotation_index(const ClassLoaderData* loader_data,
|
|||||||
|
|
||||||
void ClassFileParser::FieldAnnotationCollector::apply_to(FieldInfo* f) {
|
void ClassFileParser::FieldAnnotationCollector::apply_to(FieldInfo* f) {
|
||||||
if (is_contended())
|
if (is_contended())
|
||||||
|
// Setting the contended group also sets the contended bit in field flags
|
||||||
f->set_contended_group(contended_group());
|
f->set_contended_group(contended_group());
|
||||||
if (is_stable())
|
if (is_stable())
|
||||||
f->set_stable(true);
|
(f->field_flags_addr())->update_stable(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
ClassFileParser::FieldAnnotationCollector::~FieldAnnotationCollector() {
|
ClassFileParser::FieldAnnotationCollector::~FieldAnnotationCollector() {
|
||||||
@ -3969,7 +3924,8 @@ void ClassFileParser::apply_parsed_class_metadata(
|
|||||||
|
|
||||||
_cp->set_pool_holder(this_klass);
|
_cp->set_pool_holder(this_klass);
|
||||||
this_klass->set_constants(_cp);
|
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_methods(_methods);
|
||||||
this_klass->set_inner_classes(_inner_classes);
|
this_klass->set_inner_classes(_inner_classes);
|
||||||
this_klass->set_nest_members(_nest_members);
|
this_klass->set_nest_members(_nest_members);
|
||||||
@ -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
|
// note that is not safe to use the fields in the parser from this point on
|
||||||
assert(nullptr == _cp, "invariant");
|
assert(nullptr == _cp, "invariant");
|
||||||
assert(nullptr == _fields, "invariant");
|
assert(nullptr == _fieldinfo_stream, "invariant");
|
||||||
|
assert(nullptr == _fields_status, "invariant");
|
||||||
assert(nullptr == _methods, "invariant");
|
assert(nullptr == _methods, "invariant");
|
||||||
assert(nullptr == _inner_classes, "invariant");
|
assert(nullptr == _inner_classes, "invariant");
|
||||||
assert(nullptr == _nest_members, "invariant");
|
assert(nullptr == _nest_members, "invariant");
|
||||||
@ -5548,7 +5505,8 @@ ClassFileParser::ClassFileParser(ClassFileStream* stream,
|
|||||||
_orig_cp_size(0),
|
_orig_cp_size(0),
|
||||||
_super_klass(),
|
_super_klass(),
|
||||||
_cp(nullptr),
|
_cp(nullptr),
|
||||||
_fields(nullptr),
|
_fieldinfo_stream(nullptr),
|
||||||
|
_fields_status(nullptr),
|
||||||
_methods(nullptr),
|
_methods(nullptr),
|
||||||
_inner_classes(nullptr),
|
_inner_classes(nullptr),
|
||||||
_nest_members(nullptr),
|
_nest_members(nullptr),
|
||||||
@ -5567,6 +5525,7 @@ ClassFileParser::ClassFileParser(ClassFileStream* stream,
|
|||||||
_parsed_annotations(nullptr),
|
_parsed_annotations(nullptr),
|
||||||
_fac(nullptr),
|
_fac(nullptr),
|
||||||
_field_info(nullptr),
|
_field_info(nullptr),
|
||||||
|
_temp_field_info(nullptr),
|
||||||
_method_ordering(nullptr),
|
_method_ordering(nullptr),
|
||||||
_all_mirandas(nullptr),
|
_all_mirandas(nullptr),
|
||||||
_vtable_size(0),
|
_vtable_size(0),
|
||||||
@ -5638,7 +5597,8 @@ void ClassFileParser::clear_class_metadata() {
|
|||||||
// metadata created before the instance klass is created. Must be
|
// metadata created before the instance klass is created. Must be
|
||||||
// deallocated if classfile parsing returns an error.
|
// deallocated if classfile parsing returns an error.
|
||||||
_cp = nullptr;
|
_cp = nullptr;
|
||||||
_fields = nullptr;
|
_fieldinfo_stream = nullptr;
|
||||||
|
_fields_status = nullptr;
|
||||||
_methods = nullptr;
|
_methods = nullptr;
|
||||||
_inner_classes = nullptr;
|
_inner_classes = nullptr;
|
||||||
_nest_members = nullptr;
|
_nest_members = nullptr;
|
||||||
@ -5656,8 +5616,13 @@ ClassFileParser::~ClassFileParser() {
|
|||||||
if (_cp != nullptr) {
|
if (_cp != nullptr) {
|
||||||
MetadataFactory::free_metadata(_loader_data, _cp);
|
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) {
|
if (_methods != nullptr) {
|
||||||
@ -5894,7 +5859,7 @@ void ClassFileParser::parse_stream(const ClassFileStream* const stream,
|
|||||||
&_java_fields_count,
|
&_java_fields_count,
|
||||||
CHECK);
|
CHECK);
|
||||||
|
|
||||||
assert(_fields != nullptr, "invariant");
|
assert(_temp_field_info != nullptr, "invariant");
|
||||||
|
|
||||||
// Methods
|
// Methods
|
||||||
parse_methods(stream,
|
parse_methods(stream,
|
||||||
@ -6050,9 +6015,17 @@ void ClassFileParser::post_process_parsed_stream(const ClassFileStream* const st
|
|||||||
assert(_parsed_annotations != nullptr, "invariant");
|
assert(_parsed_annotations != nullptr, "invariant");
|
||||||
|
|
||||||
_field_info = new FieldLayoutInfo();
|
_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);
|
_parsed_annotations->is_contended(), _field_info);
|
||||||
lb.build_layout();
|
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) {
|
void ClassFileParser::set_klass(InstanceKlass* klass) {
|
||||||
|
@ -28,6 +28,7 @@
|
|||||||
#include "memory/referenceType.hpp"
|
#include "memory/referenceType.hpp"
|
||||||
#include "oops/annotations.hpp"
|
#include "oops/annotations.hpp"
|
||||||
#include "oops/constantPool.hpp"
|
#include "oops/constantPool.hpp"
|
||||||
|
#include "oops/fieldInfo.hpp"
|
||||||
#include "oops/instanceKlass.hpp"
|
#include "oops/instanceKlass.hpp"
|
||||||
#include "oops/typeArrayOop.hpp"
|
#include "oops/typeArrayOop.hpp"
|
||||||
#include "utilities/accessFlags.hpp"
|
#include "utilities/accessFlags.hpp"
|
||||||
@ -121,7 +122,8 @@ class ClassFileParser {
|
|||||||
// in which case these pointers have been set to null.
|
// in which case these pointers have been set to null.
|
||||||
const InstanceKlass* _super_klass;
|
const InstanceKlass* _super_klass;
|
||||||
ConstantPool* _cp;
|
ConstantPool* _cp;
|
||||||
Array<u2>* _fields;
|
Array<u1>* _fieldinfo_stream;
|
||||||
|
Array<FieldStatus>* _fields_status;
|
||||||
Array<Method*>* _methods;
|
Array<Method*>* _methods;
|
||||||
Array<u2>* _inner_classes;
|
Array<u2>* _inner_classes;
|
||||||
Array<u2>* _nest_members;
|
Array<u2>* _nest_members;
|
||||||
@ -141,6 +143,7 @@ class ClassFileParser {
|
|||||||
ClassAnnotationCollector* _parsed_annotations;
|
ClassAnnotationCollector* _parsed_annotations;
|
||||||
FieldAllocationCount* _fac;
|
FieldAllocationCount* _fac;
|
||||||
FieldLayoutInfo* _field_info;
|
FieldLayoutInfo* _field_info;
|
||||||
|
GrowableArray<FieldInfo>* _temp_field_info;
|
||||||
const intArray* _method_ordering;
|
const intArray* _method_ordering;
|
||||||
GrowableArray<Method*>* _all_mirandas;
|
GrowableArray<Method*>* _all_mirandas;
|
||||||
|
|
||||||
|
@ -80,18 +80,18 @@ FieldGroup::FieldGroup(int contended_group) :
|
|||||||
_contended_group(contended_group), // -1 means no contended group, 0 means default contended group
|
_contended_group(contended_group), // -1 means no contended group, 0 means default contended group
|
||||||
_oop_count(0) {}
|
_oop_count(0) {}
|
||||||
|
|
||||||
void FieldGroup::add_primitive_field(AllFieldStream fs, BasicType type) {
|
void FieldGroup::add_primitive_field(int idx, BasicType type) {
|
||||||
int size = type2aelembytes(type);
|
int size = type2aelembytes(type);
|
||||||
LayoutRawBlock* block = new LayoutRawBlock(fs.index(), LayoutRawBlock::REGULAR, size, size /* alignment == size for primitive types */, false);
|
LayoutRawBlock* block = new LayoutRawBlock(idx, LayoutRawBlock::REGULAR, size, size /* alignment == size for primitive types */, false);
|
||||||
if (_primitive_fields == nullptr) {
|
if (_primitive_fields == nullptr) {
|
||||||
_primitive_fields = new GrowableArray<LayoutRawBlock*>(INITIAL_LIST_SIZE);
|
_primitive_fields = new GrowableArray<LayoutRawBlock*>(INITIAL_LIST_SIZE);
|
||||||
}
|
}
|
||||||
_primitive_fields->append(block);
|
_primitive_fields->append(block);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FieldGroup::add_oop_field(AllFieldStream fs) {
|
void FieldGroup::add_oop_field(int idx) {
|
||||||
int size = type2aelembytes(T_OBJECT);
|
int size = type2aelembytes(T_OBJECT);
|
||||||
LayoutRawBlock* block = new LayoutRawBlock(fs.index(), LayoutRawBlock::REGULAR, size, size /* alignment == size for oops */, true);
|
LayoutRawBlock* block = new LayoutRawBlock(idx, LayoutRawBlock::REGULAR, size, size /* alignment == size for oops */, true);
|
||||||
if (_oop_fields == nullptr) {
|
if (_oop_fields == nullptr) {
|
||||||
_oop_fields = new GrowableArray<LayoutRawBlock*>(INITIAL_LIST_SIZE);
|
_oop_fields = new GrowableArray<LayoutRawBlock*>(INITIAL_LIST_SIZE);
|
||||||
}
|
}
|
||||||
@ -105,8 +105,8 @@ void FieldGroup::sort_by_size() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FieldLayout::FieldLayout(Array<u2>* fields, ConstantPool* cp) :
|
FieldLayout::FieldLayout(GrowableArray<FieldInfo>* field_info, ConstantPool* cp) :
|
||||||
_fields(fields),
|
_field_info(field_info),
|
||||||
_cp(cp),
|
_cp(cp),
|
||||||
_blocks(nullptr),
|
_blocks(nullptr),
|
||||||
_start(_blocks),
|
_start(_blocks),
|
||||||
@ -231,7 +231,7 @@ void FieldLayout::add_field_at_offset(LayoutRawBlock* block, int offset, LayoutR
|
|||||||
if (slot->size() == 0) {
|
if (slot->size() == 0) {
|
||||||
remove(slot);
|
remove(slot);
|
||||||
}
|
}
|
||||||
FieldInfo::from_field_array(_fields, block->field_index())->set_offset(block->offset());
|
_field_info->adr_at(block->field_index())->set_offset(block->offset());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
slot = slot->next_block();
|
slot = slot->next_block();
|
||||||
@ -290,7 +290,7 @@ LayoutRawBlock* FieldLayout::insert_field_block(LayoutRawBlock* slot, LayoutRawB
|
|||||||
if (slot->size() == 0) {
|
if (slot->size() == 0) {
|
||||||
remove(slot);
|
remove(slot);
|
||||||
}
|
}
|
||||||
FieldInfo::from_field_array(_fields, block->field_index())->set_offset(block->offset());
|
_field_info->adr_at(block->field_index())->set_offset(block->offset());
|
||||||
return block;
|
return block;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -298,7 +298,7 @@ bool FieldLayout::reconstruct_layout(const InstanceKlass* ik) {
|
|||||||
bool has_instance_fields = false;
|
bool has_instance_fields = false;
|
||||||
GrowableArray<LayoutRawBlock*>* all_fields = new GrowableArray<LayoutRawBlock*>(32);
|
GrowableArray<LayoutRawBlock*>* all_fields = new GrowableArray<LayoutRawBlock*>(32);
|
||||||
while (ik != nullptr) {
|
while (ik != nullptr) {
|
||||||
for (AllFieldStream fs(ik->fields(), ik->constants()); !fs.done(); fs.next()) {
|
for (AllFieldStream fs(ik->fieldinfo_stream(), ik->constants()); !fs.done(); fs.next()) {
|
||||||
BasicType type = Signature::basic_type(fs.signature());
|
BasicType type = Signature::basic_type(fs.signature());
|
||||||
// distinction between static and non-static fields is missing
|
// distinction between static and non-static fields is missing
|
||||||
if (fs.access_flags().is_static()) continue;
|
if (fs.access_flags().is_static()) continue;
|
||||||
@ -430,7 +430,7 @@ void FieldLayout::print(outputStream* output, bool is_static, const InstanceKlas
|
|||||||
while(b != _last) {
|
while(b != _last) {
|
||||||
switch(b->kind()) {
|
switch(b->kind()) {
|
||||||
case LayoutRawBlock::REGULAR: {
|
case LayoutRawBlock::REGULAR: {
|
||||||
FieldInfo* fi = FieldInfo::from_field_array(_fields, b->field_index());
|
FieldInfo* fi = _field_info->adr_at(b->field_index());
|
||||||
output->print_cr(" @%d \"%s\" %s %d/%d %s",
|
output->print_cr(" @%d \"%s\" %s %d/%d %s",
|
||||||
b->offset(),
|
b->offset(),
|
||||||
fi->name(_cp)->as_C_string(),
|
fi->name(_cp)->as_C_string(),
|
||||||
@ -441,7 +441,7 @@ void FieldLayout::print(outputStream* output, bool is_static, const InstanceKlas
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case LayoutRawBlock::FLATTENED: {
|
case LayoutRawBlock::FLATTENED: {
|
||||||
FieldInfo* fi = FieldInfo::from_field_array(_fields, b->field_index());
|
FieldInfo* fi = _field_info->adr_at(b->field_index());
|
||||||
output->print_cr(" @%d \"%s\" %s %d/%d %s",
|
output->print_cr(" @%d \"%s\" %s %d/%d %s",
|
||||||
b->offset(),
|
b->offset(),
|
||||||
fi->name(_cp)->as_C_string(),
|
fi->name(_cp)->as_C_string(),
|
||||||
@ -464,7 +464,7 @@ void FieldLayout::print(outputStream* output, bool is_static, const InstanceKlas
|
|||||||
bool found = false;
|
bool found = false;
|
||||||
const InstanceKlass* ik = super;
|
const InstanceKlass* ik = super;
|
||||||
while (!found && ik != nullptr) {
|
while (!found && ik != nullptr) {
|
||||||
for (AllFieldStream fs(ik->fields(), ik->constants()); !fs.done(); fs.next()) {
|
for (AllFieldStream fs(ik->fieldinfo_stream(), ik->constants()); !fs.done(); fs.next()) {
|
||||||
if (fs.offset() == b->offset()) {
|
if (fs.offset() == b->offset()) {
|
||||||
output->print_cr(" @%d \"%s\" %s %d/%d %s",
|
output->print_cr(" @%d \"%s\" %s %d/%d %s",
|
||||||
b->offset(),
|
b->offset(),
|
||||||
@ -499,11 +499,11 @@ void FieldLayout::print(outputStream* output, bool is_static, const InstanceKlas
|
|||||||
}
|
}
|
||||||
|
|
||||||
FieldLayoutBuilder::FieldLayoutBuilder(const Symbol* classname, const InstanceKlass* super_klass, ConstantPool* constant_pool,
|
FieldLayoutBuilder::FieldLayoutBuilder(const Symbol* classname, const InstanceKlass* super_klass, ConstantPool* constant_pool,
|
||||||
Array<u2>* fields, bool is_contended, FieldLayoutInfo* info) :
|
GrowableArray<FieldInfo>* field_info, bool is_contended, FieldLayoutInfo* info) :
|
||||||
_classname(classname),
|
_classname(classname),
|
||||||
_super_klass(super_klass),
|
_super_klass(super_klass),
|
||||||
_constant_pool(constant_pool),
|
_constant_pool(constant_pool),
|
||||||
_fields(fields),
|
_field_info(field_info),
|
||||||
_info(info),
|
_info(info),
|
||||||
_root_group(nullptr),
|
_root_group(nullptr),
|
||||||
_contended_groups(GrowableArray<FieldGroup*>(8)),
|
_contended_groups(GrowableArray<FieldGroup*>(8)),
|
||||||
@ -529,13 +529,13 @@ FieldGroup* FieldLayoutBuilder::get_or_create_contended_group(int g) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void FieldLayoutBuilder::prologue() {
|
void FieldLayoutBuilder::prologue() {
|
||||||
_layout = new FieldLayout(_fields, _constant_pool);
|
_layout = new FieldLayout(_field_info, _constant_pool);
|
||||||
const InstanceKlass* super_klass = _super_klass;
|
const InstanceKlass* super_klass = _super_klass;
|
||||||
_layout->initialize_instance_layout(super_klass);
|
_layout->initialize_instance_layout(super_klass);
|
||||||
if (super_klass != nullptr) {
|
if (super_klass != nullptr) {
|
||||||
_has_nonstatic_fields = super_klass->has_nonstatic_fields();
|
_has_nonstatic_fields = super_klass->has_nonstatic_fields();
|
||||||
}
|
}
|
||||||
_static_layout = new FieldLayout(_fields, _constant_pool);
|
_static_layout = new FieldLayout(_field_info, _constant_pool);
|
||||||
_static_layout->initialize_static_layout();
|
_static_layout->initialize_static_layout();
|
||||||
_static_fields = new FieldGroup();
|
_static_fields = new FieldGroup();
|
||||||
_root_group = new FieldGroup();
|
_root_group = new FieldGroup();
|
||||||
@ -547,14 +547,17 @@ void FieldLayoutBuilder::prologue() {
|
|||||||
// (support of the @Contended annotation)
|
// (support of the @Contended annotation)
|
||||||
// - @Contended annotation is ignored for static fields
|
// - @Contended annotation is ignored for static fields
|
||||||
void FieldLayoutBuilder::regular_field_sorting() {
|
void FieldLayoutBuilder::regular_field_sorting() {
|
||||||
for (AllFieldStream fs(_fields, _constant_pool); !fs.done(); fs.next()) {
|
int idx = 0;
|
||||||
|
for (GrowableArrayIterator<FieldInfo> it = _field_info->begin(); it != _field_info->end(); ++it, ++idx) {
|
||||||
|
FieldInfo ctrl = _field_info->at(0);
|
||||||
FieldGroup* group = nullptr;
|
FieldGroup* group = nullptr;
|
||||||
if (fs.access_flags().is_static()) {
|
FieldInfo fieldinfo = *it;
|
||||||
|
if (fieldinfo.access_flags().is_static()) {
|
||||||
group = _static_fields;
|
group = _static_fields;
|
||||||
} else {
|
} else {
|
||||||
_has_nonstatic_fields = true;
|
_has_nonstatic_fields = true;
|
||||||
if (fs.is_contended()) {
|
if (fieldinfo.field_flags().is_contended()) {
|
||||||
int g = fs.contended_group();
|
int g = fieldinfo.contended_group();
|
||||||
if (g == 0) {
|
if (g == 0) {
|
||||||
group = new FieldGroup(true);
|
group = new FieldGroup(true);
|
||||||
_contended_groups.append(group);
|
_contended_groups.append(group);
|
||||||
@ -566,7 +569,7 @@ void FieldLayoutBuilder::regular_field_sorting() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
assert(group != nullptr, "invariant");
|
assert(group != nullptr, "invariant");
|
||||||
BasicType type = Signature::basic_type(fs.signature());
|
BasicType type = Signature::basic_type(fieldinfo.signature(_constant_pool));
|
||||||
switch(type) {
|
switch(type) {
|
||||||
case T_BYTE:
|
case T_BYTE:
|
||||||
case T_CHAR:
|
case T_CHAR:
|
||||||
@ -576,12 +579,12 @@ void FieldLayoutBuilder::regular_field_sorting() {
|
|||||||
case T_LONG:
|
case T_LONG:
|
||||||
case T_SHORT:
|
case T_SHORT:
|
||||||
case T_BOOLEAN:
|
case T_BOOLEAN:
|
||||||
group->add_primitive_field(fs, type);
|
group->add_primitive_field(idx, type);
|
||||||
break;
|
break;
|
||||||
case T_OBJECT:
|
case T_OBJECT:
|
||||||
case T_ARRAY:
|
case T_ARRAY:
|
||||||
if (group != _static_fields) _nonstatic_oopmap_count++;
|
if (group != _static_fields) _nonstatic_oopmap_count++;
|
||||||
group->add_oop_field(fs);
|
group->add_oop_field(idx);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
fatal("Something wrong?");
|
fatal("Something wrong?");
|
||||||
|
@ -141,8 +141,8 @@ class FieldGroup : public ResourceObj {
|
|||||||
int contended_group() const { return _contended_group; }
|
int contended_group() const { return _contended_group; }
|
||||||
int oop_count() const { return _oop_count; }
|
int oop_count() const { return _oop_count; }
|
||||||
|
|
||||||
void add_primitive_field(AllFieldStream fs, BasicType type);
|
void add_primitive_field(int idx, BasicType type);
|
||||||
void add_oop_field(AllFieldStream fs);
|
void add_oop_field(int idx);
|
||||||
void sort_by_size();
|
void sort_by_size();
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -164,14 +164,14 @@ class FieldGroup : public ResourceObj {
|
|||||||
//
|
//
|
||||||
class FieldLayout : public ResourceObj {
|
class FieldLayout : public ResourceObj {
|
||||||
private:
|
private:
|
||||||
Array<u2>* _fields;
|
GrowableArray<FieldInfo>* _field_info;
|
||||||
ConstantPool* _cp;
|
ConstantPool* _cp;
|
||||||
LayoutRawBlock* _blocks; // the layout being computed
|
LayoutRawBlock* _blocks; // the layout being computed
|
||||||
LayoutRawBlock* _start; // points to the first block where a field can be inserted
|
LayoutRawBlock* _start; // points to the first block where a field can be inserted
|
||||||
LayoutRawBlock* _last; // points to the last block of the layout (big empty block)
|
LayoutRawBlock* _last; // points to the last block of the layout (big empty block)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
FieldLayout(Array<u2>* fields, ConstantPool* cp);
|
FieldLayout(GrowableArray<FieldInfo>* field_info, ConstantPool* cp);
|
||||||
void initialize_static_layout();
|
void initialize_static_layout();
|
||||||
void initialize_instance_layout(const InstanceKlass* ik);
|
void initialize_instance_layout(const InstanceKlass* ik);
|
||||||
|
|
||||||
@ -230,7 +230,7 @@ class FieldLayoutBuilder : public ResourceObj {
|
|||||||
const Symbol* _classname;
|
const Symbol* _classname;
|
||||||
const InstanceKlass* _super_klass;
|
const InstanceKlass* _super_klass;
|
||||||
ConstantPool* _constant_pool;
|
ConstantPool* _constant_pool;
|
||||||
Array<u2>* _fields;
|
GrowableArray<FieldInfo>* _field_info;
|
||||||
FieldLayoutInfo* _info;
|
FieldLayoutInfo* _info;
|
||||||
FieldGroup* _root_group;
|
FieldGroup* _root_group;
|
||||||
GrowableArray<FieldGroup*> _contended_groups;
|
GrowableArray<FieldGroup*> _contended_groups;
|
||||||
@ -244,7 +244,7 @@ class FieldLayoutBuilder : public ResourceObj {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
FieldLayoutBuilder(const Symbol* classname, const InstanceKlass* super_klass, ConstantPool* constant_pool,
|
FieldLayoutBuilder(const Symbol* classname, const InstanceKlass* super_klass, ConstantPool* constant_pool,
|
||||||
Array<u2>* fields, bool is_contended, FieldLayoutInfo* info);
|
GrowableArray<FieldInfo>* field_info, bool is_contended, FieldLayoutInfo* info);
|
||||||
|
|
||||||
int get_alignment() {
|
int get_alignment() {
|
||||||
assert(_alignment != -1, "Uninitialized");
|
assert(_alignment != -1, "Uninitialized");
|
||||||
|
@ -50,6 +50,7 @@
|
|||||||
#include "memory/oopFactory.hpp"
|
#include "memory/oopFactory.hpp"
|
||||||
#include "memory/resourceArea.hpp"
|
#include "memory/resourceArea.hpp"
|
||||||
#include "memory/universe.hpp"
|
#include "memory/universe.hpp"
|
||||||
|
#include "oops/fieldInfo.hpp"
|
||||||
#include "oops/fieldStreams.inline.hpp"
|
#include "oops/fieldStreams.inline.hpp"
|
||||||
#include "oops/instanceKlass.inline.hpp"
|
#include "oops/instanceKlass.inline.hpp"
|
||||||
#include "oops/instanceMirrorKlass.hpp"
|
#include "oops/instanceMirrorKlass.hpp"
|
||||||
@ -861,12 +862,29 @@ void java_lang_Class::fixup_mirror(Klass* k, TRAPS) {
|
|||||||
// During bootstrap, java.lang.Class wasn't loaded so static field
|
// During bootstrap, java.lang.Class wasn't loaded so static field
|
||||||
// offsets were computed without the size added it. Go back and
|
// offsets were computed without the size added it. Go back and
|
||||||
// update all the static field offsets to included the size.
|
// update all the static field offsets to included the size.
|
||||||
for (JavaFieldStream fs(InstanceKlass::cast(k)); !fs.done(); fs.next()) {
|
|
||||||
if (fs.access_flags().is_static()) {
|
// Unfortunately, the FieldInfo stream is encoded with UNSIGNED5 which doesn't allow
|
||||||
int real_offset = fs.offset() + InstanceMirrorKlass::offset_of_static_fields();
|
// content updates. So the FieldInfo stream has to be decompressed into a temporary array,
|
||||||
fs.set_offset(real_offset);
|
// static fields offsets are updated in this array before reencoding everything into
|
||||||
|
// a new UNSIGNED5 stream, and substitute it to the old FieldInfo stream.
|
||||||
|
|
||||||
|
int java_fields;
|
||||||
|
int injected_fields;
|
||||||
|
InstanceKlass* ik = InstanceKlass::cast(k);
|
||||||
|
GrowableArray<FieldInfo>* fields =
|
||||||
|
FieldInfoStream::create_FieldInfoArray(ik->fieldinfo_stream(),
|
||||||
|
&java_fields, &injected_fields);
|
||||||
|
for (int i = 0; i < fields->length(); i++) {
|
||||||
|
FieldInfo* fi = fields->adr_at(i);
|
||||||
|
if (fi->access_flags().is_static()) {
|
||||||
|
fi->set_offset(fi->offset() + InstanceMirrorKlass::offset_of_static_fields());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Array<u1>* old_stream = ik->fieldinfo_stream();
|
||||||
|
assert(fields->length() == (java_fields + injected_fields), "Must be");
|
||||||
|
Array<u1>* new_fis = FieldInfoStream::create_FieldInfoStream(fields, java_fields, injected_fields, k->class_loader_data(), CHECK);
|
||||||
|
ik->set_fieldinfo_stream(new_fis);
|
||||||
|
MetadataFactory::free_array<u1>(k->class_loader_data(), old_stream);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5345,7 +5363,7 @@ void JavaClasses::check_offsets() {
|
|||||||
int InjectedField::compute_offset() {
|
int InjectedField::compute_offset() {
|
||||||
InstanceKlass* ik = InstanceKlass::cast(klass());
|
InstanceKlass* ik = InstanceKlass::cast(klass());
|
||||||
for (AllFieldStream fs(ik); !fs.done(); fs.next()) {
|
for (AllFieldStream fs(ik); !fs.done(); fs.next()) {
|
||||||
if (!may_be_java && !fs.access_flags().is_internal()) {
|
if (!may_be_java && !fs.field_flags().is_injected()) {
|
||||||
// Only look at injected fields
|
// Only look at injected fields
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -1155,7 +1155,7 @@ JRT_ENTRY(void, InterpreterRuntime::post_field_access(JavaThread* current, oopDe
|
|||||||
|
|
||||||
InstanceKlass* ik = InstanceKlass::cast(cp_entry->f1_as_klass());
|
InstanceKlass* ik = InstanceKlass::cast(cp_entry->f1_as_klass());
|
||||||
int index = cp_entry->field_index();
|
int index = cp_entry->field_index();
|
||||||
if ((ik->field_access_flags(index) & JVM_ACC_FIELD_ACCESS_WATCHED) == 0) return;
|
if (!ik->field_status(index).is_access_watched()) return;
|
||||||
|
|
||||||
bool is_static = (obj == nullptr);
|
bool is_static = (obj == nullptr);
|
||||||
HandleMark hm(current);
|
HandleMark hm(current);
|
||||||
@ -1180,7 +1180,7 @@ JRT_ENTRY(void, InterpreterRuntime::post_field_modification(JavaThread* current,
|
|||||||
InstanceKlass* ik = InstanceKlass::cast(k);
|
InstanceKlass* ik = InstanceKlass::cast(k);
|
||||||
int index = cp_entry->field_index();
|
int index = cp_entry->field_index();
|
||||||
// bail out if field modifications are not watched
|
// bail out if field modifications are not watched
|
||||||
if ((ik->field_access_flags(index) & JVM_ACC_FIELD_MODIFICATION_WATCHED) == 0) return;
|
if (!ik->field_status(index).is_modification_watched()) return;
|
||||||
|
|
||||||
char sig_type = '\0';
|
char sig_type = '\0';
|
||||||
|
|
||||||
|
@ -810,12 +810,13 @@ C2V_VMENTRY_NULL(jobject, resolveFieldInPool, (JNIEnv* env, jobject, ARGUMENT_PA
|
|||||||
LinkInfo link_info(cp, index, mh, CHECK_NULL);
|
LinkInfo link_info(cp, index, mh, CHECK_NULL);
|
||||||
LinkResolver::resolve_field(fd, link_info, Bytecodes::java_code(code), false, CHECK_NULL);
|
LinkResolver::resolve_field(fd, link_info, Bytecodes::java_code(code), false, CHECK_NULL);
|
||||||
JVMCIPrimitiveArray info = JVMCIENV->wrap(info_handle);
|
JVMCIPrimitiveArray info = JVMCIENV->wrap(info_handle);
|
||||||
if (info.is_null() || JVMCIENV->get_length(info) != 3) {
|
if (info.is_null() || JVMCIENV->get_length(info) != 4) {
|
||||||
JVMCI_ERROR_NULL("info must not be null and have a length of 3");
|
JVMCI_ERROR_NULL("info must not be null and have a length of 4");
|
||||||
}
|
}
|
||||||
JVMCIENV->put_int_at(info, 0, fd.access_flags().as_int());
|
JVMCIENV->put_int_at(info, 0, fd.access_flags().as_int());
|
||||||
JVMCIENV->put_int_at(info, 1, fd.offset());
|
JVMCIENV->put_int_at(info, 1, fd.offset());
|
||||||
JVMCIENV->put_int_at(info, 2, fd.index());
|
JVMCIENV->put_int_at(info, 2, fd.index());
|
||||||
|
JVMCIENV->put_int_at(info, 3, fd.field_flags().as_uint());
|
||||||
JVMCIKlassHandle handle(THREAD, fd.field_holder());
|
JVMCIKlassHandle handle(THREAD, fd.field_holder());
|
||||||
JVMCIObject field_holder = JVMCIENV->get_jvmci_type(handle, JVMCI_CHECK_NULL);
|
JVMCIObject field_holder = JVMCIENV->get_jvmci_type(handle, JVMCI_CHECK_NULL);
|
||||||
return JVMCIENV->get_jobject(field_holder);
|
return JVMCIENV->get_jobject(field_holder);
|
||||||
@ -1963,6 +1964,25 @@ C2V_VMENTRY_NULL(jobjectArray, getDeclaredMethods, (JNIEnv* env, jobject, ARGUME
|
|||||||
return JVMCIENV->get_jobjectArray(methods);
|
return JVMCIENV->get_jobjectArray(methods);
|
||||||
C2V_END
|
C2V_END
|
||||||
|
|
||||||
|
C2V_VMENTRY_NULL(jobjectArray, getDeclaredFieldsInfo, (JNIEnv* env, jobject, ARGUMENT_PAIR(klass)))
|
||||||
|
Klass* klass = UNPACK_PAIR(Klass, klass);
|
||||||
|
if (klass == nullptr) {
|
||||||
|
JVMCI_THROW_0(NullPointerException);
|
||||||
|
}
|
||||||
|
if (!klass->is_instance_klass()) {
|
||||||
|
JVMCI_THROW_MSG_NULL(IllegalArgumentException, "not an InstanceKlass");
|
||||||
|
}
|
||||||
|
InstanceKlass* iklass = InstanceKlass::cast(klass);
|
||||||
|
int java_fields, injected_fields;
|
||||||
|
GrowableArray<FieldInfo>* fields = FieldInfoStream::create_FieldInfoArray(iklass->fieldinfo_stream(), &java_fields, &injected_fields);
|
||||||
|
JVMCIObjectArray array = JVMCIENV->new_FieldInfo_array(fields->length(), JVMCIENV);
|
||||||
|
for (int i = 0; i < fields->length(); i++) {
|
||||||
|
JVMCIObject field_info = JVMCIENV->new_FieldInfo(fields->adr_at(i), JVMCI_CHECK_NULL);
|
||||||
|
JVMCIENV->put_object_at(array, i, field_info);
|
||||||
|
}
|
||||||
|
return array.as_jobject();
|
||||||
|
C2V_END
|
||||||
|
|
||||||
static jobject read_field_value(Handle obj, long displacement, jchar type_char, bool is_static, Thread* THREAD, JVMCIEnv* JVMCIENV) {
|
static jobject read_field_value(Handle obj, long displacement, jchar type_char, bool is_static, Thread* THREAD, JVMCIEnv* JVMCIENV) {
|
||||||
|
|
||||||
BasicType basic_type = JVMCIENV->typeCharToBasicType(type_char, JVMCI_CHECK_NULL);
|
BasicType basic_type = JVMCIENV->typeCharToBasicType(type_char, JVMCI_CHECK_NULL);
|
||||||
@ -2649,8 +2669,7 @@ C2V_VMENTRY_NULL(jobject, asReflectionField, (JNIEnv* env, jobject, ARGUMENT_PAI
|
|||||||
err_msg("Expected non-primitive type, got %s", klass->external_name()));
|
err_msg("Expected non-primitive type, got %s", klass->external_name()));
|
||||||
}
|
}
|
||||||
InstanceKlass* iklass = InstanceKlass::cast(klass);
|
InstanceKlass* iklass = InstanceKlass::cast(klass);
|
||||||
Array<u2>* fields = iklass->fields();
|
if (index < 0 || index > iklass->total_fields_count()) {
|
||||||
if (index < 0 ||index > fields->length()) {
|
|
||||||
JVMCI_THROW_MSG_NULL(IllegalArgumentException,
|
JVMCI_THROW_MSG_NULL(IllegalArgumentException,
|
||||||
err_msg("Field index %d out of bounds for %s", index, klass->external_name()));
|
err_msg("Field index %d out of bounds for %s", index, klass->external_name()));
|
||||||
}
|
}
|
||||||
@ -2814,6 +2833,7 @@ C2V_VMENTRY_0(jlong, getThreadLocalLong, (JNIEnv* env, jobject, jint id))
|
|||||||
#define JAVACONSTANT "Ljdk/vm/ci/meta/JavaConstant;"
|
#define JAVACONSTANT "Ljdk/vm/ci/meta/JavaConstant;"
|
||||||
#define INSPECTED_FRAME_VISITOR "Ljdk/vm/ci/code/stack/InspectedFrameVisitor;"
|
#define INSPECTED_FRAME_VISITOR "Ljdk/vm/ci/code/stack/InspectedFrameVisitor;"
|
||||||
#define RESOLVED_METHOD "Ljdk/vm/ci/meta/ResolvedJavaMethod;"
|
#define RESOLVED_METHOD "Ljdk/vm/ci/meta/ResolvedJavaMethod;"
|
||||||
|
#define FIELDINFO "Ljdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl$FieldInfo;"
|
||||||
#define HS_RESOLVED_TYPE "Ljdk/vm/ci/hotspot/HotSpotResolvedJavaType;"
|
#define HS_RESOLVED_TYPE "Ljdk/vm/ci/hotspot/HotSpotResolvedJavaType;"
|
||||||
#define HS_INSTALLED_CODE "Ljdk/vm/ci/hotspot/HotSpotInstalledCode;"
|
#define HS_INSTALLED_CODE "Ljdk/vm/ci/hotspot/HotSpotInstalledCode;"
|
||||||
#define HS_NMETHOD "Ljdk/vm/ci/hotspot/HotSpotNmethod;"
|
#define HS_NMETHOD "Ljdk/vm/ci/hotspot/HotSpotNmethod;"
|
||||||
@ -2912,6 +2932,7 @@ JNINativeMethod CompilerToVM::methods[] = {
|
|||||||
{CC "boxPrimitive", CC "(" OBJECT ")" OBJECTCONSTANT, FN_PTR(boxPrimitive)},
|
{CC "boxPrimitive", CC "(" OBJECT ")" OBJECTCONSTANT, FN_PTR(boxPrimitive)},
|
||||||
{CC "getDeclaredConstructors", CC "(" HS_KLASS2 ")[" RESOLVED_METHOD, FN_PTR(getDeclaredConstructors)},
|
{CC "getDeclaredConstructors", CC "(" HS_KLASS2 ")[" RESOLVED_METHOD, FN_PTR(getDeclaredConstructors)},
|
||||||
{CC "getDeclaredMethods", CC "(" HS_KLASS2 ")[" RESOLVED_METHOD, FN_PTR(getDeclaredMethods)},
|
{CC "getDeclaredMethods", CC "(" HS_KLASS2 ")[" RESOLVED_METHOD, FN_PTR(getDeclaredMethods)},
|
||||||
|
{CC "getDeclaredFieldsInfo", CC "(" HS_KLASS2 ")[" FIELDINFO, FN_PTR(getDeclaredFieldsInfo)},
|
||||||
{CC "readStaticFieldValue", CC "(" HS_KLASS2 "JC)" JAVACONSTANT, FN_PTR(readStaticFieldValue)},
|
{CC "readStaticFieldValue", CC "(" HS_KLASS2 "JC)" JAVACONSTANT, FN_PTR(readStaticFieldValue)},
|
||||||
{CC "readFieldValue", CC "(" OBJECTCONSTANT HS_KLASS2 "JC)" JAVACONSTANT, FN_PTR(readFieldValue)},
|
{CC "readFieldValue", CC "(" OBJECTCONSTANT HS_KLASS2 "JC)" JAVACONSTANT, FN_PTR(readFieldValue)},
|
||||||
{CC "isInstance", CC "(" HS_KLASS2 OBJECTCONSTANT ")Z", FN_PTR(isInstance)},
|
{CC "isInstance", CC "(" HS_KLASS2 OBJECTCONSTANT ")Z", FN_PTR(isInstance)},
|
||||||
|
@ -1420,6 +1420,33 @@ JVMCIObject JVMCIEnv::new_JVMCIError(JVMCI_TRAPS) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JVMCIObject JVMCIEnv::new_FieldInfo(FieldInfo* fieldinfo, JVMCI_TRAPS) {
|
||||||
|
JavaThread* THREAD = JavaThread::current(); // For exception macros.
|
||||||
|
if (is_hotspot()) {
|
||||||
|
HotSpotJVMCI::FieldInfo::klass()->initialize(CHECK_(JVMCIObject()));
|
||||||
|
oop obj = HotSpotJVMCI::FieldInfo::klass()->allocate_instance(CHECK_(JVMCIObject()));
|
||||||
|
Handle obj_h(THREAD, obj);
|
||||||
|
HotSpotJVMCI::FieldInfo::set_nameIndex(JVMCIENV, obj_h(), (jint)fieldinfo->name_index());
|
||||||
|
HotSpotJVMCI::FieldInfo::set_signatureIndex(JVMCIENV, obj_h(), (jint)fieldinfo->signature_index());
|
||||||
|
HotSpotJVMCI::FieldInfo::set_offset(JVMCIENV, obj_h(), (jint)fieldinfo->offset());
|
||||||
|
HotSpotJVMCI::FieldInfo::set_classfileFlags(JVMCIENV, obj_h(), (jint)fieldinfo->access_flags().as_int());
|
||||||
|
HotSpotJVMCI::FieldInfo::set_internalFlags(JVMCIENV, obj_h(), (jint)fieldinfo->field_flags().as_uint());
|
||||||
|
HotSpotJVMCI::FieldInfo::set_initializerIndex(JVMCIENV, obj_h(), (jint)fieldinfo->initializer_index());
|
||||||
|
return wrap(obj_h());
|
||||||
|
} else {
|
||||||
|
JNIAccessMark jni(this, THREAD);
|
||||||
|
jobject result = jni()->NewObject(JNIJVMCI::FieldInfo::clazz(),
|
||||||
|
JNIJVMCI::FieldInfo::constructor(),
|
||||||
|
(jint)fieldinfo->name_index(),
|
||||||
|
(jint)fieldinfo->signature_index(),
|
||||||
|
(jint)fieldinfo->offset(),
|
||||||
|
(jint)fieldinfo->access_flags().as_int(),
|
||||||
|
(jint)fieldinfo->field_flags().as_uint(),
|
||||||
|
(jint)fieldinfo->initializer_index());
|
||||||
|
|
||||||
|
return wrap(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
JVMCIObject JVMCIEnv::get_object_constant(oop objOop, bool compressed, bool dont_register) {
|
JVMCIObject JVMCIEnv::get_object_constant(oop objOop, bool compressed, bool dont_register) {
|
||||||
JavaThread* THREAD = JavaThread::current(); // For exception macros.
|
JavaThread* THREAD = JavaThread::current(); // For exception macros.
|
||||||
|
@ -403,6 +403,7 @@ public:
|
|||||||
JVMCIObject new_VMIntrinsicMethod(JVMCIObject declaringClass, JVMCIObject name, JVMCIObject descriptor, int id, JVMCI_TRAPS);
|
JVMCIObject new_VMIntrinsicMethod(JVMCIObject declaringClass, JVMCIObject name, JVMCIObject descriptor, int id, JVMCI_TRAPS);
|
||||||
JVMCIObject new_HotSpotStackFrameReference(JVMCI_TRAPS);
|
JVMCIObject new_HotSpotStackFrameReference(JVMCI_TRAPS);
|
||||||
JVMCIObject new_JVMCIError(JVMCI_TRAPS);
|
JVMCIObject new_JVMCIError(JVMCI_TRAPS);
|
||||||
|
JVMCIObject new_FieldInfo(FieldInfo* fieldinfo, JVMCI_TRAPS);
|
||||||
|
|
||||||
// Makes a handle to a HotSpot heap object. These handles are
|
// Makes a handle to a HotSpot heap object. These handles are
|
||||||
// individually reclaimed by JVMCIRuntime::destroy_oop_handle and
|
// individually reclaimed by JVMCIRuntime::destroy_oop_handle and
|
||||||
|
@ -74,7 +74,15 @@
|
|||||||
object_field(HotSpotResolvedJavaFieldImpl, type, "Ljdk/vm/ci/meta/JavaType;") \
|
object_field(HotSpotResolvedJavaFieldImpl, type, "Ljdk/vm/ci/meta/JavaType;") \
|
||||||
object_field(HotSpotResolvedJavaFieldImpl, holder, "Ljdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl;") \
|
object_field(HotSpotResolvedJavaFieldImpl, holder, "Ljdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl;") \
|
||||||
int_field(HotSpotResolvedJavaFieldImpl, offset) \
|
int_field(HotSpotResolvedJavaFieldImpl, offset) \
|
||||||
int_field(HotSpotResolvedJavaFieldImpl, modifiers) \
|
end_class \
|
||||||
|
start_class(FieldInfo, jdk_vm_ci_hotspot_HotSpotResolvedObjectTypeImpl_FieldInfo) \
|
||||||
|
int_field(FieldInfo, nameIndex) \
|
||||||
|
int_field(FieldInfo, signatureIndex) \
|
||||||
|
int_field(FieldInfo, offset) \
|
||||||
|
int_field(FieldInfo, classfileFlags) \
|
||||||
|
int_field(FieldInfo, internalFlags) \
|
||||||
|
int_field(FieldInfo, initializerIndex) \
|
||||||
|
jvmci_constructor(FieldInfo, "(IIIIII)V") \
|
||||||
end_class \
|
end_class \
|
||||||
start_class(HotSpotResolvedJavaMethodImpl, jdk_vm_ci_hotspot_HotSpotResolvedJavaMethodImpl) \
|
start_class(HotSpotResolvedJavaMethodImpl, jdk_vm_ci_hotspot_HotSpotResolvedJavaMethodImpl) \
|
||||||
long_field(HotSpotResolvedJavaMethodImpl, methodHandle) \
|
long_field(HotSpotResolvedJavaMethodImpl, methodHandle) \
|
||||||
|
@ -156,7 +156,7 @@
|
|||||||
nonstatic_field(ExceptionTableElement, handler_pc, u2) \
|
nonstatic_field(ExceptionTableElement, handler_pc, u2) \
|
||||||
nonstatic_field(ExceptionTableElement, catch_type_index, u2) \
|
nonstatic_field(ExceptionTableElement, catch_type_index, u2) \
|
||||||
\
|
\
|
||||||
nonstatic_field(InstanceKlass, _fields, Array<u2>*) \
|
nonstatic_field(InstanceKlass, _fieldinfo_stream, Array<u1>*) \
|
||||||
nonstatic_field(InstanceKlass, _constants, ConstantPool*) \
|
nonstatic_field(InstanceKlass, _constants, ConstantPool*) \
|
||||||
volatile_nonstatic_field(InstanceKlass, _init_state, InstanceKlass::ClassState) \
|
volatile_nonstatic_field(InstanceKlass, _init_state, InstanceKlass::ClassState) \
|
||||||
volatile_nonstatic_field(InstanceKlass, _init_thread, JavaThread*) \
|
volatile_nonstatic_field(InstanceKlass, _init_thread, JavaThread*) \
|
||||||
@ -403,7 +403,6 @@
|
|||||||
|
|
||||||
#define VM_INT_CONSTANTS(declare_constant, declare_constant_with_value, declare_preprocessor_constant) \
|
#define VM_INT_CONSTANTS(declare_constant, declare_constant_with_value, declare_preprocessor_constant) \
|
||||||
declare_preprocessor_constant("ASSERT", DEBUG_ONLY(1) NOT_DEBUG(0)) \
|
declare_preprocessor_constant("ASSERT", DEBUG_ONLY(1) NOT_DEBUG(0)) \
|
||||||
declare_preprocessor_constant("FIELDINFO_TAG_SIZE", FIELDINFO_TAG_SIZE) \
|
|
||||||
\
|
\
|
||||||
declare_constant(CompLevel_none) \
|
declare_constant(CompLevel_none) \
|
||||||
declare_constant(CompLevel_simple) \
|
declare_constant(CompLevel_simple) \
|
||||||
@ -421,17 +420,15 @@
|
|||||||
declare_constant(JVM_ACC_HAS_FINALIZER) \
|
declare_constant(JVM_ACC_HAS_FINALIZER) \
|
||||||
declare_constant(JVM_ACC_IS_CLONEABLE_FAST) \
|
declare_constant(JVM_ACC_IS_CLONEABLE_FAST) \
|
||||||
declare_constant(JVM_ACC_IS_HIDDEN_CLASS) \
|
declare_constant(JVM_ACC_IS_HIDDEN_CLASS) \
|
||||||
declare_constant(JVM_ACC_FIELD_INTERNAL) \
|
|
||||||
declare_constant(JVM_ACC_FIELD_STABLE) \
|
|
||||||
declare_constant(JVM_ACC_FIELD_HAS_GENERIC_SIGNATURE) \
|
|
||||||
declare_constant(JVM_ACC_IS_VALUE_BASED_CLASS) \
|
declare_constant(JVM_ACC_IS_VALUE_BASED_CLASS) \
|
||||||
|
declare_constant(FieldInfo::FieldFlags::_ff_injected) \
|
||||||
|
declare_constant(FieldInfo::FieldFlags::_ff_stable) \
|
||||||
declare_preprocessor_constant("JVM_ACC_VARARGS", JVM_ACC_VARARGS) \
|
declare_preprocessor_constant("JVM_ACC_VARARGS", JVM_ACC_VARARGS) \
|
||||||
declare_preprocessor_constant("JVM_ACC_BRIDGE", JVM_ACC_BRIDGE) \
|
declare_preprocessor_constant("JVM_ACC_BRIDGE", JVM_ACC_BRIDGE) \
|
||||||
declare_preprocessor_constant("JVM_ACC_ANNOTATION", JVM_ACC_ANNOTATION) \
|
declare_preprocessor_constant("JVM_ACC_ANNOTATION", JVM_ACC_ANNOTATION) \
|
||||||
declare_preprocessor_constant("JVM_ACC_ENUM", JVM_ACC_ENUM) \
|
declare_preprocessor_constant("JVM_ACC_ENUM", JVM_ACC_ENUM) \
|
||||||
declare_preprocessor_constant("JVM_ACC_SYNTHETIC", JVM_ACC_SYNTHETIC) \
|
declare_preprocessor_constant("JVM_ACC_SYNTHETIC", JVM_ACC_SYNTHETIC) \
|
||||||
declare_preprocessor_constant("JVM_ACC_INTERFACE", JVM_ACC_INTERFACE) \
|
declare_preprocessor_constant("JVM_ACC_INTERFACE", JVM_ACC_INTERFACE) \
|
||||||
declare_preprocessor_constant("JVM_ACC_FIELD_INITIALIZED_FINAL_UPDATE", JVM_ACC_FIELD_INITIALIZED_FINAL_UPDATE) \
|
|
||||||
\
|
\
|
||||||
declare_constant(JVM_CONSTANT_Utf8) \
|
declare_constant(JVM_CONSTANT_Utf8) \
|
||||||
declare_constant(JVM_CONSTANT_Unicode) \
|
declare_constant(JVM_CONSTANT_Unicode) \
|
||||||
@ -645,13 +642,6 @@
|
|||||||
declare_constant(Deoptimization::Reason_TRAP_HISTORY_LENGTH) \
|
declare_constant(Deoptimization::Reason_TRAP_HISTORY_LENGTH) \
|
||||||
declare_constant(Deoptimization::_support_large_access_byte_array_virtualization) \
|
declare_constant(Deoptimization::_support_large_access_byte_array_virtualization) \
|
||||||
\
|
\
|
||||||
declare_constant(FieldInfo::access_flags_offset) \
|
|
||||||
declare_constant(FieldInfo::name_index_offset) \
|
|
||||||
declare_constant(FieldInfo::signature_index_offset) \
|
|
||||||
declare_constant(FieldInfo::initval_index_offset) \
|
|
||||||
declare_constant(FieldInfo::low_packed_offset) \
|
|
||||||
declare_constant(FieldInfo::high_packed_offset) \
|
|
||||||
declare_constant(FieldInfo::field_slots) \
|
|
||||||
\
|
\
|
||||||
declare_constant(InstanceKlass::linked) \
|
declare_constant(InstanceKlass::linked) \
|
||||||
declare_constant(InstanceKlass::being_initialized) \
|
declare_constant(InstanceKlass::being_initialized) \
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2012, 2022, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2012, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -38,6 +38,7 @@
|
|||||||
template(jdk_vm_ci_hotspot_HotSpotNmethod, "jdk/vm/ci/hotspot/HotSpotNmethod") \
|
template(jdk_vm_ci_hotspot_HotSpotNmethod, "jdk/vm/ci/hotspot/HotSpotNmethod") \
|
||||||
template(jdk_vm_ci_hotspot_HotSpotResolvedJavaMethodImpl, "jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl") \
|
template(jdk_vm_ci_hotspot_HotSpotResolvedJavaMethodImpl, "jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl") \
|
||||||
template(jdk_vm_ci_hotspot_HotSpotResolvedObjectTypeImpl, "jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl") \
|
template(jdk_vm_ci_hotspot_HotSpotResolvedObjectTypeImpl, "jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl") \
|
||||||
|
template(jdk_vm_ci_hotspot_HotSpotResolvedObjectTypeImpl_FieldInfo, "jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl$FieldInfo") \
|
||||||
template(jdk_vm_ci_hotspot_HotSpotResolvedPrimitiveType, "jdk/vm/ci/hotspot/HotSpotResolvedPrimitiveType") \
|
template(jdk_vm_ci_hotspot_HotSpotResolvedPrimitiveType, "jdk/vm/ci/hotspot/HotSpotResolvedPrimitiveType") \
|
||||||
template(jdk_vm_ci_hotspot_HotSpotResolvedJavaFieldImpl, "jdk/vm/ci/hotspot/HotSpotResolvedJavaFieldImpl") \
|
template(jdk_vm_ci_hotspot_HotSpotResolvedJavaFieldImpl, "jdk/vm/ci/hotspot/HotSpotResolvedJavaFieldImpl") \
|
||||||
template(jdk_vm_ci_hotspot_HotSpotCompressedNullConstant, "jdk/vm/ci/hotspot/HotSpotCompressedNullConstant") \
|
template(jdk_vm_ci_hotspot_HotSpotCompressedNullConstant, "jdk/vm/ci/hotspot/HotSpotCompressedNullConstant") \
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2000, 2022, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2000, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -41,6 +41,7 @@ class Array: public MetaspaceObj {
|
|||||||
friend class JVMCIVMStructs;
|
friend class JVMCIVMStructs;
|
||||||
friend class MethodHandleCompiler; // special case
|
friend class MethodHandleCompiler; // special case
|
||||||
friend class WhiteBox;
|
friend class WhiteBox;
|
||||||
|
friend class FieldInfoStream;
|
||||||
protected:
|
protected:
|
||||||
int _length; // the number of array elements
|
int _length; // the number of array elements
|
||||||
T _data[1]; // the array memory
|
T _data[1]; // the array memory
|
||||||
|
143
src/hotspot/share/oops/fieldInfo.cpp
Normal file
143
src/hotspot/share/oops/fieldInfo.cpp
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 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
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "precompiled.hpp"
|
||||||
|
#include "oops/fieldInfo.inline.hpp"
|
||||||
|
#include "runtime/atomic.hpp"
|
||||||
|
|
||||||
|
void FieldInfo::print(outputStream* os, ConstantPool* cp) {
|
||||||
|
os->print_cr("index=%d name_index=%d name=%s signature_index=%d signature=%s offset=%d "
|
||||||
|
"AccessFlags=%d FieldFlags=%d "
|
||||||
|
"initval_index=%d gen_signature_index=%d, gen_signature=%s contended_group=%d",
|
||||||
|
index(),
|
||||||
|
name_index(), name(cp)->as_utf8(),
|
||||||
|
signature_index(), signature(cp)->as_utf8(),
|
||||||
|
offset(),
|
||||||
|
access_flags().as_int(),
|
||||||
|
field_flags().as_uint(),
|
||||||
|
initializer_index(),
|
||||||
|
generic_signature_index(),
|
||||||
|
_field_flags.is_injected() ? lookup_symbol(generic_signature_index())->as_utf8() : cp->symbol_at(generic_signature_index())->as_utf8(),
|
||||||
|
contended_group());
|
||||||
|
}
|
||||||
|
|
||||||
|
void FieldInfo::print_from_growable_array(outputStream* os, GrowableArray<FieldInfo>* array, ConstantPool* cp) {
|
||||||
|
for (int i = 0; i < array->length(); i++) {
|
||||||
|
array->adr_at(i)->print(os, cp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Array<u1>* FieldInfoStream::create_FieldInfoStream(GrowableArray<FieldInfo>* fields, int java_fields, int injected_fields,
|
||||||
|
ClassLoaderData* loader_data, TRAPS) {
|
||||||
|
// The stream format described in fieldInfo.hpp is:
|
||||||
|
// FieldInfoStream := j=num_java_fields k=num_injected_fields Field[j+k] End
|
||||||
|
// Field := name sig offset access flags Optionals(flags)
|
||||||
|
// Optionals(i) := initval?[i&is_init] // ConstantValue attr
|
||||||
|
// gsig?[i&is_generic] // signature attr
|
||||||
|
// group?[i&is_contended] // Contended anno (group)
|
||||||
|
// End = 0
|
||||||
|
|
||||||
|
using StreamSizer = UNSIGNED5::Sizer<>;
|
||||||
|
using StreamFieldSizer = Mapper<StreamSizer>;
|
||||||
|
StreamSizer s;
|
||||||
|
StreamFieldSizer sizer(&s);
|
||||||
|
|
||||||
|
sizer.consumer()->accept_uint(java_fields);
|
||||||
|
sizer.consumer()->accept_uint(injected_fields);
|
||||||
|
for (int i = 0; i < fields->length(); i++) {
|
||||||
|
FieldInfo* fi = fields->adr_at(i);
|
||||||
|
sizer.map_field_info(*fi);
|
||||||
|
}
|
||||||
|
int storage_size = sizer.consumer()->position() + 1;
|
||||||
|
Array<u1>* const fis = MetadataFactory::new_array<u1>(loader_data, storage_size, CHECK_NULL);
|
||||||
|
|
||||||
|
using StreamWriter = UNSIGNED5::Writer<Array<u1>*, int, ArrayHelper<Array<u1>*, int>>;
|
||||||
|
using StreamFieldWriter = Mapper<StreamWriter>;
|
||||||
|
StreamWriter w(fis);
|
||||||
|
StreamFieldWriter writer(&w);
|
||||||
|
|
||||||
|
writer.consumer()->accept_uint(java_fields);
|
||||||
|
writer.consumer()->accept_uint(injected_fields);
|
||||||
|
for (int i = 0; i < fields->length(); i++) {
|
||||||
|
FieldInfo* fi = fields->adr_at(i);
|
||||||
|
writer.map_field_info(*fi);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef ASSERT
|
||||||
|
FieldInfoReader r(fis);
|
||||||
|
u2 jfc = r.next_uint();
|
||||||
|
assert(jfc == java_fields, "Must be");
|
||||||
|
int ifc = r.next_uint();
|
||||||
|
assert(ifc == injected_fields, "Must be");
|
||||||
|
for (int i = 0; i < jfc + ifc; i++) {
|
||||||
|
FieldInfo fi;
|
||||||
|
r.read_field_info(fi);
|
||||||
|
FieldInfo* fi_ref = fields->adr_at(i);
|
||||||
|
assert(fi_ref->name_index() == fi.name_index(), "Must be");
|
||||||
|
assert(fi_ref->signature_index() == fi.signature_index(), "Must be");
|
||||||
|
assert(fi_ref->offset() == fi.offset(), "Must be");
|
||||||
|
assert(fi_ref->access_flags().as_int() == fi.access_flags().as_int(), "Must be");
|
||||||
|
assert(fi_ref->field_flags().as_uint() == fi.field_flags().as_uint(), " Must be");
|
||||||
|
if(fi_ref->field_flags().is_initialized()) {
|
||||||
|
assert(fi_ref->initializer_index() == fi.initializer_index(), "Must be");
|
||||||
|
}
|
||||||
|
if (fi_ref->field_flags().is_generic()) {
|
||||||
|
assert(fi_ref->generic_signature_index() == fi.generic_signature_index(), "Must be");
|
||||||
|
}
|
||||||
|
if (fi_ref->field_flags().is_contended()) {
|
||||||
|
assert(fi_ref->contended_group() == fi.contended_group(), "Must be");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif // ASSERT
|
||||||
|
|
||||||
|
return fis;
|
||||||
|
}
|
||||||
|
|
||||||
|
GrowableArray<FieldInfo>* FieldInfoStream::create_FieldInfoArray(const Array<u1>* fis, int* java_fields_count, int* injected_fields_count) {
|
||||||
|
int length = FieldInfoStream::num_total_fields(fis);
|
||||||
|
GrowableArray<FieldInfo>* array = new GrowableArray<FieldInfo>(length);
|
||||||
|
FieldInfoReader r(fis);
|
||||||
|
*java_fields_count = r.next_uint();
|
||||||
|
*injected_fields_count = r.next_uint();
|
||||||
|
while (r.has_next()) {
|
||||||
|
FieldInfo fi;
|
||||||
|
r.read_field_info(fi);
|
||||||
|
array->append(fi);
|
||||||
|
}
|
||||||
|
assert(array->length() == length, "Must be");
|
||||||
|
assert(array->length() == *java_fields_count + *injected_fields_count, "Must be");
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FieldInfoStream::print_from_fieldinfo_stream(Array<u1>* fis, outputStream* os, ConstantPool* cp) {
|
||||||
|
int length = FieldInfoStream::num_total_fields(fis);
|
||||||
|
FieldInfoReader r(fis);
|
||||||
|
int java_field_count = r.next_uint();
|
||||||
|
int injected_fields_count = r.next_uint();
|
||||||
|
while (r.has_next()) {
|
||||||
|
FieldInfo fi;
|
||||||
|
r.read_field_info(fi);
|
||||||
|
fi.print(os, cp);
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2011, 2022, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2011, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -25,11 +25,27 @@
|
|||||||
#ifndef SHARE_OOPS_FIELDINFO_HPP
|
#ifndef SHARE_OOPS_FIELDINFO_HPP
|
||||||
#define SHARE_OOPS_FIELDINFO_HPP
|
#define SHARE_OOPS_FIELDINFO_HPP
|
||||||
|
|
||||||
#include "oops/constantPool.hpp"
|
#include "memory/allocation.hpp"
|
||||||
#include "oops/symbol.hpp"
|
|
||||||
#include "oops/typeArrayOop.hpp"
|
#include "oops/typeArrayOop.hpp"
|
||||||
|
#include "utilities/unsigned5.hpp"
|
||||||
#include "utilities/vmEnums.hpp"
|
#include "utilities/vmEnums.hpp"
|
||||||
|
|
||||||
|
static constexpr u4 flag_mask(int pos) {
|
||||||
|
return (u4)1 << pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Helper class for access to the underlying Array<u1> used to
|
||||||
|
// store the compressed stream of FieldInfo
|
||||||
|
template<typename ARR, typename OFF>
|
||||||
|
struct ArrayHelper {
|
||||||
|
uint8_t operator()(ARR a, OFF i) const { return a->at(i); };
|
||||||
|
void operator()(ARR a, OFF i, uint8_t b) const { a->at_put(i,b); };
|
||||||
|
// So, an expression ArrayWriterHelper() acts like these lambdas:
|
||||||
|
// auto get = [&](ARR a, OFF i){ return a[i]; };
|
||||||
|
// auto set = [&](ARR a, OFF i, uint8_t x){ a[i] = x; };
|
||||||
|
};
|
||||||
|
|
||||||
// This class represents the field information contained in the fields
|
// This class represents the field information contained in the fields
|
||||||
// array of an InstanceKlass. Currently it's laid on top an array of
|
// array of an InstanceKlass. Currently it's laid on top an array of
|
||||||
// Java shorts but in the future it could simply be used as a real
|
// Java shorts but in the future it could simply be used as a real
|
||||||
@ -40,135 +56,260 @@ class FieldInfo {
|
|||||||
friend class fieldDescriptor;
|
friend class fieldDescriptor;
|
||||||
friend class JavaFieldStream;
|
friend class JavaFieldStream;
|
||||||
friend class ClassFileParser;
|
friend class ClassFileParser;
|
||||||
|
friend class FieldInfoStream;
|
||||||
|
friend class FieldStreamBase;
|
||||||
|
friend class FieldInfoReader;
|
||||||
|
friend class VMStructs;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// fields
|
|
||||||
// Field info extracted from the class file and stored
|
|
||||||
// as an array of 6 shorts.
|
|
||||||
|
|
||||||
#define FIELDINFO_TAG_SIZE 2
|
class FieldFlags {
|
||||||
#define FIELDINFO_TAG_OFFSET 1 << 0
|
friend class VMStructs;
|
||||||
#define FIELDINFO_TAG_CONTENDED 1 << 1
|
friend class JVMCIVMStructs;
|
||||||
|
|
||||||
// Packed field has the tag, and can be either of:
|
// The ordering of this enum is totally internal. More frequent
|
||||||
// hi bits <--------------------------- lo bits
|
// flags should come earlier than less frequent ones, because
|
||||||
// |---------high---------|---------low---------|
|
// earlier ones compress better.
|
||||||
// ..........................................CO
|
enum FieldFlagBitPosition {
|
||||||
// ..........................................00 - non-contended field
|
_ff_initialized, // has ConstantValue initializer attribute
|
||||||
// [--contention_group--]....................10 - contended field with contention group
|
_ff_injected, // internal field injected by the JVM
|
||||||
// [------------------offset----------------]01 - real field offset
|
_ff_generic, // has a generic signature
|
||||||
|
_ff_stable, // trust as stable b/c declared as @Stable
|
||||||
|
_ff_contended, // is contended, may have contention-group
|
||||||
|
};
|
||||||
|
|
||||||
// Bit O indicates if the packed field contains an offset (O=1) or not (O=0)
|
// Some but not all of the flag bits signal the presence of an
|
||||||
// Bit C indicates if the field is contended (C=1) or not (C=0)
|
// additional 32-bit item in the field record.
|
||||||
// (if it is contended, the high packed field contains the contention group)
|
static const u4 _optional_item_bit_mask =
|
||||||
|
flag_mask((int)_ff_initialized) |
|
||||||
|
flag_mask((int)_ff_generic) |
|
||||||
|
flag_mask((int)_ff_contended);
|
||||||
|
|
||||||
enum FieldOffset {
|
// boilerplate:
|
||||||
access_flags_offset = 0,
|
u4 _flags;
|
||||||
name_index_offset = 1,
|
|
||||||
signature_index_offset = 2,
|
bool test_flag(FieldFlagBitPosition pos) const {
|
||||||
initval_index_offset = 3,
|
return (_flags & flag_mask(pos)) != 0;
|
||||||
low_packed_offset = 4,
|
}
|
||||||
high_packed_offset = 5,
|
void update_flag(FieldFlagBitPosition pos, bool z) {
|
||||||
field_slots = 6
|
if (z) _flags |= flag_mask(pos);
|
||||||
|
else _flags &= ~flag_mask(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
FieldFlags(u4 flags) {
|
||||||
|
_flags = flags;
|
||||||
|
}
|
||||||
|
u4 as_uint() const { return _flags; }
|
||||||
|
bool has_any_optionals() const {
|
||||||
|
return (_flags & _optional_item_bit_mask) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_initialized() const { return test_flag(_ff_initialized); }
|
||||||
|
bool is_injected() const { return test_flag(_ff_injected); }
|
||||||
|
bool is_generic() const { return test_flag(_ff_generic); }
|
||||||
|
bool is_stable() const { return test_flag(_ff_stable); }
|
||||||
|
bool is_contended() const { return test_flag(_ff_contended); }
|
||||||
|
|
||||||
|
void update_initialized(bool z) { update_flag(_ff_initialized, z); }
|
||||||
|
void update_injected(bool z) { update_flag(_ff_injected, z); }
|
||||||
|
void update_generic(bool z) { update_flag(_ff_generic, z); }
|
||||||
|
void update_stable(bool z) { update_flag(_ff_stable, z); }
|
||||||
|
void update_contended(bool z) { update_flag(_ff_contended, z); }
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
u2 _shorts[field_slots];
|
// The following items are the unpacked bitwise information content
|
||||||
|
// of a field record. Per-field metadata extracted from the class
|
||||||
void set_name_index(u2 val) { _shorts[name_index_offset] = val; }
|
// file are stored logically as a group of these items. The
|
||||||
void set_signature_index(u2 val) { _shorts[signature_index_offset] = val; }
|
// classfile parser produces these records in a temporary array, and
|
||||||
void set_initval_index(u2 val) { _shorts[initval_index_offset] = val; }
|
// then compresses them into a FieldInfoStream.
|
||||||
|
//
|
||||||
u2 name_index() const { return _shorts[name_index_offset]; }
|
u4 _index; // which field it is
|
||||||
u2 signature_index() const { return _shorts[signature_index_offset]; }
|
u2 _name_index; // index in CP of name
|
||||||
u2 initval_index() const { return _shorts[initval_index_offset]; }
|
u2 _signature_index; // index in CP of descriptor
|
||||||
|
u4 _offset; // offset in object layout
|
||||||
|
AccessFlags _access_flags; // access flags (JVM spec)
|
||||||
|
FieldFlags _field_flags; // VM defined flags (not JVM spec)
|
||||||
|
u2 _initializer_index; // index from ConstantValue attr (or 0)
|
||||||
|
u2 _generic_signature_index; // index from GenericSignature attr (or 0)
|
||||||
|
u2 _contention_group; // index from @Contended group item (or 0)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static FieldInfo* from_field_array(Array<u2>* fields, int index) {
|
|
||||||
return ((FieldInfo*)fields->adr_at(index * field_slots));
|
FieldInfo() : _name_index(0),
|
||||||
|
_signature_index(0),
|
||||||
|
_offset(0),
|
||||||
|
_access_flags(AccessFlags(0)),
|
||||||
|
_field_flags(FieldFlags(0)),
|
||||||
|
_initializer_index(0),
|
||||||
|
_generic_signature_index(0),
|
||||||
|
_contention_group(0) { }
|
||||||
|
|
||||||
|
FieldInfo(AccessFlags access_flags, u2 name_index, u2 signature_index, u2 initval_index, FieldInfo::FieldFlags fflags) :
|
||||||
|
_name_index(name_index),
|
||||||
|
_signature_index(signature_index),
|
||||||
|
_offset(0),
|
||||||
|
_access_flags(access_flags),
|
||||||
|
_field_flags(fflags),
|
||||||
|
_initializer_index(initval_index),
|
||||||
|
_generic_signature_index(0),
|
||||||
|
_contention_group(0) {
|
||||||
|
if (initval_index != 0) {
|
||||||
|
_field_flags.update_initialized(true);
|
||||||
}
|
}
|
||||||
static FieldInfo* from_field_array(u2* fields, int index) {
|
|
||||||
return ((FieldInfo*)(fields + index * field_slots));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void initialize(u2 access_flags,
|
u4 index() const { return _index; }
|
||||||
u2 name_index,
|
void set_index(u4 index) { _index = index; }
|
||||||
u2 signature_index,
|
u2 name_index() const { return _name_index; }
|
||||||
u2 initval_index) {
|
void set_name_index(u2 index) { _name_index = index; }
|
||||||
_shorts[access_flags_offset] = access_flags;
|
u2 signature_index() const { return _signature_index; }
|
||||||
_shorts[name_index_offset] = name_index;
|
void set_signature_index(u2 index) { _signature_index = index; }
|
||||||
_shorts[signature_index_offset] = signature_index;
|
u4 offset() const { return _offset; }
|
||||||
_shorts[initval_index_offset] = initval_index;
|
void set_offset(u4 offset) { _offset = offset; }
|
||||||
_shorts[low_packed_offset] = 0;
|
AccessFlags access_flags() const { return _access_flags; }
|
||||||
_shorts[high_packed_offset] = 0;
|
FieldFlags field_flags() const { return _field_flags; }
|
||||||
}
|
FieldFlags* field_flags_addr() { return &_field_flags; }
|
||||||
|
u2 initializer_index() const { return _initializer_index; }
|
||||||
u2 access_flags() const { return _shorts[access_flags_offset]; }
|
void set_initializer_index(u2 index) { _initializer_index = index; }
|
||||||
u4 offset() const {
|
u2 generic_signature_index() const { return _generic_signature_index; }
|
||||||
assert((_shorts[low_packed_offset] & FIELDINFO_TAG_OFFSET) != 0, "Offset must have been set");
|
void set_generic_signature_index(u2 index) { _generic_signature_index = index; }
|
||||||
return build_int_from_shorts(_shorts[low_packed_offset], _shorts[high_packed_offset]) >> FIELDINFO_TAG_SIZE;
|
u2 contention_group() const { return _contention_group; }
|
||||||
}
|
|
||||||
|
|
||||||
bool is_contended() const {
|
bool is_contended() const {
|
||||||
return (_shorts[low_packed_offset] & FIELDINFO_TAG_CONTENDED) != 0;
|
return _field_flags.is_contended();
|
||||||
}
|
}
|
||||||
|
|
||||||
u2 contended_group() const {
|
u2 contended_group() const {
|
||||||
assert((_shorts[low_packed_offset] & FIELDINFO_TAG_OFFSET) == 0, "Offset must not have been set");
|
assert(is_contended(), "");
|
||||||
assert((_shorts[low_packed_offset] & FIELDINFO_TAG_CONTENDED) != 0, "Field must be contended");
|
return _contention_group;
|
||||||
return _shorts[high_packed_offset];
|
}
|
||||||
|
|
||||||
|
void set_contended_group(u2 group) {
|
||||||
|
_field_flags.update_contended(true);
|
||||||
|
_contention_group = group;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_offset_set() const {
|
bool is_offset_set() const {
|
||||||
return (_shorts[low_packed_offset] & FIELDINFO_TAG_OFFSET)!= 0;
|
return _offset != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Symbol* name(ConstantPool* cp) const {
|
inline Symbol* name(ConstantPool* cp) const;
|
||||||
int index = name_index();
|
|
||||||
if (is_internal()) {
|
|
||||||
return lookup_symbol(index);
|
|
||||||
}
|
|
||||||
return cp->symbol_at(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
Symbol* signature(ConstantPool* cp) const {
|
inline Symbol* signature(ConstantPool* cp) const;
|
||||||
int index = signature_index();
|
|
||||||
if (is_internal()) {
|
|
||||||
return lookup_symbol(index);
|
|
||||||
}
|
|
||||||
return cp->symbol_at(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_access_flags(u2 val) { _shorts[access_flags_offset] = val; }
|
inline Symbol* lookup_symbol(int symbol_index) const;
|
||||||
void set_offset(u4 val) {
|
|
||||||
val = val << FIELDINFO_TAG_SIZE; // make room for tag
|
|
||||||
_shorts[low_packed_offset] = extract_low_short_from_int(val) | FIELDINFO_TAG_OFFSET;
|
|
||||||
_shorts[high_packed_offset] = extract_high_short_from_int(val);
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_contended_group(u2 val) {
|
void print(outputStream* os, ConstantPool* cp);
|
||||||
assert((_shorts[low_packed_offset] & FIELDINFO_TAG_OFFSET) == 0, "Offset must not have been set");
|
void static print_from_growable_array(outputStream* os, GrowableArray<FieldInfo>* array, ConstantPool* cp);
|
||||||
assert((_shorts[low_packed_offset] & FIELDINFO_TAG_CONTENDED) == 0, "Overwriting contended group");
|
};
|
||||||
_shorts[low_packed_offset] |= FIELDINFO_TAG_CONTENDED;
|
|
||||||
_shorts[high_packed_offset] = val;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool is_internal() const {
|
class FieldInfoStream;
|
||||||
return (access_flags() & JVM_ACC_FIELD_INTERNAL) != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool is_stable() const {
|
// Gadget for sizing and/or writing a stream of field records.
|
||||||
return (access_flags() & JVM_ACC_FIELD_STABLE) != 0;
|
template<typename CON>
|
||||||
}
|
class Mapper {
|
||||||
void set_stable(bool z) {
|
CON* _consumer; // can be UNSIGNED5::Writer or UNSIGNED5::Sizer
|
||||||
if (z) _shorts[access_flags_offset] |= JVM_ACC_FIELD_STABLE;
|
int _next_index;
|
||||||
else _shorts[access_flags_offset] &= ~JVM_ACC_FIELD_STABLE;
|
public:
|
||||||
}
|
Mapper(CON* consumer) : _consumer(consumer) { _next_index = 0; }
|
||||||
|
int next_index() const { return _next_index; }
|
||||||
|
void set_next_index(int next_index) { _next_index = next_index; }
|
||||||
|
CON* consumer() const { return _consumer; }
|
||||||
|
void map_field_info(const FieldInfo& fi);
|
||||||
|
};
|
||||||
|
|
||||||
Symbol* lookup_symbol(int symbol_index) const {
|
|
||||||
assert(is_internal(), "only internal fields");
|
// Gadget for decoding and reading the stream of field records.
|
||||||
return Symbol::vm_symbol_at(static_cast<vmSymbolID>(symbol_index));
|
class FieldInfoReader {
|
||||||
}
|
friend class FieldInfoStream;
|
||||||
|
friend class ClassFileParser;
|
||||||
|
friend class FieldStreamBase;
|
||||||
|
friend class FieldInfo;
|
||||||
|
|
||||||
|
UNSIGNED5::Reader<const u1*, int> _r;
|
||||||
|
int _next_index;
|
||||||
|
|
||||||
|
public:
|
||||||
|
FieldInfoReader(const Array<u1>* fi);
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint32_t next_uint() { return _r.next_uint(); }
|
||||||
|
void skip(int n) { int s = _r.try_skip(n); assert(s == n,""); }
|
||||||
|
|
||||||
|
public:
|
||||||
|
int has_next() { return _r.has_next(); }
|
||||||
|
int position() { return _r.position(); }
|
||||||
|
int next_index() { return _next_index; }
|
||||||
|
void read_field_info(FieldInfo& fi);
|
||||||
|
// skip a whole field record, both required and optional bits
|
||||||
|
FieldInfoReader& skip_field_info();
|
||||||
|
|
||||||
|
// Skip to the nth field. If the reader is freshly initialized to
|
||||||
|
// the zero index, this will call skip_field_info() n times.
|
||||||
|
FieldInfoReader& skip_to_field_info(int n);
|
||||||
|
|
||||||
|
// for random access, if you know where to go up front:
|
||||||
|
FieldInfoReader& set_position_and_next_index(int position, int next_index);
|
||||||
|
};
|
||||||
|
|
||||||
|
// The format of the stream, after decompression, is a series of
|
||||||
|
// integers organized like this:
|
||||||
|
//
|
||||||
|
// FieldInfoStream := j=num_java_fields k=num_injected_fields Field[j+k] End
|
||||||
|
// Field := name sig offset access flags Optionals(flags)
|
||||||
|
// Optionals(i) := initval?[i&is_init] // ConstantValue attr
|
||||||
|
// gsig?[i&is_generic] // signature attr
|
||||||
|
// group?[i&is_contended] // Contended anno (group)
|
||||||
|
// End = 0
|
||||||
|
//
|
||||||
|
class FieldInfoStream : AllStatic {
|
||||||
|
friend class fieldDescriptor;
|
||||||
|
friend class JavaFieldStream;
|
||||||
|
friend class FieldStreamBase;
|
||||||
|
friend class ClassFileParser;
|
||||||
|
|
||||||
|
public:
|
||||||
|
static int num_java_fields(const Array<u1>* fis);
|
||||||
|
static int num_injected_java_fields(const Array<u1>* fis);
|
||||||
|
static int num_total_fields(const Array<u1>* fis);
|
||||||
|
|
||||||
|
static Array<u1>* create_FieldInfoStream(GrowableArray<FieldInfo>* fields, int java_fields, int injected_fields,
|
||||||
|
ClassLoaderData* loader_data, TRAPS);
|
||||||
|
static GrowableArray<FieldInfo>* create_FieldInfoArray(const Array<u1>* fis, int* java_fields_count, int* injected_fields_count);
|
||||||
|
static void print_from_fieldinfo_stream(Array<u1>* fis, outputStream* os, ConstantPool* cp);
|
||||||
|
};
|
||||||
|
|
||||||
|
class FieldStatus {
|
||||||
|
enum FieldStatusBitPosition {
|
||||||
|
_fs_access_watched, // field access is watched by JVMTI
|
||||||
|
_fs_modification_watched, // field modification is watched by JVMTI
|
||||||
|
_initialized_final_update // (static) final field updated outside (class) initializer
|
||||||
|
};
|
||||||
|
|
||||||
|
// boilerplate:
|
||||||
|
u1 _flags;
|
||||||
|
static constexpr u1 flag_mask(FieldStatusBitPosition pos) { return (u1)1 << (int)pos; }
|
||||||
|
bool test_flag(FieldStatusBitPosition pos) { return (_flags & flag_mask(pos)) != 0; }
|
||||||
|
// this performs an atomic update on a live status byte!
|
||||||
|
void update_flag(FieldStatusBitPosition pos, bool z);
|
||||||
|
// out-of-line functions do a CAS-loop
|
||||||
|
static void atomic_set_bits(u1& flags, u1 mask);
|
||||||
|
static void atomic_clear_bits(u1& flags, u1 mask);
|
||||||
|
|
||||||
|
public:
|
||||||
|
FieldStatus() { _flags = 0; }
|
||||||
|
FieldStatus(u1 flags) { _flags = flags; }
|
||||||
|
u1 as_uint() { return _flags; }
|
||||||
|
|
||||||
|
bool is_access_watched() { return test_flag(_fs_access_watched); }
|
||||||
|
bool is_modification_watched() { return test_flag(_fs_modification_watched); }
|
||||||
|
bool is_initialized_final_update() { return test_flag(_initialized_final_update); }
|
||||||
|
|
||||||
|
void update_access_watched(bool z);
|
||||||
|
void update_modification_watched(bool z);
|
||||||
|
void update_initialized_final_update(bool z);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // SHARE_OOPS_FIELDINFO_HPP
|
#endif // SHARE_OOPS_FIELDINFO_HPP
|
||||||
|
182
src/hotspot/share/oops/fieldInfo.inline.hpp
Normal file
182
src/hotspot/share/oops/fieldInfo.inline.hpp
Normal file
@ -0,0 +1,182 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 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
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SHARE_OOPS_FIELDINFO_INLINE_HPP
|
||||||
|
#define SHARE_OOPS_FIELDINFO_INLINE_HPP
|
||||||
|
|
||||||
|
#include "oops/fieldInfo.hpp"
|
||||||
|
|
||||||
|
#include "memory/metadataFactory.hpp"
|
||||||
|
#include "oops/constantPool.hpp"
|
||||||
|
#include "oops/symbol.hpp"
|
||||||
|
|
||||||
|
inline Symbol* FieldInfo::name(ConstantPool* cp) const {
|
||||||
|
int index = _name_index;
|
||||||
|
if (_field_flags.is_injected()) {
|
||||||
|
return lookup_symbol(index);
|
||||||
|
}
|
||||||
|
return cp->symbol_at(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Symbol* FieldInfo::signature(ConstantPool* cp) const {
|
||||||
|
int index = _signature_index;
|
||||||
|
if (_field_flags.is_injected()) {
|
||||||
|
return lookup_symbol(index);
|
||||||
|
}
|
||||||
|
return cp->symbol_at(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Symbol* FieldInfo::lookup_symbol(int symbol_index) const {
|
||||||
|
assert(_field_flags.is_injected(), "only injected fields");
|
||||||
|
return Symbol::vm_symbol_at(static_cast<vmSymbolID>(symbol_index));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int FieldInfoStream::num_injected_java_fields(const Array<u1>* fis) {
|
||||||
|
FieldInfoReader fir(fis);
|
||||||
|
fir.skip(1);
|
||||||
|
return fir.next_uint();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int FieldInfoStream::num_total_fields(const Array<u1>* fis) {
|
||||||
|
FieldInfoReader fir(fis);
|
||||||
|
return fir.next_uint() + fir.next_uint();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int FieldInfoStream::num_java_fields(const Array<u1>* fis) { return FieldInfoReader(fis).next_uint(); }
|
||||||
|
|
||||||
|
template<typename CON>
|
||||||
|
inline void Mapper<CON>::map_field_info(const FieldInfo& fi) {
|
||||||
|
_next_index++; // pre-increment
|
||||||
|
_consumer->accept_uint(fi.name_index());
|
||||||
|
_consumer->accept_uint(fi.signature_index());
|
||||||
|
_consumer->accept_uint(fi.offset());
|
||||||
|
_consumer->accept_uint(fi.access_flags().as_int());
|
||||||
|
_consumer->accept_uint(fi.field_flags().as_uint());
|
||||||
|
if(fi.field_flags().has_any_optionals()) {
|
||||||
|
if (fi.field_flags().is_initialized()) {
|
||||||
|
_consumer->accept_uint(fi.initializer_index());
|
||||||
|
}
|
||||||
|
if (fi.field_flags().is_generic()) {
|
||||||
|
_consumer->accept_uint(fi.generic_signature_index());
|
||||||
|
}
|
||||||
|
if (fi.field_flags().is_contended()) {
|
||||||
|
_consumer->accept_uint(fi.contention_group());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
assert(fi.initializer_index() == 0, "");
|
||||||
|
assert(fi.generic_signature_index() == 0, "");
|
||||||
|
assert(fi.contention_group() == 0, "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline FieldInfoReader::FieldInfoReader(const Array<u1>* fi)
|
||||||
|
: _r(fi->data(), 0),
|
||||||
|
_next_index(0) { }
|
||||||
|
|
||||||
|
inline void FieldInfoReader::read_field_info(FieldInfo& fi) {
|
||||||
|
fi._index = _next_index++;
|
||||||
|
fi._name_index = next_uint();
|
||||||
|
fi._signature_index = next_uint();
|
||||||
|
fi._offset = next_uint();
|
||||||
|
fi._access_flags = AccessFlags(next_uint());
|
||||||
|
fi._field_flags = FieldInfo::FieldFlags(next_uint());
|
||||||
|
if (fi._field_flags.is_initialized()) {
|
||||||
|
fi._initializer_index = next_uint();
|
||||||
|
} else {
|
||||||
|
fi._initializer_index = 0;
|
||||||
|
}
|
||||||
|
if (fi._field_flags.is_generic()) {
|
||||||
|
fi._generic_signature_index = next_uint();
|
||||||
|
} else {
|
||||||
|
fi._generic_signature_index = 0;
|
||||||
|
}
|
||||||
|
if (fi._field_flags.is_contended()) {
|
||||||
|
fi._contention_group = next_uint();
|
||||||
|
} else {
|
||||||
|
fi._contention_group = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline FieldInfoReader& FieldInfoReader::skip_field_info() {
|
||||||
|
_next_index++;
|
||||||
|
const int name_sig_af_off = 4; // four items
|
||||||
|
skip(name_sig_af_off);
|
||||||
|
FieldInfo::FieldFlags ff(next_uint());
|
||||||
|
if (ff.has_any_optionals()) {
|
||||||
|
const int init_gen_cont = (ff.is_initialized() +
|
||||||
|
ff.is_generic() +
|
||||||
|
ff.is_contended());
|
||||||
|
skip(init_gen_cont); // up to three items
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip to the nth field. If the reader is freshly initialized to
|
||||||
|
// the zero index, this will call skip_field_info() n times.
|
||||||
|
inline FieldInfoReader& FieldInfoReader::skip_to_field_info(int n) {
|
||||||
|
assert(n >= _next_index, "already past that index");
|
||||||
|
const int count = n - _next_index;
|
||||||
|
for (int i = 0; i < count; i++) skip_field_info();
|
||||||
|
assert(_next_index == n, "");
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// for random access, if you know where to go up front:
|
||||||
|
inline FieldInfoReader& FieldInfoReader::set_position_and_next_index(int position, int next_index) {
|
||||||
|
_r.set_position(position);
|
||||||
|
_next_index = next_index;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void FieldStatus::atomic_set_bits(u1& flags, u1 mask) {
|
||||||
|
// Atomically update the flags with the bits given
|
||||||
|
u1 old_flags, new_flags, witness;
|
||||||
|
do {
|
||||||
|
old_flags = flags;
|
||||||
|
new_flags = old_flags | mask;
|
||||||
|
witness = Atomic::cmpxchg(&flags, old_flags, new_flags);
|
||||||
|
} while (witness != old_flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void FieldStatus::atomic_clear_bits(u1& flags, u1 mask) {
|
||||||
|
// Atomically update the flags with the bits given
|
||||||
|
u1 old_flags, new_flags, witness;
|
||||||
|
do {
|
||||||
|
old_flags = flags;
|
||||||
|
new_flags = old_flags & ~mask;
|
||||||
|
witness = Atomic::cmpxchg(&flags, old_flags, new_flags);
|
||||||
|
} while (witness != old_flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void FieldStatus::update_flag(FieldStatusBitPosition pos, bool z) {
|
||||||
|
if (z) atomic_set_bits(_flags, flag_mask(pos));
|
||||||
|
else atomic_clear_bits(_flags, flag_mask(pos));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void FieldStatus::update_access_watched(bool z) { update_flag(_fs_access_watched, z); }
|
||||||
|
inline void FieldStatus::update_modification_watched(bool z) { update_flag(_fs_modification_watched, z); }
|
||||||
|
inline void FieldStatus::update_initialized_final_update(bool z) { update_flag(_initialized_final_update, z); }
|
||||||
|
|
||||||
|
#endif // SHARE_OOPS_FIELDINFO_INLINE_HPP
|
@ -39,48 +39,33 @@
|
|||||||
// cases.
|
// cases.
|
||||||
class FieldStreamBase : public StackObj {
|
class FieldStreamBase : public StackObj {
|
||||||
protected:
|
protected:
|
||||||
Array<u2>* _fields;
|
const Array<u1>* _fieldinfo_stream;
|
||||||
|
FieldInfoReader _reader;
|
||||||
constantPoolHandle _constants;
|
constantPoolHandle _constants;
|
||||||
int _index;
|
int _index;
|
||||||
int _limit;
|
int _limit;
|
||||||
int _generic_signature_slot;
|
|
||||||
|
FieldInfo _fi_buf;
|
||||||
fieldDescriptor _fd_buf;
|
fieldDescriptor _fd_buf;
|
||||||
|
|
||||||
FieldInfo* field() const { return FieldInfo::from_field_array(_fields, _index); }
|
FieldInfo const * field() const {
|
||||||
|
assert(!done(), "no more fields");
|
||||||
int init_generic_signature_start_slot() {
|
return &_fi_buf;
|
||||||
int length = _fields->length();
|
|
||||||
int num_fields = _index;
|
|
||||||
int skipped_generic_signature_slots = 0;
|
|
||||||
FieldInfo* fi;
|
|
||||||
AccessFlags flags;
|
|
||||||
/* Scan from 0 to the current _index. Count the number of generic
|
|
||||||
signature slots for field[0] to field[_index - 1]. */
|
|
||||||
for (int i = 0; i < _index; i++) {
|
|
||||||
fi = FieldInfo::from_field_array(_fields, i);
|
|
||||||
flags.set_flags(fi->access_flags());
|
|
||||||
if (flags.field_has_generic_signature()) {
|
|
||||||
length --;
|
|
||||||
skipped_generic_signature_slots ++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* Scan from the current _index. */
|
|
||||||
for (int i = _index; i*FieldInfo::field_slots < length; i++) {
|
|
||||||
fi = FieldInfo::from_field_array(_fields, i);
|
|
||||||
flags.set_flags(fi->access_flags());
|
|
||||||
if (flags.field_has_generic_signature()) {
|
|
||||||
length --;
|
|
||||||
}
|
|
||||||
num_fields ++;
|
|
||||||
}
|
|
||||||
_generic_signature_slot = length + skipped_generic_signature_slots;
|
|
||||||
assert(_generic_signature_slot <= _fields->length(), "");
|
|
||||||
return num_fields;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline FieldStreamBase(Array<u2>* fields, ConstantPool* constants, int start, int limit);
|
inline FieldStreamBase(const Array<u1>* fieldinfo_stream, ConstantPool* constants, int start, int limit);
|
||||||
|
|
||||||
inline FieldStreamBase(Array<u2>* fields, ConstantPool* constants);
|
inline FieldStreamBase(Array<u1>* fieldinfo_stream, ConstantPool* constants);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void initialize() {
|
||||||
|
int java_fields_count = _reader.next_uint();
|
||||||
|
int injected_fields_count = _reader.next_uint();
|
||||||
|
assert( _limit <= java_fields_count + injected_fields_count, "Safety check");
|
||||||
|
if (_limit != 0) {
|
||||||
|
_reader.read_field_info(_fi_buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
public:
|
public:
|
||||||
inline FieldStreamBase(InstanceKlass* klass);
|
inline FieldStreamBase(InstanceKlass* klass);
|
||||||
|
|
||||||
@ -89,27 +74,19 @@ class FieldStreamBase : public StackObj {
|
|||||||
InstanceKlass* field_holder() const { return _constants->pool_holder(); }
|
InstanceKlass* field_holder() const { return _constants->pool_holder(); }
|
||||||
|
|
||||||
void next() {
|
void next() {
|
||||||
if (access_flags().field_has_generic_signature()) {
|
|
||||||
_generic_signature_slot ++;
|
|
||||||
assert(_generic_signature_slot <= _fields->length(), "");
|
|
||||||
}
|
|
||||||
_index += 1;
|
_index += 1;
|
||||||
|
if (done()) return;
|
||||||
|
_reader.read_field_info(_fi_buf);
|
||||||
}
|
}
|
||||||
bool done() const { return _index >= _limit; }
|
bool done() const { return _index >= _limit; }
|
||||||
|
|
||||||
// Accessors for current field
|
// Accessors for current field
|
||||||
AccessFlags access_flags() const {
|
AccessFlags access_flags() const {
|
||||||
AccessFlags flags;
|
return field()->access_flags();
|
||||||
flags.set_flags(field()->access_flags());
|
|
||||||
return flags;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_access_flags(u2 flags) const {
|
FieldInfo::FieldFlags field_flags() const {
|
||||||
field()->set_access_flags(flags);
|
return field()->field_flags();
|
||||||
}
|
|
||||||
|
|
||||||
void set_access_flags(AccessFlags flags) const {
|
|
||||||
set_access_flags(flags.as_short());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Symbol* name() const {
|
Symbol* name() const {
|
||||||
@ -121,10 +98,8 @@ class FieldStreamBase : public StackObj {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Symbol* generic_signature() const {
|
Symbol* generic_signature() const {
|
||||||
if (access_flags().field_has_generic_signature()) {
|
if (field()->field_flags().is_generic()) {
|
||||||
assert(_generic_signature_slot < _fields->length(), "out of bounds");
|
return _constants->symbol_at(field()->generic_signature_index());
|
||||||
int index = _fields->at(_generic_signature_slot);
|
|
||||||
return _constants->symbol_at(index);
|
|
||||||
} else {
|
} else {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@ -134,14 +109,6 @@ class FieldStreamBase : public StackObj {
|
|||||||
return field()->offset();
|
return field()->offset();
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_offset(int offset) {
|
|
||||||
field()->set_offset(offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool is_offset_set() const {
|
|
||||||
return field()->is_offset_set();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool is_contended() const {
|
bool is_contended() const {
|
||||||
return field()->is_contended();
|
return field()->is_contended();
|
||||||
}
|
}
|
||||||
@ -150,6 +117,16 @@ class FieldStreamBase : public StackObj {
|
|||||||
return field()->contended_group();
|
return field()->contended_group();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Convenient methods
|
||||||
|
|
||||||
|
FieldInfo to_FieldInfo() {
|
||||||
|
return _fi_buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
int num_total_fields() const {
|
||||||
|
return FieldInfoStream::num_total_fields(_fieldinfo_stream);
|
||||||
|
}
|
||||||
|
|
||||||
// bridge to a heavier API:
|
// bridge to a heavier API:
|
||||||
fieldDescriptor& field_descriptor() const {
|
fieldDescriptor& field_descriptor() const {
|
||||||
fieldDescriptor& field = const_cast<fieldDescriptor&>(_fd_buf);
|
fieldDescriptor& field = const_cast<fieldDescriptor&>(_fd_buf);
|
||||||
@ -161,47 +138,30 @@ class FieldStreamBase : public StackObj {
|
|||||||
// Iterate over only the internal fields
|
// Iterate over only the internal fields
|
||||||
class JavaFieldStream : public FieldStreamBase {
|
class JavaFieldStream : public FieldStreamBase {
|
||||||
public:
|
public:
|
||||||
JavaFieldStream(const InstanceKlass* k): FieldStreamBase(k->fields(), k->constants(), 0, k->java_fields_count()) {}
|
JavaFieldStream(const InstanceKlass* k): FieldStreamBase(k->fieldinfo_stream(), k->constants(), 0, k->java_fields_count()) {}
|
||||||
|
|
||||||
int name_index() const {
|
int name_index() const {
|
||||||
assert(!field()->is_internal(), "regular only");
|
assert(!field()->field_flags().is_injected(), "regular only");
|
||||||
return field()->name_index();
|
return field()->name_index();
|
||||||
}
|
}
|
||||||
void set_name_index(int index) {
|
|
||||||
assert(!field()->is_internal(), "regular only");
|
|
||||||
field()->set_name_index(index);
|
|
||||||
}
|
|
||||||
int signature_index() const {
|
int signature_index() const {
|
||||||
assert(!field()->is_internal(), "regular only");
|
assert(!field()->field_flags().is_injected(), "regular only");
|
||||||
return field()->signature_index();
|
return field()->signature_index();
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
void set_signature_index(int index) {
|
|
||||||
assert(!field()->is_internal(), "regular only");
|
|
||||||
field()->set_signature_index(index);
|
|
||||||
}
|
|
||||||
int generic_signature_index() const {
|
int generic_signature_index() const {
|
||||||
assert(!field()->is_internal(), "regular only");
|
assert(!field()->field_flags().is_injected(), "regular only");
|
||||||
if (access_flags().field_has_generic_signature()) {
|
if (field()->field_flags().is_generic()) {
|
||||||
assert(_generic_signature_slot < _fields->length(), "out of bounds");
|
return field()->generic_signature_index();
|
||||||
return _fields->at(_generic_signature_slot);
|
}
|
||||||
} else {
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
void set_generic_signature_index(int index) {
|
|
||||||
assert(!field()->is_internal(), "regular only");
|
|
||||||
if (access_flags().field_has_generic_signature()) {
|
|
||||||
assert(_generic_signature_slot < _fields->length(), "out of bounds");
|
|
||||||
_fields->at_put(_generic_signature_slot, index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
int initval_index() const {
|
int initval_index() const {
|
||||||
assert(!field()->is_internal(), "regular only");
|
assert(!field()->field_flags().is_injected(), "regular only");
|
||||||
return field()->initval_index();
|
return field()->initializer_index();
|
||||||
}
|
|
||||||
void set_initval_index(int index) {
|
|
||||||
assert(!field()->is_internal(), "regular only");
|
|
||||||
return field()->set_initval_index(index);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -209,14 +169,14 @@ class JavaFieldStream : public FieldStreamBase {
|
|||||||
// Iterate over only the internal fields
|
// Iterate over only the internal fields
|
||||||
class InternalFieldStream : public FieldStreamBase {
|
class InternalFieldStream : public FieldStreamBase {
|
||||||
public:
|
public:
|
||||||
InternalFieldStream(InstanceKlass* k): FieldStreamBase(k->fields(), k->constants(), k->java_fields_count(), 0) {}
|
InternalFieldStream(InstanceKlass* k): FieldStreamBase(k->fieldinfo_stream(), k->constants(), k->java_fields_count(), 0) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class AllFieldStream : public FieldStreamBase {
|
class AllFieldStream : public FieldStreamBase {
|
||||||
public:
|
public:
|
||||||
AllFieldStream(Array<u2>* fields, ConstantPool* constants): FieldStreamBase(fields, constants) {}
|
AllFieldStream(Array<u1>* fieldinfo, ConstantPool* constants): FieldStreamBase(fieldinfo, constants) {}
|
||||||
AllFieldStream(InstanceKlass* k): FieldStreamBase(k->fields(), k->constants()) {}
|
AllFieldStream(const InstanceKlass* k): FieldStreamBase(k->fieldinfo_stream(), k->constants()) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // SHARE_OOPS_FIELDSTREAMS_HPP
|
#endif // SHARE_OOPS_FIELDSTREAMS_HPP
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2019, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -27,29 +27,39 @@
|
|||||||
|
|
||||||
#include "oops/fieldStreams.hpp"
|
#include "oops/fieldStreams.hpp"
|
||||||
|
|
||||||
|
#include "oops/fieldInfo.hpp"
|
||||||
#include "runtime/javaThread.hpp"
|
#include "runtime/javaThread.hpp"
|
||||||
|
|
||||||
FieldStreamBase::FieldStreamBase(Array<u2>* fields, ConstantPool* constants, int start, int limit) : _fields(fields),
|
FieldStreamBase::FieldStreamBase(const Array<u1>* fieldinfo_stream, ConstantPool* constants, int start, int limit) :
|
||||||
|
_fieldinfo_stream(fieldinfo_stream),
|
||||||
|
_reader(FieldInfoReader(_fieldinfo_stream)),
|
||||||
_constants(constantPoolHandle(Thread::current(), constants)), _index(start) {
|
_constants(constantPoolHandle(Thread::current(), constants)), _index(start) {
|
||||||
_index = start;
|
_index = start;
|
||||||
int num_fields = init_generic_signature_start_slot();
|
|
||||||
if (limit < start) {
|
if (limit < start) {
|
||||||
_limit = num_fields;
|
_limit = FieldInfoStream::num_total_fields(_fieldinfo_stream);
|
||||||
} else {
|
} else {
|
||||||
_limit = limit;
|
_limit = limit;
|
||||||
}
|
}
|
||||||
|
initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
FieldStreamBase::FieldStreamBase(Array<u2>* fields, ConstantPool* constants) : _fields(fields),
|
FieldStreamBase::FieldStreamBase(Array<u1>* fieldinfo_stream, ConstantPool* constants) :
|
||||||
_constants(constantPoolHandle(Thread::current(), constants)), _index(0) {
|
_fieldinfo_stream(fieldinfo_stream),
|
||||||
_limit = init_generic_signature_start_slot();
|
_reader(FieldInfoReader(_fieldinfo_stream)),
|
||||||
|
_constants(constantPoolHandle(Thread::current(), constants)),
|
||||||
|
_index(0),
|
||||||
|
_limit(FieldInfoStream::num_total_fields(_fieldinfo_stream)) {
|
||||||
|
initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
FieldStreamBase::FieldStreamBase(InstanceKlass* klass) : _fields(klass->fields()),
|
FieldStreamBase::FieldStreamBase(InstanceKlass* klass) :
|
||||||
_constants(constantPoolHandle(Thread::current(), klass->constants())), _index(0),
|
_fieldinfo_stream(klass->fieldinfo_stream()),
|
||||||
_limit(klass->java_fields_count()) {
|
_reader(FieldInfoReader(_fieldinfo_stream)),
|
||||||
init_generic_signature_start_slot();
|
_constants(constantPoolHandle(Thread::current(), klass->constants())),
|
||||||
|
_index(0),
|
||||||
|
_limit(FieldInfoStream::num_total_fields(_fieldinfo_stream)) {
|
||||||
assert(klass == field_holder(), "");
|
assert(klass == field_holder(), "");
|
||||||
|
initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // SHARE_OOPS_FIELDSTREAMS_INLINE_HPP
|
#endif // SHARE_OOPS_FIELDSTREAMS_INLINE_HPP
|
||||||
|
@ -647,10 +647,15 @@ void InstanceKlass::deallocate_contents(ClassLoaderData* loader_data) {
|
|||||||
set_transitive_interfaces(nullptr);
|
set_transitive_interfaces(nullptr);
|
||||||
set_local_interfaces(nullptr);
|
set_local_interfaces(nullptr);
|
||||||
|
|
||||||
if (fields() != nullptr && !fields()->is_shared()) {
|
if (fieldinfo_stream() != nullptr && !fieldinfo_stream()->is_shared()) {
|
||||||
MetadataFactory::free_array<jushort>(loader_data, fields());
|
MetadataFactory::free_array<u1>(loader_data, fieldinfo_stream());
|
||||||
}
|
}
|
||||||
set_fields(nullptr, 0);
|
set_fieldinfo_stream(nullptr);
|
||||||
|
|
||||||
|
if (fields_status() != nullptr && !fields_status()->is_shared()) {
|
||||||
|
MetadataFactory::free_array<FieldStatus>(loader_data, fields_status());
|
||||||
|
}
|
||||||
|
set_fields_status(nullptr);
|
||||||
|
|
||||||
// If a method from a redefined class is using this constant pool, don't
|
// If a method from a redefined class is using this constant pool, don't
|
||||||
// delete it, yet. The new class's previous version will point to this.
|
// delete it, yet. The new class's previous version will point to this.
|
||||||
@ -1533,6 +1538,16 @@ bool InstanceKlass::contains_field_offset(int offset) {
|
|||||||
return find_field_from_offset(offset, false, &fd);
|
return find_field_from_offset(offset, false, &fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FieldInfo InstanceKlass::field(int index) const {
|
||||||
|
for (AllFieldStream fs(this); !fs.done(); fs.next()) {
|
||||||
|
if (fs.index() == index) {
|
||||||
|
return fs.to_FieldInfo();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fatal("Field not found");
|
||||||
|
return FieldInfo();
|
||||||
|
}
|
||||||
|
|
||||||
bool InstanceKlass::find_local_field(Symbol* name, Symbol* sig, fieldDescriptor* fd) const {
|
bool InstanceKlass::find_local_field(Symbol* name, Symbol* sig, fieldDescriptor* fd) const {
|
||||||
for (JavaFieldStream fs(this); !fs.done(); fs.next()) {
|
for (JavaFieldStream fs(this); !fs.done(); fs.next()) {
|
||||||
Symbol* f_name = fs.name();
|
Symbol* f_name = fs.name();
|
||||||
@ -2449,8 +2464,9 @@ void InstanceKlass::metaspace_pointers_do(MetaspaceClosure* it) {
|
|||||||
it->push(&_default_vtable_indices);
|
it->push(&_default_vtable_indices);
|
||||||
}
|
}
|
||||||
|
|
||||||
// _fields might be written into by Rewriter::scan_method() -> fd.set_has_initialized_final_update()
|
it->push(&_fieldinfo_stream);
|
||||||
it->push(&_fields, MetaspaceClosure::_writable);
|
// _fields_status might be written into by Rewriter::scan_method() -> fd.set_has_initialized_final_update()
|
||||||
|
it->push(&_fields_status, MetaspaceClosure::_writable);
|
||||||
|
|
||||||
if (itable_length() > 0) {
|
if (itable_length() > 0) {
|
||||||
itableOffsetEntry* ioe = (itableOffsetEntry*)start_of_itable();
|
itableOffsetEntry* ioe = (itableOffsetEntry*)start_of_itable();
|
||||||
|
@ -28,6 +28,7 @@
|
|||||||
#include "memory/referenceType.hpp"
|
#include "memory/referenceType.hpp"
|
||||||
#include "oops/annotations.hpp"
|
#include "oops/annotations.hpp"
|
||||||
#include "oops/constMethod.hpp"
|
#include "oops/constMethod.hpp"
|
||||||
|
#include "oops/constantPool.hpp"
|
||||||
#include "oops/fieldInfo.hpp"
|
#include "oops/fieldInfo.hpp"
|
||||||
#include "oops/instanceKlassFlags.hpp"
|
#include "oops/instanceKlassFlags.hpp"
|
||||||
#include "oops/instanceOop.hpp"
|
#include "oops/instanceOop.hpp"
|
||||||
@ -219,7 +220,6 @@ class InstanceKlass: public Klass {
|
|||||||
u2 _nest_host_index;
|
u2 _nest_host_index;
|
||||||
u2 _this_class_index; // constant pool entry
|
u2 _this_class_index; // constant pool entry
|
||||||
u2 _static_oop_field_count; // number of static oop fields in this klass
|
u2 _static_oop_field_count; // number of static oop fields in this klass
|
||||||
u2 _java_fields_count; // The number of declared Java fields
|
|
||||||
|
|
||||||
volatile u2 _idnum_allocated_count; // JNI/JVMTI: increments with the addition of methods, old ids don't change
|
volatile u2 _idnum_allocated_count; // JNI/JVMTI: increments with the addition of methods, old ids don't change
|
||||||
|
|
||||||
@ -272,20 +272,9 @@ class InstanceKlass: public Klass {
|
|||||||
// offset matches _default_methods offset
|
// offset matches _default_methods offset
|
||||||
Array<int>* _default_vtable_indices;
|
Array<int>* _default_vtable_indices;
|
||||||
|
|
||||||
// Instance and static variable information, starts with 6-tuples of shorts
|
// Fields information is stored in an UNSIGNED5 encoded stream (see fieldInfo.hpp)
|
||||||
// [access, name index, sig index, initval index, low_offset, high_offset]
|
Array<u1>* _fieldinfo_stream;
|
||||||
// for all fields, followed by the generic signature data at the end of
|
Array<FieldStatus>* _fields_status;
|
||||||
// the array. Only fields with generic signature attributes have the generic
|
|
||||||
// signature data set in the array. The fields array looks like following:
|
|
||||||
//
|
|
||||||
// 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]
|
|
||||||
// ...
|
|
||||||
Array<u2>* _fields;
|
|
||||||
|
|
||||||
// embedded Java vtable follows here
|
// embedded Java vtable follows here
|
||||||
// embedded Java itables follows here
|
// embedded Java itables follows here
|
||||||
@ -394,23 +383,25 @@ class InstanceKlass: public Klass {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
friend class fieldDescriptor;
|
friend class fieldDescriptor;
|
||||||
FieldInfo* field(int index) const { return FieldInfo::from_field_array(_fields, index); }
|
FieldInfo field(int index) const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
int field_offset (int index) const { return field(index)->offset(); }
|
int field_offset (int index) const { return field(index).offset(); }
|
||||||
int field_access_flags(int index) const { return field(index)->access_flags(); }
|
int field_access_flags(int index) const { return field(index).access_flags().as_int(); }
|
||||||
Symbol* field_name (int index) const { return field(index)->name(constants()); }
|
FieldInfo::FieldFlags field_flags(int index) const { return field(index).field_flags(); }
|
||||||
Symbol* field_signature (int index) const { return field(index)->signature(constants()); }
|
FieldStatus field_status(int index) const { return fields_status()->at(index); }
|
||||||
|
inline Symbol* field_name (int index) const;
|
||||||
|
inline Symbol* field_signature (int index) const;
|
||||||
|
|
||||||
// Number of Java declared fields
|
// Number of Java declared fields
|
||||||
int java_fields_count() const { return (int)_java_fields_count; }
|
int java_fields_count() const;
|
||||||
|
int total_fields_count() const;
|
||||||
|
|
||||||
Array<u2>* fields() const { return _fields; }
|
Array<u1>* fieldinfo_stream() const { return _fieldinfo_stream; }
|
||||||
void set_fields(Array<u2>* f, u2 java_fields_count) {
|
void set_fieldinfo_stream(Array<u1>* fis) { _fieldinfo_stream = fis; }
|
||||||
guarantee(_fields == nullptr || f == nullptr, "Just checking");
|
|
||||||
_fields = f;
|
Array<FieldStatus>* fields_status() const {return _fields_status; }
|
||||||
_java_fields_count = java_fields_count;
|
void set_fields_status(Array<FieldStatus>* array) { _fields_status = array; }
|
||||||
}
|
|
||||||
|
|
||||||
// inner classes
|
// inner classes
|
||||||
Array<u2>* inner_classes() const { return _inner_classes; }
|
Array<u2>* inner_classes() const { return _inner_classes; }
|
||||||
|
@ -27,7 +27,11 @@
|
|||||||
|
|
||||||
#include "oops/instanceKlass.hpp"
|
#include "oops/instanceKlass.hpp"
|
||||||
|
|
||||||
|
#include "classfile/javaClasses.hpp"
|
||||||
|
#include "classfile/vmSymbols.hpp"
|
||||||
#include "memory/memRegion.hpp"
|
#include "memory/memRegion.hpp"
|
||||||
|
#include "memory/resourceArea.hpp"
|
||||||
|
#include "oops/fieldInfo.inline.hpp"
|
||||||
#include "oops/klass.inline.hpp"
|
#include "oops/klass.inline.hpp"
|
||||||
#include "oops/oop.inline.hpp"
|
#include "oops/oop.inline.hpp"
|
||||||
#include "runtime/atomic.hpp"
|
#include "runtime/atomic.hpp"
|
||||||
@ -41,6 +45,12 @@ inline int InstanceKlass::itable_offset_in_words() const { return start_of_itabl
|
|||||||
|
|
||||||
inline oop InstanceKlass::static_field_base_raw() { return java_mirror(); }
|
inline oop InstanceKlass::static_field_base_raw() { return java_mirror(); }
|
||||||
|
|
||||||
|
inline Symbol* InstanceKlass::field_name(int index) const { return field(index).name(constants()); }
|
||||||
|
inline Symbol* InstanceKlass::field_signature(int index) const { return field(index).signature(constants()); }
|
||||||
|
|
||||||
|
inline int InstanceKlass::java_fields_count() const { return FieldInfoStream::num_java_fields(fieldinfo_stream()); }
|
||||||
|
inline int InstanceKlass::total_fields_count() const { return FieldInfoStream::num_total_fields(fieldinfo_stream()); }
|
||||||
|
|
||||||
inline OopMapBlock* InstanceKlass::start_of_nonstatic_oop_maps() const {
|
inline OopMapBlock* InstanceKlass::start_of_nonstatic_oop_maps() const {
|
||||||
return (OopMapBlock*)(start_of_itable() + itable_length());
|
return (OopMapBlock*)(start_of_itable() + itable_length());
|
||||||
}
|
}
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
#include "interpreter/bytecodeStream.hpp"
|
#include "interpreter/bytecodeStream.hpp"
|
||||||
#include "memory/universe.hpp"
|
#include "memory/universe.hpp"
|
||||||
#include "oops/fieldStreams.inline.hpp"
|
#include "oops/fieldStreams.inline.hpp"
|
||||||
|
#include "oops/instanceKlass.inline.hpp"
|
||||||
#include "oops/recordComponent.hpp"
|
#include "oops/recordComponent.hpp"
|
||||||
#include "prims/jvmtiClassFileReconstituter.hpp"
|
#include "prims/jvmtiClassFileReconstituter.hpp"
|
||||||
#include "runtime/handles.inline.hpp"
|
#include "runtime/handles.inline.hpp"
|
||||||
|
@ -3547,32 +3547,48 @@ void VM_RedefineClasses::set_new_constant_pool(
|
|||||||
int i; // for portability
|
int i; // for portability
|
||||||
|
|
||||||
// update each field in klass to use new constant pool indices as needed
|
// update each field in klass to use new constant pool indices as needed
|
||||||
for (JavaFieldStream fs(scratch_class); !fs.done(); fs.next()) {
|
int java_fields;
|
||||||
jshort cur_index = fs.name_index();
|
int injected_fields;
|
||||||
|
bool update_required = false;
|
||||||
|
GrowableArray<FieldInfo>* fields = FieldInfoStream::create_FieldInfoArray(scratch_class->fieldinfo_stream(), &java_fields, &injected_fields);
|
||||||
|
for (int i = 0; i < java_fields; i++) {
|
||||||
|
FieldInfo* fi = fields->adr_at(i);
|
||||||
|
jshort cur_index = fi->name_index();
|
||||||
jshort new_index = find_new_index(cur_index);
|
jshort new_index = find_new_index(cur_index);
|
||||||
if (new_index != 0) {
|
if (new_index != 0) {
|
||||||
log_trace(redefine, class, constantpool)("field-name_index change: %d to %d", cur_index, new_index);
|
log_trace(redefine, class, constantpool)("field-name_index change: %d to %d", cur_index, new_index);
|
||||||
fs.set_name_index(new_index);
|
fi->set_name_index(new_index);
|
||||||
|
update_required = true;
|
||||||
}
|
}
|
||||||
cur_index = fs.signature_index();
|
cur_index = fi->signature_index();
|
||||||
new_index = find_new_index(cur_index);
|
new_index = find_new_index(cur_index);
|
||||||
if (new_index != 0) {
|
if (new_index != 0) {
|
||||||
log_trace(redefine, class, constantpool)("field-signature_index change: %d to %d", cur_index, new_index);
|
log_trace(redefine, class, constantpool)("field-signature_index change: %d to %d", cur_index, new_index);
|
||||||
fs.set_signature_index(new_index);
|
fi->set_signature_index(new_index);
|
||||||
|
update_required = true;
|
||||||
}
|
}
|
||||||
cur_index = fs.initval_index();
|
cur_index = fi->initializer_index();
|
||||||
new_index = find_new_index(cur_index);
|
new_index = find_new_index(cur_index);
|
||||||
if (new_index != 0) {
|
if (new_index != 0) {
|
||||||
log_trace(redefine, class, constantpool)("field-initval_index change: %d to %d", cur_index, new_index);
|
log_trace(redefine, class, constantpool)("field-initval_index change: %d to %d", cur_index, new_index);
|
||||||
fs.set_initval_index(new_index);
|
fi->set_initializer_index(new_index);
|
||||||
|
update_required = true;
|
||||||
}
|
}
|
||||||
cur_index = fs.generic_signature_index();
|
cur_index = fi->generic_signature_index();
|
||||||
new_index = find_new_index(cur_index);
|
new_index = find_new_index(cur_index);
|
||||||
if (new_index != 0) {
|
if (new_index != 0) {
|
||||||
log_trace(redefine, class, constantpool)("field-generic_signature change: %d to %d", cur_index, new_index);
|
log_trace(redefine, class, constantpool)("field-generic_signature change: %d to %d", cur_index, new_index);
|
||||||
fs.set_generic_signature_index(new_index);
|
fi->set_generic_signature_index(new_index);
|
||||||
|
update_required = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (update_required) {
|
||||||
|
Array<u1>* old_stream = scratch_class->fieldinfo_stream();
|
||||||
|
assert(fields->length() == (java_fields + injected_fields), "Must be");
|
||||||
|
Array<u1>* new_fis = FieldInfoStream::create_FieldInfoStream(fields, java_fields, injected_fields, scratch_class->class_loader_data(), CHECK);
|
||||||
|
scratch_class->set_fieldinfo_stream(new_fis);
|
||||||
|
MetadataFactory::free_array<u1>(scratch_class->class_loader_data(), old_stream);
|
||||||
}
|
}
|
||||||
} // end for each field
|
|
||||||
|
|
||||||
// Update constant pool indices in the inner classes info to use
|
// Update constant pool indices in the inner classes info to use
|
||||||
// new constant indices as needed. The inner classes info is a
|
// new constant indices as needed. The inner classes info is a
|
||||||
|
@ -1437,7 +1437,7 @@ static int reassign_fields_by_klass(InstanceKlass* klass, frame* fr, RegisterMap
|
|||||||
InstanceKlass* ik = klass;
|
InstanceKlass* ik = klass;
|
||||||
while (ik != nullptr) {
|
while (ik != nullptr) {
|
||||||
for (AllFieldStream fs(ik); !fs.done(); fs.next()) {
|
for (AllFieldStream fs(ik); !fs.done(); fs.next()) {
|
||||||
if (!fs.access_flags().is_static() && (!skip_internal || !fs.access_flags().is_internal())) {
|
if (!fs.access_flags().is_static() && (!skip_internal || !fs.field_flags().is_injected())) {
|
||||||
ReassignedField field;
|
ReassignedField field;
|
||||||
field._offset = fs.offset();
|
field._offset = fs.offset();
|
||||||
field._type = Signature::basic_type(fs.signature());
|
field._type = Signature::basic_type(fs.signature());
|
||||||
|
@ -39,18 +39,7 @@ Symbol* fieldDescriptor::generic_signature() const {
|
|||||||
if (!has_generic_signature()) {
|
if (!has_generic_signature()) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
return _cp->symbol_at(_fieldinfo.generic_signature_index());
|
||||||
int idx = 0;
|
|
||||||
InstanceKlass* ik = field_holder();
|
|
||||||
for (AllFieldStream fs(ik); !fs.done(); fs.next()) {
|
|
||||||
if (idx == _index) {
|
|
||||||
return fs.generic_signature();
|
|
||||||
} else {
|
|
||||||
idx ++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
assert(false, "should never happen");
|
|
||||||
return vmSymbols::void_signature(); // return a default value (for code analyzers)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool fieldDescriptor::is_trusted_final() const {
|
bool fieldDescriptor::is_trusted_final() const {
|
||||||
@ -106,30 +95,14 @@ void fieldDescriptor::reinitialize(InstanceKlass* ik, int index) {
|
|||||||
// but that's ok because of constant pool merging.
|
// but that's ok because of constant pool merging.
|
||||||
assert(field_holder() == ik || ik->is_scratch_class(), "must be already initialized to this class");
|
assert(field_holder() == ik || ik->is_scratch_class(), "must be already initialized to this class");
|
||||||
}
|
}
|
||||||
FieldInfo* f = ik->field(index);
|
_fieldinfo= ik->field(index);
|
||||||
_access_flags = accessFlags_from(f->access_flags());
|
assert((int)_fieldinfo.index() == index, "just checking");
|
||||||
guarantee(f->name_index() != 0 && f->signature_index() != 0, "bad constant pool index for fieldDescriptor");
|
guarantee(_fieldinfo.name_index() != 0 && _fieldinfo.signature_index() != 0, "bad constant pool index for fieldDescriptor");
|
||||||
_index = index;
|
|
||||||
verify();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef PRODUCT
|
|
||||||
|
|
||||||
void fieldDescriptor::verify() const {
|
|
||||||
if (_cp.is_null()) {
|
|
||||||
assert(_index == badInt, "constructor must be called"); // see constructor
|
|
||||||
} else {
|
|
||||||
assert(_index >= 0, "good index");
|
|
||||||
assert(access_flags().is_internal() ||
|
|
||||||
_index < field_holder()->java_fields_count(), "oob");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* PRODUCT */
|
|
||||||
|
|
||||||
void fieldDescriptor::print_on(outputStream* st) const {
|
void fieldDescriptor::print_on(outputStream* st) const {
|
||||||
access_flags().print_on(st);
|
access_flags().print_on(st);
|
||||||
if (access_flags().is_internal()) st->print("internal ");
|
if (field_flags().is_injected()) st->print("injected ");
|
||||||
name()->print_value_on(st);
|
name()->print_value_on(st);
|
||||||
st->print(" ");
|
st->print(" ");
|
||||||
signature()->print_value_on(st);
|
signature()->print_value_on(st);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -38,33 +38,29 @@
|
|||||||
|
|
||||||
class fieldDescriptor {
|
class fieldDescriptor {
|
||||||
private:
|
private:
|
||||||
AccessFlags _access_flags;
|
FieldInfo _fieldinfo;
|
||||||
int _index; // the field index
|
|
||||||
constantPoolHandle _cp;
|
constantPoolHandle _cp;
|
||||||
|
|
||||||
// update the access_flags for the field in the klass
|
inline FieldInfo field() const { return _fieldinfo; };
|
||||||
inline void update_klass_field_access_flag();
|
|
||||||
|
|
||||||
inline FieldInfo* field() const;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
fieldDescriptor() {
|
fieldDescriptor() {}
|
||||||
DEBUG_ONLY(_index = badInt);
|
|
||||||
}
|
|
||||||
fieldDescriptor(InstanceKlass* ik, int index) {
|
fieldDescriptor(InstanceKlass* ik, int index) {
|
||||||
DEBUG_ONLY(_index = badInt);
|
|
||||||
reinitialize(ik, index);
|
reinitialize(ik, index);
|
||||||
}
|
}
|
||||||
inline Symbol* name() const;
|
inline Symbol* name() const;
|
||||||
inline Symbol* signature() const;
|
inline Symbol* signature() const;
|
||||||
inline InstanceKlass* field_holder() const;
|
inline InstanceKlass* field_holder() const {return _cp->pool_holder(); };
|
||||||
inline ConstantPool* constants() const;
|
inline ConstantPool* constants() const;
|
||||||
|
|
||||||
AccessFlags access_flags() const { return _access_flags; }
|
AccessFlags access_flags() const { return _fieldinfo.access_flags(); }
|
||||||
|
FieldInfo::FieldFlags field_flags() const { return _fieldinfo.field_flags(); }
|
||||||
|
FieldStatus field_status() const { return field_holder()->fields_status()->at(_fieldinfo.index()); }
|
||||||
|
oop loader() const;
|
||||||
// Offset (in bytes) of field from start of instanceOop / Klass*
|
// Offset (in bytes) of field from start of instanceOop / Klass*
|
||||||
inline int offset() const;
|
inline int offset() const;
|
||||||
Symbol* generic_signature() const;
|
Symbol* generic_signature() const;
|
||||||
int index() const { return _index; }
|
int index() const { return _fieldinfo.index(); }
|
||||||
AnnotationArray* annotations() const;
|
AnnotationArray* annotations() const;
|
||||||
AnnotationArray* type_annotations() const;
|
AnnotationArray* type_annotations() const;
|
||||||
|
|
||||||
@ -87,15 +83,17 @@ class fieldDescriptor {
|
|||||||
|
|
||||||
bool is_static() const { return access_flags().is_static(); }
|
bool is_static() const { return access_flags().is_static(); }
|
||||||
bool is_final() const { return access_flags().is_final(); }
|
bool is_final() const { return access_flags().is_final(); }
|
||||||
bool is_stable() const { return access_flags().is_stable(); }
|
bool is_stable() const { return field_flags().is_stable(); }
|
||||||
|
bool is_volatile() const { return access_flags().is_volatile(); }
|
||||||
|
bool is_transient() const { return access_flags().is_transient(); }
|
||||||
|
|
||||||
bool is_synthetic() const { return access_flags().is_synthetic(); }
|
bool is_synthetic() const { return access_flags().is_synthetic(); }
|
||||||
|
|
||||||
bool is_field_access_watched() const { return access_flags().is_field_access_watched(); }
|
bool is_field_access_watched() const { return field_status().is_access_watched(); }
|
||||||
bool is_field_modification_watched() const
|
bool is_field_modification_watched() const
|
||||||
{ return access_flags().is_field_modification_watched(); }
|
{ return field_status().is_modification_watched(); }
|
||||||
bool has_initialized_final_update() const { return access_flags().has_field_initialized_final_update(); }
|
bool has_initialized_final_update() const { return field_status().is_initialized_final_update(); }
|
||||||
bool has_generic_signature() const { return access_flags().field_has_generic_signature(); }
|
bool has_generic_signature() const { return field_flags().is_generic(); }
|
||||||
|
|
||||||
bool is_trusted_final() const;
|
bool is_trusted_final() const;
|
||||||
|
|
||||||
@ -110,7 +108,6 @@ class fieldDescriptor {
|
|||||||
void print() const;
|
void print() const;
|
||||||
void print_on(outputStream* st) const;
|
void print_on(outputStream* st) const;
|
||||||
void print_on_for(outputStream* st, oop obj);
|
void print_on_for(outputStream* st, oop obj);
|
||||||
void verify() const PRODUCT_RETURN;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // SHARE_RUNTIME_FIELDDESCRIPTOR_HPP
|
#endif // SHARE_RUNTIME_FIELDDESCRIPTOR_HPP
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2018, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -27,6 +27,7 @@
|
|||||||
|
|
||||||
#include "runtime/fieldDescriptor.hpp"
|
#include "runtime/fieldDescriptor.hpp"
|
||||||
|
|
||||||
|
#include "oops/fieldInfo.inline.hpp"
|
||||||
#include "runtime/handles.inline.hpp"
|
#include "runtime/handles.inline.hpp"
|
||||||
#include "runtime/signature.hpp"
|
#include "runtime/signature.hpp"
|
||||||
|
|
||||||
@ -34,48 +35,31 @@
|
|||||||
// must be put in this file, as they require runtime/handles.inline.hpp.
|
// must be put in this file, as they require runtime/handles.inline.hpp.
|
||||||
|
|
||||||
inline Symbol* fieldDescriptor::name() const {
|
inline Symbol* fieldDescriptor::name() const {
|
||||||
return field()->name(_cp());
|
return field().name(_cp());
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Symbol* fieldDescriptor::signature() const {
|
inline Symbol* fieldDescriptor::signature() const {
|
||||||
return field()->signature(_cp());
|
return field().signature(_cp());
|
||||||
}
|
|
||||||
|
|
||||||
inline InstanceKlass* fieldDescriptor::field_holder() const {
|
|
||||||
return _cp->pool_holder();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline ConstantPool* fieldDescriptor::constants() const {
|
inline ConstantPool* fieldDescriptor::constants() const {
|
||||||
return _cp();
|
return _cp();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline FieldInfo* fieldDescriptor::field() const {
|
inline int fieldDescriptor::offset() const { return field().offset(); }
|
||||||
InstanceKlass* ik = field_holder();
|
inline bool fieldDescriptor::has_initial_value() const { return field().field_flags().is_initialized(); }
|
||||||
return ik->field(_index);
|
inline int fieldDescriptor::initial_value_index() const { return field().initializer_index(); }
|
||||||
}
|
|
||||||
|
|
||||||
inline int fieldDescriptor::offset() const { return field()->offset(); }
|
|
||||||
inline bool fieldDescriptor::has_initial_value() const { return field()->initval_index() != 0; }
|
|
||||||
inline int fieldDescriptor::initial_value_index() const { return field()->initval_index(); }
|
|
||||||
|
|
||||||
inline void fieldDescriptor::update_klass_field_access_flag() {
|
|
||||||
InstanceKlass* ik = field_holder();
|
|
||||||
ik->field(index())->set_access_flags(_access_flags.as_short());
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void fieldDescriptor::set_is_field_access_watched(const bool value) {
|
inline void fieldDescriptor::set_is_field_access_watched(const bool value) {
|
||||||
_access_flags.set_is_field_access_watched(value);
|
field_holder()->fields_status()->adr_at(index())->update_access_watched(value);
|
||||||
update_klass_field_access_flag();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void fieldDescriptor::set_is_field_modification_watched(const bool value) {
|
inline void fieldDescriptor::set_is_field_modification_watched(const bool value) {
|
||||||
_access_flags.set_is_field_modification_watched(value);
|
field_holder()->fields_status()->adr_at(index())->update_modification_watched(value);
|
||||||
update_klass_field_access_flag();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void fieldDescriptor::set_has_initialized_final_update(const bool value) {
|
inline void fieldDescriptor::set_has_initialized_final_update(const bool value) {
|
||||||
_access_flags.set_has_field_initialized_final_update(value);
|
field_holder()->fields_status()->adr_at(index())->update_initialized_final_update(value);
|
||||||
update_klass_field_access_flag();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline BasicType fieldDescriptor::field_type() const {
|
inline BasicType fieldDescriptor::field_type() const {
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
#include "classfile/javaClasses.hpp"
|
#include "classfile/javaClasses.hpp"
|
||||||
#include "classfile/vmClasses.hpp"
|
#include "classfile/vmClasses.hpp"
|
||||||
#include "memory/universe.hpp"
|
#include "memory/universe.hpp"
|
||||||
|
#include "oops/instanceKlass.inline.hpp"
|
||||||
#include "runtime/reflectionUtils.hpp"
|
#include "runtime/reflectionUtils.hpp"
|
||||||
|
|
||||||
KlassStream::KlassStream(InstanceKlass* klass, bool local_only,
|
KlassStream::KlassStream(InstanceKlass* klass, bool local_only,
|
||||||
@ -68,6 +69,7 @@ bool KlassStream::eos() {
|
|||||||
return eos();
|
return eos();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int FieldStream::length() { return _klass->java_fields_count(); }
|
||||||
|
|
||||||
GrowableArray<FilteredField*> *FilteredFieldsMap::_filtered_fields =
|
GrowableArray<FilteredField*> *FilteredFieldsMap::_filtered_fields =
|
||||||
new (mtServiceability) GrowableArray<FilteredField*>(3, mtServiceability);
|
new (mtServiceability) GrowableArray<FilteredField*>(3, mtServiceability);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 1999, 2022, 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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -120,7 +120,7 @@ class MethodStream : public KlassStream {
|
|||||||
|
|
||||||
class FieldStream : public KlassStream {
|
class FieldStream : public KlassStream {
|
||||||
private:
|
private:
|
||||||
int length() { return _klass->java_fields_count(); }
|
int length();
|
||||||
|
|
||||||
fieldDescriptor _fd_buf;
|
fieldDescriptor _fd_buf;
|
||||||
|
|
||||||
|
@ -66,6 +66,7 @@
|
|||||||
#include "oops/constMethod.hpp"
|
#include "oops/constMethod.hpp"
|
||||||
#include "oops/constantPool.hpp"
|
#include "oops/constantPool.hpp"
|
||||||
#include "oops/cpCache.hpp"
|
#include "oops/cpCache.hpp"
|
||||||
|
#include "oops/fieldInfo.hpp"
|
||||||
#include "oops/instanceClassLoaderKlass.hpp"
|
#include "oops/instanceClassLoaderKlass.hpp"
|
||||||
#include "oops/instanceKlass.hpp"
|
#include "oops/instanceKlass.hpp"
|
||||||
#include "oops/instanceMirrorKlass.hpp"
|
#include "oops/instanceMirrorKlass.hpp"
|
||||||
@ -225,8 +226,7 @@
|
|||||||
nonstatic_field(InstanceKlass, _default_methods, Array<Method*>*) \
|
nonstatic_field(InstanceKlass, _default_methods, Array<Method*>*) \
|
||||||
nonstatic_field(InstanceKlass, _local_interfaces, Array<InstanceKlass*>*) \
|
nonstatic_field(InstanceKlass, _local_interfaces, Array<InstanceKlass*>*) \
|
||||||
nonstatic_field(InstanceKlass, _transitive_interfaces, Array<InstanceKlass*>*) \
|
nonstatic_field(InstanceKlass, _transitive_interfaces, Array<InstanceKlass*>*) \
|
||||||
nonstatic_field(InstanceKlass, _fields, Array<u2>*) \
|
nonstatic_field(InstanceKlass, _fieldinfo_stream, Array<u1>*) \
|
||||||
nonstatic_field(InstanceKlass, _java_fields_count, u2) \
|
|
||||||
nonstatic_field(InstanceKlass, _constants, ConstantPool*) \
|
nonstatic_field(InstanceKlass, _constants, ConstantPool*) \
|
||||||
nonstatic_field(InstanceKlass, _source_debug_extension, const char*) \
|
nonstatic_field(InstanceKlass, _source_debug_extension, const char*) \
|
||||||
nonstatic_field(InstanceKlass, _inner_classes, Array<jushort>*) \
|
nonstatic_field(InstanceKlass, _inner_classes, Array<jushort>*) \
|
||||||
@ -2092,11 +2092,6 @@
|
|||||||
declare_constant(JVM_ACC_HAS_FINALIZER) \
|
declare_constant(JVM_ACC_HAS_FINALIZER) \
|
||||||
declare_constant(JVM_ACC_IS_CLONEABLE_FAST) \
|
declare_constant(JVM_ACC_IS_CLONEABLE_FAST) \
|
||||||
declare_constant(JVM_ACC_HAS_LOCAL_VARIABLE_TABLE) \
|
declare_constant(JVM_ACC_HAS_LOCAL_VARIABLE_TABLE) \
|
||||||
declare_constant(JVM_ACC_FIELD_ACCESS_WATCHED) \
|
|
||||||
declare_constant(JVM_ACC_FIELD_MODIFICATION_WATCHED) \
|
|
||||||
declare_constant(JVM_ACC_FIELD_INTERNAL) \
|
|
||||||
declare_constant(JVM_ACC_FIELD_STABLE) \
|
|
||||||
declare_constant(JVM_ACC_FIELD_HAS_GENERIC_SIGNATURE) \
|
|
||||||
\
|
\
|
||||||
declare_constant(JVM_CONSTANT_Utf8) \
|
declare_constant(JVM_CONSTANT_Utf8) \
|
||||||
declare_constant(JVM_CONSTANT_Unicode) \
|
declare_constant(JVM_CONSTANT_Unicode) \
|
||||||
@ -2228,24 +2223,6 @@
|
|||||||
/*************************************/ \
|
/*************************************/ \
|
||||||
\
|
\
|
||||||
\
|
\
|
||||||
/*************************************/ \
|
|
||||||
/* FieldInfo FieldOffset enum */ \
|
|
||||||
/*************************************/ \
|
|
||||||
\
|
|
||||||
declare_constant(FieldInfo::access_flags_offset) \
|
|
||||||
declare_constant(FieldInfo::name_index_offset) \
|
|
||||||
declare_constant(FieldInfo::signature_index_offset) \
|
|
||||||
declare_constant(FieldInfo::initval_index_offset) \
|
|
||||||
declare_constant(FieldInfo::low_packed_offset) \
|
|
||||||
declare_constant(FieldInfo::high_packed_offset) \
|
|
||||||
declare_constant(FieldInfo::field_slots) \
|
|
||||||
\
|
|
||||||
/*************************************/ \
|
|
||||||
/* FieldInfo tag constants */ \
|
|
||||||
/*************************************/ \
|
|
||||||
\
|
|
||||||
declare_preprocessor_constant("FIELDINFO_TAG_SIZE", FIELDINFO_TAG_SIZE) \
|
|
||||||
declare_preprocessor_constant("FIELDINFO_TAG_OFFSET", FIELDINFO_TAG_OFFSET) \
|
|
||||||
\
|
\
|
||||||
/************************************************/ \
|
/************************************************/ \
|
||||||
/* InstanceKlass InnerClassAttributeOffset enum */ \
|
/* InstanceKlass InnerClassAttributeOffset enum */ \
|
||||||
@ -2315,6 +2292,17 @@
|
|||||||
declare_constant(JavaThreadStatus::BLOCKED_ON_MONITOR_ENTER) \
|
declare_constant(JavaThreadStatus::BLOCKED_ON_MONITOR_ENTER) \
|
||||||
declare_constant(JavaThreadStatus::TERMINATED) \
|
declare_constant(JavaThreadStatus::TERMINATED) \
|
||||||
\
|
\
|
||||||
|
\
|
||||||
|
/******************************/ \
|
||||||
|
/* FieldFlags enum */ \
|
||||||
|
/******************************/ \
|
||||||
|
\
|
||||||
|
declare_constant(FieldInfo::FieldFlags::_ff_initialized) \
|
||||||
|
declare_constant(FieldInfo::FieldFlags::_ff_injected) \
|
||||||
|
declare_constant(FieldInfo::FieldFlags::_ff_generic) \
|
||||||
|
declare_constant(FieldInfo::FieldFlags::_ff_stable) \
|
||||||
|
declare_constant(FieldInfo::FieldFlags::_ff_contended) \
|
||||||
|
\
|
||||||
/******************************/ \
|
/******************************/ \
|
||||||
/* Debug info */ \
|
/* Debug info */ \
|
||||||
/******************************/ \
|
/******************************/ \
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -74,30 +74,6 @@ enum {
|
|||||||
|
|
||||||
// Method* flags
|
// Method* flags
|
||||||
JVM_ACC_HAS_LOCAL_VARIABLE_TABLE= 0x00400000,
|
JVM_ACC_HAS_LOCAL_VARIABLE_TABLE= 0x00400000,
|
||||||
|
|
||||||
// field flags
|
|
||||||
// Note: these flags must be defined in the low order 16 bits because
|
|
||||||
// InstanceKlass only stores a ushort worth of information from the
|
|
||||||
// AccessFlags value.
|
|
||||||
// These bits must not conflict with any other field-related access flags
|
|
||||||
// (e.g., ACC_ENUM).
|
|
||||||
// Note that the class-related ACC_ANNOTATION bit conflicts with these flags.
|
|
||||||
JVM_ACC_FIELD_ACCESS_WATCHED = 0x00002000, // field access is watched by JVMTI
|
|
||||||
JVM_ACC_FIELD_MODIFICATION_WATCHED = 0x00008000, // field modification is watched by JVMTI
|
|
||||||
JVM_ACC_FIELD_INTERNAL = 0x00000400, // internal field, same as JVM_ACC_ABSTRACT
|
|
||||||
JVM_ACC_FIELD_STABLE = 0x00000020, // @Stable field, same as JVM_ACC_SYNCHRONIZED and JVM_ACC_SUPER
|
|
||||||
JVM_ACC_FIELD_INITIALIZED_FINAL_UPDATE = 0x00000100, // (static) final field updated outside (class) initializer, same as JVM_ACC_NATIVE
|
|
||||||
JVM_ACC_FIELD_HAS_GENERIC_SIGNATURE = 0x00000800, // field has generic signature
|
|
||||||
|
|
||||||
JVM_ACC_FIELD_INTERNAL_FLAGS = JVM_ACC_FIELD_ACCESS_WATCHED |
|
|
||||||
JVM_ACC_FIELD_MODIFICATION_WATCHED |
|
|
||||||
JVM_ACC_FIELD_INTERNAL |
|
|
||||||
JVM_ACC_FIELD_STABLE |
|
|
||||||
JVM_ACC_FIELD_HAS_GENERIC_SIGNATURE,
|
|
||||||
|
|
||||||
// flags accepted by set_field_flags()
|
|
||||||
JVM_ACC_FIELD_FLAGS = JVM_RECOGNIZED_FIELD_MODIFIERS | JVM_ACC_FIELD_INTERNAL_FLAGS
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -166,25 +142,15 @@ class AccessFlags {
|
|||||||
bool has_resolved_methods() const { return (_flags & JVM_ACC_HAS_RESOLVED_METHODS) != 0; }
|
bool has_resolved_methods() const { return (_flags & JVM_ACC_HAS_RESOLVED_METHODS) != 0; }
|
||||||
void set_has_resolved_methods() { atomic_set_bits(JVM_ACC_HAS_RESOLVED_METHODS); }
|
void set_has_resolved_methods() { atomic_set_bits(JVM_ACC_HAS_RESOLVED_METHODS); }
|
||||||
|
|
||||||
// field flags
|
|
||||||
bool is_field_access_watched() const { return (_flags & JVM_ACC_FIELD_ACCESS_WATCHED) != 0; }
|
|
||||||
bool is_field_modification_watched() const
|
|
||||||
{ return (_flags & JVM_ACC_FIELD_MODIFICATION_WATCHED) != 0; }
|
|
||||||
bool has_field_initialized_final_update() const
|
|
||||||
{ return (_flags & JVM_ACC_FIELD_INITIALIZED_FINAL_UPDATE) != 0; }
|
|
||||||
bool on_stack() const { return (_flags & JVM_ACC_ON_STACK) != 0; }
|
bool on_stack() const { return (_flags & JVM_ACC_ON_STACK) != 0; }
|
||||||
bool is_internal() const { return (_flags & JVM_ACC_FIELD_INTERNAL) != 0; }
|
|
||||||
bool is_stable() const { return (_flags & JVM_ACC_FIELD_STABLE) != 0; }
|
|
||||||
bool field_has_generic_signature() const
|
|
||||||
{ return (_flags & JVM_ACC_FIELD_HAS_GENERIC_SIGNATURE) != 0; }
|
|
||||||
|
|
||||||
// get .class file flags
|
// get .class file flags
|
||||||
jint get_flags () const { return (_flags & JVM_ACC_WRITTEN_FLAGS); }
|
jint get_flags () const { return (_flags & JVM_ACC_WRITTEN_FLAGS); }
|
||||||
|
|
||||||
// Initialization
|
// Initialization
|
||||||
void set_field_flags(jint flags) {
|
void set_field_flags(jint flags) {
|
||||||
assert((flags & JVM_ACC_FIELD_FLAGS) == flags, "only recognized flags");
|
assert((flags & JVM_RECOGNIZED_FIELD_MODIFIERS) == flags, "only recognized flags");
|
||||||
_flags = (flags & JVM_ACC_FIELD_FLAGS);
|
_flags = (flags & JVM_RECOGNIZED_FIELD_MODIFIERS);
|
||||||
}
|
}
|
||||||
void set_flags(jint flags) { _flags = (flags & JVM_ACC_WRITTEN_FLAGS); }
|
void set_flags(jint flags) { _flags = (flags & JVM_ACC_WRITTEN_FLAGS); }
|
||||||
|
|
||||||
@ -235,37 +201,6 @@ class AccessFlags {
|
|||||||
void set_is_value_based_class() { atomic_set_bits(JVM_ACC_IS_VALUE_BASED_CLASS); }
|
void set_is_value_based_class() { atomic_set_bits(JVM_ACC_IS_VALUE_BASED_CLASS); }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// field flags
|
|
||||||
void set_is_field_access_watched(const bool value)
|
|
||||||
{
|
|
||||||
if (value) {
|
|
||||||
atomic_set_bits(JVM_ACC_FIELD_ACCESS_WATCHED);
|
|
||||||
} else {
|
|
||||||
atomic_clear_bits(JVM_ACC_FIELD_ACCESS_WATCHED);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
void set_is_field_modification_watched(const bool value)
|
|
||||||
{
|
|
||||||
if (value) {
|
|
||||||
atomic_set_bits(JVM_ACC_FIELD_MODIFICATION_WATCHED);
|
|
||||||
} else {
|
|
||||||
atomic_clear_bits(JVM_ACC_FIELD_MODIFICATION_WATCHED);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_has_field_initialized_final_update(const bool value) {
|
|
||||||
if (value) {
|
|
||||||
atomic_set_bits(JVM_ACC_FIELD_INITIALIZED_FINAL_UPDATE);
|
|
||||||
} else {
|
|
||||||
atomic_clear_bits(JVM_ACC_FIELD_INITIALIZED_FINAL_UPDATE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_field_has_generic_signature()
|
|
||||||
{
|
|
||||||
atomic_set_bits(JVM_ACC_FIELD_HAS_GENERIC_SIGNATURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_on_stack(const bool value)
|
void set_on_stack(const bool value)
|
||||||
{
|
{
|
||||||
if (value) {
|
if (value) {
|
||||||
|
@ -258,8 +258,8 @@ class UNSIGNED5 : AllStatic {
|
|||||||
// MyReader r(array); while (r.has_next()) print(r.next_uint());
|
// MyReader r(array); while (r.has_next()) print(r.next_uint());
|
||||||
template<typename ARR, typename OFF, typename GET = ArrayGetSet<ARR,OFF>>
|
template<typename ARR, typename OFF, typename GET = ArrayGetSet<ARR,OFF>>
|
||||||
class Reader {
|
class Reader {
|
||||||
const ARR _array;
|
ARR _array;
|
||||||
const OFF _limit;
|
OFF _limit;
|
||||||
OFF _position;
|
OFF _position;
|
||||||
int next_length() {
|
int next_length() {
|
||||||
return UNSIGNED5::check_length(_array, _position, _limit, GET());
|
return UNSIGNED5::check_length(_array, _position, _limit, GET());
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2000, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -78,11 +78,6 @@ public class AccessFlags implements /* imports */ ClassConstants {
|
|||||||
// Klass* and Method* flags
|
// Klass* and Method* flags
|
||||||
public boolean hasLocalVariableTable() { return (flags & JVM_ACC_HAS_LOCAL_VARIABLE_TABLE ) != 0; }
|
public boolean hasLocalVariableTable() { return (flags & JVM_ACC_HAS_LOCAL_VARIABLE_TABLE ) != 0; }
|
||||||
|
|
||||||
// field flags
|
|
||||||
public boolean fieldAccessWatched () { return (flags & JVM_ACC_FIELD_ACCESS_WATCHED) != 0; }
|
|
||||||
public boolean fieldModificationWatched() { return (flags & JVM_ACC_FIELD_MODIFICATION_WATCHED) != 0; }
|
|
||||||
public boolean fieldHasGenericSignature() { return (flags & JVM_ACC_FIELD_HAS_GENERIC_SIGNATURE)!= 0; }
|
|
||||||
|
|
||||||
public void printOn(PrintStream tty) {
|
public void printOn(PrintStream tty) {
|
||||||
// prints only .class flags and not the hotspot internal flags
|
// prints only .class flags and not the hotspot internal flags
|
||||||
if (isPublic ()) tty.print("public " );
|
if (isPublic ()) tty.print("public " );
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2000, 2022, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2000, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -26,6 +26,7 @@ package sun.jvm.hotspot.oops;
|
|||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
|
|
||||||
|
import sun.jvm.hotspot.code.CompressedReadStream;
|
||||||
import sun.jvm.hotspot.runtime.*;
|
import sun.jvm.hotspot.runtime.*;
|
||||||
import sun.jvm.hotspot.utilities.*;
|
import sun.jvm.hotspot.utilities.*;
|
||||||
|
|
||||||
@ -40,23 +41,85 @@ public class Field {
|
|||||||
|
|
||||||
/** Constructor for fields that are named in an InstanceKlass's
|
/** Constructor for fields that are named in an InstanceKlass's
|
||||||
fields array (i.e., named, non-VM fields) */
|
fields array (i.e., named, non-VM fields) */
|
||||||
Field(InstanceKlass holder, int fieldIndex) {
|
private Field(InstanceKlass holder, int fieldIndex, FieldInfoValues values) {
|
||||||
this.holder = holder;
|
this.holder = holder;
|
||||||
this.fieldIndex = fieldIndex;
|
this.fieldIndex = fieldIndex;
|
||||||
|
this.values = values;
|
||||||
|
offset = values.offset;
|
||||||
|
|
||||||
offset = holder.getFieldOffset(fieldIndex);
|
name = holder.getSymbolFromIndex(values.nameIndex, isInjected());
|
||||||
genericSignature = holder.getFieldGenericSignature(fieldIndex);
|
signature = holder.getSymbolFromIndex(values.signatureIndex, isInjected());
|
||||||
|
|
||||||
name = holder.getFieldName(fieldIndex);
|
|
||||||
id = new NamedFieldIdentifier(name.asString());
|
id = new NamedFieldIdentifier(name.asString());
|
||||||
|
|
||||||
signature = holder.getFieldSignature(fieldIndex);
|
|
||||||
fieldType = new FieldType(signature);
|
fieldType = new FieldType(signature);
|
||||||
|
accessFlags = new AccessFlags(values.accessFlags);
|
||||||
|
|
||||||
short access = holder.getFieldAccessFlags(fieldIndex);
|
if (isGeneric()) {
|
||||||
accessFlags = new AccessFlags(access);
|
genericSignature = holder.getSymbolFromIndex(values.genericSignatureIndex, isInjected());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Constructor for cloning an existing Field object */
|
||||||
|
Field(InstanceKlass holder, int fieldIndex) {
|
||||||
|
this(holder, fieldIndex, holder.getField(fieldIndex).values);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static class FieldInfoValues {
|
||||||
|
int nameIndex;
|
||||||
|
int signatureIndex;
|
||||||
|
int offset;
|
||||||
|
int accessFlags;
|
||||||
|
int fieldFlags;
|
||||||
|
int initialValueIndex;
|
||||||
|
int genericSignatureIndex;
|
||||||
|
int contendedGroup;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The format of the stream, after decompression, is a series of
|
||||||
|
// integers organized like this:
|
||||||
|
//
|
||||||
|
// FieldInfoStream := j=num_java_fields k=num_injected_fields Field[j+k] End
|
||||||
|
// Field := name sig offset access flags Optionals(flags)
|
||||||
|
// Optionals(i) := initval?[i&is_init] // ConstantValue attr
|
||||||
|
// gsig?[i&is_generic] // signature attr
|
||||||
|
// group?[i&is_contended] // Contended anno (group)
|
||||||
|
// End = 0
|
||||||
|
//
|
||||||
|
|
||||||
|
static FieldInfoValues readFieldInfoValues(CompressedReadStream crs) {
|
||||||
|
FieldInfoValues fieldInfoValues = new FieldInfoValues();
|
||||||
|
fieldInfoValues.nameIndex = crs.readInt(); // read name_index
|
||||||
|
fieldInfoValues.signatureIndex = crs.readInt(); // read signature index
|
||||||
|
fieldInfoValues.offset = crs.readInt(); // read offset
|
||||||
|
fieldInfoValues.accessFlags = crs.readInt(); // read access flags
|
||||||
|
fieldInfoValues.fieldFlags = crs.readInt(); // read field flags
|
||||||
|
// Optional reads:
|
||||||
|
if (fieldIsInitialized(fieldInfoValues.fieldFlags)) {
|
||||||
|
fieldInfoValues.initialValueIndex = crs.readInt(); // read initial value index
|
||||||
|
}
|
||||||
|
if (fieldIsGeneric(fieldInfoValues.fieldFlags)) {
|
||||||
|
fieldInfoValues.genericSignatureIndex = crs.readInt(); // read generic signature index
|
||||||
|
}
|
||||||
|
if (fieldIsContended(fieldInfoValues.fieldFlags)) {
|
||||||
|
fieldInfoValues.contendedGroup = crs.readInt(); // read contended group
|
||||||
|
}
|
||||||
|
return fieldInfoValues;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Field[] getFields(InstanceKlass kls) {
|
||||||
|
CompressedReadStream crs = new CompressedReadStream(kls.getFieldInfoStream().getDataStart());
|
||||||
|
int numJavaFields = crs.readInt(); // read num_java_fields
|
||||||
|
int numInjectedFields = crs.readInt(); // read num_injected_fields;
|
||||||
|
int numFields = numJavaFields + numInjectedFields;
|
||||||
|
Field[] fields = new Field[numFields];
|
||||||
|
for (int i = 0; i < numFields; i++) {
|
||||||
|
FieldInfoValues values = readFieldInfoValues(crs);
|
||||||
|
fields[i] = new Field(kls, i, values);
|
||||||
|
}
|
||||||
|
return fields;
|
||||||
|
}
|
||||||
|
|
||||||
|
FieldInfoValues values;
|
||||||
private Symbol name;
|
private Symbol name;
|
||||||
private long offset;
|
private long offset;
|
||||||
private FieldIdentifier id;
|
private FieldIdentifier id;
|
||||||
@ -76,6 +139,7 @@ public class Field {
|
|||||||
public FieldIdentifier getID() { return id; }
|
public FieldIdentifier getID() { return id; }
|
||||||
|
|
||||||
public Symbol getName() { return name; }
|
public Symbol getName() { return name; }
|
||||||
|
public int getNameIndex() { return values.nameIndex; }
|
||||||
|
|
||||||
/** Indicates whether this is a VM field */
|
/** Indicates whether this is a VM field */
|
||||||
public boolean isVMField() { return isVMField; }
|
public boolean isVMField() { return isVMField; }
|
||||||
@ -111,9 +175,12 @@ public class Field {
|
|||||||
/** (Named, non-VM fields only) Returns the signature of this
|
/** (Named, non-VM fields only) Returns the signature of this
|
||||||
field. */
|
field. */
|
||||||
public Symbol getSignature() { return signature; }
|
public Symbol getSignature() { return signature; }
|
||||||
|
public int getSignatureIndex() { return values.signatureIndex; }
|
||||||
public Symbol getGenericSignature() { return genericSignature; }
|
public Symbol getGenericSignature() { return genericSignature; }
|
||||||
|
public int getGenericSignatureIndex() { return values.genericSignatureIndex; }
|
||||||
|
|
||||||
public boolean hasInitialValue() { return holder.getFieldInitialValueIndex(fieldIndex) != 0; }
|
public boolean hasInitialValue() { return holder.getFieldInitialValueIndex(fieldIndex) != 0; }
|
||||||
|
public int getInitialValueIndex() { return values.initialValueIndex; }
|
||||||
|
|
||||||
//
|
//
|
||||||
// Following accessors are for named, non-VM fields only
|
// Following accessors are for named, non-VM fields only
|
||||||
@ -131,6 +198,19 @@ public class Field {
|
|||||||
public boolean isSynthetic() { return accessFlags.isSynthetic(); }
|
public boolean isSynthetic() { return accessFlags.isSynthetic(); }
|
||||||
public boolean isEnumConstant() { return accessFlags.isEnum(); }
|
public boolean isEnumConstant() { return accessFlags.isEnum(); }
|
||||||
|
|
||||||
|
private static boolean fieldIsInitialized(int flags) { return ((flags >> InstanceKlass.FIELD_FLAG_IS_INITIALIZED) & 1 ) != 0; }
|
||||||
|
private static boolean fieldIsInjected(int flags) { return ((flags >> InstanceKlass.FIELD_FLAG_IS_INJECTED ) & 1 ) != 0; }
|
||||||
|
private static boolean fieldIsGeneric(int flags) { return ((flags >> InstanceKlass.FIELD_FLAG_IS_GENERIC ) & 1 ) != 0; }
|
||||||
|
private static boolean fieldIsStable(int flags) { return ((flags >> InstanceKlass.FIELD_FLAG_IS_STABLE ) & 1 ) != 0; }
|
||||||
|
private static boolean fieldIsContended(int flags) { return ((flags >> InstanceKlass.FIELD_FLAG_IS_CONTENDED ) & 1 ) != 0; }
|
||||||
|
|
||||||
|
|
||||||
|
public boolean isInitialized() { return fieldIsInitialized(values.fieldFlags); }
|
||||||
|
public boolean isInjected() { return fieldIsInjected(values.fieldFlags); }
|
||||||
|
public boolean isGeneric() { return fieldIsGeneric(values.fieldFlags); }
|
||||||
|
public boolean isStable() { return fieldIsStable(values.fieldFlags); }
|
||||||
|
public boolean isContended() { return fieldIsContended(values.fieldFlags); }
|
||||||
|
|
||||||
public boolean equals(Object obj) {
|
public boolean equals(Object obj) {
|
||||||
if (obj == null) {
|
if (obj == null) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2000, 2022, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2000, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -27,6 +27,7 @@ package sun.jvm.hotspot.oops;
|
|||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import sun.jvm.hotspot.classfile.ClassLoaderData;
|
import sun.jvm.hotspot.classfile.ClassLoaderData;
|
||||||
|
import sun.jvm.hotspot.code.CompressedReadStream;
|
||||||
import sun.jvm.hotspot.debugger.*;
|
import sun.jvm.hotspot.debugger.*;
|
||||||
import sun.jvm.hotspot.memory.*;
|
import sun.jvm.hotspot.memory.*;
|
||||||
import sun.jvm.hotspot.runtime.*;
|
import sun.jvm.hotspot.runtime.*;
|
||||||
@ -46,16 +47,12 @@ public class InstanceKlass extends Klass {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// field offset constants
|
// internal field flags constants
|
||||||
private static int ACCESS_FLAGS_OFFSET;
|
static int FIELD_FLAG_IS_INITIALIZED;
|
||||||
private static int NAME_INDEX_OFFSET;
|
static int FIELD_FLAG_IS_INJECTED;
|
||||||
private static int SIGNATURE_INDEX_OFFSET;
|
static int FIELD_FLAG_IS_GENERIC;
|
||||||
private static int INITVAL_INDEX_OFFSET;
|
static int FIELD_FLAG_IS_STABLE;
|
||||||
private static int LOW_OFFSET;
|
static int FIELD_FLAG_IS_CONTENDED;
|
||||||
private static int HIGH_OFFSET;
|
|
||||||
private static int FIELD_SLOTS;
|
|
||||||
private static short FIELDINFO_TAG_SIZE;
|
|
||||||
private static short FIELDINFO_TAG_OFFSET;
|
|
||||||
|
|
||||||
// ClassState constants
|
// ClassState constants
|
||||||
private static int CLASS_STATE_ALLOCATED;
|
private static int CLASS_STATE_ALLOCATED;
|
||||||
@ -75,8 +72,7 @@ public class InstanceKlass extends Klass {
|
|||||||
methodOrdering = type.getAddressField("_method_ordering");
|
methodOrdering = type.getAddressField("_method_ordering");
|
||||||
localInterfaces = type.getAddressField("_local_interfaces");
|
localInterfaces = type.getAddressField("_local_interfaces");
|
||||||
transitiveInterfaces = type.getAddressField("_transitive_interfaces");
|
transitiveInterfaces = type.getAddressField("_transitive_interfaces");
|
||||||
fields = type.getAddressField("_fields");
|
fieldinfoStream = type.getAddressField("_fieldinfo_stream");
|
||||||
javaFieldsCount = new CIntField(type.getCIntegerField("_java_fields_count"), 0);
|
|
||||||
constants = new MetadataField(type.getAddressField("_constants"), 0);
|
constants = new MetadataField(type.getAddressField("_constants"), 0);
|
||||||
sourceDebugExtension = type.getAddressField("_source_debug_extension");
|
sourceDebugExtension = type.getAddressField("_source_debug_extension");
|
||||||
innerClasses = type.getAddressField("_inner_classes");
|
innerClasses = type.getAddressField("_inner_classes");
|
||||||
@ -92,16 +88,13 @@ public class InstanceKlass extends Klass {
|
|||||||
}
|
}
|
||||||
headerSize = type.getSize();
|
headerSize = type.getSize();
|
||||||
|
|
||||||
// read field offset constants
|
// read internal field flags constants
|
||||||
ACCESS_FLAGS_OFFSET = db.lookupIntConstant("FieldInfo::access_flags_offset").intValue();
|
FIELD_FLAG_IS_INITIALIZED = db.lookupIntConstant("FieldInfo::FieldFlags::_ff_initialized");
|
||||||
NAME_INDEX_OFFSET = db.lookupIntConstant("FieldInfo::name_index_offset").intValue();
|
FIELD_FLAG_IS_INJECTED = db.lookupIntConstant("FieldInfo::FieldFlags::_ff_injected");
|
||||||
SIGNATURE_INDEX_OFFSET = db.lookupIntConstant("FieldInfo::signature_index_offset").intValue();
|
FIELD_FLAG_IS_GENERIC = db.lookupIntConstant("FieldInfo::FieldFlags::_ff_generic");
|
||||||
INITVAL_INDEX_OFFSET = db.lookupIntConstant("FieldInfo::initval_index_offset").intValue();
|
FIELD_FLAG_IS_STABLE = db.lookupIntConstant("FieldInfo::FieldFlags::_ff_stable");
|
||||||
LOW_OFFSET = db.lookupIntConstant("FieldInfo::low_packed_offset").intValue();
|
FIELD_FLAG_IS_CONTENDED = db.lookupIntConstant("FieldInfo::FieldFlags::_ff_contended");
|
||||||
HIGH_OFFSET = db.lookupIntConstant("FieldInfo::high_packed_offset").intValue();
|
|
||||||
FIELD_SLOTS = db.lookupIntConstant("FieldInfo::field_slots").intValue();
|
|
||||||
FIELDINFO_TAG_SIZE = db.lookupIntConstant("FIELDINFO_TAG_SIZE").shortValue();
|
|
||||||
FIELDINFO_TAG_OFFSET = db.lookupIntConstant("FIELDINFO_TAG_OFFSET").shortValue();
|
|
||||||
|
|
||||||
// read ClassState constants
|
// read ClassState constants
|
||||||
CLASS_STATE_ALLOCATED = db.lookupIntConstant("InstanceKlass::allocated").intValue();
|
CLASS_STATE_ALLOCATED = db.lookupIntConstant("InstanceKlass::allocated").intValue();
|
||||||
@ -111,6 +104,8 @@ public class InstanceKlass extends Klass {
|
|||||||
CLASS_STATE_BEING_INITIALIZED = db.lookupIntConstant("InstanceKlass::being_initialized").intValue();
|
CLASS_STATE_BEING_INITIALIZED = db.lookupIntConstant("InstanceKlass::being_initialized").intValue();
|
||||||
CLASS_STATE_FULLY_INITIALIZED = db.lookupIntConstant("InstanceKlass::fully_initialized").intValue();
|
CLASS_STATE_FULLY_INITIALIZED = db.lookupIntConstant("InstanceKlass::fully_initialized").intValue();
|
||||||
CLASS_STATE_INITIALIZATION_ERROR = db.lookupIntConstant("InstanceKlass::initialization_error").intValue();
|
CLASS_STATE_INITIALIZATION_ERROR = db.lookupIntConstant("InstanceKlass::initialization_error").intValue();
|
||||||
|
// We need a new fieldsCache each time we attach.
|
||||||
|
fieldsCache = new WeakHashMap<Address, Field[]>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public InstanceKlass(Address addr) {
|
public InstanceKlass(Address addr) {
|
||||||
@ -142,8 +137,7 @@ public class InstanceKlass extends Klass {
|
|||||||
private static AddressField methodOrdering;
|
private static AddressField methodOrdering;
|
||||||
private static AddressField localInterfaces;
|
private static AddressField localInterfaces;
|
||||||
private static AddressField transitiveInterfaces;
|
private static AddressField transitiveInterfaces;
|
||||||
private static AddressField fields;
|
private static AddressField fieldinfoStream;
|
||||||
private static CIntField javaFieldsCount;
|
|
||||||
private static MetadataField constants;
|
private static MetadataField constants;
|
||||||
private static AddressField sourceDebugExtension;
|
private static AddressField sourceDebugExtension;
|
||||||
private static AddressField innerClasses;
|
private static AddressField innerClasses;
|
||||||
@ -264,81 +258,71 @@ public class InstanceKlass extends Klass {
|
|||||||
|
|
||||||
public static long getHeaderSize() { return headerSize; }
|
public static long getHeaderSize() { return headerSize; }
|
||||||
|
|
||||||
public short getFieldAccessFlags(int index) {
|
// Each InstanceKlass mirror instance will cache the Field[] array after it is decoded,
|
||||||
return getFields().at(index * FIELD_SLOTS + ACCESS_FLAGS_OFFSET);
|
// but since there can be multiple InstanceKlass mirror instances per hotspot InstanceKlass,
|
||||||
|
// we also have a global cache that uses the Address of the hotspot InstanceKlass as the key.
|
||||||
|
private Field[] fields;
|
||||||
|
private static Map<Address, Field[]> fieldsCache;
|
||||||
|
|
||||||
|
Field getField(int index) {
|
||||||
|
synchronized (this) {
|
||||||
|
fields = fieldsCache.get(this.getAddress());
|
||||||
|
if (fields == null) {
|
||||||
|
fields = Field.getFields(this);
|
||||||
|
fieldsCache.put(this.getAddress(), fields);
|
||||||
|
} else {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return fields[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
public short getFieldNameIndex(int index) {
|
public short getFieldAccessFlags(int index) {
|
||||||
|
return (short)getField(index).getAccessFlags();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getFieldNameIndex(int index) {
|
||||||
if (index >= getJavaFieldsCount()) throw new IndexOutOfBoundsException("not a Java field;");
|
if (index >= getJavaFieldsCount()) throw new IndexOutOfBoundsException("not a Java field;");
|
||||||
return getFields().at(index * FIELD_SLOTS + NAME_INDEX_OFFSET);
|
return getField(index).getNameIndex();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Symbol getFieldName(int index) {
|
public Symbol getFieldName(int index) {
|
||||||
int nameIndex = getFields().at(index * FIELD_SLOTS + NAME_INDEX_OFFSET);
|
// Cannot use getFieldNameIndex() because this method is also used for injected fields
|
||||||
if (index < getJavaFieldsCount()) {
|
return getField(index).getName();
|
||||||
return getConstants().getSymbolAt(nameIndex);
|
}
|
||||||
|
|
||||||
|
public Symbol getSymbolFromIndex(int cpIndex, boolean injected) {
|
||||||
|
if (injected) {
|
||||||
|
return vmSymbols.symbolAt(cpIndex);
|
||||||
} else {
|
} else {
|
||||||
return vmSymbols.symbolAt(nameIndex);
|
return getConstants().getSymbolAt(cpIndex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public short getFieldSignatureIndex(int index) {
|
public int getFieldSignatureIndex(int index) {
|
||||||
if (index >= getJavaFieldsCount()) throw new IndexOutOfBoundsException("not a Java field;");
|
if (index >= getJavaFieldsCount()) throw new IndexOutOfBoundsException("not a Java field;");
|
||||||
return getFields().at(index * FIELD_SLOTS + SIGNATURE_INDEX_OFFSET);
|
return getField(index).getGenericSignatureIndex();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Symbol getFieldSignature(int index) {
|
public Symbol getFieldSignature(int index) {
|
||||||
int signatureIndex = getFields().at(index * FIELD_SLOTS + SIGNATURE_INDEX_OFFSET);
|
// Cannot use getFieldSignatureIndex() because this method is also use for injected fields
|
||||||
if (index < getJavaFieldsCount()) {
|
return getField(index).getSignature();
|
||||||
return getConstants().getSymbolAt(signatureIndex);
|
|
||||||
} else {
|
|
||||||
return vmSymbols.symbolAt(signatureIndex);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public short getFieldGenericSignatureIndex(int index) {
|
public int getFieldGenericSignatureIndex(int index) {
|
||||||
// int len = getFields().length();
|
return getField(index).getGenericSignatureIndex();
|
||||||
int allFieldsCount = getAllFieldsCount();
|
|
||||||
int generic_signature_slot = allFieldsCount * FIELD_SLOTS;
|
|
||||||
for (int i = 0; i < allFieldsCount; i++) {
|
|
||||||
short flags = getFieldAccessFlags(i);
|
|
||||||
AccessFlags access = new AccessFlags(flags);
|
|
||||||
if (i == index) {
|
|
||||||
if (access.fieldHasGenericSignature()) {
|
|
||||||
return getFields().at(generic_signature_slot);
|
|
||||||
} else {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (access.fieldHasGenericSignature()) {
|
|
||||||
generic_signature_slot ++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Symbol getFieldGenericSignature(int index) {
|
public Symbol getFieldGenericSignature(int index) {
|
||||||
short genericSignatureIndex = getFieldGenericSignatureIndex(index);
|
return getField(index).getGenericSignature();
|
||||||
if (genericSignatureIndex != 0) {
|
|
||||||
return getConstants().getSymbolAt(genericSignatureIndex);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public short getFieldInitialValueIndex(int index) {
|
public int getFieldInitialValueIndex(int index) {
|
||||||
if (index >= getJavaFieldsCount()) throw new IndexOutOfBoundsException("not a Java field;");
|
if (index >= getJavaFieldsCount()) throw new IndexOutOfBoundsException("not a Java field;");
|
||||||
return getFields().at(index * FIELD_SLOTS + INITVAL_INDEX_OFFSET);
|
return getField(index).getInitialValueIndex();
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getFieldOffset(int index) {
|
public int getFieldOffset(int index) {
|
||||||
U2Array fields = getFields();
|
return (int)getField(index).getOffset();
|
||||||
short lo = fields.at(index * FIELD_SLOTS + LOW_OFFSET);
|
|
||||||
short hi = fields.at(index * FIELD_SLOTS + HIGH_OFFSET);
|
|
||||||
if ((lo & FIELDINFO_TAG_OFFSET) == FIELDINFO_TAG_OFFSET) {
|
|
||||||
return VM.getVM().buildIntFromShorts(lo, hi) >> FIELDINFO_TAG_SIZE;
|
|
||||||
}
|
|
||||||
throw new RuntimeException("should not reach here");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Accessors for declared fields
|
// Accessors for declared fields
|
||||||
@ -358,21 +342,31 @@ public class InstanceKlass extends Klass {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public KlassArray getLocalInterfaces() { return new KlassArray(localInterfaces.getValue(getAddress())); }
|
private int javaFieldsCount = -1;
|
||||||
public KlassArray getTransitiveInterfaces() { return new KlassArray(transitiveInterfaces.getValue(getAddress())); }
|
private int allFieldsCount = -1;
|
||||||
public int getJavaFieldsCount() { return (int) javaFieldsCount.getValue(this); }
|
|
||||||
public int getAllFieldsCount() {
|
private void initFieldCounts() {
|
||||||
int len = getFields().length();
|
CompressedReadStream crs = new CompressedReadStream(getFieldInfoStream().getDataStart());
|
||||||
int allFieldsCount = 0;
|
javaFieldsCount = crs.readInt(); // read num_java_fields
|
||||||
for (; allFieldsCount*FIELD_SLOTS < len; allFieldsCount++) {
|
allFieldsCount = javaFieldsCount + crs.readInt(); // read num_injected_fields;
|
||||||
short flags = getFieldAccessFlags(allFieldsCount);
|
|
||||||
AccessFlags access = new AccessFlags(flags);
|
|
||||||
if (access.fieldHasGenericSignature()) {
|
|
||||||
len --;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getJavaFieldsCount() {
|
||||||
|
if (javaFieldsCount == -1) {
|
||||||
|
initFieldCounts();
|
||||||
|
}
|
||||||
|
return javaFieldsCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getAllFieldsCount() {
|
||||||
|
if (allFieldsCount == -1) {
|
||||||
|
initFieldCounts();
|
||||||
}
|
}
|
||||||
return allFieldsCount;
|
return allFieldsCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public KlassArray getLocalInterfaces() { return new KlassArray(localInterfaces.getValue(getAddress())); }
|
||||||
|
public KlassArray getTransitiveInterfaces() { return new KlassArray(transitiveInterfaces.getValue(getAddress())); }
|
||||||
public ConstantPool getConstants() { return (ConstantPool) constants.getValue(this); }
|
public ConstantPool getConstants() { return (ConstantPool) constants.getValue(this); }
|
||||||
public Symbol getSourceFileName() { return getConstants().getSourceFileName(); }
|
public Symbol getSourceFileName() { return getConstants().getSourceFileName(); }
|
||||||
public String getSourceDebugExtension(){ return CStringUtilities.getString(sourceDebugExtension.getValue(getAddress())); }
|
public String getSourceDebugExtension(){ return CStringUtilities.getString(sourceDebugExtension.getValue(getAddress())); }
|
||||||
@ -622,7 +616,6 @@ public class InstanceKlass extends Klass {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Field[] getStaticFields() {
|
public Field[] getStaticFields() {
|
||||||
U2Array fields = getFields();
|
|
||||||
int length = getJavaFieldsCount();
|
int length = getJavaFieldsCount();
|
||||||
ArrayList<Field> result = new ArrayList<>();
|
ArrayList<Field> result = new ArrayList<>();
|
||||||
for (int index = 0; index < length; index++) {
|
for (int index = 0; index < length; index++) {
|
||||||
@ -860,9 +853,9 @@ public class InstanceKlass extends Klass {
|
|||||||
return VMObjectFactory.newObject(IntArray.class, addr);
|
return VMObjectFactory.newObject(IntArray.class, addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
public U2Array getFields() {
|
public U1Array getFieldInfoStream() {
|
||||||
Address addr = getAddress().getAddressAt(fields.getOffset());
|
Address addr = getAddress().getAddressAt(fieldinfoStream.getOffset());
|
||||||
return VMObjectFactory.newObject(U2Array.class, addr);
|
return VMObjectFactory.newObject(U1Array.class, addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
public U2Array getInnerClasses() {
|
public U2Array getInnerClasses() {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2002, 2022, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2002, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -137,17 +137,6 @@ public interface ClassConstants
|
|||||||
// Method* flags
|
// Method* flags
|
||||||
public static final long JVM_ACC_HAS_LOCAL_VARIABLE_TABLE = 0x00200000;
|
public static final long JVM_ACC_HAS_LOCAL_VARIABLE_TABLE = 0x00200000;
|
||||||
|
|
||||||
// field flags
|
|
||||||
// Note: these flags must be defined in the low order 16 bits because
|
|
||||||
// InstanceKlass only stores a ushort worth of information from the
|
|
||||||
// AccessFlags value.
|
|
||||||
// field access is watched by JVMTI
|
|
||||||
public static final long JVM_ACC_FIELD_ACCESS_WATCHED = 0x00002000;
|
|
||||||
// field modification is watched by JVMTI
|
|
||||||
public static final long JVM_ACC_FIELD_MODIFICATION_WATCHED = 0x00008000;
|
|
||||||
// field has generic signature
|
|
||||||
public static final long JVM_ACC_FIELD_HAS_GENERIC_SIGNATURE = 0x00000800;
|
|
||||||
|
|
||||||
// flags accepted by set_field_flags
|
// flags accepted by set_field_flags
|
||||||
public static final long JVM_ACC_FIELD_FLAGS = 0x00008000 | JVM_ACC_WRITTEN_FLAGS;
|
public static final long JVM_ACC_FIELD_FLAGS = 0x00008000 | JVM_ACC_WRITTEN_FLAGS;
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -271,7 +271,7 @@ public class ClassLoaderStats extends Tool {
|
|||||||
size += arraySize(k.getInnerClasses());
|
size += arraySize(k.getInnerClasses());
|
||||||
|
|
||||||
// Fields
|
// Fields
|
||||||
size += arraySize(k.getFields());
|
size += arraySize(k.getFieldInfoStream());
|
||||||
|
|
||||||
// Methods
|
// Methods
|
||||||
MethodArray methods = k.getMethods();
|
MethodArray methods = k.getMethods();
|
||||||
|
@ -377,10 +377,10 @@ public class ClassWriter implements /* imports */ ClassConstants
|
|||||||
short accessFlags = klass.getFieldAccessFlags(index);
|
short accessFlags = klass.getFieldAccessFlags(index);
|
||||||
dos.writeShort(accessFlags & (short) JVM_RECOGNIZED_FIELD_MODIFIERS);
|
dos.writeShort(accessFlags & (short) JVM_RECOGNIZED_FIELD_MODIFIERS);
|
||||||
|
|
||||||
short nameIndex = klass.getFieldNameIndex(index);
|
int nameIndex = klass.getFieldNameIndex(index);
|
||||||
dos.writeShort(nameIndex);
|
dos.writeShort(nameIndex);
|
||||||
|
|
||||||
short signatureIndex = klass.getFieldSignatureIndex(index);
|
int signatureIndex = klass.getFieldSignatureIndex(index);
|
||||||
dos.writeShort(signatureIndex);
|
dos.writeShort(signatureIndex);
|
||||||
if (DEBUG) debugMessage("\tfield name = " + nameIndex + ", signature = " + signatureIndex);
|
if (DEBUG) debugMessage("\tfield name = " + nameIndex + ", signature = " + signatureIndex);
|
||||||
|
|
||||||
@ -389,11 +389,11 @@ public class ClassWriter implements /* imports */ ClassConstants
|
|||||||
if (hasSyn)
|
if (hasSyn)
|
||||||
fieldAttributeCount++;
|
fieldAttributeCount++;
|
||||||
|
|
||||||
short initvalIndex = klass.getFieldInitialValueIndex(index);
|
int initvalIndex = klass.getFieldInitialValueIndex(index);
|
||||||
if (initvalIndex != 0)
|
if (initvalIndex != 0)
|
||||||
fieldAttributeCount++;
|
fieldAttributeCount++;
|
||||||
|
|
||||||
short genSigIndex = klass.getFieldGenericSignatureIndex(index);
|
int genSigIndex = klass.getFieldGenericSignatureIndex(index);
|
||||||
if (genSigIndex != 0)
|
if (genSigIndex != 0)
|
||||||
fieldAttributeCount++;
|
fieldAttributeCount++;
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2002, 2022, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2002, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -1120,17 +1120,13 @@ public class HTMLGenerator implements /* imports */ ClassConstants {
|
|||||||
buf.append(" " + kls.getName().asString() + "={");
|
buf.append(" " + kls.getName().asString() + "={");
|
||||||
int flen = ov.fieldsSize();
|
int flen = ov.fieldsSize();
|
||||||
|
|
||||||
U2Array klfields = kls.getFields();
|
sun.jvm.hotspot.oops.Field[] fields = sun.jvm.hotspot.oops.Field.getFields(kls);
|
||||||
int klen = klfields.length();
|
|
||||||
int findex = 0;
|
int findex = 0;
|
||||||
for (int index = 0; index < klen; index++) {
|
for (int index = 0; index < fields.length; index++) {
|
||||||
int accsFlags = kls.getFieldAccessFlags(index);
|
if (!fields[index].getAccessFlagsObj().isStatic()) {
|
||||||
Symbol f_name = kls.getFieldName(index);
|
|
||||||
AccessFlags access = new AccessFlags(accsFlags);
|
|
||||||
if (!access.isStatic()) {
|
|
||||||
ScopeValue svf = ov.getFieldAt(findex++);
|
ScopeValue svf = ov.getFieldAt(findex++);
|
||||||
String fstr = scopeValueAsString(sd, svf);
|
String fstr = scopeValueAsString(sd, svf);
|
||||||
buf.append(" [" + f_name.asString() + " :"+ index + "]=(#" + fstr + ")");
|
buf.append(" [" + fields[index].getName().asString() + " :"+ index + "]=(#" + fstr + ")");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
buf.append(" }");
|
buf.append(" }");
|
||||||
@ -1680,14 +1676,14 @@ public class HTMLGenerator implements /* imports */ ClassConstants {
|
|||||||
|
|
||||||
protected String genHTMLListForFields(InstanceKlass klass) {
|
protected String genHTMLListForFields(InstanceKlass klass) {
|
||||||
Formatter buf = new Formatter(genHTML);
|
Formatter buf = new Formatter(genHTML);
|
||||||
U2Array fields = klass.getFields();
|
sun.jvm.hotspot.oops.Field[] fields = sun.jvm.hotspot.oops.Field.getFields(klass);
|
||||||
int numFields = klass.getAllFieldsCount();
|
int numFields = fields.length;
|
||||||
if (numFields != 0) {
|
if (numFields != 0) {
|
||||||
buf.h3("Fields");
|
buf.h3("Fields");
|
||||||
buf.beginList();
|
buf.beginList();
|
||||||
for (int f = 0; f < numFields; f++) {
|
for (int f = 0; f < numFields; f++) {
|
||||||
sun.jvm.hotspot.oops.Field field = klass.getFieldByIndex(f);
|
sun.jvm.hotspot.oops.Field field = fields[f];
|
||||||
String f_name = ((NamedFieldIdentifier)field.getID()).getName();
|
String f_name = field.getName().asString();
|
||||||
Symbol f_sig = field.getSignature();
|
Symbol f_sig = field.getSignature();
|
||||||
Symbol f_genSig = field.getGenericSignature();
|
Symbol f_genSig = field.getGenericSignature();
|
||||||
AccessFlags acc = field.getAccessFlagsObj();
|
AccessFlags acc = field.getAccessFlagsObj();
|
||||||
@ -1702,7 +1698,7 @@ public class HTMLGenerator implements /* imports */ ClassConstants {
|
|||||||
buf.append(f_name);
|
buf.append(f_name);
|
||||||
buf.append(';');
|
buf.append(';');
|
||||||
// is it generic?
|
// is it generic?
|
||||||
if (f_genSig != null) {
|
if (field.isGeneric()) {
|
||||||
buf.append(" [signature ");
|
buf.append(" [signature ");
|
||||||
buf.append(escapeHTMLSpecialChars(f_genSig.asString()));
|
buf.append(escapeHTMLSpecialChars(f_genSig.asString()));
|
||||||
buf.append("] ");
|
buf.append("] ");
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2012, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -74,6 +74,10 @@ public abstract class GenericArray extends VMObject {
|
|||||||
return length();
|
return length();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Address getDataStart() {
|
||||||
|
return getAddress().addOffsetTo(dataFieldOffset);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the element at the given index.
|
* Gets the element at the given index.
|
||||||
*/
|
*/
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2011, 2022, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2011, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -463,9 +463,10 @@ final class CompilerToVM {
|
|||||||
* {@code info} are:
|
* {@code info} are:
|
||||||
*
|
*
|
||||||
* <pre>
|
* <pre>
|
||||||
* [ flags, // fieldDescriptor::access_flags()
|
* [ aflags, // fieldDescriptor::access_flags()
|
||||||
* offset, // fieldDescriptor::offset()
|
* offset, // fieldDescriptor::offset()
|
||||||
* index // fieldDescriptor::index()
|
* index, // fieldDescriptor::index()
|
||||||
|
* fflags // fieldDescriptor::field_flags()
|
||||||
* ]
|
* ]
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
@ -1043,6 +1044,12 @@ final class CompilerToVM {
|
|||||||
|
|
||||||
native ResolvedJavaMethod[] getDeclaredMethods(HotSpotResolvedObjectTypeImpl klass, long klassPointer);
|
native ResolvedJavaMethod[] getDeclaredMethods(HotSpotResolvedObjectTypeImpl klass, long klassPointer);
|
||||||
|
|
||||||
|
HotSpotResolvedObjectTypeImpl.FieldInfo[] getDeclaredFieldsInfo(HotSpotResolvedObjectTypeImpl klass) {
|
||||||
|
return getDeclaredFieldsInfo(klass, klass.getKlassPointer());
|
||||||
|
}
|
||||||
|
|
||||||
|
native HotSpotResolvedObjectTypeImpl.FieldInfo[] getDeclaredFieldsInfo(HotSpotResolvedObjectTypeImpl klass, long klassPointer);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads the current value of a static field of {@code declaringKlass}. Extra sanity checking is
|
* Reads the current value of a static field of {@code declaringKlass}. Extra sanity checking is
|
||||||
* performed on the offset and kind of the read being performed.
|
* performed on the offset and kind of the read being performed.
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2011, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -808,7 +808,7 @@ public final class HotSpotConstantPool implements ConstantPool, MetaspaceHandleO
|
|||||||
JavaType fieldHolder = lookupType(holderIndex, opcode);
|
JavaType fieldHolder = lookupType(holderIndex, opcode);
|
||||||
|
|
||||||
if (fieldHolder instanceof HotSpotResolvedObjectTypeImpl) {
|
if (fieldHolder instanceof HotSpotResolvedObjectTypeImpl) {
|
||||||
int[] info = new int[3];
|
int[] info = new int[4];
|
||||||
HotSpotResolvedObjectTypeImpl resolvedHolder;
|
HotSpotResolvedObjectTypeImpl resolvedHolder;
|
||||||
try {
|
try {
|
||||||
resolvedHolder = compilerToVM().resolveFieldInPool(this, index, (HotSpotResolvedJavaMethodImpl) method, (byte) opcode, info);
|
resolvedHolder = compilerToVM().resolveFieldInPool(this, index, (HotSpotResolvedJavaMethodImpl) method, (byte) opcode, info);
|
||||||
@ -822,7 +822,8 @@ public final class HotSpotConstantPool implements ConstantPool, MetaspaceHandleO
|
|||||||
final int flags = info[0];
|
final int flags = info[0];
|
||||||
final int offset = info[1];
|
final int offset = info[1];
|
||||||
final int fieldIndex = info[2];
|
final int fieldIndex = info[2];
|
||||||
HotSpotResolvedJavaField result = resolvedHolder.createField(type, offset, flags, fieldIndex);
|
final int fieldFlags = info[3];
|
||||||
|
HotSpotResolvedJavaField result = resolvedHolder.createField(type, offset, flags, fieldFlags, fieldIndex);
|
||||||
return result;
|
return result;
|
||||||
} else {
|
} else {
|
||||||
return new UnresolvedJavaField(fieldHolder, lookupUtf8(getNameRefIndexAt(nameAndTypeIndex)), type);
|
return new UnresolvedJavaField(fieldHolder, lookupUtf8(getNameRefIndexAt(nameAndTypeIndex)), type);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2011, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -56,16 +56,22 @@ class HotSpotResolvedJavaFieldImpl implements HotSpotResolvedJavaField {
|
|||||||
private final int index;
|
private final int index;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This value contains all flags as stored in the VM including internal ones.
|
* This value contains all flags from the class file
|
||||||
*/
|
*/
|
||||||
private final int modifiers;
|
private final int classfileFlags;
|
||||||
|
|
||||||
HotSpotResolvedJavaFieldImpl(HotSpotResolvedObjectTypeImpl holder, JavaType type, int offset, int modifiers, int index) {
|
/**
|
||||||
|
* This value contains VM internal flags
|
||||||
|
*/
|
||||||
|
private final int internalFlags;
|
||||||
|
|
||||||
|
HotSpotResolvedJavaFieldImpl(HotSpotResolvedObjectTypeImpl holder, JavaType type, int offset, int classfileFlags, int internalFlags, int index) {
|
||||||
this.holder = holder;
|
this.holder = holder;
|
||||||
this.type = type;
|
this.type = type;
|
||||||
this.index = index;
|
|
||||||
this.offset = offset;
|
this.offset = offset;
|
||||||
this.modifiers = modifiers;
|
this.classfileFlags = classfileFlags;
|
||||||
|
this.internalFlags = internalFlags;
|
||||||
|
this.index = index;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -91,12 +97,12 @@ class HotSpotResolvedJavaFieldImpl implements HotSpotResolvedJavaField {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getModifiers() {
|
public int getModifiers() {
|
||||||
return modifiers & HotSpotModifiers.jvmFieldModifiers();
|
return classfileFlags & HotSpotModifiers.jvmFieldModifiers();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isInternal() {
|
public boolean isInternal() {
|
||||||
return (modifiers & config().jvmAccFieldInternal) != 0;
|
return (internalFlags & (1 << config().jvmFieldFlagInternalShift)) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -121,7 +127,7 @@ class HotSpotResolvedJavaFieldImpl implements HotSpotResolvedJavaField {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return holder.createFieldInfo(index).getName();
|
return holder.getFieldInfo(index).getName(holder);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -165,7 +171,7 @@ class HotSpotResolvedJavaFieldImpl implements HotSpotResolvedJavaField {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isSynthetic() {
|
public boolean isSynthetic() {
|
||||||
return (config().jvmAccSynthetic & modifiers) != 0;
|
return (config().jvmAccSynthetic & classfileFlags) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -175,7 +181,7 @@ class HotSpotResolvedJavaFieldImpl implements HotSpotResolvedJavaField {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public boolean isStable() {
|
public boolean isStable() {
|
||||||
return (config().jvmAccFieldStable & modifiers) != 0;
|
return (1 << (config().jvmFieldFlagStableShift ) & internalFlags) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean hasAnnotations() {
|
private boolean hasAnnotations() {
|
||||||
@ -219,6 +225,6 @@ class HotSpotResolvedJavaFieldImpl implements HotSpotResolvedJavaField {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public JavaConstant getConstantValue() {
|
public JavaConstant getConstantValue() {
|
||||||
return holder.createFieldInfo(index).getConstantValue();
|
return holder.getFieldInfo(index).getConstantValue(holder);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2011, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -84,6 +84,11 @@ final class HotSpotResolvedObjectTypeImpl extends HotSpotResolvedJavaType implem
|
|||||||
*/
|
*/
|
||||||
private HotSpotResolvedJavaType componentType;
|
private HotSpotResolvedJavaType componentType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lazily initialized cache for FieldInfo.
|
||||||
|
*/
|
||||||
|
private FieldInfo[] fieldInfo;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Managed exclusively by {@link HotSpotJDKReflection#getField}.
|
* Managed exclusively by {@link HotSpotJDKReflection#getField}.
|
||||||
*/
|
*/
|
||||||
@ -576,8 +581,8 @@ final class HotSpotResolvedObjectTypeImpl extends HotSpotResolvedJavaType implem
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
HotSpotResolvedJavaField createField(JavaType type, int offset, int rawFlags, int index) {
|
HotSpotResolvedJavaField createField(JavaType type, int offset, int classfileFlags, int internalFlags, int index) {
|
||||||
return new HotSpotResolvedJavaFieldImpl(this, type, offset, rawFlags, index);
|
return new HotSpotResolvedJavaFieldImpl(this, type, offset, classfileFlags, internalFlags, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -623,8 +628,15 @@ final class HotSpotResolvedObjectTypeImpl extends HotSpotResolvedJavaType implem
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
FieldInfo createFieldInfo(int index) {
|
private FieldInfo[] getFieldInfo() {
|
||||||
return new FieldInfo(index);
|
if (fieldInfo == null) {
|
||||||
|
fieldInfo = runtime().compilerToVm.getDeclaredFieldsInfo(this);
|
||||||
|
}
|
||||||
|
return fieldInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
FieldInfo getFieldInfo(int index) {
|
||||||
|
return getFieldInfo()[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ensureInitialized() {
|
public void ensureInitialized() {
|
||||||
@ -657,75 +669,74 @@ final class HotSpotResolvedObjectTypeImpl extends HotSpotResolvedJavaType implem
|
|||||||
* This class represents the field information for one field contained in the fields array of an
|
* This class represents the field information for one field contained in the fields array of an
|
||||||
* {@code InstanceKlass}. The implementation is similar to the native {@code FieldInfo} class.
|
* {@code InstanceKlass}. The implementation is similar to the native {@code FieldInfo} class.
|
||||||
*/
|
*/
|
||||||
class FieldInfo {
|
static class FieldInfo {
|
||||||
/**
|
|
||||||
* Native pointer into the array of Java shorts.
|
private final int nameIndex;
|
||||||
*/
|
private final int signatureIndex;
|
||||||
private final long metaspaceData;
|
private final int offset;
|
||||||
|
private final int classfileFlags;
|
||||||
|
private final int internalFlags;
|
||||||
|
private final int initializerIndex;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a field info for the field in the fields array at index {@code index}.
|
* Creates a field info with the provided indices.
|
||||||
*
|
*
|
||||||
* @param index index to the fields array
|
* @param nameIndex index of field's name in the constant pool
|
||||||
|
* @param signatureIndex index of field's signature in the constant pool
|
||||||
|
* @param offset field's offset
|
||||||
|
* @param classfileFlags field's access flags (from the class file)
|
||||||
|
* @param internalFlags field's internal flags (from the VM)
|
||||||
|
* @param initializerIndex field's initial value index in the constant pool
|
||||||
*/
|
*/
|
||||||
FieldInfo(int index) {
|
FieldInfo(int nameIndex, int signatureIndex, int offset, int classfileFlags, int internalFlags, int initializerIndex) {
|
||||||
HotSpotVMConfig config = config();
|
this.nameIndex = nameIndex;
|
||||||
// Get Klass::_fields
|
this.signatureIndex = signatureIndex;
|
||||||
final long metaspaceFields = UNSAFE.getAddress(getKlassPointer() + config.instanceKlassFieldsOffset);
|
this.offset = offset;
|
||||||
assert config.fieldInfoFieldSlots == 6 : "revisit the field parsing code";
|
this.classfileFlags = classfileFlags;
|
||||||
int offset = config.fieldInfoFieldSlots * Short.BYTES * index;
|
this.internalFlags = internalFlags;
|
||||||
metaspaceData = metaspaceFields + config.arrayU2DataOffset + offset;
|
this.initializerIndex = initializerIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getAccessFlags() {
|
private int getClassfileFlags() {
|
||||||
return readFieldSlot(config().fieldInfoAccessFlagsOffset);
|
return classfileFlags;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getInternalFlags() {
|
||||||
|
return internalFlags;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getNameIndex() {
|
private int getNameIndex() {
|
||||||
return readFieldSlot(config().fieldInfoNameIndexOffset);
|
return nameIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getSignatureIndex() {
|
private int getSignatureIndex() {
|
||||||
return readFieldSlot(config().fieldInfoSignatureIndexOffset);
|
return signatureIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getConstantValueIndex() {
|
private int getConstantValueIndex() {
|
||||||
return readFieldSlot(config().fieldInfoConstantValueIndexOffset);
|
return initializerIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getOffset() {
|
public int getOffset() {
|
||||||
HotSpotVMConfig config = config();
|
|
||||||
final int lowPacked = readFieldSlot(config.fieldInfoLowPackedOffset);
|
|
||||||
final int highPacked = readFieldSlot(config.fieldInfoHighPackedOffset);
|
|
||||||
final int offset = ((highPacked << Short.SIZE) | lowPacked) >> config.fieldInfoTagSize;
|
|
||||||
return offset;
|
return offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper method to read an entry (slot) from the field array. Currently field info is laid
|
|
||||||
* on top an array of Java shorts.
|
|
||||||
*/
|
|
||||||
private int readFieldSlot(int index) {
|
|
||||||
int offset = Short.BYTES * index;
|
|
||||||
return UNSAFE.getChar(metaspaceData + offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the name of this field as a {@link String}. If the field is an internal field the
|
* Returns the name of this field as a {@link String}. If the field is an internal field the
|
||||||
* name index is pointing into the vmSymbols table.
|
* name index is pointing into the vmSymbols table.
|
||||||
|
* @param klass field's holder class
|
||||||
*/
|
*/
|
||||||
public String getName() {
|
public String getName(HotSpotResolvedObjectTypeImpl klass) {
|
||||||
final int nameIndex = getNameIndex();
|
return isInternal() ? config().symbolAt(nameIndex) : klass.getConstantPool().lookupUtf8(nameIndex);
|
||||||
return isInternal() ? config().symbolAt(nameIndex) : getConstantPool().lookupUtf8(nameIndex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the signature of this field as {@link String}. If the field is an internal field
|
* Returns the signature of this field as {@link String}. If the field is an internal field
|
||||||
* the signature index is pointing into the vmSymbols table.
|
* the signature index is pointing into the vmSymbols table.
|
||||||
|
* @param klass field's holder class
|
||||||
*/
|
*/
|
||||||
public String getSignature() {
|
public String getSignature(HotSpotResolvedObjectTypeImpl klass) {
|
||||||
final int signatureIndex = getSignatureIndex();
|
return isInternal() ? config().symbolAt(signatureIndex) : klass.getConstantPool().lookupUtf8(signatureIndex);
|
||||||
return isInternal() ? config().symbolAt(signatureIndex) : getConstantPool().lookupUtf8(signatureIndex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -733,29 +744,24 @@ final class HotSpotResolvedObjectTypeImpl extends HotSpotResolvedJavaType implem
|
|||||||
*
|
*
|
||||||
* @return {@code null} if this field has no {@code ConstantValue} attribute
|
* @return {@code null} if this field has no {@code ConstantValue} attribute
|
||||||
*/
|
*/
|
||||||
public JavaConstant getConstantValue() {
|
public JavaConstant getConstantValue(HotSpotResolvedObjectTypeImpl klass) {
|
||||||
int cvIndex = getConstantValueIndex();
|
if (initializerIndex == 0) {
|
||||||
if (cvIndex == 0) {
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return constantPool.getStaticFieldConstantValue(cvIndex);
|
return klass.constantPool.getStaticFieldConstantValue(initializerIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
public JavaType getType() {
|
public JavaType getType(HotSpotResolvedObjectTypeImpl klass) {
|
||||||
String signature = getSignature();
|
String signature = getSignature(klass);
|
||||||
return runtime().lookupType(signature, HotSpotResolvedObjectTypeImpl.this, false);
|
return runtime().lookupType(signature, klass, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isInternal() {
|
private boolean isInternal() {
|
||||||
return (getAccessFlags() & config().jvmAccFieldInternal) != 0;
|
return (getInternalFlags() & (1 << config().jvmFieldFlagInternalShift)) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isStatic() {
|
public boolean isStatic() {
|
||||||
return Modifier.isStatic(getAccessFlags());
|
return Modifier.isStatic(getClassfileFlags());
|
||||||
}
|
|
||||||
|
|
||||||
public boolean hasGenericSignature() {
|
|
||||||
return (getAccessFlags() & config().jvmAccFieldHasGenericSignature) != 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -820,17 +826,11 @@ final class HotSpotResolvedObjectTypeImpl extends HotSpotResolvedJavaType implem
|
|||||||
*/
|
*/
|
||||||
private HotSpotResolvedJavaField[] getFields(boolean retrieveStaticFields, HotSpotResolvedJavaField[] prepend) {
|
private HotSpotResolvedJavaField[] getFields(boolean retrieveStaticFields, HotSpotResolvedJavaField[] prepend) {
|
||||||
HotSpotVMConfig config = config();
|
HotSpotVMConfig config = config();
|
||||||
final long metaspaceFields = UNSAFE.getAddress(getKlassPointer() + config.instanceKlassFieldsOffset);
|
|
||||||
int metaspaceFieldsLength = UNSAFE.getInt(metaspaceFields + config.arrayU1LengthOffset);
|
|
||||||
int resultCount = 0;
|
int resultCount = 0;
|
||||||
int index = 0;
|
int index = 0;
|
||||||
for (int i = 0; i < metaspaceFieldsLength; i += config.fieldInfoFieldSlots, index++) {
|
|
||||||
FieldInfo field = new FieldInfo(index);
|
|
||||||
if (field.hasGenericSignature()) {
|
|
||||||
metaspaceFieldsLength--;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (field.isStatic() == retrieveStaticFields) {
|
for (index = 0; index < getFieldInfo().length; index++) {
|
||||||
|
if (getFieldInfo(index).isStatic() == retrieveStaticFields) {
|
||||||
resultCount++;
|
resultCount++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -851,11 +851,11 @@ final class HotSpotResolvedObjectTypeImpl extends HotSpotResolvedJavaType implem
|
|||||||
// but the array of fields to be returned must be sorted by increasing offset
|
// but the array of fields to be returned must be sorted by increasing offset
|
||||||
// This code populates the array, then applies the sorting function
|
// This code populates the array, then applies the sorting function
|
||||||
int resultIndex = prependLength;
|
int resultIndex = prependLength;
|
||||||
for (int i = 0; i < index; ++i) {
|
for (int i = 0; i < getFieldInfo().length; ++i) {
|
||||||
FieldInfo field = new FieldInfo(i);
|
FieldInfo field = getFieldInfo(i);
|
||||||
if (field.isStatic() == retrieveStaticFields) {
|
if (field.isStatic() == retrieveStaticFields) {
|
||||||
int offset = field.getOffset();
|
int offset = field.getOffset();
|
||||||
HotSpotResolvedJavaField resolvedJavaField = createField(field.getType(), offset, field.getAccessFlags(), i);
|
HotSpotResolvedJavaField resolvedJavaField = createField(field.getType(this), offset, field.getClassfileFlags(), field.getInternalFlags(), i);
|
||||||
result[resultIndex++] = resolvedJavaField;
|
result[resultIndex++] = resolvedJavaField;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -99,7 +99,7 @@ class HotSpotVMConfig extends HotSpotVMConfigAccess {
|
|||||||
|
|
||||||
final int instanceKlassInitStateOffset = getFieldOffset("InstanceKlass::_init_state", Integer.class, "InstanceKlass::ClassState");
|
final int instanceKlassInitStateOffset = getFieldOffset("InstanceKlass::_init_state", Integer.class, "InstanceKlass::ClassState");
|
||||||
final int instanceKlassConstantsOffset = getFieldOffset("InstanceKlass::_constants", Integer.class, "ConstantPool*");
|
final int instanceKlassConstantsOffset = getFieldOffset("InstanceKlass::_constants", Integer.class, "ConstantPool*");
|
||||||
final int instanceKlassFieldsOffset = getFieldOffset("InstanceKlass::_fields", Integer.class, "Array<u2>*");
|
final int instanceKlassFieldInfoStreamOffset = getFieldOffset("InstanceKlass::_fieldinfo_stream", Integer.class, "Array<u1>*");
|
||||||
final int instanceKlassAnnotationsOffset = getFieldOffset("InstanceKlass::_annotations", Integer.class, "Annotations*");
|
final int instanceKlassAnnotationsOffset = getFieldOffset("InstanceKlass::_annotations", Integer.class, "Annotations*");
|
||||||
final int instanceKlassMiscFlagsOffset = getFieldOffset("InstanceKlass::_misc_flags._flags", Integer.class, "u2");
|
final int instanceKlassMiscFlagsOffset = getFieldOffset("InstanceKlass::_misc_flags._flags", Integer.class, "u2");
|
||||||
final int klassVtableStartOffset = getFieldValue("CompilerToVM::Data::Klass_vtable_start_offset", Integer.class, "int");
|
final int klassVtableStartOffset = getFieldValue("CompilerToVM::Data::Klass_vtable_start_offset", Integer.class, "int");
|
||||||
@ -116,20 +116,9 @@ class HotSpotVMConfig extends HotSpotVMConfigAccess {
|
|||||||
final int arrayU1DataOffset = getFieldOffset("Array<u1>::_data", Integer.class);
|
final int arrayU1DataOffset = getFieldOffset("Array<u1>::_data", Integer.class);
|
||||||
final int arrayU2DataOffset = getFieldOffset("Array<u2>::_data", Integer.class);
|
final int arrayU2DataOffset = getFieldOffset("Array<u2>::_data", Integer.class);
|
||||||
|
|
||||||
final int fieldInfoAccessFlagsOffset = getConstant("FieldInfo::access_flags_offset", Integer.class);
|
|
||||||
final int fieldInfoNameIndexOffset = getConstant("FieldInfo::name_index_offset", Integer.class);
|
|
||||||
final int fieldInfoSignatureIndexOffset = getConstant("FieldInfo::signature_index_offset", Integer.class);
|
|
||||||
final int fieldInfoConstantValueIndexOffset = getConstant("FieldInfo::initval_index_offset", Integer.class);
|
|
||||||
final int fieldInfoLowPackedOffset = getConstant("FieldInfo::low_packed_offset", Integer.class);
|
|
||||||
final int fieldInfoHighPackedOffset = getConstant("FieldInfo::high_packed_offset", Integer.class);
|
|
||||||
final int fieldInfoFieldSlots = getConstant("FieldInfo::field_slots", Integer.class);
|
|
||||||
|
|
||||||
final int fieldInfoTagSize = getConstant("FIELDINFO_TAG_SIZE", Integer.class);
|
|
||||||
|
|
||||||
final int jvmAccHasFinalizer = getConstant("JVM_ACC_HAS_FINALIZER", Integer.class);
|
final int jvmAccHasFinalizer = getConstant("JVM_ACC_HAS_FINALIZER", Integer.class);
|
||||||
final int jvmAccFieldInternal = getConstant("JVM_ACC_FIELD_INTERNAL", Integer.class);
|
final int jvmFieldFlagInternalShift = getConstant("FieldInfo::FieldFlags::_ff_injected", Integer.class);
|
||||||
final int jvmAccFieldStable = getConstant("JVM_ACC_FIELD_STABLE", Integer.class);
|
final int jvmFieldFlagStableShift = getConstant("FieldInfo::FieldFlags::_ff_stable", Integer.class);
|
||||||
final int jvmAccFieldHasGenericSignature = getConstant("JVM_ACC_FIELD_HAS_GENERIC_SIGNATURE", Integer.class);
|
|
||||||
final int jvmAccIsCloneableFast = getConstant("JVM_ACC_IS_CLONEABLE_FAST", Integer.class);
|
final int jvmAccIsCloneableFast = getConstant("JVM_ACC_IS_CLONEABLE_FAST", Integer.class);
|
||||||
|
|
||||||
// These modifiers are not public in Modifier so we get them via vmStructs.
|
// These modifiers are not public in Modifier so we get them via vmStructs.
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2009, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -51,12 +51,12 @@ TEST_VM(InstanceKlass, class_loader_printer) {
|
|||||||
stringStream st;
|
stringStream st;
|
||||||
loader->print_on(&st);
|
loader->print_on(&st);
|
||||||
// See if injected loader_data field is printed in string
|
// See if injected loader_data field is printed in string
|
||||||
ASSERT_TRUE(strstr(st.as_string(), "internal 'loader_data'") != NULL) << "Must contain internal fields";
|
ASSERT_TRUE(strstr(st.as_string(), "injected 'loader_data'") != NULL) << "Must contain injected fields";
|
||||||
st.reset();
|
st.reset();
|
||||||
// See if mirror injected fields are printed.
|
// See if mirror injected fields are printed.
|
||||||
oop mirror = vmClasses::ClassLoader_klass()->java_mirror();
|
oop mirror = vmClasses::ClassLoader_klass()->java_mirror();
|
||||||
mirror->print_on(&st);
|
mirror->print_on(&st);
|
||||||
ASSERT_TRUE(strstr(st.as_string(), "internal 'protection_domain'") != NULL) << "Must contain internal fields";
|
ASSERT_TRUE(strstr(st.as_string(), "injected 'protection_domain'") != NULL) << "Must contain injected fields";
|
||||||
// We should test other printing functions too.
|
// We should test other printing functions too.
|
||||||
#ifndef PRODUCT
|
#ifndef PRODUCT
|
||||||
st.reset();
|
st.reset();
|
||||||
|
@ -27,8 +27,8 @@ import jdk.vm.ci.meta.JavaType;
|
|||||||
import jdk.vm.ci.meta.ResolvedJavaField;
|
import jdk.vm.ci.meta.ResolvedJavaField;
|
||||||
|
|
||||||
public class HotSpotResolvedJavaFieldHelper {
|
public class HotSpotResolvedJavaFieldHelper {
|
||||||
public static ResolvedJavaField createField(HotSpotResolvedObjectTypeImpl holder, JavaType type, int offset, int modifiers, int index) {
|
public static ResolvedJavaField createField(HotSpotResolvedObjectTypeImpl holder, JavaType type, int offset, int modifiers, int internalModifiers, int index) {
|
||||||
return new HotSpotResolvedJavaFieldImpl(holder, type, offset, modifiers, index);
|
return new HotSpotResolvedJavaFieldImpl(holder, type, offset, modifiers, internalModifiers, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int getIndex(ResolvedJavaField field) {
|
public static int getIndex(ResolvedJavaField field) {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -104,7 +104,7 @@ public class ResolveFieldInPoolTest {
|
|||||||
cached = "cached ";
|
cached = "cached ";
|
||||||
}
|
}
|
||||||
for (int j = 0; j < entry.opcodes.length; j++) {
|
for (int j = 0; j < entry.opcodes.length; j++) {
|
||||||
int[] info = new int[3];
|
int[] info = new int[4];
|
||||||
HotSpotResolvedObjectType fieldToVerify
|
HotSpotResolvedObjectType fieldToVerify
|
||||||
= CompilerToVMHelper.resolveFieldInPool(constantPoolCTVM,
|
= CompilerToVMHelper.resolveFieldInPool(constantPoolCTVM,
|
||||||
index,
|
index,
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -22,14 +22,6 @@
|
|||||||
*/
|
*/
|
||||||
package jdk.vm.ci.hotspot.test;
|
package jdk.vm.ci.hotspot.test;
|
||||||
|
|
||||||
import static java.lang.reflect.Modifier.FINAL;
|
|
||||||
import static java.lang.reflect.Modifier.PRIVATE;
|
|
||||||
import static java.lang.reflect.Modifier.PROTECTED;
|
|
||||||
import static java.lang.reflect.Modifier.PUBLIC;
|
|
||||||
import static java.lang.reflect.Modifier.STATIC;
|
|
||||||
import static java.lang.reflect.Modifier.TRANSIENT;
|
|
||||||
import static java.lang.reflect.Modifier.VOLATILE;
|
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
@ -38,8 +30,8 @@ import org.junit.Assert;
|
|||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime;
|
import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime;
|
||||||
|
import jdk.vm.ci.hotspot.HotSpotModifiers;
|
||||||
import jdk.vm.ci.hotspot.HotSpotResolvedJavaField;
|
import jdk.vm.ci.hotspot.HotSpotResolvedJavaField;
|
||||||
import jdk.vm.ci.hotspot.HotSpotVMConfigAccess;
|
|
||||||
import jdk.vm.ci.meta.JavaType;
|
import jdk.vm.ci.meta.JavaType;
|
||||||
import jdk.vm.ci.meta.MetaAccessProvider;
|
import jdk.vm.ci.meta.MetaAccessProvider;
|
||||||
import jdk.vm.ci.meta.ResolvedJavaField;
|
import jdk.vm.ci.meta.ResolvedJavaField;
|
||||||
@ -63,35 +55,28 @@ public class HotSpotResolvedJavaFieldTest {
|
|||||||
|
|
||||||
private static final Method createFieldMethod;
|
private static final Method createFieldMethod;
|
||||||
private static final Field indexField;
|
private static final Field indexField;
|
||||||
|
private static final Field internalFlagsField;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
Method m = null;
|
Method m = null;
|
||||||
Field f = null;
|
Field f1 = null;
|
||||||
|
Field f2 = null;
|
||||||
try {
|
try {
|
||||||
Class<?> typeImpl = Class.forName("jdk.vm.ci.hotspot.HotSpotResolvedObjectTypeImpl");
|
Class<?> typeImpl = Class.forName("jdk.vm.ci.hotspot.HotSpotResolvedObjectTypeImpl");
|
||||||
m = typeImpl.getDeclaredMethod("createField", JavaType.class, int.class, int.class, int.class);
|
m = typeImpl.getDeclaredMethod("createField", JavaType.class, int.class, int.class, int.class, int.class);
|
||||||
m.setAccessible(true);
|
m.setAccessible(true);
|
||||||
Class<?> fieldImpl = Class.forName("jdk.vm.ci.hotspot.HotSpotResolvedJavaFieldImpl");
|
Class<?> fieldImpl = Class.forName("jdk.vm.ci.hotspot.HotSpotResolvedJavaFieldImpl");
|
||||||
f = fieldImpl.getDeclaredField("index");
|
f1 = fieldImpl.getDeclaredField("index");
|
||||||
f.setAccessible(true);
|
f1.setAccessible(true);
|
||||||
|
f2 = fieldImpl.getDeclaredField("internalFlags");
|
||||||
|
f2.setAccessible(true);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new AssertionError(e);
|
throw new AssertionError(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
createFieldMethod = m;
|
createFieldMethod = m;
|
||||||
indexField = f;
|
indexField = f1;
|
||||||
}
|
internalFlagsField = f2;
|
||||||
|
|
||||||
/**
|
|
||||||
* Same as {@code HotSpotModifiers.jvmFieldModifiers()} but works when using a JVMCI version
|
|
||||||
* prior to the introduction of that method.
|
|
||||||
*/
|
|
||||||
private int jvmFieldModifiers() {
|
|
||||||
HotSpotJVMCIRuntime runtime = runtime();
|
|
||||||
HotSpotVMConfigAccess access = new HotSpotVMConfigAccess(runtime.getConfigStore());
|
|
||||||
int accEnum = access.getConstant("JVM_ACC_ENUM", Integer.class, 0x4000);
|
|
||||||
int accSynthetic = access.getConstant("JVM_ACC_SYNTHETIC", Integer.class, 0x1000);
|
|
||||||
return PUBLIC | PRIVATE | PROTECTED | STATIC | FINAL | VOLATILE | TRANSIENT | accEnum | accSynthetic;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
HotSpotJVMCIRuntime runtime() {
|
HotSpotJVMCIRuntime runtime() {
|
||||||
@ -113,14 +98,14 @@ public class HotSpotResolvedJavaFieldTest {
|
|||||||
ResolvedJavaType type = getMetaAccess().lookupJavaType(c);
|
ResolvedJavaType type = getMetaAccess().lookupJavaType(c);
|
||||||
for (ResolvedJavaField field : type.getInstanceFields(false)) {
|
for (ResolvedJavaField field : type.getInstanceFields(false)) {
|
||||||
if (field.isInternal()) {
|
if (field.isInternal()) {
|
||||||
Assert.assertEquals(0, ~jvmFieldModifiers() & field.getModifiers());
|
Assert.assertEquals(0, ~HotSpotModifiers.jvmFieldModifiers() & field.getModifiers());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests that {@code HotSpotResolvedObjectTypeImpl#createField(String, JavaType, long, int)}
|
* Tests that {@code HotSpotResolvedObjectTypeImpl#createField(String, JavaType, int, int)}
|
||||||
* always returns an {@linkplain ResolvedJavaField#equals(Object) equivalent} object for an
|
* always returns an {@linkplain ResolvedJavaField#equals(Object) equivalent} object for an
|
||||||
* internal field.
|
* internal field.
|
||||||
*
|
*
|
||||||
@ -136,7 +121,8 @@ public class HotSpotResolvedJavaFieldTest {
|
|||||||
if (field.isInternal()) {
|
if (field.isInternal()) {
|
||||||
HotSpotResolvedJavaField expected = (HotSpotResolvedJavaField) field;
|
HotSpotResolvedJavaField expected = (HotSpotResolvedJavaField) field;
|
||||||
int index = indexField.getInt(expected);
|
int index = indexField.getInt(expected);
|
||||||
ResolvedJavaField actual = (ResolvedJavaField) createFieldMethod.invoke(type, expected.getType(), expected.getOffset(), expected.getModifiers(), index);
|
int internalFlags = internalFlagsField.getInt(expected);
|
||||||
|
ResolvedJavaField actual = (ResolvedJavaField) createFieldMethod.invoke(type, expected.getType(), expected.getOffset(), expected.getModifiers(), internalFlags, index);
|
||||||
Assert.assertEquals(expected, actual);
|
Assert.assertEquals(expected, actual);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -48,7 +48,7 @@ public class TestHotSpotResolvedJavaField {
|
|||||||
int max = Character.MAX_VALUE;
|
int max = Character.MAX_VALUE;
|
||||||
int[] valid = {0, 1, max - 1, max};
|
int[] valid = {0, 1, max - 1, max};
|
||||||
for (int index : valid) {
|
for (int index : valid) {
|
||||||
ResolvedJavaField field = HotSpotResolvedJavaFieldHelper.createField(null, null, 0, 0, index);
|
ResolvedJavaField field = HotSpotResolvedJavaFieldHelper.createField(null, null, 0, 0, 0, index);
|
||||||
Assert.assertEquals(HotSpotResolvedJavaFieldHelper.getIndex(field), index);
|
Assert.assertEquals(HotSpotResolvedJavaFieldHelper.getIndex(field), index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -59,7 +59,7 @@ public class TestHotSpotResolvedJavaField {
|
|||||||
int max = Integer.MAX_VALUE;
|
int max = Integer.MAX_VALUE;
|
||||||
int[] valid = {min, min + 1, -2, 0, 1, max - 1, max};
|
int[] valid = {min, min + 1, -2, 0, 1, max - 1, max};
|
||||||
for (int offset : valid) {
|
for (int offset : valid) {
|
||||||
ResolvedJavaField field = HotSpotResolvedJavaFieldHelper.createField(null, null, offset, 0, 0);
|
ResolvedJavaField field = HotSpotResolvedJavaFieldHelper.createField(null, null, offset, 0, 0, 0);
|
||||||
Assert.assertEquals(field.getOffset(), offset);
|
Assert.assertEquals(field.getOffset(), offset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2012, 2022, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2012, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
Loading…
x
Reference in New Issue
Block a user