8265934: Cleanup _suspend_flags and _special_runtime_exit_condition

Reviewed-by: rehn, dcubed, dholmes
diff --git a/src/hotspot/share/prims/jvm.cpp b/src/hotspot/share/prims/jvm.cpp
index 9ac09b0..276accf 100644
--- a/src/hotspot/share/prims/jvm.cpp
+++ b/src/hotspot/share/prims/jvm.cpp
@@ -2952,7 +2952,7 @@
       THROW_OOP(java_throwable);
     } else {
       // Use a VM_Operation to throw the exception.
-      Thread::send_async_exception(java_thread, java_throwable);
+      JavaThread::send_async_exception(java_thread, java_throwable);
     }
   } else {
     // Either:
diff --git a/src/hotspot/share/runtime/safepoint.cpp b/src/hotspot/share/runtime/safepoint.cpp
index 7323a41..b2e24fe 100644
--- a/src/hotspot/share/runtime/safepoint.cpp
+++ b/src/hotspot/share/runtime/safepoint.cpp
@@ -971,7 +971,7 @@
 
     // If we have a pending async exception deoptimize the frame
     // as otherwise we may never deliver it.
-    if (self->has_async_condition()) {
+    if (self->has_async_exception_condition()) {
       ThreadInVMfromJava __tiv(self, false /* check asyncs */);
       Deoptimization::deoptimize_frame(self, caller_fr.id());
     }
diff --git a/src/hotspot/share/runtime/thread.cpp b/src/hotspot/share/runtime/thread.cpp
index b367688..87b3b46 100644
--- a/src/hotspot/share/runtime/thread.cpp
+++ b/src/hotspot/share/runtime/thread.cpp
@@ -265,8 +265,6 @@
   set_allocated_bytes(0);
   _current_pending_raw_monitor = NULL;
 
-  _suspend_flags = 0;
-
   // thread-specific hashCode stream generator state - Marsaglia shift-xor form
   _hashStateX = os::random();
   _hashStateY = 842502087;
@@ -541,27 +539,6 @@
   os::start_thread(thread);
 }
 
-class InstallAsyncExceptionClosure : public HandshakeClosure {
-  Handle _throwable; // The Throwable thrown at the target Thread
-public:
-  InstallAsyncExceptionClosure(Handle throwable) : HandshakeClosure("InstallAsyncException"), _throwable(throwable) {}
-
-  void do_thread(Thread* thr) {
-    JavaThread* target = thr->as_Java_thread();
-    // Note that this now allows multiple ThreadDeath exceptions to be
-    // thrown at a thread.
-    // The target thread has run and has not exited yet.
-    target->send_thread_stop(_throwable());
-  }
-};
-
-void Thread::send_async_exception(oop java_thread, oop java_throwable) {
-  Handle throwable(Thread::current(), java_throwable);
-  JavaThread* target = java_lang_Thread::thread(java_thread);
-  InstallAsyncExceptionClosure vm_stop(throwable);
-  Handshake::execute(&vm_stop, target);
-}
-
 // GC Support
 bool Thread::claim_par_threads_do(uintx claim_token) {
   uintx token = _threads_do_token;
@@ -1045,7 +1022,9 @@
   _Stalled(0),
 
   _monitor_chunks(nullptr),
-  _special_runtime_exit_condition(_no_async_condition),
+
+  _suspend_flags(0),
+  _async_exception_condition(_no_async_condition),
   _pending_async_exception(nullptr),
 
   _thread_state(_thread_new),
@@ -1606,13 +1585,14 @@
   }
 }
 
-// JVM support.
 
+// Asynchronous exceptions support
+//
 // Note: this function shouldn't block if it's called in
 // _thread_in_native_trans state (such as from
 // check_special_condition_for_native_trans()).
-void JavaThread::check_and_handle_async_exceptions(bool check_unsafe_error) {
-  if (has_last_Java_frame() && has_async_condition()) {
+void JavaThread::check_and_handle_async_exceptions() {
+  if (has_last_Java_frame() && has_async_exception_condition()) {
     // If we are at a polling page safepoint (not a poll return)
     // then we must defer async exception because live registers
     // will be clobbered by the exception path. Poll return is
@@ -1636,7 +1616,7 @@
     }
   }
 
-  JavaThread::AsyncRequests condition = clear_special_runtime_exit_condition();
+  AsyncExceptionCondition condition = clear_async_exception_condition();
   if (condition == _no_async_condition) {
     // Conditions have changed since has_special_runtime_exit_condition()
     // was called:
@@ -1668,15 +1648,14 @@
         ls.print_cr(" of type: %s", _pending_async_exception->klass()->external_name());
       }
       _pending_async_exception = NULL;
-      clear_has_async_exception();
+      // Clear condition from _suspend_flags since we have finished processing it.
+      clear_suspend_flag(_has_async_exception);
     }
   }
 
