Skip to content

Commit c6c69b5

Browse files
committedOct 5, 2023
8314654: Metaspace: move locking out of MetaspaceArena
Reviewed-by: adinn, jsjolen
1 parent 3105538 commit c6c69b5

File tree

6 files changed

+36
-89
lines changed

6 files changed

+36
-89
lines changed
 

‎src/hotspot/share/memory/classLoaderMetaspace.cpp

+12-6
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
#include "memory/metaspace/metaspaceStatistics.hpp"
3737
#include "memory/metaspace/runningCounters.hpp"
3838
#include "memory/metaspaceTracer.hpp"
39+
#include "runtime/mutexLocker.hpp"
3940
#include "utilities/debug.hpp"
4041

4142
using metaspace::ChunkManager;
@@ -60,7 +61,6 @@ ClassLoaderMetaspace::ClassLoaderMetaspace(Mutex* lock, Metaspace::MetaspaceType
6061
_non_class_space_arena = new MetaspaceArena(
6162
non_class_cm,
6263
ArenaGrowthPolicy::policy_for_space_type(space_type, false),
63-
lock,
6464
RunningCounters::used_nonclass_counter(),
6565
"non-class sm");
6666

@@ -71,7 +71,6 @@ ClassLoaderMetaspace::ClassLoaderMetaspace(Mutex* lock, Metaspace::MetaspaceType
7171
_class_space_arena = new MetaspaceArena(
7272
class_cm,
7373
ArenaGrowthPolicy::policy_for_space_type(space_type, true),
74-
lock,
7574
RunningCounters::used_class_counter(),
7675
"class sm");
7776
}
@@ -82,14 +81,15 @@ ClassLoaderMetaspace::ClassLoaderMetaspace(Mutex* lock, Metaspace::MetaspaceType
8281

8382
ClassLoaderMetaspace::~ClassLoaderMetaspace() {
8483
UL(debug, "dies.");
85-
84+
MutexLocker fcl(lock(), Mutex::_no_safepoint_check_flag);
8685
delete _non_class_space_arena;
8786
delete _class_space_arena;
8887

8988
}
9089

9190
// Allocate word_size words from Metaspace.
9291
MetaWord* ClassLoaderMetaspace::allocate(size_t word_size, Metaspace::MetadataType mdType) {
92+
MutexLocker fcl(lock(), Mutex::_no_safepoint_check_flag);
9393
if (Metaspace::is_class_space_allocation(mdType)) {
9494
return class_space_arena()->allocate(word_size);
9595
} else {
@@ -131,6 +131,7 @@ MetaWord* ClassLoaderMetaspace::expand_and_allocate(size_t word_size, Metaspace:
131131
// Prematurely returns a metaspace allocation to the _block_freelists
132132
// because it is not needed anymore.
133133
void ClassLoaderMetaspace::deallocate(MetaWord* ptr, size_t word_size, bool is_class) {
134+
MutexLocker fcl(lock(), Mutex::_no_safepoint_check_flag);
134135
if (Metaspace::using_class_space() && is_class) {
135136
class_space_arena()->deallocate(ptr, word_size);
136137
} else {
@@ -141,6 +142,7 @@ void ClassLoaderMetaspace::deallocate(MetaWord* ptr, size_t word_size, bool is_c
141142

142143
// Update statistics. This walks all in-use chunks.
143144
void ClassLoaderMetaspace::add_to_statistics(metaspace::ClmsStats* out) const {
145+
MutexLocker fcl(lock(), Mutex::_no_safepoint_check_flag);
144146
if (non_class_space_arena() != nullptr) {
145147
non_class_space_arena()->add_to_statistics(&out->_arena_stats_nonclass);
146148
}
@@ -151,6 +153,7 @@ void ClassLoaderMetaspace::add_to_statistics(metaspace::ClmsStats* out) const {
151153

152154
#ifdef ASSERT
153155
void ClassLoaderMetaspace::verify() const {
156+
MutexLocker fcl(lock(), Mutex::_no_safepoint_check_flag);
154157
if (non_class_space_arena() != nullptr) {
155158
non_class_space_arena()->verify();
156159
}
@@ -172,10 +175,13 @@ void ClassLoaderMetaspace::usage_numbers(Metaspace::MetadataType mdType, size_t*
172175
void ClassLoaderMetaspace::usage_numbers(size_t* p_used_words, size_t* p_committed_words,
173176
size_t* p_capacity_words) const {
174177
size_t used_nc, comm_nc, cap_nc;
175-
usage_numbers(Metaspace::MetadataType::NonClassType, &used_nc, &comm_nc, &cap_nc);
176178
size_t used_c = 0, comm_c = 0, cap_c = 0;
177-
if (Metaspace::using_class_space()) {
178-
usage_numbers(Metaspace::MetadataType::ClassType, &used_c, &comm_c, &cap_c);
179+
{
180+
MutexLocker fcl(lock(), Mutex::_no_safepoint_check_flag);
181+
usage_numbers(Metaspace::MetadataType::NonClassType, &used_nc, &comm_nc, &cap_nc);
182+
if (Metaspace::using_class_space()) {
183+
usage_numbers(Metaspace::MetadataType::ClassType, &used_c, &comm_c, &cap_c);
184+
}
179185
}
180186
if (p_used_words != nullptr) {
181187
(*p_used_words) = used_nc + used_c;

‎src/hotspot/share/memory/metaspace/metaspaceArena.cpp

+7-41
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,6 @@ chunklevel_t MetaspaceArena::next_chunk_level() const {
5858

5959
// Given a chunk, add its remaining free committed space to the free block list.
6060
void MetaspaceArena::salvage_chunk(Metachunk* c) {
61-
assert_lock_strong(lock());
6261
size_t remaining_words = c->free_below_committed_words();
6362
if (remaining_words >= FreeBlocks::MinWordSize) {
6463

@@ -80,8 +79,6 @@ void MetaspaceArena::salvage_chunk(Metachunk* c) {
8079
// Allocate a new chunk from the underlying chunk manager able to hold at least
8180
// requested word size.
8281
Metachunk* MetaspaceArena::allocate_new_chunk(size_t requested_word_size) {
83-
assert_lock_strong(lock());
84-
8582
// Should this ever happen, we need to increase the maximum possible chunk size.
8683
guarantee(requested_word_size <= chunklevel::MAX_CHUNK_WORD_SIZE,
8784
"Requested size too large (" SIZE_FORMAT ") - max allowed size per allocation is " SIZE_FORMAT ".",
@@ -112,9 +109,8 @@ void MetaspaceArena::add_allocation_to_fbl(MetaWord* p, size_t word_size) {
112109
}
113110

114111
MetaspaceArena::MetaspaceArena(ChunkManager* chunk_manager, const ArenaGrowthPolicy* growth_policy,
115-
Mutex* lock, SizeAtomicCounter* total_used_words_counter,
112+
SizeAtomicCounter* total_used_words_counter,
116113
const char* name) :
117-
_lock(lock),
118114
_chunk_manager(chunk_manager),
119115
_growth_policy(growth_policy),
120116
_chunks(),
@@ -138,8 +134,6 @@ MetaspaceArena::~MetaspaceArena() {
138134
verify_allocation_guards();
139135
}
140136
#endif
141-
142-
MutexLocker fcl(lock(), Mutex::_no_safepoint_check_flag);
143137
MemRangeCounter return_counter;
144138

145139
Metachunk* c = _chunks.first();
@@ -173,8 +167,6 @@ MetaspaceArena::~MetaspaceArena() {
173167
//
174168
// On success, true is returned, false otherwise.
175169
bool MetaspaceArena::attempt_enlarge_current_chunk(size_t requested_word_size) {
176-
assert_lock_strong(lock());
177-
178170
Metachunk* c = current_chunk();
179171
assert(c->free_words() < requested_word_size, "Sanity");
180172

@@ -224,7 +216,6 @@ bool MetaspaceArena::attempt_enlarge_current_chunk(size_t requested_word_size) {
224216
// 4) Attempt to get a new chunk and allocate from that chunk.
225217
// At any point, if we hit a commit limit, we return null.
226218
MetaWord* MetaspaceArena::allocate(size_t requested_word_size) {
227-
MutexLocker cl(lock(), Mutex::_no_safepoint_check_flag);
228219
UL2(trace, "requested " SIZE_FORMAT " words.", requested_word_size);
229220

230221
MetaWord* p = nullptr;
@@ -270,8 +261,6 @@ MetaWord* MetaspaceArena::allocate(size_t requested_word_size) {
270261

271262
// Allocate from the arena proper, once dictionary allocations and fencing are sorted out.
272263
MetaWord* MetaspaceArena::allocate_inner(size_t word_size) {
273-
274-
assert_lock_strong(lock());
275264
assert_is_aligned(word_size, metaspace::AllocationAlignmentWordSize);
276265

277266
MetaWord* p = nullptr;
@@ -345,7 +334,7 @@ MetaWord* MetaspaceArena::allocate_inner(size_t word_size) {
345334
_total_used_words_counter->increment_by(word_size);
346335
}
347336

348-
SOMETIMES(verify_locked();)
337+
SOMETIMES(verify();)
349338

350339
if (p == nullptr) {
351340
UL(info, "allocation failed, returned null.");
@@ -362,8 +351,7 @@ MetaWord* MetaspaceArena::allocate_inner(size_t word_size) {
362351

363352
// Prematurely returns a metaspace allocation to the _block_freelists
364353
// because it is not needed anymore (requires CLD lock to be active).
365-
void MetaspaceArena::deallocate_locked(MetaWord* p, size_t word_size) {
366-
assert_lock_strong(lock());
354+
void MetaspaceArena::deallocate(MetaWord* p, size_t word_size) {
367355
// At this point a current chunk must exist since we only deallocate if we did allocate before.
368356
assert(current_chunk() != nullptr, "stray deallocation?");
369357
assert(is_valid_area(p, word_size),
@@ -382,20 +370,11 @@ void MetaspaceArena::deallocate_locked(MetaWord* p, size_t word_size) {
382370

383371
add_allocation_to_fbl(p, raw_word_size);
384372

385-
SOMETIMES(verify_locked();)
386-
}
387-
388-
// Prematurely returns a metaspace allocation to the _block_freelists because it is not
389-
// needed anymore.
390-
void MetaspaceArena::deallocate(MetaWord* p, size_t word_size) {
391-
MutexLocker cl(lock(), Mutex::_no_safepoint_check_flag);
392-
deallocate_locked(p, word_size);
373+
SOMETIMES(verify();)
393374
}
394375

395376
// Update statistics. This walks all in-use chunks.
396377
void MetaspaceArena::add_to_statistics(ArenaStats* out) const {
397-
MutexLocker cl(lock(), Mutex::_no_safepoint_check_flag);
398-
399378
for (const Metachunk* c = _chunks.first(); c != nullptr; c = c->next()) {
400379
InUseChunkStats& ucs = out->_stats[c->level()];
401380
ucs._num++;
@@ -421,7 +400,6 @@ void MetaspaceArena::add_to_statistics(ArenaStats* out) const {
421400
// Convenience method to get the most important usage statistics.
422401
// For deeper analysis use add_to_statistics().
423402
void MetaspaceArena::usage_numbers(size_t* p_used_words, size_t* p_committed_words, size_t* p_capacity_words) const {
424-
MutexLocker cl(lock(), Mutex::_no_safepoint_check_flag);
425403
size_t used = 0, comm = 0, cap = 0;
426404
for (const Metachunk* c = _chunks.first(); c != nullptr; c = c->next()) {
427405
used += c->used_words();
@@ -441,8 +419,7 @@ void MetaspaceArena::usage_numbers(size_t* p_used_words, size_t* p_committed_wor
441419

442420
#ifdef ASSERT
443421

444-
void MetaspaceArena::verify_locked() const {
445-
assert_lock_strong(lock());
422+
void MetaspaceArena::verify() const {
446423
assert(_growth_policy != nullptr && _chunk_manager != nullptr, "Sanity");
447424
_chunks.verify();
448425
if (_fbl != nullptr) {
@@ -462,11 +439,6 @@ void MetaspaceArena::verify_allocation_guards() const {
462439
}
463440
}
464441

465-
void MetaspaceArena::verify() const {
466-
MutexLocker cl(lock(), Mutex::_no_safepoint_check_flag);
467-
verify_locked();
468-
}
469-
470442
// Returns true if the area indicated by pointer and size have actually been allocated
471443
// from this arena.
472444
bool MetaspaceArena::is_valid_area(MetaWord* p, size_t word_size) const {
@@ -483,18 +455,12 @@ bool MetaspaceArena::is_valid_area(MetaWord* p, size_t word_size) const {
483455
#endif // ASSERT
484456

485457
void MetaspaceArena::print_on(outputStream* st) const {
486-
MutexLocker fcl(_lock, Mutex::_no_safepoint_check_flag);
487-
print_on_locked(st);
488-
}
489-
490-
void MetaspaceArena::print_on_locked(outputStream* st) const {
491-
assert_lock_strong(_lock);
492458
st->print_cr("sm %s: %d chunks, total word size: " SIZE_FORMAT ", committed word size: " SIZE_FORMAT, _name,
493459
_chunks.count(), _chunks.calc_word_size(), _chunks.calc_committed_word_size());
494460
_chunks.print_on(st);
495461
st->cr();
496-
st->print_cr("growth-policy " PTR_FORMAT ", lock " PTR_FORMAT ", cm " PTR_FORMAT ", fbl " PTR_FORMAT,
497-
p2i(_growth_policy), p2i(_lock), p2i(_chunk_manager), p2i(_fbl));
462+
st->print_cr("growth-policy " PTR_FORMAT ", cm " PTR_FORMAT ", fbl " PTR_FORMAT,
463+
p2i(_growth_policy), p2i(_chunk_manager), p2i(_fbl));
498464
}
499465

500466
} // namespace metaspace

‎src/hotspot/share/memory/metaspace/metaspaceArena.hpp

+5-19
Original file line numberDiff line numberDiff line change
@@ -28,18 +28,17 @@
2828

2929
#include "memory/allocation.hpp"
3030
#include "memory/metaspace.hpp"
31-
#include "memory/metaspace/chunkManager.hpp"
3231
#include "memory/metaspace/counters.hpp"
33-
#include "memory/metaspace/metachunk.hpp"
3432
#include "memory/metaspace/metachunkList.hpp"
35-
#include "memory/metaspace/metaspaceCommon.hpp"
3633

3734
class outputStream;
3835
class Mutex;
3936

4037
namespace metaspace {
4138

4239
class ArenaGrowthPolicy;
40+
class ChunkManager;
41+
class Metachunk;
4342
class FreeBlocks;
4443

4544
struct ArenaStats;
@@ -76,14 +75,8 @@ struct ArenaStats;
7675

7776
class MetaspaceArena : public CHeapObj<mtClass> {
7877

79-
// Reference to an outside lock to use for synchronizing access to this arena.
80-
// This lock is normally owned by the CLD which owns the ClassLoaderMetaspace which
81-
// owns this arena.
82-
// Todo: This should be changed. Either the CLD should synchronize access to the
83-
// CLMS and its arenas itself, or the arena should have an own lock. The latter
84-
// would allow for more fine granular locking since it would allow access to
85-
// both class- and non-class arena in the CLMS independently.
86-
Mutex* const _lock;
78+
// Please note that access to a metaspace arena may be shared
79+
// between threads and needs to be synchronized in CLMS.
8780

8881
// Reference to the chunk manager to allocate chunks from.
8982
ChunkManager* const _chunk_manager;
@@ -129,7 +122,6 @@ class MetaspaceArena : public CHeapObj<mtClass> {
129122
const Fence* _first_fence;
130123
#endif // ASSERT
131124

132-
Mutex* lock() const { return _lock; }
133125
ChunkManager* chunk_manager() const { return _chunk_manager; }
134126

135127
// free block list
@@ -152,10 +144,6 @@ class MetaspaceArena : public CHeapObj<mtClass> {
152144
// On success, true is returned, false otherwise.
153145
bool attempt_enlarge_current_chunk(size_t requested_word_size);
154146

155-
// Prematurely returns a metaspace allocation to the _block_freelists
156-
// because it is not needed anymore (requires CLD lock to be active).
157-
void deallocate_locked(MetaWord* p, size_t word_size);
158-
159147
// Returns true if the area indicated by pointer and size have actually been allocated
160148
// from this arena.
161149
DEBUG_ONLY(bool is_valid_area(MetaWord* p, size_t word_size) const;)
@@ -166,7 +154,7 @@ class MetaspaceArena : public CHeapObj<mtClass> {
166154
public:
167155

168156
MetaspaceArena(ChunkManager* chunk_manager, const ArenaGrowthPolicy* growth_policy,
169-
Mutex* lock, SizeAtomicCounter* total_used_words_counter,
157+
SizeAtomicCounter* total_used_words_counter,
170158
const char* name);
171159

172160
~MetaspaceArena();
@@ -191,11 +179,9 @@ class MetaspaceArena : public CHeapObj<mtClass> {
191179
void usage_numbers(size_t* p_used_words, size_t* p_committed_words, size_t* p_capacity_words) const;
192180

193181
DEBUG_ONLY(void verify() const;)
194-
DEBUG_ONLY(void verify_locked() const;)
195182
DEBUG_ONLY(void verify_allocation_guards() const;)
196183

197184
void print_on(outputStream* st) const;
198-
void print_on_locked(outputStream* st) const;
199185

200186
};
201187

‎src/hotspot/share/memory/metaspace/testHelpers.cpp

+8-2
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
*/
2525

2626
#include "precompiled.hpp"
27+
#include "memory/metaspace/chunkManager.hpp"
2728
#include "memory/metaspace/metaspaceArena.hpp"
2829
#include "memory/metaspace/metaspaceArenaGrowthPolicy.hpp"
2930
#include "memory/metaspace/metaspaceContext.hpp"
@@ -44,15 +45,20 @@ MetaspaceTestArena::MetaspaceTestArena(Mutex* lock, MetaspaceArena* arena) :
4445
{}
4546

4647
MetaspaceTestArena::~MetaspaceTestArena() {
47-
delete _arena;
48+
{
49+
MutexLocker fcl(_lock, Mutex::_no_safepoint_check_flag);
50+
delete _arena;
51+
}
4852
delete _lock;
4953
}
5054

5155
MetaWord* MetaspaceTestArena::allocate(size_t word_size) {
56+
MutexLocker fcl(_lock, Mutex::_no_safepoint_check_flag);
5257
return _arena->allocate(word_size);
5358
}
5459

5560
void MetaspaceTestArena::deallocate(MetaWord* p, size_t word_size) {
61+
MutexLocker fcl(_lock, Mutex::_no_safepoint_check_flag);
5662
return _arena->deallocate(p, word_size);
5763
}
5864

@@ -97,7 +103,7 @@ MetaspaceTestArena* MetaspaceTestContext::create_arena(Metaspace::MetaspaceType
97103
MetaspaceArena* arena = nullptr;
98104
{
99105
MutexLocker ml(lock, Mutex::_no_safepoint_check_flag);
100-
arena = new MetaspaceArena(_context->cm(), growth_policy, lock, &_used_words_counter, _name);
106+
arena = new MetaspaceArena(_context->cm(), growth_policy, &_used_words_counter, _name);
101107
}
102108
return new MetaspaceTestArena(lock, arena);
103109
}

0 commit comments

Comments
 (0)
Please sign in to comment.