Merge JEP-349-branch
authormgronlun
Wed, 18 Sep 2019 11:32:34 +0200
branchJEP-349-branch
changeset 58204 5d1f1ff2ad55
parent 58201 2654d1b665bf (current diff)
parent 58203 dfd434203aa0 (diff)
child 58205 9a078d4cf8a4
Merge
src/hotspot/share/runtime/thread.cpp
src/hotspot/share/runtime/thread.hpp
--- a/make/autoconf/buildjdk-spec.gmk.in	Wed Sep 18 08:20:10 2019 +0200
+++ b/make/autoconf/buildjdk-spec.gmk.in	Wed Sep 18 11:32:34 2019 +0200
@@ -91,7 +91,7 @@
 # Save speed and disk space by not enabling debug symbols for the buildjdk
 ENABLE_DEBUG_SYMBOLS := false
 
-# Control wether Hotspot builds gtest tests
+# Control whether Hotspot builds gtest tests
 BUILD_GTEST := false
 
 JVM_VARIANTS := server
--- a/make/autoconf/spec.gmk.in	Wed Sep 18 08:20:10 2019 +0200
+++ b/make/autoconf/spec.gmk.in	Wed Sep 18 11:32:34 2019 +0200
@@ -286,7 +286,7 @@
 VALID_JVM_FEATURES := @VALID_JVM_FEATURES@
 VALID_JVM_VARIANTS := @VALID_JVM_VARIANTS@
 
-# Control wether Hotspot builds gtest tests
+# Control whether Hotspot builds gtest tests
 BUILD_GTEST := @BUILD_GTEST@
 
 # Allow overriding the default hotspot library path
--- a/src/hotspot/os/aix/libodm_aix.cpp	Wed Sep 18 08:20:10 2019 +0200
+++ b/src/hotspot/os/aix/libodm_aix.cpp	Wed Sep 18 11:32:34 2019 +0200
@@ -1,6 +1,6 @@
 /*
- * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2015, 2015 SAP SE. All rights reserved.
+ * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2019 SAP SE. 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
@@ -59,7 +59,7 @@
 void odmWrapper::clean_data() { if (_data) { free(_data); _data = NULL; } }
 
 
-int odmWrapper::class_offset(char *field, bool is_aix_5)
+int odmWrapper::class_offset(const char *field, bool is_aix_5)
 {
   assert(has_class(), "initialization");
   for (int i = 0; i < odm_class()->nelem; i++) {
--- a/src/hotspot/os/aix/libodm_aix.hpp	Wed Sep 18 08:20:10 2019 +0200
+++ b/src/hotspot/os/aix/libodm_aix.hpp	Wed Sep 18 11:32:34 2019 +0200
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2015, 2015 SAP SE. All rights reserved.
+ * Copyright (c) 2015, 2019 SAP SE. 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
@@ -68,13 +68,15 @@
 
  public:
   // Make sure everything gets initialized and cleaned up properly.
-  explicit odmWrapper(char* odm_class_name, char* odm_path = NULL) : _odm_class((CLASS_SYMBOL)-1),
+  explicit odmWrapper(const char* odm_class_name, const char* odm_path = NULL) : _odm_class((CLASS_SYMBOL)-1),
                                                                      _data(NULL), _initialized(false) {
     if (!odm_loaded()) { return; }
     _initialized = ((*_odm_initialize)() != -1);
     if (_initialized) {
-      if (odm_path) { (*_odm_set_path)(odm_path); }
-      _odm_class = (*_odm_mount_class)(odm_class_name);
+      // should we free what odm_set_path returns, man page suggests it
+      // see https://www.ibm.com/support/knowledgecenter/en/ssw_aix_71/o_bostechref/odm_set_path.html
+      if (odm_path) { (*_odm_set_path)((char*)odm_path); }
+      _odm_class = (*_odm_mount_class)((char*)odm_class_name);
     }
   }
   ~odmWrapper() {
@@ -83,12 +85,12 @@
 
   CLASS_SYMBOL odm_class() { return _odm_class; }
   bool has_class() { return odm_class() != (CLASS_SYMBOL)-1; }
-  int class_offset(char *field, bool is_aix_5);
+  int class_offset(const char *field, bool is_aix_5);
   char* data() { return _data; }
 
-  char* retrieve_obj(char* name = NULL) {
+  char* retrieve_obj(const char* name = NULL) {
     clean_data();
-    char *cnp = (char*)(void*)(*_odm_get_obj)(odm_class(), name, NULL, (name == NULL) ? ODM_NEXT : ODM_FIRST);
+    char *cnp = (char*)(void*)(*_odm_get_obj)(odm_class(), (char*) name, NULL, (name == NULL) ? ODM_NEXT : ODM_FIRST);
     if (cnp != (char*)-1) { _data = cnp; }
     return data();
   }
--- a/src/hotspot/os/aix/os_aix.cpp	Wed Sep 18 08:20:10 2019 +0200
+++ b/src/hotspot/os/aix/os_aix.cpp	Wed Sep 18 11:32:34 2019 +0200
@@ -4228,7 +4228,7 @@
 // Unlike system(), this function can be called from signal handler. It
 // doesn't block SIGINT et al.
 int os::fork_and_exec(char* cmd, bool use_vfork_if_available) {
-  char * argv[4] = {"sh", "-c", cmd, NULL};
+  char* argv[4] = { (char*)"sh", (char*)"-c", cmd, NULL};
 
   pid_t pid = fork();
 
--- a/src/hotspot/os/posix/os_posix.cpp	Wed Sep 18 08:20:10 2019 +0200
+++ b/src/hotspot/os/posix/os_posix.cpp	Wed Sep 18 11:32:34 2019 +0200
@@ -640,61 +640,6 @@
   return;
 }
 
-////////////////////////////////////////////////////////////////////////////////
-// interrupt support
-
-void os::interrupt(Thread* thread) {
-  debug_only(Thread::check_for_dangling_thread_pointer(thread);)
-  assert(thread->is_Java_thread(), "invariant");
-  JavaThread* jt = (JavaThread*) thread;
-  OSThread* osthread = thread->osthread();
-
-  if (!osthread->interrupted()) {
-    osthread->set_interrupted(true);
-    // More than one thread can get here with the same value of osthread,
-    // resulting in multiple notifications.  We do, however, want the store
-    // to interrupted() to be visible to other threads before we execute unpark().
-    OrderAccess::fence();
-    ParkEvent * const slp = jt->_SleepEvent ;
-    if (slp != NULL) slp->unpark() ;
-  }
-
-  // For JSR166. Unpark even if interrupt status already was set
-  jt->parker()->unpark();
-
-  ParkEvent * ev = thread->_ParkEvent ;
-  if (ev != NULL) ev->unpark() ;
-}
-
-bool os::is_interrupted(Thread* thread, bool clear_interrupted) {
-  debug_only(Thread::check_for_dangling_thread_pointer(thread);)
-
-  OSThread* osthread = thread->osthread();
-
-  bool interrupted = osthread->interrupted();
-
-  // NOTE that since there is no "lock" around the interrupt and
-  // is_interrupted operations, there is the possibility that the
-  // interrupted flag (in osThread) will be "false" but that the
-  // low-level events will be in the signaled state. This is
-  // intentional. The effect of this is that Object.wait() and
-  // LockSupport.park() will appear to have a spurious wakeup, which
-  // is allowed and not harmful, and the possibility is so rare that
-  // it is not worth the added complexity to add yet another lock.
-  // For the sleep event an explicit reset is performed on entry
-  // to JavaThread::sleep, so there is no early return. It has also been
-  // recommended not to put the interrupted flag into the "event"
-  // structure because it hides the issue.
-  if (interrupted && clear_interrupted) {
-    osthread->set_interrupted(false);
-    // consider thread->_SleepEvent->reset() ... optional optimization
-  }
-
-  return interrupted;
-}
-
-
-
 static const struct {
   int sig; const char* name;
 }
@@ -2107,7 +2052,7 @@
 
   // Optional optimization -- avoid state transitions if there's
   // an interrupt pending.
-  if (Thread::is_interrupted(thread, false)) {
+  if (jt->is_interrupted(false)) {
     return;
   }
 
@@ -2130,7 +2075,7 @@
 
   // Don't wait if cannot get lock since interference arises from
   // unparking. Also re-check interrupt before trying wait.
-  if (Thread::is_interrupted(thread, false) ||
+  if (jt->is_interrupted(false) ||
       pthread_mutex_trylock(_mutex) != 0) {
     return;
   }
--- a/src/hotspot/os/solaris/os_solaris.cpp	Wed Sep 18 08:20:10 2019 +0200
+++ b/src/hotspot/os/solaris/os_solaris.cpp	Wed Sep 18 11:32:34 2019 +0200
@@ -5063,7 +5063,7 @@
   Thread* thread = Thread::current();
   assert(thread->is_Java_thread(), "Must be JavaThread");
   JavaThread *jt = (JavaThread *)thread;
-  if (Thread::is_interrupted(thread, false)) {
+  if (jt->is_interrupted(false)) {
     return;
   }
 
@@ -5088,7 +5088,7 @@
 
   // Don't wait if cannot get lock since interference arises from
   // unblocking.  Also. check interrupt before trying wait
-  if (Thread::is_interrupted(thread, false) ||
+  if (jt->is_interrupted(false) ||
       os::Solaris::mutex_trylock(_mutex) != 0) {
     return;
   }
--- a/src/hotspot/os/windows/osThread_windows.cpp	Wed Sep 18 08:20:10 2019 +0200
+++ b/src/hotspot/os/windows/osThread_windows.cpp	Wed Sep 18 11:32:34 2019 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 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
@@ -23,12 +23,9 @@
  */
 
 // no precompiled headers
