Skip to content

Commit bacf22b

Browse files
author
Thomas Schatzl
committed
8256641: CDS VM operations do not lock the heap
Reviewed-by: kbarrett, iklam
1 parent 58dca92 commit bacf22b

File tree

10 files changed

+85
-35
lines changed

10 files changed

+85
-35
lines changed

src/hotspot/share/gc/g1/g1HeapVerifier.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -472,6 +472,7 @@ bool G1HeapVerifier::should_verify(G1VerifyType type) {
472472

473473
void G1HeapVerifier::verify(VerifyOption vo) {
474474
assert_at_safepoint_on_vm_thread();
475+
assert(Heap_lock->is_locked(), "heap must be locked");
475476

476477
log_debug(gc, verify)("Roots");
477478
VerifyRootsClosure rootsCl(vo);

src/hotspot/share/gc/shared/gcVMOperations.cpp

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,20 @@
4646
#include "gc/g1/g1Policy.hpp"
4747
#endif // INCLUDE_G1GC
4848

49+
bool VM_GC_Sync_Operation::doit_prologue() {
50+
Heap_lock->lock();
51+
return true;
52+
}
53+
54+
void VM_GC_Sync_Operation::doit_epilogue() {
55+
Heap_lock->unlock();
56+
}
57+
58+
void VM_Verify::doit() {
59+
Universe::heap()->prepare_for_verify();
60+
Universe::verify();
61+
}
62+
4963
VM_GC_Operation::~VM_GC_Operation() {
5064
CollectedHeap* ch = Universe::heap();
5165
ch->soft_ref_policy()->set_all_soft_refs_clear(false);
@@ -94,8 +108,7 @@ bool VM_GC_Operation::doit_prologue() {
94108
proper_unit_for_byte_size(NewSize)));
95109
}
96110

97-
// If the GC count has changed someone beat us to the collection
98-
Heap_lock->lock();
111+
VM_GC_Sync_Operation::doit_prologue();
99112

100113
// Check invocations
101114
if (skip_operation()) {
@@ -116,7 +129,7 @@ void VM_GC_Operation::doit_epilogue() {
116129
if (Universe::has_reference_pending_list()) {
117130
Heap_lock->notify_all();
118131
}
119-
Heap_lock->unlock();
132+
VM_GC_Sync_Operation::doit_epilogue();
120133
}
121134

122135
bool VM_GC_HeapInspection::skip_operation() const {

src/hotspot/share/gc/shared/gcVMOperations.hpp

Lines changed: 52 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -39,17 +39,27 @@
3939
// a set of operations (VM_Operation) related to GC.
4040
//
4141
// VM_Operation
42+
// VM_GC_Sync_Operation
4243
// VM_GC_Operation
43-
// VM_GC_HeapInspection
44-
// VM_GenCollectFull
45-
// VM_GenCollectFullConcurrent
46-
// VM_ParallelGCSystemGC
47-
// VM_CollectForAllocation
48-
// VM_GenCollectForAllocation
49-
// VM_ParallelGCFailedAllocation
44+
// VM_GC_HeapInspection
45+
// VM_PopulateDynamicDumpSharedSpace
46+
// VM_GenCollectFull
47+
// VM_GenCollectFullConcurrent
48+
// VM_ParallelGCSystemGC
49+
// VM_CollectForAllocation
50+
// VM_GenCollectForAllocation
51+
// VM_ParallelGCFailedAllocation
52+
// VM_Verify
53+
// VM_PopulateDumpSharedSpace
54+
//
55+
// VM_GC_Sync_Operation
56+
// - implements only synchronization with other VM operations of the
57+
// same kind using the Heap_lock, not actually doing a GC.
58+
//
5059
// VM_GC_Operation
51-
// - implements methods common to all classes in the hierarchy:
52-
// prevents multiple gc requests and manages lock on heap;
60+
// - implements methods common to all operations that perform garbage collections,
61+
// checking that the VM is in a state to do GC and preventing multiple GC
62+
// requests.
5363
//
5464
// VM_GC_HeapInspection
5565
// - prints class histogram on SIGBREAK if PrintClassHistogram
@@ -68,11 +78,37 @@
6878
// - these operations preform full collection of heaps of
6979
// different kind
7080
//
81+
// VM_Verify
82+
// - verifies the heap
83+
//
84+
// VM_PopulateDynamicDumpSharedSpace
85+
// - populates the CDS archive area with the information from the archive file.
86+
//
87+
// VM_PopulateDumpSharedSpace
88+
// - creates the CDS archive
89+
//
90+
91+
class VM_GC_Sync_Operation : public VM_Operation {
92+
public:
93+
94+
VM_GC_Sync_Operation() : VM_Operation() { }
95+
96+
// Acquires the Heap_lock.
97+
virtual bool doit_prologue();
98+
// Releases the Heap_lock.
99+
virtual void doit_epilogue();
100+
};
101+
102+
class VM_Verify : public VM_GC_Sync_Operation {
103+
public:
104+
VMOp_Type type() const { return VMOp_Verify; }
105+
void doit();
106+
};
71107

72-
class VM_GC_Operation: public VM_Operation {
108+
class VM_GC_Operation: public VM_GC_Sync_Operation {
73109
protected:
74-
uint _gc_count_before; // gc count before acquiring PLL
75-
uint _full_gc_count_before; // full gc count before acquiring PLL
110+
uint _gc_count_before; // gc count before acquiring the Heap_lock
111+
uint _full_gc_count_before; // full gc count before acquiring the Heap_lock
76112
bool _full; // whether a "full" collection
77113
bool _prologue_succeeded; // whether doit_prologue succeeded
78114
GCCause::Cause _gc_cause; // the putative cause for this gc op
@@ -84,7 +120,7 @@ class VM_GC_Operation: public VM_Operation {
84120
VM_GC_Operation(uint gc_count_before,
85121
GCCause::Cause _cause,
86122
uint full_gc_count_before = 0,
87-
bool full = false) {
123+
bool full = false) : VM_GC_Sync_Operation() {
88124
_full = full;
89125
_prologue_succeeded = false;
90126
_gc_count_before = gc_count_before;
@@ -106,9 +142,10 @@ class VM_GC_Operation: public VM_Operation {
106142
}
107143
~VM_GC_Operation();
108144

109-
// Acquire the reference synchronization lock
145+
// Acquire the Heap_lock and determine if this VM operation should be executed
146+
// (i.e. not skipped). Return this result, and also store it in _prologue_succeeded.
110147
virtual bool doit_prologue();
111-
// Do notifyAll (if needed) and release held lock
148+
// Notify the Heap_lock if needed and release it.
112149
virtual void doit_epilogue();
113150

114151
virtual bool allow_nested_vm_operations() const { return true; }

src/hotspot/share/gc/z/zDriver.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include "precompiled.hpp"
2525
#include "gc/shared/gcId.hpp"
2626
#include "gc/shared/gcLocker.hpp"
27+
#include "gc/shared/gcVMOperations.hpp"
2728
#include "gc/shared/isGCActiveMark.hpp"
2829
#include "gc/z/zBreakpoint.hpp"
2930
#include "gc/z/zCollectedHeap.hpp"

src/hotspot/share/memory/dynamicArchive.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include "classfile/classLoaderData.inline.hpp"
2828
#include "classfile/symbolTable.hpp"
2929
#include "classfile/systemDictionaryShared.hpp"
30+
#include "gc/shared/gcVMOperations.hpp"
3031
#include "logging/log.hpp"
3132
#include "memory/archiveBuilder.hpp"
3233
#include "memory/archiveUtils.inline.hpp"
@@ -541,10 +542,10 @@ void DynamicArchiveBuilder::write_archive(char* serialized_data) {
541542
log_info(cds, dynamic)("%d klasses; %d symbols", num_klasses, num_symbols);
542543
}
543544

544-
class VM_PopulateDynamicDumpSharedSpace: public VM_Operation {
545+
class VM_PopulateDynamicDumpSharedSpace: public VM_GC_Sync_Operation {
545546
DynamicArchiveBuilder* _builder;
546547
public:
547-
VM_PopulateDynamicDumpSharedSpace(DynamicArchiveBuilder* builder) : _builder(builder) {}
548+
VM_PopulateDynamicDumpSharedSpace(DynamicArchiveBuilder* builder) : VM_GC_Sync_Operation(), _builder(builder) {}
548549
VMOp_Type type() const { return VMOp_PopulateDumpSharedSpace; }
549550
void doit() {
550551
ResourceMark rm;

src/hotspot/share/memory/heapShared.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
#include "classfile/systemDictionaryShared.hpp"
3434
#include "classfile/vmSymbols.hpp"
3535
#include "gc/shared/gcLocker.hpp"
36+
#include "gc/shared/gcVMOperations.hpp"
3637
#include "logging/log.hpp"
3738
#include "logging/logMessage.hpp"
3839
#include "logging/logStream.hpp"
@@ -655,8 +656,10 @@ static void verify_the_heap(Klass* k, const char* which) {
655656
ResourceMark rm;
656657
log_info(cds, heap)("Verify heap %s initializing static field(s) in %s",
657658
which, k->external_name());
659+
658660
VM_Verify verify_op;
659661
VMThread::execute(&verify_op);
662+
660663
if (!FLAG_IS_DEFAULT(VerifyArchivedFields)) {
661664
// If VerifyArchivedFields has a non-default value (e.g., specified on the command-line), do
662665
// more expensive checks.

src/hotspot/share/memory/metaspaceShared.cpp

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
#include "classfile/systemDictionaryShared.hpp"
3838
#include "classfile/vmSymbols.hpp"
3939
#include "code/codeCache.hpp"
40+
#include "gc/shared/gcVMOperations.hpp"
4041
#include "interpreter/abstractInterpreter.hpp"
4142
#include "interpreter/bytecodeStream.hpp"
4243
#include "interpreter/bytecodes.hpp"
@@ -577,7 +578,7 @@ void MetaspaceShared::rewrite_nofast_bytecodes_and_calculate_fingerprints(Thread
577578
}
578579
}
579580

580-
class VM_PopulateDumpSharedSpace: public VM_Operation {
581+
class VM_PopulateDumpSharedSpace : public VM_GC_Operation {
581582
private:
582583
GrowableArray<MemRegion> *_closed_archive_heap_regions;
583584
GrowableArray<MemRegion> *_open_archive_heap_regions;
@@ -602,6 +603,12 @@ class VM_PopulateDumpSharedSpace: public VM_Operation {
602603

603604
public:
604605

606+
VM_PopulateDumpSharedSpace() : VM_GC_Operation(0, /* total collections, ignored */
607+
GCCause::_archive_time_gc)
608+
{ }
609+
610+
bool skip_operation() const { return false; }
611+
605612
VMOp_Type type() const { return VMOp_PopulateDumpSharedSpace; }
606613
void doit(); // outline because gdb sucks
607614
bool allow_nested_vm_operations() const { return true; }
@@ -1085,8 +1092,6 @@ void MetaspaceShared::preload_and_dump(TRAPS) {
10851092
#endif
10861093

10871094
VM_PopulateDumpSharedSpace op;
1088-
MutexLocker ml(THREAD, HeapShared::is_heap_object_archiving_allowed() ?
1089-
Heap_lock : NULL); // needed by HeapShared::run_gc()
10901095
VMThread::execute(&op);
10911096
}
10921097
}

src/hotspot/share/runtime/thread.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
#include "gc/shared/barrierSet.hpp"
3939
#include "gc/shared/gcId.hpp"
4040
#include "gc/shared/gcLocker.inline.hpp"
41+
#include "gc/shared/gcVMOperations.hpp"
4142
#include "gc/shared/oopStorage.hpp"
4243
#include "gc/shared/oopStorageSet.hpp"
4344
#include "gc/shared/workgroup.hpp"

src/hotspot/share/runtime/vmOperations.cpp

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -156,11 +156,6 @@ void VM_ZombieAll::doit() {
156156

157157
#endif // !PRODUCT
158158

159-
void VM_Verify::doit() {
160-
Universe::heap()->prepare_for_verify();
161-
Universe::verify();
162-
}
163-
164159
bool VM_PrintThreads::doit_prologue() {
165160
// Get Heap_lock if concurrent locks will be dumped
166161
if (_print_concurrent_locks) {

src/hotspot/share/runtime/vmOperations.hpp

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -277,13 +277,6 @@ class VM_ZombieAll: public VM_Operation {
277277
};
278278
#endif // PRODUCT
279279

280-
class VM_Verify: public VM_Operation {
281-
public:
282-
VMOp_Type type() const { return VMOp_Verify; }
283-
void doit();
284-
};
285-
286-
287280
class VM_PrintThreads: public VM_Operation {
288281
private:
289282
outputStream* _out;

0 commit comments

Comments
 (0)