1521 lines
64 KiB
Diff
Executable File
1521 lines
64 KiB
Diff
Executable File
From 2821582ff1191393781ccf93d46d9c31230c8a4a Mon Sep 17 00:00:00 2001
|
|
From: mashoubing <mashoubing1@huawei.com>
|
|
Date: Mon, 11 Oct 2021 12:11:25 +0800
|
|
Subject: [PATCH 3/4] G1: Full GC parallel mark
|
|
|
|
---
|
|
.../concurrentMarkSweepGeneration.cpp | 2 +-
|
|
.../g1/g1BlockOffsetTable.inline.hpp | 2 +-
|
|
.../gc_implementation/g1/g1CollectedHeap.cpp | 2 +-
|
|
.../vm/gc_implementation/g1/g1MarkSweep.cpp | 233 +++++++++++++-----
|
|
.../vm/gc_implementation/g1/g1MarkSweep.hpp | 9 +-
|
|
.../gc_implementation/g1/g1RootProcessor.cpp | 23 +-
|
|
.../gc_implementation/g1/g1RootProcessor.hpp | 9 +-
|
|
.../vm/gc_implementation/g1/g1StringDedup.cpp | 10 +-
|
|
.../vm/gc_implementation/g1/g1StringDedup.hpp | 4 +-
|
|
.../parallelScavenge/parallelScavengeHeap.cpp | 2 +-
|
|
.../parallelScavenge/psMarkSweep.cpp | 5 +
|
|
.../parallelScavenge/psMarkSweep.hpp | 33 +--
|
|
.../parallelScavenge/psScavenge.cpp | 2 +-
|
|
.../vm/gc_implementation/shared/markSweep.cpp | 44 ++--
|
|
.../vm/gc_implementation/shared/markSweep.hpp | 89 ++++---
|
|
.../shared/markSweep.inline.hpp | 41 ++-
|
|
hotspot/src/share/vm/memory/genMarkSweep.cpp | 6 +
|
|
hotspot/src/share/vm/memory/genMarkSweep.hpp | 18 +-
|
|
hotspot/src/share/vm/memory/generation.cpp | 2 +-
|
|
.../vm/oops/instanceClassLoaderKlass.cpp | 6 +-
|
|
.../vm/oops/instanceClassLoaderKlass.hpp | 2 +-
|
|
hotspot/src/share/vm/oops/instanceKlass.cpp | 6 +-
|
|
hotspot/src/share/vm/oops/instanceKlass.hpp | 2 +-
|
|
.../src/share/vm/oops/instanceMirrorKlass.cpp | 10 +-
|
|
.../src/share/vm/oops/instanceMirrorKlass.hpp | 2 +-
|
|
.../src/share/vm/oops/instanceRefKlass.cpp | 18 +-
|
|
.../src/share/vm/oops/instanceRefKlass.hpp | 2 +-
|
|
hotspot/src/share/vm/oops/klass.hpp | 3 +-
|
|
hotspot/src/share/vm/oops/markOop.hpp | 2 +-
|
|
hotspot/src/share/vm/oops/objArrayKlass.cpp | 8 +-
|
|
hotspot/src/share/vm/oops/objArrayKlass.hpp | 6 +-
|
|
.../share/vm/oops/objArrayKlass.inline.hpp | 12 +-
|
|
hotspot/src/share/vm/oops/oop.hpp | 4 +-
|
|
hotspot/src/share/vm/oops/oop.inline.hpp | 4 +-
|
|
hotspot/src/share/vm/oops/typeArrayKlass.cpp | 2 +-
|
|
hotspot/src/share/vm/oops/typeArrayKlass.hpp | 2 +-
|
|
36 files changed, 401 insertions(+), 226 deletions(-)
|
|
|
|
diff --git a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp
|
|
index 3c3deab28..d31f9a54a 100644
|
|
--- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp
|
|
+++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp
|
|
@@ -2079,7 +2079,7 @@ void CMSCollector::do_compaction_work(bool clear_all_soft_refs) {
|
|
_intra_sweep_estimate.padded_average());
|
|
}
|
|
|
|
- GenMarkSweep::invoke_at_safepoint(_cmsGen->level(),
|
|
+ GenMarkSweep::the_gen_mark()->invoke_at_safepoint(_cmsGen->level(),
|
|
ref_processor(), clear_all_soft_refs);
|
|
#ifdef ASSERT
|
|
CompactibleFreeListSpace* cms_space = _cmsGen->cmsSpace();
|
|
diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.inline.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.inline.hpp
|
|
index 912acdbe0..9a8cb877d 100644
|
|
--- a/hotspot/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.inline.hpp
|
|
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.inline.hpp
|
|
@@ -51,7 +51,7 @@ G1BlockOffsetTable::block_start_const(const void* addr) const {
|
|
assert((index) < (_reserved.word_size() >> LogN_words), \
|
|
err_msg("%s - index: "SIZE_FORMAT", _vs.committed_size: "SIZE_FORMAT, \
|
|
msg, (index), (_reserved.word_size() >> LogN_words))); \
|
|
- assert(!G1Uncommit && G1CollectedHeap::heap()->is_in_exact(address_for_index_raw(index)) || G1Uncommit, \
|
|
+ assert((!G1Uncommit && G1CollectedHeap::heap()->is_in_exact(address_for_index_raw(index))) || G1Uncommit, \
|
|
err_msg("Index "SIZE_FORMAT" corresponding to "PTR_FORMAT \
|
|
" (%u) is not in committed area.", \
|
|
(index), \
|
|
diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp
|
|
index 060531901..1f1042caa 100644
|
|
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp
|
|
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp
|
|
@@ -1371,7 +1371,7 @@ bool G1CollectedHeap::do_collection(bool explicit_gc,
|
|
// how reference processing currently works in G1.
|
|
|
|
// Temporarily make discovery by the STW ref processor single threaded (non-MT).
|
|
- ReferenceProcessorMTDiscoveryMutator stw_rp_disc_ser(ref_processor_stw(), false);
|
|
+ ReferenceProcessorMTDiscoveryMutator stw_rp_disc_ser(ref_processor_stw(), G1ParallelFullGC);
|
|
|
|
// Temporarily clear the STW ref processor's _is_alive_non_header field.
|
|
ReferenceProcessorIsAliveMutator stw_rp_is_alive_null(ref_processor_stw(), NULL);
|
|
diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1MarkSweep.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1MarkSweep.cpp
|
|
index 2a14b967a..9ab422405 100644
|
|
--- a/hotspot/src/share/vm/gc_implementation/g1/g1MarkSweep.cpp
|
|
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1MarkSweep.cpp
|
|
@@ -216,13 +216,17 @@ size_t G1RePrepareClosure::apply(oop obj) {
|
|
|
|
bool G1MarkSweep::_parallel_prepare_compact = false;
|
|
bool G1MarkSweep::_parallel_adjust = false;
|
|
+bool G1MarkSweep::_parallel_mark = false;
|
|
+uint G1MarkSweep::_active_workers = 0;
|
|
|
|
void G1MarkSweep::invoke_at_safepoint(ReferenceProcessor* rp,
|
|
bool clear_all_softrefs) {
|
|
assert(SafepointSynchronize::is_at_safepoint(), "must be at a safepoint");
|
|
- uint active_workers = G1CollectedHeap::heap()->workers()->active_workers();
|
|
+
|
|
+ _active_workers = G1CollectedHeap::heap()->workers()->active_workers();
|
|
|
|
if (G1ParallelFullGC) {
|
|
+ _parallel_mark = true;
|
|
_parallel_prepare_compact = true;
|
|
_parallel_adjust = true;
|
|
}
|
|
@@ -238,6 +242,19 @@ void G1MarkSweep::invoke_at_safepoint(ReferenceProcessor* rp,
|
|
assert(rp != NULL, "should be non-NULL");
|
|
assert(rp == G1CollectedHeap::heap()->ref_processor_stw(), "Precondition");
|
|
|
|
+ GenMarkSweep* marks = new GenMarkSweep[_active_workers];
|
|
+
|
|
+ if (!_parallel_mark) {
|
|
+ allocate_stacks();
|
|
+ } else {
|
|
+ for (uint i = 0; i < _active_workers; i++) {
|
|
+ marks[i]._preserved_count_max = 0;
|
|
+ marks[i]._preserved_marks = NULL;
|
|
+ marks[i]._preserved_count = 0;
|
|
+ marks[i].set_worker_id(i);
|
|
+ }
|
|
+ }
|
|
+
|
|
GenMarkSweep::_ref_processor = rp;
|
|
rp->setup_policy(clear_all_softrefs);
|
|
|
|
@@ -248,30 +265,42 @@ void G1MarkSweep::invoke_at_safepoint(ReferenceProcessor* rp,
|
|
|
|
bool marked_for_unloading = false;
|
|
|
|
- allocate_stacks();
|
|
-
|
|
// We should save the marks of the currently locked biased monitors.
|
|
// The marking doesn't preserve the marks of biased objects.
|
|
BiasedLocking::preserve_marks();
|
|
|
|
{
|
|
- G1FullGCCompactionPoints cps(active_workers);
|
|
+ G1FullGCCompactionPoints cps(_active_workers);
|
|
|
|
- mark_sweep_phase1(marked_for_unloading, clear_all_softrefs);
|
|
+ mark_sweep_phase1(marked_for_unloading, clear_all_softrefs, marks);
|
|
|
|
mark_sweep_phase2(&cps);
|
|
|
|
// Don't add any more derived pointers during phase3
|
|
COMPILER2_PRESENT(DerivedPointerTable::set_active(false));
|
|
|
|
- mark_sweep_phase3();
|
|
+ mark_sweep_phase3(marks);
|
|
|
|
mark_sweep_phase4(&cps);
|
|
}
|
|
|
|
- GenMarkSweep::restore_marks();
|
|
+ if (!_parallel_mark) {
|
|
+ GenMarkSweep::the_gen_mark()->restore_marks();
|
|
+ } else {
|
|
+ for (uint i = 0; i < _active_workers; i++) {
|
|
+ marks[i].restore_marks();
|
|
+ }
|
|
+ }
|
|
+
|
|
BiasedLocking::restore_marks();
|
|
- GenMarkSweep::deallocate_stacks();
|
|
+
|
|
+ if (!_parallel_mark) {
|
|
+ GenMarkSweep::the_gen_mark()->deallocate_stacks();
|
|
+ } else {
|
|
+ for (uint i = 0; i < _active_workers; i++) {
|
|
+ marks[i].deallocate_stacks();
|
|
+ }
|
|
+ }
|
|
|
|
// "free at last gc" is calculated from these.
|
|
// CHF: cheating for now!!!
|
|
@@ -281,20 +310,62 @@ void G1MarkSweep::invoke_at_safepoint(ReferenceProcessor* rp,
|
|
Threads::gc_epilogue();
|
|
CodeCache::gc_epilogue();
|
|
JvmtiExport::gc_epilogue();
|
|
-
|
|
// refs processing: clean slate
|
|
GenMarkSweep::_ref_processor = NULL;
|
|
}
|
|
|
|
+void G1MarkSweep::run_task(AbstractGangTask* task) {
|
|
+ G1CollectedHeap::heap()->workers()->run_task(task);
|
|
+}
|
|
|
|
void G1MarkSweep::allocate_stacks() {
|
|
- GenMarkSweep::_preserved_count_max = 0;
|
|
- GenMarkSweep::_preserved_marks = NULL;
|
|
- GenMarkSweep::_preserved_count = 0;
|
|
+ GenMarkSweep::the_gen_mark()->_preserved_count_max = 0;
|
|
+ GenMarkSweep::the_gen_mark()->_preserved_marks = NULL;
|
|
+ GenMarkSweep::the_gen_mark()->_preserved_count = 0;
|
|
}
|
|
|
|
+class G1FullGCMarkTask : public AbstractGangTask {
|
|
+protected:
|
|
+ G1RootProcessor _root_processor;
|
|
+ GenMarkSweep* _marks;
|
|
+
|
|
+public:
|
|
+ G1FullGCMarkTask(GenMarkSweep* marks, uint active_workers) :
|
|
+ AbstractGangTask("G1 mark task"),
|
|
+ _root_processor(G1CollectedHeap::heap()),
|
|
+ _marks(marks) {
|
|
+ _root_processor.set_num_workers(active_workers);
|
|
+ }
|
|
+ virtual ~G1FullGCMarkTask() { }
|
|
+
|
|
+ void work(uint worker_id) {
|
|
+ Ticks start = Ticks::now();
|
|
+
|
|
+ ResourceMark rm;
|
|
+
|
|
+ MarkingCodeBlobClosure follow_code_closure(&_marks[worker_id].follow_root_closure,
|
|
+ !CodeBlobToOopClosure::FixRelocations);
|
|
+ {
|
|
+
|
|
+ if (ClassUnloading) {
|
|
+ _root_processor.process_strong_roots(&_marks[worker_id].follow_root_closure,
|
|
+ &_marks[worker_id].follow_cld_closure,
|
|
+ &follow_code_closure,
|
|
+ worker_id);
|
|
+ } else {
|
|
+ _root_processor.process_all_roots_no_string_table(&_marks[worker_id].follow_root_closure,
|
|
+ &_marks[worker_id].follow_cld_closure,
|
|
+ &follow_code_closure);
|
|
+ }
|
|
+ _marks[worker_id].follow_stack();
|
|
+ }
|
|
+ }
|
|
+};
|
|
+
|
|
+
|
|
void G1MarkSweep::mark_sweep_phase1(bool& marked_for_unloading,
|
|
- bool clear_all_softrefs) {
|
|
+ bool clear_all_softrefs,
|
|
+ GenMarkSweep* marks) {
|
|
// Recursively traverse all live objects and mark them
|
|
GCTraceTime tm("phase 1", G1Log::fine() && Verbose, true, gc_timer(), gc_tracer()->gc_id());
|
|
GenMarkSweep::trace(" 1");
|
|
@@ -304,52 +375,87 @@ void G1MarkSweep::mark_sweep_phase1(bool& marked_for_unloading,
|
|
// Need cleared claim bits for the roots processing
|
|
ClassLoaderDataGraph::clear_claimed_marks();
|
|
|
|
- MarkingCodeBlobClosure follow_code_closure(&GenMarkSweep::follow_root_closure, !CodeBlobToOopClosure::FixRelocations);
|
|
- {
|
|
- G1RootProcessor root_processor(g1h);
|
|
- if (ClassUnloading) {
|
|
- root_processor.process_strong_roots(&GenMarkSweep::follow_root_closure,
|
|
- &GenMarkSweep::follow_cld_closure,
|
|
- &follow_code_closure);
|
|
- } else {
|
|
- root_processor.process_all_roots_no_string_table(
|
|
- &GenMarkSweep::follow_root_closure,
|
|
- &GenMarkSweep::follow_cld_closure,
|
|
- &follow_code_closure);
|
|
+ if (!_parallel_mark) {
|
|
+
|
|
+ MarkingCodeBlobClosure follow_code_closure(&GenMarkSweep::the_gen_mark()->follow_root_closure,
|
|
+ !CodeBlobToOopClosure::FixRelocations);
|
|
+ {
|
|
+ G1RootProcessor root_processor(g1h);
|
|
+ if (ClassUnloading) {
|
|
+ root_processor.process_strong_roots(&GenMarkSweep::the_gen_mark()->follow_root_closure,
|
|
+ &GenMarkSweep::the_gen_mark()->follow_cld_closure,
|
|
+ &follow_code_closure);
|
|
+ } else {
|
|
+ root_processor.process_all_roots_no_string_table(&GenMarkSweep::the_gen_mark()->follow_root_closure,
|
|
+ &GenMarkSweep::the_gen_mark()->follow_cld_closure,
|
|
+ &follow_code_closure);
|
|
+ }
|
|
}
|
|
- }
|
|
|
|
- // Process reference objects found during marking
|
|
- ReferenceProcessor* rp = GenMarkSweep::ref_processor();
|
|
- assert(rp == g1h->ref_processor_stw(), "Sanity");
|
|
+ // Process reference objects found during marking
|
|
+ ReferenceProcessor* rp = GenMarkSweep::ref_processor();
|
|
+ assert(rp == g1h->ref_processor_stw(), "Sanity");
|
|
+
|
|
+ rp->setup_policy(clear_all_softrefs);
|
|
+ const ReferenceProcessorStats& stats =
|
|
+ rp->process_discovered_references(&GenMarkSweep::the_gen_mark()->is_alive,
|
|
+ &GenMarkSweep::the_gen_mark()->keep_alive,
|
|
+ &GenMarkSweep::the_gen_mark()->follow_stack_closure,
|
|
+ NULL,
|
|
+ gc_timer(),
|
|
+ gc_tracer()->gc_id());
|
|
+ gc_tracer()->report_gc_reference_stats(stats);
|
|
|
|
- rp->setup_policy(clear_all_softrefs);
|
|
- const ReferenceProcessorStats& stats =
|
|
- rp->process_discovered_references(&GenMarkSweep::is_alive,
|
|
- &GenMarkSweep::keep_alive,
|
|
- &GenMarkSweep::follow_stack_closure,
|
|
- NULL,
|
|
- gc_timer(),
|
|
- gc_tracer()->gc_id());
|
|
- gc_tracer()->report_gc_reference_stats(stats);
|
|
|
|
+ // This is the point where the entire marking should have completed.
|
|
+ assert(GenMarkSweep::the_gen_mark()->_marking_stack.is_empty(), "Marking should have completed");
|
|
|
|
- // This is the point where the entire marking should have completed.
|
|
- assert(GenMarkSweep::_marking_stack.is_empty(), "Marking should have completed");
|
|
+ if (ClassUnloading) {
|
|
+ // Unload classes and purge the SystemDictionary.
|
|
+ bool purged_class = SystemDictionary::do_unloading(&GenMarkSweep::the_gen_mark()->is_alive);
|
|
+ // Unload nmethods.
|
|
+ CodeCache::do_unloading(&GenMarkSweep::the_gen_mark()->is_alive, purged_class);
|
|
+ // Prune dead klasses from subklass/sibling/implementor lists.
|
|
+ Klass::clean_weak_klass_links(&GenMarkSweep::the_gen_mark()->is_alive);
|
|
+ }
|
|
+ // Delete entries for dead interned string and clean up unreferenced symbols in symbol table.
|
|
+ G1CollectedHeap::heap()->unlink_string_and_symbol_table(&GenMarkSweep::the_gen_mark()->is_alive);
|
|
+ } else {
|
|
+ G1FullGCMarkTask task(marks, _active_workers);
|
|
+ FlexibleWorkGang* flexible = G1CollectedHeap::heap()->workers();
|
|
+ SharedHeap::heap()->set_par_threads(_active_workers);
|
|
+ flexible->run_task(&task);
|
|
+ SharedHeap::heap()->set_par_threads(0);
|
|
+
|
|
+ // Process reference objects found during marking
|
|
+ ReferenceProcessor* rp = MarkSweep::ref_processor();
|
|
+ assert(rp == g1h->ref_processor_stw(), "Sanity");
|
|
|
|
- if (ClassUnloading) {
|
|
+ rp->setup_policy(clear_all_softrefs);
|
|
|
|
- // Unload classes and purge the SystemDictionary.
|
|
- bool purged_class = SystemDictionary::do_unloading(&GenMarkSweep::is_alive);
|
|
+ const ReferenceProcessorStats& stats =
|
|
+ rp->process_discovered_references(&marks[0].is_alive,
|
|
+ &marks[0].keep_alive,
|
|
+ &marks[0].follow_stack_closure,
|
|
+ NULL,
|
|
+ gc_timer(),
|
|
+ gc_tracer()->gc_id());
|
|
+ gc_tracer()->report_gc_reference_stats(stats);
|
|
+
|
|
+ if (ClassUnloading) {
|
|
|
|
- // Unload nmethods.
|
|
- CodeCache::do_unloading(&GenMarkSweep::is_alive, purged_class);
|
|
+ // Unload classes and purge the SystemDictionary.
|
|
+ bool purged_class = SystemDictionary::do_unloading(&marks[0].is_alive);
|
|
|
|
- // Prune dead klasses from subklass/sibling/implementor lists.
|
|
- Klass::clean_weak_klass_links(&GenMarkSweep::is_alive);
|
|
+ // Unload nmethods.
|
|
+ CodeCache::do_unloading(&marks[0].is_alive, purged_class);
|
|
+
|
|
+ // Prune dead klasses from subklass/sibling/implementor lists.
|
|
+ Klass::clean_weak_klass_links(&marks[0].is_alive);
|
|
+ }
|
|
+ // Delete entries for dead interned string and clean up unreferenced symbols in symbol table.
|
|
+ G1CollectedHeap::heap()->unlink_string_and_symbol_table(&marks[0].is_alive);
|
|
}
|
|
- // Delete entries for dead interned string and clean up unreferenced symbols in symbol table.
|
|
- G1CollectedHeap::heap()->unlink_string_and_symbol_table(&GenMarkSweep::is_alive);
|
|
|
|
if (VerifyDuringGC) {
|
|
HandleMark hm; // handle scope
|
|
@@ -374,7 +480,7 @@ void G1MarkSweep::mark_sweep_phase1(bool& marked_for_unloading,
|
|
}
|
|
}
|
|
|
|
- gc_tracer()->report_object_count_after_gc(&GenMarkSweep::is_alive);
|
|
+ gc_tracer()->report_object_count_after_gc(&GenMarkSweep::the_gen_mark()->is_alive);
|
|
}
|
|
|
|
|
|
@@ -603,7 +709,7 @@ public:
|
|
}
|
|
};
|
|
|
|
-void G1MarkSweep::mark_sweep_phase3() {
|
|
+void G1MarkSweep::mark_sweep_phase3(GenMarkSweep* marks) {
|
|
G1CollectedHeap* g1h = G1CollectedHeap::heap();
|
|
|
|
// Adjust the pointers to reflect the new locations
|
|
@@ -613,33 +719,40 @@ void G1MarkSweep::mark_sweep_phase3() {
|
|
// Need cleared claim bits for the roots processing
|
|
ClassLoaderDataGraph::clear_claimed_marks();
|
|
|
|
- CodeBlobToOopClosure adjust_code_closure(&GenMarkSweep::adjust_pointer_closure,
|
|
+ CodeBlobToOopClosure adjust_code_closure(&GenMarkSweep::the_gen_mark()->adjust_pointer_closure,
|
|
CodeBlobToOopClosure::FixRelocations);
|
|
{
|
|
G1RootProcessor root_processor(g1h);
|
|
- root_processor.process_all_roots(&GenMarkSweep::adjust_pointer_closure,
|
|
- &GenMarkSweep::adjust_cld_closure,
|
|
+ root_processor.process_all_roots(&GenMarkSweep::the_gen_mark()->adjust_pointer_closure,
|
|
+ &GenMarkSweep::the_gen_mark()->adjust_cld_closure,
|
|
&adjust_code_closure);
|
|
}
|
|
|
|
assert(GenMarkSweep::ref_processor() == g1h->ref_processor_stw(), "Sanity");
|
|
- g1h->ref_processor_stw()->weak_oops_do(&GenMarkSweep::adjust_pointer_closure);
|
|
+ g1h->ref_processor_stw()->weak_oops_do(&GenMarkSweep::the_gen_mark()->adjust_pointer_closure);
|
|
|
|
// Now adjust pointers in remaining weak roots. (All of which should
|
|
// have been cleared if they pointed to non-surviving objects.)
|
|
- JNIHandles::weak_oops_do(&GenMarkSweep::adjust_pointer_closure);
|
|
- JFR_ONLY(Jfr::weak_oops_do(&GenMarkSweep::adjust_pointer_closure));
|
|
+ JNIHandles::weak_oops_do(&GenMarkSweep::the_gen_mark()->adjust_pointer_closure);
|
|
+ JFR_ONLY(Jfr::weak_oops_do(&GenMarkSweep::the_gen_mark()->adjust_pointer_closure));
|
|
|
|
if (G1StringDedup::is_enabled()) {
|
|
- G1StringDedup::oops_do(&GenMarkSweep::adjust_pointer_closure);
|
|
+ G1StringDedup::oops_do(&GenMarkSweep::the_gen_mark()->adjust_pointer_closure);
|
|
}
|
|
|
|
- GenMarkSweep::adjust_marks();
|
|
-
|
|
if (!_parallel_adjust) {
|
|
+ GenMarkSweep::the_gen_mark()->adjust_marks();
|
|
G1AdjustPointersClosure blk;
|
|
g1h->heap_region_iterate(&blk);
|
|
} else {
|
|
+ if (!_parallel_mark) {
|
|
+ GenMarkSweep::the_gen_mark()->adjust_marks();
|
|
+ } else {
|
|
+ for (uint i = 0; i < _active_workers; i++) {
|
|
+ marks[i].adjust_marks();
|
|
+ }
|
|
+ }
|
|
+
|
|
G1FullGCAdjustTask task;
|
|
FlexibleWorkGang* flexible = G1CollectedHeap::heap()->workers();
|
|
flexible->run_task(&task);
|
|
diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1MarkSweep.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1MarkSweep.hpp
|
|
index 82aa6b63e..0787cfe86 100644
|
|
--- a/hotspot/src/share/vm/gc_implementation/g1/g1MarkSweep.hpp
|
|
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1MarkSweep.hpp
|
|
@@ -75,16 +75,19 @@ class G1MarkSweep : AllStatic {
|
|
private:
|
|
static bool _parallel_prepare_compact;
|
|
static bool _parallel_adjust;
|
|
+ static bool _parallel_mark;
|
|
+ static uint _active_workers;
|
|
|
|
private:
|
|
-
|
|
+ static void run_task(AbstractGangTask* task);
|
|
// Mark live objects
|
|
static void mark_sweep_phase1(bool& marked_for_deopt,
|
|
- bool clear_all_softrefs);
|
|
+ bool clear_all_softrefs,
|
|
+ GenMarkSweep* marks);
|
|
// Calculate new addresses
|
|
static void mark_sweep_phase2(G1FullGCCompactionPoints* cps);
|
|
// Update pointers
|
|
- static void mark_sweep_phase3();
|
|
+ static void mark_sweep_phase3(GenMarkSweep* marks);
|
|
// Move objects to new positions
|
|
static void mark_sweep_phase4(G1FullGCCompactionPoints* cps);
|
|
|
|
diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1RootProcessor.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1RootProcessor.cpp
|
|
index 5b27a017a..6b0f8e8bd 100644
|
|
--- a/hotspot/src/share/vm/gc_implementation/g1/g1RootProcessor.cpp
|
|
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1RootProcessor.cpp
|
|
@@ -213,10 +213,11 @@ void G1RootProcessor::evacuate_roots(OopClosure* scan_non_heap_roots,
|
|
|
|
void G1RootProcessor::process_strong_roots(OopClosure* oops,
|
|
CLDClosure* clds,
|
|
- CodeBlobClosure* blobs) {
|
|
+ CodeBlobClosure* blobs,
|
|
+ uint worker_id) {
|
|
|
|
- process_java_roots(oops, clds, clds, NULL, blobs, NULL, 0);
|
|
- process_vm_roots(oops, NULL, NULL, 0);
|
|
+ process_java_roots(oops, clds, clds, NULL, blobs, NULL, worker_id);
|
|
+ process_vm_roots(oops, NULL, NULL, worker_id);
|
|
|
|
_process_strong_tasks.all_tasks_completed();
|
|
}
|
|
@@ -224,23 +225,25 @@ void G1RootProcessor::process_strong_roots(OopClosure* oops,
|
|
void G1RootProcessor::process_all_roots(OopClosure* oops,
|
|
CLDClosure* clds,
|
|
CodeBlobClosure* blobs,
|
|
- bool process_string_table) {
|
|
+ bool process_string_table,
|
|
+ uint worker_id) {
|
|
|
|
- process_java_roots(oops, NULL, clds, clds, NULL, NULL, 0);
|
|
- process_vm_roots(oops, oops, NULL, 0);
|
|
+ process_java_roots(oops, NULL, clds, clds, NULL, NULL, worker_id);
|
|
+ process_vm_roots(oops, oops, NULL, worker_id);
|
|
|
|
if (process_string_table) {
|
|
- process_string_table_roots(oops, NULL, 0);
|
|
+ process_string_table_roots(oops, NULL, worker_id);
|
|
}
|
|
- process_code_cache_roots(blobs, NULL, 0);
|
|
+ process_code_cache_roots(blobs, NULL, worker_id);
|
|
|
|
_process_strong_tasks.all_tasks_completed();
|
|
}
|
|
|
|
void G1RootProcessor::process_all_roots(OopClosure* oops,
|
|
CLDClosure* clds,
|
|
- CodeBlobClosure* blobs) {
|
|
- process_all_roots(oops, clds, blobs, true);
|
|
+ CodeBlobClosure* blobs,
|
|
+ uint worker_id) {
|
|
+ process_all_roots(oops, clds, blobs, true, worker_id);
|
|
}
|
|
|
|
void G1RootProcessor::process_all_roots_no_string_table(OopClosure* oops,
|
|
diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1RootProcessor.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1RootProcessor.hpp
|
|
index ad4e75ba3..8395ee2e4 100644
|
|
--- a/hotspot/src/share/vm/gc_implementation/g1/g1RootProcessor.hpp
|
|
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1RootProcessor.hpp
|
|
@@ -75,7 +75,8 @@ class G1RootProcessor : public StackObj {
|
|
void process_all_roots(OopClosure* oops,
|
|
CLDClosure* clds,
|
|
CodeBlobClosure* blobs,
|
|
- bool process_string_table);
|
|
+ bool process_string_table,
|
|
+ uint worker_id = 0);
|
|
|
|
void process_java_roots(OopClosure* scan_non_heap_roots,
|
|
CLDClosure* thread_stack_clds,
|
|
@@ -114,12 +115,14 @@ public:
|
|
// Apply oops, clds and blobs to all strongly reachable roots in the system
|
|
void process_strong_roots(OopClosure* oops,
|
|
CLDClosure* clds,
|
|
- CodeBlobClosure* blobs);
|
|
+ CodeBlobClosure* blobs,
|
|
+ uint worker_id = 0);
|
|
|
|
// Apply oops, clds and blobs to strongly and weakly reachable roots in the system
|
|
void process_all_roots(OopClosure* oops,
|
|
CLDClosure* clds,
|
|
- CodeBlobClosure* blobs);
|
|
+ CodeBlobClosure* blobs,
|
|
+ uint worker_id = 0);
|
|
|
|
// Apply scan_rs to all locations in the union of the remembered sets for all
|
|
// regions in the collection set
|
|
diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1StringDedup.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1StringDedup.cpp
|
|
index bb960ee3a..804d1e141 100644
|
|
--- a/hotspot/src/share/vm/gc_implementation/g1/g1StringDedup.cpp
|
|
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1StringDedup.cpp
|
|
@@ -49,10 +49,10 @@ void G1StringDedup::stop() {
|
|
G1StringDedupThread::stop();
|
|
}
|
|
|
|
-bool G1StringDedup::is_candidate_from_mark(oop obj) {
|
|
+bool G1StringDedup::is_candidate_from_mark(oop obj, uint age) {
|
|
if (java_lang_String::is_instance(obj)) {
|
|
bool from_young = G1CollectedHeap::heap()->heap_region_containing_raw(obj)->is_young();
|
|
- if (from_young && obj->age() < StringDeduplicationAgeThreshold) {
|
|
+ if (from_young && age < StringDeduplicationAgeThreshold) {
|
|
// Candidate found. String is being evacuated from young to old but has not
|
|
// reached the deduplication age threshold, i.e. has not previously been a
|
|
// candidate during its life in the young generation.
|
|
@@ -64,10 +64,10 @@ bool G1StringDedup::is_candidate_from_mark(oop obj) {
|
|
return false;
|
|
}
|
|
|
|
-void G1StringDedup::enqueue_from_mark(oop java_string) {
|
|
+void G1StringDedup::enqueue_from_mark(oop java_string, uint age, uint worker_id) {
|
|
assert(is_enabled(), "String deduplication not enabled");
|
|
- if (is_candidate_from_mark(java_string)) {
|
|
- G1StringDedupQueue::push(0 /* worker_id */, java_string);
|
|
+ if (is_candidate_from_mark(java_string, age)) {
|
|
+ G1StringDedupQueue::push(worker_id /* worker_id */, java_string);
|
|
}
|
|
}
|
|
|
|
diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1StringDedup.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1StringDedup.hpp
|
|
index 3792a667a..d14284b9a 100644
|
|
--- a/hotspot/src/share/vm/gc_implementation/g1/g1StringDedup.hpp
|
|
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1StringDedup.hpp
|
|
@@ -102,7 +102,7 @@ private:
|
|
|
|
// Candidate selection policies, returns true if the given object is
|
|
// candidate for string deduplication.
|
|
- static bool is_candidate_from_mark(oop obj);
|
|
+ static bool is_candidate_from_mark(oop obj, uint age);
|
|
static bool is_candidate_from_evacuation(bool from_young, bool to_young, oop obj);
|
|
|
|
public:
|
|
@@ -124,7 +124,7 @@ public:
|
|
// Enqueues a deduplication candidate for later processing by the deduplication
|
|
// thread. Before enqueuing, these functions apply the appropriate candidate
|
|
// selection policy to filters out non-candidates.
|
|
- static void enqueue_from_mark(oop java_string);
|
|
+ static void enqueue_from_mark(oop java_string, uint age, uint worker_id);
|
|
static void enqueue_from_evacuation(bool from_young, bool to_young,
|
|
unsigned int queue, oop java_string);
|
|
|
|
diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp
|
|
index a8a87cc1b..74c15844b 100644
|
|
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp
|
|
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp
|
|
@@ -430,7 +430,7 @@ void ParallelScavengeHeap::do_full_collection(bool clear_all_soft_refs) {
|
|
bool maximum_compaction = clear_all_soft_refs;
|
|
PSParallelCompact::invoke(maximum_compaction);
|
|
} else {
|
|
- PSMarkSweep::invoke(clear_all_soft_refs);
|
|
+ PSMarkSweep::the_ps_mark()->invoke(clear_all_soft_refs);
|
|
}
|
|
}
|
|
|
|
diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp
|
|
index 2542ba1ca..4f8890f04 100644
|
|
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp
|
|
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp
|
|
@@ -59,10 +59,15 @@
|
|
|
|
PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
|
|
|
|
+MarkSweep* PSMarkSweep::_the_ps_mark = NULL;
|
|
elapsedTimer PSMarkSweep::_accumulated_time;
|
|
jlong PSMarkSweep::_time_of_last_gc = 0;
|
|
CollectorCounters* PSMarkSweep::_counters = NULL;
|
|
|
|
+void PSMarkSweep::ps_marksweep_init() {
|
|
+ PSMarkSweep::_the_ps_mark = new (ResourceObj::C_HEAP, mtGC) PSMarkSweep();
|
|
+}
|
|
+
|
|
void PSMarkSweep::initialize() {
|
|
MemRegion mr = Universe::heap()->reserved_region();
|
|
_ref_processor = new ReferenceProcessor(mr); // a vanilla ref proc
|
|
diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.hpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.hpp
|
|
index 46073f9e2..01666ea4d 100644
|
|
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.hpp
|
|
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.hpp
|
|
@@ -34,34 +34,36 @@ class PSYoungGen;
|
|
class PSOldGen;
|
|
|
|
class PSMarkSweep : public MarkSweep {
|
|
+ friend void marksweep_init();
|
|
private:
|
|
static elapsedTimer _accumulated_time;
|
|
static jlong _time_of_last_gc; // ms
|
|
static CollectorCounters* _counters;
|
|
+ static MarkSweep* _the_ps_mark;
|
|
|
|
// Closure accessors
|
|
- static OopClosure* mark_and_push_closure() { return &MarkSweep::mark_and_push_closure; }
|
|
- static VoidClosure* follow_stack_closure() { return (VoidClosure*)&MarkSweep::follow_stack_closure; }
|
|
- static CLDClosure* follow_cld_closure() { return &MarkSweep::follow_cld_closure; }
|
|
- static OopClosure* adjust_pointer_closure() { return (OopClosure*)&MarkSweep::adjust_pointer_closure; }
|
|
- static CLDClosure* adjust_cld_closure() { return &MarkSweep::adjust_cld_closure; }
|
|
- static BoolObjectClosure* is_alive_closure() { return (BoolObjectClosure*)&MarkSweep::is_alive; }
|
|
+ OopClosure* mark_and_push_closure() { return &(MarkSweep::mark_and_push_closure); }
|
|
+ VoidClosure* follow_stack_closure() { return (VoidClosure*)&(MarkSweep::follow_stack_closure); }
|
|
+ CLDClosure* follow_cld_closure() { return &(MarkSweep::follow_cld_closure); }
|
|
+ OopClosure* adjust_pointer_closure() { return (OopClosure*)&(MarkSweep::adjust_pointer_closure); }
|
|
+ CLDClosure* adjust_cld_closure() { return &(MarkSweep::adjust_cld_closure); }
|
|
+ BoolObjectClosure* is_alive_closure() { return (BoolObjectClosure*)&(MarkSweep::is_alive); }
|
|
|
|
debug_only(public:) // Used for PSParallelCompact debugging
|
|
// Mark live objects
|
|
- static void mark_sweep_phase1(bool clear_all_softrefs);
|
|
+ void mark_sweep_phase1(bool clear_all_softrefs);
|
|
// Calculate new addresses
|
|
- static void mark_sweep_phase2();
|
|
+ void mark_sweep_phase2();
|
|
debug_only(private:) // End used for PSParallelCompact debugging
|
|
// Update pointers
|
|
- static void mark_sweep_phase3();
|
|
+ void mark_sweep_phase3();
|
|
// Move objects to new positions
|
|
- static void mark_sweep_phase4();
|
|
+ void mark_sweep_phase4();
|
|
|
|
debug_only(public:) // Used for PSParallelCompact debugging
|
|
// Temporary data structures for traversal and storing/restoring marks
|
|
- static void allocate_stacks();
|
|
- static void deallocate_stacks();
|
|
+ void allocate_stacks();
|
|
+ void deallocate_stacks();
|
|
static void set_ref_processor(ReferenceProcessor* rp) { // delete this method
|
|
_ref_processor = rp;
|
|
}
|
|
@@ -75,10 +77,13 @@ class PSMarkSweep : public MarkSweep {
|
|
|
|
// Reset time since last full gc
|
|
static void reset_millis_since_last_gc();
|
|
+ static void ps_marksweep_init();
|
|
|
|
public:
|
|
- static void invoke(bool clear_all_softrefs);
|
|
- static bool invoke_no_policy(bool clear_all_softrefs);
|
|
+ static inline PSMarkSweep* the_ps_mark() { return (PSMarkSweep*)_the_ps_mark; }
|
|
+
|
|
+ void invoke(bool clear_all_softrefs);
|
|
+ bool invoke_no_policy(bool clear_all_softrefs);
|
|
|
|
static void initialize();
|
|
|
|
diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp
|
|
index 12e282eeb..670cd3e64 100644
|
|
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp
|
|
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp
|
|
@@ -248,7 +248,7 @@ bool PSScavenge::invoke() {
|
|
if (UseParallelOldGC) {
|
|
full_gc_done = PSParallelCompact::invoke_no_policy(clear_all_softrefs);
|
|
} else {
|
|
- full_gc_done = PSMarkSweep::invoke_no_policy(clear_all_softrefs);
|
|
+ full_gc_done = PSMarkSweep::the_ps_mark()->invoke_no_policy(clear_all_softrefs);
|
|
}
|
|
}
|
|
|
|
diff --git a/hotspot/src/share/vm/gc_implementation/shared/markSweep.cpp b/hotspot/src/share/vm/gc_implementation/shared/markSweep.cpp
|
|
index e2629b652..596207934 100644
|
|
--- a/hotspot/src/share/vm/gc_implementation/shared/markSweep.cpp
|
|
+++ b/hotspot/src/share/vm/gc_implementation/shared/markSweep.cpp
|
|
@@ -24,10 +24,12 @@
|
|
|
|
#include "precompiled.hpp"
|
|
#include "compiler/compileBroker.hpp"
|
|
+#include "gc_implementation/parallelScavenge/psMarkSweep.hpp"
|
|
#include "gc_implementation/shared/gcTimer.hpp"
|
|
#include "gc_implementation/shared/gcTrace.hpp"
|
|
#include "gc_implementation/shared/markSweep.inline.hpp"
|
|
#include "gc_interface/collectedHeap.inline.hpp"
|
|
+#include "memory/genMarkSweep.hpp"
|
|
#include "oops/methodData.hpp"
|
|
#include "oops/objArrayKlass.inline.hpp"
|
|
#include "oops/oop.inline.hpp"
|
|
@@ -36,53 +38,41 @@ PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
|
|
|
|
uint MarkSweep::_total_invocations = 0;
|
|
|
|
-Stack<oop, mtGC> MarkSweep::_marking_stack;
|
|
-Stack<ObjArrayTask, mtGC> MarkSweep::_objarray_stack;
|
|
-
|
|
-Stack<oop, mtGC> MarkSweep::_preserved_oop_stack;
|
|
-Stack<markOop, mtGC> MarkSweep::_preserved_mark_stack;
|
|
-size_t MarkSweep::_preserved_count = 0;
|
|
-size_t MarkSweep::_preserved_count_max = 0;
|
|
-PreservedMark* MarkSweep::_preserved_marks = NULL;
|
|
ReferenceProcessor* MarkSweep::_ref_processor = NULL;
|
|
STWGCTimer* MarkSweep::_gc_timer = NULL;
|
|
SerialOldTracer* MarkSweep::_gc_tracer = NULL;
|
|
|
|
-MarkSweep::FollowRootClosure MarkSweep::follow_root_closure;
|
|
-
|
|
-void MarkSweep::FollowRootClosure::do_oop(oop* p) { follow_root(p); }
|
|
-void MarkSweep::FollowRootClosure::do_oop(narrowOop* p) { follow_root(p); }
|
|
-
|
|
-MarkSweep::MarkAndPushClosure MarkSweep::mark_and_push_closure;
|
|
-CLDToOopClosure MarkSweep::follow_cld_closure(&mark_and_push_closure);
|
|
-CLDToOopClosure MarkSweep::adjust_cld_closure(&adjust_pointer_closure);
|
|
+void MarkSweep::FollowRootClosure::do_oop(oop* p) { _mark->follow_root(p); }
|
|
+void MarkSweep::FollowRootClosure::do_oop(narrowOop* p) { _mark->follow_root(p); }
|
|
|
|
-void MarkSweep::MarkAndPushClosure::do_oop(oop* p) { mark_and_push(p); }
|
|
-void MarkSweep::MarkAndPushClosure::do_oop(narrowOop* p) { mark_and_push(p); }
|
|
+void MarkSweep::MarkAndPushClosure::do_oop(oop* p) { _mark->mark_and_push(p); }
|
|
+void MarkSweep::MarkAndPushClosure::do_oop(narrowOop* p) { _mark->mark_and_push(p); }
|
|
|
|
void MarkSweep::follow_class_loader(ClassLoaderData* cld) {
|
|
MarkSweep::follow_cld_closure.do_cld(cld);
|
|
}
|
|
|
|
+MarkSweep* MarkSweep::the_mark() {
|
|
+ return GenMarkSweep::the_gen_mark();
|
|
+}
|
|
+
|
|
void MarkSweep::follow_stack() {
|
|
do {
|
|
while (!_marking_stack.is_empty()) {
|
|
oop obj = _marking_stack.pop();
|
|
assert (obj->is_gc_marked(), "p must be marked");
|
|
- obj->follow_contents();
|
|
+ obj->follow_contents(this);
|
|
}
|
|
// Process ObjArrays one at a time to avoid marking stack bloat.
|
|
if (!_objarray_stack.is_empty()) {
|
|
ObjArrayTask task = _objarray_stack.pop();
|
|
ObjArrayKlass* k = (ObjArrayKlass*)task.obj()->klass();
|
|
- k->oop_follow_contents(task.obj(), task.index());
|
|
+ k->oop_follow_contents(task.obj(), task.index(), this);
|
|
}
|
|
} while (!_marking_stack.is_empty() || !_objarray_stack.is_empty());
|
|
}
|
|
|
|
-MarkSweep::FollowStackClosure MarkSweep::follow_stack_closure;
|
|
-
|
|
-void MarkSweep::FollowStackClosure::do_void() { follow_stack(); }
|
|
+void MarkSweep::FollowStackClosure::do_void() { _mark->follow_stack(); }
|
|
|
|
// We preserve the mark which should be replaced at the end and the location
|
|
// that it will go. Note that the object that this markOop belongs to isn't
|
|
@@ -100,8 +90,6 @@ void MarkSweep::preserve_mark(oop obj, markOop mark) {
|
|
}
|
|
}
|
|
|
|
-MarkSweep::AdjustPointerClosure MarkSweep::adjust_pointer_closure;
|
|
-
|
|
void MarkSweep::AdjustPointerClosure::do_oop(oop* p) { adjust_pointer(p); }
|
|
void MarkSweep::AdjustPointerClosure::do_oop(narrowOop* p) { adjust_pointer(p); }
|
|
|
|
@@ -143,18 +131,16 @@ void MarkSweep::restore_marks() {
|
|
}
|
|
}
|
|
|
|
-MarkSweep::IsAliveClosure MarkSweep::is_alive;
|
|
-
|
|
bool MarkSweep::IsAliveClosure::do_object_b(oop p) { return p->is_gc_marked(); }
|
|
|
|
-MarkSweep::KeepAliveClosure MarkSweep::keep_alive;
|
|
-
|
|
void MarkSweep::KeepAliveClosure::do_oop(oop* p) { MarkSweep::KeepAliveClosure::do_oop_work(p); }
|
|
void MarkSweep::KeepAliveClosure::do_oop(narrowOop* p) { MarkSweep::KeepAliveClosure::do_oop_work(p); }
|
|
|
|
void marksweep_init() {
|
|
MarkSweep::_gc_timer = new (ResourceObj::C_HEAP, mtGC) STWGCTimer();
|
|
MarkSweep::_gc_tracer = new (ResourceObj::C_HEAP, mtGC) SerialOldTracer();
|
|
+ PSMarkSweep::ps_marksweep_init();
|
|
+ GenMarkSweep::gen_marksweep_init();
|
|
}
|
|
|
|
#ifndef PRODUCT
|
|
diff --git a/hotspot/src/share/vm/gc_implementation/shared/markSweep.hpp b/hotspot/src/share/vm/gc_implementation/shared/markSweep.hpp
|
|
index 462643e2f..813a5aef7 100644
|
|
--- a/hotspot/src/share/vm/gc_implementation/shared/markSweep.hpp
|
|
+++ b/hotspot/src/share/vm/gc_implementation/shared/markSweep.hpp
|
|
@@ -49,43 +49,55 @@ class STWGCTimer;
|
|
// declared at end
|
|
class PreservedMark;
|
|
|
|
-class MarkSweep : AllStatic {
|
|
+class MarkSweep : public ResourceObj {
|
|
//
|
|
// Inline closure decls
|
|
//
|
|
class FollowRootClosure: public OopsInGenClosure {
|
|
+ MarkSweep* _mark;
|
|
public:
|
|
+ FollowRootClosure(MarkSweep* mark) : _mark(mark) { }
|
|
virtual void do_oop(oop* p);
|
|
virtual void do_oop(narrowOop* p);
|
|
};
|
|
|
|
class MarkAndPushClosure: public OopClosure {
|
|
+ MarkSweep* _mark;
|
|
public:
|
|
+ MarkAndPushClosure(MarkSweep* mark) : _mark(mark) { }
|
|
virtual void do_oop(oop* p);
|
|
virtual void do_oop(narrowOop* p);
|
|
};
|
|
|
|
class FollowStackClosure: public VoidClosure {
|
|
+ MarkSweep* _mark;
|
|
public:
|
|
+ FollowStackClosure(MarkSweep* mark) : _mark(mark) { }
|
|
virtual void do_void();
|
|
};
|
|
|
|
class AdjustPointerClosure: public OopsInGenClosure {
|
|
+ MarkSweep* _mark;
|
|
public:
|
|
+ AdjustPointerClosure(MarkSweep* mark) : _mark(mark) { }
|
|
virtual void do_oop(oop* p);
|
|
virtual void do_oop(narrowOop* p);
|
|
};
|
|
|
|
// Used for java/lang/ref handling
|
|
class IsAliveClosure: public BoolObjectClosure {
|
|
+ MarkSweep* _mark;
|
|
public:
|
|
+ IsAliveClosure(MarkSweep* mark) : _mark(mark) { }
|
|
virtual bool do_object_b(oop p);
|
|
};
|
|
|
|
class KeepAliveClosure: public OopClosure {
|
|
+ MarkSweep* _mark;
|
|
protected:
|
|
template <class T> void do_oop_work(T* p);
|
|
public:
|
|
+ KeepAliveClosure(MarkSweep* mark) : _mark(mark) { }
|
|
virtual void do_oop(oop* p);
|
|
virtual void do_oop(narrowOop* p);
|
|
};
|
|
@@ -106,37 +118,49 @@ class MarkSweep : AllStatic {
|
|
static uint _total_invocations;
|
|
|
|
// Traversal stacks used during phase1
|
|
- static Stack<oop, mtGC> _marking_stack;
|
|
- static Stack<ObjArrayTask, mtGC> _objarray_stack;
|
|
+ Stack<oop, mtGC> _marking_stack;
|
|
+ Stack<ObjArrayTask, mtGC> _objarray_stack;
|
|
|
|
// Space for storing/restoring mark word
|
|
- static Stack<markOop, mtGC> _preserved_mark_stack;
|
|
- static Stack<oop, mtGC> _preserved_oop_stack;
|
|
- static size_t _preserved_count;
|
|
- static size_t _preserved_count_max;
|
|
- static PreservedMark* _preserved_marks;
|
|
+ Stack<markOop, mtGC> _preserved_mark_stack;
|
|
+ Stack<oop, mtGC> _preserved_oop_stack;
|
|
+ size_t _preserved_count;
|
|
+ size_t _preserved_count_max;
|
|
+ PreservedMark* _preserved_marks;
|
|
|
|
+ uint _worker_id;
|
|
// Reference processing (used in ...follow_contents)
|
|
static ReferenceProcessor* _ref_processor;
|
|
|
|
static STWGCTimer* _gc_timer;
|
|
static SerialOldTracer* _gc_tracer;
|
|
|
|
- // Non public closures
|
|
- static KeepAliveClosure keep_alive;
|
|
-
|
|
// Debugging
|
|
static void trace(const char* msg) PRODUCT_RETURN;
|
|
+ bool par_mark(oop obj);
|
|
|
|
public:
|
|
+ static MarkSweep* the_mark();
|
|
+ KeepAliveClosure keep_alive;
|
|
// Public closures
|
|
- static IsAliveClosure is_alive;
|
|
- static FollowRootClosure follow_root_closure;
|
|
- static MarkAndPushClosure mark_and_push_closure;
|
|
- static FollowStackClosure follow_stack_closure;
|
|
- static CLDToOopClosure follow_cld_closure;
|
|
- static AdjustPointerClosure adjust_pointer_closure;
|
|
- static CLDToOopClosure adjust_cld_closure;
|
|
+ IsAliveClosure is_alive;
|
|
+ FollowRootClosure follow_root_closure;
|
|
+ MarkAndPushClosure mark_and_push_closure;
|
|
+ FollowStackClosure follow_stack_closure;
|
|
+ CLDToOopClosure follow_cld_closure;
|
|
+ AdjustPointerClosure adjust_pointer_closure;
|
|
+ CLDToOopClosure adjust_cld_closure;
|
|
+
|
|
+ MarkSweep() :
|
|
+ is_alive(this),
|
|
+ follow_root_closure(this),
|
|
+ mark_and_push_closure(this),
|
|
+ follow_stack_closure(this),
|
|
+ follow_cld_closure(&mark_and_push_closure),
|
|
+ adjust_pointer_closure(this),
|
|
+ adjust_cld_closure(&adjust_pointer_closure),
|
|
+ keep_alive(this)
|
|
+ { }
|
|
|
|
// Accessors
|
|
static uint total_invocations() { return _total_invocations; }
|
|
@@ -147,26 +171,23 @@ class MarkSweep : AllStatic {
|
|
static STWGCTimer* gc_timer() { return _gc_timer; }
|
|
static SerialOldTracer* gc_tracer() { return _gc_tracer; }
|
|
|
|
+ void set_worker_id(uint worker_id) { _worker_id = worker_id; }
|
|
// Call backs for marking
|
|
- static void mark_object(oop obj);
|
|
+ bool mark_object(oop obj);
|
|
// Mark pointer and follow contents. Empty marking stack afterwards.
|
|
- template <class T> static inline void follow_root(T* p);
|
|
+ template <class T> inline void follow_root(T* p);
|
|
|
|
// Check mark and maybe push on marking stack
|
|
- template <class T> static void mark_and_push(T* p);
|
|
-
|
|
- static inline void push_objarray(oop obj, size_t index);
|
|
-
|
|
- static void follow_stack(); // Empty marking stack.
|
|
-
|
|
- static void follow_klass(Klass* klass);
|
|
-
|
|
- static void follow_class_loader(ClassLoaderData* cld);
|
|
-
|
|
- static void preserve_mark(oop p, markOop mark);
|
|
- // Save the mark word so it can be restored later
|
|
- static void adjust_marks(); // Adjust the pointers in the preserved marks table
|
|
- static void restore_marks(); // Restore the marks that we saved in preserve_mark
|
|
+ template <class T> void mark_and_push(T* p);
|
|
+
|
|
+ inline void push_objarray(oop obj, size_t index);
|
|
+ void follow_stack(); // Empty marking st
|
|
+ void follow_klass(Klass* klass);
|
|
+ void follow_class_loader(ClassLoaderData* cld);
|
|
+ void preserve_mark(oop p, markOop mark);
|
|
+ // Save the mark word so it can be restored later
|
|
+ void adjust_marks(); // Adjust the pointers in the preserved marks table
|
|
+ void restore_marks(); // Restore the marks that we saved in preserve_mark
|
|
|
|
template <class T> static inline void adjust_pointer(T* p);
|
|
};
|
|
diff --git a/hotspot/src/share/vm/gc_implementation/shared/markSweep.inline.hpp b/hotspot/src/share/vm/gc_implementation/shared/markSweep.inline.hpp
|
|
index c08e7a637..f9ede2487 100644
|
|
--- a/hotspot/src/share/vm/gc_implementation/shared/markSweep.inline.hpp
|
|
+++ b/hotspot/src/share/vm/gc_implementation/shared/markSweep.inline.hpp
|
|
@@ -34,22 +34,43 @@
|
|
#include "gc_implementation/parallelScavenge/psParallelCompact.hpp"
|
|
#endif // INCLUDE_ALL_GCS
|
|
|
|
-inline void MarkSweep::mark_object(oop obj) {
|
|
+inline bool MarkSweep::par_mark(oop obj) {
|
|
+ markOop origin = obj->mark();
|
|
+ markOop target = markOopDesc::prototype()->set_marked();
|
|
+ void* res = Atomic::cmpxchg_ptr(target, obj->mark_addr(), origin);
|
|
+ if (res == origin) {
|
|
+ return true;
|
|
+ } else {
|
|
+ return false;
|
|
+ }
|
|
+}
|
|
+
|
|
+inline bool MarkSweep::mark_object(oop obj) {
|
|
+ markOop mark = obj->mark();
|
|
#if INCLUDE_ALL_GCS
|
|
if (G1StringDedup::is_enabled()) {
|
|
// We must enqueue the object before it is marked
|
|
// as we otherwise can't read the object's age.
|
|
- G1StringDedup::enqueue_from_mark(obj);
|
|
+ uint age = 0;
|
|
+ if (mark->has_displaced_mark_helper()) {
|
|
+ age = mark->displaced_mark_helper()->age();
|
|
+ } else {
|
|
+ age = mark->age();
|
|
+ }
|
|
+
|
|
+ G1StringDedup::enqueue_from_mark(obj, age, _worker_id);
|
|
}
|
|
#endif
|
|
// some marks may contain information we need to preserve so we store them away
|
|
// and overwrite the mark. We'll restore it at the end of markSweep.
|
|
- markOop mark = obj->mark();
|
|
- obj->set_mark(markOopDesc::prototype()->set_marked());
|
|
+ if (mark->is_marked() || !par_mark(obj)) {
|
|
+ return false;
|
|
+ }
|
|
|
|
if (mark->must_be_preserved(obj)) {
|
|
preserve_mark(obj, mark);
|
|
}
|
|
+ return true;
|
|
}
|
|
|
|
inline void MarkSweep::follow_klass(Klass* klass) {
|
|
@@ -64,8 +85,9 @@ template <class T> inline void MarkSweep::follow_root(T* p) {
|
|
if (!oopDesc::is_null(heap_oop)) {
|
|
oop obj = oopDesc::decode_heap_oop_not_null(heap_oop);
|
|
if (!obj->mark()->is_marked()) {
|
|
- mark_object(obj);
|
|
- obj->follow_contents();
|
|
+ if (mark_object(obj)) {
|
|
+ obj->follow_contents(this);
|
|
+ }
|
|
}
|
|
}
|
|
follow_stack();
|
|
@@ -77,8 +99,9 @@ template <class T> inline void MarkSweep::mark_and_push(T* p) {
|
|
if (!oopDesc::is_null(heap_oop)) {
|
|
oop obj = oopDesc::decode_heap_oop_not_null(heap_oop);
|
|
if (!obj->mark()->is_marked()) {
|
|
- mark_object(obj);
|
|
- _marking_stack.push(obj);
|
|
+ if (mark_object(obj)) {
|
|
+ _marking_stack.push(obj);
|
|
+ }
|
|
}
|
|
}
|
|
}
|
|
@@ -108,7 +131,7 @@ template <class T> inline void MarkSweep::adjust_pointer(T* p) {
|
|
}
|
|
|
|
template <class T> inline void MarkSweep::KeepAliveClosure::do_oop_work(T* p) {
|
|
- mark_and_push(p);
|
|
+ _mark->mark_and_push(p);
|
|
}
|
|
|
|
#endif // SHARE_VM_GC_IMPLEMENTATION_SHARED_MARKSWEEP_INLINE_HPP
|
|
diff --git a/hotspot/src/share/vm/memory/genMarkSweep.cpp b/hotspot/src/share/vm/memory/genMarkSweep.cpp
|
|
index c5dc4947c..132703d5a 100644
|
|
--- a/hotspot/src/share/vm/memory/genMarkSweep.cpp
|
|
+++ b/hotspot/src/share/vm/memory/genMarkSweep.cpp
|
|
@@ -52,6 +52,12 @@
|
|
#include "utilities/copy.hpp"
|
|
#include "utilities/events.hpp"
|
|
|
|
+GenMarkSweep* GenMarkSweep::_the_gen_mark = NULL;
|
|
+
|
|
+void GenMarkSweep::gen_marksweep_init() {
|
|
+ GenMarkSweep::_the_gen_mark = new (ResourceObj::C_HEAP, mtGC) GenMarkSweep();
|
|
+}
|
|
+
|
|
void GenMarkSweep::invoke_at_safepoint(int level, ReferenceProcessor* rp, bool clear_all_softrefs) {
|
|
guarantee(level == 1, "We always collect both old and young.");
|
|
assert(SafepointSynchronize::is_at_safepoint(), "must be at a safepoint");
|
|
diff --git a/hotspot/src/share/vm/memory/genMarkSweep.hpp b/hotspot/src/share/vm/memory/genMarkSweep.hpp
|
|
index b6147ab5b..76d4ae1a2 100644
|
|
--- a/hotspot/src/share/vm/memory/genMarkSweep.hpp
|
|
+++ b/hotspot/src/share/vm/memory/genMarkSweep.hpp
|
|
@@ -30,24 +30,28 @@
|
|
class GenMarkSweep : public MarkSweep {
|
|
friend class VM_MarkSweep;
|
|
friend class G1MarkSweep;
|
|
+ friend void marksweep_init();
|
|
+ static GenMarkSweep* _the_gen_mark;
|
|
+ static void gen_marksweep_init();
|
|
public:
|
|
- static void invoke_at_safepoint(int level, ReferenceProcessor* rp,
|
|
+ static inline GenMarkSweep* the_gen_mark() { return _the_gen_mark; }
|
|
+ void invoke_at_safepoint(int level, ReferenceProcessor* rp,
|
|
bool clear_all_softrefs);
|
|
|
|
private:
|
|
|
|
// Mark live objects
|
|
- static void mark_sweep_phase1(int level, bool clear_all_softrefs);
|
|
+ void mark_sweep_phase1(int level, bool clear_all_softrefs);
|
|
// Calculate new addresses
|
|
- static void mark_sweep_phase2();
|
|
+ void mark_sweep_phase2();
|
|
// Update pointers
|
|
- static void mark_sweep_phase3(int level);
|
|
+ void mark_sweep_phase3(int level);
|
|
// Move objects to new positions
|
|
- static void mark_sweep_phase4();
|
|
+ void mark_sweep_phase4();
|
|
|
|
// Temporary data structures for traversal and storing/restoring marks
|
|
- static void allocate_stacks();
|
|
- static void deallocate_stacks();
|
|
+ void allocate_stacks();
|
|
+ void deallocate_stacks();
|
|
};
|
|
|
|
#endif // SHARE_VM_MEMORY_GENMARKSWEEP_HPP
|
|
diff --git a/hotspot/src/share/vm/memory/generation.cpp b/hotspot/src/share/vm/memory/generation.cpp
|
|
index 9d6c926e1..4e9848bb9 100644
|
|
--- a/hotspot/src/share/vm/memory/generation.cpp
|
|
+++ b/hotspot/src/share/vm/memory/generation.cpp
|
|
@@ -648,7 +648,7 @@ void OneContigSpaceCardGeneration::collect(bool full,
|
|
SerialOldTracer* gc_tracer = GenMarkSweep::gc_tracer();
|
|
gc_tracer->report_gc_start(gch->gc_cause(), gc_timer->gc_start());
|
|
|
|
- GenMarkSweep::invoke_at_safepoint(_level, ref_processor(), clear_all_soft_refs);
|
|
+ GenMarkSweep::the_gen_mark()->invoke_at_safepoint(_level, ref_processor(), clear_all_soft_refs);
|
|
|
|
gc_timer->register_gc_end();
|
|
|
|
diff --git a/hotspot/src/share/vm/oops/instanceClassLoaderKlass.cpp b/hotspot/src/share/vm/oops/instanceClassLoaderKlass.cpp
|
|
index 131ecbfb0..bb35ffd38 100644
|
|
--- a/hotspot/src/share/vm/oops/instanceClassLoaderKlass.cpp
|
|
+++ b/hotspot/src/share/vm/oops/instanceClassLoaderKlass.cpp
|
|
@@ -114,14 +114,14 @@ ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceClassLoaderKlass_OOP_OOP_ITERATE_BACKWARD
|
|
ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceClassLoaderKlass_OOP_OOP_ITERATE_DEFN_m)
|
|
ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceClassLoaderKlass_OOP_OOP_ITERATE_DEFN_m)
|
|
|
|
-void InstanceClassLoaderKlass::oop_follow_contents(oop obj) {
|
|
- InstanceKlass::oop_follow_contents(obj);
|
|
+void InstanceClassLoaderKlass::oop_follow_contents(oop obj, MarkSweep* mark) {
|
|
+ InstanceKlass::oop_follow_contents(obj, mark);
|
|
ClassLoaderData * const loader_data = java_lang_ClassLoader::loader_data(obj);
|
|
|
|
// We must NULL check here, since the class loader
|
|
// can be found before the loader data has been set up.
|
|
if(loader_data != NULL) {
|
|
- MarkSweep::follow_class_loader(loader_data);
|
|
+ mark->follow_class_loader(loader_data);
|
|
}
|
|
}
|
|
|
|
diff --git a/hotspot/src/share/vm/oops/instanceClassLoaderKlass.hpp b/hotspot/src/share/vm/oops/instanceClassLoaderKlass.hpp
|
|
index 309ebf96c..47abfed45 100644
|
|
--- a/hotspot/src/share/vm/oops/instanceClassLoaderKlass.hpp
|
|
+++ b/hotspot/src/share/vm/oops/instanceClassLoaderKlass.hpp
|
|
@@ -71,7 +71,7 @@ public:
|
|
#endif // INCLUDE_ALL_GCS
|
|
|
|
// Garbage collection
|
|
- void oop_follow_contents(oop obj);
|
|
+ void oop_follow_contents(oop obj, MarkSweep* mark);
|
|
|
|
// Parallel Scavenge and Parallel Old
|
|
PARALLEL_GC_DECLS
|
|
diff --git a/hotspot/src/share/vm/oops/instanceKlass.cpp b/hotspot/src/share/vm/oops/instanceKlass.cpp
|
|
index c1707bf8b..895fbbf07 100644
|
|
--- a/hotspot/src/share/vm/oops/instanceKlass.cpp
|
|
+++ b/hotspot/src/share/vm/oops/instanceKlass.cpp
|
|
@@ -2280,12 +2280,12 @@ template <class T> void assert_nothing(T *p) {}
|
|
} \
|
|
}
|
|
|
|
-void InstanceKlass::oop_follow_contents(oop obj) {
|
|
+void InstanceKlass::oop_follow_contents(oop obj, MarkSweep* mark) {
|
|
assert(obj != NULL, "can't follow the content of NULL object");
|
|
- MarkSweep::follow_klass(obj->klass());
|
|
+ mark->follow_klass(obj->klass());
|
|
InstanceKlass_OOP_MAP_ITERATE( \
|
|
obj, \
|
|
- MarkSweep::mark_and_push(p), \
|
|
+ mark->mark_and_push(p), \
|
|
assert_is_in_closed_subset)
|
|
}
|
|
|
|
diff --git a/hotspot/src/share/vm/oops/instanceKlass.hpp b/hotspot/src/share/vm/oops/instanceKlass.hpp
|
|
index 3d6f85911..39d2c580c 100644
|
|
--- a/hotspot/src/share/vm/oops/instanceKlass.hpp
|
|
+++ b/hotspot/src/share/vm/oops/instanceKlass.hpp
|
|
@@ -1013,7 +1013,7 @@ class InstanceKlass: public Klass {
|
|
#endif // INCLUDE_JVMTI
|
|
|
|
// Garbage collection
|
|
- void oop_follow_contents(oop obj);
|
|
+ void oop_follow_contents(oop obj, MarkSweep* mark);
|
|
int oop_adjust_pointers(oop obj);
|
|
|
|
void clean_weak_instanceklass_links(BoolObjectClosure* is_alive);
|
|
diff --git a/hotspot/src/share/vm/oops/instanceMirrorKlass.cpp b/hotspot/src/share/vm/oops/instanceMirrorKlass.cpp
|
|
index 82c804108..fdf2e42af 100644
|
|
--- a/hotspot/src/share/vm/oops/instanceMirrorKlass.cpp
|
|
+++ b/hotspot/src/share/vm/oops/instanceMirrorKlass.cpp
|
|
@@ -150,8 +150,8 @@ template <class T> void assert_nothing(T *p) {}
|
|
}
|
|
|
|
|
|
-void InstanceMirrorKlass::oop_follow_contents(oop obj) {
|
|
- InstanceKlass::oop_follow_contents(obj);
|
|
+void InstanceMirrorKlass::oop_follow_contents(oop obj, MarkSweep* mark) {
|
|
+ InstanceKlass::oop_follow_contents(obj, mark);
|
|
|
|
// Follow the klass field in the mirror.
|
|
Klass* klass = java_lang_Class::as_Klass(obj);
|
|
@@ -164,9 +164,9 @@ void InstanceMirrorKlass::oop_follow_contents(oop obj) {
|
|
// the call to follow_class_loader is made when the class loader itself
|
|
// is handled.
|
|
if (klass->oop_is_instance() && InstanceKlass::cast(klass)->is_anonymous()) {
|
|
- MarkSweep::follow_class_loader(klass->class_loader_data());
|
|
+ mark->follow_class_loader(klass->class_loader_data());
|
|
} else {
|
|
- MarkSweep::follow_klass(klass);
|
|
+ mark->follow_klass(klass);
|
|
}
|
|
} else {
|
|
// If klass is NULL then this a mirror for a primitive type.
|
|
@@ -177,7 +177,7 @@ void InstanceMirrorKlass::oop_follow_contents(oop obj) {
|
|
|
|
InstanceMirrorKlass_OOP_ITERATE( \
|
|
start_of_static_fields(obj), java_lang_Class::static_oop_field_count(obj), \
|
|
- MarkSweep::mark_and_push(p), \
|
|
+ mark->mark_and_push(p), \
|
|
assert_is_in_closed_subset)
|
|
}
|
|
|
|
diff --git a/hotspot/src/share/vm/oops/instanceMirrorKlass.hpp b/hotspot/src/share/vm/oops/instanceMirrorKlass.hpp
|
|
index b861639ee..759f7d074 100644
|
|
--- a/hotspot/src/share/vm/oops/instanceMirrorKlass.hpp
|
|
+++ b/hotspot/src/share/vm/oops/instanceMirrorKlass.hpp
|
|
@@ -89,7 +89,7 @@ class InstanceMirrorKlass: public InstanceKlass {
|
|
|
|
// Garbage collection
|
|
int oop_adjust_pointers(oop obj);
|
|
- void oop_follow_contents(oop obj);
|
|
+ void oop_follow_contents(oop obj, MarkSweep* mark);
|
|
|
|
// Parallel Scavenge and Parallel Old
|
|
PARALLEL_GC_DECLS
|
|
diff --git a/hotspot/src/share/vm/oops/instanceRefKlass.cpp b/hotspot/src/share/vm/oops/instanceRefKlass.cpp
|
|
index a14989314..2c3fe7496 100644
|
|
--- a/hotspot/src/share/vm/oops/instanceRefKlass.cpp
|
|
+++ b/hotspot/src/share/vm/oops/instanceRefKlass.cpp
|
|
@@ -48,7 +48,7 @@
|
|
PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
|
|
|
|
template <class T>
|
|
-void specialized_oop_follow_contents(InstanceRefKlass* ref, oop obj) {
|
|
+void specialized_oop_follow_contents(InstanceRefKlass* ref, oop obj, MarkSweep* mark) {
|
|
T* referent_addr = (T*)java_lang_ref_Reference::referent_addr(obj);
|
|
T heap_oop = oopDesc::load_heap_oop(referent_addr);
|
|
debug_only(
|
|
@@ -61,7 +61,7 @@ void specialized_oop_follow_contents(InstanceRefKlass* ref, oop obj) {
|
|
if (!referent->is_gc_marked() &&
|
|
MarkSweep::ref_processor()->discover_reference(obj, ref->reference_type())) {
|
|
// reference was discovered, referent will be traversed later
|
|
- ref->InstanceKlass::oop_follow_contents(obj);
|
|
+ ref->InstanceKlass::oop_follow_contents(obj, mark);
|
|
debug_only(
|
|
if(TraceReferenceGC && PrintGCDetails) {
|
|
gclog_or_tty->print_cr(" Non NULL enqueued " INTPTR_FORMAT, (void *)obj);
|
|
@@ -75,7 +75,7 @@ void specialized_oop_follow_contents(InstanceRefKlass* ref, oop obj) {
|
|
gclog_or_tty->print_cr(" Non NULL normal " INTPTR_FORMAT, (void *)obj);
|
|
}
|
|
)
|
|
- MarkSweep::mark_and_push(referent_addr);
|
|
+ mark->mark_and_push(referent_addr);
|
|
}
|
|
}
|
|
T* next_addr = (T*)java_lang_ref_Reference::next_addr(obj);
|
|
@@ -91,7 +91,7 @@ void specialized_oop_follow_contents(InstanceRefKlass* ref, oop obj) {
|
|
INTPTR_FORMAT, discovered_addr);
|
|
}
|
|
)
|
|
- MarkSweep::mark_and_push(discovered_addr);
|
|
+ mark->mark_and_push(discovered_addr);
|
|
}
|
|
} else {
|
|
#ifdef ASSERT
|
|
@@ -111,15 +111,15 @@ void specialized_oop_follow_contents(InstanceRefKlass* ref, oop obj) {
|
|
gclog_or_tty->print_cr(" Process next as normal " INTPTR_FORMAT, next_addr);
|
|
}
|
|
)
|
|
- MarkSweep::mark_and_push(next_addr);
|
|
- ref->InstanceKlass::oop_follow_contents(obj);
|
|
+ mark->mark_and_push(next_addr);
|
|
+ ref->InstanceKlass::oop_follow_contents(obj, mark);
|
|
}
|
|
|
|
-void InstanceRefKlass::oop_follow_contents(oop obj) {
|
|
+void InstanceRefKlass::oop_follow_contents(oop obj, MarkSweep* mark) {
|
|
if (UseCompressedOops) {
|
|
- specialized_oop_follow_contents<narrowOop>(this, obj);
|
|
+ specialized_oop_follow_contents<narrowOop>(this, obj, mark);
|
|
} else {
|
|
- specialized_oop_follow_contents<oop>(this, obj);
|
|
+ specialized_oop_follow_contents<oop>(this, obj, mark);
|
|
}
|
|
}
|
|
|
|
diff --git a/hotspot/src/share/vm/oops/instanceRefKlass.hpp b/hotspot/src/share/vm/oops/instanceRefKlass.hpp
|
|
index 3140977b4..4a15c4c75 100644
|
|
--- a/hotspot/src/share/vm/oops/instanceRefKlass.hpp
|
|
+++ b/hotspot/src/share/vm/oops/instanceRefKlass.hpp
|
|
@@ -65,7 +65,7 @@ class InstanceRefKlass: public InstanceKlass {
|
|
|
|
// Garbage collection
|
|
int oop_adjust_pointers(oop obj);
|
|
- void oop_follow_contents(oop obj);
|
|
+ void oop_follow_contents(oop obj, MarkSweep* mark);
|
|
|
|
// Parallel Scavenge and Parallel Old
|
|
PARALLEL_GC_DECLS
|
|
diff --git a/hotspot/src/share/vm/oops/klass.hpp b/hotspot/src/share/vm/oops/klass.hpp
|
|
index b7588abd0..f70587eab 100644
|
|
--- a/hotspot/src/share/vm/oops/klass.hpp
|
|
+++ b/hotspot/src/share/vm/oops/klass.hpp
|
|
@@ -93,6 +93,7 @@ class klassVtable;
|
|
class ParCompactionManager;
|
|
class KlassSizeStats;
|
|
class fieldDescriptor;
|
|
+class MarkSweep;
|
|
|
|
class Klass : public Metadata {
|
|
friend class VMStructs;
|
|
@@ -538,7 +539,7 @@ protected:
|
|
virtual const char* signature_name() const;
|
|
|
|
// garbage collection support
|
|
- virtual void oop_follow_contents(oop obj) = 0;
|
|
+ virtual void oop_follow_contents(oop obj, MarkSweep* mark) = 0;
|
|
virtual int oop_adjust_pointers(oop obj) = 0;
|
|
|
|
// Parallel Scavenge and Parallel Old
|
|
diff --git a/hotspot/src/share/vm/oops/markOop.hpp b/hotspot/src/share/vm/oops/markOop.hpp
|
|
index 649217c88..a80c99be4 100644
|
|
--- a/hotspot/src/share/vm/oops/markOop.hpp
|
|
+++ b/hotspot/src/share/vm/oops/markOop.hpp
|
|
@@ -102,8 +102,8 @@ class ObjectMonitor;
|
|
class JavaThread;
|
|
|
|
class markOopDesc: public oopDesc {
|
|
- private:
|
|
// Conversion
|
|
+ public:
|
|
uintptr_t value() const { return (uintptr_t) this; }
|
|
|
|
public:
|
|
diff --git a/hotspot/src/share/vm/oops/objArrayKlass.cpp b/hotspot/src/share/vm/oops/objArrayKlass.cpp
|
|
index 8049209bf..19abfbd5a 100644
|
|
--- a/hotspot/src/share/vm/oops/objArrayKlass.cpp
|
|
+++ b/hotspot/src/share/vm/oops/objArrayKlass.cpp
|
|
@@ -454,13 +454,13 @@ void ObjArrayKlass::initialize(TRAPS) {
|
|
a, p, low, high, do_oop) \
|
|
}
|
|
|
|
-void ObjArrayKlass::oop_follow_contents(oop obj) {
|
|
+void ObjArrayKlass::oop_follow_contents(oop obj, MarkSweep* mark) {
|
|
assert (obj->is_array(), "obj must be array");
|
|
- MarkSweep::follow_klass(obj->klass());
|
|
+ mark->follow_klass(obj->klass());
|
|
if (UseCompressedOops) {
|
|
- objarray_follow_contents<narrowOop>(obj, 0);
|
|
+ objarray_follow_contents<narrowOop>(obj, 0, mark);
|
|
} else {
|
|
- objarray_follow_contents<oop>(obj, 0);
|
|
+ objarray_follow_contents<oop>(obj, 0, mark);
|
|
}
|
|
}
|
|
|
|
diff --git a/hotspot/src/share/vm/oops/objArrayKlass.hpp b/hotspot/src/share/vm/oops/objArrayKlass.hpp
|
|
index cfe31e86e..ab3cbc61c 100644
|
|
--- a/hotspot/src/share/vm/oops/objArrayKlass.hpp
|
|
+++ b/hotspot/src/share/vm/oops/objArrayKlass.hpp
|
|
@@ -104,9 +104,9 @@ class ObjArrayKlass : public ArrayKlass {
|
|
void initialize(TRAPS);
|
|
|
|
// Garbage collection
|
|
- void oop_follow_contents(oop obj);
|
|
- inline void oop_follow_contents(oop obj, int index);
|
|
- template <class T> inline void objarray_follow_contents(oop obj, int index);
|
|
+ void oop_follow_contents(oop obj, MarkSweep* mark);
|
|
+ inline void oop_follow_contents(oop obj, int index, MarkSweep* mark);
|
|
+ template <class T> inline void objarray_follow_contents(oop obj, int index, MarkSweep* mark);
|
|
|
|
int oop_adjust_pointers(oop obj);
|
|
|
|
diff --git a/hotspot/src/share/vm/oops/objArrayKlass.inline.hpp b/hotspot/src/share/vm/oops/objArrayKlass.inline.hpp
|
|
index e082df55a..96637bad7 100644
|
|
--- a/hotspot/src/share/vm/oops/objArrayKlass.inline.hpp
|
|
+++ b/hotspot/src/share/vm/oops/objArrayKlass.inline.hpp
|
|
@@ -33,16 +33,16 @@
|
|
#include "gc_implementation/parallelScavenge/psParallelCompact.hpp"
|
|
#endif // INCLUDE_ALL_GCS
|
|
|
|
-void ObjArrayKlass::oop_follow_contents(oop obj, int index) {
|
|
+void ObjArrayKlass::oop_follow_contents(oop obj, int index, MarkSweep* mark) {
|
|
if (UseCompressedOops) {
|
|
- objarray_follow_contents<narrowOop>(obj, index);
|
|
+ objarray_follow_contents<narrowOop>(obj, index, mark);
|
|
} else {
|
|
- objarray_follow_contents<oop>(obj, index);
|
|
+ objarray_follow_contents<oop>(obj, index, mark);
|
|
}
|
|
}
|
|
|
|
template <class T>
|
|
-void ObjArrayKlass::objarray_follow_contents(oop obj, int index) {
|
|
+void ObjArrayKlass::objarray_follow_contents(oop obj, int index, MarkSweep* mark) {
|
|
objArrayOop a = objArrayOop(obj);
|
|
const size_t len = size_t(a->length());
|
|
const size_t beg_index = size_t(index);
|
|
@@ -56,11 +56,11 @@ void ObjArrayKlass::objarray_follow_contents(oop obj, int index) {
|
|
|
|
// Push the non-NULL elements of the next stride on the marking stack.
|
|
for (T* e = beg; e < end; e++) {
|
|
- MarkSweep::mark_and_push<T>(e);
|
|
+ mark->mark_and_push<T>(e);
|
|
}
|
|
|
|
if (end_index < len) {
|
|
- MarkSweep::push_objarray(a, end_index); // Push the continuation.
|
|
+ mark->push_objarray(a, end_index); // Push the continuation.
|
|
}
|
|
}
|
|
|
|
diff --git a/hotspot/src/share/vm/oops/oop.hpp b/hotspot/src/share/vm/oops/oop.hpp
|
|
index a5c1d69bf..f452e7473 100644
|
|
--- a/hotspot/src/share/vm/oops/oop.hpp
|
|
+++ b/hotspot/src/share/vm/oops/oop.hpp
|
|
@@ -56,6 +56,8 @@ class CMSIsAliveClosure;
|
|
class PSPromotionManager;
|
|
class ParCompactionManager;
|
|
|
|
+class MarkSweep;
|
|
+
|
|
class oopDesc {
|
|
friend class VMStructs;
|
|
private:
|
|
@@ -298,7 +300,7 @@ class oopDesc {
|
|
bool is_gc_marked() const;
|
|
// Apply "MarkSweep::mark_and_push" to (the address of) every non-NULL
|
|
// reference field in "this".
|
|
- void follow_contents(void);
|
|
+ void follow_contents(MarkSweep* mark);
|
|
|
|
#if INCLUDE_ALL_GCS
|
|
// Parallel Scavenge
|
|
diff --git a/hotspot/src/share/vm/oops/oop.inline.hpp b/hotspot/src/share/vm/oops/oop.inline.hpp
|
|
index ed37d0558..6407f830f 100644
|
|
--- a/hotspot/src/share/vm/oops/oop.inline.hpp
|
|
+++ b/hotspot/src/share/vm/oops/oop.inline.hpp
|
|
@@ -655,9 +655,9 @@ inline bool oopDesc::is_unlocked_oop() const {
|
|
}
|
|
#endif // PRODUCT
|
|
|
|
-inline void oopDesc::follow_contents(void) {
|
|
+inline void oopDesc::follow_contents(MarkSweep* mark) {
|
|
assert (is_gc_marked(), "should be marked");
|
|
- klass()->oop_follow_contents(this);
|
|
+ klass()->oop_follow_contents(this, mark);
|
|
}
|
|
|
|
// Used by scavengers
|
|
diff --git a/hotspot/src/share/vm/oops/typeArrayKlass.cpp b/hotspot/src/share/vm/oops/typeArrayKlass.cpp
|
|
index d69267d42..f17524e4b 100644
|
|
--- a/hotspot/src/share/vm/oops/typeArrayKlass.cpp
|
|
+++ b/hotspot/src/share/vm/oops/typeArrayKlass.cpp
|
|
@@ -204,7 +204,7 @@ int TypeArrayKlass::oop_size(oop obj) const {
|
|
return t->object_size();
|
|
}
|
|
|
|
-void TypeArrayKlass::oop_follow_contents(oop obj) {
|
|
+void TypeArrayKlass::oop_follow_contents(oop obj, MarkSweep* mark) {
|
|
assert(obj->is_typeArray(),"must be a type array");
|
|
// Performance tweak: We skip iterating over the klass pointer since we
|
|
// know that Universe::TypeArrayKlass never moves.
|
|
diff --git a/hotspot/src/share/vm/oops/typeArrayKlass.hpp b/hotspot/src/share/vm/oops/typeArrayKlass.hpp
|
|
index cf363fc76..c5cdd7000 100644
|
|
--- a/hotspot/src/share/vm/oops/typeArrayKlass.hpp
|
|
+++ b/hotspot/src/share/vm/oops/typeArrayKlass.hpp
|
|
@@ -77,7 +77,7 @@ class TypeArrayKlass : public ArrayKlass {
|
|
int oop_oop_iterate_m(oop obj, ExtendedOopClosure* blk, MemRegion mr);
|
|
|
|
// Garbage collection
|
|
- void oop_follow_contents(oop obj);
|
|
+ void oop_follow_contents(oop obj, MarkSweep* mark);
|
|
int oop_adjust_pointers(oop obj);
|
|
|
|
// Parallel Scavenge and Parallel Old
|
|
--
|
|
2.22.0
|
|
|