-#include "runtime/handles.inline.hpp"
-#include "runtime/mutexLocker.hpp"
+#include "runtime/orderAccess.hpp"
 #include "runtime/os.hpp"
 #include "runtime/osThread.hpp"
-#include "runtime/safepoint.hpp"
-#include "runtime/vmThread.hpp"
 
 void OSThread::pd_initialize() {
   set_thread_handle(NULL);
@@ -36,8 +33,34 @@
   set_interrupt_event(NULL);
 }
 
-// TODO: this is not well encapsulated; creation and deletion of the
-// interrupt_event are done in os_win32.cpp, create_thread and
-// free_thread. Should follow pattern of Linux/Solaris code here.
 void OSThread::pd_destroy() {
+  if (_interrupt_event != NULL) {
+    CloseHandle(_interrupt_event);
+  }
 }
+
+// We need to specialize these to interact with the _interrupt_event.
+
+volatile bool OSThread::interrupted() {
+  return _interrupted != 0 &&
+    (WaitForSingleObject(_interrupt_event, 0) == WAIT_OBJECT_0);
+}
+
+void OSThread::set_interrupted(bool z) {
+  if (z) {
+    _interrupted = 1;
+    // More than one thread can get here with the same value of osthread,
+    // resulting in multiple notifications.  We do, however, want the store
+    // to interrupted() to be visible to other threads before we post
+    // the interrupt event.
+    OrderAccess::release();
+    SetEvent(_interrupt_event);
+  }
+  else {
+    // We should only ever clear the interrupt if we are in fact interrupted,
+    // and this can only be done by the current thread on itself.
+    assert(_interrupted == 1, "invariant for clearing interrupt state");
+    _interrupted = 0;
+    ResetEvent(_interrupt_event);
+  }
+}
--- a/src/hotspot/os/windows/osThread_windows.hpp	Wed Sep 18 08:20:10 2019 +0200
+++ b/src/hotspot/os/windows/osThread_windows.hpp	Wed Sep 18 11:32:34 2019 +0200
@@ -32,7 +32,8 @@
  private:
   // Win32-specific thread information
   HANDLE _thread_handle;        // Win32 thread handle
-  HANDLE _interrupt_event;      // Event signalled on thread interrupt
+  HANDLE _interrupt_event;      // Event signalled on thread interrupt for use by
+                                // Process.waitFor().
   ThreadState _last_state;
 
  public:
@@ -42,6 +43,11 @@
   void set_thread_handle(HANDLE handle)            { _thread_handle = handle; }
   HANDLE interrupt_event() const                   { return _interrupt_event; }
   void set_interrupt_event(HANDLE interrupt_event) { _interrupt_event = interrupt_event; }
+  // These are specialized on Windows to interact with the _interrupt_event.
+  // Also note that Windows does not skip these calls if we are interrupted - see
+  // LibraryCallKit::inline_native_isInterrupted
+  volatile bool interrupted();
+  void set_interrupted(bool z);
 
 #ifndef PRODUCT
   // Used for debugging, return a unique integer for each thread.
@@ -54,7 +60,6 @@
     return false;
   }
 #endif // ASSERT
-  bool is_try_mutex_enter()                        { return false; }
 
   // This is a temporary fix for the thread states during
   // suspend/resume until we throw away OSThread completely.
--- a/src/hotspot/os/windows/os_windows.cpp	Wed Sep 18 08:20:10 2019 +0200
+++ b/src/hotspot/os/windows/os_windows.cpp	Wed Sep 18 11:32:34 2019 +0200
@@ -612,7 +612,9 @@
     return false;
   }
   osthread->set_interrupt_event(interrupt_event);
-  osthread->set_interrupted(false);
+  // We don't call set_interrupted(false) as it will trip the assert in there
+  // as we are not operating on the current thread. We don't need to call it
+  // because the initial state is already correct.
 
   thread->set_osthread(osthread);
 
@@ -684,7 +686,6 @@
 
   if (thread_handle == NULL) {
     // Need to clean up stuff we've allocated so far
-    CloseHandle(osthread->interrupt_event());
     thread->set_osthread(NULL);
     delete osthread;
     return false;
@@ -714,7 +715,6 @@
          "os::free_thread but not current thread");
 
   CloseHandle(osthread->thread_handle());
-  CloseHandle(osthread->interrupt_event());
   delete osthread;
 }
 
@@ -3485,7 +3485,6 @@
 }
 
 
-
 // Short sleep, direct OS call.
 //
 // ms = 0, means allow others (if any) to run.
@@ -3593,49 +3592,6 @@
   return OS_OK;
 }
 
-void os::interrupt(Thread* thread) {
-  debug_only(Thread::check_for_dangling_thread_pointer(thread);)
-  assert(thread->is_Java_thread(), "invariant");
-  JavaThread* jt = (JavaThread*) thread;
-  OSThread* osthread = thread->osthread();
-  osthread->set_interrupted(true);
-  // More than one thread can get here with the same value of osthread,
-  // resulting in multiple notifications.  We do, however, want the store
-  // to interrupted() to be visible to other threads before we post
-  // the interrupt event.
-  OrderAccess::release();
-  SetEvent(osthread->interrupt_event());
-  // For JSR166:  unpark after setting status
-  jt->parker()->unpark();
-
-  ParkEvent * ev = thread->_ParkEvent;
-  if (ev != NULL) ev->unpark();
-
-  ev = jt->_SleepEvent;
-  if (ev != NULL) ev->unpark();
-}
-
-
-bool os::is_interrupted(Thread* thread, bool clear_interrupted) {
-  debug_only(Thread::check_for_dangling_thread_pointer(thread);)
-
-  OSThread* osthread = thread->osthread();
-  // There is no synchronization between the setting of the interrupt
-  // and it being cleared here. It is critical - see 6535709 - that
-  // we only clear the interrupt state, and reset the interrupt event,
-  // if we are going to report that we were indeed interrupted - else
-  // an interrupt can be "lost", leading to spurious wakeups or lost wakeups
-  // depending on the timing. By checking thread interrupt event to see
-  // if the thread gets real interrupt thus prevent spurious wakeup.
-  bool interrupted = osthread->interrupted() && (WaitForSingleObject(osthread->interrupt_event(), 0) == WAIT_OBJECT_0);
-  if (interrupted && clear_interrupted) {
-    osthread->set_interrupted(false);
-    ResetEvent(osthread->interrupt_event());
-  } // Otherwise leave the interrupted state alone
-
-  return interrupted;
-}
-
 // GetCurrentThreadId() returns DWORD
 intx os::current_thread_id()  { return GetCurrentThreadId(); }
 
@@ -5346,7 +5302,7 @@
   JavaThread* thread = JavaThread::current();
 
   // Don't wait if interrupted or already triggered
-  if (Thread::is_interrupted(thread, false) ||
+  if (thread->is_interrupted(false) ||
       WaitForSingleObject(_ParkEvent, 0) == WAIT_OBJECT_0) {
     ResetEvent(_ParkEvent);
     return;
--- a/src/hotspot/share/compiler/compileBroker.cpp	Wed Sep 18 08:20:10 2019 +0200
+++ b/src/hotspot/share/compiler/compileBroker.cpp	Wed Sep 18 11:32:34 2019 +0200
@@ -557,8 +557,14 @@
 }
 
 void CompileQueue::print_tty() {
-  ttyLocker ttyl;
-  print(tty);
+  ResourceMark rm;
+  stringStream ss;
+  // Dump the compile queue into a buffer before locking the tty
+  print(&ss);
+  {
+    ttyLocker ttyl;
+    tty->print("%s", ss.as_string());
+  }
 }
 
 CompilerCounters::CompilerCounters() {
--- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp	Wed Sep 18 08:20:10 2019 +0200
+++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp	Wed Sep 18 11:32:34 2019 +0200
@@ -1920,7 +1920,7 @@
     else if (prev == CANCELLED) return false;
     assert(ShenandoahSuspendibleWorkers, "should not get here when not using suspendible workers");
     assert(prev == NOT_CANCELLED, "must be NOT_CANCELLED");
-    {
+    if (Thread::current()->is_Java_thread()) {
       // We need to provide a safepoint here, otherwise we might
       // spin forever if a SP is pending.
       ThreadBlockInVM sp(JavaThread::current());
--- a/src/hotspot/share/jvmci/jvmciRuntime.cpp	Wed Sep 18 08:20:10 2019 +0200
+++ b/src/hotspot/share/jvmci/jvmciRuntime.cpp	Wed Sep 18 11:32:34 2019 +0200
@@ -631,7 +631,7 @@
     // The other thread may exit during this process, which is ok so return false.
     return JNI_FALSE;
   } else {
-    return (jint) Thread::is_interrupted(receiverThread, clear_interrupted != 0);
+    return (jint) receiverThread->is_interrupted(clear_interrupted != 0);
   }
 JRT_END
 
--- a/src/hotspot/share/opto/block.hpp	Wed Sep 18 08:20:10 2019 +0200
+++ b/src/hotspot/share/opto/block.hpp	Wed Sep 18 11:32:34 2019 +0200
@@ -317,7 +317,7 @@
   uint find_node( const Node *n ) const;
   // Find and remove n from block list
   void find_remove( const Node *n );
-  // Check wether the node is in the block.
+  // Check whether the node is in the block.
   bool contains (const Node *n) const;
 
   // Return the empty status of a block
--- a/src/hotspot/share/prims/jvm.cpp	Wed Sep 18 08:20:10 2019 +0200
+++ b/src/hotspot/share/prims/jvm.cpp	Wed Sep 18 11:32:34 2019 +0200
@@ -2974,7 +2974,7 @@
     THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "timeout value is negative");
   }
 
-  if (Thread::is_interrupted (THREAD, true) && !HAS_PENDING_EXCEPTION) {
+  if (thread->is_interrupted(true) && !HAS_PENDING_EXCEPTION) {
     THROW_MSG(vmSymbols::java_lang_InterruptedException(), "sleep interrupted");
   }
 
@@ -3071,7 +3071,7 @@
   bool is_alive = tlh.cv_internal_thread_to_JavaThread(jthread, &receiver, NULL);
   if (is_alive) {
     // jthread refers to a live JavaThread.
-    Thread::interrupt(receiver);
+    receiver->interrupt();
   }
 JVM_END
 
@@ -3084,7 +3084,7 @@
   bool is_alive = tlh.cv_internal_thread_to_JavaThread(jthread, &receiver, NULL);
   if (is_alive) {
     // jthread refers to a live JavaThread.
-    return (jboolean) Thread::is_interrupted(receiver, clear_interrupted != 0);
+    return (jboolean) receiver->is_interrupted(clear_interrupted != 0);
   } else {
     return JNI_FALSE;
   }
--- a/src/hotspot/share/prims/jvmtiEnv.cpp	Wed Sep 18 08:20:10 2019 +0200
+++ b/src/hotspot/share/prims/jvmtiEnv.cpp	Wed Sep 18 11:32:34 2019 +0200
@@ -1101,7 +1101,7 @@
     return err;
   }
 
-  Thread::interrupt(java_thread);
+  java_thread->interrupt();
 
   return JVMTI_ERROR_NONE;
 } /* end InterruptThread */
