src/hotspot/share/runtime/vmThread.cpp
changeset 59325 3636bab5e81e
parent 59290 97d13893ec3c
--- a/src/hotspot/share/runtime/vmThread.cpp	Fri Nov 29 11:26:25 2019 +0100
+++ b/src/hotspot/share/runtime/vmThread.cpp	Fri Nov 29 12:09:25 2019 +0100
@@ -50,13 +50,15 @@
 #include "utilities/vmError.hpp"
 #include "utilities/xmlstream.hpp"
 
+VM_QueueHead VMOperationQueue::_queue_head[VMOperationQueue::nof_priorities];
+
 VMOperationQueue::VMOperationQueue() {
   // The queue is a circular doubled-linked list, which always contains
   // one element (i.e., one element means empty).
   for(int i = 0; i < nof_priorities; i++) {
     _queue_length[i] = 0;
     _queue_counter = 0;
-    _queue[i] = new VM_None("QueueHead");
+    _queue[i] = &_queue_head[i];
     _queue[i]->set_next(_queue[i]);
     _queue[i]->set_prev(_queue[i]);
   }
@@ -81,12 +83,7 @@
   q->set_next(n);
 }
 
-void VMOperationQueue::queue_add_front(int prio, VM_Operation *op) {
-  _queue_length[prio]++;
-  insert(_queue[prio]->next(), op);
-}
-
-void VMOperationQueue::queue_add_back(int prio, VM_Operation *op) {
+void VMOperationQueue::queue_add(int prio, VM_Operation *op) {
   _queue_length[prio]++;
   insert(_queue[prio]->prev(), op);
 }
@@ -154,11 +151,11 @@
 
   HOTSPOT_VMOPS_REQUEST(
                    (char *) op->name(), strlen(op->name()),
-                   op->evaluation_mode());
+                   op->evaluate_at_safepoint() ? 0 : 1);
 
   // Encapsulates VM queue policy. Currently, that
   // only involves putting them on the right list
-  queue_add_back(op->evaluate_at_safepoint() ? SafepointPriority : MediumPriority, op);
+  queue_add(op->evaluate_at_safepoint() ? SafepointPriority : MediumPriority, op);
 }
 
 VM_Operation* VMOperationQueue::remove_next() {
@@ -380,15 +377,11 @@
   assert(event != NULL, "invariant");
   assert(event->should_commit(), "invariant");
   assert(op != NULL, "invariant");
-  const bool is_concurrent = op->evaluate_concurrently();
   const bool evaluate_at_safepoint = op->evaluate_at_safepoint();
   event->set_operation(op->type());
   event->set_safepoint(evaluate_at_safepoint);
-  event->set_blocking(!is_concurrent);
-  // Only write caller thread information for non-concurrent vm operations.
-  // For concurrent vm operations, the thread id is set to 0 indicating thread is unknown.
-  // This is because the caller thread could have exited already.
-  event->set_caller(is_concurrent ? 0 : JFR_THREAD_ID(op->calling_thread()));
+  event->set_blocking(true);
+  event->set_caller(JFR_THREAD_ID(op->calling_thread()));
   event->set_safepointId(evaluate_at_safepoint ? SafepointSynchronize::safepoint_id() : 0);
   event->commit();
 }
@@ -400,7 +393,7 @@
     PerfTraceTime vm_op_timer(perf_accumulated_vm_operation_time());
     HOTSPOT_VMOPS_BEGIN(
                      (char *) op->name(), strlen(op->name()),
-                     op->evaluation_mode());
+                     op->evaluate_at_safepoint() ? 0 : 1);
 
     EventExecuteVMOperation event;
     op->evaluate();
@@ -410,21 +403,11 @@
 
     HOTSPOT_VMOPS_END(
                      (char *) op->name(), strlen(op->name()),
-                     op->evaluation_mode());
+                     op->evaluate_at_safepoint() ? 0 : 1);
   }
 
-  // Last access of info in _cur_vm_operation!
-  bool c_heap_allocated = op->is_cheap_allocated();
-
   // Mark as completed
-  if (!op->evaluate_concurrently()) {
-    op->calling_thread()->increment_vm_operation_completed_count();
-  }
-  // It is unsafe to access the _cur_vm_operation after the 'increment_vm_operation_completed_count' call,
-  // since if it is stack allocated the calling thread might have deallocated
-  if (c_heap_allocated) {
-    delete _cur_vm_operation;
-  }
+  op->calling_thread()->increment_vm_operation_completed_count();
 }
 
 static VM_None    safepointALot_op("SafepointALot");
@@ -441,6 +424,11 @@
   }
 };
 
