From d03e0f409e6db5da9036e90c3614a377c8bfc22a Mon Sep 17 00:00:00 2001 From: kuenking111 Date: Fri, 10 Dec 2021 15:48:24 +0800 Subject: [PATCH] I4LZJ1: G1 Full GC parallel mark --- G1-Full-GC-parallel-mark.patch | 1520 ++++++++++++++++++++++++++++++++ openjdk-1.8.0.spec | 7 +- 2 files changed, 1526 insertions(+), 1 deletion(-) create mode 100755 G1-Full-GC-parallel-mark.patch diff --git a/G1-Full-GC-parallel-mark.patch b/G1-Full-GC-parallel-mark.patch new file mode 100755 index 0000000..af8d22f --- /dev/null +++ b/G1-Full-GC-parallel-mark.patch @@ -0,0 +1,1520 @@ +From 2821582ff1191393781ccf93d46d9c31230c8a4a Mon Sep 17 00:00:00 2001 +From: mashoubing +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 MarkSweep::_marking_stack; +-Stack MarkSweep::_objarray_stack; +- +-Stack MarkSweep::_preserved_oop_stack; +-Stack 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 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 _marking_stack; +- static Stack _objarray_stack; ++ Stack _marking_stack; ++ Stack _objarray_stack; + + // Space for storing/restoring mark word +- static Stack _preserved_mark_stack; +- static Stack _preserved_oop_stack; +- static size_t _preserved_count; +- static size_t _preserved_count_max; +- static PreservedMark* _preserved_marks; ++ Stack _preserved_mark_stack; ++ Stack _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 static inline void follow_root(T* p); ++ template inline void follow_root(T* p); + + // Check mark and maybe push on marking stack +- template 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 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 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 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 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 inline void MarkSweep::adjust_pointer(T* p) { + } + + template 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 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 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 +-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(this, obj); ++ specialized_oop_follow_contents(this, obj, mark); + } else { +- specialized_oop_follow_contents(this, obj); ++ specialized_oop_follow_contents(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(obj, 0); ++ objarray_follow_contents(obj, 0, mark); + } else { +- objarray_follow_contents(obj, 0); ++ objarray_follow_contents(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 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 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(obj, index); ++ objarray_follow_contents(obj, index, mark); + } else { +- objarray_follow_contents(obj, index); ++ objarray_follow_contents(obj, index, mark); + } + } + + template +-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(e); ++ mark->mark_and_push(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 + diff --git a/openjdk-1.8.0.spec b/openjdk-1.8.0.spec index f12b3e6..af7fc81 100644 --- a/openjdk-1.8.0.spec +++ b/openjdk-1.8.0.spec @@ -916,7 +916,7 @@ Provides: java-%{javaver}-%{origin}-accessibility%{?1} = %{epoch}:%{version}-%{r Name: java-%{javaver}-%{origin} Version: %{javaver}.%{updatever}.%{buildver} -Release: 4 +Release: 5 # java-1.5.0-ibm from jpackage.org set Epoch to 1 for unknown reasons # and this change was brought into RHEL-4. java-1.5.0-ibm packages # also included the epoch in their virtual provides. This created a @@ -1119,6 +1119,7 @@ Patch221: 8183543-Aarch64-C2-compilation-often-fails-with-fail--last.patch Patch222: 8273111-Default-timezone-should-return-zone-ID-if-locatiome-is-valid-but-not-canonicalization-on-linux.patch Patch223: 8233280-Remove-GCLockerInvokesConcurrent-relative-logic-for-G1.patch Patch224: G1Ucommit-Refactor-Trigger-mechanism.patch +Patch225: G1-Full-GC-parallel-mark.patch # 8u312 @@ -1588,6 +1589,7 @@ pushd %{top_level_dir_name} %patch222 -p1 %patch223 -p1 %patch224 -p1 +%patch225 -p1 popd # System library fixes @@ -2205,6 +2207,9 @@ require "copy_jdk_configs.lua" %endif %changelog +* Fri Dec 10 2021 kuenking111 - 1:1.8.0.312-b07.5 +- add G1-Full-GC-parallel-mark.patch + * Fri Dec 10 2021 kuenking111 - 1:1.8.0.312-b07.4 - add G1Ucommit-Refactor-Trigger-mechanism.patch -- Gitee