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

