< prev index next >

src/share/vm/runtime/safepoint.cpp

Print this page
rev 13387 : [mq]: parallel_sp_cleaning.patch

@@ -70,10 +70,13 @@
 #endif
 
 // --------------------------------------------------------------------------------------------------
 // Implementation of Safepoint begin/end
 
+WorkGang* SafepointSynchronize::_cleanup_workers = NULL;
+SubTasksDone* SafepointSynchronize::_cleanup_subtasks = NULL;
+
 SafepointSynchronize::SynchronizeState volatile SafepointSynchronize::_state = SafepointSynchronize::_not_synchronized;
 volatile int  SafepointSynchronize::_waiting_to_block = 0;
 volatile int SafepointSynchronize::_safepoint_counter = 0;
 int SafepointSynchronize::_current_jni_active_count = 0;
 long  SafepointSynchronize::_end_of_last_safepoint = 0;

@@ -541,15 +544,28 @@
   }
 }
 
 // Various cleaning tasks that should be done periodically at safepoints
 void SafepointSynchronize::do_cleanup_tasks() {
+  VM_Operation* op = VMThread::vm_operation();
+  // If op does both deflating and nmethod marking, we don't bother firing up
+  // the workers.
+  bool op_does_cleanup = op != NULL && op->marks_nmethods() && op->deflates_idle_monitors();
+  if (ParallelSafepointCleanup && ! op_does_cleanup) {
+    parallel_cleanup();
+  } else {
+    serial_cleanup();
+  }
+}
+
+void SafepointSynchronize::serial_cleanup() {
+  VM_Operation* op = VMThread::vm_operation();
   {
     const char* name = "deflating idle monitors";
     EventSafepointCleanupTask event;
     TraceTime timer(name, TRACETIME_LOG(Info, safepoint, cleanup));
-    ObjectSynchronizer::deflate_idle_monitors();
+    ObjectSynchronizer::deflate_idle_monitors(op == NULL || ! op->deflates_idle_monitors());
     event_safepoint_cleanup_task_commit(event, name);
   }
 
   {
     const char* name = "updating inline caches";

@@ -564,24 +580,27 @@
     TraceTime timer("compilation policy safepoint handler", TRACETIME_LOG(Info, safepoint, cleanup));
     CompilationPolicy::policy()->do_safepoint_work();
     event_safepoint_cleanup_task_commit(event, name);
   }
 
-  {
+  if (op == NULL || ! op->marks_nmethods()) {
     const char* name = "mark nmethods";
     EventSafepointCleanupTask event;
     TraceTime timer(name, TRACETIME_LOG(Info, safepoint, cleanup));
     NMethodSweeper::mark_active_nmethods();
     event_safepoint_cleanup_task_commit(event, name);
   }
 
   if (SymbolTable::needs_rehashing()) {
+    double start = os::elapsedTime();
     const char* name = "rehashing symbol table";
     EventSafepointCleanupTask event;
     TraceTime timer(name, TRACETIME_LOG(Info, safepoint, cleanup));
     SymbolTable::rehash_table();
     event_safepoint_cleanup_task_commit(event, name);
+    double end = os::elapsedTime();
+    tty->print_cr("vmthread took: %f ms for symbol table rehash", (end - start) * 1000.0);
   }
 
   if (StringTable::needs_rehashing()) {
     const char* name = "rehashing string table";
     EventSafepointCleanupTask event;

@@ -599,10 +618,121 @@
     ClassLoaderDataGraph::purge_if_needed();
     event_safepoint_cleanup_task_commit(event, name);
   }
 }
 
+class ParallelSPCleanupThreadClosure : public ThreadClosure {
+private:
+  bool _do_deflate_idle_monitors;
+  CodeBlobClosure* _nmethod_cl;
+
+public:
+  ParallelSPCleanupThreadClosure() {
+    VM_Operation* op = VMThread::vm_operation();
+    _do_deflate_idle_monitors = op == NULL || ! op->deflates_idle_monitors();
+    if (op == NULL || ! op->marks_nmethods()) {
+      _nmethod_cl = NMethodSweeper::prepare_mark_active_nmethods();
+    } else {
+      _nmethod_cl = NULL;
+    }
+  }
+
+  void do_thread(Thread* thread) {
+    if (_do_deflate_idle_monitors) {
+      ObjectSynchronizer::deflate_idle_monitors_and_oops_do(thread, NULL);
+    }
+    if (_nmethod_cl != NULL && thread->is_Java_thread() &&
+        ! thread->is_Code_cache_sweeper_thread()) {
+      JavaThread* jt = (JavaThread*) thread;
+      jt->nmethods_do(_nmethod_cl);
+    }
+  }
+};
+
+class ParallelSPCleanupTask : public AbstractGangTask {
+private:
+  SubTasksDone* _subtasks;
+  ParallelSPCleanupThreadClosure _cleanup_threads_cl;
+public:
+  ParallelSPCleanupTask(SubTasksDone* subtasks) :
+    AbstractGangTask("Parallel Safepoint Cleanup"),
+    _cleanup_threads_cl(ParallelSPCleanupThreadClosure()),
+    _subtasks(subtasks) {}
+
+  void work(uint worker_id) {
+    // All threads deflate monitors and mark nmethods (if necessary).
+    Threads::parallel_java_threads_do(&_cleanup_threads_cl);
+
+    if (! _subtasks->is_task_claimed(SafepointSynchronize::SAFEPOINT_CLEANUP_DEFLATE_MONITORS)) {
+      const char* name = "deflating idle monitors";
+      EventSafepointCleanupTask event;
+      TraceTime timer(name, TRACETIME_LOG(Info, safepoint, cleanup));
+      ObjectSynchronizer::deflate_idle_monitors(false);
+      event_safepoint_cleanup_task_commit(event, name);
+    }
+
+    if (! _subtasks->is_task_claimed(SafepointSynchronize::SAFEPOINT_CLEANUP_UPDATE_INLINE_CACHES)) {
+      const char* name = "updating inline caches";
+      EventSafepointCleanupTask event;
+      TraceTime timer(name, TRACETIME_LOG(Info, safepoint, cleanup));
+      InlineCacheBuffer::update_inline_caches();
+      event_safepoint_cleanup_task_commit(event, name);
+    }
+
+    if (! _subtasks->is_task_claimed(SafepointSynchronize::SAFEPOINT_CLEANUP_COMPILATION_POLICY)) {
+      const char* name = "compilation policy safepoint handler";
+      EventSafepointCleanupTask event;
+      TraceTime timer("compilation policy safepoint handler", TRACETIME_LOG(Info, safepoint, cleanup));
+      CompilationPolicy::policy()->do_safepoint_work();
+      event_safepoint_cleanup_task_commit(event, name);
+    }
+
+    if (! _subtasks->is_task_claimed(SafepointSynchronize::SAFEPOINT_CLEANUP_SYMBOL_TABLE_REHASH)) {
+      if (SymbolTable::needs_rehashing()) {
+        const char* name = "rehashing symbol table";
+        EventSafepointCleanupTask event;
+        TraceTime timer(name, TRACETIME_LOG(Info, safepoint, cleanup));
+        SymbolTable::rehash_table();
+        event_safepoint_cleanup_task_commit(event, name);
+      }
+    }
+
+    if (! _subtasks->is_task_claimed(SafepointSynchronize::SAFEPOINT_CLEANUP_STRING_TABLE_REHASH)) {
+      if (StringTable::needs_rehashing()) {
+        const char* name = "rehashing string table";
+        EventSafepointCleanupTask event;
+        TraceTime timer(name, TRACETIME_LOG(Info, safepoint, cleanup));
+        StringTable::rehash_table();
+        event_safepoint_cleanup_task_commit(event, name);
+      }
+    }
+
+    if (! _subtasks->is_task_claimed(SafepointSynchronize::SAFEPOINT_CLEANUP_CLD_PURGE)) {
+      // CMS delays purging the CLDG until the beginning of the next safepoint and to
+      // make sure concurrent sweep is done
+      const char* name = "purging class loader data graph";
+      EventSafepointCleanupTask event;
+      TraceTime timer(name, TRACETIME_LOG(Info, safepoint, cleanup));
+      ClassLoaderDataGraph::purge_if_needed();
+      event_safepoint_cleanup_task_commit(event, name);
+    }
+    _subtasks->all_tasks_completed(ParallelSafepointCleanupThreads);
+  }
+};
+
+void SafepointSynchronize::parallel_cleanup() {
+  // Deferred init
+  if (_cleanup_workers == NULL) {
+    _cleanup_workers = new WorkGang("Parallel Safepoint Cleanup", ParallelSafepointCleanupThreads, false, false);
+    _cleanup_workers->initialize_workers();
+    _cleanup_subtasks = new SubTasksDone(SAFEPOINT_CLEANUP_NUM_TASKS);
+  }
+
+  StrongRootsScope srs(_cleanup_workers->active_workers());
+  ParallelSPCleanupTask cleanup_task(_cleanup_subtasks);
+  _cleanup_workers->run_task(&cleanup_task);
+}
 
 bool SafepointSynchronize::safepoint_safe(JavaThread *thread, JavaThreadState state) {
   switch(state) {
   case _thread_in_native:
     // native threads are safe if they have no java stack or have walkable stack
< prev index next >