+void VMThread::check_for_forced_cleanup() {
+  MonitorLocker mq(VMOperationQueue_lock,  Mutex::_no_safepoint_check_flag);
+  mq.notify();
+}
+
 VM_Operation* VMThread::no_op_safepoint() {
   // Check for handshakes first since we may need to return a VMop.
   if (HandshakeALot) {
@@ -451,7 +439,8 @@
   long interval_ms = SafepointTracing::time_since_last_safepoint_ms();
   bool max_time_exceeded = GuaranteedSafepointInterval != 0 &&
                            (interval_ms >= GuaranteedSafepointInterval);
-  if (max_time_exceeded && SafepointSynchronize::is_cleanup_needed()) {
+  if ((max_time_exceeded && SafepointSynchronize::is_cleanup_needed()) ||
+      SafepointSynchronize::is_forced_cleanup_needed()) {
     return &cleanup_op;
   }
   if (SafepointALot) {
@@ -480,8 +469,7 @@
       _cur_vm_operation = _vm_queue->remove_next();
 
       // Stall time tracking code
-      if (PrintVMQWaitTime && _cur_vm_operation != NULL &&
-          !_cur_vm_operation->evaluate_concurrently()) {
+      if (PrintVMQWaitTime && _cur_vm_operation != NULL) {
         long stall = os::javaTimeMillis() - _cur_vm_operation->timestamp();
         if (stall > 0)
           tty->print_cr("%s stall: %ld",  _cur_vm_operation->name(), stall);
@@ -489,8 +477,8 @@
 
       while (!should_terminate() && _cur_vm_operation == NULL) {
         // wait with a timeout to guarantee safepoints at regular intervals
-        bool timedout =
-          mu_queue.wait(GuaranteedSafepointInterval);
+        // (if there is cleanup work to do)
+        (void)mu_queue.wait(GuaranteedSafepointInterval);
 
         // Support for self destruction
         if ((SelfDestructTimer != 0) && !VMError::is_error_reported() &&
@@ -499,9 +487,12 @@
           exit(-1);
         }
 
-        if (timedout) {
+        // If the queue contains a safepoint VM op,
+        // clean up will be done so we can skip this part.
+        if (!_vm_queue->peek_at_safepoint_priority()) {
+
           // Have to unlock VMOperationQueue_lock just in case no_op_safepoint()
-          // has to do a handshake.
+          // has to do a handshake when HandshakeALot is enabled.
           MutexUnlocker mul(VMOperationQueue_lock, Mutex::_no_safepoint_check_flag);
           if ((_cur_vm_operation = VMThread::no_op_safepoint()) != NULL) {
             // Force a safepoint since we have not had one for at least
@@ -624,15 +615,6 @@
     { MonitorLocker mu(VMOperationRequest_lock, Mutex::_no_safepoint_check_flag);
       mu.notify_all();
     }
-
-    // We want to make sure that we get to a safepoint regularly
-    // even when executing VMops that don't require safepoints.
-    if ((_cur_vm_operation = VMThread::no_op_safepoint()) != NULL) {
-      HandleMark hm(VMThread::vm_thread());
-      SafepointSynchronize::begin();
-      SafepointSynchronize::end();
-      _cur_vm_operation = NULL;
-    }
   }
 }
 
@@ -667,11 +649,7 @@
   if (!t->is_VM_thread()) {
     SkipGCALot sgcalot(t);    // avoid re-entrant attempts to gc-a-lot
     // JavaThread or WatcherThread
-    bool concurrent = op->evaluate_concurrently();
-    // only blocking VM operations need to verify the caller's safepoint state:
-    if (!concurrent) {
-      t->check_for_valid_safepoint_state();
-    }
+    t->check_for_valid_safepoint_state();
 
     // New request from Java thread, evaluate prologue
     if (!op->doit_prologue()) {
@@ -681,16 +659,8 @@
     // Setup VM_operations for execution
     op->set_calling_thread(t);
 
-    // It does not make sense to execute the epilogue, if the VM operation object is getting
-    // deallocated by the VM thread.
-    bool execute_epilog = !op->is_cheap_allocated();
-    assert(!concurrent || op->is_cheap_allocated(), "concurrent => cheap_allocated");
-
-    // Get ticket number for non-concurrent VM operations
-    int ticket = 0;
-    if (!concurrent) {
-      ticket = t->vm_operation_ticket();
-    }
+    // Get ticket number for the VM operation
+    int ticket = t->vm_operation_ticket();
 
     // Add VM operation to list of waiting threads. We are guaranteed not to block while holding the
     // VMOperationQueue_lock, so we can block without a safepoint check. This allows vm operation requests
@@ -702,9 +672,8 @@
       op->set_timestamp(os::javaTimeMillis());
       ml.notify();
     }
-
-    if (!concurrent) {
-      // Wait for completion of request (non-concurrent)
+    {
+      // Wait for completion of request
       // Note: only a JavaThread triggers the safepoint check when locking
       MonitorLocker ml(VMOperationRequest_lock,
                        t->is_Java_thread() ? Mutex::_safepoint_check_flag : Mutex::_no_safepoint_check_flag);
@@ -712,10 +681,7 @@
         ml.wait();
       }
     }
-
-    if (execute_epilog) {
-      op->doit_epilogue();
-    }
+    op->doit_epilogue();
   } else {
     // invoked by VM thread; usually nested VM operation
     assert(t->is_VM_thread(), "must be a VM thread");
@@ -744,9 +710,6 @@
       op->evaluate();
     }
 
-    // Free memory if needed
-    if (op->is_cheap_allocated()) delete op;
-
     _cur_vm_operation = prev_vm_operation;
   }
 }