hotspot/src/share/vm/gc/shared/preservedMarks.cpp
changeset 37422 8a7443b5edf8
parent 37045 41e3f98fa3dc
child 38080 bb02a3ad3b0a
--- a/hotspot/src/share/vm/gc/shared/preservedMarks.cpp	Wed Apr 06 23:42:52 2016 +0000
+++ b/hotspot/src/share/vm/gc/shared/preservedMarks.cpp	Thu Apr 07 10:55:54 2016 +0200
@@ -24,24 +24,30 @@
 
 #include "precompiled.hpp"
 #include "gc/shared/preservedMarks.inline.hpp"
+#include "gc/shared/workgroup.hpp"
 #include "memory/allocation.inline.hpp"
-#include "oops/oop.inline.hpp"
 
 void PreservedMarks::restore() {
-  // First, iterate over the stack and restore all marks.
-  StackIterator<OopAndMarkOop, mtGC> iter(_stack);
-  while (!iter.is_empty()) {
-    OopAndMarkOop elem = iter.next();
+  while (!_stack.is_empty()) {
+    const OopAndMarkOop elem = _stack.pop();
     elem.set_mark();
   }
+  assert_empty();
+}
 
-  // Second, reclaim all the stack memory
-  _stack.clear(true /* clear_cache */);
+#ifndef PRODUCT
+void PreservedMarks::assert_empty() {
+  assert(_stack.is_empty(), "stack expected to be empty, size = "SIZE_FORMAT,
+         _stack.size());
+  assert(_stack.cache_size() == 0,
+         "stack expected to have no cached segments, cache size = "SIZE_FORMAT,
+         _stack.cache_size());
 }
+#endif // ndef PRODUCT
 
 void RemoveForwardedPointerClosure::do_object(oop obj) {
   if (obj->is_forwarded()) {
-    obj->init_mark();
+    PreservedMarks::init_forwarded_mark(obj);
   }
 }
 
@@ -61,15 +67,48 @@
   assert_empty();
 }
 
+class ParRestoreTask : public AbstractGangTask {
+private:
+  PreservedMarksSet* const _preserved_marks_set;
+  SequentialSubTasksDone _sub_tasks;
+  volatile size_t* const _total_size_addr;
+
+public:
+  virtual void work(uint worker_id) {
+    uint task_id = 0;
+    while (!_sub_tasks.is_task_claimed(/* reference */ task_id)) {
+      PreservedMarks* const preserved_marks = _preserved_marks_set->get(task_id);
+      const size_t size = preserved_marks->size();
+      preserved_marks->restore();
+      // Only do the atomic add if the size is > 0.
+      if (size > 0) {
+        Atomic::add(size, _total_size_addr);
+      }
+    }
+    _sub_tasks.all_tasks_completed();
+  }
+
+  ParRestoreTask(uint worker_num,
+                 PreservedMarksSet* preserved_marks_set,
+                 volatile size_t* total_size_addr)
+      : AbstractGangTask("Parallel Preserved Mark Restoration"),
+        _preserved_marks_set(preserved_marks_set),
+        _total_size_addr(total_size_addr) {
+    _sub_tasks.set_n_threads(worker_num);
+    _sub_tasks.set_n_tasks(preserved_marks_set->num());
+  }
+};
+
+void PreservedMarksSet::restore_internal(WorkGang* workers,
+                                         volatile size_t* total_size_addr) {
+  assert(workers != NULL, "pre-condition");
+  ParRestoreTask task(workers->active_workers(), this, total_size_addr);
+  workers->run_task(&task);
+}
+
+// temporary, used by PS
 void PreservedMarksSet::restore() {
-  size_t total_size = 0;
-  for (uint i = 0; i < _num; i += 1) {
-    total_size += get(i)->size();
-    get(i)->restore();
-  }
-  assert_empty();
-
-  log_trace(gc)("Restored " SIZE_FORMAT " marks", total_size);
+  restore<WorkGang>(NULL);
 }
 
 void PreservedMarksSet::reclaim() {
@@ -92,7 +131,7 @@
 void PreservedMarksSet::assert_empty() {
   assert(_stacks != NULL && _num > 0, "should have been initialized");
   for (uint i = 0; i < _num; i += 1) {
-    assert(get(i)->is_empty(), "stack should be empty");
+    get(i)->assert_empty();
   }
 }
 #endif // ndef PRODUCT