-  if (check_unsafe_error &&
-      condition == _async_unsafe_access_error && !has_pending_exception()) {
+  if (condition == _async_unsafe_access_error && !has_pending_exception()) {
     // We may be at method entry which requires we save the do-not-unlock flag.
     UnlockFlagSaver fs(this);
-    condition = _no_async_condition;  // done
     switch (thread_state()) {
     case _thread_in_vm: {
       JavaThread* THREAD = this;
@@ -1700,9 +1679,7 @@
     }
   }
 
-  assert(condition == _no_async_condition || has_pending_exception() ||
-         (!check_unsafe_error && condition == _async_unsafe_access_error),
-         "must have handled the async condition, if no exception");
+  assert(has_pending_exception(), "must have handled the async condition if no exception");
 }
 
 void JavaThread::handle_special_runtime_exit_condition(bool check_asyncs) {
@@ -1721,6 +1698,27 @@
   JFR_ONLY(SUSPEND_THREAD_CONDITIONAL(this);)
 }
 
+class InstallAsyncExceptionClosure : public HandshakeClosure {
+  Handle _throwable; // The Throwable thrown at the target Thread
+public:
+  InstallAsyncExceptionClosure(Handle throwable) : HandshakeClosure("InstallAsyncException"), _throwable(throwable) {}
+
+  void do_thread(Thread* thr) {
+    JavaThread* target = thr->as_Java_thread();
+    // Note that this now allows multiple ThreadDeath exceptions to be
+    // thrown at a thread.
+    // The target thread has run and has not exited yet.
+    target->send_thread_stop(_throwable());
+  }
+};
+
+void JavaThread::send_async_exception(oop java_thread, oop java_throwable) {
+  Handle throwable(Thread::current(), java_throwable);
+  JavaThread* target = java_lang_Thread::thread(java_thread);
+  InstallAsyncExceptionClosure vm_stop(throwable);
+  Handshake::execute(&vm_stop, target);
+}
+
 void JavaThread::send_thread_stop(oop java_throwable)  {
   ResourceMark rm;
   assert(is_handshake_safe_for(Thread::current()),
@@ -1875,10 +1873,10 @@
   // barrier, which will trap unsafe stack frames.
   StackWatermarkSet::before_unwind(thread);
 
-  if (thread->has_async_exception()) {
+  if (thread->has_async_exception_condition(false /* check unsafe access error */)) {
     // We are in _thread_in_native_trans state, don't handle unsafe
     // access error since that may block.
-    thread->check_and_handle_async_exceptions(false);
+    thread->check_and_handle_async_exceptions();
   }
 }
 
diff --git a/src/hotspot/share/runtime/thread.hpp b/src/hotspot/share/runtime/thread.hpp
index 5452175..80d78ee8d 100644
--- a/src/hotspot/share/runtime/thread.hpp
+++ b/src/hotspot/share/runtime/thread.hpp
@@ -215,20 +215,6 @@
  protected:
   static void* allocate(size_t size, bool throw_excpt, MEMFLAGS flags = mtThread);
 
-  enum SuspendFlags {
-    // NOTE: avoid using the sign-bit as cc generates different test code
-    //       when the sign-bit is used, and sometimes incorrectly - see CR 6398077
-
-    _has_async_exception    = 0x00000001U, // there is a pending async exception
-
-    _trace_flag             = 0x00000004U, // call tracing backend
-    _obj_deopt              = 0x00000008U  // suspend for object reallocation and relocking for JVMTI agent
-  };
-
-  // various suspension related flags - atomically updated
-  // overloaded for async exception checking in check_special_condition_for_native_trans.
-  volatile uint32_t _suspend_flags;
-
  private:
   DEBUG_ONLY(bool _suspendible_thread;)
 
@@ -396,20 +382,6 @@
     os::set_native_thread_name(name);
   }
 
-  bool has_async_exception() const { return (_suspend_flags & _has_async_exception) != 0; }
-
-  inline void set_suspend_flag(SuspendFlags f);
-  inline void clear_suspend_flag(SuspendFlags f);
-
-  inline void set_has_async_exception();
-  inline void clear_has_async_exception();
-
-  inline void set_trace_flag();
-  inline void clear_trace_flag();
-
-  inline void set_obj_deopt_flag();
-  inline void clear_obj_deopt_flag();
-
   // Support for Unhandled Oop detection
   // Add the field for both, fastdebug and debug, builds to keep
   // Thread's fields layout the same.
@@ -440,9 +412,6 @@
   void set_skip_gcalot(bool v) { _skip_gcalot = v;    }
 #endif
 
-  // Installs a pending exception to be inserted later
-  static void send_async_exception(oop thread_oop, oop java_throwable);
-
   // Resource area
   ResourceArea* resource_area() const            { return _resource_area; }
   void set_resource_area(ResourceArea* area)     { _resource_area = area; }
@@ -478,10 +447,6 @@
 
   JFR_ONLY(DEFINE_THREAD_LOCAL_ACCESSOR_JFR;)
 
-  bool is_trace_suspend()               { return (_suspend_flags & _trace_flag) != 0; }
-
-  bool is_obj_deopt_suspend()           { return (_suspend_flags & _obj_deopt) != 0; }
-
   // For tracking the Jvmti raw monitor the thread is pending on.
   JvmtiRawMonitor* current_pending_raw_monitor() {
     return _current_pending_raw_monitor;
@@ -807,14 +772,62 @@
                                               // allocated during deoptimization
                                               // and by JNI_MonitorEnter/Exit
 
-  // Async. requests support
-  enum AsyncRequests {
+  enum SuspendFlags {
+    // NOTE: avoid using the sign-bit as cc generates different test code
+    //       when the sign-bit is used, and sometimes incorrectly - see CR 6398077
+    _has_async_exception    = 0x00000001U, // there is a pending async exception
+    _trace_flag             = 0x00000004U, // call tracing backend
+    _obj_deopt              = 0x00000008U  // suspend for object reallocation and relocking for JVMTI agent
+  };
+
+  // various suspension related flags - atomically updated
+  // overloaded with async exceptions so that we do a single check when transitioning from native->Java
+  volatile uint32_t _suspend_flags;
+
+  inline void set_suspend_flag(SuspendFlags f);
+  inline void clear_suspend_flag(SuspendFlags f);
+
+ public:
+  inline void set_trace_flag();
+  inline void clear_trace_flag();
+  inline void set_obj_deopt_flag();
+  inline void clear_obj_deopt_flag();
+  bool is_trace_suspend()      { return (_suspend_flags & _trace_flag) != 0; }
+  bool is_obj_deopt_suspend()  { return (_suspend_flags & _obj_deopt) != 0; }
+
+  // Asynchronous exceptions support
+ private:
+  enum AsyncExceptionCondition {
     _no_async_condition = 0,
     _async_exception,
     _async_unsafe_access_error
   };
-  AsyncRequests _special_runtime_exit_condition; // Enum indicating pending async. request
-  oop           _pending_async_exception;
+  AsyncExceptionCondition _async_exception_condition;
+  oop                     _pending_async_exception;
+
+  void set_async_exception_condition(AsyncExceptionCondition aec) { _async_exception_condition = aec; }
+  AsyncExceptionCondition clear_async_exception_condition() {
+    AsyncExceptionCondition x = _async_exception_condition;
+    _async_exception_condition = _no_async_condition;
+    return x;
+  }
+
+ public:
+  bool has_async_exception_condition(bool check_unsafe_access_error = true) {
+    return check_unsafe_access_error ? _async_exception_condition != _no_async_condition
+                                     : _async_exception_condition == _async_exception;
+  }
+  inline void set_pending_async_exception(oop e);
+  void set_pending_unsafe_access_error()  {
+    // Don't overwrite an asynchronous exception sent by another thread
+    if (_async_exception_condition == _no_async_condition) {
+      set_async_exception_condition(_async_unsafe_access_error);
+    }
+  }
+  void check_and_handle_async_exceptions();
+  // Installs a pending exception to be inserted later
+  static void send_async_exception(oop thread_oop, oop java_throwable);
+  void send_thread_stop(oop throwable);
 
   // Safepoint support
  public:                                                        // Expose _thread_state for SafeFetchInt()
@@ -1127,33 +1140,16 @@
   // current thread, i.e. reverts optimizations based on escape analysis.
   void wait_for_object_deoptimization();
 
-  // Thread.stop support
-  void send_thread_stop(oop throwable);
-  AsyncRequests clear_special_runtime_exit_condition() {
-    AsyncRequests x = _special_runtime_exit_condition;
-    _special_runtime_exit_condition = _no_async_condition;
-    return x;
-  }
-
-  // Are any async conditions present?
-  bool has_async_condition() { return (_special_runtime_exit_condition != _no_async_condition); }
-
-  void check_and_handle_async_exceptions(bool check_unsafe_error = true);
-
   // these next two are also used for self-suspension and async exception support
   void handle_special_runtime_exit_condition(bool check_asyncs = true);
 
   // Return true if JavaThread has an asynchronous condition or
   // if external suspension is requested.
   bool has_special_runtime_exit_condition() {
-    return (_special_runtime_exit_condition != _no_async_condition) ||
+    return (_async_exception_condition != _no_async_condition) ||
            (_suspend_flags & (_obj_deopt JFR_ONLY(| _trace_flag))) != 0;
   }
 
-  void set_pending_unsafe_access_error()          { _special_runtime_exit_condition = _async_unsafe_access_error; }
-
-  inline void set_pending_async_exception(oop e);
-
   // Fast-locking support
   bool is_lock_owned(address adr) const;
 
diff --git a/src/hotspot/share/runtime/thread.inline.hpp b/src/hotspot/share/runtime/thread.inline.hpp
index f84dfa2..8559fe9 100644
--- a/src/hotspot/share/runtime/thread.inline.hpp
+++ b/src/hotspot/share/runtime/thread.inline.hpp
@@ -36,40 +36,6 @@
 #include "runtime/os.hpp"
 #endif
 
-inline void Thread::set_suspend_flag(SuspendFlags f) {
-  uint32_t flags;
-  do {
-    flags = _suspend_flags;
-  }
-  while (Atomic::cmpxchg(&_suspend_flags, flags, (flags | f)) != flags);
-}
-inline void Thread::clear_suspend_flag(SuspendFlags f) {
-  uint32_t flags;
-  do {
-    flags = _suspend_flags;
-  }
-  while (Atomic::cmpxchg(&_suspend_flags, flags, (flags & ~f)) != flags);
-}
-
-inline void Thread::set_has_async_exception() {
-  set_suspend_flag(_has_async_exception);
-}
-inline void Thread::clear_has_async_exception() {
-  clear_suspend_flag(_has_async_exception);
-}
-inline void Thread::set_trace_flag() {
-  set_suspend_flag(_trace_flag);
-}
-inline void Thread::clear_trace_flag() {
-  clear_suspend_flag(_trace_flag);
-}
-inline void Thread::set_obj_deopt_flag() {
-  set_suspend_flag(_obj_deopt);
-}
-inline void Thread::clear_obj_deopt_flag() {
-  clear_suspend_flag(_obj_deopt);
-}
-
 inline jlong Thread::cooked_allocated_bytes() {
   jlong allocated_bytes = Atomic::load_acquire(&_allocated_bytes);
   if (UseTLAB) {
@@ -119,10 +85,41 @@
 }
 #endif // __APPLE__ && AARCH64
 
+inline void JavaThread::set_suspend_flag(SuspendFlags f) {
+  uint32_t flags;
+  do {
+    flags = _suspend_flags;
+  }
+  while (Atomic::cmpxchg(&_suspend_flags, flags, (flags | f)) != flags);
+}
+inline void JavaThread::clear_suspend_flag(SuspendFlags f) {
+  uint32_t flags;
+  do {
+    flags = _suspend_flags;
+  }
+  while (Atomic::cmpxchg(&_suspend_flags, flags, (flags & ~f)) != flags);
+}
+
+inline void JavaThread::set_trace_flag() {
+  set_suspend_flag(_trace_flag);
+}
+inline void JavaThread::clear_trace_flag() {
+  clear_suspend_flag(_trace_flag);
+}
+inline void JavaThread::set_obj_deopt_flag() {
+  set_suspend_flag(_obj_deopt);
+}
+inline void JavaThread::clear_obj_deopt_flag() {
+  clear_suspend_flag(_obj_deopt);
+}
+
 inline void JavaThread::set_pending_async_exception(oop e) {
   _pending_async_exception = e;
-  _special_runtime_exit_condition = _async_exception;
-  set_has_async_exception();
+  set_async_exception_condition(_async_exception);
+  // Set _suspend_flags too so we save a comparison in the transition from native to Java
+  // in the native wrappers. It will be cleared in check_and_handle_async_exceptions()
+  // when we actually install the exception.
+  set_suspend_flag(_has_async_exception);
 }
 
 inline JavaThreadState JavaThread::thread_state() const    {
diff --git a/src/hotspot/share/runtime/vmStructs.cpp b/src/hotspot/share/runtime/vmStructs.cpp
index 7741904..1913a3e 100644
--- a/src/hotspot/share/runtime/vmStructs.cpp
+++ b/src/hotspot/share/runtime/vmStructs.cpp
@@ -730,7 +730,6 @@
   nonstatic_field(ThreadShadow,                _pending_exception,                            oop)                                   \
   nonstatic_field(ThreadShadow,                _exception_file,                               const char*)                           \
   nonstatic_field(ThreadShadow,                _exception_line,                               int)                                   \
-  volatile_nonstatic_field(Thread,             _suspend_flags,                                uint32_t)                              \
   nonstatic_field(Thread,                      _active_handles,                               JNIHandleBlock*)                       \
   nonstatic_field(Thread,                      _tlab,                                         ThreadLocalAllocBuffer)                \
   nonstatic_field(Thread,                      _allocated_bytes,                              jlong)                                 \
@@ -743,11 +742,12 @@
   nonstatic_field(JavaThread,                  _current_pending_monitor,                      ObjectMonitor*)                        \
   nonstatic_field(JavaThread,                  _current_pending_monitor_is_from_java,         bool)                                  \
   nonstatic_field(JavaThread,                  _current_waiting_monitor,                      ObjectMonitor*)                        \
+  volatile_nonstatic_field(JavaThread,         _suspend_flags,                                uint32_t)                              \
+  nonstatic_field(JavaThread,                  _async_exception_condition,                    JavaThread::AsyncExceptionCondition)   \
   nonstatic_field(JavaThread,                  _pending_async_exception,                      oop)                                   \
   volatile_nonstatic_field(JavaThread,         _exception_oop,                                oop)                                   \
   volatile_nonstatic_field(JavaThread,         _exception_pc,                                 address)                               \
   volatile_nonstatic_field(JavaThread,         _is_method_handle_return,                      int)                                   \
-  nonstatic_field(JavaThread,                  _special_runtime_exit_condition,               JavaThread::AsyncRequests)             \
   nonstatic_field(JavaThread,                  _saved_exception_pc,                           address)                               \
   volatile_nonstatic_field(JavaThread,         _thread_state,                                 JavaThreadState)                       \
   nonstatic_field(JavaThread,                  _osthread,                                     OSThread*)                             \
@@ -1983,7 +1983,7 @@
   declare_toplevel_type(JavaThread*)                                      \
   declare_toplevel_type(JavaThread *const *const)                         \
   declare_toplevel_type(java_lang_Class)                                  \
-  declare_integer_type(JavaThread::AsyncRequests)                         \
+  declare_integer_type(JavaThread::AsyncExceptionCondition)               \
   declare_integer_type(JavaThread::TerminatedTypes)                       \
   declare_toplevel_type(jbyte*)                                           \
   declare_toplevel_type(jbyte**)                                          \
@@ -2143,7 +2143,7 @@
   /* Thread::SuspendFlags enum */                                         \
   /*****************************/                                         \
                                                                           \
-  declare_constant(Thread::_has_async_exception)                          \
+  declare_constant(JavaThread::_has_async_exception)                      \
                                                                           \
   /*******************/                                                   \
   /* JavaThreadState */                                                   \
diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/Thread.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/Thread.java
index 5673643..fe7e684 100644
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/Thread.java
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/Thread.java
@@ -55,8 +55,8 @@
     Type typeThread = db.lookupType("Thread");
     Type typeJavaThread = db.lookupType("JavaThread");
 
-    suspendFlagsField = typeThread.getCIntegerField("_suspend_flags");
-    HAS_ASYNC_EXCEPTION = db.lookupIntConstant("Thread::_has_async_exception").intValue();
+    suspendFlagsField = typeJavaThread.getCIntegerField("_suspend_flags");
+    HAS_ASYNC_EXCEPTION = db.lookupIntConstant("JavaThread::_has_async_exception").intValue();
 
     tlabFieldOffset    = typeThread.getField("_tlab").getOffset();
     activeHandlesField = typeThread.getAddressField("_active_handles");