--- a/src/hotspot/share/prims/jvmtiRawMonitor.cpp	Wed Sep 18 08:20:10 2019 +0200
+++ b/src/hotspot/share/prims/jvmtiRawMonitor.cpp	Wed Sep 18 11:32:34 2019 +0200
@@ -373,8 +373,12 @@
   OrderAccess::fence() ;
 
   // check interrupt event
-  if (interruptible && Thread::is_interrupted(THREAD, true)) {
-    return OM_INTERRUPTED;
+  if (interruptible) {
+    assert(THREAD->is_Java_thread(), "Only JavaThreads can be interruptible");
+    JavaThread* jt = (JavaThread*) THREAD;
+    if (jt->is_interrupted(true)) {
+      return OM_INTERRUPTED;
+    }
   }
 
   intptr_t save = _recursions ;
@@ -401,8 +405,11 @@
   }
   guarantee (THREAD == _owner, "invariant") ;
 
-  if (interruptible && Thread::is_interrupted(THREAD, true)) {
-    return OM_INTERRUPTED;
+  if (interruptible) {
+    JavaThread* jt = (JavaThread*) THREAD;
+    if (jt->is_interrupted(true)) {
+      return OM_INTERRUPTED;
+    }
   }
   return OM_OK ;
 }
--- a/src/hotspot/share/runtime/objectMonitor.cpp	Wed Sep 18 08:20:10 2019 +0200
+++ b/src/hotspot/share/runtime/objectMonitor.cpp	Wed Sep 18 11:32:34 2019 +0200
@@ -1205,7 +1205,7 @@
   EventJavaMonitorWait event;
 
   // check for a pending interrupt
