Skip to content

Commit b3bf31a

Browse files
coleenpplummercj
andcommitted
8333542: Breakpoint in parallel code does not work
Co-authored-by: Chris Plummer <[email protected]> Reviewed-by: dholmes, vlivanov
1 parent 86b0cf2 commit b3bf31a

File tree

16 files changed

+387
-177
lines changed

16 files changed

+387
-177
lines changed

src/hotspot/share/classfile/javaClasses.cpp

+26
Original file line numberDiff line numberDiff line change
@@ -788,6 +788,7 @@ int java_lang_Class::_class_loader_offset;
788788
int java_lang_Class::_module_offset;
789789
int java_lang_Class::_protection_domain_offset;
790790
int java_lang_Class::_component_mirror_offset;
791+
int java_lang_Class::_init_lock_offset;
791792
int java_lang_Class::_signers_offset;
792793
int java_lang_Class::_name_offset;
793794
int java_lang_Class::_source_file_offset;
@@ -911,6 +912,12 @@ void java_lang_Class::initialize_mirror_fields(Klass* k,
911912
Handle protection_domain,
912913
Handle classData,
913914
TRAPS) {
915+
// Allocate a simple java object for a lock.
916+
// This needs to be a java object because during class initialization
917+
// it can be held across a java call.
918+
typeArrayOop r = oopFactory::new_typeArray(T_INT, 0, CHECK);
919+
set_init_lock(mirror(), r);
920+
914921
// Set protection domain also
915922
set_protection_domain(mirror(), protection_domain());
916923

@@ -1132,6 +1139,10 @@ bool java_lang_Class::restore_archived_mirror(Klass *k,
11321139
if (!k->is_array_klass()) {
11331140
// - local static final fields with initial values were initialized at dump time
11341141

1142+
// create the init_lock
1143+
typeArrayOop r = oopFactory::new_typeArray(T_INT, 0, CHECK_(false));
1144+
set_init_lock(mirror(), r);
1145+
11351146
if (protection_domain.not_null()) {
11361147
set_protection_domain(mirror(), protection_domain());
11371148
}
@@ -1196,6 +1207,15 @@ oop java_lang_Class::component_mirror(oop java_class) {
11961207
return java_class->obj_field(_component_mirror_offset);
11971208
}
11981209

1210+
oop java_lang_Class::init_lock(oop java_class) {
1211+
assert(_init_lock_offset != 0, "must be set");
1212+
return java_class->obj_field(_init_lock_offset);
1213+
}
1214+
void java_lang_Class::set_init_lock(oop java_class, oop init_lock) {
1215+
assert(_init_lock_offset != 0, "must be set");
1216+
java_class->obj_field_put(_init_lock_offset, init_lock);
1217+
}
1218+
11991219
objArrayOop java_lang_Class::signers(oop java_class) {
12001220
assert(_signers_offset != 0, "must be set");
12011221
return (objArrayOop)java_class->obj_field(_signers_offset);
@@ -1415,12 +1435,18 @@ void java_lang_Class::compute_offsets() {
14151435
InstanceKlass* k = vmClasses::Class_klass();
14161436
CLASS_FIELDS_DO(FIELD_COMPUTE_OFFSET);
14171437

1438+
// Init lock is a C union with component_mirror. Only instanceKlass mirrors have
1439+
// init_lock and only ArrayKlass mirrors have component_mirror. Since both are oops
1440+
// GC treats them the same.
1441+
_init_lock_offset = _component_mirror_offset;
1442+
14181443
CLASS_INJECTED_FIELDS(INJECTED_FIELD_COMPUTE_OFFSET);
14191444
}
14201445

14211446
#if INCLUDE_CDS
14221447
void java_lang_Class::serialize_offsets(SerializeClosure* f) {
14231448
f->do_bool(&_offsets_computed);
1449+
f->do_u4((u4*)&_init_lock_offset);
14241450

14251451
CLASS_FIELDS_DO(FIELD_SERIALIZE_OFFSET);
14261452

src/hotspot/share/classfile/javaClasses.hpp

+7-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -226,6 +226,7 @@ class java_lang_Class : AllStatic {
226226
static int _static_oop_field_count_offset;
227227

228228
static int _protection_domain_offset;
229+
static int _init_lock_offset;
229230
static int _signers_offset;
230231
static int _class_loader_offset;
231232
static int _module_offset;
@@ -240,6 +241,7 @@ class java_lang_Class : AllStatic {
240241
static GrowableArray<Klass*>* _fixup_mirror_list;
241242
static GrowableArray<Klass*>* _fixup_module_field_list;
242243

244+
static void set_init_lock(oop java_class, oop init_lock);
243245
static void set_protection_domain(oop java_class, oop protection_domain);
244246
static void set_class_loader(oop java_class, oop class_loader);
245247
static void set_component_mirror(oop java_class, oop comp_mirror);
@@ -292,6 +294,10 @@ class java_lang_Class : AllStatic {
292294

293295
// Support for embedded per-class oops
294296
static oop protection_domain(oop java_class);
297+
static oop init_lock(oop java_class);
298+
static void clear_init_lock(oop java_class) {
299+
set_init_lock(java_class, nullptr);
300+
}
295301
static oop component_mirror(oop java_class);
296302
static objArrayOop signers(oop java_class);
297303
static void set_signers(oop java_class, objArrayOop signers);

src/hotspot/share/classfile/vmSymbols.hpp

+1
Original file line numberDiff line numberDiff line change
@@ -557,6 +557,7 @@ class SerializeClosure;
557557
template(bool_array_signature, "[Z") \
558558
template(byte_array_signature, "[B") \
559559
template(char_array_signature, "[C") \
560+
template(int_array_signature, "[I") \
560561
template(runnable_signature, "Ljava/lang/Runnable;") \
561562
template(continuation_signature, "Ljdk/internal/vm/Continuation;") \
562563
template(continuationscope_signature, "Ljdk/internal/vm/ContinuationScope;") \

src/hotspot/share/interpreter/linkResolver.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -1824,7 +1824,7 @@ void LinkResolver::resolve_invokedynamic(CallInfo& result, const constantPoolHan
18241824
// the interpreter or runtime performs a serialized check of
18251825
// the relevant ResolvedIndyEntry::method field. This is done by the caller
18261826
// of this method, via CPC::set_dynamic_call, which uses
1827-
// a lock to do the final serialization of updates
1827+
// an ObjectLocker to do the final serialization of updates
18281828
// to ResolvedIndyEntry state, including method.
18291829

18301830
// Log dynamic info to CDS classlist.

src/hotspot/share/oops/cpCache.cpp

+34-11
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@
5656
#include "runtime/atomic.hpp"
5757
#include "runtime/handles.inline.hpp"
5858
#include "runtime/mutexLocker.hpp"
59+
#include "runtime/synchronizer.hpp"
5960
#include "runtime/vm_version.hpp"
6061
#include "utilities/macros.hpp"
6162

@@ -174,7 +175,7 @@ void ConstantPoolCache::set_direct_or_vtable_call(Bytecodes::Code invoke_code,
174175
}
175176
if (invoke_code == Bytecodes::_invokestatic) {
176177
assert(method->method_holder()->is_initialized() ||
177-
method->method_holder()->is_init_thread(JavaThread::current()),
178+
method->method_holder()->is_reentrant_initialization(JavaThread::current()),
178179
"invalid class initialization state for invoke_static");
179180

180181
if (!VM_Version::supports_fast_class_init_checks() && method->needs_clinit_barrier()) {
@@ -269,11 +270,20 @@ ResolvedMethodEntry* ConstantPoolCache::set_method_handle(int method_index, cons
269270
// A losing writer waits on the lock until the winner writes the method and leaves
270271
// the lock, so that when the losing writer returns, he can use the linked
271272
// cache entry.
273+
272274
// Lock fields to write
273275
Bytecodes::Code invoke_code = Bytecodes::_invokehandle;
274-
MutexLocker ml(constant_pool()->pool_holder()->init_monitor());
275-
ResolvedMethodEntry* method_entry = resolved_method_entry_at(method_index);
276276

277+
JavaThread* current = JavaThread::current();
278+
objArrayHandle resolved_references(current, constant_pool()->resolved_references());
279+
// Use the resolved_references() lock for this cpCache entry.
280+
// resolved_references are created for all classes with Invokedynamic, MethodHandle
281+
// or MethodType constant pool cache entries.
282+
assert(resolved_references() != nullptr,
283+
"a resolved_references array should have been created for this class");
284+
ObjectLocker ol(resolved_references, current);
285+
286+
ResolvedMethodEntry* method_entry = resolved_method_entry_at(method_index);
277287
if (method_entry->is_resolved(invoke_code)) {
278288
return method_entry;
279289
}
@@ -311,7 +321,6 @@ ResolvedMethodEntry* ConstantPoolCache::set_method_handle(int method_index, cons
311321
// Store appendix, if any.
312322
if (has_appendix) {
313323
const int appendix_index = method_entry->resolved_references_index();
314-
objArrayOop resolved_references = constant_pool()->resolved_references();
315324
assert(appendix_index >= 0 && appendix_index < resolved_references->length(), "oob");
316325
assert(resolved_references->obj_at(appendix_index) == nullptr, "init just once");
317326
resolved_references->obj_at_put(appendix_index, appendix());
@@ -587,7 +596,14 @@ bool ConstantPoolCache::save_and_throw_indy_exc(
587596
assert(PENDING_EXCEPTION->is_a(vmClasses::LinkageError_klass()),
588597
"No LinkageError exception");
589598

590-
MutexLocker ml(THREAD, cpool->pool_holder()->init_monitor());
599+
// Use the resolved_references() lock for this cpCache entry.
600+
// resolved_references are created for all classes with Invokedynamic, MethodHandle
601+
// or MethodType constant pool cache entries.
602+
JavaThread* current = THREAD;
603+
objArrayHandle resolved_references(current, cpool->resolved_references());
604+
assert(resolved_references() != nullptr,
605+
"a resolved_references array should have been created for this class");
606+
ObjectLocker ol(resolved_references, current);
591607

592608
// if the indy_info is resolved or the indy_resolution_failed flag is set then another
593609
// thread either succeeded in resolving the method or got a LinkageError
@@ -610,21 +626,29 @@ bool ConstantPoolCache::save_and_throw_indy_exc(
610626

611627
oop ConstantPoolCache::set_dynamic_call(const CallInfo &call_info, int index) {
612628
ResourceMark rm;
613-
MutexLocker ml(constant_pool()->pool_holder()->init_monitor());
629+
630+
// Use the resolved_references() lock for this cpCache entry.
631+
// resolved_references are created for all classes with Invokedynamic, MethodHandle
632+
// or MethodType constant pool cache entries.
633+
JavaThread* current = JavaThread::current();
634+
constantPoolHandle cp(current, constant_pool());
635+
636+
objArrayHandle resolved_references(current, cp->resolved_references());
637+
assert(resolved_references() != nullptr,
638+
"a resolved_references array should have been created for this class");
639+
ObjectLocker ol(resolved_references, current);
614640
assert(index >= 0, "Indy index must be positive at this point");
615641

616642
if (resolved_indy_entry_at(index)->method() != nullptr) {
617-
return constant_pool()->resolved_reference_from_indy(index);
643+
return cp->resolved_reference_from_indy(index);
618644
}
619645

620646
if (resolved_indy_entry_at(index)->resolution_failed()) {
621647
// Before we got here, another thread got a LinkageError exception during
622648
// resolution. Ignore our success and throw their exception.
623649
guarantee(index >= 0, "Invalid indy index");
624650
int encoded_index = ResolutionErrorTable::encode_indy_index(index);
625-
JavaThread* THREAD = JavaThread::current(); // For exception macros.
626-
constantPoolHandle cp(THREAD, constant_pool());
627-
ConstantPool::throw_resolution_error(cp, encoded_index, THREAD);
651+
ConstantPool::throw_resolution_error(cp, encoded_index, current);
628652
return nullptr;
629653
}
630654

@@ -648,7 +672,6 @@ oop ConstantPoolCache::set_dynamic_call(const CallInfo &call_info, int index) {
648672

649673
if (has_appendix) {
650674
const int appendix_index = resolved_indy_entry_at(index)->resolved_references_index();
651-
objArrayOop resolved_references = constant_pool()->resolved_references();
652675
assert(appendix_index >= 0 && appendix_index < resolved_references->length(), "oob");
653676
assert(resolved_references->obj_at(appendix_index) == nullptr, "init just once");
654677
resolved_references->obj_at_put(appendix_index, appendix());

0 commit comments

Comments
 (0)