Skip to content

Commit

Permalink
8288064: Class initialization locking
Browse files Browse the repository at this point in the history
Reviewed-by: rehn, vlivanov
  • Loading branch information
coleenp committed Jun 16, 2022
1 parent 3d12c02 commit cf4a496
Show file tree
Hide file tree
Showing 14 changed files with 140 additions and 172 deletions.
28 changes: 0 additions & 28 deletions src/hotspot/share/classfile/javaClasses.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -792,7 +792,6 @@ int java_lang_Class::_class_loader_offset;
int java_lang_Class::_module_offset;
int java_lang_Class::_protection_domain_offset;
int java_lang_Class::_component_mirror_offset;
int java_lang_Class::_init_lock_offset;
int java_lang_Class::_signers_offset;
int java_lang_Class::_name_offset;
int java_lang_Class::_source_file_offset;
Expand Down Expand Up @@ -926,12 +925,6 @@ void java_lang_Class::initialize_mirror_fields(Klass* k,
Handle protection_domain,
Handle classData,
TRAPS) {
// Allocate a simple java object for a lock.
// This needs to be a java object because during class initialization
// it can be held across a java call.
typeArrayOop r = oopFactory::new_typeArray(T_INT, 0, CHECK);
set_init_lock(mirror(), r);

// Set protection domain also
set_protection_domain(mirror(), protection_domain());

Expand Down Expand Up @@ -1270,8 +1263,6 @@ oop java_lang_Class::process_archived_mirror(Klass* k, oop mirror,
// Reset local static fields in the mirror
InstanceKlass::cast(k)->do_local_static_fields(&reset);

set_init_lock(archived_mirror, NULL);

set_protection_domain(archived_mirror, NULL);
set_signers(archived_mirror, NULL);
set_source_file(archived_mirror, NULL);
Expand Down Expand Up @@ -1353,10 +1344,6 @@ bool java_lang_Class::restore_archived_mirror(Klass *k,
if (!k->is_array_klass()) {
// - local static final fields with initial values were initialized at dump time

// create the init_lock
typeArrayOop r = oopFactory::new_typeArray(T_INT, 0, CHECK_(false));
set_init_lock(mirror(), r);

if (protection_domain.not_null()) {
set_protection_domain(mirror(), protection_domain());
}
Expand Down Expand Up @@ -1421,15 +1408,6 @@ oop java_lang_Class::component_mirror(oop java_class) {
return java_class->obj_field(_component_mirror_offset);
}

oop java_lang_Class::init_lock(oop java_class) {
assert(_init_lock_offset != 0, "must be set");
return java_class->obj_field(_init_lock_offset);
}
void java_lang_Class::set_init_lock(oop java_class, oop init_lock) {
assert(_init_lock_offset != 0, "must be set");
java_class->obj_field_put(_init_lock_offset, init_lock);
}

objArrayOop java_lang_Class::signers(oop java_class) {
assert(_signers_offset != 0, "must be set");
return (objArrayOop)java_class->obj_field(_signers_offset);
Expand Down Expand Up @@ -1641,18 +1619,12 @@ void java_lang_Class::compute_offsets() {
InstanceKlass* k = vmClasses::Class_klass();
CLASS_FIELDS_DO(FIELD_COMPUTE_OFFSET);

// Init lock is a C union with component_mirror. Only instanceKlass mirrors have
// init_lock and only ArrayKlass mirrors have component_mirror. Since both are oops
// GC treats them the same.
_init_lock_offset = _component_mirror_offset;

CLASS_INJECTED_FIELDS(INJECTED_FIELD_COMPUTE_OFFSET);
}

#if INCLUDE_CDS
void java_lang_Class::serialize_offsets(SerializeClosure* f) {
f->do_bool(&_offsets_computed);
f->do_u4((u4*)&_init_lock_offset);

CLASS_FIELDS_DO(FIELD_SERIALIZE_OFFSET);

Expand Down
6 changes: 0 additions & 6 deletions src/hotspot/share/classfile/javaClasses.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,6 @@ class java_lang_Class : AllStatic {
static int _static_oop_field_count_offset;

static int _protection_domain_offset;
static int _init_lock_offset;
static int _signers_offset;
static int _class_loader_offset;
static int _module_offset;
Expand All @@ -300,7 +299,6 @@ class java_lang_Class : AllStatic {
static GrowableArray<Klass*>* _fixup_mirror_list;
static GrowableArray<Klass*>* _fixup_module_field_list;

static void set_init_lock(oop java_class, oop init_lock);
static void set_protection_domain(oop java_class, oop protection_domain);
static void set_class_loader(oop java_class, oop class_loader);
static void set_component_mirror(oop java_class, oop comp_mirror);
Expand Down Expand Up @@ -356,10 +354,6 @@ class java_lang_Class : AllStatic {

// Support for embedded per-class oops
static oop protection_domain(oop java_class);
static oop init_lock(oop java_class);
static void clear_init_lock(oop java_class) {
set_init_lock(java_class, NULL);
}
static oop component_mirror(oop java_class);
static objArrayOop signers(oop java_class);
static void set_signers(oop java_class, objArrayOop signers);
Expand Down
2 changes: 1 addition & 1 deletion src/hotspot/share/interpreter/linkResolver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1774,7 +1774,7 @@ void LinkResolver::resolve_invokedynamic(CallInfo& result, const constantPoolHan
// the interpreter or runtime performs a serialized check of
// the relevant CPCE::f1 field. This is done by the caller
// of this method, via CPCE::set_dynamic_call, which uses
// an ObjectLocker to do the final serialization of updates
// a lock to do the final serialization of updates
// to CPCE state, including f1.

// Log dynamic info to CDS classlist.
Expand Down
2 changes: 1 addition & 1 deletion src/hotspot/share/jvmci/vmStructs_jvmci.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@
\
nonstatic_field(InstanceKlass, _fields, Array<u2>*) \
nonstatic_field(InstanceKlass, _constants, ConstantPool*) \
nonstatic_field(InstanceKlass, _init_state, u1) \
nonstatic_field(InstanceKlass, _init_state, InstanceKlass::ClassState) \
nonstatic_field(InstanceKlass, _init_thread, Thread*) \
nonstatic_field(InstanceKlass, _misc_flags, u2) \
nonstatic_field(InstanceKlass, _annotations, Annotations*) \
Expand Down
22 changes: 5 additions & 17 deletions src/hotspot/share/oops/cpCache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,7 @@ void ConstantPoolCacheEntry::set_direct_or_vtable_call(Bytecodes::Code invoke_co
}
if (invoke_code == Bytecodes::_invokestatic) {
assert(method->method_holder()->is_initialized() ||
method->method_holder()->is_reentrant_initialization(Thread::current()),
method->method_holder()->is_init_thread(Thread::current()),
"invalid class initialization state for invoke_static");

if (!VM_Version::supports_fast_class_init_checks() && method->needs_clinit_barrier()) {
Expand Down Expand Up @@ -373,15 +373,9 @@ void ConstantPoolCacheEntry::set_method_handle_common(const constantPoolHandle&
// A losing writer waits on the lock until the winner writes f1 and leaves
// the lock, so that when the losing writer returns, he can use the linked
// cache entry.
// Lock fields to write
MutexLocker ml(cpool->pool_holder()->init_monitor());

JavaThread* current = JavaThread::current();
objArrayHandle resolved_references(current, cpool->resolved_references());
// Use the resolved_references() lock for this cpCache entry.
// resolved_references are created for all classes with Invokedynamic, MethodHandle
// or MethodType constant pool cache entries.
assert(resolved_references() != NULL,
"a resolved_references array should have been created for this class");
ObjectLocker ol(resolved_references, current);
if (!is_f1_null()) {
return;
}
Expand Down Expand Up @@ -453,6 +447,7 @@ void ConstantPoolCacheEntry::set_method_handle_common(const constantPoolHandle&
// Store appendix, if any.
if (has_appendix) {
const int appendix_index = f2_as_index();
objArrayOop resolved_references = cpool->resolved_references();
assert(appendix_index >= 0 && appendix_index < resolved_references->length(), "oob");
assert(resolved_references->obj_at(appendix_index) == NULL, "init just once");
resolved_references->obj_at_put(appendix_index, appendix());
Expand Down Expand Up @@ -480,14 +475,7 @@ bool ConstantPoolCacheEntry::save_and_throw_indy_exc(
assert(PENDING_EXCEPTION->is_a(vmClasses::LinkageError_klass()),
"No LinkageError exception");

// Use the resolved_references() lock for this cpCache entry.
// resolved_references are created for all classes with Invokedynamic, MethodHandle
// or MethodType constant pool cache entries.
JavaThread* current = THREAD;
objArrayHandle resolved_references(current, cpool->resolved_references());
assert(resolved_references() != NULL,
"a resolved_references array should have been created for this class");
ObjectLocker ol(resolved_references, current);
MutexLocker ml(THREAD, cpool->pool_holder()->init_monitor());

// if f1 is not null or the indy_resolution_failed flag is set then another
// thread either succeeded in resolving the method or got a LinkageError
Expand Down

1 comment on commit cf4a496

@openjdk-notifier
Copy link

Choose a reason for hiding this comment

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

Please sign in to comment.