-  if (interruptible && Thread::is_interrupted(Self, true) && !HAS_PENDING_EXCEPTION) {
+  if (interruptible && jt->is_interrupted(true) && !HAS_PENDING_EXCEPTION) {
     // post monitor waited event.  Note that this is past-tense, we are done waiting.
     if (JvmtiExport::should_post_monitor_waited()) {
       // Note: 'false' parameter is passed here because the
@@ -1275,7 +1275,7 @@
       // Thread is in thread_blocked state and oop access is unsafe.
       jt->set_suspend_equivalent();
 
-      if (interruptible && (Thread::is_interrupted(THREAD, false) || HAS_PENDING_EXCEPTION)) {
+      if (interruptible && (jt->is_interrupted(false) || HAS_PENDING_EXCEPTION)) {
         // Intentionally empty
       } else if (node._notified == 0) {
         if (millis <= 0) {
@@ -1401,7 +1401,7 @@
   if (!WasNotified) {
     // no, it could be timeout or Thread.interrupt() or both
     // check for interrupt event, otherwise it is timeout
-    if (interruptible && Thread::is_interrupted(Self, true) && !HAS_PENDING_EXCEPTION) {
+    if (interruptible && jt->is_interrupted(true) && !HAS_PENDING_EXCEPTION) {
       THROW(vmSymbols::java_lang_InterruptedException());
     }
   }
--- a/src/hotspot/share/runtime/os.hpp	Wed Sep 18 08:20:10 2019 +0200
+++ b/src/hotspot/share/runtime/os.hpp	Wed Sep 18 11:32:34 2019 +0200
@@ -480,9 +480,6 @@
   static OSReturn set_priority(Thread* thread, ThreadPriority priority);
   static OSReturn get_priority(const Thread* const thread, ThreadPriority& priority);
 
-  static void interrupt(Thread* thread);
-  static bool is_interrupted(Thread* thread, bool clear_interrupted);
-
   static int pd_self_suspend_thread(Thread* thread);
 
   static ExtendedPC fetch_frame_from_context(const void* ucVoid, intptr_t** sp, intptr_t** fp);
--- a/src/hotspot/share/runtime/osThread.cpp	Wed Sep 18 08:20:10 2019 +0200
+++ b/src/hotspot/share/runtime/osThread.cpp	Wed Sep 18 11:32:34 2019 +0200
@@ -30,7 +30,7 @@
   pd_initialize();
   set_start_proc(start_proc);
   set_start_parm(start_parm);
-  set_interrupted(false);
+  _interrupted = 0;
 }
 
 OSThread::~OSThread() {
--- a/src/hotspot/share/runtime/osThread.hpp	Wed Sep 18 08:20:10 2019 +0200
+++ b/src/hotspot/share/runtime/osThread.hpp	Wed Sep 18 11:32:34 2019 +0200
@@ -82,10 +82,11 @@
   void set_start_proc(OSThreadStartFunc start_proc) { _start_proc = start_proc; }
   void* start_parm() const                          { return _start_parm; }
   void set_start_parm(void* start_parm)             { _start_parm = start_parm; }
-
+  // These are specialized on Windows.
+#ifndef _WINDOWS
   volatile bool interrupted() const                 { return _interrupted != 0; }
   void set_interrupted(bool z)                      { _interrupted = z ? 1 : 0; }
-
+#endif
   // Printing
   void print_on(outputStream* st) const;
   void print() const;
--- a/src/hotspot/share/runtime/thread.cpp	Wed Sep 18 08:20:10 2019 +0200
+++ b/src/hotspot/share/runtime/thread.cpp	Wed Sep 18 11:32:34 2019 +0200
@@ -856,19 +856,6 @@
   return true;
 }
 
-void Thread::interrupt(Thread* thread) {
-  debug_only(check_for_dangling_thread_pointer(thread);)
-  os::interrupt(thread);
-}
-
-bool Thread::is_interrupted(Thread* thread, bool clear_interrupted) {
-  debug_only(check_for_dangling_thread_pointer(thread);)
-  // Note:  If clear_interrupted==false, this simply fetches and
-  // returns the value of the field osthread()->interrupted().
-  return os::is_interrupted(thread, clear_interrupted);
-}
-
-
 // GC Support
 bool Thread::claim_par_threads_do(uintx claim_token) {
   uintx token = _threads_do_token;
@@ -1726,6 +1713,56 @@
   assert(deferred_card_mark().is_empty(), "Default MemRegion ctor");
 }
 
+
+// interrupt support
+
+void JavaThread::interrupt() {
+  debug_only(check_for_dangling_thread_pointer(this);)
+
+  if (!osthread()->interrupted()) {
+    osthread()->set_interrupted(true);
+    // More than one thread can get here with the same value of osthread,
+    // resulting in multiple notifications.  We do, however, want the store
+    // to interrupted() to be visible to other threads before we execute unpark().
+    OrderAccess::fence();
+
+    // For JavaThread::sleep. Historically we only unpark if changing to the interrupted
+    // state, in contrast to the other events below. Not clear exactly why.
+    _SleepEvent->unpark();
+  }
+
+  // For JSR166. Unpark even if interrupt status already was set.
+  parker()->unpark();
+
+  // For ObjectMonitor and JvmtiRawMonitor
+  _ParkEvent->unpark();
+}
+
+
+bool JavaThread::is_interrupted(bool clear_interrupted) {
+  debug_only(check_for_dangling_thread_pointer(this);)
+  bool interrupted = osthread()->interrupted();
+
+  // NOTE that since there is no "lock" around the interrupt and
+  // is_interrupted operations, there is the possibility that the
+  // interrupted flag (in osThread) will be "false" but that the
+  // low-level events will be in the signaled state. This is
+  // intentional. The effect of this is that Object.wait() and
+  // LockSupport.park() will appear to have a spurious wakeup, which
+  // is allowed and not harmful, and the possibility is so rare that
+  // it is not worth the added complexity to add yet another lock.
+  // For the sleep event an explicit reset is performed on entry
+  // to JavaThread::sleep, so there is no early return. It has also been
+  // recommended not to put the interrupted flag into the "event"
+  // structure because it hides the issue.
+  if (interrupted && clear_interrupted) {
+    osthread()->set_interrupted(false);
+    // consider thread->_SleepEvent->reset() ... optional optimization
+  }
+
+  return interrupted;
+}
+
 bool JavaThread::reguard_stack(address cur_sp) {
   if (_stack_guard_state != stack_guard_yellow_reserved_disabled
       && _stack_guard_state != stack_guard_reserved_disabled) {
@@ -2370,8 +2407,8 @@
   }
 
 
-  // Interrupt thread so it will wake up from a potential wait()
-  Thread::interrupt(this);
+  // Interrupt thread so it will wake up from a potential wait()/sleep()/park()
+  this->interrupt();
 }
 
 // External suspension mechanism.
@@ -3361,7 +3398,7 @@
 
   for (;;) {
     // interruption has precedence over timing out
-    if (os::is_interrupted(this, true)) {
+    if (this->is_interrupted(true)) {
       return false;
     }
 
@@ -3389,7 +3426,7 @@
       // time moving backwards, should only happen if no monotonic clock
       // not a guarantee() because JVM should not abort on kernel/glibc bugs
       assert(!os::supports_monotonic_clock(),
-             "unexpected time moving backwards detected in os::sleep()");
+             "unexpected time moving backwards detected in JavaThread::sleep()");
     } else {
       millis -= (newtime - prevtime) / NANOSECS_PER_MILLISEC;
     }
--- a/src/hotspot/share/runtime/thread.hpp	Wed Sep 18 08:20:10 2019 +0200
+++ b/src/hotspot/share/runtime/thread.hpp	Wed Sep 18 11:32:34 2019 +0200
@@ -514,8 +514,6 @@
   static void set_priority(Thread* thread, ThreadPriority priority);
   static ThreadPriority get_priority(const Thread* const thread);
   static void start(Thread* thread);
-  static void interrupt(Thread* thr);
-  static bool is_interrupted(Thread* thr, bool clear_interrupted);
 
   void set_native_thread_name(const char *name) {
     assert(Thread::current() == this, "set_native_thread_name can only be called on the current thread");
@@ -2055,9 +2053,14 @@
   InstanceKlass* _class_to_be_initialized;
 
   // java.lang.Thread.sleep support
+  ParkEvent * _SleepEvent;
 public:
-  ParkEvent * _SleepEvent;
   bool sleep(jlong millis);
+
+  // java.lang.Thread interruption support
+  void interrupt();
+  bool is_interrupted(bool clear_interrupted);
+
 };
 
 // Inline implementation of JavaThread::current
--- a/src/hotspot/share/utilities/ostream.cpp	Wed Sep 18 08:20:10 2019 +0200
+++ b/src/hotspot/share/utilities/ostream.cpp	Wed Sep 18 11:32:34 2019 +0200
@@ -99,13 +99,14 @@
     result_len = strlen(result);
     if (add_cr && result_len >= buflen)  result_len = buflen-1;  // truncate
   } else {
-    int written = os::vsnprintf(buffer, buflen, format, ap);
-    assert(written >= 0, "vsnprintf encoding error");
+    int required_len = os::vsnprintf(buffer, buflen, format, ap);
+    assert(required_len >= 0, "vsnprintf encoding error");
     result = buffer;
-    if ((size_t)written < buflen) {
-      result_len = written;
+    if ((size_t)required_len < buflen) {
+      result_len = required_len;
     } else {
-      DEBUG_ONLY(warning("increase O_BUFLEN in ostream.hpp -- output truncated");)
+      DEBUG_ONLY(warning("outputStream::do_vsnprintf output truncated -- buffer length is %d bytes but %d bytes are needed.",
+                         add_cr ? (int)buflen + 1 : (int)buflen, add_cr ? required_len + 2 : required_len + 1);)
       result_len = buflen - 1;
     }
   }
--- a/src/java.base/aix/native/libjli/java_md_aix.c	Wed Sep 18 08:20:10 2019 +0200
+++ b/src/java.base/aix/native/libjli/java_md_aix.c	Wed Sep 18 11:32:34 2019 +0200
@@ -39,8 +39,7 @@
     memset((void *)info, 0, sizeof(Dl_info));
     for (;;) {
         if (addr >= p->ldinfo_textorg &&
-            addr < (((char*)p->ldinfo_textorg) + p->ldinfo_textsize))
-        {
+            addr < p->ldinfo_textorg + p->ldinfo_textsize) {
             info->dli_fname = p->ldinfo_filename;
             return 1;
         }
--- a/src/java.base/unix/native/libjava/TimeZone_md.c	Wed Sep 18 08:20:10 2019 +0200
+++ b/src/java.base/unix/native/libjava/TimeZone_md.c	Wed Sep 18 11:32:34 2019 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 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
@@ -42,6 +42,8 @@
 #include "jvm.h"
 #include "TimeZone_md.h"
 
+static char *isFileIdentical(char* buf, size_t size, char *pathname);
+
 #define SKIP_SPACE(p)   while (*p == ' ' || *p == '\t') p++;
 
 #define RESTARTABLE(_cmd, _result) do { \
@@ -72,6 +74,8 @@
 static const char *DEFAULT_ZONEINFO_FILE = "/usr/share/lib/zoneinfo/localtime";
 #endif /* defined(__linux__) || defined(_ALLBSD_SOURCE) */
 
+static const char popularZones[][4] = {"UTC", "GMT"};
+
 #if defined(_AIX)
 static const char *ETC_ENVIRONMENT_FILE = "/etc/environment";
 #endif
@@ -121,14 +125,27 @@
 findZoneinfoFile(char *buf, size_t size, const char *dir)
 {
     DIR *dirp = NULL;
-    struct stat64 statbuf;
     struct dirent *dp = NULL;
     char *pathname = NULL;
-    int fd = -1;
-    char *dbuf = NULL;
     char *tz = NULL;
     int res;
 
+    if (strcmp(dir, ZONEINFO_DIR) == 0) {
+        /* fast path for 1st iteration */
+        for (unsigned int i = 0; i < sizeof (popularZones) / sizeof (popularZones[0]); i++) {
+            pathname = getPathName(dir, popularZones[i]);
+            if (pathname == NULL) {
+                continue;
+            }
+            tz = isFileIdentical(buf, size, pathname);
+            free((void *) pathname);
+            pathname = NULL;
+            if (tz != NULL) {
+                return tz;
+            }
+        }
+    }
+
     dirp = opendir(dir);
     if (dirp == NULL) {
         return NULL;
@@ -162,58 +179,67 @@
         if (pathname == NULL) {
             break;
         }
-        RESTARTABLE(stat64(pathname, &statbuf), res);
-        if (res == -1) {
-            break;
-        }
 
-        if (S_ISDIR(statbuf.st_mode)) {
-            tz = findZoneinfoFile(buf, size, pathname);
-            if (tz != NULL) {
-                break;
-            }
-        } else if (S_ISREG(statbuf.st_mode) && (size_t)statbuf.st_size == size) {
-            dbuf = (char *) malloc(size);
-            if (dbuf == NULL) {
-                break;
-            }
-            RESTARTABLE(open(pathname, O_RDONLY), fd);
-            if (fd == -1) {
-                break;
-            }
-            RESTARTABLE(read(fd, dbuf, size), res);
-            if (res != (ssize_t) size) {
-                break;
-            }
-            if (memcmp(buf, dbuf, size) == 0) {
-                tz = getZoneName(pathname);
-                if (tz != NULL) {
-                    tz = strdup(tz);
-                }
-                break;
-            }
-            free((void *) dbuf);
-            dbuf = NULL;
-            (void) close(fd);
-            fd = -1;
-        }
+        tz = isFileIdentical(buf, size, pathname);
         free((void *) pathname);
         pathname = NULL;
+        if (tz != NULL) {
+           break;
+        }
     }
 
     if (dirp != NULL) {
         (void) closedir(dirp);
     }
-    if (pathname != NULL) {
-        free((void *) pathname);
+    return tz;
+}
+
+/*
+ * Checks if the file pointed to by pathname matches
+ * the data contents in buf.
+ * Returns a representation of the timezone file name
+ * if file match is found, otherwise NULL.
+ */
+static char *
+isFileIdentical(char *buf, size_t size, char *pathname)
+{
+    char *possibleMatch = NULL;
+    struct stat64 statbuf;
+    char *dbuf = NULL;
+    int fd = -1;
+    int res;
+
+    RESTARTABLE(stat64(pathname, &statbuf), res);
+    if (res == -1) {
+        return NULL;
     }
-    if (fd != -1) {
+
+    if (S_ISDIR(statbuf.st_mode)) {
+        possibleMatch  = findZoneinfoFile(buf, size, pathname);
+    } else if (S_ISREG(statbuf.st_mode) && (size_t)statbuf.st_size == size) {
+        dbuf = (char *) malloc(size);
+        if (dbuf == NULL) {
+            return NULL;
+        }
+        RESTARTABLE(open(pathname, O_RDONLY), fd);
+        if (fd == -1) {
+            goto freedata;
+        }
+        RESTARTABLE(read(fd, dbuf, size), res);
+        if (res != (ssize_t) size) {
+            goto freedata;
+        }
+        if (memcmp(buf, dbuf, size) == 0) {
+            possibleMatch = getZoneName(pathname);
+            if (possibleMatch != NULL) {
+                possibleMatch = strdup(possibleMatch);
+            }
+        }
+        freedata:
+        free((void *) dbuf);
         (void) close(fd);
     }
-    if (dbuf != NULL) {
-        free((void *) dbuf);
-    }
-    return tz;
+    return possibleMatch;
 }
 
 #if defined(__linux__) || defined(MACOSX)
--- a/src/java.base/unix/native/libnet/NetworkInterface.c	Wed Sep 18 08:20:10 2019 +0200
+++ b/src/java.base/unix/native/libnet/NetworkInterface.c	Wed Sep 18 11:32:34 2019 +0200
@@ -1394,6 +1394,10 @@
 /** AIX **/
 #if defined(_AIX)
 
+/* seems getkerninfo is guarded by _KERNEL in the system headers */
+/* see net/proto_uipc.h */
+int getkerninfo(int, char *, int *, int32long64_t);
+
 /*
  * Opens a socket for further ioctl calls. Tries AF_INET socket first and
  * if it fails return AF_INET6 socket.
@@ -1613,7 +1617,7 @@
         return -1;
     }
 
-    if (getkerninfo(KINFO_NDD, nddp, &size, 0) < 0) {
+    if (getkerninfo(KINFO_NDD, (char*) nddp, &size, 0) < 0) {
         perror("getkerninfo 2");
         free(nddp);
         return -1;
--- a/src/java.desktop/aix/native/libawt/porting_aix.c	Wed Sep 18 08:20:10 2019 +0200
+++ b/src/java.desktop/aix/native/libawt/porting_aix.c	Wed Sep 18 11:32:34 2019 +0200
@@ -43,11 +43,10 @@
 
 static int dladdr_dont_reload(void* addr, Dl_info* info) {
   const struct ld_info* p = (struct ld_info*) dladdr_buffer;
-  info->dli_fbase = 0; info->dli_fname = 0;
-  info->dli_sname = 0; info->dli_saddr = 0;
+  memset((void *)info, 0, sizeof(Dl_info));
   for (;;) {
     if (addr >= p->ldinfo_textorg &&
-        addr < (((char*)p->ldinfo_textorg) + p->ldinfo_textsize)) {
+        addr < p->ldinfo_textorg + p->ldinfo_textsize) {
       info->dli_fname = p->ldinfo_filename;
       info->dli_fbase = p->ldinfo_textorg;
       return 1; /* [sic] */
--- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLDocumentFragmentScannerImpl.java	Wed Sep 18 08:20:10 2019 +0200
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLDocumentFragmentScannerImpl.java	Wed Sep 18 11:32:34 2019 +0200
@@ -3026,7 +3026,7 @@
                                 return XMLEvent.ENTITY_REFERENCE;
                             }
                         }
-                        //Wether it was character reference, entity reference or built-in entity
+                        //Whether it was character reference, entity reference or built-in entity
                         //set the next possible state to SCANNER_STATE_CONTENT
                         setScannerState(SCANNER_STATE_CONTENT);
                         fLastSectionWasEntityReference = true ;
--- a/src/java.xml/share/classes/com/sun/xml/internal/stream/StaxXMLInputSource.java	Wed Sep 18 08:20:10 2019 +0200
+++ b/src/java.xml/share/classes/com/sun/xml/internal/stream/StaxXMLInputSource.java	Wed Sep 18 11:32:34 2019 +0200
@@ -33,7 +33,7 @@
  *
  * @author  Neeraj
  *
- * This class wraps XMLInputSource and is also capable of telling wether application
+ * This class wraps XMLInputSource and is also capable of telling whether application
  * returned XMLStreamReader or not when XMLResolver.resolveEntity
  * was called.
  */
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/file/BaseFileManager.java	Wed Sep 18 08:20:10 2019 +0200
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/file/BaseFileManager.java	Wed Sep 18 11:32:34 2019 +0200
@@ -198,6 +198,10 @@
         return locations.isDefaultBootClassPath();
     }
 
+    public boolean isDefaultSystemModulesPath() {
+        return locations.isDefaultSystemModulesPath();
+    }
+
     // <editor-fold defaultstate="collapsed" desc="Option handling">
     @Override @DefinedBy(Api.COMPILER)
     public boolean handleOption(String current, Iterator<String> remaining) {
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/file/Locations.java	Wed Sep 18 08:20:10 2019 +0200
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/file/Locations.java	Wed Sep 18 11:32:34 2019 +0200
@@ -94,6 +94,7 @@
 import com.sun.tools.javac.util.Pair;
 import com.sun.tools.javac.util.StringUtils;
 
+import static javax.tools.StandardLocation.SYSTEM_MODULES;
 import static javax.tools.StandardLocation.PLATFORM_CLASS_PATH;
 
 import static com.sun.tools.javac.main.Option.BOOT_CLASS_PATH;
@@ -185,6 +186,12 @@
         return h.isDefault();
     }
 
+    boolean isDefaultSystemModulesPath() {
+        SystemModulesLocationHandler h
+                = (SystemModulesLocationHandler) getHandler(SYSTEM_MODULES);
+        return !h.isExplicit();
+    }
+
     /**
      * Split a search path into its elements. Empty path elements will be ignored.
      *
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Arguments.java	Wed Sep 18 08:20:10 2019 +0200
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Arguments.java	Wed Sep 18 11:32:34 2019 +0200
@@ -565,8 +565,13 @@
         boolean lintOptions = options.isUnset(Option.XLINT_CUSTOM, "-" + LintCategory.OPTIONS.option);
         if (lintOptions && source.compareTo(Source.DEFAULT) < 0 && !options.isSet(Option.RELEASE)) {
             if (fm instanceof BaseFileManager) {
-                if (((BaseFileManager) fm).isDefaultBootClassPath())
-                    log.warning(LintCategory.OPTIONS, Warnings.SourceNoBootclasspath(source.name));
+                if (source.compareTo(Source.JDK8) <= 0) {
+                    if (((BaseFileManager) fm).isDefaultBootClassPath())
+                        log.warning(LintCategory.OPTIONS, Warnings.SourceNoBootclasspath(source.name));
+                } else {
+                    if (((BaseFileManager) fm).isDefaultSystemModulesPath())
+                        log.warning(LintCategory.OPTIONS, Warnings.SourceNoSystemModulesPath(source.name));
+                }
             }
         }
 
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties	Wed Sep 18 08:20:10 2019 +0200
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties	Wed Sep 18 11:32:34 2019 +0200
@@ -1866,6 +1866,10 @@
     bootstrap class path not set in conjunction with -source {0}
 
 # 0: string
+compiler.warn.source.no.system.modules.path=\
+    system modules path not set in conjunction with -source {0}
+
+# 0: string
 compiler.warn.option.obsolete.source=\
     source value {0} is obsolete and will be removed in a future release
 
--- a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/doubleconv/BignumDtoa.java	Wed Sep 18 08:20:10 2019 +0200
+++ b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/doubleconv/BignumDtoa.java	Wed Sep 18 11:32:34 2019 +0200
@@ -280,7 +280,7 @@
 
     // Let v = numerator / denominator < 10.
     // Then we generate 'count' digits of d = x.xxxxx... (without the decimal point)
-    // from left to right. Once 'count' digits have been produced we decide wether
+    // from left to right. Once 'count' digits have been produced we decide whether
     // to round up or down. Remainders of exactly .5 round upwards. Numbers such
     // as 9.999999 propagate a carry all the way, and change the
     // exponent (decimal_point), when rounding upwards.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/compiler/print/PrintCompileQueue.java	Wed Sep 18 11:32:34 2019 +0200
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2019, Loongson Technology Co. Ltd. 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 8230943
+ * @summary possible deadlock was detected when ran with -XX:+CIPrintCompileQueue
+ * @run main/othervm -Xcomp -XX:+UnlockDiagnosticVMOptions -XX:+CIPrintCompileQueue
+ *                   compiler.print.PrintCompileQueue
+ *
+ */
+
+package compiler.print;
+
+public class PrintCompileQueue {
+    public static void main(String[] args) {
+        System.out.println("Passed");
+    }
+}
--- a/test/jdk/java/awt/GradientPaint/LinearColorSpaceGradientTest.java	Wed Sep 18 08:20:10 2019 +0200
+++ b/test/jdk/java/awt/GradientPaint/LinearColorSpaceGradientTest.java	Wed Sep 18 11:32:34 2019 +0200
@@ -30,7 +30,7 @@
  * @test
  * @key headful
  * @bug 8023483
- * @summary tests wether the colorspace-parameter is applied correctly when
+ * @summary tests whether the colorspace-parameter is applied correctly when
  *          creating a gradient.
  * @author ceisserer
  */
--- a/test/jdk/java/awt/Graphics2D/DrawString/XRenderElt254TextTest.java	Wed Sep 18 08:20:10 2019 +0200
+++ b/test/jdk/java/awt/Graphics2D/DrawString/XRenderElt254TextTest.java	Wed Sep 18 11:32:34 2019 +0200
@@ -33,7 +33,7 @@
  * @test
  * @key headful
  * @bug 8028722
- * @summary tests wether drawString with 254 characters causes the xrender
+ * @summary tests whether drawString with 254 characters causes the xrender
  *          pipeline to hang.
  * @author ceisserer
  */
--- a/test/jdk/java/nio/channels/Selector/WakeupSpeed.java	Wed Sep 18 08:20:10 2019 +0200
+++ b/test/jdk/java/nio/channels/Selector/WakeupSpeed.java	Wed Sep 18 11:32:34 2019 +0200
@@ -23,7 +23,7 @@
 
 /* @test
  * @bug 4467968
- * @summary Tests wether wakeup makes the next select() call return immediately
+ * @summary Tests whether wakeup makes the next select() call return immediately
  */
 
 import java.io.IOException;
--- a/test/jdk/java/text/Format/DecimalFormat/FormatMicroBenchmark.java	Wed Sep 18 08:20:10 2019 +0200
+++ b/test/jdk/java/text/Format/DecimalFormat/FormatMicroBenchmark.java	Wed Sep 18 11:32:34 2019 +0200
@@ -87,7 +87,7 @@
  *
  *  Note  that these benchmarks  will provide numbers  without any knowledge of
  *  the  implementation of DecimalFormat class. So  to check regression any run
- *  should be compared to another reference run with  a previous JDK, wether or
+ *  should be compared to another reference run with  a previous JDK, whether or
  *  not this previous reference JDK contains fast-path implementation.
  *
  *  The eight benchmarks below are dedicated to measure throughput on different
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/jdk/nio/zipfs/LargeEntriesTest.java	Wed Sep 18 11:32:34 2019 +0200
@@ -0,0 +1,541 @@
+/*
+ * 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.
+ *
+ */
+
+import org.testng.annotations.*;
+
+import java.io.*;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.FileSystem;
+import java.nio.file.*;
+import java.security.SecureRandom;
+import java.util.Arrays;
+import java.util.Map;
+import java.util.function.Consumer;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+
+import static java.lang.Boolean.TRUE;
+import static java.lang.String.format;
+import static java.util.stream.Collectors.joining;
+import static org.testng.Assert.*;
+
+/**
+ * @test
+ * @bug 8230870
+ * @summary Test ZIP Filesystem behavior with ~64k entries
+ * @modules jdk.zipfs
+ * @run testng LargeEntriesTest
+ */
+public class LargeEntriesTest {
+
+    private static final Path HERE = Path.of(".");
+
+    /**
+     * Number of ZIP entries which results in the use of ZIP64
+     */
+    private static final int ZIP64_ENTRIES = 65535;
+
+    /**
+     * Classes and MANIFEST attribute used for invoking Main via java -jar
+     */
+    private static final String MANIFEST_MAIN_CLASS = "LargeEntriesTest$Main";
+    private static final String MAIN_CLASS = "LargeEntriesTest$Main.class";
+    private static final String THIS_CLASS = "LargeEntriesTest.class";
+
+    /**
+     * Number of entries included in the JAR file including  META-INF,
+     * MANIFEST.MF, and the classes associated with this test
+     */
+    private static final int ADDITIONAL_JAR_ENTRIES = 4;
+
+    /**
+     * Value used for creating the required entries in a ZIP or JAR file
+     */
+    private static final String ZIP_FILE_VALUE = "US Open 2019";
+    private static final byte[] ZIP_FILE_ENTRY =
+            ZIP_FILE_VALUE.getBytes(StandardCharsets.UTF_8);
+
+    /**
+     * Location of the classes to be added to the JAR file
+     */
+    static final Path TEST_CLASSES = Paths.get(System.getProperty("test.classes", "."));
+
+    private static final SecureRandom random = new SecureRandom();
+
+    /**
+     * Fields used for timing runs
+     */
+    private static int testNumberRunning;
+    private static long runningTestTime;
+    private static long startTestRunTime;
+    private static final double NANOS_IN_SECOND = 1_000_000_000.0;
+
+    @BeforeTest(enabled = false)
+    public void beforeTest() {
+        startTestRunTime = System.nanoTime();
+    }
+
+    @AfterTest(enabled = false)
+    public void afterTest() {
+        long endTestRunTime = System.nanoTime();
+        long duration = endTestRunTime - startTestRunTime;
+        System.out.printf("#### Completed test run, total running time: %.4f in seconds%n",
+                duration / NANOS_IN_SECOND);
+    }
+
+    @BeforeMethod(enabled = false)
+    public static void beforeMethod() {
+        runningTestTime = System.nanoTime();
+        System.out.printf("**** Starting test number: %s%n", testNumberRunning);
+    }
+
+    @AfterMethod(enabled = false)
+    public void afterMethod() {
+        long endRunningTestTime = System.nanoTime();
+        long duration = endRunningTestTime - runningTestTime;
+        System.out.printf("**** Completed test number: %s, Time: %.4f%n",
+                testNumberRunning, duration / NANOS_IN_SECOND);
+        testNumberRunning++;
+    }
+
+    /**
+     * Validate that you can create a ZIP file with and without compression
+     * and that the ZIP file is created using ZIP64 if there are 65535 or
+     * more entries.
+     *
+     * @param env         Properties used for creating the ZIP Filesystem
+     * @param compression Indicates whether the files are DEFLATED(default)
+     *                    or STORED
+     * @throws Exception If an error occurs during the creation, verification or
+     *                   deletion of the ZIP file
+     */
+    @Test(dataProvider = "zipfsMap", enabled = true)
+    public void testZip(Map<String, String> env, int compression) throws Exception {
+
+        System.out.printf("ZIP FS Map = %s, Compression mode= %s%n ",
+                formatMap(env), compression);
+
+        for (int entries = ZIP64_ENTRIES - 1; entries < ZIP64_ENTRIES + 2; entries++) {
+            Path zipfile = generatePath(HERE, "test", ".zip");
+            Files.deleteIfExists(zipfile);
+            createZipFile(zipfile, env, entries);
+            verify(zipfile, compression, entries,
+                    isTrue(env, "forceZIP64End"), 0);
+            Files.deleteIfExists(zipfile);
+        }
+    }
+
+    /**
+     * Validate that when the forceZIP64End property is set to true,
+     * that ZIP64 is used.
+     *
+     * @param env         Properties used for creating the ZIP Filesystem
+     * @param compression Indicates whether the files are DEFLATED(default)
+     *                    or STORED
+     * @throws Exception If an error occurs during the creation, verification or
+     *                   deletion of the ZIP file
+     */
+    @Test(dataProvider = "zip64Map", enabled = true)
+    public void testForceZIP64End(Map<String, String> env, int compression) throws Exception {
+
+        System.out.printf("ZIP FS Map = %s, Compression mode= %s%n ",
+                formatMap(env), compression);
+
+        // Generate a ZIP file path
+        Path zipfile = generatePath(HERE, "test", ".zip");
+        Files.deleteIfExists(zipfile);
+        createZipFile(zipfile, env, 1);
+        verify(zipfile, compression, 1, isTrue(env, "forceZIP64End"), 0);
+        Files.deleteIfExists(zipfile);
+    }
+
+    /**
+     * Validate that you can create a JAR file with and without compression
+     * and that the JAR file is created using ZIP64 if there are 65535 or
+     * more entries.
+     *
+     * @param env         Properties used for creating the ZIP Filesystem
+     * @param compression Indicates whether the files are DEFLATED(default)
+     *                    or STORED
+     * @throws Exception If an error occurs during the creation, verification or
+     *                   deletion of the JAR file
+     */
+    @Test(dataProvider = "zipfsMap", enabled = true)
+    public void testJar(Map<String, String> env, int compression) throws Exception {
+        for (int entries = ZIP64_ENTRIES - 1; entries < ZIP64_ENTRIES + 2; entries++) {
+            Path jar = generatePath(HERE, "test", ".jar");
+
+            Files.deleteIfExists(jar);
+            createJarFile(jar, env, entries);
+
+            // Now run the Main-Class specified the Manifest
+            runJar(jar.getFileName().toString()).assertSuccess()
+                    .validate(r -> assertTrue(r.output.matches("\\AMain\\Z")));
+
+            verify(jar, compression, entries, isTrue(env, "forceZIP64End"),
+                    ADDITIONAL_JAR_ENTRIES);
+            Files.deleteIfExists(jar);
+        }
+    }
+
+    /**
+     * Create a ZIP File System using the specified properties and a ZIP file
+     * with the specified number of entries
+     *
+     * @param zipFile Path to the ZIP File to create
+     * @param env     Properties used for creating the ZIP Filesystem
+     * @param entries Number of entries to add to the ZIP File
+     * @throws IOException If an error occurs while creating the ZIP file
+     */
+    private void createZipFile(Path zipFile, Map<String, String> env,
+                               int entries) throws IOException {
+        System.out.printf("Creating file = %s%n", zipFile);
+        try (FileSystem zipfs =
+                     FileSystems.newFileSystem(zipFile, env)) {
+
+            for (int i = 0; i < entries; i++) {
+                Files.writeString(zipfs.getPath("Entry-" + i), ZIP_FILE_VALUE);
+            }
+        }
+    }
+
+    /**
+     * Create a ZIP File System using the specified properties and a JAR file
+     * with the specified number of entries
+     *
+     * @param zipFile Path to the JAR File to create
+     * @param env     Properties used for creating the ZIP Filesystem
+     * @param entries Number of entries to add to the JAR File
+     * @throws IOException If an error occurs while creating the JAR file
+     */
+    private void createJarFile(Path zipFile, Map<String, String> env,
+                               int entries) throws IOException {
+        System.out.printf("Creating file = %s%n", zipFile);
+        String jdkVendor = System.getProperty("java.vendor");
+        String jdkVersion = System.getProperty("java.version");
+        String manifest = "Manifest-Version: 1.0"
+                + System.lineSeparator()
+                + "Main-Class: " + MANIFEST_MAIN_CLASS
+                + System.lineSeparator()
+                + "Created-By: " + jdkVersion + " (" + jdkVendor + ")";
+
+        try (FileSystem zipfs =
+                     FileSystems.newFileSystem(zipFile, env);
+             InputStream in = new ByteArrayInputStream(manifest.getBytes())) {
+
+            // Get ZIP FS path to META-INF/MANIFEST.MF
+            Path metadir = zipfs.getPath("/", "META-INF");
+            Path manifestFile = metadir.resolve("MANIFEST.MF");
+
+            // Create META-INF directory if it does not already exist and
+            // add the MANIFEST.MF file
+            if (!Files.exists(metadir))
+                Files.createDirectory(zipfs.getPath("/", "META-INF"));
+            Files.copy(in, manifestFile);
+
+            // Add the needed test classes
+            Path target = zipfs.getPath("/");
+            Files.copy(TEST_CLASSES.resolve(MAIN_CLASS),
+                    target.resolve(MAIN_CLASS));
+            Files.copy(TEST_CLASSES.resolve(THIS_CLASS),
+                    target.resolve(THIS_CLASS));
+
+            // Add the remaining entries that are required
+            for (int i = ADDITIONAL_JAR_ENTRIES; i < entries; i++) {
+                Files.writeString(zipfs.getPath("Entry-" + i), ZIP_FILE_VALUE);
+            }
+        }
+    }
+
+    /*
+     * DataProvider used to validate that you can create a ZIP file with and
+     * without compression.
+     */
+    @DataProvider(name = "zipfsMap")
+    private Object[][] zipfsMap() {
+        return new Object[][]{
+                {Map.of("create", "true"), ZipEntry.DEFLATED},
+                {Map.of("create", "true", "noCompression", "true"),
+                        ZipEntry.STORED},
+                {Map.of("create", "true", "noCompression", "false"),
+                        ZipEntry.DEFLATED}
+        };
+    }
+
+    /*
+     * DataProvider used to validate that you can create a ZIP file with/without
+     * ZIP64 format extensions
+     */
+    @DataProvider(name = "zip64Map")
+    private Object[][] zip64Map() {
+        return new Object[][]{
+                {Map.of("create", "true", "forceZIP64End", "true"),
+                        ZipEntry.DEFLATED},
+                {Map.of("create", "true", "noCompression", "true",
+                        "forceZIP64End", "true"), ZipEntry.STORED},
+                {Map.of("create", "true", "noCompression", "false",
+                        "forceZIP64End", "false"), ZipEntry.DEFLATED},
+                {Map.of("create", "true", "noCompression", "true",
+                        "forceZIP64End", "false"), ZipEntry.STORED}
+        };
+    }
+
+    /**
+     * Verify that the given path is a ZIP file containing the
+     * expected entries.
+     *
+     * @param zipfile       ZIP file to be validated
+     * @param method        Expected Compression method: STORED or DEFLATED
+     * @param entries       Number of expected entries
+     * @param isZip64Forced true if ZIP64 use is being forced; false otherwise
+     * @param start         Starting number for verifying entries
+     * @throws Exception If an error occurs while examining the ZIP file
+     */
+    private static void verify(Path zipfile, int method, int entries,
+                               boolean isZip64Forced, int start) throws Exception {
+        // check entries with ZIP API
+        try (ZipFile zf = new ZipFile(zipfile.toFile())) {
+            // check entry count
+            assertEquals(entries, zf.size());
+
+            // check compression method and content of each entry
+            for (int i = start; i < entries; i++) {
+                ZipEntry ze = zf.getEntry("Entry-" + i);
+                assertNotNull(ze);
+                assertEquals(method, ze.getMethod());
+                try (InputStream is = zf.getInputStream(ze)) {
+                    byte[] bytes = is.readAllBytes();
+                    assertTrue(Arrays.equals(bytes, ZIP_FILE_ENTRY));
+                }
+            }
+        }
+        // check entries with FileSystem API
+        try (FileSystem fs = FileSystems.newFileSystem(zipfile)) {
+
+            // check entry count
+            Path top = fs.getPath("/");
+            long count = Files.find(top, Integer.MAX_VALUE, (path, attrs) ->
+                    attrs.isRegularFile() || (attrs.isDirectory() &&
+                            path.getFileName() != null &&
+                            path.getFileName().toString().equals("META-INF")))
+                    .count();
+            assertEquals(entries, count);
+
+            // check content of each entry
+            for (int i = start; i < entries; i++) {
+                Path file = fs.getPath("Entry-" + i);
+                byte[] bytes = Files.readAllBytes(file);
+                assertTrue(Arrays.equals(bytes, ZIP_FILE_ENTRY));
+            }
+        }
+
+        // Check for a ZIP64 End of Central Directory Locator
+        boolean foundZip64 = usesZip64(zipfile.toFile());
+
+        // Is ZIP64 required?
+        boolean requireZip64 = entries >= ZIP64_ENTRIES || isZip64Forced;
+        System.out.printf(" isZip64Forced = %s, foundZip64= %s, requireZip64= %s%n",
+                isZip64Forced, foundZip64, requireZip64);
+        assertEquals(requireZip64, foundZip64);
+
+
+    }
+
+    /**
+     * Determine if the specified property name=true/"true"
+     *
+     * @param env  ZIP Filesystem Map
+     * @param name property to validate
+     * @return true if the property value is set to true/"true"; false otherwise
+     */
+    private static boolean isTrue(Map<String, ?> env, String name) {
+        return "true".equals(env.get(name)) || TRUE.equals(env.get(name));
+    }
+
+    /**
+     * Check to see if the ZIP64 End of Central Directory Locator has been found
+     *
+     * @param b byte array to check for the locator in
+     * @param n starting offset for the search
+     * @return true if the Zip64 End of Central Directory Locator is found; false
+     * otherwise
+     */
+    private static boolean end64SigAt(byte[] b, int n) {
+        return b[n] == 'P' & b[n + 1] == 'K' & b[n + 2] == 6 & b[n + 3] == 6;
+    }
+
+    /**
+     * Utility method that checks the ZIP file for the use of the ZIP64
+     * End of Central Directory Locator
+     *
+     * @param zipFile ZIP file to check
+     * @return true if the ZIP64 End of Central Directory Locator is found; false
+     * otherwise
+     * * @throws Exception If an error occurs while traversing the file
+     */
+    private static boolean usesZip64(File zipFile) throws Exception {
+
+        try (RandomAccessFile raf = new RandomAccessFile(zipFile, "r")) {
+            byte[] buf = new byte[4096];
+            long seeklen = raf.length() - buf.length;
+
+            if (seeklen < 0)
+                seeklen = 0;
+            raf.seek(seeklen);
+            raf.read(buf);
+            for (int i = 0; i < buf.length - 4; i++) {
+                // Is there a ZIP64 End of Central Directory Locator?
+                if (end64SigAt(buf, i)) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Generate a temporary file Path
+     *
+     * @param dir    Directory used to create the path
+     * @param prefix The prefix string used to create the path
+     * @param suffix The suffix string used to create the path
+     * @return Path that was generated
+     */
+    private static Path generatePath(Path dir, String prefix, String suffix) {
+        long n = random.nextLong();
+        String s = prefix + Long.toUnsignedString(n) + suffix;
+        Path name = dir.getFileSystem().getPath(s);
+        // the generated name should be a simple file name
+        if (name.getParent() != null)
+            throw new IllegalArgumentException("Invalid prefix or suffix");
+        return dir.resolve(name);
+    }
+
+    /**
+     * Utility method to return a formatted String of the key:value entries for
+     * a Map
+     *
+     * @param env Map to format
+     * @return Formatted string of the Map entries
+     */
+    private static String formatMap(Map<String, String> env) {
+        return env.entrySet().stream()
+                .map(e -> format("(%s:%s)", e.getKey(), e.getValue()))
+                .collect(joining(", "));
+    }
+
+    /**
+     * Validates that a jar created using ZIP FS can be used by the java
+     * tool to run a program specified in the Main-Class Manifest attribute
+     *
+     * @param jarFile Name of the JAR file to specify to the -jar option
+     * @return A Result object representing the return code and output from the
+     * program that was invoked
+     */
+    private static Result runJar(String jarFile) {
+        String javaHome = System.getProperty("java.home");
+        String java = Paths.get(javaHome, "bin", "java").toString();
+        String[] cmd = {java, "-jar", jarFile};
+        String output;
+        ProcessBuilder pb = new ProcessBuilder(cmd);
+        Process p;
+        try {
+            p = pb.start();
+            output = toString(p.getInputStream(), p.getErrorStream());
+            p.waitFor();
+        } catch (IOException | InterruptedException e) {
+            throw new RuntimeException(
+                    format("Error invoking: '%s', Exception= %s", pb.command(), e));
+        }
+
+        return new Result(p.exitValue(), output);
+    }
+
+    /**
+     * Utility method to combine the output and error streams for the Process
+     * started by ProcessBuilder
+     *
+     * @param is  Process Outputstream
+     * @param is2 Process ErrorStream
+     * @return String representing the combination of the OutputStream & ErrorStream
+     * @throws IOException If an error occurs while combining the streams
+     */
+    private static String toString(InputStream is, InputStream is2) throws IOException {
+        try (ByteArrayOutputStream dst = new ByteArrayOutputStream();
+             InputStream concatenated = new SequenceInputStream(is, is2)) {
+            concatenated.transferTo(dst);
+            return new String(dst.toByteArray(), StandardCharsets.UTF_8);
+        }
+    }
+
+    /**
+     * Wrapper class used to verify the results from a ProcessBuilder invocation
+     */
+    private static class Result {
+        final int ec;         // Return code for command that was executed
+        final String output;  // Output from the command that was executed
+
+        /**
+         * Constructor
+         *
+         * @param ec     Return code from the ProcessBuilder invocation
+         * @param output ProcessBuilder output to be validated
+         */
+        private Result(int ec, String output) {
+            this.ec = ec;
+            this.output = output;
+        }
+
+        /**
+         * Validate that the command that was executed completed successfully
+         *
+         * @return This Result object
+         */
+        Result assertSuccess() {
+            assertEquals(ec, 0, format("Expected ec 0, received: %s, output [%s]", ec, output));
+            return this;
+        }
+
+        /**
+         * Validate that the expected result is received
+         *
+         * @param r The operation to perform
+         * @return This Result object
+         */
+        Result validate(Consumer<Result> r) {
+            r.accept(this);
+            return this;
+        }
+    }
+
+    /**
+     * Trivial class used to validate that a JAR created using ZIP FS
+     * can be successfully executed
+     */
+    public static class Main {
+        public static void main(String[] args) {
+            System.out.print("Main");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/diags/examples/SourceNoSystemModulesPath.java	Wed Sep 18 11:32:34 2019 +0200
@@ -0,0 +1,27 @@
+/*
+ * 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.
+ */
+
+// key: compiler.warn.source.no.system.modules.path
+// options: -source 9
+
+class SourceNoSystemModulesPath { }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/options/BCPOrSystemNotSpecified.java	Wed Sep 18 11:32:34 2019 +0200
@@ -0,0 +1,217 @@
+/*
+ * 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 8228460
+ * @summary Verify --system is required rather than -bootclasspath for -source 9.
+ * @library /tools/lib
+ * @modules jdk.compiler/com.sun.tools.javac.api
+ *          jdk.compiler/com.sun.tools.javac.main
+ * @build toolbox.ToolBox toolbox.JavacTask toolbox.TestRunner
+ * @run main BCPOrSystemNotSpecified
+ */
+
+import java.io.IOException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Arrays;
+import java.util.List;
+
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.util.EnumSet;
+import javax.tools.JavaFileManager;
+import javax.tools.JavaFileObject;
+import javax.tools.StandardLocation;
+import javax.tools.ToolProvider;
+import toolbox.JavacTask;
+import toolbox.Task;
+import toolbox.Task.Expect;
+import toolbox.TestRunner;
+import toolbox.ToolBox;
+
+public class BCPOrSystemNotSpecified extends TestRunner {
+
+    private final ToolBox tb = new ToolBox();
+    private final String fileSep = System.getProperty("file.separator");
+
+    public BCPOrSystemNotSpecified() {
+        super(System.err);
+    }
+
+    public static void main(String... args) throws Exception {
+        new BCPOrSystemNotSpecified().runTests();
+    }
+
+    @Test
+    public void testSource8(Path base) throws IOException {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src,
+                          "package test; public class Test { } ");
+        Path classes = base.resolve("classes");
+        tb.createDirectories(classes);
+
+        List<String> log;
+        List<String> expected = Arrays.asList(
+                "- compiler.warn.source.no.bootclasspath: 8",
+                "1 warning"
+        );
+
+        log = new JavacTask(tb)
+                .options("-XDrawDiagnostics", "-source", "8")
+                .outdir(classes)
+                .files(tb.findJavaFiles(src))
+                .run(Expect.SUCCESS)
+                .writeAll()
+                .getOutputLines(Task.OutputKind.DIRECT);
+
+        if (!expected.equals(log)) {
+            throw new AssertionError("Unexpected output: " + log);
+        }
+
+        Path bcp = base.resolve("bcp");
+
+        prepareBCP(bcp);
+
+        new JavacTask(tb)
+                .options("-XDrawDiagnostics",
+                         "-source", "8",
+                         "-bootclasspath", bcp.toAbsolutePath().toString(),
+                         "-Werror")
+                .outdir(classes)
+                .files(tb.findJavaFiles(src))
+                .run(Expect.SUCCESS)
+                .writeAll()
+                .getOutputLines(Task.OutputKind.DIRECT);
+
+        if (!expected.equals(log)) {
+            throw new AssertionError("Unexpected output: " + log);
+        }
+    }
+
+    @Test
+    public void testSource9(Path base) throws IOException {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src,
+                          "package test; public class Test { } ");
+        Path classes = base.resolve("classes");
+        tb.createDirectories(classes);
+
+        List<String> log;
+        List<String> expected = Arrays.asList(
+                "- compiler.warn.source.no.system.modules.path: 9",
+                "1 warning"
+        );
+
+        log = new JavacTask(tb)
+                .options("-XDrawDiagnostics",
+                         "-source", "9")
+                .outdir(classes)
+                .files(tb.findJavaFiles(src))
+                .run(Expect.SUCCESS)
+                .writeAll()
+                .getOutputLines(Task.OutputKind.DIRECT);
+
+        if (!expected.equals(log)) {
+            throw new AssertionError("Unexpected output: " + log);
+        }
+
+        Path bcp = base.resolve("bcp");
+
+        prepareBCP(bcp);
+
+        log = new JavacTask(tb)
+                .options("-XDrawDiagnostics",
+                         "-source", "9",
+                         "-bootclasspath", bcp.toAbsolutePath().toString())
+                .outdir(classes)
+                .files(tb.findJavaFiles(src))
+                .run(Expect.SUCCESS)
+                .writeAll()
+                .getOutputLines(Task.OutputKind.DIRECT);
+
+        if (!expected.equals(log)) {
+            throw new AssertionError("Unexpected output: " + log);
+        }
+
+        new JavacTask(tb)
+                .options("-XDrawDiagnostics",
+                         "-source", "9",
+                         "--system", "none",
+                         "--module-path", bcp.toAbsolutePath().toString(),
+                         "-Werror")
+                .outdir(classes)
+                .files(tb.findJavaFiles(src))
+                .run(Expect.SUCCESS)
+                .writeAll()
+                .getOutputLines(Task.OutputKind.DIRECT);
+
+        if (!expected.equals(log)) {
+            throw new AssertionError("Unexpected output: " + log);
+        }
+
+        new JavacTask(tb)
+                .options("-XDrawDiagnostics",
+                         "-source", "9",
+                         "--system", System.getProperty("java.home"),
+                         "-Werror")
+                .outdir(classes)
+                .files(tb.findJavaFiles(src))
+                .run(Expect.SUCCESS)
+                .writeAll()
+                .getOutputLines(Task.OutputKind.DIRECT);
+
+        if (!expected.equals(log)) {
+            throw new AssertionError("Unexpected output: " + log);
+        }
+    }
+
+    protected void runTests() throws Exception {
+        runTests(m -> new Object[] { Paths.get(m.getName()).toAbsolutePath() });
+    }
+
+    private void prepareBCP(Path target) throws IOException {
+        try (JavaFileManager jfm = ToolProvider.getSystemJavaCompiler()
+                                               .getStandardFileManager(null, null, null)) {
+            for (String pack : new String[] {"", "java.lang", "java.lang.annotation"}) {
+                JavaFileManager.Location javaBase =
+                        jfm.getLocationForModule(StandardLocation.SYSTEM_MODULES,
+                                                 "java.base");
+                for (JavaFileObject file : jfm.list(javaBase,
+                                                    pack,
+                                                    EnumSet.of(JavaFileObject.Kind.CLASS),
+                                                    false)) {
+                    Path targetDir = target.resolve(pack.replace(".", fileSep));
+                    Files.createDirectories(targetDir);
+                    try (InputStream in = file.openInputStream()) {
+                        String sourcePath = file.getName();
+                        int sepPos = sourcePath.lastIndexOf(fileSep);
+                        String fileName = sourcePath.substring(sepPos + 1);
+                        Files.copy(in, targetDir.resolve(fileName));
+                    }
+                }
+            }
+        }
+    }
+}
--- a/test/langtools/tools/javac/var_implicit_lambda/VarInImplicitLambdaNegTest01_source10.out	Wed Sep 18 08:20:10 2019 +0200
+++ b/test/langtools/tools/javac/var_implicit_lambda/VarInImplicitLambdaNegTest01_source10.out	Wed Sep 18 11:32:34 2019 +0200
@@ -1,4 +1,4 @@
-- compiler.warn.source.no.bootclasspath: 10
+- compiler.warn.source.no.system.modules.path: 10
 VarInImplicitLambdaNegTest01.java:12:36: compiler.err.feature.not.supported.in.source.plural: (compiler.misc.feature.var.syntax.in.implicit.lambda), 10, 11
 VarInImplicitLambdaNegTest01.java:15:28: compiler.err.invalid.lambda.parameter.declaration: (compiler.misc.implicit.and.explicit.not.allowed)
 VarInImplicitLambdaNegTest01.java:17:52: compiler.err.restricted.type.not.allowed.here: var