changeset 57499:87266ac324d7

Merge
author jwilhelm
date Wed, 18 Dec 2019 23:46:55 +0100
parents d0f45be4fbd8 5d4bf79ce2cb
children f33197adda9a
files src/hotspot/share/gc/z/zRootsIterator.cpp src/hotspot/share/runtime/thread.cpp test/jdk/TEST.groups
diffstat 30 files changed, 392 insertions(+), 94 deletions(-) [+]
line wrap: on
line diff
--- a/src/hotspot/share/code/compiledMethod.cpp	Wed Dec 18 12:14:01 2019 -0800
+++ b/src/hotspot/share/code/compiledMethod.cpp	Wed Dec 18 23:46:55 2019 +0100
@@ -549,6 +549,21 @@
   return true;
 }
 
+void CompiledMethod::run_nmethod_entry_barrier() {
+  BarrierSetNMethod* bs_nm = BarrierSet::barrier_set()->barrier_set_nmethod();
+  if (bs_nm != NULL) {
+    // We want to keep an invariant that nmethods found through iterations of a Thread's
+    // nmethods found in safepoints have gone through an entry barrier and are not armed.
+    // By calling this nmethod entry barrier, it plays along and acts
+    // like any other nmethod found on the stack of a thread (fewer surprises).
+    nmethod* nm = as_nmethod_or_null();
+    if (nm != NULL) {
+      bool alive = bs_nm->nmethod_entry_barrier(nm);
+      assert(alive, "should be alive");
+    }
+  }
+}
+
 void CompiledMethod::cleanup_inline_caches(bool clean_all) {
   for (;;) {
     ICRefillVerifier ic_refill_verifier;
@@ -557,18 +572,8 @@
         return;
       }
     }
-    BarrierSetNMethod* bs_nm = BarrierSet::barrier_set()->barrier_set_nmethod();
-    if (bs_nm != NULL) {
-      // We want to keep an invariant that nmethods found through iterations of a Thread's
-      // nmethods found in safepoints have gone through an entry barrier and are not armed.
-      // By calling this nmethod entry barrier from the sweeper, it plays along and acts
-      // like any other nmethod found on the stack of a thread (fewer surprises).
-      nmethod* nm = as_nmethod_or_null();
-      if (nm != NULL) {
-        bool alive = bs_nm->nmethod_entry_barrier(nm);
-        assert(alive, "should be alive");
-      }
-    }
+    // Call this nmethod entry barrier from the sweeper.
+    run_nmethod_entry_barrier();
     InlineCacheBuffer::refill_ic_stubs();
   }
 }
--- a/src/hotspot/share/code/compiledMethod.hpp	Wed Dec 18 12:14:01 2019 -0800
+++ b/src/hotspot/share/code/compiledMethod.hpp	Wed Dec 18 23:46:55 2019 +0100
@@ -366,6 +366,9 @@
   virtual void clear_inline_caches();
   void clear_ic_callsites();
 
+  // Execute nmethod barrier code, as if entering through nmethod call.
+  void run_nmethod_entry_barrier();
+
   // Verify and count cached icholder relocations.
   int  verify_icholder_relocations();
   void verify_oop_relocations();
--- a/src/hotspot/share/code/nmethod.cpp	Wed Dec 18 12:14:01 2019 -0800
+++ b/src/hotspot/share/code/nmethod.cpp	Wed Dec 18 23:46:55 2019 +0100
@@ -1567,6 +1567,12 @@
 // Transfer information from compilation to jvmti
 void nmethod::post_compiled_method_load_event(JvmtiThreadState* state) {
 
+  // Don't post this nmethod load event if it is already dying
+  // because the sweeper might already be deleting this nmethod.
+  if (is_not_entrant() && can_convert_to_zombie()) {
+    return;
+  }
+
   // This is a bad time for a safepoint.  We don't want
   // this nmethod to get unloaded while we're queueing the event.
   NoSafepointVerifier nsv;
@@ -1585,15 +1591,16 @@
   if (JvmtiExport::should_post_compiled_method_load()) {
     // Only post unload events if load events are found.
     set_load_reported();
-    // Keep sweeper from turning this into zombie until it is posted.
-    mark_as_seen_on_stack();
-
     // If a JavaThread hasn't been passed in, let the Service thread
     // (which is a real Java thread) post the event
     JvmtiDeferredEvent event = JvmtiDeferredEvent::compiled_method_load_event(this);
     if (state == NULL) {
+      // Execute any barrier code for this nmethod as if it's called, since
+      // keeping it alive looks like stack walking.
+      run_nmethod_entry_barrier();
       ServiceThread::enqueue_deferred_event(&event);
     } else {
+      // This enters the nmethod barrier outside in the caller.
       state->enqueue_event(&event);
     }
   }
--- a/src/hotspot/share/gc/parallel/psParallelCompact.hpp	Wed Dec 18 12:14:01 2019 -0800
+++ b/src/hotspot/share/gc/parallel/psParallelCompact.hpp	Wed Dec 18 23:46:55 2019 +0100
@@ -630,25 +630,25 @@
 }
 
 inline bool ParallelCompactData::RegionData::mark_normal() {
-  return Atomic::cmpxchg(&_shadow_state, UnusedRegion, NormalRegion, memory_order_relaxed) == UnusedRegion;
+  return Atomic::cmpxchg(&_shadow_state, UnusedRegion, NormalRegion) == UnusedRegion;
 }
 
 inline bool ParallelCompactData::RegionData::mark_shadow() {
   if (_shadow_state != UnusedRegion) return false;
-  return Atomic::cmpxchg(&_shadow_state, UnusedRegion, ShadowRegion, memory_order_relaxed) == UnusedRegion;
+  return Atomic::cmpxchg(&_shadow_state, UnusedRegion, ShadowRegion) == UnusedRegion;
 }
 
 inline void ParallelCompactData::RegionData::mark_filled() {
-  int old = Atomic::cmpxchg(&_shadow_state, ShadowRegion, FilledShadow, memory_order_relaxed);
+  int old = Atomic::cmpxchg(&_shadow_state, ShadowRegion, FilledShadow);
   assert(old == ShadowRegion, "Fail to mark the region as filled");
 }
 
 inline bool ParallelCompactData::RegionData::mark_copied() {
-  return Atomic::cmpxchg(&_shadow_state, FilledShadow, CopiedShadow, memory_order_relaxed) == FilledShadow;
+  return Atomic::cmpxchg(&_shadow_state, FilledShadow, CopiedShadow) == FilledShadow;
 }
 
 void ParallelCompactData::RegionData::shadow_to_normal() {
-  int old = Atomic::cmpxchg(&_shadow_state, ShadowRegion, NormalRegion, memory_order_relaxed);
+  int old = Atomic::cmpxchg(&_shadow_state, ShadowRegion, NormalRegion);
   assert(old == ShadowRegion, "Fail to mark the region as finish");
 }
 
