8306123: Move InstanceKlass writeable flags

Reviewed-by: iklam, fparain
This commit is contained in:
Coleen Phillimore 2023-04-19 14:06:02 +00:00
parent 1a41e12c22
commit ddb86469e0
6 changed files with 80 additions and 50 deletions

View File

@ -223,15 +223,11 @@ class InstanceKlass: public Klass {
volatile u2 _idnum_allocated_count; // JNI/JVMTI: increments with the addition of methods, old ids don't change
// _is_marked_dependent can be set concurrently, thus cannot be part of the
// _misc_flags right now.
bool _is_marked_dependent; // used for marking during flushing and deoptimization
volatile ClassState _init_state; // state of class
u1 _reference_type; // reference type
// State is set while executing, eventually atomically to not disturb other state
// State is set either at parse time or while executing, atomically to not disturb other state
InstanceKlassFlags _misc_flags;
Monitor* _init_monitor; // mutual exclusion to _init_state and _init_thread.
@ -531,8 +527,8 @@ public:
void set_should_verify_class(bool value) { _misc_flags.set_should_verify_class(value); }
// marking
bool is_marked_dependent() const { return _is_marked_dependent; }
void set_is_marked_dependent(bool value) { _is_marked_dependent = value; }
bool is_marked_dependent() const { return _misc_flags.is_marked_dependent(); }
void set_is_marked_dependent(bool value) { _misc_flags.set_is_marked_dependent(value); }
// initialization (virtuals from Klass)
bool should_be_initialized() const; // means that initialize should be called
@ -681,16 +677,8 @@ public:
// Redefinition locking. Class can only be redefined by one thread at a time.
// The flag is in access_flags so that it can be set and reset using atomic
// operations, and not be reset by other misc_flag settings.
bool is_being_redefined() const {
return _access_flags.is_being_redefined();
}
void set_is_being_redefined(bool value) {
if (value) {
_access_flags.set_is_being_redefined();
} else {
_access_flags.clear_is_being_redefined();
}
}
bool is_being_redefined() const { return _misc_flags.is_being_redefined(); }
void set_is_being_redefined(bool value) { _misc_flags.set_is_being_redefined(value); }
// RedefineClasses() support for previous versions:
void add_previous_version(InstanceKlass* ik, int emcp_method_count);
@ -716,13 +704,8 @@ public:
bool is_scratch_class() const { return _misc_flags.is_scratch_class(); }
void set_is_scratch_class() { _misc_flags.set_is_scratch_class(true); }
bool has_resolved_methods() const {
return _access_flags.has_resolved_methods();
}
void set_has_resolved_methods() {
_access_flags.set_has_resolved_methods();
}
bool has_resolved_methods() const { return _misc_flags.has_resolved_methods(); }
void set_has_resolved_methods() { _misc_flags.set_has_resolved_methods(true); }
public:
#if INCLUDE_JVMTI

View File

@ -26,9 +26,31 @@
#include "classfile/classLoader.hpp"
#include "classfile/classLoaderData.inline.hpp"
#include "oops/instanceKlassFlags.hpp"
#include "runtime/atomic.hpp"
#include "runtime/safepoint.hpp"
#include "utilities/macros.hpp"
// This can be removed for the atomic bitset functions, when available.
void InstanceKlassFlags::atomic_set_bits(u1 bits) {
// Atomically update the status with the bits given
u1 old_status, new_status, f;
do {
old_status = _status;
new_status = old_status | bits;
f = Atomic::cmpxchg(&_status, old_status, new_status);
} while(f != old_status);
}
void InstanceKlassFlags::atomic_clear_bits(u1 bits) {
// Atomically update the status with the bits given
u1 old_status, new_status, f;
do {
old_status = _status;
new_status = old_status & ~bits;
f = Atomic::cmpxchg(&_status, old_status, new_status);
} while(f != old_status);
}
#if INCLUDE_CDS
void InstanceKlassFlags::set_shared_class_loader_type(s2 loader_type) {
switch (loader_type) {

View File

@ -27,6 +27,12 @@
class ClassLoaderData;
// The InstanceKlassFlags class contains the parse-time and writeable flags associated with
// an InstanceKlass, and their associated accessors.
// _flags are parse-time and constant in the InstanceKlass after that. _status are set at runtime and
// require atomic access.
// These flags are JVM internal and not part of the AccessFlags classfile specification.
class InstanceKlassFlags {
friend class VMStructs;
friend class JVMCIVMStructs;
@ -35,18 +41,15 @@ class InstanceKlassFlags {
flag(rewritten , 1 << 0) /* methods rewritten. */ \
flag(has_nonstatic_fields , 1 << 1) /* for sizing with UseCompressedOops */ \
flag(should_verify_class , 1 << 2) /* allow caching of preverification */ \
flag(unused , 1 << 3) /* not currently used */ \
flag(is_contended , 1 << 4) /* marked with contended annotation */ \
flag(has_nonstatic_concrete_methods , 1 << 5) /* class/superclass/implemented interfaces has non-static, concrete methods */ \
flag(declares_nonstatic_concrete_methods, 1 << 6) /* directly declares non-static, concrete methods */ \
flag(has_been_redefined , 1 << 7) /* class has been redefined */ \
flag(shared_loading_failed , 1 << 8) /* class has been loaded from shared archive */ \
flag(is_scratch_class , 1 << 9) /* class is the redefined scratch class */ \
flag(is_shared_boot_class , 1 << 10) /* defining class loader is boot class loader */ \
flag(is_shared_platform_class , 1 << 11) /* defining class loader is platform class loader */ \
flag(is_shared_app_class , 1 << 12) /* defining class loader is app class loader */ \
flag(has_contended_annotations , 1 << 13) /* has @Contended annotation */ \
flag(has_localvariable_table , 1 << 14) /* has localvariable information */
flag(is_contended , 1 << 3) /* marked with contended annotation */ \
flag(has_nonstatic_concrete_methods , 1 << 4) /* class/superclass/implemented interfaces has non-static, concrete methods */ \
flag(declares_nonstatic_concrete_methods, 1 << 5) /* directly declares non-static, concrete methods */ \
flag(shared_loading_failed , 1 << 6) /* class has been loaded from shared archive */ \
flag(is_shared_boot_class , 1 << 7) /* defining class loader is boot class loader */ \
flag(is_shared_platform_class , 1 << 8) /* defining class loader is platform class loader */ \
flag(is_shared_app_class , 1 << 9) /* defining class loader is app class loader */ \
flag(has_contended_annotations , 1 << 10) /* has @Contended annotation */ \
flag(has_localvariable_table , 1 << 11) /* has localvariable information */
#define IK_FLAGS_ENUM_NAME(name, value) _misc_##name = value,
enum {
@ -54,6 +57,19 @@ class InstanceKlassFlags {
};
#undef IK_FLAGS_ENUM_NAME
#define IK_STATUS_DO(status) \
status(is_being_redefined , 1 << 0) /* True if the klass is being redefined */ \
status(has_resolved_methods , 1 << 1) /* True if the klass has resolved MethodHandle methods */ \
status(has_been_redefined , 1 << 2) /* class has been redefined */ \
status(is_scratch_class , 1 << 3) /* class is the redefined scratch class */ \
status(is_marked_dependent , 1 << 4) /* class is the redefined scratch class */
#define IK_STATUS_ENUM_NAME(name, value) _misc_##name = value,
enum {
IK_STATUS_DO(IK_STATUS_ENUM_NAME)
};
#undef IK_STATUS_ENUM_NAME
u2 shared_loader_type_bits() const {
return _misc_is_shared_boot_class|_misc_is_shared_platform_class|_misc_is_shared_app_class;
}
@ -61,6 +77,9 @@ class InstanceKlassFlags {
// These flags are write-once before the class is published and then read-only so don't require atomic updates.
u2 _flags;
// These flags are written during execution so require atomic stores
u1 _status;
public:
InstanceKlassFlags() : _flags(0) {}
@ -87,6 +106,26 @@ class InstanceKlassFlags {
void assign_class_loader_type(const ClassLoaderData* cld);
void assert_is_safe(bool set) NOT_DEBUG_RETURN;
// Create getters and setters for the status values.
#define IK_STATUS_GET(name, ignore) \
bool name() const { return (_status & _misc_##name) != 0; }
IK_STATUS_DO(IK_STATUS_GET)
#undef IK_STATUS_GET
#define IK_STATUS_SET(name, ignore) \
void set_##name(bool b) { \
if (b) { \
atomic_set_bits(_misc_##name); \
} else { \
atomic_clear_bits(_misc_##name); \
} \
}
IK_STATUS_DO(IK_STATUS_SET)
#undef IK_STATUS_SET
void atomic_set_bits(u1 bits);
void atomic_clear_bits(u1 bits);
};
#endif // SHARE_OOPS_INSTANCEKLASSFLAGS_HPP

View File

@ -236,7 +236,6 @@
nonstatic_field(InstanceKlass, _static_field_size, int) \
nonstatic_field(InstanceKlass, _static_oop_field_count, u2) \
nonstatic_field(InstanceKlass, _nonstatic_oop_map_size, int) \
nonstatic_field(InstanceKlass, _is_marked_dependent, bool) \
volatile_nonstatic_field(InstanceKlass, _init_state, InstanceKlass::ClassState) \
volatile_nonstatic_field(InstanceKlass, _init_thread, JavaThread*) \
nonstatic_field(InstanceKlass, _itable_len, int) \

View File

@ -68,8 +68,6 @@ enum {
JVM_ACC_HAS_FINAL_METHOD = 0x01000000, // True if klass has final method
JVM_ACC_IS_HIDDEN_CLASS = 0x04000000, // True if klass is hidden
JVM_ACC_IS_VALUE_BASED_CLASS = 0x08000000, // True if klass is marked as a ValueBased class
JVM_ACC_IS_BEING_REDEFINED = 0x00100000, // True if the klass is being redefined.
JVM_ACC_HAS_RESOLVED_METHODS = 0x00200000, // True if the klass has resolved methods
// Method* flags
JVM_ACC_HAS_LOCAL_VARIABLE_TABLE= 0x00400000,
@ -133,13 +131,6 @@ class AccessFlags {
void set_has_localvariable_table() { atomic_set_bits(JVM_ACC_HAS_LOCAL_VARIABLE_TABLE); }
void clear_has_localvariable_table() { atomic_clear_bits(JVM_ACC_HAS_LOCAL_VARIABLE_TABLE); }
bool is_being_redefined() const { return (_flags & JVM_ACC_IS_BEING_REDEFINED) != 0; }
void set_is_being_redefined() { atomic_set_bits(JVM_ACC_IS_BEING_REDEFINED); }
void clear_is_being_redefined() { atomic_clear_bits(JVM_ACC_IS_BEING_REDEFINED); }
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); }
bool on_stack() const { return (_flags & JVM_ACC_ON_STACK) != 0; }
// get .class file flags

View File

@ -80,7 +80,6 @@ public class InstanceKlass extends Klass {
staticFieldSize = new CIntField(type.getCIntegerField("_static_field_size"), 0);
staticOopFieldCount = new CIntField(type.getCIntegerField("_static_oop_field_count"), 0);
nonstaticOopMapSize = new CIntField(type.getCIntegerField("_nonstatic_oop_map_size"), 0);
isMarkedDependent = new CIntField(type.getCIntegerField("_is_marked_dependent"), 0);
initState = new CIntField(type.getCIntegerField("_init_state"), 0);
itableLen = new CIntField(type.getCIntegerField("_itable_len"), 0);
if (VM.getVM().isJvmtiSupported()) {
@ -145,7 +144,6 @@ public class InstanceKlass extends Klass {
private static CIntField staticFieldSize;
private static CIntField staticOopFieldCount;
private static CIntField nonstaticOopMapSize;
private static CIntField isMarkedDependent;
private static CIntField initState;
private static CIntField itableLen;
private static AddressField breakpoints;
@ -373,7 +371,6 @@ public class InstanceKlass extends Klass {
public long getNonstaticFieldSize() { return nonstaticFieldSize.getValue(this); }
public long getStaticOopFieldCount() { return staticOopFieldCount.getValue(this); }
public long getNonstaticOopMapSize() { return nonstaticOopMapSize.getValue(this); }
public boolean getIsMarkedDependent() { return isMarkedDependent.getValue(this) != 0; }
public long getItableLen() { return itableLen.getValue(this); }
public long majorVersion() { return getConstants().majorVersion(); }
public long minorVersion() { return getConstants().minorVersion(); }
@ -571,7 +568,6 @@ public class InstanceKlass extends Klass {
visitor.doCInt(staticFieldSize, true);
visitor.doCInt(staticOopFieldCount, true);
visitor.doCInt(nonstaticOopMapSize, true);
visitor.doCInt(isMarkedDependent, true);
visitor.doCInt(initState, true);
visitor.doCInt(itableLen, true);
}