--- a/src/hotspot/share/gc/shared/genCollectedHeap.cpp	Wed Dec 18 12:14:01 2019 -0800
+++ b/src/hotspot/share/gc/shared/genCollectedHeap.cpp	Wed Dec 18 23:46:55 2019 +0100
@@ -472,7 +472,7 @@
     HandleMark hm;  // Discard invalid handles created during verification
     Universe::verify("Before GC");
   }
-  COMPILER2_PRESENT(DerivedPointerTable::clear());
+  COMPILER2_OR_JVMCI_PRESENT(DerivedPointerTable::clear());
 
   if (restore_marks_for_biased_locking) {
     // We perform this mark word preservation work lazily
@@ -520,7 +520,7 @@
     rp->verify_no_references_recorded();
   }
 
-  COMPILER2_PRESENT(DerivedPointerTable::update_pointers());
+  COMPILER2_OR_JVMCI_PRESENT(DerivedPointerTable::update_pointers());
 
   gen->stat_record()->accumulated_time.stop();
 
--- a/src/hotspot/share/gc/z/zRootsIterator.cpp	Wed Dec 18 12:14:01 2019 -0800
+++ b/src/hotspot/share/gc/z/zRootsIterator.cpp	Wed Dec 18 23:46:55 2019 +0100
@@ -44,8 +44,7 @@
 #include "memory/universe.hpp"
 #include "prims/jvmtiExport.hpp"
 #include "prims/resolvedMethodTable.hpp"
-#include "runtime/atomic.hpp"
-#include "runtime/safepoint.hpp"
+#include "runtime/atomic.hpp"#include "runtime/safepoint.hpp"
 #include "runtime/synchronizer.hpp"
 #include "runtime/thread.hpp"
 #include "runtime/vmThread.hpp"
@@ -208,7 +207,7 @@
     _code_cache(this) {
   assert(SafepointSynchronize::is_at_safepoint(), "Should be at safepoint");
   ZStatTimer timer(ZSubPhasePauseRootsSetup);
-  COMPILER2_PRESENT(DerivedPointerTable::clear());
+  COMPILER2_OR_JVMCI_PRESENT(DerivedPointerTable::clear());
   if (ClassUnloading) {
     nmethod::oops_do_marking_prologue();
   } else {
@@ -225,7 +224,7 @@
     ZNMethod::oops_do_end();
   }
 
-  COMPILER2_PRESENT(DerivedPointerTable::update_pointers());
+  COMPILER2_OR_JVMCI_PRESENT(DerivedPointerTable::update_pointers());
 }
 
 void ZRootsIterator::do_universe(ZRootsIteratorClosure* cl) {
--- a/src/hotspot/share/jvmci/jvmci_globals.cpp	Wed Dec 18 12:14:01 2019 -0800
+++ b/src/hotspot/share/jvmci/jvmci_globals.cpp	Wed Dec 18 23:46:55 2019 +0100
@@ -114,6 +114,16 @@
   CHECK_NOT_SET(JVMCILibPath,                 EnableJVMCI)
   CHECK_NOT_SET(JVMCILibDumpJNIConfig,        EnableJVMCI)
 
+#ifndef COMPILER2
+  JVMCI_FLAG_CHECKED(MaxVectorSize)
+  JVMCI_FLAG_CHECKED(ReduceInitialCardMarks)
+  JVMCI_FLAG_CHECKED(UseMultiplyToLenIntrinsic)
+  JVMCI_FLAG_CHECKED(UseSquareToLenIntrinsic)
+  JVMCI_FLAG_CHECKED(UseMulAddIntrinsic)
+  JVMCI_FLAG_CHECKED(UseMontgomeryMultiplyIntrinsic)
+  JVMCI_FLAG_CHECKED(UseMontgomerySquareIntrinsic)
+#endif // !COMPILER2
+
 #ifndef PRODUCT
 #define JVMCI_CHECK4(type, name, value, doc) assert(name##checked, #name " flag not checked");
 #define JVMCI_CHECK3(type, name, doc)        assert(name##checked, #name " flag not checked");
--- a/src/hotspot/share/opto/loopopts.cpp	Wed Dec 18 12:14:01 2019 -0800
+++ b/src/hotspot/share/opto/loopopts.cpp	Wed Dec 18 23:46:55 2019 +0100
@@ -498,9 +498,10 @@
   Node * in2 = n->in(2);
   if (in1->Opcode() == Op_MulI && in2->Opcode() == Op_MulI) {
     IdealLoopTree* loop_n = get_loop(get_ctrl(n));
-    if (loop_n->_head->as_Loop()->is_valid_counted_loop() &&
-        Matcher::match_rule_supported(Op_MulAddS2I) &&
-        Matcher::match_rule_supported(Op_MulAddVS2VI)) {
+    if (loop_n->is_counted() &&
+        loop_n->_head->as_Loop()->is_valid_counted_loop() &&
+        Matcher::match_rule_supported(Op_MulAddVS2VI) &&
+        Matcher::match_rule_supported(Op_MulAddS2I)) {
       Node* mul_in1 = in1->in(1);
       Node* mul_in2 = in1->in(2);
       Node* mul_in3 = in2->in(1);
--- a/src/hotspot/share/prims/jvmtiCodeBlobEvents.cpp	Wed Dec 18 12:14:01 2019 -0800
+++ b/src/hotspot/share/prims/jvmtiCodeBlobEvents.cpp	Wed Dec 18 23:46:55 2019 +0100
@@ -34,6 +34,7 @@
 #include "prims/jvmtiExport.hpp"
 #include "prims/jvmtiThreadState.inline.hpp"
 #include "runtime/handles.inline.hpp"
+#include "runtime/safepointVerifiers.hpp"
 #include "runtime/vmThread.hpp"
 
 // Support class to collect a list of the non-nmethod CodeBlobs in
@@ -222,16 +223,22 @@
 jvmtiError JvmtiCodeBlobEvents::generate_compiled_method_load_events(JvmtiEnv* env) {
   JvmtiThreadState* state = JvmtiThreadState::state_for(JavaThread::current());
   {
-    // Walk the CodeCache notifying for live nmethods, don't release the CodeCache_lock
-    // because the sweeper may be running concurrently.
-    // Save events to the queue for posting outside the CodeCache_lock.
-    MutexLocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
-    // Iterate over non-profiled and profiled nmethods
-    NMethodIterator iter(NMethodIterator::only_alive_and_not_unloading);
-    while(iter.next()) {
-      nmethod* current = iter.method();
-      current->post_compiled_method_load_event(state);
+    NoSafepointVerifier nsv;  // safepoints are not safe while collecting methods to post.
+    {
+      // Walk the CodeCache notifying for live nmethods, don't release the CodeCache_lock
+      // because the sweeper may be running concurrently.
+      // Save events to the queue for posting outside the CodeCache_lock.
+      MutexLocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
+      // Iterate over non-profiled and profiled nmethods
+      NMethodIterator iter(NMethodIterator::only_alive_and_not_unloading);
+      while(iter.next()) {
+        nmethod* current = iter.method();
+        current->post_compiled_method_load_event(state);
+      }
     }
+
+    // Enter nmethod barrier code if present outside CodeCache_lock
+    state->run_nmethod_entry_barriers();
   }
 
   // Now post all the events outside the CodeCache_lock.
--- a/src/hotspot/share/prims/jvmtiImpl.cpp	Wed Dec 18 12:14:01 2019 -0800
+++ b/src/hotspot/share/prims/jvmtiImpl.cpp	Wed Dec 18 23:46:55 2019 +0100
@@ -25,6 +25,7 @@
 #include "precompiled.hpp"
 #include "classfile/symbolTable.hpp"
 #include "classfile/systemDictionary.hpp"
+#include "code/nmethod.hpp"
 #include "interpreter/interpreter.hpp"
 #include "interpreter/oopMapCache.hpp"
 #include "jvmtifiles/jvmtiEnv.hpp"
@@ -992,6 +993,12 @@
   JvmtiExport::post_compiled_method_load(env, nm);
 }
 
+void JvmtiDeferredEvent::run_nmethod_entry_barriers() {
+  if (_type == TYPE_COMPILED_METHOD_LOAD) {
+    _event_data.compiled_method_load->run_nmethod_entry_barrier();
+  }
+}
+
 
 // Keep the nmethod for compiled_method_load from being unloaded.
 void JvmtiDeferredEvent::oops_do(OopClosure* f, CodeBlobClosure* cf) {
@@ -1008,8 +1015,16 @@
   }
 }
 
+
 bool JvmtiDeferredEventQueue::has_events() {
-  return _queue_head != NULL;
+  // We save the queued events before the live phase and post them when it starts.
+  // This code could skip saving the events on the queue before the live
+  // phase and ignore them, but this would change how we do things now.
+  // Starting the service thread earlier causes this to be called before the live phase begins.
+  // The events on the queue should all be posted after the live phase so this is an
+  // ok check.  Before the live phase, DynamicCodeGenerated events are posted directly.
+  // If we add other types of events to the deferred queue, this could get ugly.
+  return JvmtiEnvBase::get_phase() == JVMTI_PHASE_LIVE  && _queue_head != NULL;
 }
 
 void JvmtiDeferredEventQueue::enqueue(JvmtiDeferredEvent event) {
@@ -1057,6 +1072,13 @@
   }
 }
 
+void JvmtiDeferredEventQueue::run_nmethod_entry_barriers() {
+  for(QueueNode* node = _queue_head; node != NULL; node = node->next()) {
+     node->event().run_nmethod_entry_barriers();
+  }
+}
+
+
 void JvmtiDeferredEventQueue::oops_do(OopClosure* f, CodeBlobClosure* cf) {
   for(QueueNode* node = _queue_head; node != NULL; node = node->next()) {
      node->event().oops_do(f, cf);
--- a/src/hotspot/share/prims/jvmtiImpl.hpp	Wed Dec 18 12:14:01 2019 -0800
+++ b/src/hotspot/share/prims/jvmtiImpl.hpp	Wed Dec 18 23:46:55 2019 +0100
@@ -481,6 +481,7 @@
   // Actually posts the event.
   void post() NOT_JVMTI_RETURN;
   void post_compiled_method_load_event(JvmtiEnv* env) NOT_JVMTI_RETURN;
+  void run_nmethod_entry_barriers() NOT_JVMTI_RETURN;
   // Sweeper support to keep nmethods from being zombied while in the queue.
   void nmethods_do(CodeBlobClosure* cf) NOT_JVMTI_RETURN;
   // GC support to keep nmethod from being unloaded while in the queue.
@@ -522,6 +523,7 @@
   // Post all events in the queue for the current Jvmti environment
   void post(JvmtiEnv* env) NOT_JVMTI_RETURN;
   void enqueue(JvmtiDeferredEvent event) NOT_JVMTI_RETURN;
+  void run_nmethod_entry_barriers();
 
   // Sweeper support to keep nmethods from being zombied while in the queue.
   void nmethods_do(CodeBlobClosure* cf) NOT_JVMTI_RETURN;
--- a/src/hotspot/share/prims/jvmtiThreadState.cpp	Wed Dec 18 12:14:01 2019 -0800
+++ b/src/hotspot/share/prims/jvmtiThreadState.cpp	Wed Dec 18 23:46:55 2019 +0100
@@ -432,3 +432,8 @@
   }
 }
 
+void JvmtiThreadState::run_nmethod_entry_barriers() {
+  if (_jvmti_event_queue != NULL) {
+    _jvmti_event_queue->run_nmethod_entry_barriers();
+  }
+}
--- a/src/hotspot/share/prims/jvmtiThreadState.hpp	Wed Dec 18 12:14:01 2019 -0800
+++ b/src/hotspot/share/prims/jvmtiThreadState.hpp	Wed Dec 18 23:46:55 2019 +0100
@@ -398,6 +398,7 @@
   // Thread local event queue, which doesn't require taking the Service_lock.
   void enqueue_event(JvmtiDeferredEvent* event);
   void post_events(JvmtiEnv* env);
+  void run_nmethod_entry_barriers();
 };
 
 class RedefineVerifyMark : public StackObj {
--- a/src/hotspot/share/runtime/deoptimization.cpp	Wed Dec 18 12:14:01 2019 -0800
+++ b/src/hotspot/share/runtime/deoptimization.cpp	Wed Dec 18 23:46:55 2019 +0100
@@ -302,7 +302,7 @@
 
   // Reallocate the non-escaping objects and restore their fields. Then
   // relock objects if synchronization on them was eliminated.
-  if (jvmci_enabled || (DoEscapeAnalysis && EliminateAllocations)) {
+  if (jvmci_enabled COMPILER2_PRESENT( || (DoEscapeAnalysis && EliminateAllocations) )) {
     realloc_failures = eliminate_allocations(thread, exec_mode, cm, deoptee, map, chunk);
   }
 #endif // COMPILER2_OR_JVMCI
@@ -318,7 +318,7 @@
   NoSafepointVerifier no_safepoint;
 
 #if COMPILER2_OR_JVMCI
-  if (jvmci_enabled || ((DoEscapeAnalysis || EliminateNestedLocks) && EliminateLocks)) {
+  if (jvmci_enabled COMPILER2_PRESENT( || ((DoEscapeAnalysis || EliminateNestedLocks) && EliminateLocks) )) {
     eliminate_locks(thread, chunk, realloc_failures);
   }
 #endif // COMPILER2_OR_JVMCI
--- a/src/hotspot/share/runtime/serviceThread.cpp	Wed Dec 18 12:14:01 2019 -0800
+++ b/src/hotspot/share/runtime/serviceThread.cpp	Wed Dec 18 23:46:55 2019 +0100
@@ -48,7 +48,8 @@
 ServiceThread* ServiceThread::_instance = NULL;
 JvmtiDeferredEvent* ServiceThread::_jvmti_event = NULL;
 // The service thread has it's own static deferred event queue.
-// Events can be posted before the service thread is created.
+// Events can be posted before JVMTI vm_start, so it's too early to call JvmtiThreadState::state_for
+// to add this field to the per-JavaThread event queue.  TODO: fix this sometime later
 JvmtiDeferredEventQueue ServiceThread::_jvmti_service_queue;
 
 void ServiceThread::initialize() {
@@ -195,6 +196,10 @@
 
 void ServiceThread::enqueue_deferred_event(JvmtiDeferredEvent* event) {
   MutexLocker ml(Service_lock, Mutex::_no_safepoint_check_flag);
+  // If you enqueue events before the service thread runs, gc and the sweeper
+  // cannot keep the nmethod alive.  This could be restricted to compiled method
+  // load and unload events, if we wanted to be picky.
+  assert(_instance != NULL, "cannot enqueue events before the service thread runs");
   _jvmti_service_queue.enqueue(*event);
   Service_lock->notify_all();
  }
--- a/src/hotspot/share/runtime/thread.cpp	Wed Dec 18 12:14:01 2019 -0800
+++ b/src/hotspot/share/runtime/thread.cpp	Wed Dec 18 23:46:55 2019 +0100
@@ -88,6 +88,7 @@
 #include "runtime/safepoint.hpp"
 #include "runtime/safepointMechanism.inline.hpp"
 #include "runtime/safepointVerifiers.hpp"
+#include "runtime/serviceThread.hpp"
 #include "runtime/sharedRuntime.hpp"
 #include "runtime/statSampler.hpp"
 #include "runtime/stubRoutines.hpp"
@@ -3995,6 +3996,10 @@
     Chunk::start_chunk_pool_cleaner_task();
   }
 
+  // Start the service thread
+  // The service thread enqueues JVMTI deferred events and does various hashtable
+  // and other cleanups.  Needs to start before the compilers start posting events.
+  ServiceThread::initialize();
 
   // initialize compiler(s)
 #if defined(COMPILER1) || COMPILER2_OR_JVMCI
--- a/src/hotspot/share/services/management.cpp	Wed Dec 18 12:14:01 2019 -0800
+++ b/src/hotspot/share/services/management.cpp	Wed Dec 18 23:46:55 2019 +0100
@@ -46,7 +46,6 @@
 #include "runtime/jniHandles.inline.hpp"
 #include "runtime/notificationThread.hpp"
 #include "runtime/os.hpp"
-#include "runtime/serviceThread.hpp"
 #include "runtime/thread.inline.hpp"
 #include "runtime/threadSMR.hpp"
 #include "services/classLoadingService.hpp"
@@ -147,8 +146,6 @@
 }
 
 void Management::initialize(TRAPS) {
-  // Start the service thread
-  ServiceThread::initialize();
   if (UseNotificationThread) {
     NotificationThread::initialize();
   }
--- a/src/java.base/share/classes/sun/security/tools/keytool/Main.java	Wed Dec 18 12:14:01 2019 -0800
+++ b/src/java.base/share/classes/sun/security/tools/keytool/Main.java	Wed Dec 18 23:46:55 2019 +0100
@@ -4654,7 +4654,7 @@
                     rb.getString("whose.key.risk"),
                     label,
                     String.format(rb.getString("key.bit"),
-                            KeyUtil.getKeySize(key), key.getAlgorithm())));
+                            KeyUtil.getKeySize(key), fullDisplayAlgName(key))));
         }
     }
 
--- a/src/java.base/share/classes/sun/security/util/AbstractAlgorithmConstraints.java	Wed Dec 18 12:14:01 2019 -0800
+++ b/src/java.base/share/classes/sun/security/util/AbstractAlgorithmConstraints.java	Wed Dec 18 23:46:55 2019 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -29,6 +29,10 @@
 import java.security.AlgorithmConstraints;
 import java.security.PrivilegedAction;
 import java.security.Security;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
 import java.util.Set;
 
 /**
@@ -44,7 +48,7 @@
     }
 
     // Get algorithm constraints from the specified security property.
-    static String[] getAlgorithms(String propertyName) {
+    static List<String> getAlgorithms(String propertyName) {
         String property = AccessController.doPrivileged(
                 new PrivilegedAction<String>() {
                     @Override
@@ -68,12 +72,12 @@
 
         // map the disabled algorithms
         if (algorithmsInProperty == null) {
-            algorithmsInProperty = new String[0];
+            return Collections.emptyList();
         }
-        return algorithmsInProperty;
+        return new ArrayList<>(Arrays.asList(algorithmsInProperty));
     }
 
-    static boolean checkAlgorithm(String[] algorithms, String algorithm,
+    static boolean checkAlgorithm(List<String> algorithms, String algorithm,
             AlgorithmDecomposer decomposer) {
         if (algorithm == null || algorithm.isEmpty()) {
             throw new IllegalArgumentException("No algorithm name specified");
--- a/src/java.base/share/classes/sun/security/util/ConstraintsParameters.java	Wed Dec 18 12:14:01 2019 -0800
+++ b/src/java.base/share/classes/sun/security/util/ConstraintsParameters.java	Wed Dec 18 23:46:55 2019 +0100
@@ -31,6 +31,9 @@
 import java.security.Key;
 import java.security.Timestamp;
 import java.security.cert.X509Certificate;
+import java.security.interfaces.ECKey;
+import java.security.interfaces.XECKey;
+import java.security.spec.NamedParameterSpec;
 import java.util.Date;
 
 /**
@@ -49,8 +52,8 @@
     private final String algorithm;
     // AlgorithmParameters to the algorithm being checked
     private final AlgorithmParameters algParams;
-    // Public Key being checked against constraints
-    private final Key publicKey;
+    // Key being checked against constraints
+    private final Key key;
 
     /*
      * New values that are checked against constraints that the current public
@@ -66,6 +69,9 @@
     // Timestamp of the signed JAR file
     private final Timestamp jarTimestamp;
     private final String variant;
+    // Named Curve
+    private final String[] curveStr;
+    private static final String[] EMPTYLIST = new String[0];
 
     public ConstraintsParameters(X509Certificate c, boolean match,
             Date pkixdate, Timestamp jarTime, String variant) {
@@ -76,14 +82,20 @@
         this.variant = (variant == null ? Validator.VAR_GENERIC : variant);
         algorithm = null;
         algParams = null;
-        publicKey = null;
+        key = null;
+        if (c != null) {
+            curveStr = getNamedCurveFromKey(c.getPublicKey());
+        } else {
+            curveStr = EMPTYLIST;
+        }
     }
 
     public ConstraintsParameters(String algorithm, AlgorithmParameters params,
             Key key, String variant) {
         this.algorithm = algorithm;
         algParams = params;
-        this.publicKey = key;
+        this.key = key;
+        curveStr = getNamedCurveFromKey(key);
         cert = null;
         trustedMatch = false;
         pkixDate = null;
@@ -109,9 +121,10 @@
         return algParams;
     }
 
-    public Key getPublicKey() {
-        return publicKey;
+    public Key getKey() {
+        return key;
     }
+
     // Returns if the trust anchor has a match if anchor checking is enabled.
     public boolean isTrustedMatch() {
         return trustedMatch;
@@ -132,4 +145,47 @@
     public String getVariant() {
         return variant;
     }
+
+    public String[] getNamedCurve() {
+        return curveStr;
+    }
+
+    public static String[] getNamedCurveFromKey(Key key) {
+        if (key instanceof ECKey) {
+            NamedCurve nc = CurveDB.lookup(((ECKey)key).getParams());
+            return (nc == null ? EMPTYLIST : CurveDB.getNamesByOID(nc.getObjectId()));
+        } else if (key instanceof XECKey) {
+            String[] s = {
+                    ((NamedParameterSpec)((XECKey)key).getParams()).getName()
+            };
+            return s;
+        } else {
+            return EMPTYLIST;
+        }
+    }
+
+    public String toString() {
+        StringBuilder s = new StringBuilder();
+        s.append("Cert:       ");
+        if (cert != null) {
+            s.append(cert.toString());
+            s.append("\nSigAlgo:    ");
+            s.append(cert.getSigAlgName());
+        } else {
+            s.append("None");
+        }
+        s.append("\nAlgParams:  ");
+        if (getAlgParams() != null) {
+            getAlgParams().toString();
+        } else {
+            s.append("None");
+        }
+        s.append("\nNamedCurves: ");
+        for (String c : getNamedCurve()) {
+            s.append(c + " ");
+        }
+        s.append("\nVariant:    " + getVariant());
+        return s.toString();
+    }
+
 }
--- a/src/java.base/share/classes/sun/security/util/CurveDB.java	Wed Dec 18 12:14:01 2019 -0800
+++ b/src/java.base/share/classes/sun/security/util/CurveDB.java	Wed Dec 18 23:46:55 2019 +0100
@@ -154,8 +154,27 @@
         }
     }
 
+    private static class Holder {
+        private static final Pattern nameSplitPattern = Pattern.compile(
+                SPLIT_PATTERN);
+    }
+
+    // Return all the names the EC curve could be using.
+    static String[] getNamesByOID(String oid) {
+        NamedCurve nc = oidMap.get(oid);
+        if (nc == null) {
+            return new String[0];
+        }
+        String[] list = Holder.nameSplitPattern.split(nc.getName());
+        int i = 0;
+        do {
+            list[i] = list[i].trim();
+        } while (++i < list.length);
+        return list;
+    }
+
     static {
-        Pattern nameSplitPattern = Pattern.compile(SPLIT_PATTERN);
+        Pattern nameSplitPattern = Holder.nameSplitPattern;
 
         /* SEC2 prime curves */
         add("secp112r1", "1.3.132.0.6", P,
--- a/src/java.base/share/classes/sun/security/util/DisabledAlgorithmConstraints.java	Wed Dec 18 12:14:01 2019 -0800
+++ b/src/java.base/share/classes/sun/security/util/DisabledAlgorithmConstraints.java	Wed Dec 18 23:46:55 2019 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,8 +27,6 @@
 
 import sun.security.validator.Validator;
 
-import java.io.ByteArrayOutputStream;
-import java.io.PrintStream;
 import java.security.CryptoPrimitive;
 import java.security.AlgorithmParameters;
 import java.security.Key;
@@ -37,6 +35,7 @@
 import java.security.cert.X509Certificate;
 import java.text.SimpleDateFormat;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Calendar;
 import java.util.Date;
 import java.util.HashMap;
@@ -60,19 +59,23 @@
 public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints {
     private static final Debug debug = Debug.getInstance("certpath");
 
-    // the known security property, jdk.certpath.disabledAlgorithms
+    // Disabled algorithm security property for certificate path
     public static final String PROPERTY_CERTPATH_DISABLED_ALGS =
             "jdk.certpath.disabledAlgorithms";
 
-    // the known security property, jdk.tls.disabledAlgorithms
+    // Disabled algorithm security property for TLS
     public static final String PROPERTY_TLS_DISABLED_ALGS =
             "jdk.tls.disabledAlgorithms";
 
-    // the known security property, jdk.jar.disabledAlgorithms
+    // Disabled algorithm security property for jar
     public static final String PROPERTY_JAR_DISABLED_ALGS =
             "jdk.jar.disabledAlgorithms";
 
-    private final String[] disabledAlgorithms;
+    // Property for disabled EC named curves
+    private static final String PROPERTY_DISABLED_EC_CURVES =
+            "jdk.disabled.namedCurves";
+
+    private final List<String> disabledAlgorithms;
     private final Constraints algorithmConstraints;
 
     /**
@@ -97,6 +100,24 @@
             AlgorithmDecomposer decomposer) {
         super(decomposer);
         disabledAlgorithms = getAlgorithms(propertyName);
+
+        // Check for alias
+        int ecindex = -1, i = 0;
+        for (String s : disabledAlgorithms) {
+            if (s.regionMatches(true, 0,"include ", 0, 8)) {
+                if (s.regionMatches(true, 8, PROPERTY_DISABLED_EC_CURVES, 0,
+                        PROPERTY_DISABLED_EC_CURVES.length())) {
+                    ecindex = i;
+                    break;
+                }
+            }
+            i++;
+        }
+        if (ecindex > -1) {
+            disabledAlgorithms.remove(ecindex);
+            disabledAlgorithms.addAll(ecindex,
+                    getAlgorithms(PROPERTY_DISABLED_EC_CURVES));
+        }
         algorithmConstraints = new Constraints(disabledAlgorithms);
     }
 
@@ -164,6 +185,19 @@
 
     public final void permits(String algorithm, ConstraintsParameters cp)
             throws CertPathValidatorException {
+
+        // Check if named curves in the ConstraintParameters are disabled.
+        if (cp.getNamedCurve() != null) {
+            for (String curve : cp.getNamedCurve()) {
+                if (!checkAlgorithm(disabledAlgorithms, curve, decomposer)) {
+                    throw new CertPathValidatorException(
+                            "Algorithm constraints check failed on disabled " +
+                                    "algorithm: " + curve,
+                            null, null, -1, BasicReason.ALGORITHM_CONSTRAINED);
+                }
+            }
+        }
+
         algorithmConstraints.permits(algorithm, cp);
     }
 
@@ -199,6 +233,13 @@
             return false;
         }
 
+        // If this is an elliptic curve, check disabled the named curve.
+        for (String curve : ConstraintsParameters.getNamedCurveFromKey(key)) {
+            if (!permits(primitives, curve, null)) {
+                return false;
+            }
+        }
+
         // check the key constraints
         return algorithmConstraints.permits(key);
     }
@@ -230,7 +271,7 @@
                     "denyAfter\\s+(\\d{4})-(\\d{2})-(\\d{2})");
         }
 
-        public Constraints(String[] constraintArray) {
+        public Constraints(List<String> constraintArray) {
             for (String constraintEntry : constraintArray) {
                 if (constraintEntry == null || constraintEntry.isEmpty()) {
                     continue;
@@ -257,7 +298,9 @@
                     constraintsMap.putIfAbsent(alias, constraintList);
                 }
 
-                if (space <= 0) {
+                // If there is no whitespace, it is a algorithm name; however,
+                // if there is a whitespace, could be a multi-word EC curve too.
+                if (space <= 0 || CurveDB.lookup(constraintEntry) != null) {
                     constraintList.add(new DisabledConstraint(algorithm));
                     continue;
                 }
@@ -356,7 +399,7 @@
             for (Constraint constraint : list) {
                 if (!constraint.permits(key)) {
                     if (debug != null) {
-                        debug.println("keySizeConstraint: failed key " +
+                        debug.println("Constraints: failed key size" +
                                 "constraint check " + KeyUtil.getKeySize(key));
                     }
                     return false;
@@ -375,7 +418,7 @@
             for (Constraint constraint : list) {
                 if (!constraint.permits(aps)) {
                     if (debug != null) {
-                        debug.println("keySizeConstraint: failed algorithm " +
+                        debug.println("Constraints: failed algorithm " +
                                 "parameters constraint check " + aps);
                     }
 
@@ -392,8 +435,7 @@
             X509Certificate cert = cp.getCertificate();
 
             if (debug != null) {
-                debug.println("Constraints.permits(): " + algorithm +
-                        " Variant: " + cp.getVariant());
+                debug.println("Constraints.permits(): " + cp.toString());
             }
 
             // Get all signature algorithms to check for constraints
@@ -406,8 +448,8 @@
             if (cert != null) {
                 algorithms.add(cert.getPublicKey().getAlgorithm());
             }
-            if (cp.getPublicKey() != null) {
-                algorithms.add(cp.getPublicKey().getAlgorithm());
+            if (cp.getKey() != null) {
+                algorithms.add(cp.getKey().getAlgorithm());
             }
             // Check all applicable constraints
             for (String alg : algorithms) {
@@ -546,10 +588,7 @@
          * the constraint denies the operation.
          */
         boolean next(Key key) {
-            if (nextConstraint != null && nextConstraint.permits(key)) {
-                return true;
-            }
-            return false;
+            return nextConstraint != null && nextConstraint.permits(key);
         }
 
         String extendedMsg(ConstraintsParameters cp) {
@@ -799,8 +838,8 @@
         public void permits(ConstraintsParameters cp)
                 throws CertPathValidatorException {
             Key key = null;
-            if (cp.getPublicKey() != null) {
-                key = cp.getPublicKey();
+            if (cp.getKey() != null) {
+                key = cp.getKey();
             } else if (cp.getCertificate() != null) {
                 key = cp.getCertificate().getPublicKey();
             }
--- a/src/java.base/share/classes/sun/security/util/LegacyAlgorithmConstraints.java	Wed Dec 18 12:14:01 2019 -0800
+++ b/src/java.base/share/classes/sun/security/util/LegacyAlgorithmConstraints.java	Wed Dec 18 23:46:55 2019 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -28,8 +28,8 @@
 import java.security.AlgorithmParameters;
 import java.security.CryptoPrimitive;
 import java.security.Key;
+import java.util.List;
 import java.util.Set;
-import static sun.security.util.AbstractAlgorithmConstraints.getAlgorithms;
 
 /**
  * Algorithm constraints for legacy algorithms.
@@ -40,7 +40,7 @@
     public static final String PROPERTY_TLS_LEGACY_ALGS =
             "jdk.tls.legacyAlgorithms";
 
-    private final String[] legacyAlgorithms;
+    private final List<String> legacyAlgorithms;
 
     public LegacyAlgorithmConstraints(String propertyName,
             AlgorithmDecomposer decomposer) {
--- a/src/java.base/share/conf/security/java.security	Wed Dec 18 12:14:01 2019 -0800
+++ b/src/java.base/share/conf/security/java.security	Wed Dec 18 23:46:55 2019 +0100
@@ -502,6 +502,22 @@
 sun.security.krb5.maxReferrals=5
 
 #
+# This property contains a list of disabled EC Named Curves that can be included
+# in the jdk.[tls|certpath|jar].disabledAlgorithms properties.  To include this
+# list in any of the disabledAlgorithms properties, add the property name as
+# an entry.
+jdk.disabled.namedCurves = secp112r1, secp112r2, secp128r1, secp128r2, \
+    secp160k1, secp160r1, secp160r2, secp192k1, secp192r1, secp224k1, \
+    secp224r1, secp256k1, sect113r1, sect113r2, sect131r1, sect131r2, \
+    sect163k1, sect163r1, sect163r2, sect193r1, sect193r2, sect233k1, \
+    sect233r1, sect239k1, sect283k1, sect283r1, sect409k1, sect409r1, \
+    sect571k1, sect571r1, X9.62 c2tnb191v1, X9.62 c2tnb191v2, \
+    X9.62 c2tnb191v3, X9.62 c2tnb239v1, X9.62 c2tnb239v2, X9.62 c2tnb239v3, \
+    X9.62 c2tnb359v1, X9.62 c2tnb431r1, X9.62 prime192v2, X9.62 prime192v3, \
+    X9.62 prime239v1, X9.62 prime239v2, X9.62 prime239v3, brainpoolP256r1, \
+    brainpoolP320r1, brainpoolP384r1, brainpoolP512r1
+
+#
 # Algorithm restrictions for certification path (CertPath) processing
 #
 # In some environments, certain algorithms or key lengths may be undesirable
@@ -515,7 +531,7 @@
 #       " DisabledAlgorithm { , DisabledAlgorithm } "
 #
 #   DisabledAlgorithm:
-#       AlgorithmName [Constraint] { '&' Constraint }
+#       AlgorithmName [Constraint] { '&' Constraint } | IncludeProperty
 #
 #   AlgorithmName:
 #       (see below)
@@ -542,6 +558,9 @@
 #   UsageConstraint:
 #       usage [TLSServer] [TLSClient] [SignedJAR]
 #
+#   IncludeProperty:
+#       include <security property>
+#
 # The "AlgorithmName" is the standard algorithm name of the disabled
 # algorithm. See the Java Security Standard Algorithm Names Specification
 # for information about Standard Algorithm Names.  Matching is
@@ -554,6 +573,14 @@
 # that rely on DSA, such as NONEwithDSA, SHA1withDSA.  However, the assertion
 # will not disable algorithms related to "ECDSA".
 #
+# The "IncludeProperty" allows a implementation-defined security property that
+# can be included in the disabledAlgorithms properties.  These properties are
+# to help manage common actions easier across multiple disabledAlgorithm
+# properties.
+# There is one defined security property:  jdk.disabled.NamedCurves
+# See the property for more specific details.
+#
+#
 # A "Constraint" defines restrictions on the keys and/or certificates for
 # a specified AlgorithmName:
 #
@@ -626,7 +653,8 @@
 #
 #
 jdk.certpath.disabledAlgorithms=MD2, MD5, SHA1 jdkCA & usage TLSServer, \
-    RSA keySize < 1024, DSA keySize < 1024, EC keySize < 224
+    RSA keySize < 1024, DSA keySize < 1024, EC keySize < 224, \
+    include jdk.disabled.namedCurves
 
 #
 # Algorithm restrictions for signed JAR files
@@ -670,7 +698,7 @@
 # See "jdk.certpath.disabledAlgorithms" for syntax descriptions.
 #
 jdk.jar.disabledAlgorithms=MD2, MD5, RSA keySize < 1024, \
-      DSA keySize < 1024
+      DSA keySize < 1024, include jdk.disabled.namedCurves
 
 #
 # Algorithm restrictions for Secure Socket Layer/Transport Layer Security
@@ -705,7 +733,8 @@
 #   jdk.tls.disabledAlgorithms=MD5, SSLv3, DSA, RSA keySize < 2048, \
 #       rsa_pkcs1_sha1, secp224r1
 jdk.tls.disabledAlgorithms=SSLv3, RC4, DES, MD5withRSA, DH keySize < 1024, \
-    EC keySize < 224, 3DES_EDE_CBC, anon, NULL
+    EC keySize < 224, 3DES_EDE_CBC, anon, NULL, \
+    include jdk.disabled.namedCurves
 
 #
 # Legacy algorithms for Secure Socket Layer/Transport Layer Security (SSL/TLS)
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/CommandProcessor.java	Wed Dec 18 12:14:01 2019 -0800
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/CommandProcessor.java	Wed Dec 18 23:46:55 2019 +0100
@@ -1731,6 +1731,8 @@
 
     // called after debuggee attach
     private void postAttach() {
+        /*
+         * JavaScript engine no longer works. For now disable it. Eventually we will remove it.
         // create JavaScript engine and start it
         try {
             jsengine = new JSJavaScriptEngine() {
@@ -1774,6 +1776,7 @@
                 ex.printStackTrace(out);
             }
         }
+        */
     }
 
     public void registerCommand(String cmd, String usage, final String func) {
--- a/test/hotspot/jtreg/ProblemList.txt	Wed Dec 18 12:14:01 2019 -0800
+++ b/test/hotspot/jtreg/ProblemList.txt	Wed Dec 18 23:46:55 2019 +0100
@@ -115,7 +115,7 @@
 serviceability/sa/ClhsdbPrintStatics.java 8193639 solaris-all
 serviceability/sa/ClhsdbPstack.java 8193639 solaris-all
 serviceability/sa/ClhsdbRegionDetailsScanOopsForG1.java 8193639 solaris-all
-serviceability/sa/ClhsdbScanOops.java 8193639 solaris-all
+serviceability/sa/ClhsdbScanOops.java 8193639,8235220,8230731 solaris-all,linux-x64,macosx-x64,windows-x64
 serviceability/sa/ClhsdbSource.java 8193639 solaris-all
 serviceability/sa/ClhsdbThread.java 8193639 solaris-all
 serviceability/sa/ClhsdbVmStructsDump.java 8193639 solaris-all
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/compiler/loopopts/TestIrreducibleLoopWithVNNI.java	Wed Dec 18 23:46:55 2019 +0100
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8230185
+ * @summary assert(is_Loop()) failed: invalid node class, during OSR compilation
+ * for VNNI pattern match.
+ *
+ * @run main/othervm -Xcomp
+ *      -XX:CompileCommand=compileonly,compiler.loopopts.TestIrreducibleLoopWithVNNI::*
+ *      compiler.loopopts.TestIrreducibleLoopWithVNNI
+ */
+
+package compiler.loopopts;
+
+public class TestIrreducibleLoopWithVNNI {
+    public static boolean condition = false;
+
+    public static void main(String[] strArr) {
+        TestIrreducibleLoopWithVNNI _instance = new TestIrreducibleLoopWithVNNI();
+        for (int i = 0; i < 10; i++) {
+            _instance.mainTest();
+        }
+    }
+
+    public void mainTest() {
+        int a = 1, b = 1, c = 1, d = 51;
+        for (b = 0; b < 100; b++) {
+            a = a + b * 342;
+            for (c = 0; c < 100; c++) {
+                for (d = 0; d < 1; d++)
+                    a = d;
+                if (condition)
+                    break;
+            }
+            a = d * a;
+        }
+    }
+}
--- a/test/hotspot/jtreg/serviceability/jvmti/CompiledMethodLoad/Zombie.java	Wed Dec 18 12:14:01 2019 -0800
+++ b/test/hotspot/jtreg/serviceability/jvmti/CompiledMethodLoad/Zombie.java	Wed Dec 18 23:46:55 2019 +0100
@@ -26,9 +26,9 @@
  * @bug 8212159
  * @summary Generate compiled method load events without crashing
  * @run main/othervm/native -agentlib:CompiledZombie -Xcomp -XX:ReservedCodeCacheSize=20m Zombie
- *
- * The stress test that made this fail was -jar SwingSet2.jar from demos (without DISPLAY set so it exits)
- */
+ **/
+
+ // The stress test that made this fail was -jar SwingSet2.jar from demos (without DISPLAY set so it exits)
 
 public class Zombie {
     public static void main(java.lang.String[] unused) {
--- a/test/hotspot/jtreg/serviceability/sa/ClhsdbLauncher.java	Wed Dec 18 12:14:01 2019 -0800
+++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbLauncher.java	Wed Dec 18 23:46:55 2019 +0100
@@ -71,7 +71,6 @@
             cmdStringList = SATestUtils.addPrivileges(cmdStringList);
         }
         ProcessBuilder processBuilder = new ProcessBuilder(cmdStringList);
-        processBuilder.redirectError(ProcessBuilder.Redirect.INHERIT);
         toolProcess = processBuilder.start();
     }
 
@@ -91,8 +90,6 @@
                            " and exe " + JDKToolFinder.getTestJDKTool("java"));
 
         ProcessBuilder processBuilder = new ProcessBuilder(launcher.getCommand());
-        processBuilder.redirectError(ProcessBuilder.Redirect.INHERIT);
-
         toolProcess = processBuilder.start();
     }
 
@@ -116,6 +113,17 @@
             throw new RuntimeException("CLHSDB command must be provided\n");
         }
 
+        // Enable verbose exception tracing so we see the full exception backtrace
+        // when there is a failure. We need to insert this command into the start
+        // of the commands list. We can't just issue the "verbose true" command seperately
+        // because code below won't work correctly if all executed commands are
+        // not in the commands list. And since it's immutable, we need to allocate
+        // a mutable one.
+        List<String> savedCommands = commands;
+        commands = new java.util.LinkedList<String>();
+        commands.add("verbose true");
+        commands.addAll(savedCommands);
+
         try (OutputStream out = toolProcess.getOutputStream()) {
             for (String cmd : commands) {
                 out.write((cmd + "\n").getBytes());
@@ -134,8 +142,15 @@
 
         oa.shouldHaveExitValue(0);
         output = oa.getOutput();
+        System.out.println("Output: ");
         System.out.println(output);
 
+        // This will detect most SA failures, including during the attach.
+        oa.shouldNotMatch("^sun.jvm.hotspot.debugger.DebuggerException:.*$");
+        // This will detect unexpected exceptions, like NPEs and asserts, that are caught
+        // by sun.jvm.hotspot.CommandProcessor.
+        oa.shouldNotMatch("^Error: .*$");
+
         String[] parts = output.split("hsdb>");
         for (String cmd : commands) {
             int index = commands.indexOf(cmd) + 1;
--- a/test/jdk/TEST.groups	Wed Dec 18 12:14:01 2019 -0800
+++ b/test/jdk/TEST.groups	Wed Dec 18 23:46:55 2019 +0100
@@ -356,7 +356,6 @@
     java/beans
 
 jdk_swing = \
-    javax/accessibility \
     javax/swing \
     com/sun/java/swing
 
@@ -366,6 +365,10 @@
 jdk_imageio = \
     javax/imageio
 
+jdk_accessibility = \
+    javax/accessibility \
+    com/sun/java/accessibility
+
 jfc_demo = \
      demo/jfc
 
@@ -376,6 +379,7 @@
     :jdk_swing \
     :jdk_sound \
     :jdk_imageio \
+    :jdk_accessibility \
     :jfc_demo \
     :jdk_client_sanity