Merge
authoraph
Mon, 27 Nov 2017 17:04:45 +0000
changeset 48128 2d91c9a4f409
parent 48127 efc459cf351e (current diff)
parent 48125 4e5124dacf91 (diff)
child 48129 c134a8bee21a
Merge
src/hotspot/cpu/aarch64/templateInterpreterGenerator_aarch64.cpp
src/hotspot/share/gc/g1/hSpaceCounters.cpp
src/hotspot/share/gc/g1/hSpaceCounters.hpp
src/java.desktop/share/classes/sun/java2d/pisces/Curve.java
src/java.desktop/share/classes/sun/java2d/pisces/Dasher.java
src/java.desktop/share/classes/sun/java2d/pisces/Helpers.java
src/java.desktop/share/classes/sun/java2d/pisces/PiscesCache.java
src/java.desktop/share/classes/sun/java2d/pisces/PiscesRenderingEngine.java
src/java.desktop/share/classes/sun/java2d/pisces/PiscesTileGenerator.java
src/java.desktop/share/classes/sun/java2d/pisces/Renderer.java
src/java.desktop/share/classes/sun/java2d/pisces/Stroker.java
src/java.desktop/share/classes/sun/java2d/pisces/TransformingPathConsumer2D.java
src/java.desktop/unix/classes/sun/java2d/jules/IdleTileCache.java
src/java.desktop/unix/classes/sun/java2d/jules/JulesAATileGenerator.java
src/java.desktop/unix/classes/sun/java2d/jules/JulesPathBuf.java
src/java.desktop/unix/classes/sun/java2d/jules/JulesRenderingEngine.java
src/java.desktop/unix/classes/sun/java2d/jules/JulesShapePipe.java
src/java.desktop/unix/classes/sun/java2d/jules/JulesTile.java
src/java.desktop/unix/classes/sun/java2d/jules/TileTrapContainer.java
src/java.desktop/unix/classes/sun/java2d/jules/TileWorker.java
src/java.desktop/unix/classes/sun/java2d/jules/TrapezoidList.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/TableHeader.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlDocWriter.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlWriter.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/GroupTypes.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/MethodTypes.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/ModulePackageTypes.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/TableTabTypes.java
src/jdk.jshell/share/classes/jdk/jshell/tool/resources/JAVASE.jsh
test/hotspot/jtreg/gc/metaspace/PerfCounter.java
test/hotspot/jtreg/gc/metaspace/PerfCounters.java
test/jdk/sun/java2d/pisces/OpenJDKFillBug.java
test/jdk/sun/java2d/pisces/Renderer/Test7019861.java
test/jdk/sun/java2d/pisces/Renderer/TestNPE.java
test/jdk/sun/java2d/pisces/Test7036754.java
test/jdk/sun/pisces/DashStrokeTest.java
test/jdk/sun/pisces/JoinMiterTest.java
test/jdk/sun/pisces/ScaleTest.java
test/jdk/sun/pisces/StrokeShapeTest.java
test/jdk/sun/pisces/TEST.properties
test/jdk/sun/pisces/ThinLineTest.java
test/langtools/tools/javadoc/sourceOnly/p/NonSource.class
--- a/.hgtags	Fri Nov 24 17:19:47 2017 +0000
+++ b/.hgtags	Mon Nov 27 17:04:45 2017 +0000
@@ -456,3 +456,5 @@
 a6e591e12f122768f675428e1e5a838fd0e9c7ec jdk-10+29
 8fee80b92e65149f7414250fd5e34b6f35d417b4 jdk-10+30
 e6278add9ff28fab70fe1cc4c1d65f7363dc9445 jdk-10+31
+a2008587c13fa05fa2dbfcb09fe987576fbedfd1 jdk-10+32
+bbd692ad4fa300ecca7939ffbe3b1d5e52a28cc6 jdk-10+33
--- a/doc/building.html	Fri Nov 24 17:19:47 2017 +0000
+++ b/doc/building.html	Mon Nov 27 17:04:45 2017 +0000
@@ -871,9 +871,9 @@
 <p>When building for distribution, <code>zipped</code> is a good solution. Binaries built with <code>internal</code> is suitable for use by developers, since they facilitate debugging, but should be stripped before distributed to end users.</p>
 <h3 id="autoconf-details">Autoconf Details</h3>
 <p>The <code>configure</code> script is based on the autoconf framework, but in some details deviate from a normal autoconf <code>configure</code> script.</p>
-<p>The <code>configure</code> script in the top level directory of OpenJDK is just a thin wrapper that calls <code>common/autoconf/configure</code>. This in turn provides functionality that is not easily expressed in the normal Autoconf framework, and then calls into the core of the <code>configure</code> script, which is the <code>common/autoconf/generated-configure.sh</code> file.</p>
+<p>The <code>configure</code> script in the top level directory of OpenJDK is just a thin wrapper that calls <code>make/autoconf/configure</code>. This in turn provides functionality that is not easily expressed in the normal Autoconf framework, and then calls into the core of the <code>configure</code> script, which is the <code>make/autoconf/generated-configure.sh</code> file.</p>
 <p>As the name implies, this file is generated by Autoconf. It is checked in after regeneration, to alleviate the common user to have to install Autoconf.</p>
-<p>The build system will detect if the Autoconf source files have changed, and will trigger a regeneration of <code>common/autoconf/generated-configure.sh</code> if needed. You can also manually request such an update by <code>bash common/autoconf/autogen.sh</code>.</p>
+<p>The build system will detect if the Autoconf source files have changed, and will trigger a regeneration of <code>make/autoconf/generated-configure.sh</code> if needed. You can also manually request such an update by <code>bash make/autoconf/autogen.sh</code>.</p>
 <p>If you make changes to the build system that requires a re-generation, note the following:</p>
 <ul>
 <li><p>You must use <em>exactly</em> version 2.69 of autoconf for your patch to be accepted. This is to avoid spurious changes in the generated file. Note that Ubuntu 16.04 ships a patched version of autoconf which claims to be 2.69, but is not.</p></li>
--- a/doc/building.md	Fri Nov 24 17:19:47 2017 +0000
+++ b/doc/building.md	Mon Nov 27 17:04:45 2017 +0000
@@ -1660,18 +1660,18 @@
 deviate from a normal autoconf `configure` script.
 
 The `configure` script in the top level directory of OpenJDK is just a thin
-wrapper that calls `common/autoconf/configure`. This in turn provides
+wrapper that calls `make/autoconf/configure`. This in turn provides
 functionality that is not easily expressed in the normal Autoconf framework,
 and then calls into the core of the `configure` script, which is the
-`common/autoconf/generated-configure.sh` file.
+`make/autoconf/generated-configure.sh` file.
 
 As the name implies, this file is generated by Autoconf. It is checked in after
 regeneration, to alleviate the common user to have to install Autoconf.
 
 The build system will detect if the Autoconf source files have changed, and
-will trigger a regeneration of `common/autoconf/generated-configure.sh` if
+will trigger a regeneration of `make/autoconf/generated-configure.sh` if
 needed. You can also manually request such an update by `bash
-common/autoconf/autogen.sh`.
+make/autoconf/autogen.sh`.
 
 If you make changes to the build system that requires a re-generation, note the
 following:
--- a/make/Init.gmk	Fri Nov 24 17:19:47 2017 +0000
+++ b/make/Init.gmk	Mon Nov 27 17:04:45 2017 +0000
@@ -329,7 +329,7 @@
 	$(call PrintFailureReports)
 	$(call PrintBuildLogFailures)
 	$(call ReportProfileTimes)
-	$(PRINTF) "Hint: See common/doc/building.html#troubleshooting for assistance.\n\n"
+	$(PRINTF) "Hint: See doc/building.html#troubleshooting for assistance.\n\n"
         ifneq ($(COMPARE_BUILD), )
 	  $(call CleanupCompareBuild)
         endif
--- a/make/RunTests.gmk	Fri Nov 24 17:19:47 2017 +0000
+++ b/make/RunTests.gmk	Mon Nov 27 17:04:45 2017 +0000
@@ -32,9 +32,6 @@
 # We will always run multiple tests serially
 .NOTPARALLEL:
 
-# Directories to find jtreg tests relative to
-JTREG_TEST_TOPDIRS := $(TOPDIR) $(JTREG_TESTROOTS)
-
 # Hook to include the corresponding custom file, if present.
 $(eval $(call IncludeCustomExtension, RunTests.gmk))
 
@@ -119,12 +116,40 @@
   )
 endef
 
+# Take a partial Jtreg root path and return a full, absolute path to that Jtreg
+# root. Also support having "hotspot" as an alias for "hotspot/jtreg".
+ExpandJtregRoot = \
+  $(strip $(wildcard $(patsubst %/, %, \
+    $(if $(filter /%, $1), \
+      $1 \
+    , \
+      $(filter $(addprefix %, $1), $(JTREG_TESTROOTS) $(addsuffix /, $(JTREG_TESTROOTS))) \
+      $(filter $(addprefix %, $(strip $1)/jtreg), $(JTREG_TESTROOTS) $(addsuffix /, $(JTREG_TESTROOTS))) \
+    ) \
+  )))
+
+# Take a partial Jtreg test path and return a full, absolute path to that Jtreg
+# test. Also support having "hotspot" as an alias for "hotspot/jtreg".
+ExpandJtregPath = \
+  $(if $(call ExpandJtregRoot, $1), \
+    $(call ExpandJtregRoot, $1) \
+  , \
+    $(strip $(wildcard $(patsubst %/, %, \
+      $(if $(filter /%, $1), \
+        $1 \
+      , \
+        $(addsuffix /$(strip $1), $(JTREG_TESTROOTS) $(TEST_BASEDIRS)) \
+        $(addsuffix $(strip $(patsubst hotspot/%, /hotspot/jtreg/%, $1)), $(JTREG_TESTROOTS) $(TEST_BASEDIRS)) \
+      ) \
+    ))) \
+  )
+
 # Helper function to determine if a test specification is a Jtreg test
 #
 # It is a Jtreg test if it optionally begins with jtreg:, and then is either
 # an unspecified group name (possibly prefixed by :), or a group in a
-# specified test/<component> directory, or a path to a test or test directory,
-# either absolute or relative to any of the JTREG_TEST_TOPDIRS.
+# specified test root, or a path to a test or test directory,
+# either absolute or relative to any of the TEST_BASEDIRS or test roots.
 define ParseJtregTestSelection
   $(eval TEST_NAME := $(strip $(patsubst jtreg:%, %, $1))) \
   $(if $(or $(findstring :, $(TEST_NAME)), $(findstring /, $(TEST_NAME))), , \
@@ -132,20 +157,16 @@
   ) \
   $(if $(findstring :, $(TEST_NAME)), \
     $(if $(filter :%, $(TEST_NAME)), \
-      $(foreach root, $(JTREG_TESTROOTS), \
-        $(if $(filter $(patsubst :%, %, $(TEST_NAME)), \
-            $($(root)_JTREG_TEST_GROUPS)), \
-          jtreg:$(root):$(patsubst :%,%,$(TEST_NAME)) \
-        ) \
-      ) \
+      $(eval TEST_GROUP := $(patsubst :%, %, $(TEST_NAME))) \
+      $(eval TEST_ROOTS := $(JTREG_TESTROOTS)) \
     , \
-      $(eval ROOT_PART := $(word 1, $(subst :, $(SPACE), $(TEST_NAME)))) \
-      $(eval ROOT := $(filter $(addprefix %, $(ROOT_PART)), $(JTREG_TESTROOTS))) \
-      $(eval GROUP := $(word 2, $(subst :, $(SPACE), $(TEST_NAME)))) \
-      $(foreach root, $(ROOT), \
-        $(if $(filter $(GROUP), $($(root)_JTREG_TEST_GROUPS)), \
-          jtreg:$(root):$(GROUP) \
-        ) \
+      $(eval TEST_PATH := $(word 1, $(subst :, $(SPACE), $(TEST_NAME)))) \
+      $(eval TEST_GROUP := $(word 2, $(subst :, $(SPACE), $(TEST_NAME)))) \
+      $(eval TEST_ROOTS := $(call ExpandJtregRoot, $(TEST_PATH))) \
+    ) \
+    $(foreach test_root, $(TEST_ROOTS), \
+      $(if $(filter $(TEST_GROUP), $($(test_root)_JTREG_TEST_GROUPS)), \
+        jtreg:$(test_root):$(TEST_GROUP) \
       ) \
     ) \
   , \
@@ -154,7 +175,10 @@
         jtreg:$(TEST_NAME) \
       ) \
     , \
-      $(addprefix jtreg:, $(wildcard $(addsuffix /$(TEST_NAME), $(JTREG_TEST_TOPDIRS)))) \
+      $(eval TEST_PATHS := $(call ExpandJtregPath, $(TEST_NAME))) \
+      $(foreach test_path, $(TEST_PATHS), \
+        jtreg:$(test_path) \
+      ) \
     ) \
   )
 endef
@@ -162,7 +186,7 @@
 ifeq ($(TEST), )
   $(info No test selection given in TEST!)
   $(info Please use e.g. 'run-test TEST=tier1' or 'run-test-tier1')
-  $(info See common/doc/testing.[md|html] for help)
+  $(info See doc/testing.[md|html] for help)
   $(error Cannot continue)
 endif
 
@@ -185,7 +209,7 @@
 
 ifneq ($(UNKNOWN_TEST), )
   $(info Unknown test selection: '$(UNKNOWN_TEST)')
-  $(info See common/doc/testing.[md|html] for help)
+  $(info See doc/testing.[md|html] for help)
   $(error Cannot continue)
 endif
 
@@ -299,8 +323,17 @@
   $1_TEST_SUPPORT_DIR := $$(TEST_SUPPORT_DIR)/$1
 
   $1_TEST_NAME := $$(strip $$(patsubst jtreg:%, %, $$($1_TEST)))
-  $1_COMPONENT := $$(firstword $$(subst /, $$(SPACE), \
-      $$(patsubst test/%, %, $$($1_TEST_NAME))))
+
+  $1_COMPONENT := \
+      $$(strip $$(foreach root, $$(JTREG_TESTROOTS), \
+        $$(if $$(filter $$(root)%, $$($1_TEST_NAME)), \
+          $$(lastword $$(subst /, $$(SPACE), $$(root))) \
+        ) \
+      ))
+  # This will work only as long as just hotspot has the additional "jtreg" directory
+  ifeq ($$($1_COMPONENT), jtreg)
+    $1_COMPONENT := hotspot
+  endif
 
   ifeq ($$(JT_HOME), )
     $$(info Error: jtreg framework is not found.)
--- a/make/autoconf/configure	Fri Nov 24 17:19:47 2017 +0000
+++ b/make/autoconf/configure	Mon Nov 27 17:04:45 2017 +0000
@@ -90,13 +90,13 @@
 
 check_hg_updates() {
   if test "x`which hg 2> /dev/null | grep -v '^no hg in'`" != x; then
-    conf_updated_autoconf_files=`cd $conf_script_dir && hg status -mard 2> /dev/null | grep autoconf`
+    conf_updated_autoconf_files=`cd $conf_script_dir && hg status -mard . 2> /dev/null`
     if test "x$conf_updated_autoconf_files" != x; then
       echo "Configure source code has been updated, checking time stamps"
       check_autoconf_timestamps
     elif test "x$CUSTOM_CONFIG_DIR" != x; then
       # If custom source configure is available, make sure it is up-to-date as well.
-      conf_custom_updated_autoconf_files=`cd $CUSTOM_CONFIG_DIR && hg status -mard 2> /dev/null | grep autoconf`
+      conf_custom_updated_autoconf_files=`cd $CUSTOM_CONFIG_DIR && hg status -mard . 2> /dev/null`
       if test "x$conf_custom_updated_autoconf_files" != x; then
         echo "Configure custom source code has been updated, checking time stamps"
         check_autoconf_timestamps
--- a/make/autoconf/generated-configure.sh	Fri Nov 24 17:19:47 2017 +0000
+++ b/make/autoconf/generated-configure.sh	Mon Nov 27 17:04:45 2017 +0000
@@ -656,7 +656,6 @@
 ENABLE_INTREE_EC
 VALID_JVM_FEATURES
 JVM_FEATURES_custom
-JVM_FEATURES_zeroshark
 JVM_FEATURES_zero
 JVM_FEATURES_minimal
 JVM_FEATURES_core
@@ -676,10 +675,6 @@
 PNG_CFLAGS
 USE_EXTERNAL_LIBGIF
 USE_EXTERNAL_LIBJPEG
-LLVM_LIBS
-LLVM_LDFLAGS
-LLVM_CFLAGS
-LLVM_CONFIG
 LIBFFI_LIB_FILE
 ENABLE_LIBFFI_BUNDLING
 LIBFFI_LIBS
@@ -1993,6 +1988,7 @@
   --enable-cds[=yes/no]   enable class data sharing feature in non-minimal VM.
                           Default is yes.
   --disable-hotspot-gtest Disables building of the Hotspot unit tests
+                          [enabled]
   --disable-freetype-bundling
                           disable bundling of the freetype library with the
                           build result [enabled on Windows or when using
@@ -2033,8 +2029,7 @@
   --with-debug-level      set the debug level (release, fastdebug, slowdebug,
                           optimized) [release]
   --with-jvm-variants     JVM variants (separated by commas) to build
-                          (server,client,minimal,core,zero,zeroshark,custom)
-                          [server]
+                          (server,client,minimal,core,zero,custom) [server]
   --with-cpu-port         specify sources to use for Hotspot 64-bit ARM port
                           (arm64,aarch64) [aarch64]
   --with-devkit           use this devkit for compilers, tools and resources
@@ -4272,12 +4267,12 @@
 #
 
 # All valid JVM features, regardless of platform
-VALID_JVM_FEATURES="compiler1 compiler2 zero shark minimal dtrace jvmti jvmci \
+VALID_JVM_FEATURES="compiler1 compiler2 zero minimal dtrace jvmti jvmci \
     graal vm-structs jni-check services management all-gcs nmt cds \
     static-build link-time-opt aot"
 
 # All valid JVM variants
-VALID_JVM_VARIANTS="server client minimal core zero zeroshark custom"
+VALID_JVM_VARIANTS="server client minimal core zero custom"
 
 ###############################################################################
 # Check if the specified JVM variant should be built. To be used in shell if
@@ -4308,7 +4303,6 @@
 #   minimal: reduced form of client with optional features stripped out
 #   core: normal interpreter only, no compiler
 #   zero: C++ based interpreter only, no compiler
-#   zeroshark: C++ based interpreter, and a llvm-based compiler
 #   custom: baseline JVM with no default features
 #
 
@@ -4809,11 +4803,6 @@
 
 
 ################################################################################
-# Setup llvm (Low-Level VM)
-################################################################################
-
-
-################################################################################
 # Setup various libraries, typically small system libraries
 ################################################################################
 
@@ -5166,7 +5155,7 @@
 #CUSTOM_AUTOCONF_INCLUDE
 
 # Do not change or remove the following line, it is needed for consistency checks:
-DATE_WHEN_GENERATED=1509128484
+DATE_WHEN_GENERATED=1511254554
 
 ###############################################################################
 #
@@ -17069,7 +17058,7 @@
 
 
 
-  if   [[ " $JVM_VARIANTS " =~ " zero " ]]   ||   [[ " $JVM_VARIANTS " =~ " zeroshark " ]]  ; then
+  if   [[ " $JVM_VARIANTS " =~ " zero " ]]  ; then
     # zero behaves as a platform and rewrites these values. This is really weird. :(
     # We are guaranteed that we do not build any other variants when building zero.
     HOTSPOT_TARGET_CPU=zero
@@ -25114,7 +25103,7 @@
 
   # Should we build the serviceability agent (SA)?
   INCLUDE_SA=true
-  if   [[ " $JVM_VARIANTS " =~ " zero " ]]   ||   [[ " $JVM_VARIANTS " =~ " zeroshark " ]]  ; then
+  if   [[ " $JVM_VARIANTS " =~ " zero " ]]  ; then
     INCLUDE_SA=false
   fi
   if test "x$OPENJDK_TARGET_OS" = xaix ; then
@@ -51971,7 +51960,7 @@
 
 
     fi
-    if !   [[ " $JVM_VARIANTS " =~ " zero " ]]   && !   [[ " $JVM_VARIANTS " =~ " zeroshark " ]]  ; then
+    if !   [[ " $JVM_VARIANTS " =~ " zero " ]]  ; then
       # Non-zero builds have stricter warnings
       JVM_CFLAGS="$JVM_CFLAGS -Wreturn-type -Wundef -Wformat=2"
     else
@@ -52852,7 +52841,7 @@
 
 
     fi
-    if !   [[ " $JVM_VARIANTS " =~ " zero " ]]   && !   [[ " $JVM_VARIANTS " =~ " zeroshark " ]]  ; then
+    if !   [[ " $JVM_VARIANTS " =~ " zero " ]]  ; then
       # Non-zero builds have stricter warnings
       OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -Wreturn-type -Wundef -Wformat=2"
     else
@@ -54613,7 +54602,7 @@
   fi
 
   # Check if ffi is needed
-  if   [[ " $JVM_VARIANTS " =~ " zero " ]]   ||   [[ " $JVM_VARIANTS " =~ " zeroshark " ]]  ; then
+  if   [[ " $JVM_VARIANTS " =~ " zero " ]]  ; then
     NEEDS_LIB_FFI=true
   else
     NEEDS_LIB_FFI=false
@@ -54686,8 +54675,7 @@
     # If dynamic wasn't requested, go with static unless it isn't available.
     { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to link with libstdc++" >&5
 $as_echo_n "checking how to link with libstdc++... " >&6; }
-    if test "x$with_stdc__lib" = xdynamic || test "x$has_static_libstdcxx" = xno \
-        ||   [[ " $JVM_VARIANTS " =~ " zeroshark " ]]  ; then
+    if test "x$with_stdc__lib" = xdynamic || test "x$has_static_libstdcxx" = xno ; then
       { $as_echo "$as_me:${as_lineno-$LINENO}: result: dynamic" >&5
 $as_echo "dynamic" >&6; }
     else
@@ -65169,94 +65157,6 @@
 
 
 
-  if   [[ " $JVM_VARIANTS " =~ " zeroshark " ]]  ; then
-    # Extract the first word of "llvm-config", so it can be a program name with args.
-set dummy llvm-config; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_LLVM_CONFIG+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if test -n "$LLVM_CONFIG"; then
-  ac_cv_prog_LLVM_CONFIG="$LLVM_CONFIG" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-    for ac_exec_ext in '' $ac_executable_extensions; do
-  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
-    ac_cv_prog_LLVM_CONFIG="llvm-config"
-    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-  done
-IFS=$as_save_IFS
-
-fi
-fi
-LLVM_CONFIG=$ac_cv_prog_LLVM_CONFIG
-if test -n "$LLVM_CONFIG"; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LLVM_CONFIG" >&5
-$as_echo "$LLVM_CONFIG" >&6; }
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
-
-    if test "x$LLVM_CONFIG" != xllvm-config; then
-      as_fn_error $? "llvm-config not found in $PATH." "$LINENO" 5
-    fi
-
-    llvm_components="jit mcjit engine nativecodegen native"
-    unset LLVM_CFLAGS
-    for flag in $("$LLVM_CONFIG" --cxxflags); do
-      if echo "${flag}" | grep -q '^-[ID]'; then
-        if test "${flag}" != "-D_DEBUG" ; then
-          if test "${LLVM_CFLAGS}" != "" ; then
-            LLVM_CFLAGS="${LLVM_CFLAGS} "
-          fi
-          LLVM_CFLAGS="${LLVM_CFLAGS}${flag}"
-        fi
-      fi
-    done
-    llvm_version=$("${LLVM_CONFIG}" --version | $SED 's/\.//; s/svn.*//')
-    LLVM_CFLAGS="${LLVM_CFLAGS} -DSHARK_LLVM_VERSION=${llvm_version}"
-
-    unset LLVM_LDFLAGS
-    for flag in $("${LLVM_CONFIG}" --ldflags); do
-      if echo "${flag}" | grep -q '^-L'; then
-        if test "${LLVM_LDFLAGS}" != ""; then
-          LLVM_LDFLAGS="${LLVM_LDFLAGS} "
-        fi
-        LLVM_LDFLAGS="${LLVM_LDFLAGS}${flag}"
-      fi
-    done
-
-    unset LLVM_LIBS
-    for flag in $("${LLVM_CONFIG}" --libs ${llvm_components}); do
-      if echo "${flag}" | grep -q '^-l'; then
-        if test "${LLVM_LIBS}" != ""; then
-          LLVM_LIBS="${LLVM_LIBS} "
-        fi
-        LLVM_LIBS="${LLVM_LIBS}${flag}"
-      fi
-    done
-
-    # Due to https://llvm.org/bugs/show_bug.cgi?id=16902, llvm does not
-    # always properly detect -ltinfo
-    LLVM_LIBS="${LLVM_LIBS} -ltinfo"
-
-
-
-
-  fi
-
-
 
 # Check whether --with-libjpeg was given.
 if test "${with_libjpeg+set}" = set; then :
@@ -66053,7 +65953,6 @@
 
 
 
-
 # Hotspot setup depends on lib checks.
 
 
@@ -66124,15 +66023,9 @@
     fi
   fi
 
-  if !   [[ " $JVM_VARIANTS " =~ " zero " ]]   && !   [[ " $JVM_VARIANTS " =~ " zeroshark " ]]  ; then
+  if !   [[ " $JVM_VARIANTS " =~ " zero " ]]  ; then
     if   [[ " $JVM_FEATURES " =~ " zero " ]]  ; then
-      as_fn_error $? "To enable zero/zeroshark, you must use --with-jvm-variants=zero/zeroshark" "$LINENO" 5
-    fi
-  fi
-
-  if !   [[ " $JVM_VARIANTS " =~ " zeroshark " ]]  ; then
-    if   [[ " $JVM_FEATURES " =~ " shark " ]]  ; then
-      as_fn_error $? "To enable shark, you must use --with-jvm-variants=zeroshark" "$LINENO" 5
+      as_fn_error $? "To enable zero, you must use --with-jvm-variants=zero" "$LINENO" 5
     fi
   fi
 
@@ -66216,7 +66109,6 @@
   JVM_FEATURES_core="$NON_MINIMAL_FEATURES $JVM_FEATURES"
   JVM_FEATURES_minimal="compiler1 minimal $JVM_FEATURES $JVM_FEATURES_link_time_opt"
   JVM_FEATURES_zero="zero $NON_MINIMAL_FEATURES $JVM_FEATURES"
-  JVM_FEATURES_zeroshark="zero shark $NON_MINIMAL_FEATURES $JVM_FEATURES"
   JVM_FEATURES_custom="$JVM_FEATURES"
 
 
@@ -66226,7 +66118,6 @@
 
 
 
-
   # Used for verification of Makefiles by check-jvm-feature
 
 
@@ -68104,7 +67995,6 @@
   JVM_FEATURES_core="$($ECHO $($PRINTF '%s\n' $JVM_FEATURES_core | $SORT -u))"
   JVM_FEATURES_minimal="$($ECHO $($PRINTF '%s\n' $JVM_FEATURES_minimal | $SORT -u))"
   JVM_FEATURES_zero="$($ECHO $($PRINTF '%s\n' $JVM_FEATURES_zero | $SORT -u))"
-  JVM_FEATURES_zeroshark="$($ECHO $($PRINTF '%s\n' $JVM_FEATURES_zeroshark | $SORT -u))"
   JVM_FEATURES_custom="$($ECHO $($PRINTF '%s\n' $JVM_FEATURES_custom | $SORT -u))"
 
   # Validate features
--- a/make/autoconf/hotspot.m4	Fri Nov 24 17:19:47 2017 +0000
+++ b/make/autoconf/hotspot.m4	Mon Nov 27 17:04:45 2017 +0000
@@ -393,7 +393,7 @@
   NON_MINIMAL_FEATURES="$NON_MINIMAL_FEATURES jvmti vm-structs jni-check services management all-gcs nmt"
   if test "x$ENABLE_CDS" = "xtrue"; then
     NON_MINIMAL_FEATURES="$NON_MINIMAL_FEATURES cds"
-  fi                                            
+  fi
 
   # Enable features depending on variant.
   JVM_FEATURES_server="compiler1 compiler2 $NON_MINIMAL_FEATURES $JVM_FEATURES $JVM_FEATURES_jvmci $JVM_FEATURES_aot $JVM_FEATURES_graal"
@@ -476,7 +476,7 @@
 AC_DEFUN_ONCE([HOTSPOT_ENABLE_DISABLE_GTEST],
 [
   AC_ARG_ENABLE([hotspot-gtest], [AS_HELP_STRING([--disable-hotspot-gtest],
-      [Disables building of the Hotspot unit tests])])
+      [Disables building of the Hotspot unit tests @<:@enabled@:>@])])
 
   if test -e "${TOPDIR}/test/hotspot/gtest"; then
     GTEST_DIR_EXISTS="true"
--- a/make/common/FindTests.gmk	Fri Nov 24 17:19:47 2017 +0000
+++ b/make/common/FindTests.gmk	Mon Nov 27 17:04:45 2017 +0000
@@ -29,6 +29,9 @@
 # Hook to include the corresponding custom file, if present.
 $(eval $(call IncludeCustomExtension, common/FindTests.gmk))
 
+# TEST_BASEDIRS might have been set by a custom extension
+TEST_BASEDIRS += $(TOPDIR)/test $(TOPDIR)
+
 # JTREG_TESTROOTS might have been set by a custom extension
 JTREG_TESTROOTS += $(addprefix $(TOPDIR)/test/, hotspot/jtreg jdk langtools nashorn jaxp)
 
--- a/make/common/Modules.gmk	Fri Nov 24 17:19:47 2017 +0000
+++ b/make/common/Modules.gmk	Mon Nov 27 17:04:45 2017 +0000
@@ -328,8 +328,9 @@
 	      $(NAWK) -v MODULE=$(call GetModuleNameFromModuleInfo, $m) '\
 	          BEGIN      { if (MODULE != "java.base") printf(" java.base"); } \
 	          /^ *requires/ { sub(/;/, ""); \
-	                          sub(/requires/, ""); \
-	                          sub(/transitive/, ""); \
+	                          sub(/requires /, " "); \
+	                          sub(/ static /, " "); \
+	                          sub(/ transitive /, " "); \
 	                          sub(/\/\/.*/, ""); \
 	                          sub(/\/\*.*\*\//, ""); \
 	                          gsub(/^ +\*.*/, ""); \
--- a/make/conf/jib-profiles.js	Fri Nov 24 17:19:47 2017 +0000
+++ b/make/conf/jib-profiles.js	Mon Nov 27 17:04:45 2017 +0000
@@ -203,7 +203,7 @@
     data.src_bundle_excludes = "./build webrev* */webrev* */*/webrev* */*/*/webrev* .hg */.hg */*/.hg */*/*/.hg";
     // Include list to use when creating a minimal jib source bundle which
     // contains just the jib configuration files.
-    data.conf_bundle_includes = "*/conf/jib-profiles.* common/autoconf/version-numbers"
+    data.conf_bundle_includes = "*/conf/jib-profiles.* make/autoconf/version-numbers"
 
     // Define some common values
     var common = getJibProfilesCommon(input, data);
@@ -1043,7 +1043,7 @@
 
 /**
  * Constructs the numeric version string from reading the
- * common/autoconf/version-numbers file and removing all trailing ".0".
+ * make/autoconf/version-numbers file and removing all trailing ".0".
  *
  * @param major Override major version
  * @param minor Override minor version
@@ -1080,17 +1080,17 @@
     return args;
 }
 
-// Properties representation of the common/autoconf/version-numbers file. Lazily
+// Properties representation of the make/autoconf/version-numbers file. Lazily
 // initiated by the function below.
 var version_numbers;
 
 /**
- * Read the common/autoconf/version-numbers file into a Properties object.
+ * Read the make/autoconf/version-numbers file into a Properties object.
  *
  * @returns {java.utilProperties}
  */
 var getVersionNumbers = function () {
-    // Read version information from common/autoconf/version-numbers
+    // Read version information from make/autoconf/version-numbers
     if (version_numbers == null) {
         version_numbers = new java.util.Properties();
         var stream = new java.io.FileInputStream(__DIR__ + "/../autoconf/version-numbers");
--- a/make/data/lsrdata/language-subtag-registry.txt	Fri Nov 24 17:19:47 2017 +0000
+++ b/make/data/lsrdata/language-subtag-registry.txt	Mon Nov 27 17:04:45 2017 +0000
@@ -1,4 +1,4 @@
-File-Date: 2016-02-10
+File-Date: 2017-08-15
 %%
 Type: language
 Subtag: aa
@@ -106,6 +106,7 @@
 Type: language
 Subtag: bn
 Description: Bengali
+Description: Bangla
 Added: 2005-10-16
 Suppress-Script: Beng
 %%
@@ -792,6 +793,7 @@
 Type: language
 Subtag: or
 Description: Oriya (macrolanguage)
+Description: Odia (macrolanguage)
 Added: 2005-10-16
 Suppress-Script: Orya
 Scope: macrolanguage
@@ -4107,7 +4109,7 @@
 %%
 Type: language
 Subtag: bcg
-Description: Baga Binari
+Description: Baga Pokur
 Added: 2009-07-29
 %%
 Type: language
@@ -4641,6 +4643,8 @@
 Subtag: bgm
 Description: Baga Mboteni
 Added: 2009-07-29
+Deprecated: 2016-05-30
+Preferred-Value: bcg
 %%
 Type: language
 Subtag: bgn
@@ -5330,6 +5334,7 @@
 %%
 Type: language
 Subtag: blv
+Description: Kibala
 Description: Bolo
 Added: 2009-07-29
 %%
@@ -5380,7 +5385,7 @@
 %%
 Type: language
 Subtag: bmf
-Description: Bom
+Description: Bom-Kim
 Added: 2009-07-29
 %%
 Type: language
@@ -6281,6 +6286,7 @@
 Subtag: btl
 Description: Bhatola
 Added: 2009-07-29
+Deprecated: 2016-05-30
 %%
 Type: language
 Subtag: btm
@@ -7268,6 +7274,7 @@
 Subtag: cbe
 Description: Chipiajes
 Added: 2009-07-29
+Deprecated: 2016-05-30
 %%
 Type: language
 Subtag: cbg
@@ -7278,6 +7285,7 @@
 Subtag: cbh
 Description: Cagua
 Added: 2009-07-29
+Deprecated: 2016-05-30
 %%
 Type: language
 Subtag: cbi
@@ -8071,6 +8079,7 @@
 %%
 Type: language
 Subtag: cnh
+Description: Hakha Chin
 Description: Haka Chin
 Added: 2009-07-29
 %%
@@ -8230,6 +8239,8 @@
 Subtag: coy
 Description: Coyaima
 Added: 2009-07-29
+Deprecated: 2016-05-30
+Preferred-Value: pij
 %%
 Type: language
 Subtag: coz
@@ -8320,6 +8331,8 @@
 Subtag: cqu
 Description: Chilean Quechua
 Added: 2009-07-29
+Deprecated: 2016-05-30
+Preferred-Value: quh
 Macrolanguage: qu
 %%
 Type: language
@@ -8666,6 +8679,7 @@
 %%
 Type: language
 Subtag: cug
+Description: Chungmboko
 Description: Cung
 Added: 2009-07-29
 %%
@@ -8700,6 +8714,7 @@
 Subtag: cum
 Description: Cumeral
 Added: 2009-07-29
+Deprecated: 2016-05-30
 %%
 Type: language
 Subtag: cuo
@@ -9320,6 +9335,7 @@
 %%
 Type: language
 Subtag: dhg
+Description: Dhangu-Djangu
 Description: Dhangu
 Description: Djangu
 Added: 2009-07-29
@@ -9958,7 +9974,7 @@
 %%
 Type: language
 Subtag: dri
-Description: C'lela
+Description: C'Lela
 Added: 2009-07-29
 %%
 Type: language
@@ -10090,12 +10106,18 @@
 Added: 2009-07-29
 %%
 Type: language
+Subtag: dtn
+Description: Daatsʼíin
+Added: 2016-05-30
+%%
+Type: language
 Subtag: dto
 Description: Tommo So Dogon
 Added: 2012-08-12
 %%
 Type: language
 Subtag: dtp
+Description: Kadazan Dusun
 Description: Central Dusun
 Added: 2009-07-29
 %%
@@ -10176,6 +10198,8 @@
 Subtag: duj
 Description: Dhuwal
 Added: 2009-07-29
+Deprecated: 2016-05-30
+Comments: see dwu, dwy
 %%
 Type: language
 Subtag: duk
@@ -10250,7 +10274,7 @@
 %%
 Type: language
 Subtag: duz
-Description: Duli
+Description: Duli-Gey
 Added: 2009-07-29
 %%
 Type: language
@@ -10281,11 +10305,21 @@
 Added: 2009-07-29
 %%
 Type: language
+Subtag: dwu
+Description: Dhuwal
+Added: 2016-05-30
+%%
+Type: language
 Subtag: dww
 Description: Dawawa
 Added: 2009-07-29
 %%
 Type: language
+Subtag: dwy
+Description: Dhuwaya
+Added: 2016-05-30
+%%
+Type: language
 Subtag: dya
 Description: Dyan
 Added: 2009-07-29
@@ -10818,6 +10852,12 @@
 Added: 2009-07-29
 %%
 Type: language
+Subtag: esg
+Description: Aheri Gondi
+Added: 2016-05-30
+Macrolanguage: gon
+%%
+Type: language
 Subtag: esh
 Description: Eshtehardi
 Added: 2009-07-29
@@ -11214,6 +11254,11 @@
 Added: 2009-07-29
 %%
 Type: language
+Subtag: fnb
+Description: Fanbak
+Added: 2016-05-30
+%%
+Type: language
 Subtag: fng
 Description: Fanagalo
 Added: 2009-07-29
@@ -11898,7 +11943,7 @@
 %%
 Type: language
 Subtag: gek
-Description: Yiwom
+Description: Ywom
 Added: 2009-07-29
 %%
 Type: language
@@ -12003,12 +12048,15 @@
 Subtag: ggn
 Description: Eastern Gurung
 Added: 2009-07-29
+Deprecated: 2016-05-30
+Preferred-Value: gvr
 %%
 Type: language
 Subtag: ggo
 Description: Southern Gondi
 Added: 2009-07-29
-Macrolanguage: gon
+Deprecated: 2016-05-30
+Comments: see esg, wsg
 %%
 Type: language
 Subtag: ggr
@@ -12110,6 +12158,12 @@
 Added: 2009-07-29
 %%
 Type: language
+Subtag: gie
+Description: Gaɓogbo
+Description: Guébie
+Added: 2017-02-23
+%%
+Type: language
 Subtag: gig
 Description: Goaria
 Added: 2009-07-29
@@ -12212,6 +12266,11 @@
 Added: 2009-07-29
 %%
 Type: language
+Subtag: gjr
+Description: Gurindji Kriol
+Added: 2016-05-30
+%%
+Type: language
 Subtag: gju
 Description: Gujari
 Added: 2009-07-29
@@ -12791,6 +12850,7 @@
 %%
 Type: language
 Subtag: gsn
+Description: Nema
 Description: Gusan
 Added: 2009-07-29
 %%
@@ -12942,6 +13002,8 @@
 Subtag: guv
 Description: Gey
 Added: 2009-07-29
+Deprecated: 2016-05-30
+Preferred-Value: duz
 %%
 Type: language
 Subtag: guw
@@ -13011,7 +13073,7 @@
 %%
 Type: language
 Subtag: gvr
-Description: Western Gurung
+Description: Gurung
 Added: 2009-07-29
 %%
 Type: language
@@ -14195,6 +14257,7 @@
 Subtag: iap
 Description: Iapama
 Added: 2009-07-29
+Deprecated: 2016-05-30
 %%
 Type: language
 Subtag: iar
@@ -14227,6 +14290,11 @@
 Added: 2009-07-29
 %%
 Type: language
+Subtag: ibh
+Description: Bih
+Added: 2017-02-23
+%%
+Type: language
 Subtag: ibi
 Description: Ibilo
 Added: 2009-07-29
@@ -14581,6 +14649,13 @@
 Subtag: ill
 Description: Iranun
 Added: 2009-07-29
+Deprecated: 2016-05-30
+Comments: see ilm, ilp
+%%
+Type: language
+Subtag: ilm
+Description: Iranun (Malaysia)
+Added: 2016-05-30
 %%
 Type: language
 Subtag: ilo
@@ -14588,6 +14663,11 @@
 Added: 2005-10-16
 %%
 Type: language
+Subtag: ilp
+Description: Iranun (Philippines)
+Added: 2016-05-30
+%%
+Type: language
 Subtag: ils
 Description: International Sign
 Added: 2009-07-29
@@ -14901,6 +14981,11 @@
 Scope: collection
 %%
 Type: language
+Subtag: itd
+Description: Southern Tidung
+Added: 2016-05-30
+%%
+Type: language
 Subtag: ite
 Description: Itene
 Added: 2009-07-29
@@ -15252,6 +15337,8 @@
 Subtag: jeg
 Description: Jeng
 Added: 2009-07-29
+Deprecated: 2017-02-23
+Preferred-Value: oyb
 %%
 Type: language
 Subtag: jeh
@@ -15416,6 +15503,11 @@
 Added: 2012-08-12
 %%
 Type: language
+Subtag: jka
+Description: Kaera
+Added: 2016-05-30
+%%
+Type: language
 Subtag: jkm
 Description: Mobwa Karen
 Added: 2012-08-12
@@ -15796,6 +15888,7 @@
 %%
 Type: language
 Subtag: kak
+Description: Kalanguya
 Description: Kayapa Kallahan
 Added: 2009-07-29
 %%
@@ -16450,7 +16543,8 @@
 %%
 Type: language
 Subtag: kfr
-Description: Kachchi
+Description: Kachhi
+Description: Kutchi
 Added: 2009-07-29
 %%
 Type: language
@@ -16507,11 +16601,15 @@
 Subtag: kgc
 Description: Kasseng
 Added: 2009-07-29
+Deprecated: 2016-05-30
+Preferred-Value: tdf
 %%
 Type: language
 Subtag: kgd
 Description: Kataang
 Added: 2009-07-29
+Deprecated: 2017-02-23
+Comments: see ncq, sct
 %%
 Type: language
 Subtag: kge
@@ -17238,6 +17336,7 @@
 %%
 Type: language
 Subtag: klw
+Description: Tado
 Description: Lindu
 Added: 2009-07-29
 %%
@@ -17621,6 +17720,7 @@
 Subtag: kox
 Description: Coxima
 Added: 2009-07-29
+Deprecated: 2016-05-30
 %%
 Type: language
 Subtag: koy
@@ -17955,6 +18055,8 @@
 Subtag: krm
 Description: Krim
 Added: 2009-07-29
+Deprecated: 2017-02-23
+Preferred-Value: bmf
 %%
 Type: language
 Subtag: krn
@@ -17974,7 +18076,7 @@
 %%
 Type: language
 Subtag: krr
-Description: Kru'ng 2
+Description: Krung
 Added: 2009-07-29
 %%
 Type: language
@@ -18238,6 +18340,8 @@
 Subtag: ktr
 Description: Kota Marudu Tinagas
 Added: 2009-07-29
+Deprecated: 2016-05-30
+Preferred-Value: dtp
 %%
 Type: language
 Subtag: kts
@@ -18278,6 +18382,7 @@
 Subtag: ktz
 Description: Ju/'hoan
 Description: Juǀʼhoan
+Description: Juǀʼhoansi
 Added: 2009-07-29
 %%
 Type: language
@@ -18496,6 +18601,8 @@
 Subtag: kvs
 Description: Kunggara
 Added: 2009-07-29
+Deprecated: 2016-05-30
+Preferred-Value: gdj
 %%
 Type: language
 Subtag: kvt
@@ -18979,6 +19086,8 @@
 Subtag: kzj
 Description: Coastal Kadazan
 Added: 2009-07-29
+Deprecated: 2016-05-30
+Preferred-Value: dtp
 %%
 Type: language
 Subtag: kzk
@@ -19029,6 +19138,8 @@
 Subtag: kzt
 Description: Tambunan Dusun
 Added: 2009-07-29
+Deprecated: 2016-05-30
+Preferred-Value: dtp
 %%
 Type: language
 Subtag: kzu
@@ -19306,6 +19417,7 @@
 Type: language
 Subtag: lce
 Description: Loncong
+Description: Sekak
 Added: 2009-07-29
 Macrolanguage: ms
 %%
@@ -19602,6 +19714,7 @@
 %%
 Type: language
 Subtag: lgn
+Description: T'apo
 Description: Opuuo
 Added: 2009-07-29
 %%
@@ -20320,7 +20433,7 @@
 %%
 Type: language
 Subtag: lou
-Description: Louisiana Creole French
+Description: Louisiana Creole
 Added: 2009-07-29
 %%
 Type: language
@@ -20532,6 +20645,11 @@
 Macrolanguage: lv
 %%
 Type: language
+Subtag: lth
+Description: Thur
+Added: 2017-02-23
+%%
+Type: language
 Subtag: lti
 Description: Leti (Indonesia)
 Added: 2009-07-29
@@ -21926,6 +22044,11 @@
 Deprecated: 2011-08-16
 %%
 Type: language
+Subtag: mjb
+Description: Makalero
+Added: 2016-05-30
+%%
+Type: language
 Subtag: mjc
 Description: San Juan Colorado Mixtec
 Added: 2009-07-29
@@ -24093,6 +24216,8 @@
 Subtag: nad
 Description: Nijadali
 Added: 2009-07-29
+Deprecated: 2016-05-30
+Preferred-Value: xny
 %%
 Type: language
 Subtag: nae
@@ -24404,6 +24529,11 @@
 Added: 2009-07-29
 %%
 Type: language
+Subtag: ncq
+Description: Northern Katang
+Added: 2017-02-23
+%%
+Type: language
 Subtag: ncr
 Description: Ncane
 Added: 2009-07-29
@@ -24802,6 +24932,7 @@
 %%
 Type: language
 Subtag: ngt
+Description: Kriang
 Description: Ngeq
 Added: 2009-07-29
 %%
@@ -25810,6 +25941,11 @@
 Added: 2009-07-29
 %%
 Type: language
+Subtag: npx
+Description: Noipx
+Added: 2017-02-23
+%%
+Type: language
 Subtag: npy
 Description: Napu
 Added: 2009-07-29
@@ -25825,6 +25961,11 @@
 Added: 2009-07-29
 %%
 Type: language
+Subtag: nql
+Description: Ngendelengo
+Added: 2017-02-23
+%%
+Type: language
 Subtag: nqm
 Description: Ndom
 Added: 2009-07-29
@@ -26062,6 +26203,11 @@
 Added: 2009-07-29
 %%
 Type: language
+Subtag: ntd
+Description: Northern Tidung
+Added: 2016-05-30
+%%
+Type: language
 Subtag: nte
 Description: Nathembo
 Added: 2009-07-29
@@ -26110,6 +26256,8 @@
 Subtag: nts
 Description: Natagaimas
 Added: 2009-07-29
+Deprecated: 2016-05-30
+Preferred-Value: pij
 %%
 Type: language
 Subtag: ntu
@@ -26918,6 +27066,11 @@
 Added: 2014-02-28
 %%
 Type: language
+Subtag: olu
+Description: Kuvale
+Added: 2016-05-30
+%%
+Type: language
 Subtag: oma
 Description: Omaha-Ponca
 Added: 2009-07-29
@@ -26936,6 +27089,7 @@
 Subtag: ome
 Description: Omejes
 Added: 2009-07-29
+Deprecated: 2016-05-30
 %%
 Type: language
 Subtag: omg
@@ -27219,6 +27373,7 @@
 %%
 Type: language
 Subtag: ory
+Description: Odia (individual language)
 Description: Oriya (individual language)
 Added: 2012-08-12
 Macrolanguage: or
@@ -27398,6 +27553,12 @@
 Preferred-Value: vaj
 %%
 Type: language
+Subtag: ovd
+Description: Elfdalian
+Description: Övdalian
+Added: 2016-06-16
+%%
+Type: language
 Subtag: owi
 Description: Owiniga
 Added: 2009-07-29
@@ -27941,6 +28102,11 @@
 Deprecated: 2012-08-12
 %%
 Type: language
+Subtag: pgz
+Description: Papua New Guinean Sign Language
+Added: 2016-05-30
+%%
+Type: language
 Subtag: pha
 Description: Pa-Hng
 Added: 2009-07-29
@@ -28343,6 +28509,8 @@
 Subtag: pmc
 Description: Palumata
 Added: 2009-07-29
+Deprecated: 2016-05-30
+Preferred-Value: huw
 %%
 Type: language
 Subtag: pmd
@@ -28580,6 +28748,7 @@
 Subtag: pod
 Description: Ponares
 Added: 2009-07-29
+Deprecated: 2016-05-30
 %%
 Type: language
 Subtag: poe
@@ -28676,6 +28845,8 @@
 Subtag: ppa
 Description: Pao
 Added: 2009-07-29
+Deprecated: 2016-05-30
+Preferred-Value: bfy
 %%
 Type: language
 Subtag: ppe
@@ -28777,6 +28948,7 @@
 Subtag: prb
 Description: Lua'
 Added: 2009-07-29
+Deprecated: 2017-02-23
 %%
 Type: language
 Subtag: prc
@@ -28885,6 +29057,8 @@
 Subtag: pry
 Description: Pray 3
 Added: 2009-07-29
+Deprecated: 2016-05-30
+Preferred-Value: prt
 %%
 Type: language
 Subtag: prz
@@ -29104,6 +29278,7 @@
 Subtag: puk
 Description: Pu Ko
 Added: 2009-07-29
+Deprecated: 2017-02-23
 %%
 Type: language
 Subtag: pum
@@ -29874,6 +30049,7 @@
 Subtag: rie
 Description: Rien
 Added: 2009-07-29
+Deprecated: 2017-02-23
 %%
 Type: language
 Subtag: rif
@@ -30099,6 +30275,7 @@
 Subtag: rna
 Description: Runa
 Added: 2009-07-29
+Deprecated: 2016-05-30
 %%
 Type: language
 Subtag: rnd
@@ -30241,6 +30418,7 @@
 Subtag: rsi
 Description: Rennellese Sign Language
 Added: 2009-07-29
+Deprecated: 2017-02-23
 %%
 Type: language
 Subtag: rsl
@@ -30248,6 +30426,11 @@
 Added: 2009-07-29
 %%
 Type: language
+Subtag: rsm
+Description: Miriwoong Sign Language
+Added: 2016-05-30
+%%
+Type: language
 Subtag: rtc
 Description: Rungtu Chin
 Added: 2012-08-12
@@ -30401,6 +30584,11 @@
 Added: 2009-07-29
 %%
 Type: language
+Subtag: rzh
+Description: Rāziḥī
+Added: 2016-05-30
+%%
+Type: language
 Subtag: saa
 Description: Saba
 Added: 2009-07-29
@@ -30729,6 +30917,11 @@
 Macrolanguage: den
 %%
 Type: language
+Subtag: sct
+Description: Southern Katang
+Added: 2017-02-23
+%%
+Type: language
 Subtag: scu
 Description: Shumcho
 Added: 2009-07-29
@@ -31515,6 +31708,8 @@
 Subtag: skk
 Description: Sok
 Added: 2009-07-29
+Deprecated: 2017-02-23
+Preferred-Value: oyb
 %%
 Type: language
 Subtag: skm
@@ -31849,6 +32044,7 @@
 Subtag: snh
 Description: Shinabo
 Added: 2009-07-29
+Deprecated: 2017-02-23
 %%
 Type: language
 Subtag: sni
@@ -32710,6 +32906,7 @@
 Subtag: svr
 Description: Savara
 Added: 2009-07-29
+Deprecated: 2016-05-30
 %%
 Type: language
 Subtag: svs
@@ -33023,6 +33220,11 @@
 Added: 2009-07-29
 %%
 Type: language
+Subtag: szs
+Description: Solomon Islands Sign Language
+Added: 2017-02-23
+%%
+Type: language
 Subtag: szv
 Description: Isu (Fako Division)
 Added: 2009-07-29
@@ -33458,6 +33660,11 @@
 Added: 2009-07-29
 %%
 Type: language
+Subtag: tdm
+Description: Taruma
+Added: 2016-05-30
+%%
+Type: language
 Subtag: tdn
 Description: Tondano
 Added: 2009-07-29
@@ -33491,6 +33698,8 @@
 Subtag: tdu
 Description: Tempasuk Dusun
 Added: 2009-07-29
+Deprecated: 2016-05-30
+Preferred-Value: dtp
 %%
 Type: language
 Subtag: tdv
@@ -33771,6 +33980,8 @@
 Subtag: thc
 Description: Tai Hang Tong
 Added: 2009-07-29
+Deprecated: 2016-05-30
+Preferred-Value: tpo
 %%
 Type: language
 Subtag: thd
@@ -33891,6 +34102,8 @@
 Subtag: tid
 Description: Tidong
 Added: 2009-07-29
+Deprecated: 2016-05-30
+Comments: see itd, ntd
 %%
 Type: language
 Subtag: tie
@@ -34246,6 +34459,7 @@
 %%
 Type: language
 Subtag: tlt
+Description: Sou Nama
 Description: Teluti
 Added: 2009-07-29
 %%
@@ -34358,6 +34572,8 @@
 Subtag: tmp
 Description: Tai Mène
 Added: 2009-07-29
+Deprecated: 2016-05-30
+Preferred-Value: tyj
 %%
 Type: language
 Subtag: tmq
@@ -34429,6 +34645,8 @@
 Subtag: tne
 Description: Tinoc Kallahan
 Added: 2009-07-29
+Deprecated: 2016-05-30
+Preferred-Value: kak
 %%
 Type: language
 Subtag: tnf
@@ -34529,7 +34747,7 @@
 %%
 Type: language
 Subtag: tnz
-Description: Tonga (Thailand)
+Description: Ten'edn
 Added: 2009-07-29
 %%
 Type: language
@@ -34551,6 +34769,7 @@
 Subtag: toe
 Description: Tomedes
 Added: 2009-07-29
+Deprecated: 2016-05-30
 %%
 Type: language
 Subtag: tof
@@ -35596,6 +35815,7 @@
 Type: language
 Subtag: tyj
 Description: Tai Do
+Description: Tai Yo
 Added: 2009-07-29
 %%
 Type: language
@@ -35855,6 +36075,11 @@
 Added: 2009-07-29
 %%
 Type: language
+Subtag: ukk
+Description: Muak Sa-aak
+Added: 2017-02-23
+%%
+Type: language
 Subtag: ukl
 Description: Ukrainian Sign Language
 Added: 2009-07-29
@@ -36989,6 +37214,11 @@
 Macrolanguage: raj
 %%
 Type: language
+Subtag: wbs
+Description: West Bengal Sign Language
+Added: 2017-02-23
+%%
+Type: language
 Subtag: wbt
 Description: Wanman
 Added: 2009-07-29
@@ -37169,6 +37399,7 @@
 %%
 Type: language
 Subtag: wha
+Description: Sou Upaa
 Description: Manusela
 Added: 2009-07-29
 %%
@@ -37739,6 +37970,12 @@
 Added: 2009-07-29
 %%
 Type: language
+Subtag: wsg
+Description: Adilabad Gondi
+Added: 2016-05-30
+Macrolanguage: gon
+%%
+Type: language
 Subtag: wsi
 Description: Wusi
 Added: 2009-07-29
@@ -37971,6 +38208,11 @@
 Added: 2014-02-28
 %%
 Type: language
+Subtag: xak
+Description: Máku
+Added: 2016-05-30
+%%
+Type: language
 Subtag: xal
 Description: Kalmyk
 Description: Oirat
@@ -38041,6 +38283,8 @@
 Subtag: xba
 Description: Kamba (Brazil)
 Added: 2009-07-29
+Deprecated: 2016-05-30
+Preferred-Value: cax
 %%
 Type: language
 Subtag: xbb
@@ -38111,6 +38355,7 @@
 Subtag: xbx
 Description: Kabixí
 Added: 2009-07-29
+Deprecated: 2016-05-30
 %%
 Type: language
 Subtag: xby
@@ -38214,6 +38459,11 @@
 Added: 2009-07-29
 %%
 Type: language
+Subtag: xdo
+Description: Kwandu
+Added: 2017-02-23
+%%
+Type: language
 Subtag: xdy
 Description: Malayic Dayak
 Added: 2009-07-29
@@ -38408,6 +38658,7 @@
 Subtag: xip
 Description: Xipináwa
 Added: 2009-07-29
+Deprecated: 2016-05-30
 %%
 Type: language
 Subtag: xir
@@ -38478,6 +38729,8 @@
 Subtag: xkh
 Description: Karahawyana
 Added: 2009-07-29
+Deprecated: 2016-05-30
+Preferred-Value: waw
 %%
 Type: language
 Subtag: xki
@@ -39328,6 +39581,7 @@
 Type: language
 Subtag: xuu
 Description: Kxoe
+Description: Khwedam
 Added: 2009-07-29
 %%
 Type: language
@@ -40394,6 +40648,7 @@
 Subtag: yri
 Description: Yarí
 Added: 2009-07-29
+Deprecated: 2016-05-30
 %%
 Type: language
 Subtag: yrk
@@ -40416,6 +40671,11 @@
 Added: 2009-07-29
 %%
 Type: language
+Subtag: yro
+Description: Yaroamë
+Added: 2016-05-30
+%%
+Type: language
 Subtag: yrs
 Description: Yarsun
 Added: 2009-07-29
@@ -40740,6 +41000,7 @@
 %%
 Type: language
 Subtag: zab
+Description: Western Tlacolula Valley Zapotec
 Description: San Juan Guelavía Zapotec
 Added: 2009-07-29
 Macrolanguage: zap
@@ -42633,6 +42894,7 @@
 Type: extlang
 Subtag: lce
 Description: Loncong
+Description: Sekak
 Added: 2009-07-29
 Preferred-Value: lce
 Prefix: ms
@@ -42953,6 +43215,13 @@
 Macrolanguage: ar
 %%
 Type: extlang
+Subtag: pgz
+Description: Papua New Guinean Sign Language
+Added: 2016-05-30
+Preferred-Value: pgz
+Prefix: sgn
+%%
+Type: extlang
 Subtag: pks
 Description: Pakistan Sign Language
 Added: 2009-07-29
@@ -43049,7 +43318,7 @@
 Subtag: rsi
 Description: Rennellese Sign Language
 Added: 2009-07-29
-Preferred-Value: rsi
+Deprecated: 2017-02-23
 Prefix: sgn
 %%
 Type: extlang
@@ -43060,6 +43329,13 @@
 Prefix: sgn
 %%
 Type: extlang
+Subtag: rsm
+Description: Miriwoong Sign Language
+Added: 2016-05-30
+Preferred-Value: rsm
+Prefix: sgn
+%%
+Type: extlang
 Subtag: sdl
 Description: Saudi Arabian Sign Language
 Added: 2009-07-29
@@ -43192,6 +43468,13 @@
 Prefix: sgn
 %%
 Type: extlang
+Subtag: szs
+Description: Solomon Islands Sign Language
+Added: 2017-02-23
+Preferred-Value: szs
+Prefix: sgn
+%%
+Type: extlang
 Subtag: tmw
 Description: Temuan
 Added: 2009-07-29
@@ -43342,6 +43625,13 @@
 Prefix: sgn
 %%
 Type: extlang
+Subtag: wbs
+Description: West Bengal Sign Language
+Added: 2017-02-23
+Preferred-Value: wbs
+Prefix: sgn
+%%
+Type: extlang
 Subtag: wuu
 Description: Wu Chinese
 Added: 2009-07-29
@@ -43522,6 +43812,7 @@
 Type: script
 Subtag: Beng
 Description: Bengali
+Description: Bangla
 Added: 2005-10-16
 %%
 Type: script
@@ -43595,8 +43886,13 @@
 Added: 2005-10-16
 %%
 Type: script
+Subtag: Cpmn
+Description: Cypro-Minoan
+Added: 2017-08-13
+%%
+Type: script
 Subtag: Cprt
-Description: Cypriot
+Description: Cypriot syllabary
 Added: 2005-10-16
 %%
 Type: script
@@ -43616,6 +43912,11 @@
 Added: 2005-10-16
 %%
 Type: script
+Subtag: Dogr
+Description: Dogra
+Added: 2017-01-13
+%%
+Type: script
 Subtag: Dsrt
 Description: Deseret
 Description: Mormon
@@ -43661,7 +43962,7 @@
 %%
 Type: script
 Subtag: Geor
-Description: Georgian (Mkhedruli)
+Description: Georgian (Mkhedruli and Mtavruli)
 Added: 2005-10-16
 %%
 Type: script
@@ -43670,6 +43971,16 @@
 Added: 2005-10-16
 %%
 Type: script
+Subtag: Gong
+Description: Gunjala Gondi
+Added: 2017-01-13
+%%
+Type: script
+Subtag: Gonm
+Description: Masaram Gondi
+Added: 2017-01-13
+%%
+Type: script
 Subtag: Goth
 Description: Gothic
 Added: 2005-10-16
@@ -43758,6 +44069,11 @@
 Added: 2005-10-16
 %%
 Type: script
+Subtag: Hmnp
+Description: Nyiakeng Puachue Hmong
+Added: 2017-08-13
+%%
+Type: script
 Subtag: Hrkt
 Description: Japanese syllabaries (alias for Hiragana + Katakana)
 Added: 2005-10-16
@@ -43933,6 +44249,11 @@
 Added: 2012-11-01
 %%
 Type: script
+Subtag: Maka
+Description: Makasar
+Added: 2017-01-13
+%%
+Type: script
 Subtag: Mand
 Description: Mandaic
 Description: Mandaean
@@ -43954,6 +44275,13 @@
 Added: 2005-10-16
 %%
 Type: script
+Subtag: Medf
+Description: Medefaidrin
+Description: Oberi Okaime
+Description: Oberi Ɔkaimɛ
+Added: 2017-01-13
+%%
+Type: script
 Subtag: Mend
 Description: Mende Kikakui
 Added: 2010-04-10
@@ -44036,10 +44364,18 @@
 Added: 2016-01-04
 %%
 Type: script
+Subtag: Nkdb
+Description: Naxi Dongba
+Description: na²¹ɕi³³ to³³ba²¹
+Description: Nakhi Tomba
+Added: 2017-08-13
+%%
+Type: script
 Subtag: Nkgb
+Description: Naxi Geba
+Description: na²¹ɕi³³ gʌ²¹ba²¹
+Description: 'Na-'Khi ²Ggŏ-¹baw
 Description: Nakhi Geba
-Description: 'Na-'Khi ²Ggŏ-¹baw
-Description: Naxi Geba
 Added: 2009-03-13
 %%
 Type: script
@@ -44075,6 +44411,7 @@
 Type: script
 Subtag: Orya
 Description: Oriya
+Description: Odia
 Added: 2005-10-16
 %%
 Type: script
@@ -44203,6 +44540,11 @@
 Added: 2011-01-07
 %%
 Type: script
+Subtag: Shui
+Description: Shuishu
+Added: 2017-08-13
+%%
+Type: script
 Subtag: Sidd
 Description: Siddham
 Description: Siddhaṃ
@@ -44226,6 +44568,11 @@
 Added: 2011-01-07
 %%
 Type: script
+Subtag: Soyo
+Description: Soyombo
+Added: 2017-01-13
+%%
+Type: script
 Subtag: Sund
 Description: Sundanese
 Added: 2006-07-21
@@ -44357,6 +44704,11 @@
 Added: 2009-12-09
 %%
 Type: script
+Subtag: Wcho
+Description: Wancho
+Added: 2017-08-13
+%%
+Type: script
 Subtag: Wole
 Description: Woleai
 Added: 2011-01-07
@@ -44377,6 +44729,14 @@
 Added: 2005-10-16
 %%
 Type: script
+Subtag: Zanb
+Description: Zanabazar Square
+Description: Zanabazarin Dörböljin Useg
+Description: Xewtee Dörböljin Bicig
+Description: Horizontal Square Script
+Added: 2017-01-13
+%%
+Type: script
 Subtag: Zinh
 Description: Code for inherited script
 Added: 2009-04-03
@@ -44726,6 +45086,7 @@
 %%
 Type: region
 Subtag: CZ
+Description: Czechia
 Description: Czech Republic
 Added: 2005-10-16
 %%
@@ -44817,6 +45178,11 @@
 Added: 2009-07-29
 %%
 Type: region
+Subtag: EZ
+Description: Eurozone
+Added: 2016-07-14
+%%
+Type: region
 Subtag: FI
 Description: Finland
 Added: 2005-10-16
@@ -45675,6 +46041,11 @@
 Added: 2005-10-16
 %%
 Type: region
+Subtag: UN
+Description: United Nations
+Added: 2016-07-14
+%%
+Type: region
 Subtag: US
 Description: United States
 Added: 2005-10-16
@@ -45940,6 +46311,11 @@
 Added: 2005-10-16
 %%
 Type: region
+Subtag: 202
+Description: Sub-Saharan Africa
+Added: 2017-04-18
+%%
+Type: region
 Subtag: 419
 Description: Latin America and the Caribbean
 Added: 2005-10-16
@@ -46020,6 +46396,12 @@
   continuum in Eastern Suriname and Western French Guiana
 %%
 Type: variant
+Subtag: akuapem
+Description: Akuapem Twi
+Added: 2017-06-05
+Prefix: tw
+%%
+Type: variant
 Subtag: ao1990
 Description: Portuguese Language Orthographic Agreement of 1990 (Acordo
   Ortográfico da Língua Portuguesa de 1990)
@@ -46042,6 +46424,13 @@
 Prefix: hy
 %%
 Type: variant
+Subtag: asante
+Description: Asante Twi
+Description: Ashanti Twi
+Added: 2017-06-05
+Prefix: tw
+%%
+Type: variant
 Subtag: baku1926
 Description: Unified Turkic Latin Alphabet (Historical)
 Added: 2007-04-18
@@ -46167,6 +46556,12 @@
 Added: 2006-12-11
 %%
 Type: variant
+Subtag: fonnapa
+Description: North American Phonetic Alphabet
+Description: Americanist Phonetic Notation
+Added: 2016-06-24
+%%
+Type: variant
 Subtag: fonupa
 Description: Uralic Phonetic Alphabet
 Added: 2006-12-11
@@ -46201,6 +46596,13 @@
   including modern usage.
 %%
 Type: variant
+Subtag: hsistemo
+Description: Standard H-system orthographic fallback for spelling
+  Esperanto
+Added: 2017-03-14
+Prefix: eo
+%%
+Type: variant
 Subtag: ijekavsk
 Description: Serbian with Ijekavian pronunciation
 Prefix: sr
@@ -46346,6 +46748,27 @@
 Prefix: en
 %%
 Type: variant
+Subtag: pahawh2
+Description: Pahawh Hmong Second Stage Reduced orthography
+Added: 2017-01-13
+Prefix: mww
+Prefix: hnj
+%%
+Type: variant
+Subtag: pahawh3
+Description: Pahawh Hmong Third Stage Reduced orthography
+Added: 2017-01-13
+Prefix: mww
+Prefix: hnj
+%%
+Type: variant
+Subtag: pahawh4
+Description: Pahawh Hmong Final Version orthography
+Added: 2017-01-13
+Prefix: mww
+Prefix: hnj
+%%
+Type: variant
 Subtag: pamaka
 Description: Pamaka dialect
 Added: 2009-09-05
@@ -46442,6 +46865,14 @@
 Added: 2013-12-10
 %%
 Type: variant
+Subtag: spanglis
+Description: Spanglish
+Added: 2017-02-23
+Prefix: en
+Prefix: es
+Comments: A variety of contact dialects of English and Spanish
+%%
+Type: variant
 Subtag: surmiran
 Description: Surmiran idiom of Romansh
 Added: 2010-06-29
@@ -46533,6 +46964,13 @@
 Added: 2008-10-03
 Prefix: zh-Latn
 %%
+Type: variant
+Subtag: xsistemo
+Description: Standard X-system orthographic fallback for spelling
+  Esperanto
+Added: 2017-03-14
+Prefix: eo
+%%
 Type: grandfathered
 Tag: art-lojban
 Description: Lojban
--- a/make/hotspot/lib/CompileJvm.gmk	Fri Nov 24 17:19:47 2017 +0000
+++ b/make/hotspot/lib/CompileJvm.gmk	Mon Nov 27 17:04:45 2017 +0000
@@ -114,7 +114,7 @@
     #
 
 # These files and directories are always excluded
-JVM_EXCLUDE_FILES += jsig.c args.cc
+JVM_EXCLUDE_FILES += args.cc
 JVM_EXCLUDES += adlc
 
 # Needed by vm_version.cpp
--- a/make/hotspot/lib/CompileLibjsig.gmk	Fri Nov 24 17:19:47 2017 +0000
+++ b/make/hotspot/lib/CompileLibjsig.gmk	Mon Nov 27 17:04:45 2017 +0000
@@ -81,7 +81,7 @@
       $(error Unknown target OS $(OPENJDK_TARGET_OS) in CompileLibjsig.gmk)
     endif
 
-    LIBJSIG_SRC_FILE := $(TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS)/native/libjsig/jsig.c
+    LIBJSIG_SRC_DIR := $(TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS)/native/libjsig
     LIBJSIG_MAPFILE := $(wildcard $(TOPDIR)/make/mapfiles/libjsig/mapfile-vers-$(OPENJDK_TARGET_OS))
     LIBJSIG_OUTPUTDIR := $(HOTSPOT_OUTPUTDIR)/libjsig
 
@@ -91,7 +91,7 @@
 
     $(eval $(call SetupNativeCompilation, BUILD_LIBJSIG, \
         LIBRARY := jsig, \
-        EXTRA_FILES := $(LIBJSIG_SRC_FILE), \
+        SRC := $(LIBJSIG_SRC_DIR), \
         OUTPUT_DIR := $(LIB_OUTPUTDIR), \
         LANG := C, \
         CFLAGS := $(LIBJSIG_CFLAGS) $(LIBJSIG_CPU_FLAGS), \
--- a/make/mapfiles/libawt/mapfile-mawt-vers	Fri Nov 24 17:19:47 2017 +0000
+++ b/make/mapfiles/libawt/mapfile-mawt-vers	Mon Nov 27 17:04:45 2017 +0000
@@ -177,7 +177,6 @@
         Java_sun_java2d_xr_XRBackendNative_setGCMode;
         Java_sun_java2d_xr_XRBackendNative_GCRectanglesNative;
         Java_sun_java2d_xr_XRUtils_initFormatPtrs;
-        Java_sun_java2d_xr_XRBackendNative_renderCompositeTrapezoidsNative;
         XRT_DrawGlyphList;
 
         Java_sun_java2d_opengl_OGLContext_getOGLIdString;
--- a/make/mapfiles/libawt_xawt/mapfile-vers	Fri Nov 24 17:19:47 2017 +0000
+++ b/make/mapfiles/libawt_xawt/mapfile-vers	Mon Nov 27 17:04:45 2017 +0000
@@ -408,7 +408,6 @@
         Java_sun_java2d_xr_XRBackendNative_XRenderCompositeTextNative;
         Java_sun_java2d_xr_XRBackendNative_setGCMode;
         Java_sun_java2d_xr_XRBackendNative_GCRectanglesNative;
-        Java_sun_java2d_xr_XRBackendNative_renderCompositeTrapezoidsNative;
 
         Java_com_sun_java_swing_plaf_gtk_GTKEngine_native_1paint_1arrow;
         Java_com_sun_java_swing_plaf_gtk_GTKEngine_native_1paint_1box;
--- a/make/nashorn/build.xml	Fri Nov 24 17:19:47 2017 +0000
+++ b/make/nashorn/build.xml	Mon Nov 27 17:04:45 2017 +0000
@@ -278,7 +278,7 @@
       <arg value="${javadoc.option}"/>
       <fileset dir="${nashorn.module.src.dir}" includes="**/*.java"/>
       <fileset dir="${dynalink.module.src.dir}" includes="**/*.java"/>
-      <link href="http://docs.oracle.com/javase/8/docs/api/"/>
+      <link offline="true" href="${javadoc.base.url}" packagelistLoc="${javadoc.pkg.list}"/>
     </javadoc>
   </target>
 
@@ -296,7 +296,7 @@
       <arg value="."/>
       <arg value="${javadoc.option}"/>
       <fileset dir="${nashorn.module.src.dir}" includes="jdk/nashorn/api/**/*.java"/>
-      <link href="http://docs.oracle.com/javase/8/docs/api/"/>
+      <link offline="true" href="${javadoc.base.url}" packagelistLoc="${javadoc.pkg.list}"/>
     </javadoc>
   </target>
 
@@ -314,7 +314,7 @@
       <arg value="."/>
       <arg value="${javadoc.option}"/>
       <fileset dir="${dynalink.module.src.dir}" includes="**/*.java"/>
-      <link href="http://docs.oracle.com/javase/8/docs/api/"/>
+      <link offline="true" href="${javadoc.base.url}" packagelistLoc="${javadoc.pkg.list}"/>
     </javadoc>
   </target>
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/make/nashorn/package-list	Mon Nov 27 17:04:45 2017 +0000
@@ -0,0 +1,315 @@
+com.sun.jarsigner
+com.sun.java.accessibility.util
+com.sun.javadoc
+com.sun.jdi
+com.sun.jdi.connect
+com.sun.jdi.connect.spi
+com.sun.jdi.event
+com.sun.jdi.request
+com.sun.management
+com.sun.net.httpserver
+com.sun.net.httpserver.spi
+com.sun.nio.sctp
+com.sun.security.auth
+com.sun.security.auth.callback
+com.sun.security.auth.login
+com.sun.security.auth.module
+com.sun.security.jgss
+com.sun.source.doctree
+com.sun.source.tree
+com.sun.source.util
+com.sun.tools.attach
+com.sun.tools.attach.spi
+com.sun.tools.doclets
+com.sun.tools.doclets.standard
+com.sun.tools.javac
+com.sun.tools.javadoc
+com.sun.tools.jconsole
+java.applet
+java.awt
+java.awt.color
+java.awt.datatransfer
+java.awt.desktop
+java.awt.dnd
+java.awt.event
+java.awt.font
+java.awt.geom
+java.awt.im
+java.awt.im.spi
+java.awt.image
+java.awt.image.renderable
+java.awt.print
+java.beans
+java.beans.beancontext
+java.io
+java.lang
+java.lang.annotation
+java.lang.instrument
+java.lang.invoke
+java.lang.management
+java.lang.module
+java.lang.ref
+java.lang.reflect
+java.math
+java.net
+java.net.spi
+java.nio
+java.nio.channels
+java.nio.channels.spi
+java.nio.charset
+java.nio.charset.spi
+java.nio.file
+java.nio.file.attribute
+java.nio.file.spi
+java.rmi
+java.rmi.activation
+java.rmi.dgc
+java.rmi.registry
+java.rmi.server
+java.security
+java.security.acl
+java.security.cert
+java.security.interfaces
+java.security.spec
+java.sql
+java.text
+java.text.spi
+java.time
+java.time.chrono
+java.time.format
+java.time.temporal
+java.time.zone
+java.util
+java.util.concurrent
+java.util.concurrent.atomic
+java.util.concurrent.locks
+java.util.function
+java.util.jar
+java.util.logging
+java.util.prefs
+java.util.regex
+java.util.spi
+java.util.stream
+java.util.zip
+javafx.animation
+javafx.application
+javafx.beans
+javafx.beans.binding
+javafx.beans.property
+javafx.beans.property.adapter
+javafx.beans.value
+javafx.collections
+javafx.collections.transformation
+javafx.concurrent
+javafx.css
+javafx.css.converter
+javafx.embed.swing
+javafx.event
+javafx.fxml
+javafx.geometry
+javafx.print
+javafx.scene
+javafx.scene.canvas
+javafx.scene.chart
+javafx.scene.control
+javafx.scene.control.cell
+javafx.scene.control.skin
+javafx.scene.effect
+javafx.scene.image
+javafx.scene.input
+javafx.scene.layout
+javafx.scene.media
+javafx.scene.paint
+javafx.scene.shape
+javafx.scene.text
+javafx.scene.transform
+javafx.scene.web
+javafx.stage
+javafx.util
+javafx.util.converter
+javax.accessibility
+javax.activation
+javax.activity
+javax.annotation
+javax.annotation.processing
+javax.crypto
+javax.crypto.interfaces
+javax.crypto.spec
+javax.imageio
+javax.imageio.event
+javax.imageio.metadata
+javax.imageio.plugins.bmp
+javax.imageio.plugins.jpeg
+javax.imageio.plugins.tiff
+javax.imageio.spi
+javax.imageio.stream
+javax.jnlp
+javax.jws
+javax.jws.soap
+javax.lang.model
+javax.lang.model.element
+javax.lang.model.type
+javax.lang.model.util
+javax.management
+javax.management.loading
+javax.management.modelmbean
+javax.management.monitor
+javax.management.openmbean
+javax.management.relation
+javax.management.remote
+javax.management.remote.rmi
+javax.management.timer
+javax.naming
+javax.naming.directory
+javax.naming.event
+javax.naming.ldap
+javax.naming.spi
+javax.net
+javax.net.ssl
+javax.print
+javax.print.attribute
+javax.print.attribute.standard
+javax.print.event
+javax.rmi
+javax.rmi.CORBA
+javax.rmi.ssl
+javax.script
+javax.security.auth
+javax.security.auth.callback
+javax.security.auth.kerberos
+javax.security.auth.login
+javax.security.auth.spi
+javax.security.auth.x500
+javax.security.cert
+javax.security.sasl
+javax.smartcardio
+javax.sound.midi
+javax.sound.midi.spi
+javax.sound.sampled
+javax.sound.sampled.spi
+javax.sql
+javax.sql.rowset
+javax.sql.rowset.serial
+javax.sql.rowset.spi
+javax.swing
+javax.swing.border
+javax.swing.colorchooser
+javax.swing.event
+javax.swing.filechooser
+javax.swing.plaf
+javax.swing.plaf.basic
+javax.swing.plaf.metal
+javax.swing.plaf.multi
+javax.swing.plaf.nimbus
+javax.swing.plaf.synth
+javax.swing.table
+javax.swing.text
+javax.swing.text.html
+javax.swing.text.html.parser
+javax.swing.text.rtf
+javax.swing.tree
+javax.swing.undo
+javax.tools
+javax.transaction
+javax.transaction.xa
+javax.xml
+javax.xml.bind
+javax.xml.bind.annotation
+javax.xml.bind.annotation.adapters
+javax.xml.bind.attachment
+javax.xml.bind.helpers
+javax.xml.bind.util
+javax.xml.catalog
+javax.xml.crypto
+javax.xml.crypto.dom
+javax.xml.crypto.dsig
+javax.xml.crypto.dsig.dom
+javax.xml.crypto.dsig.keyinfo
+javax.xml.crypto.dsig.spec
+javax.xml.datatype
+javax.xml.namespace
+javax.xml.parsers
+javax.xml.soap
+javax.xml.stream
+javax.xml.stream.events
+javax.xml.stream.util
+javax.xml.transform
+javax.xml.transform.dom
+javax.xml.transform.sax
+javax.xml.transform.stax
+javax.xml.transform.stream
+javax.xml.validation
+javax.xml.ws
+javax.xml.ws.handler
+javax.xml.ws.handler.soap
+javax.xml.ws.http
+javax.xml.ws.soap
+javax.xml.ws.spi
+javax.xml.ws.spi.http
+javax.xml.ws.wsaddressing
+javax.xml.xpath
+jdk.dynalink
+jdk.dynalink.beans
+jdk.dynalink.linker
+jdk.dynalink.linker.support
+jdk.dynalink.support
+jdk.incubator.http
+jdk.javadoc.doclet
+jdk.jfr
+jdk.jfr.consumer
+jdk.jshell
+jdk.jshell.execution
+jdk.jshell.spi
+jdk.jshell.tool
+jdk.management.cmm
+jdk.management.jfr
+jdk.management.resource
+jdk.nashorn.api.scripting
+jdk.nashorn.api.tree
+jdk.net
+jdk.packager.services
+jdk.security.jarsigner
+netscape.javascript
+org.ietf.jgss
+org.omg.CORBA
+org.omg.CORBA_2_3
+org.omg.CORBA_2_3.portable
+org.omg.CORBA.DynAnyPackage
+org.omg.CORBA.ORBPackage
+org.omg.CORBA.portable
+org.omg.CORBA.TypeCodePackage
+org.omg.CosNaming
+org.omg.CosNaming.NamingContextExtPackage
+org.omg.CosNaming.NamingContextPackage
+org.omg.Dynamic
+org.omg.DynamicAny
+org.omg.DynamicAny.DynAnyFactoryPackage
+org.omg.DynamicAny.DynAnyPackage
+org.omg.IOP
+org.omg.IOP.CodecFactoryPackage
+org.omg.IOP.CodecPackage
+org.omg.Messaging
+org.omg.PortableInterceptor
+org.omg.PortableInterceptor.ORBInitInfoPackage
+org.omg.PortableServer
+org.omg.PortableServer.CurrentPackage
+org.omg.PortableServer.POAManagerPackage
+org.omg.PortableServer.POAPackage
+org.omg.PortableServer.portable
+org.omg.PortableServer.ServantLocatorPackage
+org.omg.SendingContext
+org.omg.stub.java.rmi
+org.w3c.dom
+org.w3c.dom.bootstrap
+org.w3c.dom.css
+org.w3c.dom.events
+org.w3c.dom.html
+org.w3c.dom.ls
+org.w3c.dom.ranges
+org.w3c.dom.stylesheets
+org.w3c.dom.traversal
+org.w3c.dom.views
+org.w3c.dom.xpath
+org.xml.sax
+org.xml.sax.ext
+org.xml.sax.helpers
--- a/make/nashorn/project.properties	Fri Nov 24 17:19:47 2017 +0000
+++ b/make/nashorn/project.properties	Mon Nov 27 17:04:45 2017 +0000
@@ -33,6 +33,12 @@
 # source and target levels
 build.compiler=modern
 
+jdk.build.dir=build
+nashorn.make.dir=make/nashorn
+
+javadoc.base.url=https://docs.oracle.com/javase/9/docs/api/
+javadoc.pkg.list=make/nashorn
+
 javadoc.option=\
     -tag "implSpec:a:Implementation Requirements:" \
     -tag "implNote:a:Implementation Note:" \
@@ -43,9 +49,6 @@
 nashorn.fullversion=0.1
 nashorn.product.name=Oracle Nashorn
 
-jdk.build.dir=build
-nashorn.make.dir=make/nashorn
-
 # This directory is removed when the project is cleaned:
 build.dir=${jdk.build.dir}/nashorn
 build.classes.dir=${build.dir}/classes
--- a/src/hotspot/cpu/arm/stubGenerator_arm.cpp	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/hotspot/cpu/arm/stubGenerator_arm.cpp	Mon Nov 27 17:04:45 2017 +0000
@@ -2968,7 +2968,9 @@
         CardTableModRefBS* ct = barrier_set_cast<CardTableModRefBS>(bs);
         assert(sizeof(*ct->byte_map_base) == sizeof(jbyte), "adjust this code");
 
-        Label L_cardtable_loop;
+        Label L_cardtable_loop, L_done;
+
+        __ cbz_32(count, L_done); // zero count - nothing to do
 
         __ add_ptr_scaled_int32(count, addr, count, LogBytesPerHeapOop);
         __ sub(count, count, BytesPerHeapOop);                            // last addr
@@ -2987,6 +2989,7 @@
         __ strb(zero, Address(addr, 1, post_indexed));
         __ subs(count, count, 1);
         __ b(L_cardtable_loop, ge);
+        __ BIND(L_done);
       }
       break;
     case BarrierSet::ModRef:
--- a/src/hotspot/cpu/s390/assembler_s390.hpp	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/hotspot/cpu/s390/assembler_s390.hpp	Mon Nov 27 17:04:45 2017 +0000
@@ -582,7 +582,11 @@
 #define LOC_ZOPC    (unsigned long)(0xebL << 40 | 0xf2L)        // z196
 #define LOCG_ZOPC   (unsigned long)(0xebL << 40 | 0xe2L)        // z196
 
-#define LMG_ZOPC    (unsigned long)(235L << 40 | 4L)
+
+// LOAD multiple registers at once
+#define LM_ZOPC     (unsigned  int)(0x98  << 24)
+#define LMY_ZOPC    (unsigned long)(0xebL << 40 | 0x98L)
+#define LMG_ZOPC    (unsigned long)(0xebL << 40 | 0x04L)
 
 #define LE_ZOPC     (unsigned  int)(0x78 << 24)
 #define LEY_ZOPC    (unsigned long)(237L << 40 | 100L)
@@ -613,7 +617,10 @@
 #define STOC_ZOPC   (unsigned long)(0xebL << 40 | 0xf3L)        // z196
 #define STOCG_ZOPC  (unsigned long)(0xebL << 40 | 0xe3L)        // z196
 
-#define STMG_ZOPC   (unsigned long)(235L << 40 | 36L)
+// STORE multiple registers at once
+#define STM_ZOPC    (unsigned  int)(0x90  << 24)
+#define STMY_ZOPC   (unsigned long)(0xebL << 40 | 0x90L)
+#define STMG_ZOPC   (unsigned long)(0xebL << 40 | 0x24L)
 
 #define STE_ZOPC    (unsigned  int)(0x70 << 24)
 #define STEY_ZOPC   (unsigned long)(237L << 40 | 102L)
@@ -874,15 +881,19 @@
 
 // Shift
 // arithmetic
-#define SLA_ZOPC    (unsigned  int)(139 << 24)
-#define SLAG_ZOPC   (unsigned long)(235L << 40 | 11L)
-#define SRA_ZOPC    (unsigned  int)(138 << 24)
-#define SRAG_ZOPC   (unsigned long)(235L << 40 | 10L)
+#define SLA_ZOPC    (unsigned  int)(0x8b  << 24)
+#define SLAK_ZOPC   (unsigned long)(0xebL << 40 | 0xddL)
+#define SLAG_ZOPC   (unsigned long)(0xebL << 40 | 0x0bL)
+#define SRA_ZOPC    (unsigned  int)(0x8a  << 24)
+#define SRAK_ZOPC   (unsigned long)(0xebL << 40 | 0xdcL)
+#define SRAG_ZOPC   (unsigned long)(0xebL << 40 | 0x0aL)
 // logical
-#define SLL_ZOPC    (unsigned  int)(137 << 24)
-#define SLLG_ZOPC   (unsigned long)(235L << 40 | 13L)
-#define SRL_ZOPC    (unsigned  int)(136 << 24)
-#define SRLG_ZOPC   (unsigned long)(235L << 40 | 12L)
+#define SLL_ZOPC    (unsigned  int)(0x89  << 24)
+#define SLLK_ZOPC   (unsigned long)(0xebL << 40 | 0xdfL)
+#define SLLG_ZOPC   (unsigned long)(0xebL << 40 | 0x0dL)
+#define SRL_ZOPC    (unsigned  int)(0x88  << 24)
+#define SRLK_ZOPC   (unsigned long)(0xebL << 40 | 0xdeL)
+#define SRLG_ZOPC   (unsigned long)(0xebL << 40 | 0x0cL)
 
 // Rotate, then AND/XOR/OR/insert
 // rotate
@@ -2262,12 +2273,16 @@
 
   // shift
   inline void z_sla( Register r1,              int64_t d2, Register b2=Z_R0); // shift left  r1 = r1 << ((d2+b2)&0x3f) ; int32, only 31 bits shifted, sign preserved!
+  inline void z_slak(Register r1, Register r3, int64_t d2, Register b2=Z_R0); // shift left  r1 = r3 << ((d2+b2)&0x3f) ; int32, only 31 bits shifted, sign preserved!
   inline void z_slag(Register r1, Register r3, int64_t d2, Register b2=Z_R0); // shift left  r1 = r3 << ((d2+b2)&0x3f) ; int64, only 63 bits shifted, sign preserved!
   inline void z_sra( Register r1,              int64_t d2, Register b2=Z_R0); // shift right r1 = r1 >> ((d2+b2)&0x3f) ; int32, sign extended
+  inline void z_srak(Register r1, Register r3, int64_t d2, Register b2=Z_R0); // shift right r1 = r3 >> ((d2+b2)&0x3f) ; int32, sign extended
   inline void z_srag(Register r1, Register r3, int64_t d2, Register b2=Z_R0); // shift right r1 = r3 >> ((d2+b2)&0x3f) ; int64, sign extended
   inline void z_sll( Register r1,              int64_t d2, Register b2=Z_R0); // shift left  r1 = r1 << ((d2+b2)&0x3f) ; int32, zeros added
+  inline void z_sllk(Register r1, Register r3, int64_t d2, Register b2=Z_R0); // shift left  r1 = r3 << ((d2+b2)&0x3f) ; int32, zeros added
   inline void z_sllg(Register r1, Register r3, int64_t d2, Register b2=Z_R0); // shift left  r1 = r3 << ((d2+b2)&0x3f) ; int64, zeros added
   inline void z_srl( Register r1,              int64_t d2, Register b2=Z_R0); // shift right r1 = r1 >> ((d2+b2)&0x3f) ; int32, zero extended
+  inline void z_srlk(Register r1, Register r3, int64_t d2, Register b2=Z_R0); // shift right r1 = r3 >> ((d2+b2)&0x3f) ; int32, zero extended
   inline void z_srlg(Register r1, Register r3, int64_t d2, Register b2=Z_R0); // shift right r1 = r3 >> ((d2+b2)&0x3f) ; int64, zero extended
 
   // rotate
@@ -3035,7 +3050,11 @@
 
   inline void z_tam();
   inline void z_stckf(int64_t d2, Register b2);
+  inline void z_stm( Register r1, Register r3, int64_t d2, Register b2);
+  inline void z_stmy(Register r1, Register r3, int64_t d2, Register b2);
   inline void z_stmg(Register r1, Register r3, int64_t d2, Register b2);
+  inline void z_lm( Register r1, Register r3, int64_t d2, Register b2);
+  inline void z_lmy(Register r1, Register r3, int64_t d2, Register b2);
   inline void z_lmg(Register r1, Register r3, int64_t d2, Register b2);
 
   inline void z_cs( Register r1, Register r3, int64_t d2, Register b2);
--- a/src/hotspot/cpu/s390/assembler_s390.inline.hpp	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/hotspot/cpu/s390/assembler_s390.inline.hpp	Mon Nov 27 17:04:45 2017 +0000
@@ -334,12 +334,16 @@
 // SHIFT/RORATE OPERATIONS
 //-----------------------------------
 inline void Assembler::z_sla( Register r1,              int64_t d2, Register b2) { emit_32( SLA_ZOPC  | regt(r1, 8, 32) | uimm12(d2, 20, 32) | reg(b2, 16, 32)); }
+inline void Assembler::z_slak(Register r1, Register r3, int64_t d2, Register b2) { emit_48( SLAK_ZOPC | regt(r1, 8, 48) | simm20(d2)         | reg(b2, 16, 48) | reg(r3, 12, 48)); }
 inline void Assembler::z_slag(Register r1, Register r3, int64_t d2, Register b2) { emit_48( SLAG_ZOPC | regt(r1, 8, 48) | simm20(d2)         | reg(b2, 16, 48) | reg(r3, 12, 48)); }
 inline void Assembler::z_sra( Register r1,              int64_t d2, Register b2) { emit_32( SRA_ZOPC  | regt(r1, 8, 32) | uimm12(d2, 20, 32) | reg(b2, 16, 32)); }
+inline void Assembler::z_srak(Register r1, Register r3, int64_t d2, Register b2) { emit_48( SRAK_ZOPC | regt(r1, 8, 48) | simm20(d2)         | reg(b2, 16, 48) | reg(r3, 12, 48)); }
 inline void Assembler::z_srag(Register r1, Register r3, int64_t d2, Register b2) { emit_48( SRAG_ZOPC | regt(r1, 8, 48) | simm20(d2)         | reg(b2, 16, 48) | reg(r3, 12, 48)); }
 inline void Assembler::z_sll( Register r1,              int64_t d2, Register b2) { emit_32( SLL_ZOPC  | regt(r1, 8, 32) | uimm12(d2, 20, 32) | reg(b2, 16, 32)); }
+inline void Assembler::z_sllk(Register r1, Register r3, int64_t d2, Register b2) { emit_48( SLLK_ZOPC | regt(r1, 8, 48) | simm20(d2)         | reg(b2, 16, 48) | reg(r3, 12, 48)); }
 inline void Assembler::z_sllg(Register r1, Register r3, int64_t d2, Register b2) { emit_48( SLLG_ZOPC | regt(r1, 8, 48) | simm20(d2)         | reg(b2, 16, 48) | reg(r3, 12, 48)); }
 inline void Assembler::z_srl( Register r1,              int64_t d2, Register b2) { emit_32( SRL_ZOPC  | regt(r1, 8, 32) | uimm12(d2, 20, 32) | reg(b2, 16, 32)); }
+inline void Assembler::z_srlk(Register r1, Register r3, int64_t d2, Register b2) { emit_48( SRLK_ZOPC | regt(r1, 8, 48) | simm20(d2)         | reg(b2, 16, 48) | reg(r3, 12, 48)); }
 inline void Assembler::z_srlg(Register r1, Register r3, int64_t d2, Register b2) { emit_48( SRLG_ZOPC | regt(r1, 8, 48) | simm20(d2)         | reg(b2, 16, 48) | reg(r3, 12, 48)); }
 
 // rotate left
@@ -690,10 +694,14 @@
 
 inline void Assembler::z_tam() { emit_16( TAM_ZOPC); }
 inline void Assembler::z_stckf(int64_t d2, Register b2) { emit_32( STCKF_ZOPC | uimm12(d2, 20, 32) | regz(b2, 16, 32)); }
-inline void Assembler::z_stmg(Register r1, Register r3, int64_t d2, Register b2) { emit_48( STMG_ZOPC | simm20(d2) | reg(r1, 8, 48) | reg(r3,12,48)| reg(b2,16,48) ); }
-inline void Assembler::z_lmg(Register r1, Register r3, int64_t d2, Register b2)  { emit_48( LMG_ZOPC  | simm20(d2) | reg(r1, 8, 48) | reg(r3,12,48)| reg(b2,16,48) ); }
+inline void Assembler::z_stm( Register r1, Register r3, int64_t d2, Register b2) { emit_32( STM_ZOPC  | reg(r1, 8, 32) | reg(r3,12,32)| reg(b2,16,32) | uimm12(d2, 20,32)); }
+inline void Assembler::z_stmy(Register r1, Register r3, int64_t d2, Register b2) { emit_48( STMY_ZOPC | reg(r1, 8, 48) | reg(r3,12,48)| reg(b2,16,48) | simm20(d2) ); }
+inline void Assembler::z_stmg(Register r1, Register r3, int64_t d2, Register b2) { emit_48( STMG_ZOPC | reg(r1, 8, 48) | reg(r3,12,48)| reg(b2,16,48) | simm20(d2) ); }
+inline void Assembler::z_lm(  Register r1, Register r3, int64_t d2, Register b2) { emit_32( LM_ZOPC   | reg(r1, 8, 32) | reg(r3,12,32)| reg(b2,16,32) | uimm12(d2, 20,32)); }
+inline void Assembler::z_lmy( Register r1, Register r3, int64_t d2, Register b2) { emit_48( LMY_ZOPC  | reg(r1, 8, 48) | reg(r3,12,48)| reg(b2,16,48) | simm20(d2) ); }
+inline void Assembler::z_lmg( Register r1, Register r3, int64_t d2, Register b2) { emit_48( LMG_ZOPC  | reg(r1, 8, 48) | reg(r3,12,48)| reg(b2,16,48) | simm20(d2) ); }
 
-inline void Assembler::z_cs(Register r1, Register r3, int64_t d2, Register b2)  { emit_32( CS_ZOPC  | regt(r1, 8, 32) | reg(r3, 12, 32) | reg(b2, 16, 32) | uimm12(d2, 20, 32)); }
+inline void Assembler::z_cs( Register r1, Register r3, int64_t d2, Register b2) { emit_32( CS_ZOPC  | regt(r1, 8, 32) | reg(r3, 12, 32) | reg(b2, 16, 32) | uimm12(d2, 20, 32)); }
 inline void Assembler::z_csy(Register r1, Register r3, int64_t d2, Register b2) { emit_48( CSY_ZOPC | regt(r1, 8, 48) | reg(r3, 12, 48) | reg(b2, 16, 48) | simm20(d2)); }
 inline void Assembler::z_csg(Register r1, Register r3, int64_t d2, Register b2) { emit_48( CSG_ZOPC | regt(r1, 8, 48) | reg(r3, 12, 48) | reg(b2, 16, 48) | simm20(d2)); }
 inline void Assembler::z_cs( Register r1, Register r3, const Address& a) { assert(!a.has_index(), "Cannot encode index"); z_cs( r1, r3, a.disp(), a.baseOrR0()); }
--- a/src/hotspot/cpu/s390/macroAssembler_s390.cpp	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/hotspot/cpu/s390/macroAssembler_s390.cpp	Mon Nov 27 17:04:45 2017 +0000
@@ -936,7 +936,7 @@
 
   // Some extra safety net.
   if (!RelAddr::is_in_range_of_RelAddr32(total_distance)) {
-    guarantee(RelAddr::is_in_range_of_RelAddr32(total_distance), "too far away");
+    guarantee(RelAddr::is_in_range_of_RelAddr32(total_distance), "load_long_pcrelative can't handle distance " INTPTR_FORMAT, total_distance);
   }
 
   (this)->relocate(rspec, relocInfo::pcrel_addr_format);
@@ -956,7 +956,7 @@
 
   // Some extra safety net.
   if (!RelAddr::is_in_range_of_RelAddr32(total_distance)) {
-    guarantee(RelAddr::is_in_range_of_RelAddr32(total_distance), "too far away");
+    guarantee(RelAddr::is_in_range_of_RelAddr32(total_distance), "load_long_pcrelative can't handle distance " INTPTR_FORMAT, total_distance);
   }
 
   (this)->relocate(rspec, relocInfo::pcrel_addr_format);
@@ -1025,6 +1025,13 @@
   }
 }
 
+void MacroAssembler::prefetch_read(Address a) {
+  z_pfd(1, a.disp20(), a.indexOrR0(), a.base());
+}
+void MacroAssembler::prefetch_update(Address a) {
+  z_pfd(2, a.disp20(), a.indexOrR0(), a.base());
+}
+
 // Clear a register, i.e. load const zero into reg.
 // Return len (in bytes) of generated instruction(s).
 // whole_reg: Clear 64 bits if true, 32 bits otherwise.
@@ -4896,77 +4903,295 @@
 
 // Intrinsics for CompactStrings
 
-// Compress char[] to byte[]. odd_reg contains cnt. Kills dst. Early clobber: result
+// Compress char[] to byte[].
+//   Restores: src, dst
+//   Uses:     cnt
+//   Kills:    tmp, Z_R0, Z_R1.
+//   Early clobber: result.
+// Note:
+//   cnt is signed int. Do not rely on high word!
+//       counts # characters, not bytes.
 // The result is the number of characters copied before the first incompatible character was found.
-// If tmp2 is provided and the compression fails, the compression stops exactly at this point and the result is precise.
+// If precise is true, the processing stops exactly at this point. Otherwise, the result may be off
+// by a few bytes. The result always indicates the number of copied characters.
 //
 // Note: Does not behave exactly like package private StringUTF16 compress java implementation in case of failure:
-// - Different number of characters may have been written to dead array (if tmp2 not provided).
+// - Different number of characters may have been written to dead array (if precise is false).
 // - Returns a number <cnt instead of 0. (Result gets compared with cnt.)
-unsigned int MacroAssembler::string_compress(Register result, Register src, Register dst, Register odd_reg,
-                                             Register even_reg, Register tmp, Register tmp2) {
-  int block_start = offset();
-  Label Lloop1, Lloop2, Lslow, Ldone;
-  const Register addr2 = dst, ind1 = result, mask = tmp;
-  const bool precise = (tmp2 != noreg);
-
-  BLOCK_COMMENT("string_compress {");
-
-  z_sll(odd_reg, 1);       // Number of bytes to read. (Must be a positive simm32.)
-  clear_reg(ind1);         // Index to read.
-  z_llilf(mask, 0xFF00FF00);
-  z_ahi(odd_reg, -16);     // Last possible index for fast loop.
-  z_brl(Lslow);
-
-  // ind1: index, even_reg: index increment, odd_reg: index limit
-  z_iihf(mask, 0xFF00FF00);
-  z_lhi(even_reg, 16);
-
-  bind(Lloop1); // 8 Characters per iteration.
-  z_lg(Z_R0, Address(src, ind1));
-  z_lg(Z_R1, Address(src, ind1, 8));
+unsigned int MacroAssembler::string_compress(Register result, Register src, Register dst, Register cnt,
+                                             Register tmp,    bool precise) {
+  assert_different_registers(Z_R0, Z_R1, src, dst, cnt, tmp);
+
   if (precise) {
+    BLOCK_COMMENT("encode_iso_array {");
+  } else {
+    BLOCK_COMMENT("string_compress {");
+  }
+  int  block_start = offset();
+
+  Register       Rsrc  = src;
+  Register       Rdst  = dst;
+  Register       Rix   = tmp;
+  Register       Rcnt  = cnt;
+  Register       Rmask = result;  // holds incompatibility check mask until result value is stored.
+  Label          ScalarShortcut, AllDone;
+
+  z_iilf(Rmask, 0xFF00FF00);
+  z_iihf(Rmask, 0xFF00FF00);
+
+#if 0  // Sacrifice shortcuts for code compactness
+  {
+    //---<  shortcuts for short strings (very frequent)   >---
+    //   Strings with 4 and 8 characters were fond to occur very frequently.
+    //   Therefore, we handle them right away with minimal overhead.
+    Label     skipShortcut, skip4Shortcut, skip8Shortcut;
+    Register  Rout = Z_R0;
+    z_chi(Rcnt, 4);
+    z_brne(skip4Shortcut);                 // 4 characters are very frequent
+      z_lg(Z_R0, 0, Rsrc);                 // Treat exactly 4 characters specially.
+      if (VM_Version::has_DistinctOpnds()) {
+        Rout = Z_R0;
+        z_ngrk(Rix, Z_R0, Rmask);
+      } else {
+        Rout = Rix;
+        z_lgr(Rix, Z_R0);
+        z_ngr(Z_R0, Rmask);
+      }
+      z_brnz(skipShortcut);
+      z_stcmh(Rout, 5, 0, Rdst);
+      z_stcm(Rout,  5, 2, Rdst);
+      z_lgfr(result, Rcnt);
+      z_bru(AllDone);
+    bind(skip4Shortcut);
+
+    z_chi(Rcnt, 8);
+    z_brne(skip8Shortcut);                 // There's more to do...
+      z_lmg(Z_R0, Z_R1, 0, Rsrc);          // Treat exactly 8 characters specially.
+      if (VM_Version::has_DistinctOpnds()) {
+        Rout = Z_R0;
+        z_ogrk(Rix, Z_R0, Z_R1);
+        z_ngr(Rix, Rmask);
+      } else {
+        Rout = Rix;
+        z_lgr(Rix, Z_R0);
+        z_ogr(Z_R0, Z_R1);
+        z_ngr(Z_R0, Rmask);
+      }
+      z_brnz(skipShortcut);
+      z_stcmh(Rout, 5, 0, Rdst);
+      z_stcm(Rout,  5, 2, Rdst);
+      z_stcmh(Z_R1, 5, 4, Rdst);
+      z_stcm(Z_R1,  5, 6, Rdst);
+      z_lgfr(result, Rcnt);
+      z_bru(AllDone);
+
+    bind(skip8Shortcut);
+    clear_reg(Z_R0, true, false);          // #characters already processed (none). Precond for scalar loop.
+    z_brl(ScalarShortcut);                 // Just a few characters
+
+    bind(skipShortcut);
+  }
+#endif
+  clear_reg(Z_R0);                         // make sure register is properly initialized.
+
+  if (VM_Version::has_VectorFacility()) {
+    const int  min_vcnt     = 32;          // Minimum #characters required to use vector instructions.
+                                           // Otherwise just do nothing in vector mode.
+                                           // Must be multiple of 2*(vector register length in chars (8 HW = 128 bits)).
+    const int  log_min_vcnt = exact_log2(min_vcnt);
+    Label      VectorLoop, VectorDone, VectorBreak;
+
+    VectorRegister Vtmp1      = Z_V16;
+    VectorRegister Vtmp2      = Z_V17;
+    VectorRegister Vmask      = Z_V18;
+    VectorRegister Vzero      = Z_V19;
+    VectorRegister Vsrc_first = Z_V20;
+    VectorRegister Vsrc_last  = Z_V23;
+
+    assert((Vsrc_last->encoding() - Vsrc_first->encoding() + 1) == min_vcnt/8, "logic error");
+    assert(VM_Version::has_DistinctOpnds(), "Assumption when has_VectorFacility()");
+    z_srak(Rix, Rcnt, log_min_vcnt);       // # vector loop iterations
+    z_brz(VectorDone);                     // not enough data for vector loop
+
+    z_vzero(Vzero);                        // all zeroes
+    z_vgmh(Vmask, 0, 7);                   // generate 0xff00 mask for all 2-byte elements
+    z_sllg(Z_R0, Rix, log_min_vcnt);       // remember #chars that will be processed by vector loop
+
+    bind(VectorLoop);
+      z_vlm(Vsrc_first, Vsrc_last, 0, Rsrc);
+      add2reg(Rsrc, min_vcnt*2);
+
+      //---<  check for incompatible character  >---
+      z_vo(Vtmp1, Z_V20, Z_V21);
+      z_vo(Vtmp2, Z_V22, Z_V23);
+      z_vo(Vtmp1, Vtmp1, Vtmp2);
+      z_vn(Vtmp1, Vtmp1, Vmask);
+      z_vceqhs(Vtmp1, Vtmp1, Vzero);       // high half of all chars must be zero for successful compress.
+      z_brne(VectorBreak);                 // break vector loop, incompatible character found.
+                                           // re-process data from current iteration in break handler.
+
+      //---<  pack & store characters  >---
+      z_vpkh(Vtmp1, Z_V20, Z_V21);         // pack (src1, src2) -> tmp1
+      z_vpkh(Vtmp2, Z_V22, Z_V23);         // pack (src3, src4) -> tmp2
+      z_vstm(Vtmp1, Vtmp2, 0, Rdst);       // store packed string
+      add2reg(Rdst, min_vcnt);
+
+      z_brct(Rix, VectorLoop);
+
+    z_bru(VectorDone);
+
+    bind(VectorBreak);
+      z_sll(Rix, log_min_vcnt);            // # chars processed so far in VectorLoop, excl. current iteration.
+      z_sr(Z_R0, Rix);                     // correct # chars processed in total.
+
+    bind(VectorDone);
+  }
+
+  {
+    const int  min_cnt     =  8;           // Minimum #characters required to use unrolled loop.
+                                           // Otherwise just do nothing in unrolled loop.
+                                           // Must be multiple of 8.
+    const int  log_min_cnt = exact_log2(min_cnt);
+    Label      UnrolledLoop, UnrolledDone, UnrolledBreak;
+
     if (VM_Version::has_DistinctOpnds()) {
-      z_ogrk(tmp2, Z_R0, Z_R1);
+      z_srk(Rix, Rcnt, Z_R0);              // remaining # chars to compress in unrolled loop
     } else {
-      z_lgr(tmp2, Z_R0);
-      z_ogr(tmp2, Z_R1);
+      z_lr(Rix, Rcnt);
+      z_sr(Rix, Z_R0);
     }
-    z_ngr(tmp2, mask);
-    z_brne(Lslow);         // Failed fast case, retry slowly.
-  }
-  z_stcmh(Z_R0, 5, 0, addr2);
-  z_stcm(Z_R0, 5, 2, addr2);
-  if (!precise) { z_ogr(Z_R0, Z_R1); }
-  z_stcmh(Z_R1, 5, 4, addr2);
-  z_stcm(Z_R1, 5, 6, addr2);
-  if (!precise) {
-    z_ngr(Z_R0, mask);
-    z_brne(Ldone);         // Failed (more than needed was written).
-  }
-  z_aghi(addr2, 8);
-  z_brxle(ind1, even_reg, Lloop1);
-
-  bind(Lslow);
-  // Compute index limit and skip if negative.
-  z_ahi(odd_reg, 16-2);    // Last possible index for slow loop.
-  z_lhi(even_reg, 2);
-  z_cr(ind1, odd_reg);
-  z_brh(Ldone);
-
-  bind(Lloop2); // 1 Character per iteration.
-  z_llh(Z_R0, Address(src, ind1));
-  z_tmll(Z_R0, 0xFF00);
-  z_brnaz(Ldone);          // Failed slow case: Return number of written characters.
-  z_stc(Z_R0, Address(addr2));
-  z_aghi(addr2, 1);
-  z_brxle(ind1, even_reg, Lloop2);
-
-  bind(Ldone);             // result = ind1 = 2*cnt
-  z_srl(ind1, 1);
-
-  BLOCK_COMMENT("} string_compress");
-
+    z_sra(Rix, log_min_cnt);             // unrolled loop count
+    z_brz(UnrolledDone);
+
+    bind(UnrolledLoop);
+      z_lmg(Z_R0, Z_R1, 0, Rsrc);
+      if (precise) {
+        z_ogr(Z_R1, Z_R0);                 // check all 8 chars for incompatibility
+        z_ngr(Z_R1, Rmask);
+        z_brnz(UnrolledBreak);
+
+        z_lg(Z_R1, 8, Rsrc);               // reload destroyed register
+        z_stcmh(Z_R0, 5, 0, Rdst);
+        z_stcm(Z_R0,  5, 2, Rdst);
+      } else {
+        z_stcmh(Z_R0, 5, 0, Rdst);
+        z_stcm(Z_R0,  5, 2, Rdst);
+
+        z_ogr(Z_R0, Z_R1);
+        z_ngr(Z_R0, Rmask);
+        z_brnz(UnrolledBreak);
+      }
+      z_stcmh(Z_R1, 5, 4, Rdst);
+      z_stcm(Z_R1,  5, 6, Rdst);
+
+      add2reg(Rsrc, min_cnt*2);
+      add2reg(Rdst, min_cnt);
+      z_brct(Rix, UnrolledLoop);
+
+    z_lgfr(Z_R0, Rcnt);                    // # chars processed in total after unrolled loop.
+    z_nilf(Z_R0, ~(min_cnt-1));
+    z_tmll(Rcnt, min_cnt-1);
+    z_brnaz(ScalarShortcut);               // if all bits zero, there is nothing left to do for scalar loop.
+                                           // Rix == 0 in all cases.
+    z_lgfr(result, Rcnt);                  // all characters processed.
+    z_sgfr(Rdst, Rcnt);                    // restore ptr
+    z_sgfr(Rsrc, Rcnt);                    // restore ptr, double the element count for Rsrc restore
+    z_sgfr(Rsrc, Rcnt);
+    z_bru(AllDone);
+
+    bind(UnrolledBreak);
+    z_lgfr(Z_R0, Rcnt);                    // # chars processed in total after unrolled loop
+    z_nilf(Z_R0, ~(min_cnt-1));
+    z_sll(Rix, log_min_cnt);               // # chars processed so far in UnrolledLoop, excl. current iteration.
+    z_sr(Z_R0, Rix);                       // correct # chars processed in total.
+    if (!precise) {
+      z_lgfr(result, Z_R0);
+      z_aghi(result, min_cnt/2);           // min_cnt/2 characters have already been written
+                                           // but ptrs were not updated yet.
+      z_sgfr(Rdst, Z_R0);                  // restore ptr
+      z_sgfr(Rsrc, Z_R0);                  // restore ptr, double the element count for Rsrc restore
+      z_sgfr(Rsrc, Z_R0);
+      z_bru(AllDone);
+    }
+    bind(UnrolledDone);
+  }
+
+  {
+    Label     ScalarLoop, ScalarDone, ScalarBreak;
+
+    bind(ScalarShortcut);
+    z_ltgfr(result, Rcnt);
+    z_brz(AllDone);
+
+#if 0  // Sacrifice shortcuts for code compactness
+    {
+      //---<  Special treatment for very short strings (one or two characters)  >---
+      //   For these strings, we are sure that the above code was skipped.
+      //   Thus, no registers were modified, register restore is not required.
+      Label     ScalarDoit, Scalar2Char;
+      z_chi(Rcnt, 2);
+      z_brh(ScalarDoit);
+      z_llh(Z_R1,  0, Z_R0, Rsrc);
+      z_bre(Scalar2Char);
+      z_tmll(Z_R1, 0xff00);
+      z_lghi(result, 0);                   // cnt == 1, first char invalid, no chars successfully processed
+      z_brnaz(AllDone);
+      z_stc(Z_R1,  0, Z_R0, Rdst);
+      z_lghi(result, 1);
+      z_bru(AllDone);
+
+      bind(Scalar2Char);
+      z_llh(Z_R0,  2, Z_R0, Rsrc);
+      z_tmll(Z_R1, 0xff00);
+      z_lghi(result, 0);                   // cnt == 2, first char invalid, no chars successfully processed
+      z_brnaz(AllDone);
+      z_stc(Z_R1,  0, Z_R0, Rdst);
+      z_tmll(Z_R0, 0xff00);
+      z_lghi(result, 1);                   // cnt == 2, second char invalid, one char successfully processed
+      z_brnaz(AllDone);
+      z_stc(Z_R0,  1, Z_R0, Rdst);
+      z_lghi(result, 2);
+      z_bru(AllDone);
+
+      bind(ScalarDoit);
+    }
+#endif
+
+    if (VM_Version::has_DistinctOpnds()) {
+      z_srk(Rix, Rcnt, Z_R0);              // remaining # chars to compress in unrolled loop
+    } else {
+      z_lr(Rix, Rcnt);
+      z_sr(Rix, Z_R0);
+    }
+    z_lgfr(result, Rcnt);                  // # processed characters (if all runs ok).
+    z_brz(ScalarDone);
+
+    bind(ScalarLoop);
+      z_llh(Z_R1, 0, Z_R0, Rsrc);
+      z_tmll(Z_R1, 0xff00);
+      z_brnaz(ScalarBreak);
+      z_stc(Z_R1, 0, Z_R0, Rdst);
+      add2reg(Rsrc, 2);
+      add2reg(Rdst, 1);
+      z_brct(Rix, ScalarLoop);
+
+    z_bru(ScalarDone);
+
+    bind(ScalarBreak);
+    z_sr(result, Rix);
+
+    bind(ScalarDone);
+    z_sgfr(Rdst, result);                  // restore ptr
+    z_sgfr(Rsrc, result);                  // restore ptr, double the element count for Rsrc restore
+    z_sgfr(Rsrc, result);
+  }
+  bind(AllDone);
+
+  if (precise) {
+    BLOCK_COMMENT("} encode_iso_array");
+  } else {
+    BLOCK_COMMENT("} string_compress");
+  }
   return offset() - block_start;
 }
 
@@ -4997,53 +5222,432 @@
   return offset() - block_start;
 }
 
-// Inflate byte[] to char[]. odd_reg contains cnt. Kills src.
-unsigned int MacroAssembler::string_inflate(Register src, Register dst, Register odd_reg,
-                                            Register even_reg, Register tmp) {
-  int block_start = offset();
+// Inflate byte[] to char[].
+//   Restores: src, dst
+//   Uses:     cnt
+//   Kills:    tmp, Z_R0, Z_R1.
+// Note:
+//   cnt is signed int. Do not rely on high word!
+//       counts # characters, not bytes.
+unsigned int MacroAssembler::string_inflate(Register src, Register dst, Register cnt, Register tmp) {
+  assert_different_registers(Z_R0, Z_R1, src, dst, cnt, tmp);
 
   BLOCK_COMMENT("string_inflate {");
-
-  Label Lloop1, Lloop2, Lslow, Ldone;
-  const Register addr1 = src, ind2 = tmp;
-
-  z_sll(odd_reg, 1);       // Number of bytes to write. (Must be a positive simm32.)
-  clear_reg(ind2);         // Index to write.
-  z_ahi(odd_reg, -16);     // Last possible index for fast loop.
-  z_brl(Lslow);
-
-  // ind2: index, even_reg: index increment, odd_reg: index limit
-  clear_reg(Z_R0);
-  clear_reg(Z_R1);
-  z_lhi(even_reg, 16);
-
-  bind(Lloop1); // 8 Characters per iteration.
-  z_icmh(Z_R0, 5, 0, addr1);
-  z_icmh(Z_R1, 5, 4, addr1);
-  z_icm(Z_R0, 5, 2, addr1);
-  z_icm(Z_R1, 5, 6, addr1);
-  z_aghi(addr1, 8);
-  z_stg(Z_R0, Address(dst, ind2));
-  z_stg(Z_R1, Address(dst, ind2, 8));
-  z_brxle(ind2, even_reg, Lloop1);
-
-  bind(Lslow);
-  // Compute index limit and skip if negative.
-  z_ahi(odd_reg, 16-2);    // Last possible index for slow loop.
-  z_lhi(even_reg, 2);
-  z_cr(ind2, odd_reg);
-  z_brh(Ldone);
-
-  bind(Lloop2); // 1 Character per iteration.
-  z_llc(Z_R0, Address(addr1));
-  z_sth(Z_R0, Address(dst, ind2));
-  z_aghi(addr1, 1);
-  z_brxle(ind2, even_reg, Lloop2);
-
-  bind(Ldone);
+  int block_start = offset();
+
+  Register   Rcnt = cnt;   // # characters (src: bytes, dst: char (2-byte)), remaining after current loop.
+  Register   Rix  = tmp;   // loop index
+  Register   Rsrc = src;   // addr(src array)
+  Register   Rdst = dst;   // addr(dst array)
+  Label      ScalarShortcut, AllDone;
+
+#if 0  // Sacrifice shortcuts for code compactness
+  {
+    //---<  shortcuts for short strings (very frequent)   >---
+    Label   skipShortcut, skip4Shortcut;
+    z_ltr(Rcnt, Rcnt);                     // absolutely nothing to do for strings of len == 0.
+    z_brz(AllDone);
+    clear_reg(Z_R0);                       // make sure registers are properly initialized.
+    clear_reg(Z_R1);
+    z_chi(Rcnt, 4);
+    z_brne(skip4Shortcut);                 // 4 characters are very frequent
+      z_icm(Z_R0, 5,    0, Rsrc);          // Treat exactly 4 characters specially.
+      z_icm(Z_R1, 5,    2, Rsrc);
+      z_stm(Z_R0, Z_R1, 0, Rdst);
+      z_bru(AllDone);
+    bind(skip4Shortcut);
+
+    z_chi(Rcnt, 8);
+    z_brh(skipShortcut);                   // There's a lot to do...
+    z_lgfr(Z_R0, Rcnt);                    // remaining #characters (<= 8). Precond for scalar loop.
+                                           // This does not destroy the "register cleared" state of Z_R0.
+    z_brl(ScalarShortcut);                 // Just a few characters
+      z_icmh(Z_R0, 5, 0, Rsrc);            // Treat exactly 8 characters specially.
+      z_icmh(Z_R1, 5, 4, Rsrc);
+      z_icm(Z_R0,  5, 2, Rsrc);
+      z_icm(Z_R1,  5, 6, Rsrc);
+      z_stmg(Z_R0, Z_R1, 0, Rdst);
+      z_bru(AllDone);
+    bind(skipShortcut);
+  }
+#endif
+  clear_reg(Z_R0);                         // make sure register is properly initialized.
+
+  if (VM_Version::has_VectorFacility()) {
+    const int  min_vcnt     = 32;          // Minimum #characters required to use vector instructions.
+                                           // Otherwise just do nothing in vector mode.
+                                           // Must be multiple of vector register length (16 bytes = 128 bits).
+    const int  log_min_vcnt = exact_log2(min_vcnt);
+    Label      VectorLoop, VectorDone;
+
+    assert(VM_Version::has_DistinctOpnds(), "Assumption when has_VectorFacility()");
+    z_srak(Rix, Rcnt, log_min_vcnt);       // calculate # vector loop iterations
+    z_brz(VectorDone);                     // skip if none
+
+    z_sllg(Z_R0, Rix, log_min_vcnt);       // remember #chars that will be processed by vector loop
+
+    bind(VectorLoop);
+      z_vlm(Z_V20, Z_V21, 0, Rsrc);        // get next 32 characters (single-byte)
+      add2reg(Rsrc, min_vcnt);
+
+      z_vuplhb(Z_V22, Z_V20);              // V2 <- (expand) V0(high)
+      z_vupllb(Z_V23, Z_V20);              // V3 <- (expand) V0(low)
+      z_vuplhb(Z_V24, Z_V21);              // V4 <- (expand) V1(high)
+      z_vupllb(Z_V25, Z_V21);              // V5 <- (expand) V1(low)
+      z_vstm(Z_V22, Z_V25, 0, Rdst);       // store next 32 bytes
+      add2reg(Rdst, min_vcnt*2);
+
+      z_brct(Rix, VectorLoop);
+
+    bind(VectorDone);
+  }
+
+  const int  min_cnt     =  8;             // Minimum #characters required to use unrolled scalar loop.
+                                           // Otherwise just do nothing in unrolled scalar mode.
+                                           // Must be multiple of 8.
+  {
+    const int  log_min_cnt = exact_log2(min_cnt);
+    Label      UnrolledLoop, UnrolledDone;
+
+
+    if (VM_Version::has_DistinctOpnds()) {
+      z_srk(Rix, Rcnt, Z_R0);              // remaining # chars to process in unrolled loop
+    } else {
+      z_lr(Rix, Rcnt);
+      z_sr(Rix, Z_R0);
+    }
+    z_sra(Rix, log_min_cnt);               // unrolled loop count
+    z_brz(UnrolledDone);
+
+    clear_reg(Z_R0);
+    clear_reg(Z_R1);
+
+    bind(UnrolledLoop);
+      z_icmh(Z_R0, 5, 0, Rsrc);
+      z_icmh(Z_R1, 5, 4, Rsrc);
+      z_icm(Z_R0,  5, 2, Rsrc);
+      z_icm(Z_R1,  5, 6, Rsrc);
+      add2reg(Rsrc, min_cnt);
+
+      z_stmg(Z_R0, Z_R1, 0, Rdst);
+
+      add2reg(Rdst, min_cnt*2);
+      z_brct(Rix, UnrolledLoop);
+
+    bind(UnrolledDone);
+    z_lgfr(Z_R0, Rcnt);                    // # chars left over after unrolled loop.
+    z_nilf(Z_R0, min_cnt-1);
+    z_brnz(ScalarShortcut);                // if zero, there is nothing left to do for scalar loop.
+                                           // Rix == 0 in all cases.
+    z_sgfr(Z_R0, Rcnt);                    // negative # characters the ptrs have been advanced previously.
+    z_agr(Rdst, Z_R0);                     // restore ptr, double the element count for Rdst restore.
+    z_agr(Rdst, Z_R0);
+    z_agr(Rsrc, Z_R0);                     // restore ptr.
+    z_bru(AllDone);
+  }
+
+  {
+    bind(ScalarShortcut);
+    // Z_R0 must contain remaining # characters as 64-bit signed int here.
+    //      register contents is preserved over scalar processing (for register fixup).
+
+#if 0  // Sacrifice shortcuts for code compactness
+    {
+      Label      ScalarDefault;
+      z_chi(Rcnt, 2);
+      z_brh(ScalarDefault);
+      z_llc(Z_R0,  0, Z_R0, Rsrc);     // 6 bytes
+      z_sth(Z_R0,  0, Z_R0, Rdst);     // 4 bytes
+      z_brl(AllDone);
+      z_llc(Z_R0,  1, Z_R0, Rsrc);     // 6 bytes
+      z_sth(Z_R0,  2, Z_R0, Rdst);     // 4 bytes
+      z_bru(AllDone);
+      bind(ScalarDefault);
+    }
+#endif
+
+    Label   CodeTable;
+    // Some comments on Rix calculation:
+    //  - Rcnt is small, therefore no bits shifted out of low word (sll(g) instructions).
+    //  - high word of both Rix and Rcnt may contain garbage
+    //  - the final lngfr takes care of that garbage, extending the sign to high word
+    z_sllg(Rix, Z_R0, 2);                // calculate 10*Rix = (4*Rix + Rix)*2
+    z_ar(Rix, Z_R0);
+    z_larl(Z_R1, CodeTable);
+    z_sll(Rix, 1);
+    z_lngfr(Rix, Rix);      // ix range: [0..7], after inversion & mult: [-(7*12)..(0*12)].
+    z_bc(Assembler::bcondAlways, 0, Rix, Z_R1);
+
+    z_llc(Z_R1,  6, Z_R0, Rsrc);  // 6 bytes
+    z_sth(Z_R1, 12, Z_R0, Rdst);  // 4 bytes
+
+    z_llc(Z_R1,  5, Z_R0, Rsrc);
+    z_sth(Z_R1, 10, Z_R0, Rdst);
+
+    z_llc(Z_R1,  4, Z_R0, Rsrc);
+    z_sth(Z_R1,  8, Z_R0, Rdst);
+
+    z_llc(Z_R1,  3, Z_R0, Rsrc);
+    z_sth(Z_R1,  6, Z_R0, Rdst);
+
+    z_llc(Z_R1,  2, Z_R0, Rsrc);
+    z_sth(Z_R1,  4, Z_R0, Rdst);
+
+    z_llc(Z_R1,  1, Z_R0, Rsrc);
+    z_sth(Z_R1,  2, Z_R0, Rdst);
+
+    z_llc(Z_R1,  0, Z_R0, Rsrc);
+    z_sth(Z_R1,  0, Z_R0, Rdst);
+    bind(CodeTable);
+
+    z_chi(Rcnt, 8);                        // no fixup for small strings. Rdst, Rsrc were not modified.
+    z_brl(AllDone);
+
+    z_sgfr(Z_R0, Rcnt);                    // # characters the ptrs have been advanced previously.
+    z_agr(Rdst, Z_R0);                     // restore ptr, double the element count for Rdst restore.
+    z_agr(Rdst, Z_R0);
+    z_agr(Rsrc, Z_R0);                     // restore ptr.
+  }
+  bind(AllDone);
 
   BLOCK_COMMENT("} string_inflate");
-
+  return offset() - block_start;
+}
+
+// Inflate byte[] to char[], length known at compile time.
+//   Restores: src, dst
+//   Kills:    tmp, Z_R0, Z_R1.
+// Note:
+//   len is signed int. Counts # characters, not bytes.
+unsigned int MacroAssembler::string_inflate_const(Register src, Register dst, Register tmp, int len) {
+  assert_different_registers(Z_R0, Z_R1, src, dst, tmp);
+
+  BLOCK_COMMENT("string_inflate_const {");
+  int block_start = offset();
+
+  Register   Rix  = tmp;   // loop index
+  Register   Rsrc = src;   // addr(src array)
+  Register   Rdst = dst;   // addr(dst array)
+  Label      ScalarShortcut, AllDone;
+  int        nprocessed = 0;
+  int        src_off    = 0;  // compensate for saved (optimized away) ptr advancement.
+  int        dst_off    = 0;  // compensate for saved (optimized away) ptr advancement.
+  bool       restore_inputs = false;
+  bool       workreg_clear  = false;
+
+  if ((len >= 32) && VM_Version::has_VectorFacility()) {
+    const int  min_vcnt     = 32;          // Minimum #characters required to use vector instructions.
+                                           // Otherwise just do nothing in vector mode.
+                                           // Must be multiple of vector register length (16 bytes = 128 bits).
+    const int  log_min_vcnt = exact_log2(min_vcnt);
+    const int  iterations   = (len - nprocessed) >> log_min_vcnt;
+    nprocessed             += iterations << log_min_vcnt;
+    Label      VectorLoop;
+
+    if (iterations == 1) {
+      z_vlm(Z_V20, Z_V21, 0+src_off, Rsrc);  // get next 32 characters (single-byte)
+      z_vuplhb(Z_V22, Z_V20);                // V2 <- (expand) V0(high)
+      z_vupllb(Z_V23, Z_V20);                // V3 <- (expand) V0(low)
+      z_vuplhb(Z_V24, Z_V21);                // V4 <- (expand) V1(high)
+      z_vupllb(Z_V25, Z_V21);                // V5 <- (expand) V1(low)
+      z_vstm(Z_V22, Z_V25, 0+dst_off, Rdst); // store next 32 bytes
+
+      src_off += min_vcnt;
+      dst_off += min_vcnt*2;
+    } else {
+      restore_inputs = true;
+
+      z_lgfi(Rix, len>>log_min_vcnt);
+      bind(VectorLoop);
+        z_vlm(Z_V20, Z_V21, 0, Rsrc);        // get next 32 characters (single-byte)
+        add2reg(Rsrc, min_vcnt);
+
+        z_vuplhb(Z_V22, Z_V20);              // V2 <- (expand) V0(high)
+        z_vupllb(Z_V23, Z_V20);              // V3 <- (expand) V0(low)
+        z_vuplhb(Z_V24, Z_V21);              // V4 <- (expand) V1(high)
+        z_vupllb(Z_V25, Z_V21);              // V5 <- (expand) V1(low)
+        z_vstm(Z_V22, Z_V25, 0, Rdst);       // store next 32 bytes
+        add2reg(Rdst, min_vcnt*2);
+
+        z_brct(Rix, VectorLoop);
+    }
+  }
+
+  if (((len-nprocessed) >= 16) && VM_Version::has_VectorFacility()) {
+    const int  min_vcnt     = 16;          // Minimum #characters required to use vector instructions.
+                                           // Otherwise just do nothing in vector mode.
+                                           // Must be multiple of vector register length (16 bytes = 128 bits).
+    const int  log_min_vcnt = exact_log2(min_vcnt);
+    const int  iterations   = (len - nprocessed) >> log_min_vcnt;
+    nprocessed             += iterations << log_min_vcnt;
+    assert(iterations == 1, "must be!");
+
+    z_vl(Z_V20, 0+src_off, Z_R0, Rsrc);    // get next 16 characters (single-byte)
+    z_vuplhb(Z_V22, Z_V20);                // V2 <- (expand) V0(high)
+    z_vupllb(Z_V23, Z_V20);                // V3 <- (expand) V0(low)
+    z_vstm(Z_V22, Z_V23, 0+dst_off, Rdst); // store next 32 bytes
+
+    src_off += min_vcnt;
+    dst_off += min_vcnt*2;
+  }
+
+  if ((len-nprocessed) > 8) {
+    const int  min_cnt     =  8;           // Minimum #characters required to use unrolled scalar loop.
+                                           // Otherwise just do nothing in unrolled scalar mode.
+                                           // Must be multiple of 8.
+    const int  log_min_cnt = exact_log2(min_cnt);
+    const int  iterations  = (len - nprocessed) >> log_min_cnt;
+    nprocessed     += iterations << log_min_cnt;
+
+    //---<  avoid loop overhead/ptr increment for small # iterations  >---
+    if (iterations <= 2) {
+      clear_reg(Z_R0);
+      clear_reg(Z_R1);
+      workreg_clear = true;
+
+      z_icmh(Z_R0, 5, 0+src_off, Rsrc);
+      z_icmh(Z_R1, 5, 4+src_off, Rsrc);
+      z_icm(Z_R0,  5, 2+src_off, Rsrc);
+      z_icm(Z_R1,  5, 6+src_off, Rsrc);
+      z_stmg(Z_R0, Z_R1, 0+dst_off, Rdst);
+
+      src_off += min_cnt;
+      dst_off += min_cnt*2;
+    }
+
+    if (iterations == 2) {
+      z_icmh(Z_R0, 5, 0+src_off, Rsrc);
+      z_icmh(Z_R1, 5, 4+src_off, Rsrc);
+      z_icm(Z_R0,  5, 2+src_off, Rsrc);
+      z_icm(Z_R1,  5, 6+src_off, Rsrc);
+      z_stmg(Z_R0, Z_R1, 0+dst_off, Rdst);
+
+      src_off += min_cnt;
+      dst_off += min_cnt*2;
+    }
+
+    if (iterations > 2) {
+      Label      UnrolledLoop;
+      restore_inputs  = true;
+
+      clear_reg(Z_R0);
+      clear_reg(Z_R1);
+      workreg_clear = true;
+
+      z_lgfi(Rix, iterations);
+      bind(UnrolledLoop);
+        z_icmh(Z_R0, 5, 0, Rsrc);
+        z_icmh(Z_R1, 5, 4, Rsrc);
+        z_icm(Z_R0,  5, 2, Rsrc);
+        z_icm(Z_R1,  5, 6, Rsrc);
+        add2reg(Rsrc, min_cnt);
+
+        z_stmg(Z_R0, Z_R1, 0, Rdst);
+        add2reg(Rdst, min_cnt*2);
+
+        z_brct(Rix, UnrolledLoop);
+    }
+  }
+
+  if ((len-nprocessed) > 0) {
+    switch (len-nprocessed) {
+      case 8:
+        if (!workreg_clear) {
+          clear_reg(Z_R0);
+          clear_reg(Z_R1);
+        }
+        z_icmh(Z_R0, 5, 0+src_off, Rsrc);
+        z_icmh(Z_R1, 5, 4+src_off, Rsrc);
+        z_icm(Z_R0,  5, 2+src_off, Rsrc);
+        z_icm(Z_R1,  5, 6+src_off, Rsrc);
+        z_stmg(Z_R0, Z_R1, 0+dst_off, Rdst);
+        break;
+      case 7:
+        if (!workreg_clear) {
+          clear_reg(Z_R0);
+          clear_reg(Z_R1);
+        }
+        clear_reg(Rix);
+        z_icm(Z_R0,  5, 0+src_off, Rsrc);
+        z_icm(Z_R1,  5, 2+src_off, Rsrc);
+        z_icm(Rix,   5, 4+src_off, Rsrc);
+        z_stm(Z_R0,  Z_R1, 0+dst_off, Rdst);
+        z_llc(Z_R0,  6+src_off, Z_R0, Rsrc);
+        z_st(Rix,    8+dst_off, Z_R0, Rdst);
+        z_sth(Z_R0, 12+dst_off, Z_R0, Rdst);
+        break;
+      case 6:
+        if (!workreg_clear) {
+          clear_reg(Z_R0);
+          clear_reg(Z_R1);
+        }
+        clear_reg(Rix);
+        z_icm(Z_R0, 5, 0+src_off, Rsrc);
+        z_icm(Z_R1, 5, 2+src_off, Rsrc);
+        z_icm(Rix,  5, 4+src_off, Rsrc);
+        z_stm(Z_R0, Z_R1, 0+dst_off, Rdst);
+        z_st(Rix,   8+dst_off, Z_R0, Rdst);
+        break;
+      case 5:
+        if (!workreg_clear) {
+          clear_reg(Z_R0);
+          clear_reg(Z_R1);
+        }
+        z_icm(Z_R0, 5, 0+src_off, Rsrc);
+        z_icm(Z_R1, 5, 2+src_off, Rsrc);
+        z_llc(Rix,  4+src_off, Z_R0, Rsrc);
+        z_stm(Z_R0, Z_R1, 0+dst_off, Rdst);
+        z_sth(Rix,  8+dst_off, Z_R0, Rdst);
+        break;
+      case 4:
+        if (!workreg_clear) {
+          clear_reg(Z_R0);
+          clear_reg(Z_R1);
+        }
+        z_icm(Z_R0, 5, 0+src_off, Rsrc);
+        z_icm(Z_R1, 5, 2+src_off, Rsrc);
+        z_stm(Z_R0, Z_R1, 0+dst_off, Rdst);
+        break;
+      case 3:
+        if (!workreg_clear) {
+          clear_reg(Z_R0);
+        }
+        z_llc(Z_R1, 2+src_off, Z_R0, Rsrc);
+        z_icm(Z_R0, 5, 0+src_off, Rsrc);
+        z_sth(Z_R1, 4+dst_off, Z_R0, Rdst);
+        z_st(Z_R0,  0+dst_off, Rdst);
+        break;
+      case 2:
+        z_llc(Z_R0, 0+src_off, Z_R0, Rsrc);
+        z_llc(Z_R1, 1+src_off, Z_R0, Rsrc);
+        z_sth(Z_R0, 0+dst_off, Z_R0, Rdst);
+        z_sth(Z_R1, 2+dst_off, Z_R0, Rdst);
+        break;
+      case 1:
+        z_llc(Z_R0, 0+src_off, Z_R0, Rsrc);
+        z_sth(Z_R0, 0+dst_off, Z_R0, Rdst);
+        break;
+      default:
+        guarantee(false, "Impossible");
+        break;
+    }
+    src_off   +=  len-nprocessed;
+    dst_off   += (len-nprocessed)*2;
+    nprocessed = len;
+  }
+
+  //---< restore modified input registers  >---
+  if ((nprocessed > 0) && restore_inputs) {
+    z_agfi(Rsrc, -(nprocessed-src_off));
+    if (nprocessed < 1000000000) { // avoid int overflow
+      z_agfi(Rdst, -(nprocessed*2-dst_off));
+    } else {
+      z_agfi(Rdst, -(nprocessed-dst_off));
+      z_agfi(Rdst, -nprocessed);
+    }
+  }
+
+  BLOCK_COMMENT("} string_inflate_const");
   return offset() - block_start;
 }
 
--- a/src/hotspot/cpu/s390/macroAssembler_s390.hpp	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/hotspot/cpu/s390/macroAssembler_s390.hpp	Mon Nov 27 17:04:45 2017 +0000
@@ -198,6 +198,9 @@
   // Test a bit in a register. Result is reflected in CC.
   void testbit(Register r, unsigned int bitPos);
 
+  void prefetch_read(Address a);
+  void prefetch_update(Address a);
+
   // Clear a register, i.e. load const zero into reg. Return len (in bytes) of
   // generated instruction(s).
   //   whole_reg: Clear 64 bits if true, 32 bits otherwise.
@@ -836,7 +839,7 @@
   void load_mirror(Register mirror, Register method);
 
   //--------------------------
-  //---  perations on arrays.
+  //---  Operations on arrays.
   //--------------------------
   unsigned int Clear_Array(Register cnt_arg, Register base_pointer_arg, Register src_addr, Register src_len);
   unsigned int Clear_Array_Const(long cnt, Register base);
@@ -849,20 +852,34 @@
   // Special String Intrinsics Implementation.
   //-------------------------------------------
   // Intrinsics for CompactStrings
-  // Compress char[] to byte[]. odd_reg contains cnt. tmp3 is only needed for precise behavior in failure case. Kills dst.
-  unsigned int string_compress(Register result, Register src, Register dst, Register odd_reg,
-                               Register even_reg, Register tmp, Register tmp2 = noreg);
+  //   Restores: src, dst
+  //   Uses:     cnt
+  //   Kills:    tmp, Z_R0, Z_R1.
+  //   Early clobber: result.
+  //   Boolean precise controls accuracy of result value.
+  unsigned int string_compress(Register result, Register src, Register dst, Register cnt,
+                               Register tmp,    bool precise);
+
+  // Inflate byte[] to char[].
+  unsigned int string_inflate_trot(Register src, Register dst, Register cnt, Register tmp);
+
+  // Inflate byte[] to char[].
+  //   Restores: src, dst
+  //   Uses:     cnt
+  //   Kills:    tmp, Z_R0, Z_R1.
+  unsigned int string_inflate(Register src, Register dst, Register cnt, Register tmp);
+
+  // Inflate byte[] to char[], length known at compile time.
+  //   Restores: src, dst
+  //   Kills:    tmp, Z_R0, Z_R1.
+  // Note:
+  //   len is signed int. Counts # characters, not bytes.
+  unsigned int string_inflate_const(Register src, Register dst, Register tmp, int len);
 
   // Kills src.
   unsigned int has_negatives(Register result, Register src, Register cnt,
                              Register odd_reg, Register even_reg, Register tmp);
 
-  // Inflate byte[] to char[].
-  unsigned int string_inflate_trot(Register src, Register dst, Register cnt, Register tmp);
-  // Odd_reg contains cnt. Kills src.
-  unsigned int string_inflate(Register src, Register dst, Register odd_reg,
-                              Register even_reg, Register tmp);
-
   unsigned int string_compare(Register str1, Register str2, Register cnt1, Register cnt2,
                               Register odd_reg, Register even_reg, Register result, int ae);
 
--- a/src/hotspot/cpu/s390/s390.ad	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/hotspot/cpu/s390/s390.ad	Mon Nov 27 17:04:45 2017 +0000
@@ -10267,14 +10267,14 @@
 %}
 
 // char[] to byte[] compression
-instruct string_compress(iRegP src, rarg5RegP dst, iRegI result, roddRegI len, revenRegI evenReg, iRegI tmp, flagsReg cr) %{
+instruct string_compress(iRegP src, iRegP dst, iRegI result, iRegI len, iRegI tmp, flagsReg cr) %{
   match(Set result (StrCompressedCopy src (Binary dst len)));
-  effect(TEMP_DEF result, USE_KILL dst, USE_KILL len, TEMP evenReg, TEMP tmp, KILL cr); // R0, R1 are killed, too.
+  effect(TEMP_DEF result, TEMP tmp, KILL cr); // R0, R1 are killed, too.
   ins_cost(300);
   format %{ "String Compress $src->$dst($len) -> $result" %}
   ins_encode %{
     __ string_compress($result$$Register, $src$$Register, $dst$$Register, $len$$Register,
-                       $evenReg$$Register, $tmp$$Register);
+                       $tmp$$Register, false);
   %}
   ins_pipe(pipe_class_dummy);
 %}
@@ -10293,13 +10293,25 @@
 //%}
 
 // byte[] to char[] inflation
-instruct string_inflate(Universe dummy, rarg5RegP src, iRegP dst, roddRegI len, revenRegI evenReg, iRegI tmp, flagsReg cr) %{
+instruct string_inflate(Universe dummy, iRegP src, iRegP dst, iRegI len, iRegI tmp, flagsReg cr) %{
   match(Set dummy (StrInflatedCopy src (Binary dst len)));
-  effect(USE_KILL src, USE_KILL len, TEMP evenReg, TEMP tmp, KILL cr); // R0, R1 are killed, too.
+  effect(TEMP tmp, KILL cr); // R0, R1 are killed, too.
   ins_cost(300);
   format %{ "String Inflate $src->$dst($len)" %}
   ins_encode %{
-    __ string_inflate($src$$Register, $dst$$Register, $len$$Register, $evenReg$$Register, $tmp$$Register);
+    __ string_inflate($src$$Register, $dst$$Register, $len$$Register, $tmp$$Register);
+  %}
+  ins_pipe(pipe_class_dummy);
+%}
+
+// byte[] to char[] inflation
+instruct string_inflate_const(Universe dummy, iRegP src, iRegP dst, iRegI tmp, immI len, flagsReg cr) %{
+  match(Set dummy (StrInflatedCopy src (Binary dst len)));
+  effect(TEMP tmp, KILL cr); // R0, R1 are killed, too.
+  ins_cost(300);
+  format %{ "String Inflate (constLen) $src->$dst($len)" %}
+  ins_encode %{
+    __ string_inflate_const($src$$Register, $dst$$Register, $tmp$$Register, $len$$constant);
   %}
   ins_pipe(pipe_class_dummy);
 %}
@@ -10318,14 +10330,14 @@
 %}
 
 // encode char[] to byte[] in ISO_8859_1
-instruct encode_iso_array(rarg5RegP src, iRegP dst, iRegI result, roddRegI len, revenRegI evenReg, iRegI tmp, iRegI tmp2, flagsReg cr) %{
+instruct encode_iso_array(iRegP src, iRegP dst, iRegI result, iRegI len, iRegI tmp, flagsReg cr) %{
   match(Set result (EncodeISOArray src (Binary dst len)));
-  effect(TEMP_DEF result, USE_KILL src, USE_KILL len, TEMP evenReg, TEMP tmp, TEMP tmp2, KILL cr); // R0, R1 are killed, too.
+  effect(TEMP_DEF result, TEMP tmp, KILL cr); // R0, R1 are killed, too.
   ins_cost(300);
   format %{ "Encode array $src->$dst($len) -> $result" %}
   ins_encode %{
     __ string_compress($result$$Register, $src$$Register, $dst$$Register, $len$$Register,
-                       $evenReg$$Register, $tmp$$Register, $tmp2$$Register);
+                       $tmp$$Register, true);
   %}
   ins_pipe(pipe_class_dummy);
 %}
--- a/src/hotspot/cpu/sparc/c1_LIRAssembler_sparc.cpp	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/hotspot/cpu/sparc/c1_LIRAssembler_sparc.cpp	Mon Nov 27 17:04:45 2017 +0000
@@ -398,8 +398,13 @@
   if (o == NULL) {
     __ set(NULL_WORD, reg);
   } else {
+#ifdef ASSERT
+    {
+      ThreadInVMfromNative tiv(JavaThread::current());
+      assert(Universe::heap()->is_in_reserved(JNIHandles::resolve(o)), "should be real oop");
+    }
+#endif
     int oop_index = __ oop_recorder()->find_index(o);
-    assert(Universe::heap()->is_in_reserved(JNIHandles::resolve(o)), "should be real oop");
     RelocationHolder rspec = oop_Relocation::spec(oop_index);
     __ set(NULL_WORD, reg, rspec); // Will be set when the nmethod is created
   }
--- a/src/hotspot/cpu/sparc/stubGenerator_sparc.cpp	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/hotspot/cpu/sparc/stubGenerator_sparc.cpp	Mon Nov 27 17:04:45 2017 +0000
@@ -898,7 +898,9 @@
           assert(sizeof(*ct->byte_map_base) == sizeof(jbyte), "adjust this code");
           assert_different_registers(addr, count, tmp);
 
-          Label L_loop;
+          Label L_loop, L_done;
+
+          __ cmp_and_br_short(count, 0, Assembler::equal, Assembler::pt, L_done); // zero count - nothing to do
 
           __ sll_ptr(count, LogBytesPerHeapOop, count);
           __ sub(count, BytesPerHeapOop, count);
@@ -914,6 +916,7 @@
           __ subcc(count, 1, count);
           __ brx(Assembler::greaterEqual, false, Assembler::pt, L_loop);
           __ delayed()->add(addr, 1, addr);
+        __ BIND(L_done);
         }
         break;
       case BarrierSet::ModRef:
--- a/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp	Mon Nov 27 17:04:45 2017 +0000
@@ -1264,9 +1264,12 @@
           CardTableModRefBS* ct = barrier_set_cast<CardTableModRefBS>(bs);
           assert(sizeof(*ct->byte_map_base) == sizeof(jbyte), "adjust this code");
 
-          Label L_loop;
+          Label L_loop, L_done;
           const Register end = count;
 
+          __ testl(count, count);
+          __ jcc(Assembler::zero, L_done); // zero count - nothing to do
+
           __ leaq(end, Address(start, count, TIMES_OOP, 0));  // end == start+count*oop_size
           __ subptr(end, BytesPerHeapOop); // end - 1 to make inclusive
           __ shrptr(start, CardTableModRefBS::card_shift);
@@ -1280,6 +1283,7 @@
           __ movb(Address(start, count, Address::times_1), 0);
           __ decrement(count);
           __ jcc(Assembler::greaterEqual, L_loop);
+        __ BIND(L_done);
         }
         break;
       default:
--- a/src/hotspot/os/linux/os_linux.cpp	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/hotspot/os/linux/os_linux.cpp	Mon Nov 27 17:04:45 2017 +0000
@@ -59,6 +59,7 @@
 #include "runtime/stubRoutines.hpp"
 #include "runtime/thread.inline.hpp"
 #include "runtime/threadCritical.hpp"
+#include "runtime/threadSMR.hpp"
 #include "runtime/timer.hpp"
 #include "semaphore_posix.hpp"
 #include "services/attachListener.hpp"
@@ -1646,7 +1647,10 @@
         //
         // Dynamic loader will make all stacks executable after
         // this function returns, and will not do that again.
-        assert(Threads::first() == NULL, "no Java threads should exist yet.");
+#ifdef ASSERT
+        ThreadsListHandle tlh;
+        assert(tlh.length() == 0, "no Java threads should exist yet.");
+#endif
       } else {
         warning("You have loaded library %s which might have disabled stack guard. "
                 "The VM will try to fix the stack guard now.\n"
@@ -1874,16 +1878,13 @@
   // may have been queued at the same time.
 
   if (!_stack_is_executable) {
-    JavaThread *jt = Threads::first();
-
-    while (jt) {
+    for (JavaThreadIteratorWithHandle jtiwh; JavaThread *jt = jtiwh.next(); ) {
       if (!jt->stack_guard_zone_unused() &&     // Stack not yet fully initialized
           jt->stack_guards_enabled()) {         // No pending stack overflow exceptions
         if (!os::guard_memory((char *)jt->stack_end(), jt->stack_guard_zone_size())) {
           warning("Attempt to reguard stack yellow zone failed.");
         }
       }
-      jt = jt->next();
     }
   }
 
@@ -4947,25 +4948,20 @@
         UseNUMA = false;
       }
     }
-    // With SHM and HugeTLBFS large pages we cannot uncommit a page, so there's no way
-    // we can make the adaptive lgrp chunk resizing work. If the user specified
-    // both UseNUMA and UseLargePages (or UseSHM/UseHugeTLBFS) on the command line - warn and
-    // disable adaptive resizing.
-    if (UseNUMA && UseLargePages && !can_commit_large_page_memory()) {
-      if (FLAG_IS_DEFAULT(UseNUMA)) {
-        UseNUMA = false;
-      } else {
-        if (FLAG_IS_DEFAULT(UseLargePages) &&
-            FLAG_IS_DEFAULT(UseSHM) &&
-            FLAG_IS_DEFAULT(UseHugeTLBFS)) {
-          UseLargePages = false;
-        } else if (UseAdaptiveSizePolicy || UseAdaptiveNUMAChunkSizing) {
-          warning("UseNUMA is not fully compatible with SHM/HugeTLBFS large pages, disabling adaptive resizing (-XX:-UseAdaptiveSizePolicy -XX:-UseAdaptiveNUMAChunkSizing)");
-          UseAdaptiveSizePolicy = false;
-          UseAdaptiveNUMAChunkSizing = false;
-        }
+
+    if (UseParallelGC && UseNUMA && UseLargePages && !can_commit_large_page_memory()) {
+      // With SHM and HugeTLBFS large pages we cannot uncommit a page, so there's no way
+      // we can make the adaptive lgrp chunk resizing work. If the user specified both
+      // UseNUMA and UseLargePages (or UseSHM/UseHugeTLBFS) on the command line - warn
+      // and disable adaptive resizing.
+      if (UseAdaptiveSizePolicy || UseAdaptiveNUMAChunkSizing) {
+        warning("UseNUMA is not fully compatible with SHM/HugeTLBFS large pages, "
+                "disabling adaptive resizing (-XX:-UseAdaptiveSizePolicy -XX:-UseAdaptiveNUMAChunkSizing)");
+        UseAdaptiveSizePolicy = false;
+        UseAdaptiveNUMAChunkSizing = false;
       }
     }
+
     if (!UseNUMA && ForceNUMA) {
       UseNUMA = true;
     }
--- a/src/hotspot/os/posix/os_posix.cpp	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/hotspot/os/posix/os_posix.cpp	Mon Nov 27 17:04:45 2017 +0000
@@ -478,8 +478,7 @@
 // interrupt support
 
 void os::interrupt(Thread* thread) {
-  assert(Thread::current() == thread || Threads_lock->owned_by_self(),
-    "possibility of dangling Thread pointer");
+  debug_only(Thread::check_for_dangling_thread_pointer(thread);)
 
   OSThread* osthread = thread->osthread();
 
@@ -499,12 +498,10 @@
 
   ParkEvent * ev = thread->_ParkEvent ;
   if (ev != NULL) ev->unpark() ;
-
 }
 
 bool os::is_interrupted(Thread* thread, bool clear_interrupted) {
-  assert(Thread::current() == thread || Threads_lock->owned_by_self(),
-    "possibility of dangling Thread pointer");
+  debug_only(Thread::check_for_dangling_thread_pointer(thread);)
 
   OSThread* osthread = thread->osthread();
 
--- a/src/hotspot/os/windows/os_windows.cpp	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/hotspot/os/windows/os_windows.cpp	Mon Nov 27 17:04:45 2017 +0000
@@ -3490,9 +3490,7 @@
 void os::hint_no_preempt() {}
 
 void os::interrupt(Thread* thread) {
-  assert(!thread->is_Java_thread() || Thread::current() == thread ||
-         Threads_lock->owned_by_self(),
-         "possibility of dangling Thread pointer");
+  debug_only(Thread::check_for_dangling_thread_pointer(thread);)
 
   OSThread* osthread = thread->osthread();
   osthread->set_interrupted(true);
@@ -3513,8 +3511,7 @@
 
 
 bool os::is_interrupted(Thread* thread, bool clear_interrupted) {
-  assert(!thread->is_Java_thread() || Thread::current() == thread || Threads_lock->owned_by_self(),
-         "possibility of dangling Thread pointer");
+  debug_only(Thread::check_for_dangling_thread_pointer(thread);)
 
   OSThread* osthread = thread->osthread();
   // There is no synchronization between the setting of the interrupt
--- a/src/hotspot/os_cpu/linux_zero/atomic_linux_zero.hpp	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/hotspot/os_cpu/linux_zero/atomic_linux_zero.hpp	Mon Nov 27 17:04:45 2017 +0000
@@ -30,74 +30,6 @@
 
 // Implementation of class atomic
 
-#ifdef M68K
-
-/*
- * __m68k_cmpxchg
- *
- * Atomically store newval in *ptr if *ptr is equal to oldval for user space.
- * Returns newval on success and oldval if no exchange happened.
- * This implementation is processor specific and works on
- * 68020 68030 68040 and 68060.
- *
- * It will not work on ColdFire, 68000 and 68010 since they lack the CAS
- * instruction.
- * Using a kernelhelper would be better for arch complete implementation.
- *
- */
-
-static inline int __m68k_cmpxchg(int oldval, int newval, volatile int *ptr) {
-  int ret;
-  __asm __volatile ("cas%.l %0,%2,%1"
-                   : "=d" (ret), "+m" (*(ptr))
-                   : "d" (newval), "0" (oldval));
-  return ret;
-}
-
-/* Perform an atomic compare and swap: if the current value of `*PTR'
-   is OLDVAL, then write NEWVAL into `*PTR'.  Return the contents of
-   `*PTR' before the operation.*/
-static inline int m68k_compare_and_swap(int newval,
-                                        volatile int *ptr,
-                                        int oldval) {
-  for (;;) {
-      int prev = *ptr;
-      if (prev != oldval)
-        return prev;
-
-      if (__m68k_cmpxchg (prev, newval, ptr) == newval)
-        // Success.
-        return prev;
-
-      // We failed even though prev == oldval.  Try again.
-    }
-}
-
-/* Atomically add an int to memory.  */
-static inline int m68k_add_and_fetch(int add_value, volatile int *ptr) {
-  for (;;) {
-      // Loop until success.
-
-      int prev = *ptr;
-
-      if (__m68k_cmpxchg (prev, prev + add_value, ptr) == prev + add_value)
-        return prev + add_value;
-    }
-}
-
-/* Atomically write VALUE into `*PTR' and returns the previous
-   contents of `*PTR'.  */
-static inline int m68k_lock_test_and_set(int newval, volatile int *ptr) {
-  for (;;) {
-      // Loop until success.
-      int prev = *ptr;
-
-      if (__m68k_cmpxchg (prev, newval, ptr) == prev)
-        return prev;
-    }
-}
-#endif // M68K
-
 #ifdef ARM
 
 /*
@@ -176,11 +108,7 @@
 #ifdef ARM
   return add_using_helper<int>(arm_add_and_fetch, add_value, dest);
 #else
-#ifdef M68K
-  return add_using_helper<int>(m68k_add_and_fetch, add_value, dest);
-#else
   return __sync_add_and_fetch(dest, add_value);
-#endif // M68K
 #endif // ARM
 }
 
@@ -201,9 +129,6 @@
 #ifdef ARM
   return xchg_using_helper<int>(arm_lock_test_and_set, exchange_value, dest);
 #else
-#ifdef M68K
-  return xchg_using_helper<int>(m68k_lock_test_and_set, exchange_value, dest);
-#else
   // __sync_lock_test_and_set is a bizarrely named atomic exchange
   // operation.  Note that some platforms only support this with the
   // limitation that the only valid value to store is the immediate
@@ -215,7 +140,6 @@
   // barrier.
   __sync_synchronize();
   return result;
-#endif // M68K
 #endif // ARM
 }
 
@@ -243,11 +167,7 @@
 #ifdef ARM
   return cmpxchg_using_helper<int>(arm_compare_and_swap, exchange_value, dest, compare_value);
 #else
-#ifdef M68K
-  return cmpxchg_using_helper<int>(m68k_compare_and_swap, exchange_value, dest, compare_value);
-#else
   return __sync_val_compare_and_swap(dest, compare_value, exchange_value);
-#endif // M68K
 #endif // ARM
 }
 
--- a/src/hotspot/share/c1/c1_GraphBuilder.cpp	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/hotspot/share/c1/c1_GraphBuilder.cpp	Mon Nov 27 17:04:45 2017 +0000
@@ -3441,6 +3441,7 @@
   if ( callee->is_native())            return "native method";
   if ( callee->is_abstract())          return "abstract method";
   if (!callee->can_be_compiled())      return "not compilable (disabled)";
+  if (!callee->can_be_parsed())        return "cannot be parsed";
   return NULL;
 }
 
--- a/src/hotspot/share/ci/ciMethod.cpp	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/hotspot/share/ci/ciMethod.cpp	Mon Nov 27 17:04:45 2017 +0000
@@ -87,6 +87,7 @@
   _balanced_monitors  = !_uses_monitors || h_m()->access_flags().is_monitor_matching();
   _is_c1_compilable   = !h_m()->is_not_c1_compilable();
   _is_c2_compilable   = !h_m()->is_not_c2_compilable();
+  _can_be_parsed      = true;
   _has_reserved_stack_access = h_m()->has_reserved_stack_access();
   // Lazy fields, filled in on demand.  Require allocation.
   _code               = NULL;
@@ -99,12 +100,13 @@
 #endif // COMPILER2
 
   ciEnv *env = CURRENT_ENV;
-  if (env->jvmti_can_hotswap_or_post_breakpoint() && can_be_compiled()) {
+  if (env->jvmti_can_hotswap_or_post_breakpoint()) {
     // 6328518 check hotswap conditions under the right lock.
     MutexLocker locker(Compile_lock);
     if (Dependencies::check_evol_method(h_m()) != NULL) {
       _is_c1_compilable = false;
       _is_c2_compilable = false;
+      _can_be_parsed = false;
     }
   } else {
     CHECK_UNHANDLED_OOPS_ONLY(Thread::current()->clear_unhandled_oops());
--- a/src/hotspot/share/ci/ciMethod.hpp	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/hotspot/share/ci/ciMethod.hpp	Mon Nov 27 17:04:45 2017 +0000
@@ -87,6 +87,7 @@
   bool _balanced_monitors;
   bool _is_c1_compilable;
   bool _is_c2_compilable;
+  bool _can_be_parsed;
   bool _can_be_statically_bound;
   bool _has_reserved_stack_access;
 
@@ -291,6 +292,7 @@
   bool has_option(const char *option);
   bool has_option_value(const char* option, double& value);
   bool can_be_compiled();
+  bool can_be_parsed() const { return _can_be_parsed; }
   bool can_be_osr_compiled(int entry_bci);
   void set_not_compilable(const char* reason = NULL);
   bool has_compiled_code();
--- a/src/hotspot/share/classfile/classLoader.hpp	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/hotspot/share/classfile/classLoader.hpp	Mon Nov 27 17:04:45 2017 +0000
@@ -26,6 +26,7 @@
 #define SHARE_VM_CLASSFILE_CLASSLOADER_HPP
 
 #include "jimage.hpp"
+#include "runtime/handles.hpp"
 #include "runtime/orderAccess.hpp"
 #include "runtime/perfData.hpp"
 #include "utilities/exceptions.hpp"
@@ -42,6 +43,7 @@
 class JImageFile;
 class ClassFileStream;
 class PackageEntry;
+template <typename T> class GrowableArray;
 
 class ClassPathEntry : public CHeapObj<mtClass> {
 private:
--- a/src/hotspot/share/code/codeCache.cpp	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/hotspot/share/code/codeCache.cpp	Mon Nov 27 17:04:45 2017 +0000
@@ -259,12 +259,12 @@
   }
 
   // We do not need the profiled CodeHeap, use all space for the non-profiled CodeHeap
-  if(!heap_available(CodeBlobType::MethodProfiled)) {
+  if (!heap_available(CodeBlobType::MethodProfiled)) {
     non_profiled_size += profiled_size;
     profiled_size = 0;
   }
   // We do not need the non-profiled CodeHeap, use all space for the non-nmethod CodeHeap
-  if(!heap_available(CodeBlobType::MethodNonProfiled)) {
+  if (!heap_available(CodeBlobType::MethodNonProfiled)) {
     non_nmethod_size += non_profiled_size;
     non_profiled_size = 0;
   }
@@ -282,10 +282,11 @@
   FLAG_SET_ERGO(uintx, ProfiledCodeHeapSize, profiled_size);
   FLAG_SET_ERGO(uintx, NonProfiledCodeHeapSize, non_profiled_size);
 
-  // Align CodeHeaps
-  size_t alignment = heap_alignment();
+  // If large page support is enabled, align code heaps according to large
+  // page size to make sure that code cache is covered by large pages.
+  const size_t alignment = MAX2(page_size(false), (size_t) os::vm_allocation_granularity());
   non_nmethod_size = align_up(non_nmethod_size, alignment);
-  profiled_size   = align_down(profiled_size, alignment);
+  profiled_size    = align_down(profiled_size, alignment);
 
   // Reserve one continuous chunk of memory for CodeHeaps and split it into
   // parts for the individual heaps. The memory layout looks like this:
@@ -308,37 +309,29 @@
   add_heap(non_profiled_space, "CodeHeap 'non-profiled nmethods'", CodeBlobType::MethodNonProfiled);
 }
 
-size_t CodeCache::heap_alignment() {
-  // If large page support is enabled, align code heaps according to large
-  // page size to make sure that code cache is covered by large pages.
-  const size_t page_size = os::can_execute_large_page_memory() ?
-             os::page_size_for_region_unaligned(ReservedCodeCacheSize, 8) :
-             os::vm_page_size();
-  return MAX2(page_size, (size_t) os::vm_allocation_granularity());
+size_t CodeCache::page_size(bool aligned) {
+  if (os::can_execute_large_page_memory()) {
+    return aligned ? os::page_size_for_region_aligned(ReservedCodeCacheSize, 8) :
+                     os::page_size_for_region_unaligned(ReservedCodeCacheSize, 8);
+  } else {
+    return os::vm_page_size();
+  }
 }
 
 ReservedCodeSpace CodeCache::reserve_heap_memory(size_t size) {
-  // Determine alignment
-  const size_t page_size = os::can_execute_large_page_memory() ?
-          MIN2(os::page_size_for_region_aligned(InitialCodeCacheSize, 8),
-               os::page_size_for_region_aligned(size, 8)) :
-          os::vm_page_size();
-  const size_t granularity = os::vm_allocation_granularity();
-  const size_t r_align = MAX2(page_size, granularity);
-  const size_t r_size = align_up(size, r_align);
-  const size_t rs_align = page_size == (size_t) os::vm_page_size() ? 0 :
-    MAX2(page_size, granularity);
-
-  ReservedCodeSpace rs(r_size, rs_align, rs_align > 0);
-
+  // Align and reserve space for code cache
+  const size_t rs_ps = page_size();
+  const size_t rs_align = MAX2(rs_ps, (size_t) os::vm_allocation_granularity());
+  const size_t rs_size = align_up(size, rs_align);
+  ReservedCodeSpace rs(rs_size, rs_align, rs_ps > (size_t) os::vm_page_size());
   if (!rs.is_reserved()) {
-    vm_exit_during_initialization("Could not reserve enough space for code cache");
+    vm_exit_during_initialization(err_msg("Could not reserve enough space for code cache (" SIZE_FORMAT "K)",
+                                          rs_size/K));
   }
 
   // Initialize bounds
   _low_bound = (address)rs.base();
   _high_bound = _low_bound + rs.size();
-
   return rs;
 }
 
@@ -415,7 +408,8 @@
   size_t size_initial = MIN2(InitialCodeCacheSize, rs.size());
   size_initial = align_up(size_initial, os::vm_page_size());
   if (!heap->reserve(rs, size_initial, CodeCacheSegmentSize)) {
-    vm_exit_during_initialization("Could not reserve enough space for code cache");
+    vm_exit_during_initialization(err_msg("Could not reserve enough space in %s (" SIZE_FORMAT "K)",
+                                          heap->name(), size_initial/K));
   }
 
   // Register the CodeHeap
--- a/src/hotspot/share/code/codeCache.hpp	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/hotspot/share/code/codeCache.hpp	Mon Nov 27 17:04:45 2017 +0000
@@ -107,7 +107,7 @@
   static CodeHeap* get_code_heap(int code_blob_type);         // Returns the CodeHeap for the given CodeBlobType
   // Returns the name of the VM option to set the size of the corresponding CodeHeap
   static const char* get_code_heap_flag_name(int code_blob_type);
-  static size_t heap_alignment();                             // Returns the alignment of the CodeHeaps in bytes
+  static size_t page_size(bool aligned = true);               // Returns the page size used by the CodeCache
   static ReservedCodeSpace reserve_heap_memory(size_t size);  // Reserves one continuous chunk of memory for the CodeHeaps
 
   // Iteration
--- a/src/hotspot/share/code/debugInfo.cpp	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/hotspot/share/code/debugInfo.cpp	Mon Nov 27 17:04:45 2017 +0000
@@ -28,6 +28,8 @@
 #include "code/nmethod.hpp"
 #include "oops/oop.inline.hpp"
 #include "runtime/handles.inline.hpp"
+#include "runtime/interfaceSupport.hpp"
+#include "runtime/thread.hpp"
 
 // Constructors
 
@@ -209,14 +211,24 @@
 // ConstantOopWriteValue
 
 void ConstantOopWriteValue::write_on(DebugInfoWriteStream* stream) {
-  assert(JNIHandles::resolve(value()) == NULL ||
-         Universe::heap()->is_in_reserved(JNIHandles::resolve(value())),
-         "Should be in heap");
+#ifdef ASSERT
+  {
+    // cannot use ThreadInVMfromNative here since in case of JVMCI compiler,
+    // thread is already in VM state.
+    ThreadInVMfromUnknown tiv;
+    assert(JNIHandles::resolve(value()) == NULL ||
+           Universe::heap()->is_in_reserved(JNIHandles::resolve(value())),
+           "Should be in heap");
+ }
+#endif
   stream->write_int(CONSTANT_OOP_CODE);
   stream->write_handle(value());
 }
 
 void ConstantOopWriteValue::print_on(outputStream* st) const {
+  // using ThreadInVMfromUnknown here since in case of JVMCI compiler,
+  // thread is already in VM state.
+  ThreadInVMfromUnknown tiv;
   JNIHandles::resolve(value())->print_value_on(st);
 }
 
--- a/src/hotspot/share/code/stubs.cpp	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/hotspot/share/code/stubs.cpp	Mon Nov 27 17:04:45 2017 +0000
@@ -78,7 +78,6 @@
   _queue_begin     = 0;
   _queue_end       = 0;
   _number_of_stubs = 0;
-  register_queue(this);
 }
 
 
@@ -205,36 +204,6 @@
 }
 
 
-enum { StubQueueLimit = 10 };  // there are only a few in the world
-static StubQueue* registered_stub_queues[StubQueueLimit];
-
-void StubQueue::register_queue(StubQueue* sq) {
-  for (int i = 0; i < StubQueueLimit; i++) {
-    if (registered_stub_queues[i] == NULL) {
-      registered_stub_queues[i] = sq;
-      return;
-    }
-  }
-  ShouldNotReachHere();
-}
-
-
-void StubQueue::queues_do(void f(StubQueue* sq)) {
-  for (int i = 0; i < StubQueueLimit; i++) {
-    if (registered_stub_queues[i] != NULL) {
-      f(registered_stub_queues[i]);
-    }
-  }
-}
-
-
-void StubQueue::stubs_do(void f(Stub* s)) {
-  debug_only(verify();)
-  MutexLockerEx lock(_mutex);
-  for (Stub* s = first(); s != NULL; s = next(s)) f(s);
-}
-
-
 void StubQueue::verify() {
   // verify only if initialized
   if (_stub_buffer == NULL) return;
--- a/src/hotspot/share/code/stubs.hpp	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/hotspot/share/code/stubs.hpp	Mon Nov 27 17:04:45 2017 +0000
@@ -172,8 +172,6 @@
   void  stub_verify(Stub* s)                     { _stub_interface->verify(s); }
   void  stub_print(Stub* s)                      { _stub_interface->print(s); }
 
-  static void register_queue(StubQueue*);
-
  public:
   StubQueue(StubInterface* stub_interface, int buffer_size, Mutex* lock,
             const char* name);
@@ -204,8 +202,6 @@
   void deallocate_unused_tail();                 // deallocate the unused tail of the underlying CodeBlob
                                                  // only used from TemplateInterpreter::initialize()
   // Iteration
-  static void queues_do(void f(StubQueue* s));   // call f with each StubQueue
-  void  stubs_do(void f(Stub* s));               // call f with all stubs
   Stub* first() const                            { return number_of_stubs() > 0 ? stub_at(_queue_begin) : NULL; }
   Stub* next(Stub* s) const                      { int i = index_of(s) + stub_size(s);
                                                    // Only wrap around in the non-contiguous case (see stubss.cpp)
@@ -213,9 +209,6 @@
                                                    return (i == _queue_end) ? NULL : stub_at(i);
                                                  }
 
-  address stub_code_begin(Stub* s) const         { return _stub_interface->code_begin(s); }
-  address stub_code_end(Stub* s) const           { return _stub_interface->code_end(s);   }
-
   // Debugging/printing
   void  verify();                                // verifies the stub queue
   void  print();                                 // prints information about the stub queue
--- a/src/hotspot/share/gc/cms/cmsCollectorPolicy.cpp	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/hotspot/share/gc/cms/cmsCollectorPolicy.cpp	Mon Nov 27 17:04:45 2017 +0000
@@ -71,6 +71,6 @@
 }
 
 void ConcurrentMarkSweepPolicy::initialize_gc_policy_counters() {
-  // initialize the policy counters - 2 collectors, 3 generations
-  _gc_policy_counters = new GCPolicyCounters("ParNew:CMS", 2, 3);
+  // initialize the policy counters - 2 collectors, 2 generations
+  _gc_policy_counters = new GCPolicyCounters("ParNew:CMS", 2, 2);
 }
--- a/src/hotspot/share/gc/g1/dirtyCardQueue.cpp	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/hotspot/share/gc/g1/dirtyCardQueue.cpp	Mon Nov 27 17:04:45 2017 +0000
@@ -32,6 +32,7 @@
 #include "runtime/mutexLocker.hpp"
 #include "runtime/safepoint.hpp"
 #include "runtime/thread.inline.hpp"
+#include "runtime/threadSMR.hpp"
 
 // Closure used for updating remembered sets and recording references that
 // point into the collection set while the mutator is running.
@@ -319,7 +320,7 @@
   clear();
   // Since abandon is done only at safepoints, we can safely manipulate
   // these queues.
-  for (JavaThread* t = Threads::first(); t; t = t->next()) {
+  for (JavaThreadIteratorWithHandle jtiwh; JavaThread *t = jtiwh.next(); ) {
     t->dirty_card_queue().reset();
   }
   shared_dirty_card_queue()->reset();
@@ -338,7 +339,7 @@
   int save_max_completed_queue = _max_completed_queue;
   _max_completed_queue = max_jint;
   assert(SafepointSynchronize::is_at_safepoint(), "Must be at safepoint.");
-  for (JavaThread* t = Threads::first(); t; t = t->next()) {
+  for (JavaThreadIteratorWithHandle jtiwh; JavaThread *t = jtiwh.next(); ) {
     concatenate_log(t->dirty_card_queue());
   }
   concatenate_log(_shared_dirty_card_queue);
--- a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp	Mon Nov 27 17:04:45 2017 +0000
@@ -39,7 +39,6 @@
 #include "gc/g1/g1ConcurrentRefineThread.hpp"
 #include "gc/g1/g1EvacStats.inline.hpp"
 #include "gc/g1/g1FullCollector.hpp"
-#include "gc/g1/g1FullGCScope.hpp"
 #include "gc/g1/g1GCPhaseTimes.hpp"
 #include "gc/g1/g1HeapSizingPolicy.hpp"
 #include "gc/g1/g1HeapTransition.hpp"
@@ -81,6 +80,7 @@
 #include "runtime/atomic.hpp"
 #include "runtime/init.hpp"
 #include "runtime/orderAccess.inline.hpp"
+#include "runtime/threadSMR.hpp"
 #include "runtime/vmThread.hpp"
 #include "utilities/align.hpp"
 #include "utilities/globalDefinitions.hpp"
@@ -1217,34 +1217,6 @@
 #endif
 }
 
-void G1CollectedHeap::do_full_collection_inner(G1FullGCScope* scope) {
-  GCTraceTime(Info, gc) tm("Pause Full", NULL, gc_cause(), true);
-  g1_policy()->record_full_collection_start();
-
-  print_heap_before_gc();
-  print_heap_regions();
-
-  abort_concurrent_cycle();
-  verify_before_full_collection(scope->is_explicit_gc());
-
-  gc_prologue(true);
-  prepare_heap_for_full_collection();
-
-  G1FullCollector collector(scope, ref_processor_stw(), concurrent_mark()->next_mark_bitmap(), workers()->active_workers());
-  collector.prepare_collection();
-  collector.collect();
-  collector.complete_collection();
-
-  prepare_heap_for_mutators();
-
-  g1_policy()->record_full_collection_end();
-  gc_epilogue(true);
-
-  verify_after_full_collection();
-
-  print_heap_after_full_collection(scope->heap_transition());
-}
-
 bool G1CollectedHeap::do_full_collection(bool explicit_gc,
                                          bool clear_all_soft_refs) {
   assert_at_safepoint(true /* should_be_vm_thread */);
@@ -1257,8 +1229,12 @@
   const bool do_clear_all_soft_refs = clear_all_soft_refs ||
       collector_policy()->should_clear_all_soft_refs();
 
-  G1FullGCScope scope(explicit_gc, do_clear_all_soft_refs);
-  do_full_collection_inner(&scope);
+  G1FullCollector collector(this, explicit_gc, do_clear_all_soft_refs);
+  GCTraceTime(Info, gc) tm("Pause Full", NULL, gc_cause(), true);
+
+  collector.prepare_collection();
+  collector.collect();
+  collector.complete_collection();
 
   // Full collection was successfully completed.
   return true;
@@ -2653,11 +2629,9 @@
 
 size_t G1CollectedHeap::pending_card_num() {
   size_t extra_cards = 0;
-  JavaThread *curr = Threads::first();
-  while (curr != NULL) {
+  for (JavaThreadIteratorWithHandle jtiwh; JavaThread *curr = jtiwh.next(); ) {
     DirtyCardQueue& dcq = curr->dirty_card_queue();
     extra_cards += dcq.size();
-    curr = curr->next();
   }
   DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
   size_t buffer_size = dcqs.buffer_size();
--- a/src/hotspot/share/gc/g1/g1CollectedHeap.hpp	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/hotspot/share/gc/g1/g1CollectedHeap.hpp	Mon Nov 27 17:04:45 2017 +0000
@@ -42,11 +42,11 @@
 #include "gc/g1/g1SATBCardTableModRefBS.hpp"
 #include "gc/g1/g1SurvivorRegions.hpp"
 #include "gc/g1/g1YCTypes.hpp"
-#include "gc/g1/hSpaceCounters.hpp"
 #include "gc/g1/heapRegionManager.hpp"
 #include "gc/g1/heapRegionSet.hpp"
 #include "gc/shared/barrierSet.hpp"
 #include "gc/shared/collectedHeap.hpp"
+#include "gc/shared/gcHeapSummary.hpp"
 #include "gc/shared/plab.hpp"
 #include "gc/shared/preservedMarks.hpp"
 #include "memory/memRegion.hpp"
@@ -126,6 +126,7 @@
   friend class VM_G1IncCollectionPause;
   friend class VMStructs;
   friend class MutatorAllocRegion;
+  friend class G1FullCollector;
   friend class G1GCAllocRegion;
   friend class G1HeapVerifier;
 
@@ -517,7 +518,6 @@
 private:
   // Internal helpers used during full GC to split it up to
   // increase readability.
-  void do_full_collection_inner(G1FullGCScope* scope);
   void abort_concurrent_cycle();
   void verify_before_full_collection(bool explicit_gc);
   void prepare_heap_for_full_collection();
--- a/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp	Mon Nov 27 17:04:45 2017 +0000
@@ -1756,28 +1756,24 @@
   G1ConcurrentMark* _cm;
 public:
   void work(uint worker_id) {
-    // Since all available tasks are actually started, we should
-    // only proceed if we're supposed to be active.
-    if (worker_id < _cm->active_tasks()) {
-      G1CMTask* task = _cm->task(worker_id);
-      task->record_start_time();
-      {
-        ResourceMark rm;
-        HandleMark hm;
-
-        G1RemarkThreadsClosure threads_f(G1CollectedHeap::heap(), task);
-        Threads::threads_do(&threads_f);
-      }
-
-      do {
-        task->do_marking_step(1000000000.0 /* something very large */,
-                              true         /* do_termination       */,
-                              false        /* is_serial            */);
-      } while (task->has_aborted() && !_cm->has_overflown());
-      // If we overflow, then we do not want to restart. We instead
-      // want to abort remark and do concurrent marking again.
-      task->record_end_time();
+    G1CMTask* task = _cm->task(worker_id);
+    task->record_start_time();
+    {
+      ResourceMark rm;
+      HandleMark hm;
+
+      G1RemarkThreadsClosure threads_f(G1CollectedHeap::heap(), task);
+      Threads::threads_do(&threads_f);
     }
+
+    do {
+      task->do_marking_step(1000000000.0 /* something very large */,
+                            true         /* do_termination       */,
+                            false        /* is_serial            */);
+    } while (task->has_aborted() && !_cm->has_overflown());
+    // If we overflow, then we do not want to restart. We instead
+    // want to abort remark and do concurrent marking again.
+    task->record_end_time();
   }
 
   G1CMRemarkTask(G1ConcurrentMark* cm, uint active_workers) :
--- a/src/hotspot/share/gc/g1/g1ConcurrentRefine.cpp	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/hotspot/share/gc/g1/g1ConcurrentRefine.cpp	Mon Nov 27 17:04:45 2017 +0000
@@ -33,6 +33,107 @@
 #include "utilities/pair.hpp"
 #include <math.h>
 
+G1ConcurrentRefineThread* G1ConcurrentRefineThreadControl::create_refinement_thread(uint worker_id, bool initializing) {
+  G1ConcurrentRefineThread* result = NULL;
+  if (initializing || !InjectGCWorkerCreationFailure) {
+    result = new G1ConcurrentRefineThread(_cr, worker_id);
+  }
+  if (result == NULL || result->osthread() == NULL) {
+    log_warning(gc)("Failed to create refinement thread %u, no more %s",
+                    worker_id,
+                    result == NULL ? "memory" : "OS threads");
+  }
+  return result;
+}
+
+G1ConcurrentRefineThreadControl::G1ConcurrentRefineThreadControl() :
+  _cr(NULL),
+  _threads(NULL),
+  _num_max_threads(0)
+{
+}
+
+G1ConcurrentRefineThreadControl::~G1ConcurrentRefineThreadControl() {
+  for (uint i = 0; i < _num_max_threads; i++) {
+    G1ConcurrentRefineThread* t = _threads[i];
+    if (t != NULL) {
+      delete t;
+    }
+  }
+  FREE_C_HEAP_ARRAY(G1ConcurrentRefineThread*, _threads);
+}
+
+jint G1ConcurrentRefineThreadControl::initialize(G1ConcurrentRefine* cr, uint num_max_threads) {
+  assert(cr != NULL, "G1ConcurrentRefine must not be NULL");
+  _cr = cr;
+  _num_max_threads = num_max_threads;
+
+  _threads = NEW_C_HEAP_ARRAY_RETURN_NULL(G1ConcurrentRefineThread*, num_max_threads, mtGC);
+  if (_threads == NULL) {
+    vm_shutdown_during_initialization("Could not allocate thread holder array.");
+    return JNI_ENOMEM;
+  }
+
+  for (uint i = 0; i < num_max_threads; i++) {
+    if (UseDynamicNumberOfGCThreads && i != 0 /* Always start first thread. */) {
+      _threads[i] = NULL;
+    } else {
+      _threads[i] = create_refinement_thread(i, true);
+      if (_threads[i] == NULL) {
+        vm_shutdown_during_initialization("Could not allocate refinement threads.");
+        return JNI_ENOMEM;
+      }
+    }
+  }
+  return JNI_OK;
+}
+
+void G1ConcurrentRefineThreadControl::maybe_activate_next(uint cur_worker_id) {
+  assert(cur_worker_id < _num_max_threads,
+         "Activating another thread from %u not allowed since there can be at most %u",
+         cur_worker_id, _num_max_threads);
+  if (cur_worker_id == (_num_max_threads - 1)) {
+    // Already the last thread, there is no more thread to activate.
+    return;
+  }
+
+  uint worker_id = cur_worker_id + 1;
+  G1ConcurrentRefineThread* thread_to_activate = _threads[worker_id];
+  if (thread_to_activate == NULL) {
+    // Still need to create the thread...
+    _threads[worker_id] = create_refinement_thread(worker_id, false);
+    thread_to_activate = _threads[worker_id];
+  }
+  if (thread_to_activate != NULL && !thread_to_activate->is_active()) {
+    thread_to_activate->activate();
+  }
+}
+
+void G1ConcurrentRefineThreadControl::print_on(outputStream* st) const {
+  for (uint i = 0; i < _num_max_threads; ++i) {
+    if (_threads[i] != NULL) {
+      _threads[i]->print_on(st);
+      st->cr();
+    }
+  }
+}
+
+void G1ConcurrentRefineThreadControl::worker_threads_do(ThreadClosure* tc) {
+  for (uint i = 0; i < _num_max_threads; i++) {
+    if (_threads[i] != NULL) {
+      tc->do_thread(_threads[i]);
+    }
+  }
+}
+
+void G1ConcurrentRefineThreadControl::stop() {
+  for (uint i = 0; i < _num_max_threads; i++) {
+    if (_threads[i] != NULL) {
+      _threads[i]->stop();
+    }
+  }
+}
+
 // Arbitrary but large limits, to simplify some of the zone calculations.
 // The general idea is to allow expressions like
 //   MIN2(x OP y, max_XXX_zone)
@@ -96,7 +197,7 @@
                                   size_t yellow_zone,
                                   uint worker_i) {
   double yellow_size = yellow_zone - green_zone;
-  double step = yellow_size / G1ConcurrentRefine::thread_num();
+  double step = yellow_size / G1ConcurrentRefine::max_num_threads();
   if (worker_i == 0) {
     // Potentially activate worker 0 more aggressively, to keep
     // available buffers near green_zone value.  When yellow_size is
@@ -115,8 +216,7 @@
                                        size_t yellow_zone,
                                        size_t red_zone,
                                        size_t min_yellow_zone_size) :
-  _threads(NULL),
-  _n_worker_threads(thread_num()),
+  _thread_control(),
   _green_zone(green_zone),
   _yellow_zone(yellow_zone),
   _red_zone(red_zone),
@@ -125,9 +225,13 @@
   assert_zone_constraints_gyr(green_zone, yellow_zone, red_zone);
 }
 
+jint G1ConcurrentRefine::initialize() {
+  return _thread_control.initialize(this, max_num_threads());
+}
+
 static size_t calc_min_yellow_zone_size() {
   size_t step = G1ConcRefinementThresholdStep;
-  uint n_workers = G1ConcurrentRefine::thread_num();
+  uint n_workers = G1ConcurrentRefine::max_num_threads();
   if ((max_yellow_zone / step) < n_workers) {
     return max_yellow_zone;
   } else {
@@ -191,77 +295,27 @@
     return NULL;
   }
 
-  cr->_threads = NEW_C_HEAP_ARRAY_RETURN_NULL(G1ConcurrentRefineThread*, cr->_n_worker_threads, mtGC);
-  if (cr->_threads == NULL) {
-    *ecode = JNI_ENOMEM;
-    vm_shutdown_during_initialization("Could not allocate an array for G1ConcurrentRefineThread");
-    return NULL;
-  }
-
-  uint worker_id_offset = DirtyCardQueueSet::num_par_ids();
-
-  G1ConcurrentRefineThread *next = NULL;
-  for (uint i = cr->_n_worker_threads - 1; i != UINT_MAX; i--) {
-    Thresholds thresholds = calc_thresholds(green_zone, yellow_zone, i);
-    G1ConcurrentRefineThread* t =
-      new G1ConcurrentRefineThread(cr,
-                                   next,
-                                   worker_id_offset,
-                                   i,
-                                   activation_level(thresholds),
-                                   deactivation_level(thresholds));
-    assert(t != NULL, "Conc refine should have been created");
-    if (t->osthread() == NULL) {
-      *ecode = JNI_ENOMEM;
-      vm_shutdown_during_initialization("Could not create G1ConcurrentRefineThread");
-      return NULL;
-    }
-
-    assert(t->cr() == cr, "Conc refine thread should refer to this");
-    cr->_threads[i] = t;
-    next = t;
-  }
-
-  *ecode = JNI_OK;
+  *ecode = cr->initialize();
   return cr;
 }
 
 void G1ConcurrentRefine::stop() {
-  for (uint i = 0; i < _n_worker_threads; i++) {
-    _threads[i]->stop();
-  }
-}
-
-void G1ConcurrentRefine::update_thread_thresholds() {
-  for (uint i = 0; i < _n_worker_threads; i++) {
-    Thresholds thresholds = calc_thresholds(_green_zone, _yellow_zone, i);
-    _threads[i]->update_thresholds(activation_level(thresholds),
-                                   deactivation_level(thresholds));
-  }
+  _thread_control.stop();
 }
 
 G1ConcurrentRefine::~G1ConcurrentRefine() {
-  for (uint i = 0; i < _n_worker_threads; i++) {
-    delete _threads[i];
-  }
-  FREE_C_HEAP_ARRAY(G1ConcurrentRefineThread*, _threads);
 }
 
 void G1ConcurrentRefine::threads_do(ThreadClosure *tc) {
-  for (uint i = 0; i < _n_worker_threads; i++) {
-    tc->do_thread(_threads[i]);
-  }
+  _thread_control.worker_threads_do(tc);
 }
 
-uint G1ConcurrentRefine::thread_num() {
+uint G1ConcurrentRefine::max_num_threads() {
   return G1ConcRefinementThreads;
 }
 
 void G1ConcurrentRefine::print_threads_on(outputStream* st) const {
-  for (uint i = 0; i < _n_worker_threads; ++i) {
-    _threads[i]->print_on(st);
-    st->cr();
-  }
+  _thread_control.print_on(st);
 }
 
 static size_t calc_new_green_zone(size_t green,
@@ -326,16 +380,15 @@
 
   if (G1UseAdaptiveConcRefinement) {
     update_zones(update_rs_time, update_rs_processed_buffers, goal_ms);
-    update_thread_thresholds();
 
     // Change the barrier params
-    if (_n_worker_threads == 0) {
+    if (max_num_threads() == 0) {
       // Disable dcqs notification when there are no threads to notify.
       dcqs.set_process_completed_threshold(INT_MAX);
     } else {
       // Worker 0 is the primary; wakeup is via dcqs notification.
       STATIC_ASSERT(max_yellow_zone <= INT_MAX);
-      size_t activate = _threads[0]->activation_threshold();
+      size_t activate = activation_threshold(0);
       dcqs.set_process_completed_threshold((int)activate);
     }
     dcqs.set_max_completed_queue((int)red_zone());
@@ -349,3 +402,42 @@
   }
   dcqs.notify_if_necessary();
 }
+
+size_t G1ConcurrentRefine::activation_threshold(uint worker_id) const {
+  Thresholds thresholds = calc_thresholds(_green_zone, _yellow_zone, worker_id);
+  return activation_level(thresholds);
+}
+
+size_t G1ConcurrentRefine::deactivation_threshold(uint worker_id) const {
+  Thresholds thresholds = calc_thresholds(_green_zone, _yellow_zone, worker_id);
+  return deactivation_level(thresholds);
+}
+
+uint G1ConcurrentRefine::worker_id_offset() {
+  return DirtyCardQueueSet::num_par_ids();
+}
+
+void G1ConcurrentRefine::maybe_activate_more_threads(uint worker_id, size_t num_cur_buffers) {
+  if (num_cur_buffers > activation_threshold(worker_id + 1)) {
+    _thread_control.maybe_activate_next(worker_id);
+  }
+}
+
+bool G1ConcurrentRefine::do_refinement_step(uint worker_id) {
+  DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
+
+  size_t curr_buffer_num = dcqs.completed_buffers_num();
+  // If the number of the buffers falls down into the yellow zone,
+  // that means that the transition period after the evacuation pause has ended.
+  // Since the value written to the DCQS is the same for all threads, there is no
+  // need to synchronize.
+  if (dcqs.completed_queue_padding() > 0 && curr_buffer_num <= yellow_zone()) {
+    dcqs.set_completed_queue_padding(0);
+  }
+
+  maybe_activate_more_threads(worker_id, curr_buffer_num);
+
+  // Process the next buffer, if there are enough left.
+  return dcqs.refine_completed_buffer_concurrently(worker_id + worker_id_offset(),
+                                                   deactivation_threshold(worker_id));
+}
--- a/src/hotspot/share/gc/g1/g1ConcurrentRefine.hpp	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/hotspot/share/gc/g1/g1ConcurrentRefine.hpp	Mon Nov 27 17:04:45 2017 +0000
@@ -30,30 +30,63 @@
 
 // Forward decl
 class CardTableEntryClosure;
+class G1ConcurrentRefine;
 class G1ConcurrentRefineThread;
 class outputStream;
 class ThreadClosure;
 
-class G1ConcurrentRefine : public CHeapObj<mtGC> {
+// Helper class for refinement thread management. Used to start, stop and
+// iterate over them.
+class G1ConcurrentRefineThreadControl VALUE_OBJ_CLASS_SPEC {
+  G1ConcurrentRefine* _cr;
+
   G1ConcurrentRefineThread** _threads;
-  uint _n_worker_threads;
- /*
-  * The value of the update buffer queue length falls into one of 3 zones:
-  * green, yellow, red. If the value is in [0, green) nothing is
-  * done, the buffers are left unprocessed to enable the caching effect of the
-  * dirtied cards. In the yellow zone [green, yellow) the concurrent refinement
-  * threads are gradually activated. In [yellow, red) all threads are
-  * running. If the length becomes red (max queue length) the mutators start
-  * processing the buffers.
-  *
-  * There are some interesting cases (when G1UseAdaptiveConcRefinement
-  * is turned off):
-  * 1) green = yellow = red = 0. In this case the mutator will process all
-  *    buffers. Except for those that are created by the deferred updates
-  *    machinery during a collection.
-  * 2) green = 0. Means no caching. Can be a good way to minimize the
-  *    amount of time spent updating rsets during a collection.
-  */
+  uint _num_max_threads;
+
+  // Create the refinement thread for the given worker id.
+  // If initializing is true, ignore InjectGCWorkerCreationFailure.
+  G1ConcurrentRefineThread* create_refinement_thread(uint worker_id, bool initializing);
+public:
+  G1ConcurrentRefineThreadControl();
+  ~G1ConcurrentRefineThreadControl();
+
+  jint initialize(G1ConcurrentRefine* cr, uint num_max_threads);
+
+  // If there is a "successor" thread that can be activated given the current id,
+  // activate it.
+  void maybe_activate_next(uint cur_worker_id);
+
+  void print_on(outputStream* st) const;
+  void worker_threads_do(ThreadClosure* tc);
+  void stop();
+};
+
+// Controls refinement threads and their activation based on the number of completed
+// buffers currently available in the global dirty card queue.
+// Refinement threads pick work from the queue based on these thresholds. They are activated
+// gradually based on the amount of work to do.
+// Refinement thread n activates thread n+1 if the instance of this class determines there
+// is enough work available. Threads deactivate themselves if the current amount of
+// completed buffers falls below their individual threshold.
+class G1ConcurrentRefine : public CHeapObj<mtGC> {
+  G1ConcurrentRefineThreadControl _thread_control;
+  /*
+   * The value of the completed dirty card queue length falls into one of 3 zones:
+   * green, yellow, red. If the value is in [0, green) nothing is
+   * done, the buffers are left unprocessed to enable the caching effect of the
+   * dirtied cards. In the yellow zone [green, yellow) the concurrent refinement
+   * threads are gradually activated. In [yellow, red) all threads are
+   * running. If the length becomes red (max queue length) the mutators start
+   * processing the buffers.
+   *
+   * There are some interesting cases (when G1UseAdaptiveConcRefinement
+   * is turned off):
+   * 1) green = yellow = red = 0. In this case the mutator will process all
+   *    buffers. Except for those that are created by the deferred updates
+   *    machinery during a collection.
+   * 2) green = 0. Means no caching. Can be a good way to minimize the
+   *    amount of time spent updating remembered sets during a collection.
+   */
   size_t _green_zone;
   size_t _yellow_zone;
   size_t _red_zone;
@@ -69,24 +102,32 @@
                     size_t update_rs_processed_buffers,
                     double goal_ms);
 
-  // Update thread thresholds to account for updated zone values.
-  void update_thread_thresholds();
+  static uint worker_id_offset();
+  void maybe_activate_more_threads(uint worker_id, size_t num_cur_buffers);
 
- public:
+  jint initialize();
+public:
   ~G1ConcurrentRefine();
 
-  // Returns a G1ConcurrentRefine instance if succeeded to create/initialize G1ConcurrentRefine and G1ConcurrentRefineThreads.
-  // Otherwise, returns NULL with error code.
+  // Returns a G1ConcurrentRefine instance if succeeded to create/initialize the
+  // G1ConcurrentRefine instance. Otherwise, returns NULL with error code.
   static G1ConcurrentRefine* create(jint* ecode);
 
   void stop();
 
+  // Adjust refinement thresholds based on work done during the pause and the goal time.
   void adjust(double update_rs_time, size_t update_rs_processed_buffers, double goal_ms);
 
+  size_t activation_threshold(uint worker_id) const;
+  size_t deactivation_threshold(uint worker_id) const;
+  // Perform a single refinement step. Called by the refinement threads when woken up.
+  bool do_refinement_step(uint worker_id);
+
   // Iterate over all concurrent refinement threads applying the given closure.
   void threads_do(ThreadClosure *tc);
 
-  static uint thread_num();
+  // Maximum number of refinement threads.
+  static uint max_num_threads();
 
   void print_threads_on(outputStream* st) const;
 
--- a/src/hotspot/share/gc/g1/g1ConcurrentRefineThread.cpp	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/hotspot/share/gc/g1/g1ConcurrentRefineThread.cpp	Mon Nov 27 17:04:45 2017 +0000
@@ -25,32 +25,20 @@
 #include "precompiled.hpp"
 #include "gc/g1/g1ConcurrentRefine.hpp"
 #include "gc/g1/g1ConcurrentRefineThread.hpp"
-#include "gc/g1/g1CollectedHeap.inline.hpp"
-#include "gc/g1/g1RemSet.hpp"
 #include "gc/shared/suspendibleThreadSet.hpp"
 #include "logging/log.hpp"
 #include "memory/resourceArea.hpp"
 #include "runtime/handles.inline.hpp"
 #include "runtime/mutexLocker.hpp"
 
-G1ConcurrentRefineThread::G1ConcurrentRefineThread(G1ConcurrentRefine* cr,
-                                                   G1ConcurrentRefineThread *next,
-                                                   uint worker_id_offset,
-                                                   uint worker_id,
-                                                   size_t activate,
-                                                   size_t deactivate) :
+G1ConcurrentRefineThread::G1ConcurrentRefineThread(G1ConcurrentRefine* cr, uint worker_id) :
   ConcurrentGCThread(),
-  _worker_id_offset(worker_id_offset),
   _worker_id(worker_id),
   _active(false),
-  _next(next),
   _monitor(NULL),
   _cr(cr),
-  _vtime_accum(0.0),
-  _activation_threshold(activate),
-  _deactivation_threshold(deactivate)
+  _vtime_accum(0.0)
 {
-
   // Each thread has its own monitor. The i-th thread is responsible for signaling
   // to thread i+1 if the number of buffers in the queue exceeds a threshold for this
   // thread. Monitors are also used to wake up the threads during termination.
@@ -67,13 +55,6 @@
   create_and_start();
 }
 
-void G1ConcurrentRefineThread::update_thresholds(size_t activate,
-                                                 size_t deactivate) {
-  assert(deactivate < activate, "precondition");
-  _activation_threshold = activate;
-  _deactivation_threshold = deactivate;
-}
-
 void G1ConcurrentRefineThread::wait_for_completed_buffers() {
   MutexLockerEx x(_monitor, Mutex::_no_safepoint_check_flag);
   while (!should_terminate() && !is_active()) {
@@ -118,9 +99,9 @@
     }
 
     size_t buffers_processed = 0;
-    DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
-    log_debug(gc, refine)("Activated %d, on threshold: " SIZE_FORMAT ", current: " SIZE_FORMAT,
-                          _worker_id, _activation_threshold, dcqs.completed_buffers_num());
+    log_debug(gc, refine)("Activated worker %d, on threshold: " SIZE_FORMAT ", current: " SIZE_FORMAT,
+                          _worker_id, _cr->activation_threshold(_worker_id),
+                           JavaThread::dirty_card_queue_set().completed_buffers_num());
 
     {
       SuspendibleThreadSetJoiner sts_join;
@@ -131,33 +112,18 @@
           continue;             // Re-check for termination after yield delay.
         }
 
-        size_t curr_buffer_num = dcqs.completed_buffers_num();
-        // If the number of the buffers falls down into the yellow zone,
-        // that means that the transition period after the evacuation pause has ended.
-        if (dcqs.completed_queue_padding() > 0 && curr_buffer_num <= cr()->yellow_zone()) {
-          dcqs.set_completed_queue_padding(0);
-        }
-
-        // Check if we need to activate the next thread.
-        if ((_next != NULL) &&
-            !_next->is_active() &&
-            (curr_buffer_num > _next->_activation_threshold)) {
-          _next->activate();
-        }
-
-        // Process the next buffer, if there are enough left.
-        if (!dcqs.refine_completed_buffer_concurrently(_worker_id + _worker_id_offset, _deactivation_threshold)) {
-          break; // Deactivate, number of buffers fell below threshold.
+        if (!_cr->do_refinement_step(_worker_id)) {
+          break;
         }
         ++buffers_processed;
       }
     }
 
     deactivate();
-    log_debug(gc, refine)("Deactivated %d, off threshold: " SIZE_FORMAT
+    log_debug(gc, refine)("Deactivated worker %d, off threshold: " SIZE_FORMAT
                           ", current: " SIZE_FORMAT ", processed: " SIZE_FORMAT,
-                          _worker_id, _deactivation_threshold,
-                          dcqs.completed_buffers_num(),
+                          _worker_id, _cr->deactivation_threshold(_worker_id),
+                          JavaThread::dirty_card_queue_set().completed_buffers_num(),
                           buffers_processed);
 
     if (os::supports_vtime()) {
--- a/src/hotspot/share/gc/g1/g1ConcurrentRefineThread.hpp	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/hotspot/share/gc/g1/g1ConcurrentRefineThread.hpp	Mon Nov 27 17:04:45 2017 +0000
@@ -43,43 +43,29 @@
   uint _worker_id;
   uint _worker_id_offset;
 
-  // The refinement threads collection is linked list. A predecessor can activate a successor
-  // when the number of the rset update buffer crosses a certain threshold. A successor
-  // would self-deactivate when the number of the buffers falls below the threshold.
   bool _active;
-  G1ConcurrentRefineThread* _next;
   Monitor* _monitor;
   G1ConcurrentRefine* _cr;
 
-  // This thread's activation/deactivation thresholds
-  size_t _activation_threshold;
-  size_t _deactivation_threshold;
-
   void wait_for_completed_buffers();
 
   void set_active(bool x) { _active = x; }
-  bool is_active();
-  void activate();
+  // Deactivate this thread.
   void deactivate();
 
   bool is_primary() { return (_worker_id == 0); }
 
   void run_service();
   void stop_service();
+public:
+  G1ConcurrentRefineThread(G1ConcurrentRefine* cg1r, uint worker_id);
 
-public:
-  // Constructor
-  G1ConcurrentRefineThread(G1ConcurrentRefine* cr, G1ConcurrentRefineThread* next,
-                           uint worker_id_offset, uint worker_id,
-                           size_t activate, size_t deactivate);
-
-  void update_thresholds(size_t activate, size_t deactivate);
-  size_t activation_threshold() const { return _activation_threshold; }
+  bool is_active();
+  // Activate this thread.
+  void activate();
 
   // Total virtual time so far.
   double vtime_accum() { return _vtime_accum; }
-
-  G1ConcurrentRefine* cr() { return _cr;     }
 };
 
 #endif // SHARE_VM_GC_G1_G1CONCURRENTREFINETHREAD_HPP
--- a/src/hotspot/share/gc/g1/g1DefaultPolicy.cpp	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/hotspot/share/gc/g1/g1DefaultPolicy.cpp	Mon Nov 27 17:04:45 2017 +0000
@@ -52,7 +52,7 @@
   _analytics(new G1Analytics(&_predictor)),
   _mmu_tracker(new G1MMUTrackerQueue(GCPauseIntervalMillis / 1000.0, MaxGCPauseMillis / 1000.0)),
   _ihop_control(create_ihop_control(&_predictor)),
-  _policy_counters(new GCPolicyCounters("GarbageFirst", 1, 3)),
+  _policy_counters(new GCPolicyCounters("GarbageFirst", 1, 2)),
   _young_list_fixed_length(0),
   _short_lived_surv_rate_group(new SurvRateGroup()),
   _survivor_surv_rate_group(new SurvRateGroup()),
--- a/src/hotspot/share/gc/g1/g1FullCollector.cpp	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/hotspot/share/gc/g1/g1FullCollector.cpp	Mon Nov 27 17:04:45 2017 +0000
@@ -35,6 +35,7 @@
 #include "gc/g1/g1FullGCReferenceProcessorExecutor.hpp"
 #include "gc/g1/g1FullGCScope.hpp"
 #include "gc/g1/g1OopClosures.hpp"
+#include "gc/g1/g1Policy.hpp"
 #include "gc/g1/g1StringDedup.hpp"
 #include "gc/shared/gcTraceTime.inline.hpp"
 #include "gc/shared/preservedMarks.hpp"
@@ -62,20 +63,24 @@
 #endif
 }
 
-G1FullCollector::G1FullCollector(G1FullGCScope* scope,
-                                 ReferenceProcessor* reference_processor,
-                                 G1CMBitMap* bitmap,
-                                 uint workers) :
-    _scope(scope),
-    _num_workers(workers),
-    _mark_bitmap(bitmap),
+G1CMBitMap* G1FullCollector::mark_bitmap() {
+  return _heap->concurrent_mark()->next_mark_bitmap();
+}
+
+ReferenceProcessor* G1FullCollector::reference_processor() {
+  return _heap->ref_processor_stw();
+}
+
+G1FullCollector::G1FullCollector(G1CollectedHeap* heap, bool explicit_gc, bool clear_soft_refs) :
+    _heap(heap),
+    _scope(explicit_gc, clear_soft_refs),
+    _num_workers(heap->workers()->active_workers()),
     _oop_queue_set(_num_workers),
     _array_queue_set(_num_workers),
     _preserved_marks_set(true),
-    _reference_processor(reference_processor),
     _serial_compaction_point(),
-    _is_alive(_mark_bitmap),
-    _is_alive_mutator(_reference_processor, &_is_alive) {
+    _is_alive(heap->concurrent_mark()->next_mark_bitmap()),
+    _is_alive_mutator(heap->ref_processor_stw(), &_is_alive) {
   assert(SafepointSynchronize::is_at_safepoint(), "must be at a safepoint");
 
   _preserved_marks_set.init(_num_workers);
@@ -99,8 +104,19 @@
 }
 
 void G1FullCollector::prepare_collection() {
-  _reference_processor->enable_discovery();
-  _reference_processor->setup_policy(scope()->should_clear_soft_refs());
+  _heap->g1_policy()->record_full_collection_start();
+
+  _heap->print_heap_before_gc();
+  _heap->print_heap_regions();
+
+  _heap->abort_concurrent_cycle();
+  _heap->verify_before_full_collection(scope()->is_explicit_gc());
+
+  _heap->gc_prologue(true);
+  _heap->prepare_heap_for_full_collection();
+
+  reference_processor()->enable_discovery();
+  reference_processor()->setup_policy(scope()->should_clear_soft_refs());
 
   // When collecting the permanent generation Method*s may be moving,
   // so we either have to flush all bcp data or convert it into bci.
@@ -139,6 +155,15 @@
   BiasedLocking::restore_marks();
   CodeCache::gc_epilogue();
   JvmtiExport::gc_epilogue();
+
+  _heap->prepare_heap_for_mutators();
+
+  _heap->g1_policy()->record_full_collection_end();
+  _heap->gc_epilogue(true);
+
+  _heap->verify_after_full_collection();
+
+  _heap->print_heap_after_full_collection(scope()->heap_transition());
 }
 
 void G1FullCollector::phase1_mark_live_objects() {
@@ -164,11 +189,11 @@
     GCTraceTime(Debug, gc, phases) debug("Phase 1: Class Unloading and Cleanup", scope()->timer());
     // Unload classes and purge the SystemDictionary.
     bool purged_class = SystemDictionary::do_unloading(&_is_alive, scope()->timer());
-    G1CollectedHeap::heap()->complete_cleaning(&_is_alive, purged_class);
+    _heap->complete_cleaning(&_is_alive, purged_class);
   } else {
     GCTraceTime(Debug, gc, phases) debug("Phase 1: String and Symbol Tables Cleanup", scope()->timer());
     // If no class unloading just clean out strings and symbols.
-    G1CollectedHeap::heap()->partial_cleaning(&_is_alive, true, true, G1StringDedup::is_enabled());
+    _heap->partial_cleaning(&_is_alive, true, true, G1StringDedup::is_enabled());
   }
 
   scope()->tracer()->report_object_count_after_gc(&_is_alive);
@@ -210,13 +235,13 @@
 }
 
 void G1FullCollector::restore_marks() {
-  SharedRestorePreservedMarksTaskExecutor task_executor(G1CollectedHeap::heap()->workers());
+  SharedRestorePreservedMarksTaskExecutor task_executor(_heap->workers());
   _preserved_marks_set.restore(&task_executor);
   _preserved_marks_set.reclaim();
 }
 
 void G1FullCollector::run_task(AbstractGangTask* task) {
-  G1CollectedHeap::heap()->workers()->run_task(task, _num_workers);
+  _heap->workers()->run_task(task, _num_workers);
 }
 
 void G1FullCollector::verify_after_marking() {
@@ -229,7 +254,7 @@
 #if COMPILER2_OR_JVMCI
   DerivedPointerTableDeactivate dpt_deact;
 #endif
-  G1CollectedHeap::heap()->prepare_for_verify();
+  _heap->prepare_for_verify();
   // Note: we can verify only the heap here. When an object is
   // marked, the previous value of the mark word (including
   // identity hash values, ages, etc) is preserved, and the mark
@@ -241,5 +266,5 @@
   // (including hash values) are restored to the appropriate
   // objects.
   GCTraceTime(Info, gc, verify)("During GC (full)");
-  G1CollectedHeap::heap()->verify(VerifyOption_G1UseFullMarking);
+  _heap->verify(VerifyOption_G1UseFullMarking);
 }
--- a/src/hotspot/share/gc/g1/g1FullCollector.hpp	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/hotspot/share/gc/g1/g1FullCollector.hpp	Mon Nov 27 17:04:45 2017 +0000
@@ -28,6 +28,7 @@
 #include "gc/g1/g1FullGCCompactionPoint.hpp"
 #include "gc/g1/g1FullGCMarker.hpp"
 #include "gc/g1/g1FullGCOopClosures.hpp"
+#include "gc/g1/g1FullGCScope.hpp"
 #include "gc/shared/preservedMarks.hpp"
 #include "gc/shared/referenceProcessor.hpp"
 #include "gc/shared/taskqueue.hpp"
@@ -42,41 +43,36 @@
 
 // The G1FullCollector holds data associated with the current Full GC.
 class G1FullCollector : StackObj {
-  G1FullGCScope*            _scope;
+  G1CollectedHeap*          _heap;
+  G1FullGCScope             _scope;
   uint                      _num_workers;
   G1FullGCMarker**          _markers;
   G1FullGCCompactionPoint** _compaction_points;
-  G1CMBitMap*               _mark_bitmap;
   OopQueueSet               _oop_queue_set;
   ObjArrayTaskQueueSet      _array_queue_set;
   PreservedMarksSet         _preserved_marks_set;
-  ReferenceProcessor*       _reference_processor;
   G1FullGCCompactionPoint   _serial_compaction_point;
-
   G1IsAliveClosure          _is_alive;
   ReferenceProcessorIsAliveMutator _is_alive_mutator;
 
 public:
-  G1FullCollector(G1FullGCScope* scope,
-                  ReferenceProcessor* reference_processor,
-                  G1CMBitMap* mark_bitmap,
-                  uint workers);
+  G1FullCollector(G1CollectedHeap* heap, bool explicit_gc, bool clear_soft_refs);
   ~G1FullCollector();
 
   void prepare_collection();
   void collect();
   void complete_collection();
 
-  G1FullGCScope*           scope() { return _scope; }
+  G1FullGCScope*           scope() { return &_scope; }
   uint                     workers() { return _num_workers; }
   G1FullGCMarker*          marker(uint id) { return _markers[id]; }
   G1FullGCCompactionPoint* compaction_point(uint id) { return _compaction_points[id]; }
-  G1CMBitMap*              mark_bitmap() { return _mark_bitmap; }
   OopQueueSet*             oop_queue_set() { return &_oop_queue_set; }
   ObjArrayTaskQueueSet*    array_queue_set() { return &_array_queue_set; }
   PreservedMarksSet*       preserved_mark_set() { return &_preserved_marks_set; }
-  ReferenceProcessor*      reference_processor() { return _reference_processor; }
   G1FullGCCompactionPoint* serial_compaction_point() { return &_serial_compaction_point; }
+  G1CMBitMap*              mark_bitmap();
+  ReferenceProcessor*      reference_processor();
 
 private:
   void phase1_mark_live_objects();
--- a/src/hotspot/share/gc/g1/g1MonitoringSupport.cpp	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/hotspot/share/gc/g1/g1MonitoringSupport.cpp	Mon Nov 27 17:04:45 2017 +0000
@@ -26,6 +26,7 @@
 #include "gc/g1/g1CollectedHeap.inline.hpp"
 #include "gc/g1/g1MonitoringSupport.hpp"
 #include "gc/g1/g1Policy.hpp"
+#include "gc/shared/hSpaceCounters.hpp"
 
 G1GenerationCounters::G1GenerationCounters(G1MonitoringSupport* g1mm,
                                            const char* name,
@@ -128,10 +129,10 @@
   //  name  "generation.1.space.0"
   // Counters are created from maxCapacity, capacity, initCapacity,
   // and used.
-  _old_space_counters = new HSpaceCounters("space", 0 /* ordinal */,
+  _old_space_counters = new HSpaceCounters(_old_collection_counters->name_space(),
+    "space", 0 /* ordinal */,
     pad_capacity(overall_reserved()) /* max_capacity */,
-    pad_capacity(old_space_committed()) /* init_capacity */,
-   _old_collection_counters);
+    pad_capacity(old_space_committed()) /* init_capacity */);
 
   //   Young collection set
   //  name "generation.0".  This is logically the young generation.
@@ -139,27 +140,29 @@
   // See  _old_collection_counters for additional counters
   _young_collection_counters = new G1YoungGenerationCounters(this, "young");
 
+  const char* young_collection_name_space = _young_collection_counters->name_space();
+
   //  name "generation.0.space.0"
   // See _old_space_counters for additional counters
-  _eden_counters = new HSpaceCounters("eden", 0 /* ordinal */,
+  _eden_counters = new HSpaceCounters(young_collection_name_space,
+    "eden", 0 /* ordinal */,
     pad_capacity(overall_reserved()) /* max_capacity */,
-    pad_capacity(eden_space_committed()) /* init_capacity */,
-    _young_collection_counters);
+    pad_capacity(eden_space_committed()) /* init_capacity */);
 
   //  name "generation.0.space.1"
   // See _old_space_counters for additional counters
   // Set the arguments to indicate that this survivor space is not used.
-  _from_counters = new HSpaceCounters("s0", 1 /* ordinal */,
+  _from_counters = new HSpaceCounters(young_collection_name_space,
+    "s0", 1 /* ordinal */,
     pad_capacity(0) /* max_capacity */,
-    pad_capacity(0) /* init_capacity */,
-    _young_collection_counters);
+    pad_capacity(0) /* init_capacity */);
 
   //  name "generation.0.space.2"
   // See _old_space_counters for additional counters
-  _to_counters = new HSpaceCounters("s1", 2 /* ordinal */,
+  _to_counters = new HSpaceCounters(young_collection_name_space,
+    "s1", 2 /* ordinal */,
     pad_capacity(overall_reserved()) /* max_capacity */,
-    pad_capacity(survivor_space_committed()) /* init_capacity */,
-    _young_collection_counters);
+    pad_capacity(survivor_space_committed()) /* init_capacity */);
 
   if (UsePerfData) {
     // Given that this survivor space is not used, we update it here
--- a/src/hotspot/share/gc/g1/g1MonitoringSupport.hpp	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/hotspot/share/gc/g1/g1MonitoringSupport.hpp	Mon Nov 27 17:04:45 2017 +0000
@@ -25,9 +25,11 @@
 #ifndef SHARE_VM_GC_G1_G1MONITORINGSUPPORT_HPP
 #define SHARE_VM_GC_G1_G1MONITORINGSUPPORT_HPP
 
-#include "gc/g1/hSpaceCounters.hpp"
+#include "gc/shared/generationCounters.hpp"
 
+class CollectorCounters;
 class G1CollectedHeap;
+class HSpaceCounters;
 
 // Class for monitoring logical spaces in G1. It provides data for
 // both G1's jstat counters as well as G1's memory pools.
--- a/src/hotspot/share/gc/g1/g1RemSet.cpp	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/hotspot/share/gc/g1/g1RemSet.cpp	Mon Nov 27 17:04:45 2017 +0000
@@ -298,7 +298,7 @@
 }
 
 uint G1RemSet::num_par_rem_sets() {
-  return MAX2(DirtyCardQueueSet::num_par_ids() + G1ConcurrentRefine::thread_num(), ParallelGCThreads);
+  return MAX2(DirtyCardQueueSet::num_par_ids() + G1ConcurrentRefine::max_num_threads(), ParallelGCThreads);
 }
 
 void G1RemSet::initialize(size_t capacity, uint max_regions) {
--- a/src/hotspot/share/gc/g1/g1RemSetSummary.cpp	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/hotspot/share/gc/g1/g1RemSetSummary.cpp	Mon Nov 27 17:04:45 2017 +0000
@@ -86,7 +86,7 @@
   _num_processed_buf_mutator(0),
   _num_processed_buf_rs_threads(0),
   _num_coarsenings(0),
-  _num_vtimes(G1ConcurrentRefine::thread_num()),
+  _num_vtimes(G1ConcurrentRefine::max_num_threads()),
   _rs_threads_vtimes(NEW_C_HEAP_ARRAY(double, _num_vtimes, mtGC)),
   _sampling_thread_vtime(0.0f) {
 
@@ -99,7 +99,7 @@
   _num_processed_buf_mutator(0),
   _num_processed_buf_rs_threads(0),
   _num_coarsenings(0),
-  _num_vtimes(G1ConcurrentRefine::thread_num()),
+  _num_vtimes(G1ConcurrentRefine::max_num_threads()),
   _rs_threads_vtimes(NEW_C_HEAP_ARRAY(double, _num_vtimes, mtGC)),
   _sampling_thread_vtime(0.0f) {
   update();
--- a/src/hotspot/share/gc/g1/g1SATBCardTableModRefBS.cpp	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/hotspot/share/gc/g1/g1SATBCardTableModRefBS.cpp	Mon Nov 27 17:04:45 2017 +0000
@@ -175,6 +175,9 @@
 
 void
 G1SATBCardTableLoggingModRefBS::invalidate(MemRegion mr) {
+  if (mr.is_empty()) {
+    return;
+  }
   volatile jbyte* byte = byte_for(mr.start());
   jbyte* last_byte = byte_for(mr.last());
   Thread* thr = Thread::current();
--- a/src/hotspot/share/gc/g1/hSpaceCounters.cpp	Fri Nov 24 17:19:47 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,66 +0,0 @@
-/*
- * Copyright (c) 2011, 2015, 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.
- *
- */
-
-#include "precompiled.hpp"
-#include "gc/g1/hSpaceCounters.hpp"
-#include "gc/shared/generation.hpp"
-#include "memory/resourceArea.hpp"
-
-HSpaceCounters::HSpaceCounters(const char* name,
-                               int ordinal,
-                               size_t max_size,
-                               size_t initial_capacity,
-                               GenerationCounters* gc) {
-
-  if (UsePerfData) {
-    EXCEPTION_MARK;
-    ResourceMark rm;
-
-    const char* cns =
-      PerfDataManager::name_space(gc->name_space(), "space", ordinal);
-
-    _name_space = NEW_C_HEAP_ARRAY(char, strlen(cns)+1, mtGC);
-    strcpy(_name_space, cns);
-
-    const char* cname = PerfDataManager::counter_name(_name_space, "name");
-    PerfDataManager::create_string_constant(SUN_GC, cname, name, CHECK);
-
-    cname = PerfDataManager::counter_name(_name_space, "maxCapacity");
-    PerfDataManager::create_constant(SUN_GC, cname, PerfData::U_Bytes,
-                                     (jlong)max_size, CHECK);
-
-    cname = PerfDataManager::counter_name(_name_space, "capacity");
-    _capacity = PerfDataManager::create_variable(SUN_GC, cname,
-                                                 PerfData::U_Bytes,
-                                                 initial_capacity, CHECK);
-
-    cname = PerfDataManager::counter_name(_name_space, "used");
-    _used = PerfDataManager::create_variable(SUN_GC, cname, PerfData::U_Bytes,
-                                             (jlong) 0, CHECK);
-
-    cname = PerfDataManager::counter_name(_name_space, "initCapacity");
-    PerfDataManager::create_constant(SUN_GC, cname, PerfData::U_Bytes,
-                                     initial_capacity, CHECK);
-  }
-}
--- a/src/hotspot/share/gc/g1/hSpaceCounters.hpp	Fri Nov 24 17:19:47 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,86 +0,0 @@
-/*
- * Copyright (c) 2011, 2015, 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.
- *
- */
-
-#ifndef SHARE_VM_GC_G1_HSPACECOUNTERS_HPP
-#define SHARE_VM_GC_G1_HSPACECOUNTERS_HPP
-
-#include "gc/shared/generation.hpp"
-#include "gc/shared/generationCounters.hpp"
-#include "runtime/perfData.hpp"
-#include "utilities/macros.hpp"
-
-// A HSpaceCounter is a holder class for performance counters
-// that track a collections (logical spaces) in a heap;
-
-class HeapSpaceUsedHelper;
-class G1SpaceMonitoringSupport;
-
-class HSpaceCounters: public CHeapObj<mtGC> {
-  friend class VMStructs;
-
- private:
-  PerfVariable*        _capacity;
-  PerfVariable*        _used;
-
-  // Constant PerfData types don't need to retain a reference.
-  // However, it's a good idea to document them here.
-
-  char*             _name_space;
-
- public:
-
-  HSpaceCounters(const char* name, int ordinal, size_t max_size,
-                 size_t initial_capacity, GenerationCounters* gc);
-
-  ~HSpaceCounters() {
-    if (_name_space != NULL) FREE_C_HEAP_ARRAY(char, _name_space);
-  }
-
-  inline void update_capacity(size_t v) {
-    _capacity->set_value(v);
-  }
-
-  inline void update_used(size_t v) {
-    _used->set_value(v);
-  }
-
-  debug_only(
-    // for security reasons, we do not allow arbitrary reads from
-    // the counters as they may live in shared memory.
-    jlong used() {
-      return _used->get_value();
-    }
-    jlong capacity() {
-      return _used->get_value();
-    }
-  )
-
-  inline void update_all(size_t capacity, size_t used) {
-    update_capacity(capacity);
-    update_used(used);
-  }
-
-  const char* name_space() const        { return _name_space; }
-};
-#endif // SHARE_VM_GC_G1_HSPACECOUNTERS_HPP
--- a/src/hotspot/share/gc/g1/satbMarkQueue.cpp	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/hotspot/share/gc/g1/satbMarkQueue.cpp	Mon Nov 27 17:04:45 2017 +0000
@@ -32,6 +32,7 @@
 #include "runtime/mutexLocker.hpp"
 #include "runtime/safepoint.hpp"
 #include "runtime/thread.hpp"
+#include "runtime/threadSMR.hpp"
 #include "runtime/vmThread.hpp"
 
 SATBMarkQueue::SATBMarkQueue(SATBMarkQueueSet* qset, bool permanent) :
@@ -214,7 +215,7 @@
   log_error(gc, verify)("Expected SATB active state: %s", expected_active ? "ACTIVE" : "INACTIVE");
   log_error(gc, verify)("Actual SATB active states:");
   log_error(gc, verify)("  Queue set: %s", is_active() ? "ACTIVE" : "INACTIVE");
-  for (JavaThread* t = Threads::first(); t; t = t->next()) {
+  for (JavaThreadIteratorWithHandle jtiwh; JavaThread *t = jtiwh.next(); ) {
     log_error(gc, verify)("  Thread \"%s\" queue: %s", t->name(), t->satb_mark_queue().is_active() ? "ACTIVE" : "INACTIVE");
   }
   log_error(gc, verify)("  Shared queue: %s", shared_satb_queue()->is_active() ? "ACTIVE" : "INACTIVE");
@@ -228,7 +229,7 @@
   }
 
   // Verify thread queue states
-  for (JavaThread* t = Threads::first(); t; t = t->next()) {
+  for (JavaThreadIteratorWithHandle jtiwh; JavaThread *t = jtiwh.next(); ) {
     if (t->satb_mark_queue().is_active() != expected_active) {
       dump_active_states(expected_active);
       guarantee(false, "Thread SATB queue has an unexpected active state");
@@ -249,14 +250,14 @@
   verify_active_states(expected_active);
 #endif // ASSERT
   _all_active = active;
-  for (JavaThread* t = Threads::first(); t; t = t->next()) {
+  for (JavaThreadIteratorWithHandle jtiwh; JavaThread *t = jtiwh.next(); ) {
     t->satb_mark_queue().set_active(active);
   }
   shared_satb_queue()->set_active(active);
 }
 
 void SATBMarkQueueSet::filter_thread_buffers() {
-  for(JavaThread* t = Threads::first(); t; t = t->next()) {
+  for (JavaThreadIteratorWithHandle jtiwh; JavaThread *t = jtiwh.next(); ) {
     t->satb_mark_queue().filter();
   }
   shared_satb_queue()->filter();
@@ -309,7 +310,7 @@
     i += 1;
   }
 
-  for (JavaThread* t = Threads::first(); t; t = t->next()) {
+  for (JavaThreadIteratorWithHandle jtiwh; JavaThread *t = jtiwh.next(); ) {
     jio_snprintf(buffer, SATB_PRINTER_BUFFER_SIZE, "Thread: %s", t->name());
     t->satb_mark_queue().print(buffer);
   }
@@ -341,8 +342,8 @@
   }
   assert(SafepointSynchronize::is_at_safepoint(), "Must be at safepoint.");
   // So we can safely manipulate these queues.
-  for (JavaThread* t = Threads::first(); t; t = t->next()) {
+  for (JavaThreadIteratorWithHandle jtiwh; JavaThread *t = jtiwh.next(); ) {
     t->satb_mark_queue().reset();
   }
- shared_satb_queue()->reset();
+  shared_satb_queue()->reset();
 }
--- a/src/hotspot/share/gc/parallel/mutableNUMASpace.cpp	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/hotspot/share/gc/parallel/mutableNUMASpace.cpp	Mon Nov 27 17:04:45 2017 +0000
@@ -29,6 +29,7 @@
 #include "oops/oop.inline.hpp"
 #include "runtime/atomic.hpp"
 #include "runtime/thread.inline.hpp"
+#include "runtime/threadSMR.hpp"
 #include "utilities/align.hpp"
 
 MutableNUMASpace::MutableNUMASpace(size_t alignment) : MutableSpace(alignment), _must_use_large_pages(false) {
@@ -287,7 +288,7 @@
     FREE_C_HEAP_ARRAY(int, lgrp_ids);
 
     if (changed) {
-      for (JavaThread *thread = Threads::first(); thread; thread = thread->next()) {
+      for (JavaThreadIteratorWithHandle jtiwh; JavaThread *thread = jtiwh.next(); ) {
         thread->set_lgrp_id(-1);
       }
     }
--- a/src/hotspot/share/gc/parallel/parallelScavengeHeap.cpp	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/hotspot/share/gc/parallel/parallelScavengeHeap.cpp	Mon Nov 27 17:04:45 2017 +0000
@@ -105,9 +105,9 @@
     (old_gen()->virtual_space()->high_boundary() ==
      young_gen()->virtual_space()->low_boundary()),
     "Boundaries must meet");
-  // initialize the policy counters - 2 collectors, 3 generations
+  // initialize the policy counters - 2 collectors, 2 generations
   _gc_policy_counters =
-    new PSGCAdaptivePolicyCounters("ParScav:MSC", 2, 3, _size_policy);
+    new PSGCAdaptivePolicyCounters("ParScav:MSC", 2, 2, _size_policy);
 
   // Set up the GCTaskManager
   _gc_task_manager = GCTaskManager::create(ParallelGCThreads);
--- a/src/hotspot/share/gc/shared/collectedHeap.cpp	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/hotspot/share/gc/shared/collectedHeap.cpp	Mon Nov 27 17:04:45 2017 +0000
@@ -40,6 +40,7 @@
 #include "oops/oop.inline.hpp"
 #include "runtime/init.hpp"
 #include "runtime/thread.inline.hpp"
+#include "runtime/threadSMR.hpp"
 #include "services/heapDumper.hpp"
 #include "utilities/align.hpp"
 
@@ -540,10 +541,11 @@
   const bool deferred = _defer_initial_card_mark;
   // The main thread starts allocating via a TLAB even before it
   // has added itself to the threads list at vm boot-up.
-  assert(!use_tlab || Threads::first() != NULL,
+  JavaThreadIteratorWithHandle jtiwh;
+  assert(!use_tlab || jtiwh.length() > 0,
          "Attempt to fill tlabs before main thread has been added"
          " to threads list is doomed to failure!");
-  for (JavaThread *thread = Threads::first(); thread; thread = thread->next()) {
+  for (; JavaThread *thread = jtiwh.next(); ) {
      if (use_tlab) thread->tlab().make_parsable(retire_tlabs);
 #if COMPILER2_OR_JVMCI
      // The deferred store barriers must all have been flushed to the
--- a/src/hotspot/share/gc/shared/collectorCounters.cpp	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/hotspot/share/gc/shared/collectorCounters.cpp	Mon Nov 27 17:04:45 2017 +0000
@@ -25,6 +25,7 @@
 #include "precompiled.hpp"
 #include "gc/shared/collectorCounters.hpp"
 #include "memory/resourceArea.hpp"
+#include "runtime/os.hpp"
 
 CollectorCounters::CollectorCounters(const char* name, int ordinal) {
 
@@ -59,3 +60,24 @@
                                                        CHECK);
   }
 }
+
+CollectorCounters::~CollectorCounters() {
+  if (_name_space != NULL) {
+    FREE_C_HEAP_ARRAY(char, _name_space);
+  }
+}
+
+TraceCollectorStats::TraceCollectorStats(CollectorCounters* c) :
+    PerfTraceTimedEvent(c->time_counter(), c->invocation_counter()),
+    _c(c) {
+
+  if (UsePerfData) {
+     _c->last_entry_counter()->set_value(os::elapsed_counter());
+  }
+}
+
+TraceCollectorStats::~TraceCollectorStats() {
+  if (UsePerfData) {
+    _c->last_exit_counter()->set_value(os::elapsed_counter());
+  }
+}
--- a/src/hotspot/share/gc/shared/collectorCounters.hpp	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/hotspot/share/gc/shared/collectorCounters.hpp	Mon Nov 27 17:04:45 2017 +0000
@@ -49,9 +49,7 @@
 
     CollectorCounters(const char* name, int ordinal);
 
-    ~CollectorCounters() {
-      if (_name_space != NULL) FREE_C_HEAP_ARRAY(char, _name_space);
-    }
+    ~CollectorCounters();
 
     inline PerfCounter* invocation_counter() const  { return _invocations; }
 
@@ -70,18 +68,9 @@
     CollectorCounters* _c;
 
   public:
-    inline TraceCollectorStats(CollectorCounters* c) :
-           PerfTraceTimedEvent(c->time_counter(), c->invocation_counter()),
-           _c(c) {
+    TraceCollectorStats(CollectorCounters* c);
 
-      if (UsePerfData) {
-         _c->last_entry_counter()->set_value(os::elapsed_counter());
-      }
-    }
-
-    inline ~TraceCollectorStats() {
-      if (UsePerfData) _c->last_exit_counter()->set_value(os::elapsed_counter());
-    }
+    ~TraceCollectorStats();
 };
 
 #endif // SHARE_VM_GC_SHARED_COLLECTORCOUNTERS_HPP
--- a/src/hotspot/share/gc/shared/collectorPolicy.cpp	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/hotspot/share/gc/shared/collectorPolicy.cpp	Mon Nov 27 17:04:45 2017 +0000
@@ -911,7 +911,7 @@
 }
 
 void MarkSweepPolicy::initialize_gc_policy_counters() {
-  // Initialize the policy counters - 2 collectors, 3 generations.
-  _gc_policy_counters = new GCPolicyCounters("Copy:MSC", 2, 3);
+  // Initialize the policy counters - 2 collectors, 2 generations.
+  _gc_policy_counters = new GCPolicyCounters("Copy:MSC", 2, 2);
 }
 
--- a/src/hotspot/share/gc/shared/gcLocker.cpp	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/hotspot/share/gc/shared/gcLocker.cpp	Mon Nov 27 17:04:45 2017 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, 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,7 @@
 #include "logging/log.hpp"
 #include "runtime/atomic.hpp"
 #include "runtime/thread.inline.hpp"
+#include "runtime/threadSMR.hpp"
 
 volatile jint GCLocker::_jni_lock_count = 0;
 volatile bool GCLocker::_needs_gc       = false;
@@ -45,14 +46,16 @@
     assert(!needs_gc() || _debug_jni_lock_count == _jni_lock_count, "must agree");
     int count = 0;
     // Count the number of threads with critical operations in progress
-    for (JavaThread* thr = Threads::first(); thr; thr = thr->next()) {
+    JavaThreadIteratorWithHandle jtiwh;
+    for (; JavaThread *thr = jtiwh.next(); ) {
       if (thr->in_critical()) {
         count++;
       }
     }
     if (_jni_lock_count != count) {
       log_error(gc, verify)("critical counts don't match: %d != %d", _jni_lock_count, count);
-      for (JavaThread* thr = Threads::first(); thr; thr = thr->next()) {
+      jtiwh.rewind();
+      for (; JavaThread *thr = jtiwh.next(); ) {
         if (thr->in_critical()) {
           log_error(gc, verify)(INTPTR_FORMAT " in_critical %d", p2i(thr), thr->in_critical());
         }
--- a/src/hotspot/share/gc/shared/generationCounters.cpp	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/hotspot/share/gc/shared/generationCounters.cpp	Mon Nov 27 17:04:45 2017 +0000
@@ -78,6 +78,12 @@
   initialize(name, ordinal, spaces, min_capacity, max_capacity, curr_capacity);
 }
 
+GenerationCounters::~GenerationCounters() {
+  if (_name_space != NULL) {
+    FREE_C_HEAP_ARRAY(char, _name_space);
+  }
+}
+
 void GenerationCounters::update_all() {
   assert(_virtual_space != NULL, "otherwise, override this method");
   _current_size->set_value(_virtual_space->committed_size());
--- a/src/hotspot/share/gc/shared/generationCounters.hpp	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/hotspot/share/gc/shared/generationCounters.hpp	Mon Nov 27 17:04:45 2017 +0000
@@ -68,9 +68,7 @@
   GenerationCounters(const char* name, int ordinal, int spaces,
                      size_t min_capacity, size_t max_capacity, VirtualSpace* v);
 
-  ~GenerationCounters() {
-    if (_name_space != NULL) FREE_C_HEAP_ARRAY(char, _name_space);
-  }
+  ~GenerationCounters();
 
   virtual void update_all();
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/shared/hSpaceCounters.cpp	Mon Nov 27 17:04:45 2017 +0000
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2011, 2017, 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.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "gc/shared/hSpaceCounters.hpp"
+#include "memory/allocation.hpp"
+#include "memory/resourceArea.hpp"
+#include "runtime/perfData.hpp"
+
+HSpaceCounters::HSpaceCounters(const char* name_space,
+                               const char* name,
+                               int ordinal,
+                               size_t max_size,
+                               size_t initial_capacity) {
+
+  if (UsePerfData) {
+    EXCEPTION_MARK;
+    ResourceMark rm;
+
+    const char* cns =
+      PerfDataManager::name_space(name_space, "space", ordinal);
+
+    _name_space = NEW_C_HEAP_ARRAY(char, strlen(cns)+1, mtGC);
+    strcpy(_name_space, cns);
+
+    const char* cname = PerfDataManager::counter_name(_name_space, "name");
+    PerfDataManager::create_string_constant(SUN_GC, cname, name, CHECK);
+
+    cname = PerfDataManager::counter_name(_name_space, "maxCapacity");
+    PerfDataManager::create_constant(SUN_GC, cname, PerfData::U_Bytes,
+                                     (jlong)max_size, CHECK);
+
+    cname = PerfDataManager::counter_name(_name_space, "capacity");
+    _capacity = PerfDataManager::create_variable(SUN_GC, cname,
+                                                 PerfData::U_Bytes,
+                                                 initial_capacity, CHECK);
+
+    cname = PerfDataManager::counter_name(_name_space, "used");
+    _used = PerfDataManager::create_variable(SUN_GC, cname, PerfData::U_Bytes,
+                                             (jlong) 0, CHECK);
+
+    cname = PerfDataManager::counter_name(_name_space, "initCapacity");
+    PerfDataManager::create_constant(SUN_GC, cname, PerfData::U_Bytes,
+                                     initial_capacity, CHECK);
+  }
+}
+
+HSpaceCounters::~HSpaceCounters() {
+  if (_name_space != NULL) {
+    FREE_C_HEAP_ARRAY(char, _name_space);
+  }
+}
+
+void HSpaceCounters::update_capacity(size_t v) {
+  _capacity->set_value(v);
+}
+
+void HSpaceCounters::update_used(size_t v) {
+  _used->set_value(v);
+}
+
+void HSpaceCounters::update_all(size_t capacity, size_t used) {
+  update_capacity(capacity);
+  update_used(used);
+}
+
+debug_only(
+  // for security reasons, we do not allow arbitrary reads from
+  // the counters as they may live in shared memory.
+  jlong HSpaceCounters::used() {
+    return _used->get_value();
+  }
+  jlong HSpaceCounters::capacity() {
+    return _used->get_value();
+  }
+)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/shared/hSpaceCounters.hpp	Mon Nov 27 17:04:45 2017 +0000
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2011, 2017, 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.
+ *
+ */
+
+#ifndef SHARE_VM_GC_SHARED_HSPACECOUNTERS_HPP
+#define SHARE_VM_GC_SHARED_HSPACECOUNTERS_HPP
+
+#include "memory/allocation.hpp"
+#include "runtime/perfData.hpp"
+#include "utilities/macros.hpp"
+
+// A HSpaceCounter is a holder class for performance counters
+// that track a collections (logical spaces) in a heap;
+
+class HSpaceCounters: public CHeapObj<mtGC> {
+  friend class VMStructs;
+
+ private:
+  PerfVariable* _capacity;
+  PerfVariable* _used;
+
+  // Constant PerfData types don't need to retain a reference.
+  // However, it's a good idea to document them here.
+
+  char*         _name_space;
+
+ public:
+
+  HSpaceCounters(const char* name_space, const char* name, int ordinal,
+                 size_t max_size, size_t initial_capacity);
+
+  ~HSpaceCounters();
+
+  void update_capacity(size_t v);
+  void update_used(size_t v);
+
+  void update_all(size_t capacity, size_t used);
+
+  debug_only(
+    // for security reasons, we do not allow arbitrary reads from
+    // the counters as they may live in shared memory.
+    jlong used();
+    jlong capacity();
+  )
+
+  const char* name_space() const        { return _name_space; }
+};
+#endif // SHARE_VM_GC_SHARED_HSPACECOUNTERS_HPP
--- a/src/hotspot/share/gc/shared/threadLocalAllocBuffer.cpp	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/hotspot/share/gc/shared/threadLocalAllocBuffer.cpp	Mon Nov 27 17:04:45 2017 +0000
@@ -30,6 +30,7 @@
 #include "memory/universe.inline.hpp"
 #include "oops/oop.inline.hpp"
 #include "runtime/thread.inline.hpp"
+#include "runtime/threadSMR.hpp"
 #include "utilities/copy.hpp"
 
 // Thread-Local Edens support
@@ -48,7 +49,7 @@
 void ThreadLocalAllocBuffer::accumulate_statistics_before_gc() {
   global_stats()->initialize();
 
-  for (JavaThread *thread = Threads::first(); thread != NULL; thread = thread->next()) {
+  for (JavaThreadIteratorWithHandle jtiwh; JavaThread *thread = jtiwh.next(); ) {
     thread->tlab().accumulate_statistics();
     thread->tlab().initialize_statistics();
   }
@@ -130,7 +131,7 @@
 
 void ThreadLocalAllocBuffer::resize_all_tlabs() {
   if (ResizeTLAB) {
-    for (JavaThread *thread = Threads::first(); thread != NULL; thread = thread->next()) {
+    for (JavaThreadIteratorWithHandle jtiwh; JavaThread *thread = jtiwh.next(); ) {
       thread->tlab().resize();
     }
   }
--- a/src/hotspot/share/gc/shared/workgroup.cpp	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/hotspot/share/gc/shared/workgroup.cpp	Mon Nov 27 17:04:45 2017 +0000
@@ -261,6 +261,10 @@
     _dispatcher(create_dispatcher())
 { }
 
+WorkGang::~WorkGang() {
+  delete _dispatcher;
+}
+
 AbstractGangWorker* WorkGang::allocate_worker(uint worker_id) {
   return new GangWorker(this, worker_id);
 }
--- a/src/hotspot/share/gc/shared/workgroup.hpp	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/hotspot/share/gc/shared/workgroup.hpp	Mon Nov 27 17:04:45 2017 +0000
@@ -122,6 +122,8 @@
   // Printing support.
   const char* _name;
 
+  ~AbstractWorkGang() {}
+
  private:
   // Initialize only instance data.
   const bool _are_GC_task_threads;
@@ -206,9 +208,6 @@
   // To get access to the GangTaskDispatcher instance.
   friend class GangWorker;
 
-  // Never deleted.
-  ~WorkGang();
-
   GangTaskDispatcher* const _dispatcher;
   GangTaskDispatcher* dispatcher() const {
     return _dispatcher;
@@ -220,6 +219,8 @@
            bool are_GC_task_threads,
            bool are_ConcurrentGC_threads);
 
+  ~WorkGang();
+
   // Run a task using the current active number of workers, returns when the task is done.
   virtual void run_task(AbstractGangTask* task);
   // Run a task with the given number of workers, returns
--- a/src/hotspot/share/jvmci/jvmciRuntime.cpp	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/hotspot/share/jvmci/jvmciRuntime.cpp	Mon Nov 27 17:04:45 2017 +0000
@@ -42,6 +42,7 @@
 #include "runtime/interfaceSupport.hpp"
 #include "runtime/reflection.hpp"
 #include "runtime/sharedRuntime.hpp"
+#include "runtime/threadSMR.hpp"
 #include "utilities/debug.hpp"
 #include "utilities/defaultStream.hpp"
 #include "utilities/macros.hpp"
@@ -598,12 +599,13 @@
 JRT_END
 
 JRT_ENTRY(jboolean, JVMCIRuntime::thread_is_interrupted(JavaThread* thread, oopDesc* receiver, jboolean clear_interrupted))
-  // Ensure that the C++ Thread and OSThread structures aren't freed before we operate.
-  // This locking requires thread_in_vm which is why this method cannot be JRT_LEAF.
   Handle receiverHandle(thread, receiver);
-  MutexLockerEx ml(thread->threadObj() == (void*)receiver ? NULL : Threads_lock);
+  // A nested ThreadsListHandle may require the Threads_lock which
+  // requires thread_in_vm which is why this method cannot be JRT_LEAF.
+  ThreadsListHandle tlh;
+
   JavaThread* receiverThread = java_lang_Thread::thread(receiverHandle());
-  if (receiverThread == NULL) {
+  if (receiverThread == NULL || (EnableThreadSMRExtraValidityChecks && !tlh.includes(receiverThread))) {
     // The other thread may exit during this process, which is ok so return false.
     return JNI_FALSE;
   } else {
--- a/src/hotspot/share/logging/logTag.hpp	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/hotspot/share/logging/logTag.hpp	Mon Nov 27 17:04:45 2017 +0000
@@ -121,6 +121,7 @@
   LOG_TAG(safepoint) \
   LOG_TAG(scavenge) \
   LOG_TAG(scrub) \
+  LOG_TAG(smr) \
   LOG_TAG(stacktrace) \
   LOG_TAG(stackwalk) \
   LOG_TAG(start) \
--- a/src/hotspot/share/memory/universe.cpp	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/hotspot/share/memory/universe.cpp	Mon Nov 27 17:04:45 2017 +0000
@@ -687,6 +687,10 @@
 
   Metaspace::global_initialize();
 
+  // Initialize performance counters for metaspaces
+  MetaspaceCounters::initialize_performance_counters();
+  CompressedClassSpaceCounters::initialize_performance_counters();
+
   AOTLoader::universe_init();
 
   // Checks 'AfterMemoryInit' constraints.
@@ -1085,10 +1089,6 @@
   // ("weak") refs processing infrastructure initialization
   Universe::heap()->post_initialize();
 
-  // Initialize performance counters for metaspaces
-  MetaspaceCounters::initialize_performance_counters();
-  CompressedClassSpaceCounters::initialize_performance_counters();
-
   MemoryService::add_metaspace_memory_pools();
 
   MemoryService::set_universe_heap(Universe::heap());
--- a/src/hotspot/share/oops/instanceMirrorKlass.inline.hpp	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/hotspot/share/oops/instanceMirrorKlass.inline.hpp	Mon Nov 27 17:04:45 2017 +0000
@@ -71,10 +71,15 @@
         Devirtualizer<nv>::do_klass(closure, klass);
       }
     } else {
-      // If klass is NULL then this a mirror for a primitive type.
-      // We don't have to follow them, since they are handled as strong
-      // roots in Universe::oops_do.
-      assert(java_lang_Class::is_primitive(obj), "Sanity check");
+      // We would like to assert here (as below) that if klass has been NULL, then
+      // this has been a mirror for a primitive type that we do not need to follow
+      // as they are always strong roots.
+      // However, we might get across a klass that just changed during CMS concurrent
+      // marking if allocation occurred in the old generation.
+      // This is benign here, as we keep alive all CLDs that were loaded during the
+      // CMS concurrent phase in the class loading, i.e. they will be iterated over
+      // and kept alive during remark.
+      // assert(java_lang_Class::is_primitive(obj), "Sanity check");
     }
   }
 
--- a/src/hotspot/share/opto/bytecodeInfo.cpp	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/hotspot/share/opto/bytecodeInfo.cpp	Mon Nov 27 17:04:45 2017 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2017, 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
@@ -480,6 +480,7 @@
   if ( callee->is_abstract())                   return "abstract method";
   if (!callee->has_balanced_monitors())         return "not compilable (unbalanced monitors)";
   if ( callee->get_flow_analysis()->failing())  return "not compilable (flow analysis failed)";
+  if (!callee->can_be_parsed())                 return "cannot be parsed";
   return NULL;
 }
 
--- a/src/hotspot/share/opto/idealGraphPrinter.cpp	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/hotspot/share/opto/idealGraphPrinter.cpp	Mon Nov 27 17:04:45 2017 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2017, 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,7 @@
 #include "opto/machnode.hpp"
 #include "opto/parse.hpp"
 #include "runtime/threadCritical.hpp"
+#include "runtime/threadSMR.hpp"
 
 #ifndef PRODUCT
 
@@ -91,8 +92,7 @@
 }
 
 void IdealGraphPrinter::clean_up() {
-  JavaThread *p;
-  for (p = Threads::first(); p; p = p->next()) {
+  for (JavaThreadIteratorWithHandle jtiwh; JavaThread *p = jtiwh.next(); ) {
     if (p->is_Compiler_thread()) {
       CompilerThread *c = (CompilerThread *)p;
       IdealGraphPrinter *printer = c->ideal_graph_printer();
--- a/src/hotspot/share/prims/jni.cpp	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/hotspot/share/prims/jni.cpp	Mon Nov 27 17:04:45 2017 +0000
@@ -4119,7 +4119,7 @@
   thread->initialize_thread_current();
 
   if (!os::create_attached_thread(thread)) {
-    delete thread;
+    thread->smr_delete();
     return JNI_ERR;
   }
   // Enable stack overflow checks
@@ -4250,7 +4250,7 @@
   // (platform-dependent) methods where we do alternate stack
   // maintenance work?)
   thread->exit(false, JavaThread::jni_detach);
-  delete thread;
+  thread->smr_delete();
 
   HOTSPOT_JNI_DETACHCURRENTTHREAD_RETURN(JNI_OK);
   return JNI_OK;
--- a/src/hotspot/share/prims/jvm.cpp	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/hotspot/share/prims/jvm.cpp	Mon Nov 27 17:04:45 2017 +0000
@@ -66,6 +66,7 @@
 #include "runtime/perfData.hpp"
 #include "runtime/reflection.hpp"
 #include "runtime/thread.inline.hpp"
+#include "runtime/threadSMR.hpp"
 #include "runtime/vframe.hpp"
 #include "runtime/vm_operations.hpp"
 #include "runtime/vm_version.hpp"
@@ -2737,16 +2738,12 @@
 
 // java.lang.Thread //////////////////////////////////////////////////////////////////////////////
 
-// In most of the JVM Thread support functions we need to be sure to lock the Threads_lock
-// to prevent the target thread from exiting after we have a pointer to the C++ Thread or
-// OSThread objects.  The exception to this rule is when the target object is the thread
-// doing the operation, in which case we know that the thread won't exit until the
-// operation is done (all exits being voluntary).  There are a few cases where it is
-// rather silly to do operations on yourself, like resuming yourself or asking whether
-// you are alive.  While these can still happen, they are not subject to deadlocks if
-// the lock is held while the operation occurs (this is not the case for suspend, for
-// instance), and are very unlikely.  Because IsAlive needs to be fast and its
-// implementation is local to this file, we always lock Threads_lock for that one.
+// In most of the JVM thread support functions we need to access the
+// thread through a ThreadsListHandle to prevent it from exiting and
+// being reclaimed while we try to operate on it. The exceptions to this
+// rule are when operating on the current thread, or if the monitor of
+// the target java.lang.Thread is locked at the Java level - in both
+// cases the target cannot exit.
 
 static void thread_entry(JavaThread* thread, TRAPS) {
   HandleMark hm(THREAD);
@@ -2821,7 +2818,7 @@
 
   if (native_thread->osthread() == NULL) {
     // No one should hold a reference to the 'native_thread'.
-    delete native_thread;
+    native_thread->smr_delete();
     if (JvmtiExport::should_post_resource_exhausted()) {
       JvmtiExport::post_resource_exhausted(
         JVMTI_RESOURCE_EXHAUSTED_OOM_ERROR | JVMTI_RESOURCE_EXHAUSTED_THREADS,
@@ -2835,41 +2832,45 @@
 
 JVM_END
 
+
 // JVM_Stop is implemented using a VM_Operation, so threads are forced to safepoints
 // before the quasi-asynchronous exception is delivered.  This is a little obtrusive,
 // but is thought to be reliable and simple. In the case, where the receiver is the
-// same thread as the sender, no safepoint is needed.
+// same thread as the sender, no VM_Operation is needed.
 JVM_ENTRY(void, JVM_StopThread(JNIEnv* env, jobject jthread, jobject throwable))
   JVMWrapper("JVM_StopThread");
 
+  // A nested ThreadsListHandle will grab the Threads_lock so create
+  // tlh before we resolve throwable.
+  ThreadsListHandle tlh(thread);
   oop java_throwable = JNIHandles::resolve(throwable);
   if (java_throwable == NULL) {
     THROW(vmSymbols::java_lang_NullPointerException());
   }
-  oop java_thread = JNIHandles::resolve_non_null(jthread);
-  JavaThread* receiver = java_lang_Thread::thread(java_thread);
-  Events::log_exception(JavaThread::current(),
+  oop java_thread = NULL;
+  JavaThread* receiver = NULL;
+  bool is_alive = tlh.cv_internal_thread_to_JavaThread(jthread, &receiver, &java_thread);
+  Events::log_exception(thread,
                         "JVM_StopThread thread JavaThread " INTPTR_FORMAT " as oop " INTPTR_FORMAT " [exception " INTPTR_FORMAT "]",
                         p2i(receiver), p2i((address)java_thread), p2i(throwable));
-  // First check if thread is alive
-  if (receiver != NULL) {
-    // Check if exception is getting thrown at self (use oop equality, since the
-    // target object might exit)
-    if (java_thread == thread->threadObj()) {
+
+  if (is_alive) {
+    // jthread refers to a live JavaThread.
+    if (thread == receiver) {
+      // Exception is getting thrown at self so no VM_Operation needed.
       THROW_OOP(java_throwable);
     } else {
-      // Enques a VM_Operation to stop all threads and then deliver the exception...
-      Thread::send_async_exception(java_thread, JNIHandles::resolve(throwable));
+      // Use a VM_Operation to throw the exception.
+      Thread::send_async_exception(java_thread, java_throwable);
     }
-  }
-  else {
+  } else {
     // Either:
     // - target thread has not been started before being stopped, or
     // - target thread already terminated
     // We could read the threadStatus to determine which case it is
     // but that is overkill as it doesn't matter. We must set the
     // stillborn flag for the first case, and if the thread has already
-    // exited setting this flag has no affect
+    // exited setting this flag has no effect.
     java_lang_Thread::set_stillborn(java_thread);
   }
 JVM_END
@@ -2885,12 +2886,12 @@
 
 JVM_ENTRY(void, JVM_SuspendThread(JNIEnv* env, jobject jthread))
   JVMWrapper("JVM_SuspendThread");
-  oop java_thread = JNIHandles::resolve_non_null(jthread);
-  JavaThread* receiver = java_lang_Thread::thread(java_thread);
-
-  if (receiver != NULL) {
-    // thread has run and has not exited (still on threads list)
-
+
+  ThreadsListHandle tlh(thread);
+  JavaThread* receiver = NULL;
+  bool is_alive = tlh.cv_internal_thread_to_JavaThread(jthread, &receiver, NULL);
+  if (is_alive) {
+    // jthread refers to a live JavaThread.
     {
       MutexLockerEx ml(receiver->SR_lock(), Mutex::_no_safepoint_check_flag);
       if (receiver->is_external_suspend()) {
@@ -2922,30 +2923,49 @@
 
 JVM_ENTRY(void, JVM_ResumeThread(JNIEnv* env, jobject jthread))
   JVMWrapper("JVM_ResumeThread");
-  // Ensure that the C++ Thread and OSThread structures aren't freed before we operate.
-  // We need to *always* get the threads lock here, since this operation cannot be allowed during
-  // a safepoint. The safepoint code relies on suspending a thread to examine its state. If other
-  // threads randomly resumes threads, then a thread might not be suspended when the safepoint code
-  // looks at it.
-  MutexLocker ml(Threads_lock);
-  JavaThread* thr = java_lang_Thread::thread(JNIHandles::resolve_non_null(jthread));
-  if (thr != NULL) {
-    // the thread has run and is not in the process of exiting
-    thr->java_resume();
+
+  ThreadsListHandle tlh(thread);
+  JavaThread* receiver = NULL;
+  bool is_alive = tlh.cv_internal_thread_to_JavaThread(jthread, &receiver, NULL);
+  if (is_alive) {
+    // jthread refers to a live JavaThread.
+
+    // This is the original comment for this Threads_lock grab:
+    //   We need to *always* get the threads lock here, since this operation cannot be allowed during
+    //   a safepoint. The safepoint code relies on suspending a thread to examine its state. If other
+    //   threads randomly resumes threads, then a thread might not be suspended when the safepoint code
+    //   looks at it.
+    //
+    // The above comment dates back to when we had both internal and
+    // external suspend APIs that shared a common underlying mechanism.
+    // External suspend is now entirely cooperative and doesn't share
+    // anything with internal suspend. That said, there are some
+    // assumptions in the VM that an external resume grabs the
+    // Threads_lock. We can't drop the Threads_lock grab here until we
+    // resolve the assumptions that exist elsewhere.
+    //
+    MutexLocker ml(Threads_lock);
+    receiver->java_resume();
   }
 JVM_END
 
 
 JVM_ENTRY(void, JVM_SetThreadPriority(JNIEnv* env, jobject jthread, jint prio))
   JVMWrapper("JVM_SetThreadPriority");
-  // Ensure that the C++ Thread and OSThread structures aren't freed before we operate
-  MutexLocker ml(Threads_lock);
-  oop java_thread = JNIHandles::resolve_non_null(jthread);
+
+  ThreadsListHandle tlh(thread);
+  oop java_thread = NULL;
+  JavaThread* receiver = NULL;
+  bool is_alive = tlh.cv_internal_thread_to_JavaThread(jthread, &receiver, &java_thread);
   java_lang_Thread::set_priority(java_thread, (ThreadPriority)prio);
-  JavaThread* thr = java_lang_Thread::thread(java_thread);
-  if (thr != NULL) {                  // Thread not yet started; priority pushed down when it is
-    Thread::set_priority(thr, (ThreadPriority)prio);
+
+  if (is_alive) {
+    // jthread refers to a live JavaThread.
+    Thread::set_priority(receiver, (ThreadPriority)prio);
   }
+  // Implied else: If the JavaThread hasn't started yet, then the
+  // priority set in the java.lang.Thread object above will be pushed
+  // down when it does start.
 JVM_END
 
 
@@ -3016,67 +3036,39 @@
 JVM_ENTRY(jint, JVM_CountStackFrames(JNIEnv* env, jobject jthread))
   JVMWrapper("JVM_CountStackFrames");
 
-  // Ensure that the C++ Thread and OSThread structures aren't freed before we operate
-  oop java_thread = JNIHandles::resolve_non_null(jthread);
-  bool throw_illegal_thread_state = false;
+  uint32_t debug_bits = 0;
+  ThreadsListHandle tlh(thread);
+  JavaThread* receiver = NULL;
+  bool is_alive = tlh.cv_internal_thread_to_JavaThread(jthread, &receiver, NULL);
   int count = 0;
-
-  {
-    MutexLockerEx ml(thread->threadObj() == java_thread ? NULL : Threads_lock);
-    // We need to re-resolve the java_thread, since a GC might have happened during the
-    // acquire of the lock
-    JavaThread* thr = java_lang_Thread::thread(JNIHandles::resolve_non_null(jthread));
-
-    if (thr == NULL) {
-      // do nothing
-    } else if(! thr->is_external_suspend() || ! thr->frame_anchor()->walkable()) {
-      // Check whether this java thread has been suspended already. If not, throws
-      // IllegalThreadStateException. We defer to throw that exception until
-      // Threads_lock is released since loading exception class has to leave VM.
-      // The correct way to test a thread is actually suspended is
-      // wait_for_ext_suspend_completion(), but we can't call that while holding
-      // the Threads_lock. The above tests are sufficient for our purposes
-      // provided the walkability of the stack is stable - which it isn't
-      // 100% but close enough for most practical purposes.
-      throw_illegal_thread_state = true;
+  if (is_alive) {
+    // jthread refers to a live JavaThread.
+    if (receiver->is_thread_fully_suspended(true /* wait for suspend completion */, &debug_bits)) {
+      // Count all java activation, i.e., number of vframes.
+      for (vframeStream vfst(receiver); !vfst.at_end(); vfst.next()) {
+        // Native frames are not counted.
+        if (!vfst.method()->is_native()) count++;
+      }
     } else {
-      // Count all java activation, i.e., number of vframes
-      for(vframeStream vfst(thr); !vfst.at_end(); vfst.next()) {
-        // Native frames are not counted
-        if (!vfst.method()->is_native()) count++;
-       }
+      THROW_MSG_0(vmSymbols::java_lang_IllegalThreadStateException(),
+                  "this thread is not suspended");
     }
   }
-
-  if (throw_illegal_thread_state) {
-    THROW_MSG_0(vmSymbols::java_lang_IllegalThreadStateException(),
-                "this thread is not suspended");
-  }
+  // Implied else: if JavaThread is not alive simply return a count of 0.
+
   return count;
 JVM_END
 
-// Consider: A better way to implement JVM_Interrupt() is to acquire
-// Threads_lock to resolve the jthread into a Thread pointer, fetch
-// Thread->platformevent, Thread->native_thr, Thread->parker, etc.,
-// drop Threads_lock, and the perform the unpark() and thr_kill() operations
-// outside the critical section.  Threads_lock is hot so we want to minimize
-// the hold-time.  A cleaner interface would be to decompose interrupt into
-// two steps.  The 1st phase, performed under Threads_lock, would return
-// a closure that'd be invoked after Threads_lock was dropped.
-// This tactic is safe as PlatformEvent and Parkers are type-stable (TSM) and
-// admit spurious wakeups.
 
 JVM_ENTRY(void, JVM_Interrupt(JNIEnv* env, jobject jthread))
   JVMWrapper("JVM_Interrupt");
 
-  // Ensure that the C++ Thread and OSThread structures aren't freed before we operate
-  oop java_thread = JNIHandles::resolve_non_null(jthread);
-  MutexLockerEx ml(thread->threadObj() == java_thread ? NULL : Threads_lock);
-  // We need to re-resolve the java_thread, since a GC might have happened during the
-  // acquire of the lock
-  JavaThread* thr = java_lang_Thread::thread(JNIHandles::resolve_non_null(jthread));
-  if (thr != NULL) {
-    Thread::interrupt(thr);
+  ThreadsListHandle tlh(thread);
+  JavaThread* receiver = NULL;
+  bool is_alive = tlh.cv_internal_thread_to_JavaThread(jthread, &receiver, NULL);
+  if (is_alive) {
+    // jthread refers to a live JavaThread.
+    Thread::interrupt(receiver);
   }
 JVM_END
 
@@ -3084,16 +3076,14 @@
 JVM_QUICK_ENTRY(jboolean, JVM_IsInterrupted(JNIEnv* env, jobject jthread, jboolean clear_interrupted))
   JVMWrapper("JVM_IsInterrupted");
 
-  // Ensure that the C++ Thread and OSThread structures aren't freed before we operate
-  oop java_thread = JNIHandles::resolve_non_null(jthread);
-  MutexLockerEx ml(thread->threadObj() == java_thread ? NULL : Threads_lock);
-  // We need to re-resolve the java_thread, since a GC might have happened during the
-  // acquire of the lock
-  JavaThread* thr = java_lang_Thread::thread(JNIHandles::resolve_non_null(jthread));
-  if (thr == NULL) {
+  ThreadsListHandle tlh(thread);
+  JavaThread* receiver = NULL;
+  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);
+  } else {
     return JNI_FALSE;
-  } else {
-    return (jboolean) Thread::is_interrupted(thr, clear_interrupted != 0);
   }
 JVM_END
 
@@ -3122,14 +3112,16 @@
 
 JVM_ENTRY(void, JVM_SetNativeThreadName(JNIEnv* env, jobject jthread, jstring name))
   JVMWrapper("JVM_SetNativeThreadName");
-  ResourceMark rm(THREAD);
+
+  // We don't use a ThreadsListHandle here because the current thread
+  // must be alive.
   oop java_thread = JNIHandles::resolve_non_null(jthread);
   JavaThread* thr = java_lang_Thread::thread(java_thread);
-  // Thread naming only supported for the current thread, doesn't work for
-  // target threads.
-  if (Thread::current() == thr && !thr->has_attached_via_jni()) {
+  if (thread == thr && !thr->has_attached_via_jni()) {
+    // Thread naming is only supported for the current thread and
     // we don't set the name of an attached thread to avoid stepping
-    // on other programs
+    // on other programs.
+    ResourceMark rm(thread);
     const char *thread_name = java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(name));
     os::set_native_thread_name(thread_name);
   }
@@ -3671,6 +3663,8 @@
     thread_handle_array->append(h);
   }
 
+  // The JavaThread references in thread_handle_array are validated
+  // in VM_ThreadDump::doit().
   Handle stacktraces = ThreadService::dump_stack_traces(thread_handle_array, num_threads, CHECK_NULL);
   return (jobjectArray)JNIHandles::make_local(env, stacktraces());
 
--- a/src/hotspot/share/prims/jvmtiEnter.xsl	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/hotspot/share/prims/jvmtiEnter.xsl	Mon Nov 27 17:04:45 2017 +0000
@@ -45,6 +45,7 @@
 # include "prims/jvmtiEnter.hpp"
 # include "prims/jvmtiRawMonitor.hpp"
 # include "prims/jvmtiUtil.hpp"
+# include "runtime/threadSMR.hpp"
 
 </xsl:text>
 
@@ -769,47 +770,27 @@
 
 <xsl:template match="jthread" mode="dochecksbody">
   <xsl:param name="name"/>
-    <xsl:text>    oop thread_oop = JNIHandles::resolve_external_guard(</xsl:text>
+    <xsl:text>    err = JvmtiExport::cv_external_thread_to_JavaThread(tlh.list(), </xsl:text>
     <xsl:value-of select="$name"/>
-    <xsl:text>);
-    if (thread_oop == NULL) {
+    <xsl:text>, &amp;java_thread, NULL);
+    if (err != JVMTI_ERROR_NONE) {
 </xsl:text>
     <xsl:apply-templates select=".." mode="traceError">     
-      <xsl:with-param name="err">JVMTI_ERROR_INVALID_THREAD</xsl:with-param>
-      <xsl:with-param name="comment"> - jthread resolved to NULL - jthread = " PTR_FORMAT "</xsl:with-param>
+      <xsl:with-param name="err">err</xsl:with-param>
+      <xsl:with-param name="comment"> - jthread did not convert to a JavaThread - jthread = " PTR_FORMAT "</xsl:with-param>
       <xsl:with-param name="extraValue">, p2i(<xsl:value-of select="$name"/>)</xsl:with-param>
     </xsl:apply-templates>
     <xsl:text>
     }
-    if (!thread_oop-&gt;is_a(SystemDictionary::Thread_klass())) {
 </xsl:text>
-    <xsl:apply-templates select=".." mode="traceError">     
-      <xsl:with-param name="err">JVMTI_ERROR_INVALID_THREAD</xsl:with-param>
-      <xsl:with-param name="comment"> - oop is not a thread - jthread = " PTR_FORMAT "</xsl:with-param>
-      <xsl:with-param name="extraValue">, p2i(<xsl:value-of select="$name"/>)</xsl:with-param>
-    </xsl:apply-templates>
-    <xsl:text>
-    }
-    java_thread = java_lang_Thread::thread(thread_oop); 
-    if (java_thread == NULL) {
-</xsl:text>
-    <xsl:apply-templates select=".." mode="traceError">     
-      <xsl:with-param name="err">
-        <xsl:text>JVMTI_ERROR_THREAD_NOT_ALIVE</xsl:text>
-      </xsl:with-param>
-      <xsl:with-param name="comment"> - not a Java thread - jthread = " PTR_FORMAT "</xsl:with-param>
-      <xsl:with-param name="extraValue">, p2i(<xsl:value-of select="$name"/>)</xsl:with-param>
-    </xsl:apply-templates>
-    <xsl:text>
-    }
-</xsl:text>  
 </xsl:template>
 
 <xsl:template match="jthread" mode="dochecks">
   <xsl:param name="name"/>
   <!-- If we convert and test threads -->
   <xsl:if test="count(@impl)=0 or not(contains(@impl,'noconvert'))">
-    <xsl:text>  JavaThread* java_thread;
+    <xsl:text>  JavaThread* java_thread = NULL;
+  ThreadsListHandle tlh(this_thread);
 </xsl:text>
     <xsl:choose>
       <xsl:when test="count(@null)=0">
--- a/src/hotspot/share/prims/jvmtiEnv.cpp	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/hotspot/share/prims/jvmtiEnv.cpp	Mon Nov 27 17:04:45 2017 +0000
@@ -62,6 +62,7 @@
 #include "runtime/reflectionUtils.hpp"
 #include "runtime/signature.hpp"
 #include "runtime/thread.inline.hpp"
+#include "runtime/threadSMR.hpp"
 #include "runtime/timerTrace.hpp"
 #include "runtime/vframe.hpp"
 #include "runtime/vmThread.hpp"
@@ -162,7 +163,6 @@
     *data_ptr = (state == NULL) ? NULL :
       state->env_thread_state(this)->get_agent_thread_local_storage_data();
   } else {
-
     // jvmti_GetThreadLocalStorage is "in native" and doesn't transition
     // the thread to _thread_in_vm. However, when the TLS for a thread
     // other than the current thread is required we need to transition
@@ -172,17 +172,13 @@
     VM_ENTRY_BASE(jvmtiError, JvmtiEnv::GetThreadLocalStorage , current_thread)
     debug_only(VMNativeEntryWrapper __vew;)
 
-    oop thread_oop = JNIHandles::resolve_external_guard(thread);
-    if (thread_oop == NULL) {
-      return JVMTI_ERROR_INVALID_THREAD;
+    JavaThread* java_thread = NULL;
+    ThreadsListHandle tlh(current_thread);
+    jvmtiError err = JvmtiExport::cv_external_thread_to_JavaThread(tlh.list(), thread, &java_thread, NULL);
+    if (err != JVMTI_ERROR_NONE) {
+      return err;
     }
-    if (!thread_oop->is_a(SystemDictionary::Thread_klass())) {
-      return JVMTI_ERROR_INVALID_THREAD;
-    }
-    JavaThread* java_thread = java_lang_Thread::thread(thread_oop);
-    if (java_thread == NULL) {
-      return JVMTI_ERROR_THREAD_NOT_ALIVE;
-    }
+
     JvmtiThreadState* state = java_thread->jvmti_thread_state();
     *data_ptr = (state == NULL) ? NULL :
       state->env_thread_state(this)->get_agent_thread_local_storage_data();
@@ -518,43 +514,61 @@
 // event_thread - NULL is a valid value, must be checked
 jvmtiError
 JvmtiEnv::SetEventNotificationMode(jvmtiEventMode mode, jvmtiEvent event_type, jthread event_thread,   ...) {
-  JavaThread* java_thread = NULL;
-  if (event_thread != NULL) {
-    oop thread_oop = JNIHandles::resolve_external_guard(event_thread);
-    if (thread_oop == NULL) {
-      return JVMTI_ERROR_INVALID_THREAD;
+  if (event_thread == NULL) {
+    // Can be called at Agent_OnLoad() time with event_thread == NULL
+    // when Thread::current() does not work yet so we cannot create a
+    // ThreadsListHandle that is common to both thread-specific and
+    // global code paths.
+
+    // event_type must be valid
+    if (!JvmtiEventController::is_valid_event_type(event_type)) {
+      return JVMTI_ERROR_INVALID_EVENT_TYPE;
+    }
+
+    bool enabled = (mode == JVMTI_ENABLE);
+
+    // assure that needed capabilities are present
+    if (enabled && !JvmtiUtil::has_event_capability(event_type, get_capabilities())) {
+      return JVMTI_ERROR_MUST_POSSESS_CAPABILITY;
+    }
+
+    if (event_type == JVMTI_EVENT_CLASS_FILE_LOAD_HOOK && enabled) {
+      record_class_file_load_hook_enabled();
     }
-    if (!thread_oop->is_a(SystemDictionary::Thread_klass())) {
-      return JVMTI_ERROR_INVALID_THREAD;
+    JvmtiEventController::set_user_enabled(this, (JavaThread*) NULL, event_type, enabled);
+  } else {
+    // We have a specified event_thread.
+
+    JavaThread* java_thread = NULL;
+    ThreadsListHandle tlh;
+    jvmtiError err = JvmtiExport::cv_external_thread_to_JavaThread(tlh.list(), event_thread, &java_thread, NULL);
+    if (err != JVMTI_ERROR_NONE) {
+      return err;
+    }
+
+    // event_type must be valid
+    if (!JvmtiEventController::is_valid_event_type(event_type)) {
+      return JVMTI_ERROR_INVALID_EVENT_TYPE;
     }
-    java_thread = java_lang_Thread::thread(thread_oop);
-    if (java_thread == NULL) {
-      return JVMTI_ERROR_THREAD_NOT_ALIVE;
+
+    // global events cannot be controlled at thread level.
+    if (JvmtiEventController::is_global_event(event_type)) {
+      return JVMTI_ERROR_ILLEGAL_ARGUMENT;
     }
+
+    bool enabled = (mode == JVMTI_ENABLE);
+
+    // assure that needed capabilities are present
+    if (enabled && !JvmtiUtil::has_event_capability(event_type, get_capabilities())) {
+      return JVMTI_ERROR_MUST_POSSESS_CAPABILITY;
+    }
+
+    if (event_type == JVMTI_EVENT_CLASS_FILE_LOAD_HOOK && enabled) {
+      record_class_file_load_hook_enabled();
+    }
+    JvmtiEventController::set_user_enabled(this, java_thread, event_type, enabled);
   }
 
-  // event_type must be valid
-  if (!JvmtiEventController::is_valid_event_type(event_type)) {
-    return JVMTI_ERROR_INVALID_EVENT_TYPE;
-  }
-
-  // global events cannot be controlled at thread level.
-  if (java_thread != NULL && JvmtiEventController::is_global_event(event_type)) {
-    return JVMTI_ERROR_ILLEGAL_ARGUMENT;
-  }
-
-  bool enabled = (mode == JVMTI_ENABLE);
-
-  // assure that needed capabilities are present
-  if (enabled && !JvmtiUtil::has_event_capability(event_type, get_capabilities())) {
-    return JVMTI_ERROR_MUST_POSSESS_CAPABILITY;
-  }
-
-  if (event_type == JVMTI_EVENT_CLASS_FILE_LOAD_HOOK && enabled) {
-    record_class_file_load_hook_enabled();
-  }
-  JvmtiEventController::set_user_enabled(this, java_thread, event_type, enabled);
-
   return JVMTI_ERROR_NONE;
 } /* end SetEventNotificationMode */
 
@@ -817,35 +831,45 @@
 // thread_state_ptr - pre-checked for NULL
 jvmtiError
 JvmtiEnv::GetThreadState(jthread thread, jint* thread_state_ptr) {
-  jint state;
-  oop thread_oop;
-  JavaThread* thr;
+  JavaThread* current_thread = JavaThread::current();
+  JavaThread* java_thread = NULL;
+  oop thread_oop = NULL;
+  ThreadsListHandle tlh(current_thread);
 
   if (thread == NULL) {
-    thread_oop = JavaThread::current()->threadObj();
+    java_thread = current_thread;
+    thread_oop = java_thread->threadObj();
+
+    if (thread_oop == NULL || !thread_oop->is_a(SystemDictionary::Thread_klass())) {
+      return JVMTI_ERROR_INVALID_THREAD;
+    }
   } else {
-    thread_oop = JNIHandles::resolve_external_guard(thread);
-  }
-
-  if (thread_oop == NULL || !thread_oop->is_a(SystemDictionary::Thread_klass())) {
-    return JVMTI_ERROR_INVALID_THREAD;
+    jvmtiError err = JvmtiExport::cv_external_thread_to_JavaThread(tlh.list(), thread, &java_thread, &thread_oop);
+    if (err != JVMTI_ERROR_NONE) {
+      // We got an error code so we don't have a JavaThread *, but
+      // only return an error from here if we didn't get a valid
+      // thread_oop.
+      if (thread_oop == NULL) {
+        return err;
+      }
+      // We have a valid thread_oop so we can return some thread state.
+    }
   }
 
   // get most state bits
-  state = (jint)java_lang_Thread::get_thread_status(thread_oop);
-
-  // add more state bits
-  thr = java_lang_Thread::thread(thread_oop);
-  if (thr != NULL) {
-    JavaThreadState jts = thr->thread_state();
-
-    if (thr->is_being_ext_suspended()) {
+  jint state = (jint)java_lang_Thread::get_thread_status(thread_oop);
+
+  if (java_thread != NULL) {
+    // We have a JavaThread* so add more state bits.
+    JavaThreadState jts = java_thread->thread_state();
+
+    if (java_thread->is_being_ext_suspended()) {
       state |= JVMTI_THREAD_STATE_SUSPENDED;
     }
     if (jts == _thread_in_native) {
       state |= JVMTI_THREAD_STATE_IN_NATIVE;
     }
-    OSThread* osThread = thr->osthread();
+    OSThread* osThread = java_thread->osthread();
     if (osThread != NULL && osThread->interrupted()) {
       state |= JVMTI_THREAD_STATE_INTERRUPTED;
     }
@@ -891,7 +915,6 @@
     thread_objs[i] = Handle(tle.get_threadObj(i));
   }
 
-  // have to make global handles outside of Threads_lock
   jthread *jthreads  = new_jthreadArray(nthreads, thread_objs);
   NULL_CHECK(jthreads, JVMTI_ERROR_OUT_OF_MEMORY);
 
@@ -935,19 +958,12 @@
 jvmtiError
 JvmtiEnv::SuspendThreadList(jint request_count, const jthread* request_list, jvmtiError* results) {
   int needSafepoint = 0;  // > 0 if we need a safepoint
+  ThreadsListHandle tlh;
   for (int i = 0; i < request_count; i++) {
-    JavaThread *java_thread = get_JavaThread(request_list[i]);
-    if (java_thread == NULL) {
-      results[i] = JVMTI_ERROR_INVALID_THREAD;
-      continue;
-    }
-    // the thread has not yet run or has exited (not on threads list)
-    if (java_thread->threadObj() == NULL) {
-      results[i] = JVMTI_ERROR_THREAD_NOT_ALIVE;
-      continue;
-    }
-    if (java_lang_Thread::thread(java_thread->threadObj()) == NULL) {
-      results[i] = JVMTI_ERROR_THREAD_NOT_ALIVE;
+    JavaThread *java_thread = NULL;
+    jvmtiError err = JvmtiExport::cv_external_thread_to_JavaThread(tlh.list(), request_list[i], &java_thread, NULL);
+    if (err != JVMTI_ERROR_NONE) {
+      results[i] = err;
       continue;
     }
     // don't allow hidden thread suspend request.
@@ -1018,10 +1034,12 @@
 // results - pre-checked for NULL
 jvmtiError
 JvmtiEnv::ResumeThreadList(jint request_count, const jthread* request_list, jvmtiError* results) {
+  ThreadsListHandle tlh;
   for (int i = 0; i < request_count; i++) {
-    JavaThread *java_thread = get_JavaThread(request_list[i]);
-    if (java_thread == NULL) {
-      results[i] = JVMTI_ERROR_INVALID_THREAD;
+    JavaThread* java_thread = NULL;
+    jvmtiError err = JvmtiExport::cv_external_thread_to_JavaThread(tlh.list(), request_list[i], &java_thread, NULL);
+    if (err != JVMTI_ERROR_NONE) {
+      results[i] = err;
       continue;
     }
     // don't allow hidden thread resume request.
@@ -1039,7 +1057,7 @@
       continue;
     }
 
-    results[i] = JVMTI_ERROR_NONE;  // indicate successful suspend
+    results[i] = JVMTI_ERROR_NONE;  // indicate successful resume
   }
   // per-thread resume results returned via results parameter
   return JVMTI_ERROR_NONE;
@@ -1064,20 +1082,14 @@
 // thread - NOT pre-checked
 jvmtiError
 JvmtiEnv::InterruptThread(jthread thread) {
-  oop thread_oop = JNIHandles::resolve_external_guard(thread);
-  if (thread_oop == NULL || !thread_oop->is_a(SystemDictionary::Thread_klass()))
-    return JVMTI_ERROR_INVALID_THREAD;
-
+  // TODO: this is very similar to JVM_Interrupt(); share code in future
   JavaThread* current_thread  = JavaThread::current();
-
-  // Todo: this is a duplicate of JVM_Interrupt; share code in future
-  // Ensure that the C++ Thread and OSThread structures aren't freed before we operate
-  MutexLockerEx ml(current_thread->threadObj() == thread_oop ? NULL : Threads_lock);
-  // We need to re-resolve the java_thread, since a GC might have happened during the
-  // acquire of the lock
-
-  JavaThread* java_thread = java_lang_Thread::thread(JNIHandles::resolve_external_guard(thread));
-  NULL_CHECK(java_thread, JVMTI_ERROR_THREAD_NOT_ALIVE);
+  JavaThread* java_thread = NULL;
+  ThreadsListHandle tlh(current_thread);
+  jvmtiError err = JvmtiExport::cv_external_thread_to_JavaThread(tlh.list(), thread, &java_thread, NULL);
+  if (err != JVMTI_ERROR_NONE) {
+    return err;
+  }
 
   Thread::interrupt(java_thread);
 
@@ -1094,16 +1106,28 @@
   HandleMark hm;
 
   JavaThread* current_thread = JavaThread::current();
+  ThreadsListHandle tlh(current_thread);
 
   // if thread is NULL the current thread is used
-  oop thread_oop;
+  oop thread_oop = NULL;
   if (thread == NULL) {
     thread_oop = current_thread->threadObj();
+    if (thread_oop == NULL || !thread_oop->is_a(SystemDictionary::Thread_klass())) {
+      return JVMTI_ERROR_INVALID_THREAD;
+    }
   } else {
-    thread_oop = JNIHandles::resolve_external_guard(thread);
+    JavaThread* java_thread = NULL;
+    jvmtiError err = JvmtiExport::cv_external_thread_to_JavaThread(tlh.list(), thread, &java_thread, &thread_oop);
+    if (err != JVMTI_ERROR_NONE) {
+      // We got an error code so we don't have a JavaThread *, but
+      // only return an error from here if we didn't get a valid
+      // thread_oop.
+      if (thread_oop == NULL) {
+        return err;
+      }
+      // We have a valid thread_oop so we can return some thread info.
+    }
   }
-  if (thread_oop == NULL || !thread_oop->is_a(SystemDictionary::Thread_klass()))
-    return JVMTI_ERROR_INVALID_THREAD;
 
   Handle thread_obj(current_thread, thread_oop);
   Handle name;
@@ -1272,17 +1296,31 @@
 // arg - NULL is a valid value, must be checked
 jvmtiError
 JvmtiEnv::RunAgentThread(jthread thread, jvmtiStartFunction proc, const void* arg, jint priority) {
-  oop thread_oop = JNIHandles::resolve_external_guard(thread);
-  if (thread_oop == NULL || !thread_oop->is_a(SystemDictionary::Thread_klass())) {
+  JavaThread* current_thread = JavaThread::current();
+
+  JavaThread* java_thread = NULL;
+  oop thread_oop = NULL;
+  ThreadsListHandle tlh(current_thread);
+  jvmtiError err = JvmtiExport::cv_external_thread_to_JavaThread(tlh.list(), thread, &java_thread, &thread_oop);
+  if (err != JVMTI_ERROR_NONE) {
+    // We got an error code so we don't have a JavaThread *, but
+    // only return an error from here if we didn't get a valid
+    // thread_oop.
+    if (thread_oop == NULL) {
+      return err;
+    }
+    // We have a valid thread_oop.
+  }
+
+  if (java_thread != NULL) {
+    // 'thread' refers to an existing JavaThread.
     return JVMTI_ERROR_INVALID_THREAD;
   }
+
   if (priority < JVMTI_THREAD_MIN_PRIORITY || priority > JVMTI_THREAD_MAX_PRIORITY) {
     return JVMTI_ERROR_INVALID_PRIORITY;
   }
 
-  //Thread-self
-  JavaThread* current_thread = JavaThread::current();
-
   Handle thread_hndl(current_thread, thread_oop);
   {
     MutexLocker mu(Threads_lock); // grab Threads_lock
@@ -1292,7 +1330,9 @@
     // At this point it may be possible that no osthread was created for the
     // JavaThread due to lack of memory.
     if (new_thread == NULL || new_thread->osthread() == NULL) {
-      if (new_thread) delete new_thread;
+      if (new_thread != NULL) {
+        new_thread->smr_delete();
+      }
       return JVMTI_ERROR_OUT_OF_MEMORY;
     }
 
@@ -1394,36 +1434,53 @@
   int ngroups = 0;
   int hidden_threads = 0;
 
-  ResourceMark rm;
-  HandleMark hm;
+  ResourceMark rm(current_thread);
+  HandleMark hm(current_thread);
 
   Handle group_hdl(current_thread, group_obj);
 
-  { MutexLocker mu(Threads_lock);
+  { // Cannot allow thread or group counts to change.
+    MutexLocker mu(Threads_lock);
 
     nthreads = java_lang_ThreadGroup::nthreads(group_hdl());
     ngroups  = java_lang_ThreadGroup::ngroups(group_hdl());
 
     if (nthreads > 0) {
+      ThreadsListHandle tlh(current_thread);
       objArrayOop threads = java_lang_ThreadGroup::threads(group_hdl());
       assert(nthreads <= threads->length(), "too many threads");
       thread_objs = NEW_RESOURCE_ARRAY(Handle,nthreads);
       for (int i=0, j=0; i<nthreads; i++) {
         oop thread_obj = threads->obj_at(i);
         assert(thread_obj != NULL, "thread_obj is NULL");
-        JavaThread *javathread = java_lang_Thread::thread(thread_obj);
-        // Filter out hidden java threads.
-        if (javathread != NULL && javathread->is_hidden_from_external_view()) {
-          hidden_threads++;
-          continue;
+        JavaThread *java_thread = NULL;
+        jvmtiError err = JvmtiExport::cv_oop_to_JavaThread(tlh.list(), thread_obj, &java_thread);
+        if (err == JVMTI_ERROR_NONE) {
+          // Have a valid JavaThread*.
+          if (java_thread->is_hidden_from_external_view()) {
+            // Filter out hidden java threads.
+            hidden_threads++;
+            continue;
+          }
+        } else {
+          // We couldn't convert thread_obj into a JavaThread*.
+          if (err == JVMTI_ERROR_INVALID_THREAD) {
+            // The thread_obj does not refer to a java.lang.Thread object
+            // so skip it.
+            hidden_threads++;
+            continue;
+          }
+          // We have a valid thread_obj, but no JavaThread*; the caller
+          // can still have limited use for the thread_obj.
         }
         thread_objs[j++] = Handle(current_thread, thread_obj);
       }
       nthreads -= hidden_threads;
-    }
+    } // ThreadsListHandle is destroyed here.
+
     if (ngroups > 0) {
       objArrayOop groups = java_lang_ThreadGroup::groups(group_hdl());
-      assert(ngroups <= groups->length(), "too many threads");
+      assert(ngroups <= groups->length(), "too many groups");
       group_objs = NEW_RESOURCE_ARRAY(Handle,ngroups);
       for (int i=0; i<ngroups; i++) {
         oop group_obj = groups->obj_at(i);
@@ -1556,7 +1613,7 @@
   }
 
   // Check if java_thread is fully suspended
-  if (!is_thread_fully_suspended(java_thread, true /* wait for suspend completion */, &debug_bits)) {
+  if (!java_thread->is_thread_fully_suspended(true /* wait for suspend completion */, &debug_bits)) {
     return JVMTI_ERROR_THREAD_NOT_SUSPENDED;
   }
   // Check to see if a PopFrame was already in progress
@@ -1686,8 +1743,8 @@
     return JVMTI_ERROR_THREAD_NOT_ALIVE;
   }
 
-  if (!JvmtiEnv::is_thread_fully_suspended(java_thread, true, &debug_bits)) {
-      return JVMTI_ERROR_THREAD_NOT_SUSPENDED;
+  if (!java_thread->is_thread_fully_suspended(true, &debug_bits)) {
+    return JVMTI_ERROR_THREAD_NOT_SUSPENDED;
   }
 
   if (TraceJVMTICalls) {
--- a/src/hotspot/share/prims/jvmtiEnvBase.cpp	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/hotspot/share/prims/jvmtiEnvBase.cpp	Mon Nov 27 17:04:45 2017 +0000
@@ -44,6 +44,7 @@
 #include "runtime/objectMonitor.inline.hpp"
 #include "runtime/signature.hpp"
 #include "runtime/thread.inline.hpp"
+#include "runtime/threadSMR.hpp"
 #include "runtime/vframe.hpp"
 #include "runtime/vframe_hp.hpp"
 #include "runtime/vmThread.hpp"
@@ -487,37 +488,6 @@
   }
 }
 
-// Called from JVMTI entry points which perform stack walking. If the
-// associated JavaThread is the current thread, then wait_for_suspend
-// is not used. Otherwise, it determines if we should wait for the
-// "other" thread to complete external suspension. (NOTE: in future
-// releases the suspension mechanism should be reimplemented so this
-// is not necessary.)
-//
-bool
-JvmtiEnvBase::is_thread_fully_suspended(JavaThread* thr, bool wait_for_suspend, uint32_t *bits) {
-  // "other" threads require special handling
-  if (thr != JavaThread::current()) {
-    if (wait_for_suspend) {
-      // We are allowed to wait for the external suspend to complete
-      // so give the other thread a chance to get suspended.
-      if (!thr->wait_for_ext_suspend_completion(SuspendRetryCount,
-          SuspendRetryDelay, bits)) {
-        // didn't make it so let the caller know
-        return false;
-      }
-    }
-    // We aren't allowed to wait for the external suspend to complete
-    // so if the other thread isn't externally suspended we need to
-    // let the caller know.
-    else if (!thr->is_ext_suspend_completed_with_lock(bits)) {
-      return false;
-    }
-  }
-
-  return true;
-}
-
 
 // In the fullness of time, all users of the method should instead
 // directly use allocate, besides being cleaner and faster, this will
@@ -560,19 +530,6 @@
   return (jthreadGroup *) new_jobjectArray(length,handles);
 }
 
-
-JavaThread *
-JvmtiEnvBase::get_JavaThread(jthread jni_thread) {
-  oop t = JNIHandles::resolve_external_guard(jni_thread);
-  if (t == NULL || !t->is_a(SystemDictionary::Thread_klass())) {
-    return NULL;
-  }
-  // The following returns NULL if the thread has not yet run or is in
-  // process of exiting
-  return java_lang_Thread::thread(t);
-}
-
-
 // return the vframe on the specified thread and depth, NULL if no such frame
 vframe*
 JvmtiEnvBase::vframeFor(JavaThread* java_thread, jint depth) {
@@ -670,7 +627,7 @@
   uint32_t debug_bits = 0;
 #endif
   assert((SafepointSynchronize::is_at_safepoint() ||
-          is_thread_fully_suspended(java_thread, false, &debug_bits)),
+          java_thread->is_thread_fully_suspended(false, &debug_bits)),
          "at safepoint or target thread is suspended");
   oop obj = NULL;
   ObjectMonitor *mon = java_thread->current_waiting_monitor();
@@ -709,7 +666,7 @@
   uint32_t debug_bits = 0;
 #endif
   assert((SafepointSynchronize::is_at_safepoint() ||
-          is_thread_fully_suspended(java_thread, false, &debug_bits)),
+          java_thread->is_thread_fully_suspended(false, &debug_bits)),
          "at safepoint or target thread is suspended");
 
   if (java_thread->has_last_Java_frame()) {
@@ -831,7 +788,7 @@
   uint32_t debug_bits = 0;
 #endif
   assert((SafepointSynchronize::is_at_safepoint() ||
-          is_thread_fully_suspended(java_thread, false, &debug_bits)),
+          java_thread->is_thread_fully_suspended(false, &debug_bits)),
          "at safepoint or target thread is suspended");
   int count = 0;
   if (java_thread->has_last_Java_frame()) {
@@ -914,7 +871,7 @@
   uint32_t debug_bits = 0;
 #endif
   assert((SafepointSynchronize::is_at_safepoint() ||
-          is_thread_fully_suspended(java_thread, false, &debug_bits)),
+          java_thread->is_thread_fully_suspended(false, &debug_bits)),
          "at safepoint or target thread is suspended");
   Thread* current_thread = Thread::current();
   ResourceMark rm(current_thread);
@@ -976,7 +933,7 @@
   // first derive the object's owner and entry_count (if any)
   {
     // Revoke any biases before querying the mark word
-    if (SafepointSynchronize::is_at_safepoint()) {
+    if (at_safepoint) {
       BiasedLocking::revoke_at_safepoint(hobj);
     } else {
       BiasedLocking::revoke_and_rebias(hobj, false, calling_thread);
@@ -1008,11 +965,11 @@
     }
 
     if (owner != NULL) {
+      // Use current thread since function can be called from a
+      // JavaThread or the VMThread.
+      ThreadsListHandle tlh;
       // This monitor is owned so we have to find the owning JavaThread.
-      // Since owning_thread_from_monitor_owner() grabs a lock, GC can
-      // move our object at this point. However, our owner value is safe
-      // since it is either the Lock word on a stack or a JavaThread *.
-      owning_thread = Threads::owning_thread_from_monitor_owner(owner, !at_safepoint);
+      owning_thread = Threads::owning_thread_from_monitor_owner(tlh.list(), owner);
       // Cannot assume (owning_thread != NULL) here because this function
       // may not have been called at a safepoint and the owning_thread
       // might not be suspended.
@@ -1021,7 +978,7 @@
         // or it has to be suspended. Any of these conditions will prevent both
         // contending and waiting threads from modifying the state of
         // the monitor.
-        if (!at_safepoint && !JvmtiEnv::is_thread_fully_suspended(owning_thread, true, &debug_bits)) {
+        if (!at_safepoint && !owning_thread->is_thread_fully_suspended(true, &debug_bits)) {
           // Don't worry! This return of JVMTI_ERROR_THREAD_NOT_SUSPENDED
           // will not make it back to the JVM/TI agent. The error code will
           // get intercepted in JvmtiEnv::GetObjectMonitorUsage() which
@@ -1033,7 +990,7 @@
         ret.owner = (jthread)jni_reference(calling_thread, th);
       }
       // implied else: no owner
-    }
+    } // ThreadsListHandle is destroyed here.
 
     if (owning_thread != NULL) {  // monitor is owned
       // The recursions field of a monitor does not reflect recursions
@@ -1084,13 +1041,15 @@
     if (ret.waiter_count > 0) {
       // we have contending and/or waiting threads
       HandleMark hm;
+      // Use current thread since function can be called from a
+      // JavaThread or the VMThread.
+      ThreadsListHandle tlh;
       if (nWant > 0) {
         // we have contending threads
         ResourceMark rm;
         // get_pending_threads returns only java thread so we do not need to
-        // check for  non java threads.
-        GrowableArray<JavaThread*>* wantList = Threads::get_pending_threads(
-          nWant, (address)mon, !at_safepoint);
+        // check for non java threads.
+        GrowableArray<JavaThread*>* wantList = Threads::get_pending_threads(tlh.list(), nWant, (address)mon);
         if (wantList->length() < nWant) {
           // robustness: the pending list has gotten smaller
           nWant = wantList->length();
@@ -1101,7 +1060,7 @@
           // thread could potentially change the state of the monitor by
           // entering it. The JVM/TI spec doesn't allow this.
           if (owning_thread == NULL && !at_safepoint &
-              !JvmtiEnv::is_thread_fully_suspended(pending_thread, true, &debug_bits)) {
+              !pending_thread->is_thread_fully_suspended(true, &debug_bits)) {
             if (ret.owner != NULL) {
               destroy_jni_reference(calling_thread, ret.owner);
             }
@@ -1139,7 +1098,7 @@
           waiter = mon->next_waiter(waiter);
         }
       }
-    }
+    } // ThreadsListHandle is destroyed here.
 
     // Adjust count. nWant and nWait count values may be less than original.
     ret.waiter_count = nWant + nWait;
@@ -1291,14 +1250,23 @@
   assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
 
   ResourceMark rm;
+  ThreadsListHandle tlh;
   for (int i = 0; i < _thread_count; ++i) {
     jthread jt = _thread_list[i];
-    oop thread_oop = JNIHandles::resolve_external_guard(jt);
-    if (thread_oop == NULL || !thread_oop->is_a(SystemDictionary::Thread_klass())) {
-      set_result(JVMTI_ERROR_INVALID_THREAD);
-      return;
+    JavaThread* java_thread = NULL;
+    oop thread_oop = NULL;
+    jvmtiError err = JvmtiExport::cv_external_thread_to_JavaThread(tlh.list(), jt, &java_thread, &thread_oop);
+    if (err != JVMTI_ERROR_NONE) {
+      // We got an error code so we don't have a JavaThread *, but
+      // only return an error from here if we didn't get a valid
+      // thread_oop.
+      if (thread_oop == NULL) {
+        set_result(err);
+        return;
+      }
+      // We have a valid thread_oop.
     }
-    fill_frames(jt, java_lang_Thread::thread(thread_oop), thread_oop);
+    fill_frames(jt, java_thread, thread_oop);
   }
   allocate_and_fill_stacks(_thread_count);
 }
@@ -1309,7 +1277,7 @@
 
   ResourceMark rm;
   _final_thread_count = 0;
-  for (JavaThread *jt = Threads::first(); jt != NULL; jt = jt->next()) {
+  for (JavaThreadIteratorWithHandle jtiwh; JavaThread *jt = jtiwh.next(); ) {
     oop thread_oop = jt->threadObj();
     if (thread_oop != NULL &&
         !jt->is_exiting() &&
@@ -1404,9 +1372,7 @@
   }
 
   // Check if java_thread is fully suspended
-  if (!is_thread_fully_suspended(java_thread,
-                                 true /* wait for suspend completion */,
-                                 &debug_bits)) {
+  if (!java_thread->is_thread_fully_suspended(true /* wait for suspend completion */, &debug_bits)) {
     return JVMTI_ERROR_THREAD_NOT_SUSPENDED;
   }
 
@@ -1521,3 +1487,79 @@
   return JVMTI_ERROR_NONE;
 }
 
+void
+VM_UpdateForPopTopFrame::doit() {
+  JavaThread* jt = _state->get_thread();
+  ThreadsListHandle tlh;
+  if (jt != NULL && tlh.includes(jt) && !jt->is_exiting() && jt->threadObj() != NULL) {
+    _state->update_for_pop_top_frame();
+  } else {
+    _result = JVMTI_ERROR_THREAD_NOT_ALIVE;
+  }
+}
+
+void
+VM_SetFramePop::doit() {
+  JavaThread* jt = _state->get_thread();
+  ThreadsListHandle tlh;
+  if (jt != NULL && tlh.includes(jt) && !jt->is_exiting() && jt->threadObj() != NULL) {
+    int frame_number = _state->count_frames() - _depth;
+    _state->env_thread_state((JvmtiEnvBase*)_env)->set_frame_pop(frame_number);
+  } else {
+    _result = JVMTI_ERROR_THREAD_NOT_ALIVE;
+  }
+}
+
+void
+VM_GetOwnedMonitorInfo::doit() {
+  _result = JVMTI_ERROR_THREAD_NOT_ALIVE;
+  ThreadsListHandle tlh;
+  if (_java_thread != NULL && tlh.includes(_java_thread)
+      && !_java_thread->is_exiting() && _java_thread->threadObj() != NULL) {
+    _result = ((JvmtiEnvBase *)_env)->get_owned_monitors(_calling_thread, _java_thread,
+                                                          _owned_monitors_list);
+  }
+}
+
+void
+VM_GetCurrentContendedMonitor::doit() {
+  _result = JVMTI_ERROR_THREAD_NOT_ALIVE;
+  ThreadsListHandle tlh;
+  if (_java_thread != NULL && tlh.includes(_java_thread)
+      && !_java_thread->is_exiting() && _java_thread->threadObj() != NULL) {
+    _result = ((JvmtiEnvBase *)_env)->get_current_contended_monitor(_calling_thread,_java_thread,_owned_monitor_ptr);
+  }
+}
+
+void
+VM_GetStackTrace::doit() {
+  _result = JVMTI_ERROR_THREAD_NOT_ALIVE;
+  ThreadsListHandle tlh;
+  if (_java_thread != NULL && tlh.includes(_java_thread)
+      && !_java_thread->is_exiting() && _java_thread->threadObj() != NULL) {
+    _result = ((JvmtiEnvBase *)_env)->get_stack_trace(_java_thread,
+                                                      _start_depth, _max_count,
+                                                      _frame_buffer, _count_ptr);
+  }
+}
+
+void
+VM_GetFrameCount::doit() {
+  _result = JVMTI_ERROR_THREAD_NOT_ALIVE;
+  JavaThread* jt = _state->get_thread();
+  ThreadsListHandle tlh;
+  if (jt != NULL && tlh.includes(jt) && !jt->is_exiting() && jt->threadObj() != NULL) {
+    _result = ((JvmtiEnvBase*)_env)->get_frame_count(_state, _count_ptr);
+  }
+}
+
+void
+VM_GetFrameLocation::doit() {
+  _result = JVMTI_ERROR_THREAD_NOT_ALIVE;
+  ThreadsListHandle tlh;
+  if (_java_thread != NULL && tlh.includes(_java_thread)
+      && !_java_thread->is_exiting() && _java_thread->threadObj() != NULL) {
+    _result = ((JvmtiEnvBase*)_env)->get_frame_location(_java_thread, _depth,
+                                                        _method_ptr, _location_ptr);
+  }
+}
--- a/src/hotspot/share/prims/jvmtiEnvBase.hpp	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/hotspot/share/prims/jvmtiEnvBase.hpp	Mon Nov 27 17:04:45 2017 +0000
@@ -280,9 +280,6 @@
   jthread * new_jthreadArray(int length, Handle *handles);
   jthreadGroup * new_jthreadGroupArray(int length, Handle *handles);
 
-  // convert from JNIHandle to JavaThread *
-  JavaThread  * get_JavaThread(jthread jni_thread);
-
   // convert to a jni jclass from a non-null Klass*
   jclass get_jni_class_non_null(Klass* k);
 
@@ -297,11 +294,6 @@
  public:
   // get a field descriptor for the specified class and field
   static bool get_field_descriptor(Klass* k, jfieldID field, fieldDescriptor* fd);
-  // test for suspend - most (all?) of these should go away
-  static bool is_thread_fully_suspended(JavaThread *thread,
-                                        bool wait_for_suspend,
-                                        uint32_t *bits);
-
 
   // JVMTI API helper functions which are called at safepoint or thread is suspended.
   jvmtiError get_frame_count(JvmtiThreadState *state, jint *count_ptr);
@@ -360,14 +352,7 @@
   }
   VMOp_Type type() const { return VMOp_UpdateForPopTopFrame; }
   jvmtiError result() { return _result; }
-  void doit() {
-    JavaThread* jt = _state->get_thread();
-    if (Threads::includes(jt) && !jt->is_exiting() && jt->threadObj() != NULL) {
-      _state->update_for_pop_top_frame();
-    } else {
-      _result = JVMTI_ERROR_THREAD_NOT_ALIVE;
-    }
-  }
+  void doit();
 };
 
 // VM operation to set frame pop.
@@ -390,15 +375,7 @@
   bool allow_nested_vm_operations() const { return true; }
   VMOp_Type type() const { return VMOp_SetFramePop; }
   jvmtiError result() { return _result; }
-  void doit() {
-    JavaThread* jt = _state->get_thread();
-    if (Threads::includes(jt) && !jt->is_exiting() && jt->threadObj() != NULL) {
-      int frame_number = _state->count_frames() - _depth;
-      _state->env_thread_state((JvmtiEnvBase*)_env)->set_frame_pop(frame_number);
-    } else {
-      _result = JVMTI_ERROR_THREAD_NOT_ALIVE;
-    }
-  }
+  void doit();
 };
 
 
@@ -422,14 +399,7 @@
     _result = JVMTI_ERROR_NONE;
   }
   VMOp_Type type() const { return VMOp_GetOwnedMonitorInfo; }
-  void doit() {
-    _result = JVMTI_ERROR_THREAD_NOT_ALIVE;
-    if (Threads::includes(_java_thread) && !_java_thread->is_exiting()
-                                        && _java_thread->threadObj() != NULL) {
-      _result = ((JvmtiEnvBase *)_env)->get_owned_monitors(_calling_thread, _java_thread,
-                                                            _owned_monitors_list);
-    }
-  }
+  void doit();
   jvmtiError result() { return _result; }
 };
 
@@ -476,13 +446,7 @@
   }
   VMOp_Type type() const { return VMOp_GetCurrentContendedMonitor; }
   jvmtiError result() { return _result; }
-  void doit() {
-    _result = JVMTI_ERROR_THREAD_NOT_ALIVE;
-    if (Threads::includes(_java_thread) && !_java_thread->is_exiting() &&
-        _java_thread->threadObj() != NULL) {
-      _result = ((JvmtiEnvBase *)_env)->get_current_contended_monitor(_calling_thread,_java_thread,_owned_monitor_ptr);
-    }
-  }
+  void doit();
 };
 
 // VM operation to get stack trace at safepoint.
@@ -509,15 +473,7 @@
   }
   jvmtiError result() { return _result; }
   VMOp_Type type() const { return VMOp_GetStackTrace; }
-  void doit() {
-    _result = JVMTI_ERROR_THREAD_NOT_ALIVE;
-    if (Threads::includes(_java_thread) && !_java_thread->is_exiting()
-                                        && _java_thread->threadObj() != NULL) {
-      _result = ((JvmtiEnvBase *)_env)->get_stack_trace(_java_thread,
-                                                        _start_depth, _max_count,
-                                                        _frame_buffer, _count_ptr);
-    }
-  }
+  void doit();
 };
 
 // forward declaration
@@ -607,13 +563,7 @@
   }
   VMOp_Type type() const { return VMOp_GetFrameCount; }
   jvmtiError result()    { return _result; }
-  void doit() {
-    _result = JVMTI_ERROR_THREAD_NOT_ALIVE;
-    JavaThread* jt = _state->get_thread();
-    if (Threads::includes(jt) && !jt->is_exiting() && jt->threadObj() != NULL) {
-      _result = ((JvmtiEnvBase*)_env)->get_frame_count(_state, _count_ptr);
-    }
-  }
+  void doit();
 };
 
 // VM operation to frame location at safepoint.
@@ -637,14 +587,7 @@
   }
   VMOp_Type type() const { return VMOp_GetFrameLocation; }
   jvmtiError result()    { return _result; }
-  void doit() {
-    _result = JVMTI_ERROR_THREAD_NOT_ALIVE;
-    if (Threads::includes(_java_thread) && !_java_thread->is_exiting() &&
-        _java_thread->threadObj() != NULL) {
-      _result = ((JvmtiEnvBase*)_env)->get_frame_location(_java_thread, _depth,
-                                                          _method_ptr, _location_ptr);
-    }
-  }
+  void doit();
 };
 
 
--- a/src/hotspot/share/prims/jvmtiEnvThreadState.cpp	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/hotspot/share/prims/jvmtiEnvThreadState.cpp	Mon Nov 27 17:04:45 2017 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2017, 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
@@ -35,6 +35,7 @@
 #include "runtime/interfaceSupport.hpp"
 #include "runtime/javaCalls.hpp"
 #include "runtime/signature.hpp"
+#include "runtime/thread.inline.hpp"
 #include "runtime/vframe.hpp"
 #include "runtime/vm_operations.hpp"
 
--- a/src/hotspot/share/prims/jvmtiEventController.cpp	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/hotspot/share/prims/jvmtiEventController.cpp	Mon Nov 27 17:04:45 2017 +0000
@@ -33,7 +33,8 @@
 #include "prims/jvmtiImpl.hpp"
 #include "prims/jvmtiThreadState.inline.hpp"
 #include "runtime/frame.hpp"
-#include "runtime/thread.hpp"
+#include "runtime/thread.inline.hpp"
+#include "runtime/threadSMR.hpp"
 #include "runtime/vframe.hpp"
 #include "runtime/vframe_hp.hpp"
 #include "runtime/vmThread.hpp"
@@ -580,13 +581,10 @@
   // filtered events and there weren't last time
   if (    (any_env_thread_enabled & THREAD_FILTERED_EVENT_BITS) != 0 &&
       (was_any_env_thread_enabled & THREAD_FILTERED_EVENT_BITS) == 0) {
-    {
-      MutexLocker mu(Threads_lock);   //hold the Threads_lock for the iteration
-      for (JavaThread *tp = Threads::first(); tp != NULL; tp = tp->next()) {
-        // state_for_while_locked() makes tp->is_exiting() check
-        JvmtiThreadState::state_for_while_locked(tp);  // create the thread state if missing
-      }
-    }// release Threads_lock
+    for (JavaThreadIteratorWithHandle jtiwh; JavaThread *tp = jtiwh.next(); ) {
+      // state_for_while_locked() makes tp->is_exiting() check
+      JvmtiThreadState::state_for_while_locked(tp);  // create the thread state if missing
+    }
   }
 
   // compute and set thread-filtered events
--- a/src/hotspot/share/prims/jvmtiExport.cpp	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/hotspot/share/prims/jvmtiExport.cpp	Mon Nov 27 17:04:45 2017 +0000
@@ -53,6 +53,7 @@
 #include "runtime/objectMonitor.inline.hpp"
 #include "runtime/os.inline.hpp"
 #include "runtime/thread.inline.hpp"
+#include "runtime/threadSMR.hpp"
 #include "runtime/vframe.hpp"
 #include "services/serviceUtil.hpp"
 #include "utilities/macros.hpp"
@@ -721,6 +722,108 @@
   }
 }
 
+// Convert an external thread reference to a JavaThread found on the
+// specified ThreadsList. The ThreadsListHandle in the caller "protects"
+// the returned JavaThread *.
+//
+// If thread_oop_p is not NULL, then the caller wants to use the oop
+// after this call so the oop is returned. On success, *jt_pp is set
+// to the converted JavaThread * and JVMTI_ERROR_NONE is returned.
+// On error, returns various JVMTI_ERROR_* values.
+//
+jvmtiError
+JvmtiExport::cv_external_thread_to_JavaThread(ThreadsList * t_list,
+                                              jthread thread,
+                                              JavaThread ** jt_pp,
+                                              oop * thread_oop_p) {
+  assert(t_list != NULL, "must have a ThreadsList");
+  assert(jt_pp != NULL, "must have a return JavaThread pointer");
+  // thread_oop_p is optional so no assert()
+
+  oop thread_oop = JNIHandles::resolve_external_guard(thread);
+  if (thread_oop == NULL) {
+    // NULL jthread, GC'ed jthread or a bad JNI handle.
+    return JVMTI_ERROR_INVALID_THREAD;
+  }
+  // Looks like an oop at this point.
+
+  if (!thread_oop->is_a(SystemDictionary::Thread_klass())) {
+    // The oop is not a java.lang.Thread.
+    return JVMTI_ERROR_INVALID_THREAD;
+  }
+  // Looks like a java.lang.Thread oop at this point.
+
+  if (thread_oop_p != NULL) {
+    // Return the oop to the caller; the caller may still want
+    // the oop even if this function returns an error.
+    *thread_oop_p = thread_oop;
+  }
+
+  JavaThread * java_thread = java_lang_Thread::thread(thread_oop);
+  if (java_thread == NULL) {
+    // The java.lang.Thread does not contain a JavaThread * so it has
+    // not yet run or it has died.
+    return JVMTI_ERROR_THREAD_NOT_ALIVE;
+  }
+  // Looks like a live JavaThread at this point.
+
+  // We do not check the EnableThreadSMRExtraValidityChecks option
+  // for this includes() call because JVM/TI's spec is tighter.
+  if (!t_list->includes(java_thread)) {
+    // Not on the JavaThreads list so it is not alive.
+    return JVMTI_ERROR_THREAD_NOT_ALIVE;
+  }
+
+  // Return a live JavaThread that is "protected" by the
+  // ThreadsListHandle in the caller.
+  *jt_pp = java_thread;
+
+  return JVMTI_ERROR_NONE;
+}
+
+// Convert an oop to a JavaThread found on the specified ThreadsList.
+// The ThreadsListHandle in the caller "protects" the returned
+// JavaThread *.
+//
+// On success, *jt_pp is set to the converted JavaThread * and
+// JVMTI_ERROR_NONE is returned. On error, returns various
+// JVMTI_ERROR_* values.
+//
+jvmtiError
+JvmtiExport::cv_oop_to_JavaThread(ThreadsList * t_list, oop thread_oop,
+                                  JavaThread ** jt_pp) {
+  assert(t_list != NULL, "must have a ThreadsList");
+  assert(thread_oop != NULL, "must have an oop");
+  assert(jt_pp != NULL, "must have a return JavaThread pointer");
+
+  if (!thread_oop->is_a(SystemDictionary::Thread_klass())) {
+    // The oop is not a java.lang.Thread.
+    return JVMTI_ERROR_INVALID_THREAD;
+  }
+  // Looks like a java.lang.Thread oop at this point.
+
+  JavaThread * java_thread = java_lang_Thread::thread(thread_oop);
+  if (java_thread == NULL) {
+    // The java.lang.Thread does not contain a JavaThread * so it has
+    // not yet run or it has died.
+    return JVMTI_ERROR_THREAD_NOT_ALIVE;
+  }
+  // Looks like a live JavaThread at this point.
+
+  // We do not check the EnableThreadSMRExtraValidityChecks option
+  // for this includes() call because JVM/TI's spec is tighter.
+  if (!t_list->includes(java_thread)) {
+    // Not on the JavaThreads list so it is not alive.
+    return JVMTI_ERROR_THREAD_NOT_ALIVE;
+  }
+
+  // Return a live JavaThread that is "protected" by the
+  // ThreadsListHandle in the caller.
+  *jt_pp = java_thread;
+
+  return JVMTI_ERROR_NONE;
+}
+
 class JvmtiClassFileLoadHookPoster : public StackObj {
  private:
   Symbol*            _h_name;
@@ -2685,8 +2788,7 @@
     return;
   }
 
-  // Runs at safepoint. So no need to acquire Threads_lock.
-  for (JavaThread *jthr = Threads::first(); jthr != NULL; jthr = jthr->next()) {
+  for (JavaThreadIteratorWithHandle jtiwh; JavaThread *jthr = jtiwh.next(); ) {
     JvmtiThreadState *state = jthr->jvmti_thread_state();
     if (state != NULL) {
       JvmtiVMObjectAllocEventCollector *collector;
--- a/src/hotspot/share/prims/jvmtiExport.hpp	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/hotspot/share/prims/jvmtiExport.hpp	Mon Nov 27 17:04:45 2017 +0000
@@ -399,6 +399,14 @@
 
   // SetNativeMethodPrefix support
   static char** get_all_native_method_prefixes(int* count_ptr) NOT_JVMTI_RETURN_(NULL);
+
+  // JavaThread lifecycle support:
+  static jvmtiError cv_external_thread_to_JavaThread(ThreadsList * t_list,
+                                                     jthread thread,
+                                                     JavaThread ** jt_pp,
+                                                     oop * thread_oop_p);
+  static jvmtiError cv_oop_to_JavaThread(ThreadsList * t_list, oop thread_oop,
+                                         JavaThread ** jt_pp);
 };
 
 // Support class used by JvmtiDynamicCodeEventCollector and others. It
--- a/src/hotspot/share/prims/jvmtiImpl.cpp	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/hotspot/share/prims/jvmtiImpl.cpp	Mon Nov 27 17:04:45 2017 +0000
@@ -46,6 +46,7 @@
 #include "runtime/serviceThread.hpp"
 #include "runtime/signature.hpp"
 #include "runtime/thread.inline.hpp"
+#include "runtime/threadSMR.hpp"
 #include "runtime/vframe.hpp"
 #include "runtime/vframe_hp.hpp"
 #include "runtime/vm_operations.hpp"
@@ -878,10 +879,9 @@
 
 void JvmtiSuspendControl::print() {
 #ifndef PRODUCT
-  MutexLocker mu(Threads_lock);
   LogStreamHandle(Trace, jvmti) log_stream;
   log_stream.print("Suspended Threads: [");
-  for (JavaThread *thread = Threads::first(); thread != NULL; thread = thread->next()) {
+  for (JavaThreadIteratorWithHandle jtiwh; JavaThread *thread = jtiwh.next(); ) {
 #ifdef JVMTI_TRACE
     const char *name   = JvmtiTrace::safe_get_thread_name(thread);
 #else
--- a/src/hotspot/share/prims/jvmtiRedefineClasses.cpp	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/hotspot/share/prims/jvmtiRedefineClasses.cpp	Mon Nov 27 17:04:45 2017 +0000
@@ -43,6 +43,7 @@
 #include "oops/oop.inline.hpp"
 #include "prims/jvmtiImpl.hpp"
 #include "prims/jvmtiRedefineClasses.hpp"
+#include "prims/jvmtiThreadState.inline.hpp"
 #include "prims/resolvedMethodTable.hpp"
 #include "prims/methodComparator.hpp"
 #include "runtime/deoptimization.hpp"
--- a/src/hotspot/share/prims/jvmtiTagMap.cpp	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/hotspot/share/prims/jvmtiTagMap.cpp	Mon Nov 27 17:04:45 2017 +0000
@@ -45,6 +45,8 @@
 #include "runtime/mutex.hpp"
 #include "runtime/mutexLocker.hpp"
 #include "runtime/reflectionUtils.hpp"
+#include "runtime/thread.inline.hpp"
+#include "runtime/threadSMR.hpp"
 #include "runtime/vframe.hpp"
 #include "runtime/vmThread.hpp"
 #include "runtime/vm_operations.hpp"
@@ -3174,7 +3176,7 @@
 // stack to find all references and local JNI refs.
 inline bool VM_HeapWalkOperation::collect_stack_roots() {
   JNILocalRootsClosure blk;
-  for (JavaThread* thread = Threads::first(); thread != NULL ; thread = thread->next()) {
+  for (JavaThreadIteratorWithHandle jtiwh; JavaThread *thread = jtiwh.next(); ) {
     oop threadObj = thread->threadObj();
     if (threadObj != NULL && !thread->is_exiting() && !thread->is_hidden_from_external_view()) {
       // Collect the simple root for this thread before we
--- a/src/hotspot/share/prims/jvmtiThreadState.hpp	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/hotspot/share/prims/jvmtiThreadState.hpp	Mon Nov 27 17:04:45 2017 +0000
@@ -336,34 +336,10 @@
 
   // already holding JvmtiThreadState_lock - retrieve or create JvmtiThreadState
   // Can return NULL if JavaThread is exiting.
-  inline static JvmtiThreadState *state_for_while_locked(JavaThread *thread) {
-    assert(JvmtiThreadState_lock->is_locked(), "sanity check");
-
-    JvmtiThreadState *state = thread->jvmti_thread_state();
-    if (state == NULL) {
-      if (thread->is_exiting()) {
-        // don't add a JvmtiThreadState to a thread that is exiting
-        return NULL;
-      }
-
-      state = new JvmtiThreadState(thread);
-    }
-    return state;
-  }
-
+  static JvmtiThreadState *state_for_while_locked(JavaThread *thread);
   // retrieve or create JvmtiThreadState
   // Can return NULL if JavaThread is exiting.
-  inline static JvmtiThreadState *state_for(JavaThread *thread) {
-    JvmtiThreadState *state = thread->jvmti_thread_state();
-    if (state == NULL) {
-      MutexLocker mu(JvmtiThreadState_lock);
-      // check again with the lock held
-      state = state_for_while_locked(thread);
-    } else {
-      CHECK_UNHANDLED_OOPS_ONLY(Thread::current()->clear_unhandled_oops());
-    }
-    return state;
-  }
+  static JvmtiThreadState *state_for(JavaThread *thread);
 
   // JVMTI ForceEarlyReturn support
 
--- a/src/hotspot/share/prims/jvmtiThreadState.inline.hpp	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/hotspot/share/prims/jvmtiThreadState.inline.hpp	Mon Nov 27 17:04:45 2017 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2017, 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
@@ -68,4 +68,31 @@
   _head_env_thread_state = ets;
 }
 
+inline JvmtiThreadState* JvmtiThreadState::state_for_while_locked(JavaThread *thread) {
+  assert(JvmtiThreadState_lock->is_locked(), "sanity check");
+
+  JvmtiThreadState *state = thread->jvmti_thread_state();
+  if (state == NULL) {
+    if (thread->is_exiting()) {
+      // don't add a JvmtiThreadState to a thread that is exiting
+      return NULL;
+    }
+
+    state = new JvmtiThreadState(thread);
+  }
+  return state;
+}
+
+inline JvmtiThreadState* JvmtiThreadState::state_for(JavaThread *thread) {
+  JvmtiThreadState *state = thread->jvmti_thread_state();
+  if (state == NULL) {
+    MutexLocker mu(JvmtiThreadState_lock);
+    // check again with the lock held
+    state = state_for_while_locked(thread);
+  } else {
+    CHECK_UNHANDLED_OOPS_ONLY(Thread::current()->clear_unhandled_oops());
+  }
+  return state;
+}
+
 #endif // SHARE_VM_PRIMS_JVMTITHREADSTATE_INLINE_HPP
--- a/src/hotspot/share/prims/perf.cpp	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/hotspot/share/prims/perf.cpp	Mon Nov 27 17:04:45 2017 +0000
@@ -30,7 +30,7 @@
 #include "memory/resourceArea.hpp"
 #include "oops/oop.inline.hpp"
 #include "runtime/interfaceSupport.hpp"
-#include "runtime/perfData.hpp"
+#include "runtime/perfData.inline.hpp"
 #include "runtime/perfMemory.hpp"
 
 /*
--- a/src/hotspot/share/prims/unsafe.cpp	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/hotspot/share/prims/unsafe.cpp	Mon Nov 27 17:04:45 2017 +0000
@@ -39,6 +39,8 @@
 #include "runtime/interfaceSupport.hpp"
 #include "runtime/orderAccess.inline.hpp"
 #include "runtime/reflection.hpp"
+#include "runtime/thread.hpp"
+#include "runtime/threadSMR.hpp"
 #include "runtime/vm_version.hpp"
 #include "services/threadService.hpp"
 #include "trace/tracing.hpp"
@@ -937,8 +939,12 @@
   Parker* p = NULL;
 
   if (jthread != NULL) {
-    oop java_thread = JNIHandles::resolve_non_null(jthread);
+    ThreadsListHandle tlh;
+    JavaThread* thr = NULL;
+    oop java_thread = NULL;
+    (void) tlh.cv_internal_thread_to_JavaThread(jthread, &thr, &java_thread);
     if (java_thread != NULL) {
+      // This is a valid oop.
       jlong lp = java_lang_Thread::park_event(java_thread);
       if (lp != 0) {
         // This cast is OK even though the jlong might have been read
@@ -946,22 +952,19 @@
         // always be zero anyway and the value set is always the same
         p = (Parker*)addr_from_java(lp);
       } else {
-        // Grab lock if apparently null or using older version of library
-        MutexLocker mu(Threads_lock);
-        java_thread = JNIHandles::resolve_non_null(jthread);
-
-        if (java_thread != NULL) {
-          JavaThread* thr = java_lang_Thread::thread(java_thread);
-          if (thr != NULL) {
-            p = thr->parker();
-            if (p != NULL) { // Bind to Java thread for next time.
-              java_lang_Thread::set_park_event(java_thread, addr_to_java(p));
-            }
+        // Not cached in the java.lang.Thread oop yet (could be an
+        // older version of library).
+        if (thr != NULL) {
+          // The JavaThread is alive.
+          p = thr->parker();
+          if (p != NULL) {
+            // Cache the Parker in the java.lang.Thread oop for next time.
+            java_lang_Thread::set_park_event(java_thread, addr_to_java(p));
           }
         }
       }
     }
-  }
+  } // ThreadsListHandle is destroyed here.
 
   if (p != NULL) {
     HOTSPOT_THREAD_UNPARK((uintptr_t) p);
--- a/src/hotspot/share/prims/whitebox.cpp	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/hotspot/share/prims/whitebox.cpp	Mon Nov 27 17:04:45 2017 +0000
@@ -55,6 +55,7 @@
 #include "runtime/os.hpp"
 #include "runtime/sweeper.hpp"
 #include "runtime/thread.hpp"
+#include "runtime/threadSMR.hpp"
 #include "runtime/vm_version.hpp"
 #include "utilities/align.hpp"
 #include "utilities/debug.hpp"
@@ -665,7 +666,7 @@
   int  result() const { return _result; }
 
   void doit() {
-    for (JavaThread* t = Threads::first(); t != NULL; t = t->next()) {
+    for (JavaThreadIteratorWithHandle jtiwh; JavaThread *t = jtiwh.next(); ) {
       if (t->has_last_Java_frame()) {
         for (StackFrameStream fst(t, UseBiasedLocking); !fst.is_done(); fst.next()) {
           frame* f = fst.current();
--- a/src/hotspot/share/runtime/arguments.cpp	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/hotspot/share/runtime/arguments.cpp	Mon Nov 27 17:04:45 2017 +0000
@@ -497,7 +497,7 @@
   SpecialFlag flag;
   if (lookup_special_flag(flag_name, flag)) {
     if (!flag.obsolete_in.is_undefined()) {
-      if (version_less_than(JDK_Version::current(), flag.expired_in)) {
+      if (!version_less_than(JDK_Version::current(), flag.obsolete_in)) {
         *version = flag.obsolete_in;
         return true;
       }
@@ -2152,12 +2152,7 @@
   // Check lower bounds of the code cache
   // Template Interpreter code is approximately 3X larger in debug builds.
   uint min_code_cache_size = CodeCacheMinimumUseSpace DEBUG_ONLY(* 3);
-  if (InitialCodeCacheSize < (uintx)os::vm_page_size()) {
-    jio_fprintf(defaultStream::error_stream(),
-                "Invalid InitialCodeCacheSize=%dK. Must be at least %dK.\n", InitialCodeCacheSize/K,
-                os::vm_page_size()/K);
-    status = false;
-  } else if (ReservedCodeCacheSize < InitialCodeCacheSize) {
+  if (ReservedCodeCacheSize < InitialCodeCacheSize) {
     jio_fprintf(defaultStream::error_stream(),
                 "Invalid ReservedCodeCacheSize: %dK. Must be at least InitialCodeCacheSize=%dK.\n",
                 ReservedCodeCacheSize/K, InitialCodeCacheSize/K);
@@ -2770,18 +2765,6 @@
       if (FLAG_SET_CMDLINE(intx, ThreadStackSize, value) != Flag::SUCCESS) {
         return JNI_EINVAL;
       }
-    } else if (match_option(option, "-XX:CodeCacheExpansionSize=", &tail)) {
-      julong long_CodeCacheExpansionSize = 0;
-      ArgsRange errcode = parse_memory_size(tail, &long_CodeCacheExpansionSize, os::vm_page_size());
-      if (errcode != arg_in_range) {
-        jio_fprintf(defaultStream::error_stream(),
-                   "Invalid argument: %s. Must be at least %luK.\n", option->optionString,
-                   os::vm_page_size()/K);
-        return JNI_EINVAL;
-      }
-      if (FLAG_SET_CMDLINE(uintx, CodeCacheExpansionSize, (uintx)long_CodeCacheExpansionSize) != Flag::SUCCESS) {
-        return JNI_EINVAL;
-      }
     } else if (match_option(option, "-Xmaxjitcodesize", &tail) ||
                match_option(option, "-XX:ReservedCodeCacheSize=", &tail)) {
       julong long_ReservedCodeCacheSize = 0;
@@ -2795,45 +2778,6 @@
       if (FLAG_SET_CMDLINE(uintx, ReservedCodeCacheSize, (uintx)long_ReservedCodeCacheSize) != Flag::SUCCESS) {
         return JNI_EINVAL;
       }
-      // -XX:NonNMethodCodeHeapSize=
-    } else if (match_option(option, "-XX:NonNMethodCodeHeapSize=", &tail)) {
-      julong long_NonNMethodCodeHeapSize = 0;
-
-      ArgsRange errcode = parse_memory_size(tail, &long_NonNMethodCodeHeapSize, 1);
-      if (errcode != arg_in_range) {
-        jio_fprintf(defaultStream::error_stream(),
-                    "Invalid maximum non-nmethod code heap size: %s.\n", option->optionString);
-        return JNI_EINVAL;
-      }
-      if (FLAG_SET_CMDLINE(uintx, NonNMethodCodeHeapSize, (uintx)long_NonNMethodCodeHeapSize) != Flag::SUCCESS) {
-        return JNI_EINVAL;
-      }
-      // -XX:ProfiledCodeHeapSize=
-    } else if (match_option(option, "-XX:ProfiledCodeHeapSize=", &tail)) {
-      julong long_ProfiledCodeHeapSize = 0;
-
-      ArgsRange errcode = parse_memory_size(tail, &long_ProfiledCodeHeapSize, 1);
-      if (errcode != arg_in_range) {
-        jio_fprintf(defaultStream::error_stream(),
-                    "Invalid maximum profiled code heap size: %s.\n", option->optionString);
-        return JNI_EINVAL;
-      }
-      if (FLAG_SET_CMDLINE(uintx, ProfiledCodeHeapSize, (uintx)long_ProfiledCodeHeapSize) != Flag::SUCCESS) {
-        return JNI_EINVAL;
-      }
-      // -XX:NonProfiledCodeHeapSizee=
-    } else if (match_option(option, "-XX:NonProfiledCodeHeapSize=", &tail)) {
-      julong long_NonProfiledCodeHeapSize = 0;
-
-      ArgsRange errcode = parse_memory_size(tail, &long_NonProfiledCodeHeapSize, 1);
-      if (errcode != arg_in_range) {
-        jio_fprintf(defaultStream::error_stream(),
-                    "Invalid maximum non-profiled code heap size: %s.\n", option->optionString);
-        return JNI_EINVAL;
-      }
-      if (FLAG_SET_CMDLINE(uintx, NonProfiledCodeHeapSize, (uintx)long_NonProfiledCodeHeapSize) != Flag::SUCCESS) {
-        return JNI_EINVAL;
-      }
     // -green
     } else if (match_option(option, "-green")) {
       jio_fprintf(defaultStream::error_stream(),
--- a/src/hotspot/share/runtime/arguments.hpp	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/hotspot/share/runtime/arguments.hpp	Mon Nov 27 17:04:45 2017 +0000
@@ -27,6 +27,7 @@
 
 #include "logging/logLevel.hpp"
 #include "logging/logTag.hpp"
+#include "memory/allocation.inline.hpp"
 #include "runtime/java.hpp"
 #include "runtime/os.hpp"
 #include "runtime/perfData.hpp"
--- a/src/hotspot/share/runtime/biasedLocking.cpp	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/hotspot/share/runtime/biasedLocking.cpp	Mon Nov 27 17:04:45 2017 +0000
@@ -32,6 +32,7 @@
 #include "runtime/basicLock.hpp"
 #include "runtime/biasedLocking.hpp"
 #include "runtime/task.hpp"
+#include "runtime/threadSMR.hpp"
 #include "runtime/vframe.hpp"
 #include "runtime/vmThread.hpp"
 #include "runtime/vm_operations.hpp"
@@ -214,12 +215,8 @@
   if (requesting_thread == biased_thread) {
     thread_is_alive = true;
   } else {
-    for (JavaThread* cur_thread = Threads::first(); cur_thread != NULL; cur_thread = cur_thread->next()) {
-      if (cur_thread == biased_thread) {
-        thread_is_alive = true;
-        break;
-      }
-    }
+    ThreadsListHandle tlh;
+    thread_is_alive = tlh.includes(biased_thread);
   }
   if (!thread_is_alive) {
     if (allow_rebias) {
@@ -390,72 +387,76 @@
   Klass* k_o = o->klass();
   Klass* klass = k_o;
 
-  if (bulk_rebias) {
-    // Use the epoch in the klass of the object to implicitly revoke
-    // all biases of objects of this data type and force them to be
-    // reacquired. However, we also need to walk the stacks of all
-    // threads and update the headers of lightweight locked objects
-    // with biases to have the current epoch.
+  {
+    JavaThreadIteratorWithHandle jtiwh;
+
+    if (bulk_rebias) {
+      // Use the epoch in the klass of the object to implicitly revoke
+      // all biases of objects of this data type and force them to be
+      // reacquired. However, we also need to walk the stacks of all
+      // threads and update the headers of lightweight locked objects
+      // with biases to have the current epoch.
+
+      // If the prototype header doesn't have the bias pattern, don't
+      // try to update the epoch -- assume another VM operation came in
+      // and reset the header to the unbiased state, which will
+      // implicitly cause all existing biases to be revoked
+      if (klass->prototype_header()->has_bias_pattern()) {
+        int prev_epoch = klass->prototype_header()->bias_epoch();
+        klass->set_prototype_header(klass->prototype_header()->incr_bias_epoch());
+        int cur_epoch = klass->prototype_header()->bias_epoch();
 
-    // If the prototype header doesn't have the bias pattern, don't
-    // try to update the epoch -- assume another VM operation came in
-    // and reset the header to the unbiased state, which will
-    // implicitly cause all existing biases to be revoked
-    if (klass->prototype_header()->has_bias_pattern()) {
-      int prev_epoch = klass->prototype_header()->bias_epoch();
-      klass->set_prototype_header(klass->prototype_header()->incr_bias_epoch());
-      int cur_epoch = klass->prototype_header()->bias_epoch();
+        // Now walk all threads' stacks and adjust epochs of any biased
+        // and locked objects of this data type we encounter
+        for (; JavaThread *thr = jtiwh.next(); ) {
+          GrowableArray<MonitorInfo*>* cached_monitor_info = get_or_compute_monitor_info(thr);
+          for (int i = 0; i < cached_monitor_info->length(); i++) {
+            MonitorInfo* mon_info = cached_monitor_info->at(i);
+            oop owner = mon_info->owner();
+            markOop mark = owner->mark();
+            if ((owner->klass() == k_o) && mark->has_bias_pattern()) {
+              // We might have encountered this object already in the case of recursive locking
+              assert(mark->bias_epoch() == prev_epoch || mark->bias_epoch() == cur_epoch, "error in bias epoch adjustment");
+              owner->set_mark(mark->set_bias_epoch(cur_epoch));
+            }
+          }
+        }
+      }
 
-      // Now walk all threads' stacks and adjust epochs of any biased
-      // and locked objects of this data type we encounter
-      for (JavaThread* thr = Threads::first(); thr != NULL; thr = thr->next()) {
+      // At this point we're done. All we have to do is potentially
+      // adjust the header of the given object to revoke its bias.
+      revoke_bias(o, attempt_rebias_of_object && klass->prototype_header()->has_bias_pattern(), true, requesting_thread, NULL);
+    } else {
+      if (log_is_enabled(Info, biasedlocking)) {
+        ResourceMark rm;
+        log_info(biasedlocking)("* Disabling biased locking for type %s", klass->external_name());
+      }
+
+      // Disable biased locking for this data type. Not only will this
+      // cause future instances to not be biased, but existing biased
+      // instances will notice that this implicitly caused their biases
+      // to be revoked.
+      klass->set_prototype_header(markOopDesc::prototype());
+
+      // Now walk all threads' stacks and forcibly revoke the biases of
+      // any locked and biased objects of this data type we encounter.
+      for (; JavaThread *thr = jtiwh.next(); ) {
         GrowableArray<MonitorInfo*>* cached_monitor_info = get_or_compute_monitor_info(thr);
         for (int i = 0; i < cached_monitor_info->length(); i++) {
           MonitorInfo* mon_info = cached_monitor_info->at(i);
           oop owner = mon_info->owner();
           markOop mark = owner->mark();
           if ((owner->klass() == k_o) && mark->has_bias_pattern()) {
-            // We might have encountered this object already in the case of recursive locking
-            assert(mark->bias_epoch() == prev_epoch || mark->bias_epoch() == cur_epoch, "error in bias epoch adjustment");
-            owner->set_mark(mark->set_bias_epoch(cur_epoch));
+            revoke_bias(owner, false, true, requesting_thread, NULL);
           }
         }
       }
-    }
 
-    // At this point we're done. All we have to do is potentially
-    // adjust the header of the given object to revoke its bias.
-    revoke_bias(o, attempt_rebias_of_object && klass->prototype_header()->has_bias_pattern(), true, requesting_thread, NULL);
-  } else {
-    if (log_is_enabled(Info, biasedlocking)) {
-      ResourceMark rm;
-      log_info(biasedlocking)("* Disabling biased locking for type %s", klass->external_name());
+      // Must force the bias of the passed object to be forcibly revoked
+      // as well to ensure guarantees to callers
+      revoke_bias(o, false, true, requesting_thread, NULL);
     }
-
-    // Disable biased locking for this data type. Not only will this
-    // cause future instances to not be biased, but existing biased
-    // instances will notice that this implicitly caused their biases
-    // to be revoked.
-    klass->set_prototype_header(markOopDesc::prototype());
-
-    // Now walk all threads' stacks and forcibly revoke the biases of
-    // any locked and biased objects of this data type we encounter.
-    for (JavaThread* thr = Threads::first(); thr != NULL; thr = thr->next()) {
-      GrowableArray<MonitorInfo*>* cached_monitor_info = get_or_compute_monitor_info(thr);
-      for (int i = 0; i < cached_monitor_info->length(); i++) {
-        MonitorInfo* mon_info = cached_monitor_info->at(i);
-        oop owner = mon_info->owner();
-        markOop mark = owner->mark();
-        if ((owner->klass() == k_o) && mark->has_bias_pattern()) {
-          revoke_bias(owner, false, true, requesting_thread, NULL);
-        }
-      }
-    }
-
-    // Must force the bias of the passed object to be forcibly revoked
-    // as well to ensure guarantees to callers
-    revoke_bias(o, false, true, requesting_thread, NULL);
-  }
+  } // ThreadsListHandle is destroyed here.
 
   log_info(biasedlocking)("* Ending bulk revocation");
 
@@ -481,7 +482,7 @@
 
 static void clean_up_cached_monitor_info() {
   // Walk the thread list clearing out the cached monitors
-  for (JavaThread* thr = Threads::first(); thr != NULL; thr = thr->next()) {
+  for (JavaThreadIteratorWithHandle jtiwh; JavaThread *thr = jtiwh.next(); ) {
     thr->set_cached_monitor_info(NULL);
   }
 }
@@ -768,7 +769,7 @@
 
   ResourceMark rm;
   Thread* cur = Thread::current();
-  for (JavaThread* thread = Threads::first(); thread != NULL; thread = thread->next()) {
+  for (JavaThreadIteratorWithHandle jtiwh; JavaThread *thread = jtiwh.next(); ) {
     if (thread->has_last_Java_frame()) {
       RegisterMap rm(thread);
       for (javaVFrame* vf = thread->last_java_vframe(&rm); vf != NULL; vf = vf->java_sender()) {
--- a/src/hotspot/share/runtime/deoptimization.cpp	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/hotspot/share/runtime/deoptimization.cpp	Mon Nov 27 17:04:45 2017 +0000
@@ -50,6 +50,7 @@
 #include "runtime/signature.hpp"
 #include "runtime/stubRoutines.hpp"
 #include "runtime/thread.hpp"
+#include "runtime/threadSMR.hpp"
 #include "runtime/vframe.hpp"
 #include "runtime/vframeArray.hpp"
 #include "runtime/vframe_hp.hpp"
@@ -1297,7 +1298,7 @@
 
   assert(SafepointSynchronize::is_at_safepoint(), "must only be called from safepoint");
   GrowableArray<Handle>* objects_to_revoke = new GrowableArray<Handle>();
-  for (JavaThread* jt = Threads::first(); jt != NULL ; jt = jt->next()) {
+  for (JavaThreadIteratorWithHandle jtiwh; JavaThread *jt = jtiwh.next(); ) {
     if (jt->has_last_Java_frame()) {
       StackFrameStream sfs(jt, true);
       while (!sfs.is_done()) {
--- a/src/hotspot/share/runtime/globals.hpp	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/hotspot/share/runtime/globals.hpp	Mon Nov 27 17:04:45 2017 +0000
@@ -2484,6 +2484,12 @@
   LP64_ONLY(range(-1, max_intx/MICROUNITS))                                 \
   NOT_LP64(range(-1, max_intx))                                             \
                                                                             \
+  diagnostic(bool, EnableThreadSMRExtraValidityChecks, true,                \
+             "Enable Thread SMR extra validity checks")                     \
+                                                                            \
+  diagnostic(bool, EnableThreadSMRStatistics, true,                         \
+             "Enable Thread SMR Statistics")                                \
+                                                                            \
   product(bool, Inline, true,                                               \
           "Enable inlining")                                                \
                                                                             \
@@ -3359,7 +3365,7 @@
                                                                             \
   product_pd(uintx, InitialCodeCacheSize,                                   \
           "Initial code cache size (in bytes)")                             \
-          range(0, max_uintx)                                               \
+          range(os::vm_page_size(), max_uintx)                              \
                                                                             \
   develop_pd(uintx, CodeCacheMinimumUseSpace,                               \
           "Minimum code cache size (in bytes) required to start VM.")       \
@@ -3370,7 +3376,7 @@
                                                                             \
   product_pd(uintx, ReservedCodeCacheSize,                                  \
           "Reserved code cache size (in bytes) - maximum code cache size")  \
-          range(0, max_uintx)                                               \
+          range(os::vm_page_size(), max_uintx)                              \
                                                                             \
   product_pd(uintx, NonProfiledCodeHeapSize,                                \
           "Size of code heap with non-profiled methods (in bytes)")         \
@@ -3382,11 +3388,11 @@
                                                                             \
   product_pd(uintx, NonNMethodCodeHeapSize,                                 \
           "Size of code heap with non-nmethods (in bytes)")                 \
-          range(0, max_uintx)                                               \
+          range(os::vm_page_size(), max_uintx)                              \
                                                                             \
   product_pd(uintx, CodeCacheExpansionSize,                                 \
           "Code cache expansion size (in bytes)")                           \
-          range(0, max_uintx)                                               \
+          range(os::vm_page_size(), max_uintx)                              \
                                                                             \
   diagnostic_pd(uintx, CodeCacheMinBlockLength,                             \
           "Minimum number of segments in a code cache block")               \
--- a/src/hotspot/share/runtime/handshake.cpp	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/hotspot/share/runtime/handshake.cpp	Mon Nov 27 17:04:45 2017 +0000
@@ -37,8 +37,6 @@
 #include "utilities/formatBuffer.hpp"
 #include "utilities/preserveException.hpp"
 
-#define ALL_JAVA_THREADS(X) for (JavaThread* X = Threads::first(); X; X = X->next())
-
 class HandshakeOperation: public StackObj {
 public:
   virtual void do_handshake(JavaThread* thread) = 0;
@@ -94,8 +92,7 @@
 
 void VM_Handshake::handle_timeout() {
   LogStreamHandle(Warning, handshake) log_stream;
-  MutexLockerEx ml(Threads_lock, Mutex::_no_safepoint_check_flag);
-  ALL_JAVA_THREADS(thr) {
+  for (JavaThreadIteratorWithHandle jtiwh; JavaThread *thr = jtiwh.next(); ) {
     if (thr->has_handshake()) {
       log_stream.print("Thread " PTR_FORMAT " has not cleared its handshake op", p2i(thr));
       thr->print_thread_state_on(&log_stream);
@@ -117,8 +114,8 @@
     TraceTime timer("Performing single-target operation (vmoperation doit)", TRACETIME_LOG(Info, handshake));
 
     {
-      MutexLockerEx ml(Threads_lock, Mutex::_no_safepoint_check_flag);
-      if (Threads::includes(_target)) {
+      ThreadsListHandle tlh;
+      if (tlh.includes(_target)) {
         set_handshake(_target);
         _thread_alive = true;
       }
@@ -139,9 +136,24 @@
         handle_timeout();
       }
 
+      // We need to re-think this with SMR ThreadsList.
+      // There is an assumption in the code that the Threads_lock should be
+      // locked during certain phases.
       MutexLockerEx ml(Threads_lock, Mutex::_no_safepoint_check_flag);
-      _target->handshake_process_by_vmthread();
-
+      ThreadsListHandle tlh;
+      if (tlh.includes(_target)) {
+        // Warning _target's address might be re-used.
+        // handshake_process_by_vmthread will check the semaphore for us again.
+        // Since we can't have more then one handshake in flight a reuse of
+        // _target's address should be okay since the new thread will not have
+        // an operation.
+        _target->handshake_process_by_vmthread();
+      } else {
+        // We can't warn here since the thread does cancel_handshake after
+        // it has been removed from the ThreadsList. So we should just keep
+        // looping here until while below returns false. If we have a bug,
+        // then we hang here, which is good for debugging.
+      }
     } while (!poll_for_completed_thread());
   }
 
@@ -157,15 +169,15 @@
   void doit() {
     TraceTime timer("Performing operation (vmoperation doit)", TRACETIME_LOG(Info, handshake));
 
-    int number_of_threads_issued = -1;
-    int number_of_threads_completed = 0;
-    {
-      MutexLockerEx ml(Threads_lock, Mutex::_no_safepoint_check_flag);
-      number_of_threads_issued = Threads::number_of_threads();
+    int number_of_threads_issued = 0;
+    for (JavaThreadIteratorWithHandle jtiwh; JavaThread *thr = jtiwh.next(); ) {
+      set_handshake(thr);
+      number_of_threads_issued++;
+    }
 
-      ALL_JAVA_THREADS(thr) {
-        set_handshake(thr);
-      }
+    if (number_of_threads_issued < 1) {
+      log_debug(handshake)("No threads to handshake.");
+      return;
     }
 
     if (!UseMembar) {
@@ -174,6 +186,7 @@
 
     log_debug(handshake)("Threads signaled, begin processing blocked threads by VMThtread");
     const jlong start_time = os::elapsed_counter();
+    int number_of_threads_completed = 0;
     do {
       // Check if handshake operation has timed out
       if (handshake_has_timed_out(start_time)) {
@@ -184,13 +197,19 @@
       // Observing a blocked state may of course be transient but the processing is guarded
       // by semaphores and we optimistically begin by working on the blocked threads
       {
+          // We need to re-think this with SMR ThreadsList.
+          // There is an assumption in the code that the Threads_lock should
+          // be locked during certain phases.
           MutexLockerEx ml(Threads_lock, Mutex::_no_safepoint_check_flag);
-          ALL_JAVA_THREADS(thr) {
+          for (JavaThreadIteratorWithHandle jtiwh; JavaThread *thr = jtiwh.next(); ) {
+            // A new thread on the ThreadsList will not have an operation,
+            // hence it is skipped in handshake_process_by_vmthread.
             thr->handshake_process_by_vmthread();
           }
       }
 
       while (poll_for_completed_thread()) {
+        // Includes canceled operations by exiting threads.
         number_of_threads_completed++;
       }
 
@@ -212,7 +231,7 @@
       _thread_cl(cl), _target_thread(target), _all_threads(false), _thread_alive(false) {}
 
   void doit() {
-    ALL_JAVA_THREADS(t) {
+    for (JavaThreadIteratorWithHandle jtiwh; JavaThread *t = jtiwh.next(); ) {
       if (_all_threads || t == _target_thread) {
         if (t == _target_thread) {
           _thread_alive = true;
@@ -298,8 +317,8 @@
   assert(thread->thread_state() == _thread_in_vm, "must be in vm state");
 #ifdef DEBUG
   {
-    MutexLockerEx ml(Threads_lock,  Mutex::_no_safepoint_check_flag);
-    assert(!Threads::includes(thread), "java thread must not be on threads list");
+    ThreadsListHandle tlh;
+    assert(!tlh.includes(_target), "java thread must not be on threads list");
   }
 #endif
   HandshakeOperation* op = _operation;
--- a/src/hotspot/share/runtime/java.cpp	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/hotspot/share/runtime/java.cpp	Mon Nov 27 17:04:45 2017 +0000
@@ -356,6 +356,8 @@
   if (PrintNMTStatistics) {
     MemTracker::final_report(tty);
   }
+
+  Threads::log_smr_statistics();
 }
 
 #else // PRODUCT MODE STATISTICS
@@ -396,6 +398,8 @@
   if (LogTouchedMethods && PrintTouchedMethodsAtExit) {
     Method::print_touched_methods(tty);
   }
+
+  Threads::log_smr_statistics();
 }
 
 #endif
--- a/src/hotspot/share/runtime/memprofiler.cpp	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/hotspot/share/runtime/memprofiler.cpp	Mon Nov 27 17:04:45 2017 +0000
@@ -36,6 +36,7 @@
 #include "runtime/os.hpp"
 #include "runtime/task.hpp"
 #include "runtime/thread.inline.hpp"
+#include "runtime/threadSMR.hpp"
 #include "runtime/vmThread.hpp"
 
 #ifndef PRODUCT
@@ -51,8 +52,6 @@
 
 
 void MemProfilerTask::task() {
-  // Get thread lock to provide mutual exclusion, and so we can iterate safely over the thread list.
-  MutexLocker mu(Threads_lock);
   MemProfiler::do_trace();
 }
 
@@ -109,20 +108,21 @@
   // Calculate thread local sizes
   size_t handles_memory_usage    = VMThread::vm_thread()->handle_area()->size_in_bytes();
   size_t resource_memory_usage   = VMThread::vm_thread()->resource_area()->size_in_bytes();
-  JavaThread *cur = Threads::first();
-  while (cur != NULL) {
-    handles_memory_usage  += cur->handle_area()->size_in_bytes();
-    resource_memory_usage += cur->resource_area()->size_in_bytes();
-    cur = cur->next();
-  }
+  {
+    JavaThreadIteratorWithHandle jtiwh;
+    for (; JavaThread *cur = jtiwh.next(); ) {
+      handles_memory_usage  += cur->handle_area()->size_in_bytes();
+      resource_memory_usage += cur->resource_area()->size_in_bytes();
+    }
 
-  // Print trace line in log
-  fprintf(_log_fp, "%6.1f,%5d,%5d," UINTX_FORMAT_W(6) "," UINTX_FORMAT_W(6) ",",
-          os::elapsedTime(),
-          Threads::number_of_threads(),
-          InstanceKlass::number_of_instance_classes(),
-          Universe::heap()->used() / K,
-          Universe::heap()->capacity() / K);
+    // Print trace line in log
+    fprintf(_log_fp, "%6.1f,%5d,%5d," UINTX_FORMAT_W(6) "," UINTX_FORMAT_W(6) ",",
+            os::elapsedTime(),
+            jtiwh.length(),
+            InstanceKlass::number_of_instance_classes(),
+            Universe::heap()->used() / K,
+            Universe::heap()->capacity() / K);
+  }
 
   fprintf(_log_fp, UINTX_FORMAT_W(6) ",", CodeCache::capacity() / K);
 
--- a/src/hotspot/share/runtime/objectMonitor.hpp	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/hotspot/share/runtime/objectMonitor.hpp	Mon Nov 27 17:04:45 2017 +0000
@@ -25,6 +25,7 @@
 #ifndef SHARE_VM_RUNTIME_OBJECTMONITOR_HPP
 #define SHARE_VM_RUNTIME_OBJECTMONITOR_HPP
 
+#include "memory/allocation.inline.hpp"
 #include "memory/padded.hpp"
 #include "runtime/os.hpp"
 #include "runtime/park.hpp"
--- a/src/hotspot/share/runtime/os.cpp	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/hotspot/share/runtime/os.cpp	Mon Nov 27 17:04:45 2017 +0000
@@ -54,6 +54,7 @@
 #include "runtime/os.inline.hpp"
 #include "runtime/stubRoutines.hpp"
 #include "runtime/thread.inline.hpp"
+#include "runtime/threadSMR.hpp"
 #include "runtime/vm_version.hpp"
 #include "services/attachListener.hpp"
 #include "services/mallocTracker.hpp"
@@ -197,15 +198,7 @@
 }
 
 OSReturn os::set_priority(Thread* thread, ThreadPriority p) {
-#ifdef ASSERT
-  if (!(!thread->is_Java_thread() ||
-         Thread::current() == thread  ||
-         Threads_lock->owned_by_self()
-         || thread->is_Compiler_thread()
-        )) {
-    assert(false, "possibility of dangling Thread pointer");
-  }
-#endif
+  debug_only(Thread::check_for_dangling_thread_pointer(thread);)
 
   if (p >= MinPriority && p <= MaxPriority) {
     int priority = java_to_os_priority[p];
@@ -1100,7 +1093,7 @@
   }
 #endif
 
-  for(JavaThread *thread = Threads::first(); thread; thread = thread->next()) {
+  for (JavaThreadIteratorWithHandle jtiwh; JavaThread *thread = jtiwh.next(); ) {
     // Check for privilege stack
     if (thread->privileged_stack_top() != NULL &&
         thread->privileged_stack_top()->contains(addr)) {
@@ -1126,7 +1119,6 @@
       if (verbose) thread->print_on(st);
       return;
     }
-
   }
 
   // Check if in metaspace and print types that have vptrs (only method now)
@@ -1665,7 +1657,6 @@
 }
 
 void os::SuspendedThreadTask::run() {
-  assert(Threads_lock->owned_by_self() || (_thread == VMThread::vm_thread()), "must have threads lock to call this");
   internal_do_task();
   _done = true;
 }
--- a/src/hotspot/share/runtime/perfData.cpp	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/hotspot/share/runtime/perfData.cpp	Mon Nov 27 17:04:45 2017 +0000
@@ -32,7 +32,7 @@
 #include "runtime/mutex.hpp"
 #include "runtime/mutexLocker.hpp"
 #include "runtime/os.hpp"
-#include "runtime/perfData.hpp"
+#include "runtime/perfData.inline.hpp"
 #include "utilities/exceptions.hpp"
 #include "utilities/globalDefinitions.hpp"
 
@@ -611,3 +611,10 @@
 
   return copy;
 }
+
+PerfTraceTime::~PerfTraceTime() {
+  if (!UsePerfData || (_recursion_counter != NULL &&
+      --(*_recursion_counter) > 0)) return;
+  _t.stop();
+  _timerp->inc(_t.ticks());
+}
--- a/src/hotspot/share/runtime/perfData.hpp	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/hotspot/share/runtime/perfData.hpp	Mon Nov 27 17:04:45 2017 +0000
@@ -25,10 +25,11 @@
 #ifndef SHARE_VM_RUNTIME_PERFDATA_HPP
 #define SHARE_VM_RUNTIME_PERFDATA_HPP
 
-#include "memory/allocation.inline.hpp"
+#include "memory/allocation.hpp"
 #include "runtime/perfMemory.hpp"
 #include "runtime/timer.hpp"
-#include "utilities/growableArray.hpp"
+
+template <typename T> class GrowableArray;
 
 /* jvmstat global and subsystem counter name space - enumeration value
  * serve as an index into the PerfDataManager::_name_space[] array
@@ -629,10 +630,10 @@
     bool contains(const char* name) { return find_by_name(name) != NULL; }
 
     // return the number of PerfData items in this list
-    int length() { return _set->length(); }
+    inline int length();
 
     // add a PerfData item to this list
-    void append(PerfData *p) { _set->append(p); }
+    inline void append(PerfData *p);
 
     // remove the given PerfData item from this list. When called
     // while iterating over the list, this method will result in a
@@ -640,7 +641,7 @@
     // method is also impacted by this method as elements with an
     // index greater than the index of the element removed by this
     // method will be shifted down by one.
-    void remove(PerfData *p) { _set->remove(p); }
+    inline void remove(PerfData *p);
 
     // create a new PerfDataList from this list. The new list is
     // a shallow copy of the original list and care should be taken
@@ -651,7 +652,7 @@
     // for backward compatibility with GrowableArray - need to implement
     // some form of iterator to provide a cleaner abstraction for
     // iteration over the container.
-    PerfData* at(int index) { return _set->at(index); }
+    inline PerfData* at(int index);
 };
 
 
@@ -677,23 +678,23 @@
   protected:
     // return the list of all known PerfData items
     static PerfDataList* all();
-    static int count() { return _all->length(); }
+    static inline int count();
 
     // return the list of all known PerfData items that are to be
     // sampled by the StatSampler.
     static PerfDataList* sampled();
-    static int sampled_count() { return _sampled->length(); }
+    static inline int sampled_count();
 
     // return the list of all known PerfData items that have a
     // variability classification of type Constant
     static PerfDataList* constants();
-    static int constants_count() { return _constants->length(); }
+    static inline int constants_count();
 
   public:
 
     // method to check for the existence of a PerfData item with
     // the given name.
-    static bool exists(const char* name) { return _all->contains(name); }
+    static inline bool exists(const char* name);
 
     // method to search for a instrumentation object by name
     static PerfData* find_by_name(const char* name);
@@ -929,12 +930,7 @@
     inline void suspend() { if (!UsePerfData) return; _t.stop(); }
     inline void resume() { if (!UsePerfData) return; _t.start(); }
 
-    inline ~PerfTraceTime() {
-      if (!UsePerfData || (_recursion_counter != NULL &&
-                           --(*_recursion_counter) > 0)) return;
-      _t.stop();
-      _timerp->inc(_t.ticks());
-    }
+    ~PerfTraceTime();
 };
 
 /* The PerfTraceTimedEvent class is responsible for counting the
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/runtime/perfData.inline.hpp	Mon Nov 27 17:04:45 2017 +0000
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2002, 2017, 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.
+ *
+ */
+
+#ifndef SHARE_VM_RUNTIME_PERFDATA_INLINE_HPP
+#define SHARE_VM_RUNTIME_PERFDATA_INLINE_HPP
+
+#include "runtime/perfData.hpp"
+#include "utilities/globalDefinitions.hpp"
+#include "utilities/growableArray.hpp"
+
+inline int PerfDataList::length() {
+  return _set->length();
+}
+
+inline void PerfDataList::append(PerfData *p) {
+  _set->append(p);
+}
+
+inline void PerfDataList::remove(PerfData *p) {
+  _set->remove(p);
+}
+
+inline PerfData* PerfDataList::at(int index) {
+  return _set->at(index);
+}
+
+inline int PerfDataManager::count() {
+  return _all->length();
+}
+
+inline int PerfDataManager::sampled_count() {
+  return _sampled->length();
+}
+
+inline int PerfDataManager::constants_count() {
+  return _constants->length();
+}
+
+inline bool PerfDataManager::exists(const char* name) {
+  return _all->contains(name);
+}
+
+#endif // SHARE_VM_RUNTIME_PERFDATA_INLINE_HPP
--- a/src/hotspot/share/runtime/safepoint.cpp	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/hotspot/share/runtime/safepoint.cpp	Mon Nov 27 17:04:45 2017 +0000
@@ -59,6 +59,7 @@
 #include "runtime/sweeper.hpp"
 #include "runtime/synchronizer.hpp"
 #include "runtime/thread.inline.hpp"
+#include "runtime/threadSMR.hpp"
 #include "runtime/timerTrace.hpp"
 #include "services/runtimeService.hpp"
 #include "trace/tracing.hpp"
@@ -174,7 +175,7 @@
     if (SafepointMechanism::uses_thread_local_poll()) {
       // Arming the per thread poll while having _state != _not_synchronized means safepointing
       log_trace(safepoint)("Setting thread local yield flag for threads");
-      for (JavaThread *cur = Threads::first(); cur != NULL; cur = cur->next()) {
+      for (JavaThreadIteratorWithHandle jtiwh; JavaThread *cur = jtiwh.next(); ) {
         // Make sure the threads start polling, it is time to yield.
         SafepointMechanism::arm_local_poll(cur); // release store, global state -> local state
       }
@@ -200,133 +201,137 @@
 
     // Consider using active_processor_count() ... but that call is expensive.
     int ncpus = os::processor_count() ;
+    unsigned int iterations = 0;
 
+    {
+      JavaThreadIteratorWithHandle jtiwh;
 #ifdef ASSERT
-    for (JavaThread *cur = Threads::first(); cur != NULL; cur = cur->next()) {
-      assert(cur->safepoint_state()->is_running(), "Illegal initial state");
-      // Clear the visited flag to ensure that the critical counts are collected properly.
-      cur->set_visited_for_critical_count(false);
-    }
+      for (; JavaThread *cur = jtiwh.next(); ) {
+        assert(cur->safepoint_state()->is_running(), "Illegal initial state");
+        // Clear the visited flag to ensure that the critical counts are collected properly.
+        cur->set_visited_for_critical_count(false);
+      }
 #endif // ASSERT
 
-    if (SafepointTimeout)
-      safepoint_limit_time = os::javaTimeNanos() + (jlong)SafepointTimeoutDelay * MICROUNITS;
+      if (SafepointTimeout)
+        safepoint_limit_time = os::javaTimeNanos() + (jlong)SafepointTimeoutDelay * MICROUNITS;
 
-    // Iterate through all threads until it have been determined how to stop them all at a safepoint
-    unsigned int iterations = 0;
-    int steps = 0 ;
-    while(still_running > 0) {
-      for (JavaThread *cur = Threads::first(); cur != NULL; cur = cur->next()) {
-        assert(!cur->is_ConcurrentGC_thread(), "A concurrent GC thread is unexpectly being suspended");
-        ThreadSafepointState *cur_state = cur->safepoint_state();
-        if (cur_state->is_running()) {
-          cur_state->examine_state_of_thread();
-          if (!cur_state->is_running()) {
-            still_running--;
-            // consider adjusting steps downward:
-            //   steps = 0
-            //   steps -= NNN
-            //   steps >>= 1
-            //   steps = MIN(steps, 2000-100)
-            //   if (iterations != 0) steps -= NNN
-          }
-          LogTarget(Trace, safepoint) lt;
-          if (lt.is_enabled()) {
-            ResourceMark rm;
-            LogStream ls(lt);
-            cur_state->print_on(&ls);
+      // Iterate through all threads until it have been determined how to stop them all at a safepoint
+      int steps = 0 ;
+      while(still_running > 0) {
+        jtiwh.rewind();
+        for (; JavaThread *cur = jtiwh.next(); ) {
+          assert(!cur->is_ConcurrentGC_thread(), "A concurrent GC thread is unexpectly being suspended");
+          ThreadSafepointState *cur_state = cur->safepoint_state();
+          if (cur_state->is_running()) {
+            cur_state->examine_state_of_thread();
+            if (!cur_state->is_running()) {
+              still_running--;
+              // consider adjusting steps downward:
+              //   steps = 0
+              //   steps -= NNN
+              //   steps >>= 1
+              //   steps = MIN(steps, 2000-100)
+              //   if (iterations != 0) steps -= NNN
+            }
+            LogTarget(Trace, safepoint) lt;
+            if (lt.is_enabled()) {
+              ResourceMark rm;
+              LogStream ls(lt);
+              cur_state->print_on(&ls);
+            }
           }
         }
-      }
 
-      if (iterations == 0) {
-        initial_running = still_running;
-        if (PrintSafepointStatistics) {
-          begin_statistics(nof_threads, still_running);
-        }
-      }
-
-      if (still_running > 0) {
-        // Check for if it takes to long
-        if (SafepointTimeout && safepoint_limit_time < os::javaTimeNanos()) {
-          print_safepoint_timeout(_spinning_timeout);
+        if (iterations == 0) {
+          initial_running = still_running;
+          if (PrintSafepointStatistics) {
+            begin_statistics(nof_threads, still_running);
+          }
         }
 
-        // Spin to avoid context switching.
-        // There's a tension between allowing the mutators to run (and rendezvous)
-        // vs spinning.  As the VM thread spins, wasting cycles, it consumes CPU that
-        // a mutator might otherwise use profitably to reach a safepoint.  Excessive
-        // spinning by the VM thread on a saturated system can increase rendezvous latency.
-        // Blocking or yielding incur their own penalties in the form of context switching
-        // and the resultant loss of $ residency.
-        //
-        // Further complicating matters is that yield() does not work as naively expected
-        // on many platforms -- yield() does not guarantee that any other ready threads
-        // will run.   As such we revert to naked_short_sleep() after some number of iterations.
-        // nakes_short_sleep() is implemented as a short unconditional sleep.
-        // Typical operating systems round a "short" sleep period up to 10 msecs, so sleeping
-        // can actually increase the time it takes the VM thread to detect that a system-wide
-        // stop-the-world safepoint has been reached.  In a pathological scenario such as that
-        // described in CR6415670 the VMthread may sleep just before the mutator(s) become safe.
-        // In that case the mutators will be stalled waiting for the safepoint to complete and the
-        // the VMthread will be sleeping, waiting for the mutators to rendezvous.  The VMthread
-        // will eventually wake up and detect that all mutators are safe, at which point
-        // we'll again make progress.
-        //
-        // Beware too that that the VMThread typically runs at elevated priority.
-        // Its default priority is higher than the default mutator priority.
-        // Obviously, this complicates spinning.
-        //
-        // Note too that on Windows XP SwitchThreadTo() has quite different behavior than Sleep(0).
-        // Sleep(0) will _not yield to lower priority threads, while SwitchThreadTo() will.
-        //
-        // See the comments in synchronizer.cpp for additional remarks on spinning.
-        //
-        // In the future we might:
-        // 1. Modify the safepoint scheme to avoid potentially unbounded spinning.
-        //    This is tricky as the path used by a thread exiting the JVM (say on
-        //    on JNI call-out) simply stores into its state field.  The burden
-        //    is placed on the VM thread, which must poll (spin).
-        // 2. Find something useful to do while spinning.  If the safepoint is GC-related
-        //    we might aggressively scan the stacks of threads that are already safe.
-        // 3. Use Solaris schedctl to examine the state of the still-running mutators.
-        //    If all the mutators are ONPROC there's no reason to sleep or yield.
-        // 4. YieldTo() any still-running mutators that are ready but OFFPROC.
-        // 5. Check system saturation.  If the system is not fully saturated then
-        //    simply spin and avoid sleep/yield.
-        // 6. As still-running mutators rendezvous they could unpark the sleeping
-        //    VMthread.  This works well for still-running mutators that become
-        //    safe.  The VMthread must still poll for mutators that call-out.
-        // 7. Drive the policy on time-since-begin instead of iterations.
-        // 8. Consider making the spin duration a function of the # of CPUs:
-        //    Spin = (((ncpus-1) * M) + K) + F(still_running)
-        //    Alternately, instead of counting iterations of the outer loop
-        //    we could count the # of threads visited in the inner loop, above.
-        // 9. On windows consider using the return value from SwitchThreadTo()
-        //    to drive subsequent spin/SwitchThreadTo()/Sleep(N) decisions.
-
-        if (SafepointMechanism::uses_global_page_poll() && int(iterations) == DeferPollingPageLoopCount) {
-          guarantee (PageArmed == 0, "invariant") ;
-          PageArmed = 1 ;
-          os::make_polling_page_unreadable();
-        }
-
-        // Instead of (ncpus > 1) consider either (still_running < (ncpus + EPSILON)) or
-        // ((still_running + _waiting_to_block - TryingToBlock)) < ncpus)
-        ++steps ;
-        if (ncpus > 1 && steps < SafepointSpinBeforeYield) {
-          SpinPause() ;     // MP-Polite spin
-        } else
-          if (steps < DeferThrSuspendLoopCount) {
-            os::naked_yield() ;
-          } else {
-            os::naked_short_sleep(1);
+        if (still_running > 0) {
+          // Check for if it takes to long
+          if (SafepointTimeout && safepoint_limit_time < os::javaTimeNanos()) {
+            print_safepoint_timeout(_spinning_timeout);
           }
 
-        iterations ++ ;
+          // Spin to avoid context switching.
+          // There's a tension between allowing the mutators to run (and rendezvous)
+          // vs spinning.  As the VM thread spins, wasting cycles, it consumes CPU that
+          // a mutator might otherwise use profitably to reach a safepoint.  Excessive
+          // spinning by the VM thread on a saturated system can increase rendezvous latency.
+          // Blocking or yielding incur their own penalties in the form of context switching
+          // and the resultant loss of $ residency.
+          //
+          // Further complicating matters is that yield() does not work as naively expected
+          // on many platforms -- yield() does not guarantee that any other ready threads
+          // will run.   As such we revert to naked_short_sleep() after some number of iterations.
+          // nakes_short_sleep() is implemented as a short unconditional sleep.
+          // Typical operating systems round a "short" sleep period up to 10 msecs, so sleeping
+          // can actually increase the time it takes the VM thread to detect that a system-wide
+          // stop-the-world safepoint has been reached.  In a pathological scenario such as that
+          // described in CR6415670 the VMthread may sleep just before the mutator(s) become safe.
+          // In that case the mutators will be stalled waiting for the safepoint to complete and the
+          // the VMthread will be sleeping, waiting for the mutators to rendezvous.  The VMthread
+          // will eventually wake up and detect that all mutators are safe, at which point
+          // we'll again make progress.
+          //
+          // Beware too that that the VMThread typically runs at elevated priority.
+          // Its default priority is higher than the default mutator priority.
+          // Obviously, this complicates spinning.
+          //
+          // Note too that on Windows XP SwitchThreadTo() has quite different behavior than Sleep(0).
+          // Sleep(0) will _not yield to lower priority threads, while SwitchThreadTo() will.
+          //
+          // See the comments in synchronizer.cpp for additional remarks on spinning.
+          //
+          // In the future we might:
+          // 1. Modify the safepoint scheme to avoid potentially unbounded spinning.
+          //    This is tricky as the path used by a thread exiting the JVM (say on
+          //    on JNI call-out) simply stores into its state field.  The burden
+          //    is placed on the VM thread, which must poll (spin).
+          // 2. Find something useful to do while spinning.  If the safepoint is GC-related
+          //    we might aggressively scan the stacks of threads that are already safe.
+          // 3. Use Solaris schedctl to examine the state of the still-running mutators.
+          //    If all the mutators are ONPROC there's no reason to sleep or yield.
+          // 4. YieldTo() any still-running mutators that are ready but OFFPROC.
+          // 5. Check system saturation.  If the system is not fully saturated then
+          //    simply spin and avoid sleep/yield.
+          // 6. As still-running mutators rendezvous they could unpark the sleeping
+          //    VMthread.  This works well for still-running mutators that become
+          //    safe.  The VMthread must still poll for mutators that call-out.
+          // 7. Drive the policy on time-since-begin instead of iterations.
+          // 8. Consider making the spin duration a function of the # of CPUs:
+          //    Spin = (((ncpus-1) * M) + K) + F(still_running)
+          //    Alternately, instead of counting iterations of the outer loop
+          //    we could count the # of threads visited in the inner loop, above.
+          // 9. On windows consider using the return value from SwitchThreadTo()
+          //    to drive subsequent spin/SwitchThreadTo()/Sleep(N) decisions.
+
+          if (SafepointMechanism::uses_global_page_poll() && int(iterations) == DeferPollingPageLoopCount) {
+            guarantee (PageArmed == 0, "invariant") ;
+            PageArmed = 1 ;
+            os::make_polling_page_unreadable();
+          }
+
+          // Instead of (ncpus > 1) consider either (still_running < (ncpus + EPSILON)) or
+          // ((still_running + _waiting_to_block - TryingToBlock)) < ncpus)
+          ++steps ;
+          if (ncpus > 1 && steps < SafepointSpinBeforeYield) {
+            SpinPause() ;     // MP-Polite spin
+          } else
+            if (steps < DeferThrSuspendLoopCount) {
+              os::naked_yield() ;
+            } else {
+              os::naked_short_sleep(1);
+            }
+
+          iterations ++ ;
+        }
+        assert(iterations < (uint)max_jint, "We have been iterating in the safepoint loop too long");
       }
-      assert(iterations < (uint)max_jint, "We have been iterating in the safepoint loop too long");
-    }
+    } // ThreadsListHandle destroyed here.
     assert(still_running == 0, "sanity check");
 
     if (PrintSafepointStatistics) {
@@ -341,7 +346,7 @@
       sync_event.set_iterations(iterations);
       sync_event.commit();
     }
-  } //EventSafepointStateSync
+  } // EventSafepointStateSynchronization destroyed here.
 
   // wait until all threads are stopped
   {
@@ -393,8 +398,8 @@
   } // EventSafepointWaitBlocked
 
 #ifdef ASSERT
-  for (JavaThread *cur = Threads::first(); cur != NULL; cur = cur->next()) {
-    // make sure all the threads were visited
+  // Make sure all the threads were visited.
+  for (JavaThreadIteratorWithHandle jtiwh; JavaThread *cur = jtiwh.next(); ) {
     assert(cur->was_visited_for_critical_count(), "missed a thread");
   }
 #endif // ASSERT
@@ -452,81 +457,86 @@
     end_statistics(os::javaTimeNanos());
   }
 
+  {
+    JavaThreadIteratorWithHandle jtiwh;
 #ifdef ASSERT
-  // A pending_exception cannot be installed during a safepoint.  The threads
-  // may install an async exception after they come back from a safepoint into
-  // pending_exception after they unblock.  But that should happen later.
-  for (JavaThread *cur = Threads::first(); cur; cur = cur->next()) {
-    assert (!(cur->has_pending_exception() &&
-              cur->safepoint_state()->is_at_poll_safepoint()),
-            "safepoint installed a pending exception");
-  }
+    // A pending_exception cannot be installed during a safepoint.  The threads
+    // may install an async exception after they come back from a safepoint into
+    // pending_exception after they unblock.  But that should happen later.
+    for (; JavaThread *cur = jtiwh.next(); ) {
+      assert (!(cur->has_pending_exception() &&
+                cur->safepoint_state()->is_at_poll_safepoint()),
+              "safepoint installed a pending exception");
+    }
 #endif // ASSERT
 
-  if (PageArmed) {
-    assert(SafepointMechanism::uses_global_page_poll(), "sanity");
-    // Make polling safepoint aware
-    os::make_polling_page_readable();
-    PageArmed = 0 ;
-  }
-
-  if (SafepointMechanism::uses_global_page_poll()) {
-    // Remove safepoint check from interpreter
-    Interpreter::ignore_safepoints();
-  }
-
-  {
-    MutexLocker mu(Safepoint_lock);
-
-    assert(_state == _synchronized, "must be synchronized before ending safepoint synchronization");
+    if (PageArmed) {
+      assert(SafepointMechanism::uses_global_page_poll(), "sanity");
+      // Make polling safepoint aware
+      os::make_polling_page_readable();
+      PageArmed = 0 ;
+    }
 
-    if (SafepointMechanism::uses_thread_local_poll()) {
-      _state = _not_synchronized;
-      OrderAccess::storestore(); // global state -> local state
-      for (JavaThread *current = Threads::first(); current; current = current->next()) {
-        ThreadSafepointState* cur_state = current->safepoint_state();
-        cur_state->restart(); // TSS _running
-        SafepointMechanism::disarm_local_poll(current); // release store, local state -> polling page
-      }
-      log_debug(safepoint)("Leaving safepoint region");
-    } else {
-      // Set to not synchronized, so the threads will not go into the signal_thread_blocked method
-      // when they get restarted.
-      _state = _not_synchronized;
-      OrderAccess::fence();
-
-      log_debug(safepoint)("Leaving safepoint region");
-
-      // Start suspended threads
-      for (JavaThread *current = Threads::first(); current; current = current->next()) {
-        // A problem occurring on Solaris is when attempting to restart threads
-        // the first #cpus - 1 go well, but then the VMThread is preempted when we get
-        // to the next one (since it has been running the longest).  We then have
-        // to wait for a cpu to become available before we can continue restarting
-        // threads.
-        // FIXME: This causes the performance of the VM to degrade when active and with
-        // large numbers of threads.  Apparently this is due to the synchronous nature
-        // of suspending threads.
-        //
-        // TODO-FIXME: the comments above are vestigial and no longer apply.
-        // Furthermore, using solaris' schedctl in this particular context confers no benefit
-        if (VMThreadHintNoPreempt) {
-          os::hint_no_preempt();
-        }
-        ThreadSafepointState* cur_state = current->safepoint_state();
-        assert(cur_state->type() != ThreadSafepointState::_running, "Thread not suspended at safepoint");
-        cur_state->restart();
-        assert(cur_state->is_running(), "safepoint state has not been reset");
-      }
+    if (SafepointMechanism::uses_global_page_poll()) {
+      // Remove safepoint check from interpreter
+      Interpreter::ignore_safepoints();
     }
 
-    RuntimeService::record_safepoint_end();
+    {
+      MutexLocker mu(Safepoint_lock);
+
+      assert(_state == _synchronized, "must be synchronized before ending safepoint synchronization");
+
+      if (SafepointMechanism::uses_thread_local_poll()) {
+        _state = _not_synchronized;
+        OrderAccess::storestore(); // global state -> local state
+        jtiwh.rewind();
+        for (; JavaThread *current = jtiwh.next(); ) {
+          ThreadSafepointState* cur_state = current->safepoint_state();
+          cur_state->restart(); // TSS _running
+          SafepointMechanism::disarm_local_poll(current); // release store, local state -> polling page
+        }
+        log_debug(safepoint)("Leaving safepoint region");
+      } else {
+        // Set to not synchronized, so the threads will not go into the signal_thread_blocked method
+        // when they get restarted.
+        _state = _not_synchronized;
+        OrderAccess::fence();
+
+        log_debug(safepoint)("Leaving safepoint region");
 
-    // Release threads lock, so threads can be created/destroyed again. It will also starts all threads
-    // blocked in signal_thread_blocked
-    Threads_lock->unlock();
+        // Start suspended threads
+        jtiwh.rewind();
+        for (; JavaThread *current = jtiwh.next(); ) {
+          // A problem occurring on Solaris is when attempting to restart threads
+          // the first #cpus - 1 go well, but then the VMThread is preempted when we get
+          // to the next one (since it has been running the longest).  We then have
+          // to wait for a cpu to become available before we can continue restarting
+          // threads.
+          // FIXME: This causes the performance of the VM to degrade when active and with
+          // large numbers of threads.  Apparently this is due to the synchronous nature
+          // of suspending threads.
+          //
+          // TODO-FIXME: the comments above are vestigial and no longer apply.
+          // Furthermore, using solaris' schedctl in this particular context confers no benefit
+          if (VMThreadHintNoPreempt) {
+            os::hint_no_preempt();
+          }
+          ThreadSafepointState* cur_state = current->safepoint_state();
+          assert(cur_state->type() != ThreadSafepointState::_running, "Thread not suspended at safepoint");
+          cur_state->restart();
+          assert(cur_state->is_running(), "safepoint state has not been reset");
+        }
+      }
 
-  }
+      RuntimeService::record_safepoint_end();
+
+      // Release threads lock, so threads can be created/destroyed again.
+      // It will also release all threads blocked in signal_thread_blocked.
+      Threads_lock->unlock();
+    }
+  } // ThreadsListHandle destroyed here.
+
   Universe::heap()->safepoint_synchronize_end();
   // record this time so VMThread can keep track how much time has elapsed
   // since last safepoint.
@@ -915,12 +925,11 @@
     tty->print_cr("# SafepointSynchronize::begin: Threads which did not reach the safepoint:");
     ThreadSafepointState *cur_state;
     ResourceMark rm;
-    for (JavaThread *cur_thread = Threads::first(); cur_thread;
-        cur_thread = cur_thread->next()) {
+    for (JavaThreadIteratorWithHandle jtiwh; JavaThread *cur_thread = jtiwh.next(); ) {
       cur_state = cur_thread->safepoint_state();
 
       if (cur_thread->thread_state() != _thread_blocked &&
-          ((reason == _spinning_timeout && cur_state->is_running()) ||
+        ((reason == _spinning_timeout && cur_state->is_running()) ||
            (reason == _blocking_timeout && !cur_state->has_called_back()))) {
         tty->print("# ");
         cur_thread->print();
@@ -1427,7 +1436,7 @@
     tty->print_cr("State: %s", (_state == _synchronizing) ? "synchronizing" :
                   "synchronized");
 
-    for (JavaThread *cur = Threads::first(); cur; cur = cur->next()) {
+    for (JavaThreadIteratorWithHandle jtiwh; JavaThread *cur = jtiwh.next(); ) {
        cur->safepoint_state()->print();
     }
   }
--- a/src/hotspot/share/runtime/statSampler.cpp	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/hotspot/share/runtime/statSampler.cpp	Mon Nov 27 17:04:45 2017 +0000
@@ -32,6 +32,7 @@
 #include "runtime/java.hpp"
 #include "runtime/javaCalls.hpp"
 #include "runtime/os.hpp"
+#include "runtime/perfData.inline.hpp"
 #include "runtime/statSampler.hpp"
 #include "runtime/vm_version.hpp"
 
--- a/src/hotspot/share/runtime/synchronizer.cpp	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/hotspot/share/runtime/synchronizer.cpp	Mon Nov 27 17:04:45 2017 +0000
@@ -894,7 +894,7 @@
 }
 
 // FIXME: jvmti should call this
-JavaThread* ObjectSynchronizer::get_lock_owner(Handle h_obj, bool doLock) {
+JavaThread* ObjectSynchronizer::get_lock_owner(ThreadsList * t_list, Handle h_obj) {
   if (UseBiasedLocking) {
     if (SafepointSynchronize::is_at_safepoint()) {
       BiasedLocking::revoke_at_safepoint(h_obj);
@@ -923,7 +923,7 @@
 
   if (owner != NULL) {
     // owning_thread_from_monitor_owner() may also return NULL here
-    return Threads::owning_thread_from_monitor_owner(owner, doLock);
+    return Threads::owning_thread_from_monitor_owner(t_list, owner);
   }
 
   // Unlocked case, header in place
--- a/src/hotspot/share/runtime/synchronizer.hpp	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/hotspot/share/runtime/synchronizer.hpp	Mon Nov 27 17:04:45 2017 +0000
@@ -32,6 +32,7 @@
 #include "runtime/perfData.hpp"
 
 class ObjectMonitor;
+class ThreadsList;
 
 struct DeflateMonitorCounters {
   int nInuse;          // currently associated with objects
@@ -125,7 +126,7 @@
   static bool current_thread_holds_lock(JavaThread* thread, Handle h_obj);
   static LockOwnership query_lock_ownership(JavaThread * self, Handle h_obj);
 
-  static JavaThread* get_lock_owner(Handle h_obj, bool doLock);
+  static JavaThread* get_lock_owner(ThreadsList * t_list, Handle h_obj);
 
   // JNI detach support
   static void release_monitors_owned_by_thread(TRAPS);
--- a/src/hotspot/share/runtime/thread.cpp	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/hotspot/share/runtime/thread.cpp	Mon Nov 27 17:04:45 2017 +0000
@@ -71,12 +71,12 @@
 #include "runtime/java.hpp"
 #include "runtime/javaCalls.hpp"
 #include "runtime/jniPeriodicChecker.hpp"
-#include "runtime/timerTrace.hpp"
 #include "runtime/memprofiler.hpp"
 #include "runtime/mutexLocker.hpp"
 #include "runtime/objectMonitor.hpp"
 #include "runtime/orderAccess.inline.hpp"
 #include "runtime/osThread.hpp"
+#include "runtime/prefetch.inline.hpp"
 #include "runtime/safepoint.hpp"
 #include "runtime/safepointMechanism.inline.hpp"
 #include "runtime/sharedRuntime.hpp"
@@ -86,6 +86,9 @@
 #include "runtime/task.hpp"
 #include "runtime/thread.inline.hpp"
 #include "runtime/threadCritical.hpp"
+#include "runtime/threadSMR.inline.hpp"
+#include "runtime/timer.hpp"
+#include "runtime/timerTrace.hpp"
 #include "runtime/vframe.hpp"
 #include "runtime/vframeArray.hpp"
 #include "runtime/vframe_hp.hpp"
@@ -104,6 +107,7 @@
 #include "utilities/events.hpp"
 #include "utilities/macros.hpp"
 #include "utilities/preserveException.hpp"
+#include "utilities/resourceHash.hpp"
 #include "utilities/vmError.hpp"
 #if INCLUDE_ALL_GCS
 #include "gc/cms/concurrentMarkSweepThread.hpp"
@@ -195,13 +199,19 @@
 
 void Thread::operator delete(void* p) {
   if (UseBiasedLocking) {
-    void* real_malloc_addr = ((Thread*) p)->_real_malloc_address;
-    FreeHeap(real_malloc_addr);
+    FreeHeap(((Thread*) p)->_real_malloc_address);
   } else {
     FreeHeap(p);
   }
 }
 
+void JavaThread::smr_delete() {
+  if (_on_thread_list) {
+    Threads::smr_delete(this);
+  } else {
+    delete this;
+  }
+}
 
 // Base class for all threads: VMThread, WatcherThread, ConcurrentMarkSweepThread,
 // JavaThread
@@ -227,6 +237,9 @@
 
   // This initial value ==> never claimed.
   _oops_do_parity = 0;
+  _threads_hazard_ptr = NULL;
+  _nested_threads_hazard_ptr = NULL;
+  _nested_threads_hazard_ptr_cnt = 0;
 
   // the handle mark links itself to last_handle_mark
   new HandleMark(this);
@@ -398,9 +411,15 @@
 }
 
 #ifdef ASSERT
-// Private method to check for dangling thread pointer
-void check_for_dangling_thread_pointer(Thread *thread) {
-  assert(!thread->is_Java_thread() || Thread::current() == thread || Threads_lock->owned_by_self(),
+// A JavaThread is considered "dangling" if it is not the current
+// thread, has been added the Threads list, the system is not at a
+// safepoint and the Thread is not "protected".
+//
+void Thread::check_for_dangling_thread_pointer(Thread *thread) {
+  assert(!thread->is_Java_thread() || Thread::current() == thread ||
+         !((JavaThread *) thread)->on_thread_list() ||
+         SafepointSynchronize::is_at_safepoint() ||
+         Threads::is_a_protected_JavaThread_with_lock((JavaThread *) thread),
          "possibility of dangling Thread pointer");
 }
 #endif
@@ -732,6 +751,37 @@
   return false;
 }
 
+// Called from API entry points which perform stack walking. If the
+// associated JavaThread is the current thread, then wait_for_suspend
+// is not used. Otherwise, it determines if we should wait for the
+// "other" thread to complete external suspension. (NOTE: in future
+// releases the suspension mechanism should be reimplemented so this
+// is not necessary.)
+//
+bool
+JavaThread::is_thread_fully_suspended(bool wait_for_suspend, uint32_t *bits) {
+  if (this != JavaThread::current()) {
+    // "other" threads require special handling.
+    if (wait_for_suspend) {
+      // We are allowed to wait for the external suspend to complete
+      // so give the other thread a chance to get suspended.
+      if (!wait_for_ext_suspend_completion(SuspendRetryCount,
+                                           SuspendRetryDelay, bits)) {
+        // Didn't make it so let the caller know.
+        return false;
+      }
+    }
+    // We aren't allowed to wait for the external suspend to complete
+    // so if the other thread isn't externally suspended we need to
+    // let the caller know.
+    else if (!is_ext_suspend_completed_with_lock(bits)) {
+      return false;
+    }
+  }
+
+  return true;
+}
+
 #ifndef PRODUCT
 void JavaThread::record_jump(address target, address instr, const char* file,
                              int line) {
@@ -810,9 +860,33 @@
     ext().print_on(st);
     osthread()->print_on(st);
   }
+  if (_threads_hazard_ptr != NULL) {
+    st->print("_threads_hazard_ptr=" INTPTR_FORMAT, p2i(_threads_hazard_ptr));
+  }
+  if (_nested_threads_hazard_ptr != NULL) {
+    print_nested_threads_hazard_ptrs_on(st);
+  }
+  st->print(" ");
   debug_only(if (WizardMode) print_owned_locks_on(st);)
 }
 
+void Thread::print_nested_threads_hazard_ptrs_on(outputStream* st) const {
+  assert(_nested_threads_hazard_ptr != NULL, "must be set to print");
+
+  if (EnableThreadSMRStatistics) {
+    st->print(", _nested_threads_hazard_ptr_cnt=%u", _nested_threads_hazard_ptr_cnt);
+  }
+  st->print(", _nested_threads_hazard_ptrs=");
+  for (NestedThreadsList* node = _nested_threads_hazard_ptr; node != NULL;
+       node = node->next()) {
+    if (node != _nested_threads_hazard_ptr) {
+      // First node does not need a comma-space separator.
+      st->print(", ");
+    }
+    st->print(INTPTR_FORMAT, p2i(node->t_list()));
+  }
+}
+
 // Thread::print_on_error() is called by fatal error handler. Don't use
 // any lock or allocate memory.
 void Thread::print_on_error(outputStream* st, char* buf, int buflen) const {
@@ -834,6 +908,13 @@
   if (osthread()) {
     st->print(" [id=%d]", osthread()->thread_id());
   }
+
+  if (_threads_hazard_ptr != NULL) {
+    st->print(" _threads_hazard_ptr=" INTPTR_FORMAT, p2i(_threads_hazard_ptr));
+  }
+  if (_nested_threads_hazard_ptr != NULL) {
+    print_nested_threads_hazard_ptrs_on(st);
+  }
 }
 
 void Thread::print_value_on(outputStream* st) const {
@@ -871,8 +952,8 @@
 
 #ifndef PRODUCT
 
-// The flag: potential_vm_operation notifies if this particular safepoint state could potential
-// invoke the vm-thread (i.e., and oop allocation). In that case, we also have to make sure that
+// The flag: potential_vm_operation notifies if this particular safepoint state could potentially
+// invoke the vm-thread (e.g., an oop allocation). In that case, we also have to make sure that
 // no threads which allow_vm_block's are held
 void Thread::check_for_valid_safepoint_state(bool potential_vm_operation) {
   // Check if current thread is allowed to block at a safepoint
@@ -1399,10 +1480,11 @@
 void JavaThread::collect_counters(typeArrayOop array) {
   if (JVMCICounterSize > 0) {
     MutexLocker tl(Threads_lock);
+    JavaThreadIteratorWithHandle jtiwh;
     for (int i = 0; i < array->length(); i++) {
       array->long_at_put(i, _jvmci_old_thread_counters[i]);
     }
-    for (JavaThread* tp = Threads::first(); tp != NULL; tp = tp->next()) {
+    for (; JavaThread *tp = jtiwh.next(); ) {
       if (jvmci_counters_include(tp)) {
         for (int i = 0; i < array->length(); i++) {
           array->long_at_put(i, array->long_at(i) + tp->_jvmci_counters[i]);
@@ -1435,6 +1517,7 @@
   clear_must_deopt_id();
   set_monitor_chunks(NULL);
   set_next(NULL);
+  _on_thread_list = false;
   set_thread_state(_thread_new);
   _terminated = _not_terminated;
   _privileged_stack_top = NULL;
@@ -1715,12 +1798,12 @@
   DTRACE_THREAD_PROBE(stop, this);
 
   this->exit(false);
-  delete this;
+  this->smr_delete();
 }
 
 
 static void ensure_join(JavaThread* thread) {
-  // We do not need to grap the Threads_lock, since we are operating on ourself.
+  // We do not need to grab the Threads_lock, since we are operating on ourself.
   Handle threadObj(thread, thread->threadObj());
   assert(threadObj.not_null(), "java thread object must exist");
   ObjectLocker lock(threadObj, thread);
@@ -1742,6 +1825,15 @@
 void JavaThread::exit(bool destroy_vm, ExitType exit_type) {
   assert(this == JavaThread::current(), "thread consistency check");
 
+  elapsedTimer _timer_exit_phase1;
+  elapsedTimer _timer_exit_phase2;
+  elapsedTimer _timer_exit_phase3;
+  elapsedTimer _timer_exit_phase4;
+
+  if (log_is_enabled(Debug, os, thread, timer)) {
+    _timer_exit_phase1.start();
+  }
+
   HandleMark hm(this);
   Handle uncaught_exception(this, this->pending_exception());
   this->clear_pending_exception();
@@ -1841,12 +1933,20 @@
     // before_exit() has already posted JVMTI THREAD_END events
   }
 
+  if (log_is_enabled(Debug, os, thread, timer)) {
+    _timer_exit_phase1.stop();
+    _timer_exit_phase2.start();
+  }
   // Notify waiters on thread object. This has to be done after exit() is called
   // on the thread (if the thread is the last thread in a daemon ThreadGroup the
   // group should have the destroyed bit set before waiters are notified).
   ensure_join(this);
   assert(!this->has_pending_exception(), "ensure_join should have cleared");
 
+  if (log_is_enabled(Debug, os, thread, timer)) {
+    _timer_exit_phase2.stop();
+    _timer_exit_phase3.start();
+  }
   // 6282335 JNI DetachCurrentThread spec states that all Java monitors
   // held by this thread must be released. The spec does not distinguish
   // between JNI-acquired and regular Java monitors. We can only see
@@ -1914,12 +2014,26 @@
     exit_type == JavaThread::normal_exit ? "exiting" : "detaching",
     os::current_thread_id());
 
+  if (log_is_enabled(Debug, os, thread, timer)) {
+    _timer_exit_phase3.stop();
+    _timer_exit_phase4.start();
+  }
   // Remove from list of active threads list, and notify VM thread if we are the last non-daemon thread
   Threads::remove(this);
 
-  // If someone set a handshake on us just as we entered exit path, we simple cancel it.
-  if (ThreadLocalHandshakes) {
-    cancel_handshake();
+  if (log_is_enabled(Debug, os, thread, timer)) {
+    _timer_exit_phase4.stop();
+    ResourceMark rm(this);
+    log_debug(os, thread, timer)("name='%s'"
+                                 ", exit-phase1=" JLONG_FORMAT
+                                 ", exit-phase2=" JLONG_FORMAT
+                                 ", exit-phase3=" JLONG_FORMAT
+                                 ", exit-phase4=" JLONG_FORMAT,
+                                 get_thread_name(),
+                                 _timer_exit_phase1.milliseconds(),
+                                 _timer_exit_phase2.milliseconds(),
+                                 _timer_exit_phase3.milliseconds(),
+                                 _timer_exit_phase4.milliseconds());
   }
 }
 
@@ -1980,7 +2094,7 @@
 #endif // INCLUDE_ALL_GCS
 
   Threads::remove(this);
-  delete this;
+  this->smr_delete();
 }
 
 
@@ -2235,10 +2349,9 @@
 //   + Target thread will not enter any new monitors
 //
 void JavaThread::java_suspend() {
-  { MutexLocker mu(Threads_lock);
-    if (!Threads::includes(this) || is_exiting() || this->threadObj() == NULL) {
-      return;
-    }
+  ThreadsListHandle tlh;
+  if (!tlh.includes(this) || threadObj() == NULL || is_exiting()) {
+    return;
   }
 
   { MutexLockerEx ml(SR_lock(), Mutex::_no_safepoint_check_flag);
@@ -2327,14 +2440,8 @@
 // verify the JavaThread has not yet been published in the Threads::list, and
 // hence doesn't need protection from concurrent access at this stage
 void JavaThread::verify_not_published() {
-  if (!Threads_lock->owned_by_self()) {
-    MutexLockerEx ml(Threads_lock,  Mutex::_no_safepoint_check_flag);
-    assert(!Threads::includes(this),
-           "java thread shouldn't have been published yet!");
-  } else {
-    assert(!Threads::includes(this),
-           "java thread shouldn't have been published yet!");
-  }
+  ThreadsListHandle tlh;
+  assert(!tlh.includes(this), "JavaThread shouldn't have been published yet!");
 }
 #endif
 
@@ -2451,7 +2558,8 @@
 
   // Sanity check: thread is gone, has started exiting or the thread
   // was not externally suspended.
-  if (!Threads::includes(this) || is_exiting() || !is_external_suspend()) {
+  ThreadsListHandle tlh;
+  if (!tlh.includes(this) || is_exiting() || !is_external_suspend()) {
     return;
   }
 
@@ -2925,6 +3033,13 @@
   st->print(", stack(" PTR_FORMAT "," PTR_FORMAT ")",
             p2i(stack_end()), p2i(stack_base()));
   st->print("]");
+
+  if (_threads_hazard_ptr != NULL) {
+    st->print(" _threads_hazard_ptr=" INTPTR_FORMAT, p2i(_threads_hazard_ptr));
+  }
+  if (_nested_threads_hazard_ptr != NULL) {
+    print_nested_threads_hazard_ptrs_on(st);
+  }
   return;
 }
 
@@ -3318,23 +3433,136 @@
 // ======= Threads ========
 
 // The Threads class links together all active threads, and provides
-// operations over all threads.  It is protected by its own Mutex
-// lock, which is also used in other contexts to protect thread
-// operations from having the thread being operated on from exiting
-// and going away unexpectedly (e.g., safepoint synchronization)
-
-JavaThread* Threads::_thread_list = NULL;
-int         Threads::_number_of_threads = 0;
-int         Threads::_number_of_non_daemon_threads = 0;
-int         Threads::_return_code = 0;
-int         Threads::_thread_claim_parity = 0;
-size_t      JavaThread::_stack_size_at_create = 0;
+// operations over all threads. It is protected by the Threads_lock,
+// which is also used in other global contexts like safepointing.
+// ThreadsListHandles are used to safely perform operations on one
+// or more threads without the risk of the thread exiting during the
+// operation.
+//
+// Note: The Threads_lock is currently more widely used than we
+// would like. We are actively migrating Threads_lock uses to other
+// mechanisms in order to reduce Threads_lock contention.
+
+JavaThread*           Threads::_thread_list = NULL;
+int                   Threads::_number_of_threads = 0;
+int                   Threads::_number_of_non_daemon_threads = 0;
+int                   Threads::_return_code = 0;
+int                   Threads::_thread_claim_parity = 0;
+size_t                JavaThread::_stack_size_at_create = 0;
+// Safe Memory Reclamation (SMR) support:
+Monitor*              Threads::_smr_delete_lock =
+                          new Monitor(Monitor::special, "smr_delete_lock",
+                                      false /* allow_vm_block */,
+                                      Monitor::_safepoint_check_never);
+// The '_cnt', '_max' and '_times" fields are enabled via
+// -XX:+EnableThreadSMRStatistics:
+
+// # of parallel threads in _smr_delete_lock->wait().
+// Impl note: Hard to imagine > 64K waiting threads so this could be 16-bit,
+// but there is no nice 16-bit _FORMAT support.
+uint                  Threads::_smr_delete_lock_wait_cnt = 0;
+
+// Max # of parallel threads in _smr_delete_lock->wait().
+// Impl note: See _smr_delete_lock_wait_cnt note.
+uint                  Threads::_smr_delete_lock_wait_max = 0;
+
+// Flag to indicate when an _smr_delete_lock->notify() is needed.
+// Impl note: See _smr_delete_lock_wait_cnt note.
+volatile uint         Threads::_smr_delete_notify = 0;
+
+// # of threads deleted over VM lifetime.
+// Impl note: Atomically incremented over VM lifetime so use unsigned for more
+// range. Unsigned 64-bit would be more future proof, but 64-bit atomic inc
+// isn't available everywhere (or is it?).
+volatile uint         Threads::_smr_deleted_thread_cnt = 0;
+
+// Max time in millis to delete a thread.
+// Impl note: 16-bit might be too small on an overloaded machine. Use
+// unsigned since this is a time value. Set via Atomic::cmpxchg() in a
+// loop for correctness.
+volatile uint         Threads::_smr_deleted_thread_time_max = 0;
+
+// Cumulative time in millis to delete threads.
+// Impl note: Atomically added to over VM lifetime so use unsigned for more
+// range. Unsigned 64-bit would be more future proof, but 64-bit atomic inc
+// isn't available everywhere (or is it?).
+volatile uint         Threads::_smr_deleted_thread_times = 0;
+
+ThreadsList* volatile Threads::_smr_java_thread_list = new ThreadsList(0);
+
+// # of ThreadsLists allocated over VM lifetime.
+// Impl note: We allocate a new ThreadsList for every thread create and
+// every thread delete so we need a bigger type than the
+// _smr_deleted_thread_cnt field.
+uint64_t              Threads::_smr_java_thread_list_alloc_cnt = 1;
+
+// # of ThreadsLists freed over VM lifetime.
+// Impl note: See _smr_java_thread_list_alloc_cnt note.
+uint64_t              Threads::_smr_java_thread_list_free_cnt = 0;
+
+// Max size ThreadsList allocated.
+// Impl note: Max # of threads alive at one time should fit in unsigned 32-bit.
+uint                  Threads::_smr_java_thread_list_max = 0;
+
+// Max # of nested ThreadsLists for a thread.
+// Impl note: Hard to imagine > 64K nested ThreadsLists so this could be
+// 16-bit, but there is no nice 16-bit _FORMAT support.
+uint                  Threads::_smr_nested_thread_list_max = 0;
+
+// # of ThreadsListHandles deleted over VM lifetime.
+// Impl note: Atomically incremented over VM lifetime so use unsigned for
+// more range. There will be fewer ThreadsListHandles than threads so
+// unsigned 32-bit should be fine.
+volatile uint         Threads::_smr_tlh_cnt = 0;
+
+// Max time in millis to delete a ThreadsListHandle.
+// Impl note: 16-bit might be too small on an overloaded machine. Use
+// unsigned since this is a time value. Set via Atomic::cmpxchg() in a
+// loop for correctness.
+volatile uint         Threads::_smr_tlh_time_max = 0;
+
+// Cumulative time in millis to delete ThreadsListHandles.
+// Impl note: Atomically added to over VM lifetime so use unsigned for more
+// range. Unsigned 64-bit would be more future proof, but 64-bit atomic inc
+// isn't available everywhere (or is it?).
+volatile uint         Threads::_smr_tlh_times = 0;
+
+ThreadsList*          Threads::_smr_to_delete_list = NULL;
+
+// # of parallel ThreadsLists on the to-delete list.
+// Impl note: Hard to imagine > 64K ThreadsLists needing to be deleted so
+// this could be 16-bit, but there is no nice 16-bit _FORMAT support.
+uint                  Threads::_smr_to_delete_list_cnt = 0;
+
+// Max # of parallel ThreadsLists on the to-delete list.
+// Impl note: See _smr_to_delete_list_cnt note.
+uint                  Threads::_smr_to_delete_list_max = 0;
+
 #ifdef ASSERT
-bool        Threads::_vm_complete = false;
+bool                  Threads::_vm_complete = false;
 #endif
 
+static inline void *prefetch_and_load_ptr(void **addr, intx prefetch_interval) {
+  Prefetch::read((void*)addr, prefetch_interval);
+  return *addr;
+}
+
+// Possibly the ugliest for loop the world has seen. C++ does not allow
+// multiple types in the declaration section of the for loop. In this case
+// we are only dealing with pointers and hence can cast them. It looks ugly
+// but macros are ugly and therefore it's fine to make things absurdly ugly.
+#define DO_JAVA_THREADS(LIST, X)                                                                                          \
+    for (JavaThread *MACRO_scan_interval = (JavaThread*)(uintptr_t)PrefetchScanIntervalInBytes,                           \
+             *MACRO_list = (JavaThread*)(LIST),                                                                           \
+             **MACRO_end = ((JavaThread**)((ThreadsList*)MACRO_list)->threads()) + ((ThreadsList*)MACRO_list)->length(),  \
+             **MACRO_current_p = (JavaThread**)((ThreadsList*)MACRO_list)->threads(),                                     \
+             *X = (JavaThread*)prefetch_and_load_ptr((void**)MACRO_current_p, (intx)MACRO_scan_interval);                 \
+         MACRO_current_p != MACRO_end;                                                                                    \
+         MACRO_current_p++,                                                                                               \
+             X = (JavaThread*)prefetch_and_load_ptr((void**)MACRO_current_p, (intx)MACRO_scan_interval))
+
 // All JavaThreads
-#define ALL_JAVA_THREADS(X) for (JavaThread* X = _thread_list; X; X = X->next())
+#define ALL_JAVA_THREADS(X) DO_JAVA_THREADS(get_smr_java_thread_list(), X)
 
 // All JavaThreads + all non-JavaThreads (i.e., every thread in the system)
 void Threads::threads_do(ThreadClosure* tc) {
@@ -3435,6 +3663,214 @@
                                          vmSymbols::void_method_signature(), CHECK);
 }
 
+// Safe Memory Reclamation (SMR) support:
+//
+
+// Acquire a stable ThreadsList.
+//
+ThreadsList *Threads::acquire_stable_list(Thread *self, bool is_ThreadsListSetter) {
+  assert(self != NULL, "sanity check");
+  // acquire_stable_list_nested_path() will grab the Threads_lock
+  // so let's make sure the ThreadsListHandle is in a safe place.
+  // ThreadsListSetter cannot make this check on this code path.
+  debug_only(if (!is_ThreadsListSetter && StrictSafepointChecks) self->check_for_valid_safepoint_state(/* potential_vm_operation */ false);)
+
+  if (self->get_threads_hazard_ptr() == NULL) {
+    // The typical case is first.
+    return acquire_stable_list_fast_path(self);
+  }
+
+  // The nested case is rare.
+  return acquire_stable_list_nested_path(self);
+}
+
+// Fast path (and lock free) way to acquire a stable ThreadsList.
+//
+ThreadsList *Threads::acquire_stable_list_fast_path(Thread *self) {
+  assert(self != NULL, "sanity check");
+  assert(self->get_threads_hazard_ptr() == NULL, "sanity check");
+  assert(self->get_nested_threads_hazard_ptr() == NULL,
+         "cannot have a nested hazard ptr with a NULL regular hazard ptr");
+
+  ThreadsList* threads;
+
+  // Stable recording of a hazard ptr for SMR. This code does not use
+  // locks so its use of the _smr_java_thread_list & _threads_hazard_ptr
+  // fields is racy relative to code that uses those fields with locks.
+  // OrderAccess and Atomic functions are used to deal with those races.
+  //
+  while (true) {
+    threads = get_smr_java_thread_list();
+
+    // Publish a tagged hazard ptr to denote that the hazard ptr is not
+    // yet verified as being stable. Due to the fence after the hazard
+    // ptr write, it will be sequentially consistent w.r.t. the
+    // sequentially consistent writes of the ThreadsList, even on
+    // non-multiple copy atomic machines where stores can be observed
+    // in different order from different observer threads.
+    ThreadsList* unverified_threads = Thread::tag_hazard_ptr(threads);
+    self->set_threads_hazard_ptr(unverified_threads);
+
+    // If _smr_java_thread_list has changed, we have lost a race with
+    // Threads::add() or Threads::remove() and have to try again.
+    if (get_smr_java_thread_list() != threads) {
+      continue;
+    }
+
+    // We try to remove the tag which will verify the hazard ptr as
+    // being stable. This exchange can race with a scanning thread
+    // which might invalidate the tagged hazard ptr to keep it from
+    // being followed to access JavaThread ptrs. If we lose the race,
+    // we simply retry. If we win the race, then the stable hazard
+    // ptr is officially published.
+    if (self->cmpxchg_threads_hazard_ptr(threads, unverified_threads) == unverified_threads) {
+      break;
+    }
+  }
+
+  // A stable hazard ptr has been published letting other threads know
+  // that the ThreadsList and the JavaThreads reachable from this list
+  // are protected and hence they should not be deleted until everyone
+  // agrees it is safe to do so.
+
+  return threads;
+}
+
+// Acquire a nested stable ThreadsList; this is rare so it uses
+// Threads_lock.
+//
+ThreadsList *Threads::acquire_stable_list_nested_path(Thread *self) {
+  assert(self != NULL, "sanity check");
+  assert(self->get_threads_hazard_ptr() != NULL,
+         "cannot have a NULL regular hazard ptr when acquiring a nested hazard ptr");
+
+  // The thread already has a hazard ptr (ThreadsList ref) so we need
+  // to create a nested ThreadsListHandle with the current ThreadsList
+  // since it might be different than our current hazard ptr. The need
+  // for a nested ThreadsListHandle is rare so we do this while holding
+  // the Threads_lock so we don't race with the scanning code; the code
+  // is so much simpler this way.
+
+  NestedThreadsList* node;
+  {
+    // Only grab the Threads_lock if we don't already own it.
+    MutexLockerEx ml(Threads_lock->owned_by_self() ? NULL : Threads_lock);
+    node = new NestedThreadsList(get_smr_java_thread_list());
+    // We insert at the front of the list to match up with the delete
+    // in release_stable_list().
+    node->set_next(self->get_nested_threads_hazard_ptr());
+    self->set_nested_threads_hazard_ptr(node);
+    if (EnableThreadSMRStatistics) {
+      self->inc_nested_threads_hazard_ptr_cnt();
+      if (self->nested_threads_hazard_ptr_cnt() > _smr_nested_thread_list_max) {
+        _smr_nested_thread_list_max = self->nested_threads_hazard_ptr_cnt();
+      }
+    }
+  }
+  log_debug(thread, smr)("tid=" UINTX_FORMAT ": Threads::acquire_stable_list: add NestedThreadsList node containing ThreadsList=" INTPTR_FORMAT, os::current_thread_id(), p2i(node->t_list()));
+
+  return node->t_list();
+}
+
+// Release a stable ThreadsList.
+//
+void Threads::release_stable_list(Thread *self) {
+  assert(self != NULL, "sanity check");
+  // release_stable_list_nested_path() will grab the Threads_lock
+  // so let's make sure the ThreadsListHandle is in a safe place.
+  debug_only(if (StrictSafepointChecks) self->check_for_valid_safepoint_state(/* potential_vm_operation */ false);)
+
+  if (self->get_nested_threads_hazard_ptr() == NULL) {
+    // The typical case is first.
+    release_stable_list_fast_path(self);
+    return;
+  }
+
+  // The nested case is rare.
+  release_stable_list_nested_path(self);
+}
+
+// Fast path way to release a stable ThreadsList. The release portion
+// is lock-free, but the wake up portion is not.
+//
+void Threads::release_stable_list_fast_path(Thread *self) {
+  assert(self != NULL, "sanity check");
+  assert(self->get_threads_hazard_ptr() != NULL, "sanity check");
+  assert(self->get_nested_threads_hazard_ptr() == NULL,
+         "cannot have a nested hazard ptr when releasing a regular hazard ptr");
+
+  // After releasing the hazard ptr, other threads may go ahead and
+  // free up some memory temporarily used by a ThreadsList snapshot.
+  self->set_threads_hazard_ptr(NULL);
+
+  // We use double-check locking to reduce traffic on the system
+  // wide smr_delete_lock.
+  if (Threads::smr_delete_notify()) {
+    // An exiting thread might be waiting in smr_delete(); we need to
+    // check with smr_delete_lock to be sure.
+    release_stable_list_wake_up((char *) "regular hazard ptr");
+  }
+}
+
+// Release a nested stable ThreadsList; this is rare so it uses
+// Threads_lock.
+//
+void Threads::release_stable_list_nested_path(Thread *self) {
+  assert(self != NULL, "sanity check");
+  assert(self->get_nested_threads_hazard_ptr() != NULL, "sanity check");
+  assert(self->get_threads_hazard_ptr() != NULL,
+         "must have a regular hazard ptr to have nested hazard ptrs");
+
+  // We have a nested ThreadsListHandle so we have to release it first.
+  // The need for a nested ThreadsListHandle is rare so we do this while
+  // holding the Threads_lock so we don't race with the scanning code;
+  // the code is so much simpler this way.
+
+  NestedThreadsList *node;
+  {
+    // Only grab the Threads_lock if we don't already own it.
+    MutexLockerEx ml(Threads_lock->owned_by_self() ? NULL : Threads_lock);
+    // We remove from the front of the list to match up with the insert
+    // in acquire_stable_list().
+    node = self->get_nested_threads_hazard_ptr();
+    self->set_nested_threads_hazard_ptr(node->next());
+    if (EnableThreadSMRStatistics) {
+      self->dec_nested_threads_hazard_ptr_cnt();
+    }
+  }
+
+  // An exiting thread might be waiting in smr_delete(); we need to
+  // check with smr_delete_lock to be sure.
+  release_stable_list_wake_up((char *) "nested hazard ptr");
+
+  log_debug(thread, smr)("tid=" UINTX_FORMAT ": Threads::release_stable_list: delete NestedThreadsList node containing ThreadsList=" INTPTR_FORMAT, os::current_thread_id(), p2i(node->t_list()));
+
+  delete node;
+}
+
+// Wake up portion of the release stable ThreadsList protocol;
+// uses the smr_delete_lock().
+//
+void Threads::release_stable_list_wake_up(char *log_str) {
+  assert(log_str != NULL, "sanity check");
+
+  // Note: smr_delete_lock is held in smr_delete() for the entire
+  // hazard ptr search so that we do not lose this notify() if
+  // the exiting thread has to wait. That code path also holds
+  // Threads_lock (which was grabbed before smr_delete_lock) so that
+  // threads_do() can be called. This means the system can't start a
+  // safepoint which means this thread can't take too long to get to
+  // a safepoint because of being blocked on smr_delete_lock.
+  //
+  MonitorLockerEx ml(Threads::smr_delete_lock(), Monitor::_no_safepoint_check_flag);
+  if (Threads::smr_delete_notify()) {
+    // Notify any exiting JavaThreads that are waiting in smr_delete()
+    // that we've released a ThreadsList.
+    ml.notify_all();
+    log_debug(thread, smr)("tid=" UINTX_FORMAT ": Threads::release_stable_list notified %s", os::current_thread_id(), log_str);
+  }
+}
+
 void Threads::initialize_java_lang_classes(JavaThread* main_thread, TRAPS) {
   TraceTime timer("Initialize java.lang classes", TRACETIME_LOG(Info, startuptime));
 
@@ -3616,7 +4052,7 @@
   if (!main_thread->set_as_starting_thread()) {
     vm_shutdown_during_initialization(
                                       "Failed necessary internal allocation. Out of swap space");
-    delete main_thread;
+    main_thread->smr_delete();
     *canTryAgain = false; // don't let caller call JNI_CreateJavaVM again
     return JNI_ENOMEM;
   }
@@ -3631,7 +4067,7 @@
   // Initialize global modules
   jint status = init_globals();
   if (status != JNI_OK) {
-    delete main_thread;
+    main_thread->smr_delete();
     *canTryAgain = false; // don't let caller call JNI_CreateJavaVM again
     return status;
   }
@@ -4037,23 +4473,6 @@
   }
 }
 
-JavaThread* Threads::find_java_thread_from_java_tid(jlong java_tid) {
-  assert(Threads_lock->owned_by_self(), "Must hold Threads_lock");
-
-  JavaThread* java_thread = NULL;
-  // Sequential search for now.  Need to do better optimization later.
-  for (JavaThread* thread = Threads::first(); thread != NULL; thread = thread->next()) {
-    oop tobj = thread->threadObj();
-    if (!thread->is_exiting() &&
-        tobj != NULL &&
-        java_tid == java_lang_Thread::thread_id(tobj)) {
-      java_thread = thread;
-      break;
-    }
-  }
-  return java_thread;
-}
-
 
 // Last thread running calls java.lang.Shutdown.shutdown()
 void JavaThread::invoke_shutdown_hooks() {
@@ -4179,6 +4598,11 @@
 
   notify_vm_shutdown();
 
+  // We are after VM_Exit::set_vm_exited() so we can't call
+  // thread->smr_delete() or we will block on the Threads_lock.
+  // Deleting the shutdown thread here is safe because another
+  // JavaThread cannot have an active ThreadsListHandle for
+  // this JavaThread.
   delete thread;
 
 #if INCLUDE_JVMCI
@@ -4212,6 +4636,501 @@
   return JNI_FALSE;
 }
 
+// Hash table of pointers found by a scan. Used for collecting hazard
+// pointers (ThreadsList references). Also used for collecting JavaThreads
+// that are indirectly referenced by hazard ptrs. An instance of this
+// class only contains one type of pointer.
+//
+class ThreadScanHashtable : public CHeapObj<mtThread> {
+ private:
+  static bool ptr_equals(void * const& s1, void * const& s2) {
+    return s1 == s2;
+  }
+
+  static unsigned int ptr_hash(void * const& s1) {
+    // 2654435761 = 2^32 * Phi (golden ratio)
+    return (unsigned int)(((uint32_t)(uintptr_t)s1) * 2654435761u);
+  }
+
+  int _table_size;
+  // ResourceHashtable SIZE is specified at compile time so our
+  // dynamic _table_size is unused for now; 1031 is the first prime
+  // after 1024.
+  typedef ResourceHashtable<void *, int, &ThreadScanHashtable::ptr_hash,
+                            &ThreadScanHashtable::ptr_equals, 1031,
+                            ResourceObj::C_HEAP, mtThread> PtrTable;
+  PtrTable * _ptrs;
+
+ public:
+  // ResourceHashtable is passed to various functions and populated in
+  // different places so we allocate it using C_HEAP to make it immune
+  // from any ResourceMarks that happen to be in the code paths.
+  ThreadScanHashtable(int table_size) : _table_size(table_size), _ptrs(new (ResourceObj::C_HEAP, mtThread) PtrTable()) {}
+
+  ~ThreadScanHashtable() { delete _ptrs; }
+
+  bool has_entry(void *pointer) {
+    int *val_ptr = _ptrs->get(pointer);
+    return val_ptr != NULL && *val_ptr == 1;
+  }
+
+  void add_entry(void *pointer) {
+    _ptrs->put(pointer, 1);
+  }
+};
+
+// Closure to gather JavaThreads indirectly referenced by hazard ptrs
+// (ThreadsList references) into a hash table. This closure handles part 2
+// of the dance - adding all the JavaThreads referenced by the hazard
+// pointer (ThreadsList reference) to the hash table.
+//
+class AddThreadHazardPointerThreadClosure : public ThreadClosure {
+ private:
+  ThreadScanHashtable *_table;
+
+ public:
+  AddThreadHazardPointerThreadClosure(ThreadScanHashtable *table) : _table(table) {}
+
+  virtual void do_thread(Thread *thread) {
+    if (!_table->has_entry((void*)thread)) {
+      // The same JavaThread might be on more than one ThreadsList or
+      // more than one thread might be using the same ThreadsList. In
+      // either case, we only need a single entry for a JavaThread.
+      _table->add_entry((void*)thread);
+    }
+  }
+};
+
+// Closure to gather JavaThreads indirectly referenced by hazard ptrs
+// (ThreadsList references) into a hash table. This closure handles part 1
+// of the dance - hazard ptr chain walking and dispatch to another
+// closure.
+//
+class ScanHazardPtrGatherProtectedThreadsClosure : public ThreadClosure {
+ private:
+  ThreadScanHashtable *_table;
+ public:
+  ScanHazardPtrGatherProtectedThreadsClosure(ThreadScanHashtable *table) : _table(table) {}
+
+  virtual void do_thread(Thread *thread) {
+    assert_locked_or_safepoint(Threads_lock);
+
+    if (thread == NULL) return;
+
+    // This code races with Threads::acquire_stable_list() which is
+    // lock-free so we have to handle some special situations.
+    //
+    ThreadsList *current_list = NULL;
+    while (true) {
+      current_list = thread->get_threads_hazard_ptr();
+      // No hazard ptr so nothing more to do.
+      if (current_list == NULL) {
+        assert(thread->get_nested_threads_hazard_ptr() == NULL,
+               "cannot have a nested hazard ptr with a NULL regular hazard ptr");
+        return;
+      }
+
+      // If the hazard ptr is verified as stable (since it is not tagged),
+      // then it is safe to use.
+      if (!Thread::is_hazard_ptr_tagged(current_list)) break;
+
+      // The hazard ptr is tagged as not yet verified as being stable
+      // so we are racing with acquire_stable_list(). This exchange
+      // attempts to invalidate the hazard ptr. If we win the race,
+      // then we can ignore this unstable hazard ptr and the other
+      // thread will retry the attempt to publish a stable hazard ptr.
+      // If we lose the race, then we retry our attempt to look at the
+      // hazard ptr.
+      if (thread->cmpxchg_threads_hazard_ptr(NULL, current_list) == current_list) return;
+    }
+
+    // The current JavaThread has a hazard ptr (ThreadsList reference)
+    // which might be _smr_java_thread_list or it might be an older
+    // ThreadsList that has been removed but not freed. In either case,
+    // the hazard ptr is protecting all the JavaThreads on that
+    // ThreadsList.
+    AddThreadHazardPointerThreadClosure add_cl(_table);
+    current_list->threads_do(&add_cl);
+
+    // Any NestedThreadsLists are also protecting JavaThreads so
+    // gather those also; the ThreadsLists may be different.
+    for (NestedThreadsList* node = thread->get_nested_threads_hazard_ptr();
+         node != NULL; node = node->next()) {
+      node->t_list()->threads_do(&add_cl);
+    }
+  }
+};
+
+// Closure to print JavaThreads that have a hazard ptr (ThreadsList
+// reference) that contains an indirect reference to a specific JavaThread.
+//
+class ScanHazardPtrPrintMatchingThreadsClosure : public ThreadClosure {
+ private:
+  JavaThread *_thread;
+ public:
+  ScanHazardPtrPrintMatchingThreadsClosure(JavaThread *thread) : _thread(thread) {}
+
+  virtual void do_thread(Thread *thread) {
+    assert_locked_or_safepoint(Threads_lock);
+
+    if (thread == NULL) return;
+    ThreadsList *current_list = thread->get_threads_hazard_ptr();
+    if (current_list == NULL) {
+      assert(thread->get_nested_threads_hazard_ptr() == NULL,
+             "cannot have a nested hazard ptr with a NULL regular hazard ptr");
+      return;
+    }
+    // If the hazard ptr is unverified, then ignore it.
+    if (Thread::is_hazard_ptr_tagged(current_list)) return;
+
+    // The current JavaThread has a hazard ptr (ThreadsList reference)
+    // which might be _smr_java_thread_list or it might be an older
+    // ThreadsList that has been removed but not freed. In either case,
+    // the hazard ptr is protecting all the JavaThreads on that
+    // ThreadsList, but we only care about matching a specific JavaThread.
+    DO_JAVA_THREADS(current_list, p) {
+      if (p == _thread) {
+        log_debug(thread, smr)("tid=" UINTX_FORMAT ": Threads::smr_delete: thread1=" INTPTR_FORMAT " has a hazard pointer for thread2=" INTPTR_FORMAT, os::current_thread_id(), p2i(thread), p2i(_thread));
+        break;
+      }
+    }
+
+    // Any NestedThreadsLists are also protecting JavaThreads so
+    // check those also; the ThreadsLists may be different.
+    for (NestedThreadsList* node = thread->get_nested_threads_hazard_ptr();
+         node != NULL; node = node->next()) {
+      DO_JAVA_THREADS(node->t_list(), p) {
+        if (p == _thread) {
+          log_debug(thread, smr)("tid=" UINTX_FORMAT ": Threads::smr_delete: thread1=" INTPTR_FORMAT " has a nested hazard pointer for thread2=" INTPTR_FORMAT, os::current_thread_id(), p2i(thread), p2i(_thread));
+          return;
+        }
+      }
+    }
+  }
+};
+
+// Return true if the specified JavaThread is protected by a hazard
+// pointer (ThreadsList reference). Otherwise, returns false.
+//
+bool Threads::is_a_protected_JavaThread(JavaThread *thread) {
+  assert_locked_or_safepoint(Threads_lock);
+
+  // Hash table size should be first power of two higher than twice
+  // the length of the Threads list.
+  int hash_table_size = MIN2(_number_of_threads, 32) << 1;
+  hash_table_size--;
+  hash_table_size |= hash_table_size >> 1;
+  hash_table_size |= hash_table_size >> 2;
+  hash_table_size |= hash_table_size >> 4;
+  hash_table_size |= hash_table_size >> 8;
+  hash_table_size |= hash_table_size >> 16;
+  hash_table_size++;
+
+  // Gather a hash table of the JavaThreads indirectly referenced by
+  // hazard ptrs.
+  ThreadScanHashtable *scan_table = new ThreadScanHashtable(hash_table_size);
+  ScanHazardPtrGatherProtectedThreadsClosure scan_cl(scan_table);
+  Threads::threads_do(&scan_cl);
+
+  bool thread_is_protected = false;
+  if (scan_table->has_entry((void*)thread)) {
+    thread_is_protected = true;
+  }
+  delete scan_table;
+  return thread_is_protected;
+}
+
+// Safely delete a JavaThread when it is no longer in use by a
+// ThreadsListHandle.
+//
+void Threads::smr_delete(JavaThread *thread) {
+  assert(!Threads_lock->owned_by_self(), "sanity");
+
+  bool has_logged_once = false;
+  elapsedTimer timer;
+  if (EnableThreadSMRStatistics) {
+    timer.start();
+  }
+
+  while (true) {
+    {
+      // No safepoint check because this JavaThread is not on the
+      // Threads list.
+      MutexLockerEx ml(Threads_lock, Mutex::_no_safepoint_check_flag);
+      // Cannot use a MonitorLockerEx helper here because we have
+      // to drop the Threads_lock first if we wait.
+      Threads::smr_delete_lock()->lock_without_safepoint_check();
+      // Set the smr_delete_notify flag after we grab smr_delete_lock
+      // and before we scan hazard ptrs because we're doing
+      // double-check locking in release_stable_list().
+      Threads::set_smr_delete_notify();
+
+      if (!is_a_protected_JavaThread(thread)) {
+        // This is the common case.
+        Threads::clear_smr_delete_notify();
+        Threads::smr_delete_lock()->unlock();
+        break;
+      }
+      if (!has_logged_once) {
+        has_logged_once = true;
+        log_debug(thread, smr)("tid=" UINTX_FORMAT ": Threads::smr_delete: thread=" INTPTR_FORMAT " is not deleted.", os::current_thread_id(), p2i(thread));
+        if (log_is_enabled(Debug, os, thread)) {
+          ScanHazardPtrPrintMatchingThreadsClosure scan_cl(thread);
+          Threads::threads_do(&scan_cl);
+        }
+      }
+    } // We have to drop the Threads_lock to wait or delete the thread
+
+    if (EnableThreadSMRStatistics) {
+      _smr_delete_lock_wait_cnt++;
+      if (_smr_delete_lock_wait_cnt > _smr_delete_lock_wait_max) {
+        _smr_delete_lock_wait_max = _smr_delete_lock_wait_cnt;
+      }
+    }
+    // Wait for a release_stable_list() call before we check again. No
+    // safepoint check, no timeout, and not as suspend equivalent flag
+    // because this JavaThread is not on the Threads list.
+    Threads::smr_delete_lock()->wait(Mutex::_no_safepoint_check_flag, 0,
+                                     !Mutex::_as_suspend_equivalent_flag);
+    if (EnableThreadSMRStatistics) {
+      _smr_delete_lock_wait_cnt--;
+    }
+
+    Threads::clear_smr_delete_notify();
+    Threads::smr_delete_lock()->unlock();
+    // Retry the whole scenario.
+  }
+
+  if (ThreadLocalHandshakes) {
+    // The thread is about to be deleted so cancel any handshake.
+    thread->cancel_handshake();
+  }
+
+  delete thread;
+  if (EnableThreadSMRStatistics) {
+    timer.stop();
+    uint millis = (uint)timer.milliseconds();
+    Threads::inc_smr_deleted_thread_cnt();
+    Threads::add_smr_deleted_thread_times(millis);
+    Threads::update_smr_deleted_thread_time_max(millis);
+  }
+
+  log_debug(thread, smr)("tid=" UINTX_FORMAT ": Threads::smr_delete: thread=" INTPTR_FORMAT " is deleted.", os::current_thread_id(), p2i(thread));
+}
+
+bool Threads::smr_delete_notify() {
+  // Use load_acquire() in order to see any updates to _smr_delete_notify
+  // earlier than when smr_delete_lock is grabbed.
+  return (OrderAccess::load_acquire(&_smr_delete_notify) != 0);
+}
+
+// set_smr_delete_notify() and clear_smr_delete_notify() are called
+// under the protection of the smr_delete_lock, but we also use an
+// Atomic operation to ensure the memory update is seen earlier than
+// when the smr_delete_lock is dropped.
+//
+void Threads::set_smr_delete_notify() {
+  Atomic::inc(&_smr_delete_notify);
+}
+
+void Threads::clear_smr_delete_notify() {
+  Atomic::dec(&_smr_delete_notify);
+}
+
+// Closure to gather hazard ptrs (ThreadsList references) into a hash table.
+//
+class ScanHazardPtrGatherThreadsListClosure : public ThreadClosure {
+ private:
+  ThreadScanHashtable *_table;
+ public:
+  ScanHazardPtrGatherThreadsListClosure(ThreadScanHashtable *table) : _table(table) {}
+
+  virtual void do_thread(Thread* thread) {
+    assert_locked_or_safepoint(Threads_lock);
+
+    if (thread == NULL) return;
+    ThreadsList *threads = thread->get_threads_hazard_ptr();
+    if (threads == NULL) {
+      assert(thread->get_nested_threads_hazard_ptr() == NULL,
+             "cannot have a nested hazard ptr with a NULL regular hazard ptr");
+      return;
+    }
+    // In this closure we always ignore the tag that might mark this
+    // hazard ptr as not yet verified. If we happen to catch an
+    // unverified hazard ptr that is subsequently discarded (not
+    // published), then the only side effect is that we might keep a
+    // to-be-deleted ThreadsList alive a little longer.
+    threads = Thread::untag_hazard_ptr(threads);
+    if (!_table->has_entry((void*)threads)) {
+      _table->add_entry((void*)threads);
+    }
+
+    // Any NestedThreadsLists are also protecting JavaThreads so
+    // gather those also; the ThreadsLists may be different.
+    for (NestedThreadsList* node = thread->get_nested_threads_hazard_ptr();
+         node != NULL; node = node->next()) {
+      threads = node->t_list();
+      if (!_table->has_entry((void*)threads)) {
+        _table->add_entry((void*)threads);
+      }
+    }
+  }
+};
+
+// Safely free a ThreadsList after a Threads::add() or Threads::remove().
+// The specified ThreadsList may not get deleted during this call if it
+// is still in-use (referenced by a hazard ptr). Other ThreadsLists
+// in the chain may get deleted by this call if they are no longer in-use.
+void Threads::smr_free_list(ThreadsList* threads) {
+  assert_locked_or_safepoint(Threads_lock);
+
+  threads->set_next_list(_smr_to_delete_list);
+  _smr_to_delete_list = threads;
+  if (EnableThreadSMRStatistics) {
+    _smr_to_delete_list_cnt++;
+    if (_smr_to_delete_list_cnt > _smr_to_delete_list_max) {
+      _smr_to_delete_list_max = _smr_to_delete_list_cnt;
+    }
+  }
+
+  // Hash table size should be first power of two higher than twice the length of the ThreadsList
+  int hash_table_size = MIN2(_number_of_threads, 32) << 1;
+  hash_table_size--;
+  hash_table_size |= hash_table_size >> 1;
+  hash_table_size |= hash_table_size >> 2;
+  hash_table_size |= hash_table_size >> 4;
+  hash_table_size |= hash_table_size >> 8;
+  hash_table_size |= hash_table_size >> 16;
+  hash_table_size++;
+
+  // Gather a hash table of the current hazard ptrs:
+  ThreadScanHashtable *scan_table = new ThreadScanHashtable(hash_table_size);
+  ScanHazardPtrGatherThreadsListClosure scan_cl(scan_table);
+  Threads::threads_do(&scan_cl);
+
+  // Walk through the linked list of pending freeable ThreadsLists
+  // and free the ones that are not referenced from hazard ptrs.
+  ThreadsList* current = _smr_to_delete_list;
+  ThreadsList* prev = NULL;
+  ThreadsList* next = NULL;
+  bool threads_is_freed = false;
+  while (current != NULL) {
+    next = current->next_list();
+    if (!scan_table->has_entry((void*)current)) {
+      // This ThreadsList is not referenced by a hazard ptr.
+      if (prev != NULL) {
+        prev->set_next_list(next);
+      }
+      if (_smr_to_delete_list == current) {
+        _smr_to_delete_list = next;
+      }
+
+      log_debug(thread, smr)("tid=" UINTX_FORMAT ": Threads::smr_free_list: threads=" INTPTR_FORMAT " is freed.", os::current_thread_id(), p2i(current));
+      if (current == threads) threads_is_freed = true;
+      delete current;
+      if (EnableThreadSMRStatistics) {
+        _smr_java_thread_list_free_cnt++;
+        _smr_to_delete_list_cnt--;
+      }
+    } else {
+      prev = current;
+    }
+    current = next;
+  }
+
+  if (!threads_is_freed) {
+    // Only report "is not freed" on the original call to
+    // smr_free_list() for this ThreadsList.
+    log_debug(thread, smr)("tid=" UINTX_FORMAT ": Threads::smr_free_list: threads=" INTPTR_FORMAT " is not freed.", os::current_thread_id(), p2i(threads));
+  }
+
+  delete scan_table;
+}
+
+// Remove a JavaThread from a ThreadsList. The returned ThreadsList is a
+// new copy of the specified ThreadsList with the specified JavaThread
+// removed.
+ThreadsList *ThreadsList::remove_thread(ThreadsList* list, JavaThread* java_thread) {
+  assert(list->_length > 0, "sanity");
+
+  uint i = 0;
+  DO_JAVA_THREADS(list, current) {
+    if (current == java_thread) {
+      break;
+    }
+    i++;
+  }
+  assert(i < list->_length, "did not find JavaThread on the list");
+  const uint index = i;
+  const uint new_length = list->_length - 1;
+  const uint head_length = index;
+  const uint tail_length = (new_length >= index) ? (new_length - index) : 0;
+  ThreadsList *const new_list = new ThreadsList(new_length);
+
+  if (head_length > 0) {
+    Copy::disjoint_words((HeapWord*)list->_threads, (HeapWord*)new_list->_threads, head_length);
+  }
+  if (tail_length > 0) {
+    Copy::disjoint_words((HeapWord*)list->_threads + index + 1, (HeapWord*)new_list->_threads + index, tail_length);
+  }
+
+  return new_list;
+}
+
+// Add a JavaThread to a ThreadsList. The returned ThreadsList is a
+// new copy of the specified ThreadsList with the specified JavaThread
+// appended to the end.
+ThreadsList *ThreadsList::add_thread(ThreadsList *list, JavaThread *java_thread) {
+  const uint index = list->_length;
+  const uint new_length = index + 1;
+  const uint head_length = index;
+  ThreadsList *const new_list = new ThreadsList(new_length);
+
+  if (head_length > 0) {
+    Copy::disjoint_words((HeapWord*)list->_threads, (HeapWord*)new_list->_threads, head_length);
+  }
+  *(JavaThread**)(new_list->_threads + index) = java_thread;
+
+  return new_list;
+}
+
+int ThreadsList::find_index_of_JavaThread(JavaThread *target) {
+  if (target == NULL) {
+    return -1;
+  }
+  for (uint i = 0; i < length(); i++) {
+    if (target == thread_at(i)) {
+      return (int)i;
+    }
+  }
+  return -1;
+}
+
+JavaThread* ThreadsList::find_JavaThread_from_java_tid(jlong java_tid) const {
+  DO_JAVA_THREADS(this, thread) {
+    oop tobj = thread->threadObj();
+    // Ignore the thread if it hasn't run yet, has exited
+    // or is starting to exit.
+    if (tobj != NULL && !thread->is_exiting() &&
+        java_tid == java_lang_Thread::thread_id(tobj)) {
+      // found a match
+      return thread;
+    }
+  }
+  return NULL;
+}
+
+bool ThreadsList::includes(const JavaThread * const p) const {
+  if (p == NULL) {
+    return false;
+  }
+  DO_JAVA_THREADS(this, q) {
+    if (q == p) {
+      return true;
+    }
+  }
+  return false;
+}
 
 void Threads::add(JavaThread* p, bool force_daemon) {
   // The threads lock must be owned at this point
@@ -4222,6 +5141,11 @@
   p->initialize_queues();
   p->set_next(_thread_list);
   _thread_list = p;
+
+  // Once a JavaThread is added to the Threads list, smr_delete() has
+  // to be used to delete it. Otherwise we can just delete it directly.
+  p->set_on_thread_list();
+
   _number_of_threads++;
   oop threadObj = p->threadObj();
   bool daemon = true;
@@ -4234,6 +5158,20 @@
 
   ThreadService::add_thread(p, daemon);
 
+  // Maintain fast thread list
+  ThreadsList *new_list = ThreadsList::add_thread(get_smr_java_thread_list(), p);
+  if (EnableThreadSMRStatistics) {
+    _smr_java_thread_list_alloc_cnt++;
+    if (new_list->length() > _smr_java_thread_list_max) {
+      _smr_java_thread_list_max = new_list->length();
+    }
+  }
+  // Initial _smr_java_thread_list will not generate a "Threads::add" mesg.
+  log_debug(thread, smr)("tid=" UINTX_FORMAT ": Threads::add: new ThreadsList=" INTPTR_FORMAT, os::current_thread_id(), p2i(new_list));
+
+  ThreadsList *old_list = xchg_smr_java_thread_list(new_list);
+  smr_free_list(old_list);
+
   // Possible GC point.
   Events::log(p, "Thread added: " INTPTR_FORMAT, p2i(p));
 }
@@ -4247,7 +5185,20 @@
   // that we do not remove thread without safepoint code notice
   { MutexLocker ml(Threads_lock);
 
-    assert(includes(p), "p must be present");
+    assert(get_smr_java_thread_list()->includes(p), "p must be present");
+
+    // Maintain fast thread list
+    ThreadsList *new_list = ThreadsList::remove_thread(get_smr_java_thread_list(), p);
+    if (EnableThreadSMRStatistics) {
+      _smr_java_thread_list_alloc_cnt++;
+      // This list is smaller so no need to check for a "longest" update.
+    }
+
+    // Final _smr_java_thread_list will not generate a "Threads::remove" mesg.
+    log_debug(thread, smr)("tid=" UINTX_FORMAT ": Threads::remove: new ThreadsList=" INTPTR_FORMAT, os::current_thread_id(), p2i(new_list));
+
+    ThreadsList *old_list = xchg_smr_java_thread_list(new_list);
+    smr_free_list(old_list);
 
     JavaThread* current = _thread_list;
     JavaThread* prev    = NULL;
@@ -4262,6 +5213,7 @@
     } else {
       _thread_list = p->next();
     }
+
     _number_of_threads--;
     oop threadObj = p->threadObj();
     bool daemon = true;
@@ -4288,17 +5240,6 @@
   Events::log(p, "Thread exited: " INTPTR_FORMAT, p2i(p));
 }
 
-// Threads_lock must be held when this is called (or must be called during a safepoint)
-bool Threads::includes(JavaThread* p) {
-  assert(Threads_lock->is_locked(), "sanity check");
-  ALL_JAVA_THREADS(q) {
-    if (q == p) {
-      return true;
-    }
-  }
-  return false;
-}
-
 // Operations on the Threads list for GC.  These are not explicitly locked,
 // but the garbage collector must provide a safe context for them to run.
 // In particular, these things should never be called when the Threads_lock
@@ -4411,47 +5352,36 @@
 
 
 // Get count Java threads that are waiting to enter the specified monitor.
-GrowableArray<JavaThread*>* Threads::get_pending_threads(int count,
-                                                         address monitor,
-                                                         bool doLock) {
-  assert(doLock || SafepointSynchronize::is_at_safepoint(),
-         "must grab Threads_lock or be at safepoint");
+GrowableArray<JavaThread*>* Threads::get_pending_threads(ThreadsList * t_list,
+                                                         int count,
+                                                         address monitor) {
   GrowableArray<JavaThread*>* result = new GrowableArray<JavaThread*>(count);
 
   int i = 0;
-  {
-    MutexLockerEx ml(doLock ? Threads_lock : NULL);
-    ALL_JAVA_THREADS(p) {
-      if (!p->can_call_java()) continue;
-
-      address pending = (address)p->current_pending_monitor();
-      if (pending == monitor) {             // found a match
-        if (i < count) result->append(p);   // save the first count matches
-        i++;
-      }
+  DO_JAVA_THREADS(t_list, p) {
+    if (!p->can_call_java()) continue;
+
+    address pending = (address)p->current_pending_monitor();
+    if (pending == monitor) {             // found a match
+      if (i < count) result->append(p);   // save the first count matches
+      i++;
     }
   }
+
   return result;
 }
 
 
-JavaThread *Threads::owning_thread_from_monitor_owner(address owner,
-                                                      bool doLock) {
-  assert(doLock ||
-         Threads_lock->owned_by_self() ||
-         SafepointSynchronize::is_at_safepoint(),
-         "must grab Threads_lock or be at safepoint");
-
+JavaThread *Threads::owning_thread_from_monitor_owner(ThreadsList * t_list,
+                                                      address owner) {
   // NULL owner means not locked so we can skip the search
   if (owner == NULL) return NULL;
 
-  {
-    MutexLockerEx ml(doLock ? Threads_lock : NULL);
-    ALL_JAVA_THREADS(p) {
-      // first, see if owner is the address of a Java thread
-      if (owner == (address)p) return p;
-    }
-  }
+  DO_JAVA_THREADS(t_list, p) {
+    // first, see if owner is the address of a Java thread
+    if (owner == (address)p) return p;
+  }
+
   // Cannot assert on lack of success here since this function may be
   // used by code that is trying to report useful problem information
   // like deadlock detection.
@@ -4462,15 +5392,13 @@
   // Lock Word in the owning Java thread's stack.
   //
   JavaThread* the_owner = NULL;
-  {
-    MutexLockerEx ml(doLock ? Threads_lock : NULL);
-    ALL_JAVA_THREADS(q) {
-      if (q->is_lock_owned(owner)) {
-        the_owner = q;
-        break;
-      }
+  DO_JAVA_THREADS(t_list, q) {
+    if (q->is_lock_owned(owner)) {
+      the_owner = q;
+      break;
     }
   }
+
   // cannot assert on lack of success here; see above comment
   return the_owner;
 }
@@ -4495,6 +5423,9 @@
   }
 #endif // INCLUDE_SERVICES
 
+  print_smr_info_on(st);
+  st->cr();
+
   ALL_JAVA_THREADS(p) {
     ResourceMark rm;
     p->print_on(st);
@@ -4521,9 +5452,105 @@
     wt->print_on(st);
     st->cr();
   }
+
   st->flush();
 }
 
+// Log Threads class SMR info.
+void Threads::log_smr_statistics() {
+  LogTarget(Info, thread, smr) log;
+  if (log.is_enabled()) {
+    LogStream out(log);
+    print_smr_info_on(&out);
+  }
+}
+
+// Print Threads class SMR info.
+void Threads::print_smr_info_on(outputStream* st) {
+  // Only grab the Threads_lock if we don't already own it
+  // and if we are not reporting an error.
+  MutexLockerEx ml((Threads_lock->owned_by_self() || VMError::is_error_reported()) ? NULL : Threads_lock);
+
+  st->print_cr("Threads class SMR info:");
+  st->print_cr("_smr_java_thread_list=" INTPTR_FORMAT ", length=%u, "
+               "elements={", p2i(_smr_java_thread_list),
+               _smr_java_thread_list->length());
+  print_smr_info_elements_on(st, _smr_java_thread_list);
+  st->print_cr("}");
+  if (_smr_to_delete_list != NULL) {
+    st->print_cr("_smr_to_delete_list=" INTPTR_FORMAT ", length=%u, "
+                 "elements={", p2i(_smr_to_delete_list),
+                 _smr_to_delete_list->length());
+    print_smr_info_elements_on(st, _smr_to_delete_list);
+    st->print_cr("}");
+    for (ThreadsList *t_list = _smr_to_delete_list->next_list();
+         t_list != NULL; t_list = t_list->next_list()) {
+      st->print("next-> " INTPTR_FORMAT ", length=%u, "
+                "elements={", p2i(t_list), t_list->length());
+      print_smr_info_elements_on(st, t_list);
+      st->print_cr("}");
+    }
+  }
+  if (!EnableThreadSMRStatistics) {
+    return;
+  }
+  st->print_cr("_smr_java_thread_list_alloc_cnt=" UINT64_FORMAT ","
+               "_smr_java_thread_list_free_cnt=" UINT64_FORMAT ","
+               "_smr_java_thread_list_max=%u, "
+               "_smr_nested_thread_list_max=%u",
+               _smr_java_thread_list_alloc_cnt,
+               _smr_java_thread_list_free_cnt,
+               _smr_java_thread_list_max,
+               _smr_nested_thread_list_max);
+  if (_smr_tlh_cnt > 0) {
+    st->print_cr("_smr_tlh_cnt=%u"
+                 ", _smr_tlh_times=%u"
+                 ", avg_smr_tlh_time=%0.2f"
+                 ", _smr_tlh_time_max=%u",
+                 _smr_tlh_cnt, _smr_tlh_times,
+                 ((double) _smr_tlh_times / _smr_tlh_cnt),
+                 _smr_tlh_time_max);
+  }
+  if (_smr_deleted_thread_cnt > 0) {
+    st->print_cr("_smr_deleted_thread_cnt=%u"
+                 ", _smr_deleted_thread_times=%u"
+                 ", avg_smr_deleted_thread_time=%0.2f"
+                 ", _smr_deleted_thread_time_max=%u",
+                 _smr_deleted_thread_cnt, _smr_deleted_thread_times,
+                 ((double) _smr_deleted_thread_times / _smr_deleted_thread_cnt),
+                 _smr_deleted_thread_time_max);
+  }
+  st->print_cr("_smr_delete_lock_wait_cnt=%u, _smr_delete_lock_wait_max=%u",
+               _smr_delete_lock_wait_cnt, _smr_delete_lock_wait_max);
+  st->print_cr("_smr_to_delete_list_cnt=%u, _smr_to_delete_list_max=%u",
+               _smr_to_delete_list_cnt, _smr_to_delete_list_max);
+}
+
+// Print ThreadsList elements (4 per line).
+void Threads::print_smr_info_elements_on(outputStream* st,
+                                         ThreadsList* t_list) {
+  uint cnt = 0;
+  JavaThreadIterator jti(t_list);
+  for (JavaThread *jt = jti.first(); jt != NULL; jt = jti.next()) {
+    st->print(INTPTR_FORMAT, p2i(jt));
+    if (cnt < t_list->length() - 1) {
+      // Separate with comma or comma-space except for the last one.
+      if (((cnt + 1) % 4) == 0) {
+        // Four INTPTR_FORMAT fit on an 80 column line so end the
+        // current line with just a comma.
+        st->print_cr(",");
+      } else {
+        // Not the last one on the current line so use comma-space:
+        st->print(", ");
+      }
+    } else {
+      // Last one so just end the current line.
+      st->cr();
+    }
+    cnt++;
+  }
+}
+
 void Threads::print_on_error(Thread* this_thread, outputStream* st, Thread* current, char* buf,
                              int buflen, bool* found_current) {
   if (this_thread != NULL) {
@@ -4560,6 +5587,9 @@
 // memory (even in resource area), it might deadlock the error handler.
 void Threads::print_on_error(outputStream* st, Thread* current, char* buf,
                              int buflen) {
+  print_smr_info_on(st);
+  st->cr();
+
   bool found_current = false;
   st->print_cr("Java Threads: ( => current thread )");
   ALL_JAVA_THREADS(thread) {
@@ -4581,6 +5611,7 @@
     st->cr();
   }
   st->cr();
+
   st->print_cr("Threads with active compile tasks:");
   print_threads_compiling(st, buf, buflen);
 }
--- a/src/hotspot/share/runtime/thread.hpp	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/hotspot/share/runtime/thread.hpp	Mon Nov 27 17:04:45 2017 +0000
@@ -57,6 +57,8 @@
 #endif
 
 class ThreadSafepointState;
+class ThreadsList;
+class NestedThreadsList;
 
 class JvmtiThreadState;
 class JvmtiGetLoadedClassesClosure;
@@ -101,6 +103,7 @@
 //   - WatcherThread
 
 class Thread: public ThreadShadow {
+  friend class Threads;
   friend class VMStructs;
   friend class JVMCIVMStructs;
  private:
@@ -118,6 +121,47 @@
  protected:
   // Support for forcing alignment of thread objects for biased locking
   void*       _real_malloc_address;
+  // JavaThread lifecycle support:
+  friend class ScanHazardPtrGatherProtectedThreadsClosure;
+  friend class ScanHazardPtrGatherThreadsListClosure;
+  friend class ScanHazardPtrPrintMatchingThreadsClosure;
+  friend class ThreadsListHandle;
+  friend class ThreadsListSetter;
+  ThreadsList* volatile _threads_hazard_ptr;
+  ThreadsList*          cmpxchg_threads_hazard_ptr(ThreadsList* exchange_value, ThreadsList* compare_value);
+  ThreadsList*          get_threads_hazard_ptr();
+  void                  set_threads_hazard_ptr(ThreadsList* new_list);
+  static bool           is_hazard_ptr_tagged(ThreadsList* list) {
+    return (intptr_t(list) & intptr_t(1)) == intptr_t(1);
+  }
+  static ThreadsList*   tag_hazard_ptr(ThreadsList* list) {
+    return (ThreadsList*)(intptr_t(list) | intptr_t(1));
+  }
+  static ThreadsList*   untag_hazard_ptr(ThreadsList* list) {
+    return (ThreadsList*)(intptr_t(list) & ~intptr_t(1));
+  }
+  NestedThreadsList* _nested_threads_hazard_ptr;
+  NestedThreadsList* get_nested_threads_hazard_ptr() {
+    return _nested_threads_hazard_ptr;
+  }
+  void set_nested_threads_hazard_ptr(NestedThreadsList* value) {
+    assert(Threads_lock->owned_by_self(),
+           "must own Threads_lock for _nested_threads_hazard_ptr to be valid.");
+    _nested_threads_hazard_ptr = value;
+  }
+  // This field is enabled via -XX:+EnableThreadSMRStatistics:
+  uint _nested_threads_hazard_ptr_cnt;
+  void dec_nested_threads_hazard_ptr_cnt() {
+    assert(_nested_threads_hazard_ptr_cnt != 0, "mismatched {dec,inc}_nested_threads_hazard_ptr_cnt()");
+    _nested_threads_hazard_ptr_cnt--;
+  }
+  void inc_nested_threads_hazard_ptr_cnt() {
+    _nested_threads_hazard_ptr_cnt++;
+  }
+  uint nested_threads_hazard_ptr_cnt() {
+    return _nested_threads_hazard_ptr_cnt;
+  }
+
  public:
   void* operator new(size_t size) throw() { return allocate(size, true); }
   void* operator new(size_t size, const std::nothrow_t& nothrow_constant) throw() {
@@ -359,6 +403,9 @@
   static inline Thread* current_or_null_safe();
 
   // Common thread operations
+#ifdef ASSERT
+  static void check_for_dangling_thread_pointer(Thread *thread);
+#endif
   static void set_priority(Thread* thread, ThreadPriority priority);
   static ThreadPriority get_priority(const Thread* const thread);
   static void start(Thread* thread);
@@ -576,6 +623,7 @@
 
   // Printing
   virtual void print_on(outputStream* st) const;
+  virtual void print_nested_threads_hazard_ptrs_on(outputStream* st) const;
   void print() const { print_on(tty); }
   virtual void print_on_error(outputStream* st, char* buf, int buflen) const;
   void print_value_on(outputStream* st) const;
@@ -798,6 +846,7 @@
   friend class WhiteBox;
  private:
   JavaThread*    _next;                          // The next thread in the Threads list
+  bool           _on_thread_list;                // Is set when this JavaThread is added to the Threads list
   oop            _threadObj;                     // The Java level thread object
 
 #ifdef ASSERT
@@ -1125,15 +1174,23 @@
   void set_safepoint_state(ThreadSafepointState *state) { _safepoint_state = state; }
   bool is_at_poll_safepoint()                    { return _safepoint_state->is_at_poll_safepoint(); }
 
+  // JavaThread termination and lifecycle support:
+  void smr_delete();
+  bool on_thread_list() const { return _on_thread_list; }
+  void set_on_thread_list() { _on_thread_list = true; }
+
   // thread has called JavaThread::exit() or is terminated
-  bool is_exiting()                              { return _terminated == _thread_exiting || is_terminated(); }
+  bool is_exiting() const;
   // thread is terminated (no longer on the threads list); we compare
   // against the two non-terminated values so that a freed JavaThread
   // will also be considered terminated.
-  bool is_terminated()                           { return _terminated != _not_terminated && _terminated != _thread_exiting; }
-  void set_terminated(TerminatedTypes t)         { _terminated = t; }
+  bool check_is_terminated(TerminatedTypes l_terminated) const {
+    return l_terminated != _not_terminated && l_terminated != _thread_exiting;
+  }
+  bool is_terminated() const;
+  void set_terminated(TerminatedTypes t);
   // special for Threads::remove() which is static:
-  void set_terminated_value()                    { _terminated = _thread_terminated; }
+  void set_terminated_value();
   void block_if_vm_exited();
 
   bool doing_unsafe_access()                     { return _doing_unsafe_access; }
@@ -1220,6 +1277,9 @@
   // via the appropriate -XX options.
   bool wait_for_ext_suspend_completion(int count, int delay, uint32_t *bits);
 
+  // test for suspend - most (all?) of these should go away
+  bool is_thread_fully_suspended(bool wait_for_suspend, uint32_t *bits);
+
   inline void set_external_suspend();
   inline void clear_external_suspend();
 
@@ -2066,28 +2126,84 @@
 class Threads: AllStatic {
   friend class VMStructs;
  private:
-  static JavaThread* _thread_list;
-  static int         _number_of_threads;
-  static int         _number_of_non_daemon_threads;
-  static int         _return_code;
-  static int         _thread_claim_parity;
+  // Safe Memory Reclamation (SMR) support:
+  static Monitor*              _smr_delete_lock;
+  // The '_cnt', '_max' and '_times" fields are enabled via
+  // -XX:+EnableThreadSMRStatistics (see thread.cpp for a
+  // description about each field):
+  static uint                  _smr_delete_lock_wait_cnt;
+  static uint                  _smr_delete_lock_wait_max;
+  static volatile uint         _smr_delete_notify;
+  static volatile uint         _smr_deleted_thread_cnt;
+  static volatile uint         _smr_deleted_thread_time_max;
+  static volatile uint         _smr_deleted_thread_times;
+  static ThreadsList* volatile _smr_java_thread_list;
+  static ThreadsList*          get_smr_java_thread_list();
+  static ThreadsList*          xchg_smr_java_thread_list(ThreadsList* new_list);
+  static uint64_t              _smr_java_thread_list_alloc_cnt;
+  static uint64_t              _smr_java_thread_list_free_cnt;
+  static uint                  _smr_java_thread_list_max;
+  static uint                  _smr_nested_thread_list_max;
+  static volatile uint         _smr_tlh_cnt;
+  static volatile uint         _smr_tlh_time_max;
+  static volatile uint         _smr_tlh_times;
+  static ThreadsList*          _smr_to_delete_list;
+  static uint                  _smr_to_delete_list_cnt;
+  static uint                  _smr_to_delete_list_max;
+
+  static JavaThread*           _thread_list;
+  static int                   _number_of_threads;
+  static int                   _number_of_non_daemon_threads;
+  static int                   _return_code;
+  static int                   _thread_claim_parity;
 #ifdef ASSERT
-  static bool        _vm_complete;
+  static bool                  _vm_complete;
 #endif
 
   static void initialize_java_lang_classes(JavaThread* main_thread, TRAPS);
   static void initialize_jsr292_core_classes(TRAPS);
+
+  static void smr_free_list(ThreadsList* threads);
+
  public:
   // Thread management
   // force_daemon is a concession to JNI, where we may need to add a
   // thread to the thread list before allocating its thread object
   static void add(JavaThread* p, bool force_daemon = false);
   static void remove(JavaThread* p);
-  static bool includes(JavaThread* p);
-  static JavaThread* first()                     { return _thread_list; }
   static void threads_do(ThreadClosure* tc);
   static void possibly_parallel_threads_do(bool is_par, ThreadClosure* tc);
 
+  // SMR support:
+  static ThreadsList *acquire_stable_list(Thread *self, bool is_ThreadsListSetter);
+  static ThreadsList *acquire_stable_list_fast_path(Thread *self);
+  static ThreadsList *acquire_stable_list_nested_path(Thread *self);
+  static void release_stable_list(Thread *self);
+  static void release_stable_list_fast_path(Thread *self);
+  static void release_stable_list_nested_path(Thread *self);
+  static void release_stable_list_wake_up(char *log_str);
+  static bool is_a_protected_JavaThread(JavaThread *thread);
+  static bool is_a_protected_JavaThread_with_lock(JavaThread *thread) {
+    MutexLockerEx ml(Threads_lock->owned_by_self() ? NULL : Threads_lock);
+    return is_a_protected_JavaThread(thread);
+  }
+  static void smr_delete(JavaThread *thread);
+  // The coordination between Threads::release_stable_list() and
+  // Threads::smr_delete() uses the smr_delete_lock in order to
+  // reduce the traffic on the Threads_lock.
+  static Monitor* smr_delete_lock() { return _smr_delete_lock; }
+  // The smr_delete_notify flag is used for proper double-check
+  // locking in order to reduce the traffic on the smr_delete_lock.
+  static bool smr_delete_notify();
+  static void set_smr_delete_notify();
+  static void clear_smr_delete_notify();
+  static void inc_smr_deleted_thread_cnt();
+  static void update_smr_deleted_thread_time_max(uint new_value);
+  static void add_smr_deleted_thread_times(uint add_value);
+  static void inc_smr_tlh_cnt();
+  static void update_smr_tlh_time_max(uint new_value);
+  static void add_smr_tlh_times(uint add_value);
+
   // Initializes the vm and creates the vm thread
   static jint create_vm(JavaVMInitArgs* args, bool* canTryAgain);
   static void convert_vm_init_libraries_to_agents();
@@ -2148,7 +2264,10 @@
 
   // Verification
   static void verify();
+  static void log_smr_statistics();
   static void print_on(outputStream* st, bool print_stacks, bool internal_format, bool print_concurrent_locks);
+  static void print_smr_info_on(outputStream* st);
+  static void print_smr_info_elements_on(outputStream* st, ThreadsList* t_list);
   static void print(bool print_stacks, bool internal_format) {
     // this function is only used by debug.cpp
     print_on(tty, print_stacks, internal_format, false /* no concurrent lock printed */);
@@ -2158,17 +2277,13 @@
                              int buflen, bool* found_current);
   static void print_threads_compiling(outputStream* st, char* buf, int buflen);
 
-  // Get Java threads that are waiting to enter a monitor. If doLock
-  // is true, then Threads_lock is grabbed as needed. Otherwise, the
-  // VM needs to be at a safepoint.
-  static GrowableArray<JavaThread*>* get_pending_threads(int count,
-                                                         address monitor, bool doLock);
+  // Get Java threads that are waiting to enter a monitor.
+  static GrowableArray<JavaThread*>* get_pending_threads(ThreadsList * t_list,
+                                                         int count, address monitor);
 
-  // Get owning Java thread from the monitor's owner field. If doLock
-  // is true, then Threads_lock is grabbed as needed. Otherwise, the
-  // VM needs to be at a safepoint.
-  static JavaThread *owning_thread_from_monitor_owner(address owner,
-                                                      bool doLock);
+  // Get owning Java thread from the monitor's owner field.
+  static JavaThread *owning_thread_from_monitor_owner(ThreadsList * t_list,
+                                                      address owner);
 
   // Number of threads on the active threads list
   static int number_of_threads()                 { return _number_of_threads; }
@@ -2177,9 +2292,6 @@
 
   // Deoptimizes all frames tied to marked nmethods
   static void deoptimized_wrt_marked_nmethods();
-
-  static JavaThread* find_java_thread_from_java_tid(jlong java_tid);
-
 };
 
 
--- a/src/hotspot/share/runtime/thread.inline.hpp	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/hotspot/share/runtime/thread.inline.hpp	Mon Nov 27 17:04:45 2017 +0000
@@ -25,13 +25,10 @@
 #ifndef SHARE_VM_RUNTIME_THREAD_INLINE_HPP
 #define SHARE_VM_RUNTIME_THREAD_INLINE_HPP
 
-#define SHARE_VM_RUNTIME_THREAD_INLINE_HPP_SCOPE
-
 #include "runtime/atomic.hpp"
 #include "runtime/os.inline.hpp"
 #include "runtime/thread.hpp"
-
-#undef SHARE_VM_RUNTIME_THREAD_INLINE_HPP_SCOPE
+#include "runtime/threadSMR.hpp"
 
 inline void Thread::set_suspend_flag(SuspendFlags f) {
   assert(sizeof(jint) == sizeof(_suspend_flags), "size mismatch");
@@ -89,6 +86,18 @@
   return allocated_bytes;
 }
 
+inline ThreadsList* Thread::cmpxchg_threads_hazard_ptr(ThreadsList* exchange_value, ThreadsList* compare_value) {
+  return (ThreadsList*)Atomic::cmpxchg(exchange_value, &_threads_hazard_ptr, compare_value);
+}
+
+inline ThreadsList* Thread::get_threads_hazard_ptr() {
+  return (ThreadsList*)OrderAccess::load_acquire(&_threads_hazard_ptr);
+}
+
+inline void Thread::set_threads_hazard_ptr(ThreadsList* new_list) {
+  OrderAccess::release_store_fence(&_threads_hazard_ptr, new_list);
+}
+
 inline void JavaThread::set_ext_suspended() {
   set_suspend_flag (_ext_suspended);
 }
@@ -176,4 +185,83 @@
   return OrderAccess::load_acquire(polling_page_addr());
 }
 
+inline bool JavaThread::is_exiting() const {
+  // Use load-acquire so that setting of _terminated by
+  // JavaThread::exit() is seen more quickly.
+  TerminatedTypes l_terminated = (TerminatedTypes)
+      OrderAccess::load_acquire((volatile jint *) &_terminated);
+  return l_terminated == _thread_exiting || check_is_terminated(l_terminated);
+}
+
+inline bool JavaThread::is_terminated() const {
+  // Use load-acquire so that setting of _terminated by
+  // JavaThread::exit() is seen more quickly.
+  TerminatedTypes l_terminated = (TerminatedTypes)
+      OrderAccess::load_acquire((volatile jint *) &_terminated);
+  return check_is_terminated(l_terminated);
+}
+
+inline void JavaThread::set_terminated(TerminatedTypes t) {
+  // use release-store so the setting of _terminated is seen more quickly
+  OrderAccess::release_store((volatile jint *) &_terminated, (jint) t);
+}
+
+// special for Threads::remove() which is static:
+inline void JavaThread::set_terminated_value() {
+  // use release-store so the setting of _terminated is seen more quickly
+  OrderAccess::release_store((volatile jint *) &_terminated, (jint) _thread_terminated);
+}
+
+inline ThreadsList* Threads::get_smr_java_thread_list() {
+  return (ThreadsList*)OrderAccess::load_acquire(&_smr_java_thread_list);
+}
+
+inline ThreadsList* Threads::xchg_smr_java_thread_list(ThreadsList* new_list) {
+  return (ThreadsList*)Atomic::xchg(new_list, &_smr_java_thread_list);
+}
+
+inline void Threads::inc_smr_deleted_thread_cnt() {
+  Atomic::inc(&_smr_deleted_thread_cnt);
+}
+
+inline void Threads::update_smr_deleted_thread_time_max(uint new_value) {
+  while (true) {
+    uint cur_value = _smr_deleted_thread_time_max;
+    if (new_value <= cur_value) {
+      // No need to update max value so we're done.
+      break;
+    }
+    if (Atomic::cmpxchg(new_value, &_smr_deleted_thread_time_max, cur_value) == cur_value) {
+      // Updated max value so we're done. Otherwise try it all again.
+      break;
+    }
+  }
+}
+
+inline void Threads::add_smr_deleted_thread_times(uint add_value) {
+  Atomic::add(add_value, &_smr_deleted_thread_times);
+}
+
+inline void Threads::inc_smr_tlh_cnt() {
+  Atomic::inc(&_smr_tlh_cnt);
+}
+
+inline void Threads::update_smr_tlh_time_max(uint new_value) {
+  while (true) {
+    uint cur_value = _smr_tlh_time_max;
+    if (new_value <= cur_value) {
+      // No need to update max value so we're done.
+      break;
+    }
+    if (Atomic::cmpxchg(new_value, &_smr_tlh_time_max, cur_value) == cur_value) {
+      // Updated max value so we're done. Otherwise try it all again.
+      break;
+    }
+  }
+}
+
+inline void Threads::add_smr_tlh_times(uint add_value) {
+  Atomic::add(add_value, &_smr_tlh_times);
+}
+
 #endif // SHARE_VM_RUNTIME_THREAD_INLINE_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/runtime/threadSMR.cpp	Mon Nov 27 17:04:45 2017 +0000
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2017, 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.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "memory/allocation.inline.hpp"
+#include "runtime/thread.inline.hpp"
+#include "runtime/threadSMR.hpp"
+#include "services/threadService.hpp"
+
+// 'entries + 1' so we always have at least one entry.
+ThreadsList::ThreadsList(int entries) : _length(entries), _threads(NEW_C_HEAP_ARRAY(JavaThread*, entries + 1, mtThread)), _next_list(NULL) {
+  *(JavaThread**)(_threads + entries) = NULL;  // Make sure the extra entry is NULL.
+}
+
+ThreadsList::~ThreadsList() {
+  FREE_C_HEAP_ARRAY(JavaThread*, _threads);
+}
+
+ThreadsListSetter::~ThreadsListSetter() {
+  if (_target_needs_release) {
+    // The hazard ptr in the target needs to be released.
+    Threads::release_stable_list(_target);
+  }
+}
+
+void ThreadsListSetter::set() {
+  assert(_target->get_threads_hazard_ptr() == NULL, "hazard ptr should not already be set");
+  (void) Threads::acquire_stable_list(_target, /* is_ThreadsListSetter */ true);
+  _target_needs_release = true;
+}
+
+ThreadsListHandle::ThreadsListHandle(Thread *self) : _list(Threads::acquire_stable_list(self, /* is_ThreadsListSetter */ false)), _self(self) {
+  assert(self == Thread::current(), "sanity check");
+  if (EnableThreadSMRStatistics) {
+    _timer.start();
+  }
+}
+
+ThreadsListHandle::~ThreadsListHandle() {
+  Threads::release_stable_list(_self);
+  if (EnableThreadSMRStatistics) {
+    _timer.stop();
+    uint millis = (uint)_timer.milliseconds();
+    Threads::inc_smr_tlh_cnt();
+    Threads::add_smr_tlh_times(millis);
+    Threads::update_smr_tlh_time_max(millis);
+  }
+}
+
+// Convert an internal thread reference to a JavaThread found on the
+// associated ThreadsList. This ThreadsListHandle "protects" the
+// returned JavaThread *.
+//
+// If thread_oop_p is not NULL, then the caller wants to use the oop
+// after this call so the oop is returned. On success, *jt_pp is set
+// to the converted JavaThread * and true is returned. On error,
+// returns false.
+//
+bool ThreadsListHandle::cv_internal_thread_to_JavaThread(jobject jthread,
+                                                         JavaThread ** jt_pp,
+                                                         oop * thread_oop_p) {
+  assert(this->list() != NULL, "must have a ThreadsList");
+  assert(jt_pp != NULL, "must have a return JavaThread pointer");
+  // thread_oop_p is optional so no assert()
+
+  // The JVM_* interfaces don't allow a NULL thread parameter; JVM/TI
+  // allows a NULL thread parameter to signify "current thread" which
+  // allows us to avoid calling cv_external_thread_to_JavaThread().
+  // The JVM_* interfaces have no such leeway.
+
+  oop thread_oop = JNIHandles::resolve_non_null(jthread);
+  // Looks like an oop at this point.
+  if (thread_oop_p != NULL) {
+    // Return the oop to the caller; the caller may still want
+    // the oop even if this function returns false.
+    *thread_oop_p = thread_oop;
+  }
+
+  JavaThread *java_thread = java_lang_Thread::thread(thread_oop);
+  if (java_thread == NULL) {
+    // The java.lang.Thread does not contain a JavaThread * so it has
+    // not yet run or it has died.
+    return false;
+  }
+  // Looks like a live JavaThread at this point.
+
+  if (java_thread != JavaThread::current()) {
+    // jthread is not for the current JavaThread so have to verify
+    // the JavaThread * against the ThreadsList.
+    if (EnableThreadSMRExtraValidityChecks && !includes(java_thread)) {
+      // Not on the JavaThreads list so it is not alive.
+      return false;
+    }
+  }
+
+  // Return a live JavaThread that is "protected" by the
+  // ThreadsListHandle in the caller.
+  *jt_pp = java_thread;
+  return true;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/runtime/threadSMR.hpp	Mon Nov 27 17:04:45 2017 +0000
@@ -0,0 +1,257 @@
+/*
+ * Copyright (c) 2017, 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.
+ *
+ */
+
+#ifndef SHARE_VM_RUNTIME_THREADSMR_HPP
+#define SHARE_VM_RUNTIME_THREADSMR_HPP
+
+#include "memory/allocation.hpp"
+#include "runtime/timer.hpp"
+
+// Thread Safe Memory Reclamation (Thread-SMR) support.
+//
+// ThreadsListHandles are used to safely perform operations on one or more
+// threads without the risk of the thread or threads exiting during the
+// operation. It is no longer necessary to hold the Threads_lock to safely
+// perform an operation on a target thread.
+//
+// There are several different ways to refer to java.lang.Thread objects
+// so we have a few ways to get a protected JavaThread *:
+//
+// JNI jobject example:
+//   jobject jthread = ...;
+//   :
+//   ThreadsListHandle tlh;
+//   JavaThread* jt = NULL;
+//   bool is_alive = tlh.cv_internal_thread_to_JavaThread(jthread, &jt, NULL);
+//   if (is_alive) {
+//     :  // do stuff with 'jt'...
+//   }
+//
+// JVM/TI jthread example:
+//   jthread thread = ...;
+//   :
+//   JavaThread* jt = NULL;
+//   ThreadsListHandle tlh;
+//   jvmtiError err = JvmtiExport::cv_external_thread_to_JavaThread(tlh.list(), thread, &jt, NULL);
+//   if (err != JVMTI_ERROR_NONE) {
+//     return err;
+//   }
+//   :  // do stuff with 'jt'...
+//
+// JVM/TI oop example (this one should be very rare):
+//   oop thread_obj = ...;
+//   :
+//   JavaThread *jt = NULL;
+//   ThreadsListHandle tlh;
+//   jvmtiError err = JvmtiExport::cv_oop_to_JavaThread(tlh.list(), thread_obj, &jt);
+//   if (err != JVMTI_ERROR_NONE) {
+//     return err;
+//   }
+//   :  // do stuff with 'jt'...
+//
+// A JavaThread * that is included in the ThreadsList that is held by
+// a ThreadsListHandle is protected as long as the ThreadsListHandle
+// remains in scope. The target JavaThread * may have logically exited,
+// but that target JavaThread * will not be deleted until it is no
+// longer protected by a ThreadsListHandle.
+
+
+// A fast list of JavaThreads.
+//
+class ThreadsList : public CHeapObj<mtThread> {
+  friend class ScanHazardPtrGatherProtectedThreadsClosure;
+  friend class Threads;
+
+  const uint _length;
+  ThreadsList* _next_list;
+  JavaThread *const *const _threads;
+
+  template <class T>
+  void threads_do_dispatch(T *cl, JavaThread *const thread) const;
+
+  ThreadsList *next_list() const        { return _next_list; }
+  void set_next_list(ThreadsList *list) { _next_list = list; }
+
+public:
+  ThreadsList(int entries);
+  ~ThreadsList();
+
+  template <class T>
+  void threads_do(T *cl) const;
+
+  uint length() const                       { return _length; }
+
+  JavaThread *const thread_at(uint i) const { return _threads[i]; }
+
+  JavaThread *const *threads() const        { return _threads; }
+
+  // Returns -1 if target is not found.
+  int find_index_of_JavaThread(JavaThread* target);
+  JavaThread* find_JavaThread_from_java_tid(jlong java_tid) const;
+  bool includes(const JavaThread * const p) const;
+
+  static ThreadsList* add_thread(ThreadsList* list, JavaThread* java_thread);
+  static ThreadsList* remove_thread(ThreadsList* list, JavaThread* java_thread);
+};
+
+// Linked list of ThreadsLists to support nested ThreadsListHandles.
+class NestedThreadsList : public CHeapObj<mtThread> {
+  ThreadsList*const _t_list;
+  NestedThreadsList* _next;
+
+public:
+  NestedThreadsList(ThreadsList* t_list) : _t_list(t_list) {
+    assert(Threads_lock->owned_by_self(),
+           "must own Threads_lock for saved t_list to be valid.");
+  }
+
+  ThreadsList* t_list() { return _t_list; }
+  NestedThreadsList* next() { return _next; }
+  void set_next(NestedThreadsList* value) { _next = value; }
+};
+
+// A helper to optionally set the hazard ptr in ourself. This helper can
+// be used by ourself or by another thread. If the hazard ptr is set(),
+// then the destructor will release it.
+//
+class ThreadsListSetter : public StackObj {
+private:
+  bool _target_needs_release;  // needs release only when set()
+  Thread * _target;
+
+public:
+  ThreadsListSetter() : _target_needs_release(false), _target(Thread::current()) {
+  }
+  ~ThreadsListSetter();
+  ThreadsList* list();
+  void set();
+  bool target_needs_release() { return _target_needs_release; }
+};
+
+// This stack allocated ThreadsListHandle keeps all JavaThreads in the
+// ThreadsList from being deleted until it is safe.
+//
+class ThreadsListHandle : public StackObj {
+  ThreadsList * _list;
+  Thread *const _self;
+  elapsedTimer _timer;  // Enabled via -XX:+EnableThreadSMRStatistics.
+
+public:
+  ThreadsListHandle(Thread *self = Thread::current());
+  ~ThreadsListHandle();
+
+  ThreadsList *list() const {
+    return _list;
+  }
+
+  template <class T>
+  void threads_do(T *cl) const {
+    return _list->threads_do(cl);
+  }
+
+  bool cv_internal_thread_to_JavaThread(jobject jthread, JavaThread ** jt_pp, oop * thread_oop_p);
+
+  bool includes(JavaThread* p) {
+    return _list->includes(p);
+  }
+
+  uint length() const {
+    return _list->length();
+  }
+};
+
+// This stack allocated JavaThreadIterator is used to walk the
+// specified ThreadsList using the following style:
+//
+//   JavaThreadIterator jti(t_list);
+//   for (JavaThread *jt = jti.first(); jt != NULL; jt = jti.next()) {
+//     ...
+//   }
+//
+class JavaThreadIterator : public StackObj {
+  ThreadsList * _list;
+  uint _index;
+
+public:
+  JavaThreadIterator(ThreadsList *list) : _list(list), _index(0) {
+    assert(list != NULL, "ThreadsList must not be NULL.");
+  }
+
+  JavaThread *first() {
+    _index = 0;
+    return _list->thread_at(_index);
+  }
+
+  uint length() const {
+    return _list->length();
+  }
+
+  ThreadsList *list() const {
+    return _list;
+  }
+
+  JavaThread *next() {
+    if (++_index >= length()) {
+      return NULL;
+    }
+    return _list->thread_at(_index);
+  }
+};
+
+// This stack allocated ThreadsListHandle and JavaThreadIterator combo
+// is used to walk the ThreadsList in the included ThreadsListHandle
+// using the following style:
+//
+//   for (JavaThreadIteratorWithHandle jtiwh; JavaThread *jt = jtiwh.next(); ) {
+//     ...
+//   }
+//
+class JavaThreadIteratorWithHandle : public StackObj {
+  ThreadsListHandle _tlh;
+  uint _index;
+
+public:
+  JavaThreadIteratorWithHandle() : _index(0) {}
+
+  uint length() const {
+    return _tlh.length();
+  }
+
+  ThreadsList *list() const {
+    return _tlh.list();
+  }
+
+  JavaThread *next() {
+    if (_index >= length()) {
+      return NULL;
+    }
+    return _tlh.list()->thread_at(_index++);
+  }
+
+  void rewind() {
+    _index = 0;
+  }
+};
+
+#endif // SHARE_VM_RUNTIME_THREADSMR_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/runtime/threadSMR.inline.hpp	Mon Nov 27 17:04:45 2017 +0000
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2017, 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.
+ *
+ */
+
+#ifndef SHARE_VM_RUNTIME_THREADSMR_INLINE_HPP
+#define SHARE_VM_RUNTIME_THREADSMR_INLINE_HPP
+
+#include "runtime/atomic.hpp"
+#include "runtime/prefetch.inline.hpp"
+#include "runtime/thread.inline.hpp"
+#include "runtime/threadSMR.hpp"
+
+// Devirtualize known thread closure types.
+template <class T>
+inline void ThreadsList::threads_do_dispatch(T *cl, JavaThread *const thread) const {
+  cl->T::do_thread(thread);
+}
+
+template <>
+inline void ThreadsList::threads_do_dispatch<ThreadClosure>(ThreadClosure *cl, JavaThread *const thread) const {
+  cl->do_thread(thread);
+}
+
+template <class T>
+inline void ThreadsList::threads_do(T *cl) const {
+  const intx scan_interval = PrefetchScanIntervalInBytes;
+  JavaThread *const *const end = _threads + _length;
+  for (JavaThread *const *current_p = _threads; current_p != end; current_p++) {
+    Prefetch::read((void*)current_p, scan_interval);
+    JavaThread *const current = *current_p;
+    threads_do_dispatch(cl, current);
+  }
+}
+
+inline ThreadsList* ThreadsListSetter::list() {
+  ThreadsList *ret = _target->get_threads_hazard_ptr();
+  assert(ret != NULL, "hazard ptr should be set");
+  assert(!Thread::is_hazard_ptr_tagged(ret), "hazard ptr should be validated");
+  return ret;
+}
+
+#endif // SHARE_VM_RUNTIME_THREADSMR_INLINE_HPP
--- a/src/hotspot/share/runtime/vm_operations.cpp	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/hotspot/share/runtime/vm_operations.cpp	Mon Nov 27 17:04:45 2017 +0000
@@ -38,6 +38,7 @@
 #include "runtime/interfaceSupport.hpp"
 #include "runtime/sweeper.hpp"
 #include "runtime/thread.inline.hpp"
+#include "runtime/threadSMR.inline.hpp"
 #include "runtime/vm_operations.hpp"
 #include "services/threadService.hpp"
 #include "trace/tracing.hpp"
@@ -96,11 +97,12 @@
 
 void VM_ThreadStop::doit() {
   assert(SafepointSynchronize::is_at_safepoint(), "must be at a safepoint");
+  ThreadsListHandle tlh;
   JavaThread* target = java_lang_Thread::thread(target_thread());
   // Note that this now allows multiple ThreadDeath exceptions to be
   // thrown at a thread.
-  if (target != NULL) {
-    // the thread has run and is not already in the process of exiting
+  if (target != NULL && (!EnableThreadSMRExtraValidityChecks || tlh.includes(target))) {
+    // The target thread has run and has not exited yet.
     target->send_thread_stop(throwable());
   }
 }
@@ -146,9 +148,10 @@
 
 void VM_DeoptimizeAll::doit() {
   DeoptimizationMarker dm;
+  JavaThreadIteratorWithHandle jtiwh;
   // deoptimize all java threads in the system
   if (DeoptimizeALot) {
-    for (JavaThread* thread = Threads::first(); thread != NULL; thread = thread->next()) {
+    for (; JavaThread *thread = jtiwh.next(); ) {
       if (thread->has_last_Java_frame()) {
         thread->deoptimize();
       }
@@ -159,7 +162,7 @@
     int tnum = os::random() & 0x3;
     int fnum =  os::random() & 0x3;
     int tcount = 0;
-    for (JavaThread* thread = Threads::first(); thread != NULL; thread = thread->next()) {
+    for (; JavaThread *thread = jtiwh.next(); ) {
       if (thread->has_last_Java_frame()) {
         if (tcount++ == tnum)  {
         tcount = 0;
@@ -259,12 +262,19 @@
 }
 
 void VM_FindDeadlocks::doit() {
-  _deadlocks = ThreadService::find_deadlocks_at_safepoint(_concurrent_locks);
+  // Update the hazard ptr in the originating thread to the current
+  // list of threads. This VM operation needs the current list of
+  // threads for proper deadlock detection and those are the
+  // JavaThreads we need to be protected when we return info to the
+  // originating thread.
+  _setter.set();
+
+  _deadlocks = ThreadService::find_deadlocks_at_safepoint(_setter.list(), _concurrent_locks);
   if (_out != NULL) {
     int num_deadlocks = 0;
     for (DeadlockCycle* cycle = _deadlocks; cycle != NULL; cycle = cycle->next()) {
       num_deadlocks++;
-      cycle->print_on(_out);
+      cycle->print_on_with(_setter.list(), _out);
     }
 
     if (num_deadlocks == 1) {
@@ -331,6 +341,12 @@
 void VM_ThreadDump::doit() {
   ResourceMark rm;
 
+  // Set the hazard ptr in the originating thread to protect the
+  // current list of threads. This VM operation needs the current list
+  // of threads for a proper dump and those are the JavaThreads we need
+  // to be protected when we return info to the originating thread.
+  _result->set_t_list();
+
   ConcurrentLocksDump concurrent_locks(true);
   if (_with_locked_synchronizers) {
     concurrent_locks.dump_at_safepoint();
@@ -338,7 +354,9 @@
 
   if (_num_threads == 0) {
     // Snapshot all live threads
-    for (JavaThread* jt = Threads::first(); jt != NULL; jt = jt->next()) {
+
+    for (uint i = 0; i < _result->t_list()->length(); i++) {
+      JavaThread* jt = _result->t_list()->thread_at(i);
       if (jt->is_exiting() ||
           jt->is_hidden_from_external_view())  {
         // skip terminating threads and hidden threads
@@ -354,6 +372,7 @@
   } else {
     // Snapshot threads in the given _threads array
     // A dummy snapshot is created if a thread doesn't exist
+
     for (int i = 0; i < _num_threads; i++) {
       instanceHandle th = _threads->at(i);
       if (th() == NULL) {
@@ -366,6 +385,12 @@
       // Dump thread stack only if the thread is alive and not exiting
       // and not VM internal thread.
       JavaThread* jt = java_lang_Thread::thread(th());
+      if (jt != NULL && !_result->t_list()->includes(jt)) {
+        // _threads[i] doesn't refer to a valid JavaThread; this check
+        // is primarily for JVM_DumpThreads() which doesn't have a good
+        // way to validate the _threads array.
+        jt = NULL;
+      }
       if (jt == NULL || /* thread not alive */
           jt->is_exiting() ||
           jt->is_hidden_from_external_view())  {
@@ -384,7 +409,7 @@
 }
 
 ThreadSnapshot* VM_ThreadDump::snapshot_thread(JavaThread* java_thread, ThreadConcurrentLocks* tcl) {
-  ThreadSnapshot* snapshot = new ThreadSnapshot(java_thread);
+  ThreadSnapshot* snapshot = new ThreadSnapshot(_result->t_list(), java_thread);
   snapshot->dump_stack_at_safepoint(_max_depth, _with_locked_monitors);
   snapshot->set_concurrent_locks(tcl);
   return snapshot;
@@ -403,11 +428,12 @@
 
   _shutdown_thread = thr_cur;
   _vm_exited = true;                                // global flag
-  for(JavaThread *thr = Threads::first(); thr != NULL; thr = thr->next())
+  for (JavaThreadIteratorWithHandle jtiwh; JavaThread *thr = jtiwh.next(); ) {
     if (thr!=thr_cur && thr->thread_state() == _thread_in_native) {
       ++num_active;
       thr->set_terminated(JavaThread::_vm_exited);  // per-thread flag
     }
+  }
 
   return num_active;
 }
@@ -435,11 +461,13 @@
   int max_wait = max_wait_compiler_thread;
 
   int attempts = 0;
+  JavaThreadIteratorWithHandle jtiwh;
   while (true) {
     int num_active = 0;
     int num_active_compiler_thread = 0;
 
-    for(JavaThread *thr = Threads::first(); thr != NULL; thr = thr->next()) {
+    jtiwh.rewind();
+    for (; JavaThread *thr = jtiwh.next(); ) {
       if (thr!=thr_cur && thr->thread_state() == _thread_in_native) {
         num_active++;
         if (thr->is_Compiler_thread()) {
--- a/src/hotspot/share/runtime/vm_operations.hpp	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/hotspot/share/runtime/vm_operations.hpp	Mon Nov 27 17:04:45 2017 +0000
@@ -392,12 +392,14 @@
 class DeadlockCycle;
 class VM_FindDeadlocks: public VM_Operation {
  private:
-  bool           _concurrent_locks;
-  DeadlockCycle* _deadlocks;
-  outputStream*  _out;
+  bool              _concurrent_locks;
+  DeadlockCycle*    _deadlocks;
+  outputStream*     _out;
+  ThreadsListSetter _setter;  // Helper to set hazard ptr in the originating thread
+                              // which protects the JavaThreads in _deadlocks.
 
  public:
-  VM_FindDeadlocks(bool concurrent_locks) :  _concurrent_locks(concurrent_locks), _out(NULL), _deadlocks(NULL) {};
+  VM_FindDeadlocks(bool concurrent_locks) :  _concurrent_locks(concurrent_locks), _out(NULL), _deadlocks(NULL), _setter() {};
   VM_FindDeadlocks(outputStream* st) : _concurrent_locks(true), _out(st), _deadlocks(NULL) {};
   ~VM_FindDeadlocks();
 
--- a/src/hotspot/share/services/heapDumper.cpp	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/hotspot/share/services/heapDumper.cpp	Mon Nov 27 17:04:45 2017 +0000
@@ -39,6 +39,8 @@
 #include "runtime/jniHandles.hpp"
 #include "runtime/os.hpp"
 #include "runtime/reflectionUtils.hpp"
+#include "runtime/thread.inline.hpp"
+#include "runtime/threadSMR.hpp"
 #include "runtime/vframe.hpp"
 #include "runtime/vmThread.hpp"
 #include "runtime/vm_operations.hpp"
@@ -1895,7 +1897,7 @@
 
   _stack_traces = NEW_C_HEAP_ARRAY(ThreadStackTrace*, Threads::number_of_threads(), mtInternal);
   int frame_serial_num = 0;
-  for (JavaThread* thread = Threads::first(); thread != NULL ; thread = thread->next()) {
+  for (JavaThreadIteratorWithHandle jtiwh; JavaThread *thread = jtiwh.next(); ) {
     oop threadObj = thread->threadObj();
     if (threadObj != NULL && !thread->is_exiting() && !thread->is_hidden_from_external_view()) {
       // dump thread stack trace
--- a/src/hotspot/share/services/management.cpp	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/hotspot/share/services/management.cpp	Mon Nov 27 17:04:45 2017 +0000
@@ -42,6 +42,7 @@
 #include "runtime/os.hpp"
 #include "runtime/serviceThread.hpp"
 #include "runtime/thread.inline.hpp"
+#include "runtime/threadSMR.hpp"
 #include "services/classLoadingService.hpp"
 #include "services/diagnosticCommand.hpp"
 #include "services/diagnosticFramework.hpp"
@@ -1025,11 +1026,15 @@
   // First get an array of threadObj handles.
   // A JavaThread may terminate before we get the stack trace.
   GrowableArray<instanceHandle>* thread_handle_array = new GrowableArray<instanceHandle>(num_threads);
+
   {
-    MutexLockerEx ml(Threads_lock);
+    // Need this ThreadsListHandle for converting Java thread IDs into
+    // threadObj handles; dump_result->set_t_list() is called in the
+    // VM op below so we can't use it yet.
+    ThreadsListHandle tlh;
     for (int i = 0; i < num_threads; i++) {
       jlong tid = ids_ah->long_at(i);
-      JavaThread* jt = Threads::find_java_thread_from_java_tid(tid);
+      JavaThread* jt = tlh.list()->find_JavaThread_from_java_tid(tid);
       oop thread_obj = (jt != NULL ? jt->threadObj() : (oop)NULL);
       instanceHandle threadObj_h(THREAD, (instanceOop) thread_obj);
       thread_handle_array->append(threadObj_h);
@@ -1101,22 +1106,21 @@
   ThreadDumpResult dump_result(num_threads);
 
   if (maxDepth == 0) {
-    // no stack trace dumped - do not need to stop the world
-    {
-      MutexLockerEx ml(Threads_lock);
-      for (int i = 0; i < num_threads; i++) {
-        jlong tid = ids_ah->long_at(i);
-        JavaThread* jt = Threads::find_java_thread_from_java_tid(tid);
-        ThreadSnapshot* ts;
-        if (jt == NULL) {
-          // if the thread does not exist or now it is terminated,
-          // create dummy snapshot
-          ts = new ThreadSnapshot();
-        } else {
-          ts = new ThreadSnapshot(jt);
-        }
-        dump_result.add_thread_snapshot(ts);
+    // No stack trace to dump so we do not need to stop the world.
+    // Since we never do the VM op here we must set the threads list.
+    dump_result.set_t_list();
+    for (int i = 0; i < num_threads; i++) {
+      jlong tid = ids_ah->long_at(i);
+      JavaThread* jt = dump_result.t_list()->find_JavaThread_from_java_tid(tid);
+      ThreadSnapshot* ts;
+      if (jt == NULL) {
+        // if the thread does not exist or now it is terminated,
+        // create dummy snapshot
+        ts = new ThreadSnapshot();
+      } else {
+        ts = new ThreadSnapshot(dump_result.t_list(), jt);
       }
+      dump_result.add_thread_snapshot(ts);
     }
   } else {
     // obtain thread dump with the specific list of threads with stack trace
@@ -1131,6 +1135,7 @@
 
   int num_snapshots = dump_result.num_snapshots();
   assert(num_snapshots == num_threads, "Must match the number of thread snapshots");
+  assert(num_snapshots == 0 || dump_result.t_list_has_been_set(), "ThreadsList must have been set if we have a snapshot");
   int index = 0;
   for (ThreadSnapshot* ts = dump_result.snapshots(); ts != NULL; index++, ts = ts->next()) {
     // For each thread, create an java/lang/management/ThreadInfo object
@@ -1196,6 +1201,7 @@
   }
 
   int num_snapshots = dump_result.num_snapshots();
+  assert(num_snapshots == 0 || dump_result.t_list_has_been_set(), "ThreadsList must have been set if we have a snapshot");
 
   // create the result ThreadInfo[] object
   InstanceKlass* ik = Management::java_lang_management_ThreadInfo_klass(CHECK_NULL);
@@ -1319,10 +1325,10 @@
       }
 
       // Look for the JavaThread of this given tid
-      MutexLockerEx ml(Threads_lock);
+      JavaThreadIteratorWithHandle jtiwh;
       if (tid == 0) {
         // reset contention statistics for all threads if tid == 0
-        for (JavaThread* java_thread = Threads::first(); java_thread != NULL; java_thread = java_thread->next()) {
+        for (; JavaThread *java_thread = jtiwh.next(); ) {
           if (type == JMM_STAT_THREAD_CONTENTION_COUNT) {
             ThreadService::reset_contention_count_stat(java_thread);
           } else {
@@ -1331,7 +1337,7 @@
         }
       } else {
         // reset contention statistics for a given thread
-        JavaThread* java_thread = Threads::find_java_thread_from_java_tid(tid);
+        JavaThread* java_thread = jtiwh.list()->find_JavaThread_from_java_tid(tid);
         if (java_thread == NULL) {
           return false;
         }
@@ -1399,8 +1405,8 @@
     // current thread
     return os::current_thread_cpu_time();
   } else {
-    MutexLockerEx ml(Threads_lock);
-    java_thread = Threads::find_java_thread_from_java_tid(thread_id);
+    ThreadsListHandle tlh;
+    java_thread = tlh.list()->find_JavaThread_from_java_tid(thread_id);
     if (java_thread != NULL) {
       return os::thread_cpu_time((Thread*) java_thread);
     }
@@ -1649,6 +1655,7 @@
 // Called with Threads_lock held
 //
 void ThreadTimesClosure::do_thread(Thread* thread) {
+  assert(Threads_lock->owned_by_self(), "Must hold Threads_lock");
   assert(thread != NULL, "thread was NULL");
 
   // exclude externally visible JavaThreads
@@ -2109,9 +2116,9 @@
               "the given array of thread IDs");
   }
 
-  MutexLockerEx ml(Threads_lock);
+  ThreadsListHandle tlh;
   for (int i = 0; i < num_threads; i++) {
-    JavaThread* java_thread = Threads::find_java_thread_from_java_tid(ids_ah->long_at(i));
+    JavaThread* java_thread = tlh.list()->find_JavaThread_from_java_tid(ids_ah->long_at(i));
     if (java_thread != NULL) {
       sizeArray_h->long_at_put(i, java_thread->cooked_allocated_bytes());
     }
@@ -2138,8 +2145,8 @@
     // current thread
     return os::current_thread_cpu_time(user_sys_cpu_time != 0);
   } else {
-    MutexLockerEx ml(Threads_lock);
-    java_thread = Threads::find_java_thread_from_java_tid(thread_id);
+    ThreadsListHandle tlh;
+    java_thread = tlh.list()->find_JavaThread_from_java_tid(thread_id);
     if (java_thread != NULL) {
       return os::thread_cpu_time((Thread*) java_thread, user_sys_cpu_time != 0);
     }
@@ -2180,9 +2187,9 @@
               "the given array of thread IDs");
   }
 
-  MutexLockerEx ml(Threads_lock);
+  ThreadsListHandle tlh;
   for (int i = 0; i < num_threads; i++) {
-    JavaThread* java_thread = Threads::find_java_thread_from_java_tid(ids_ah->long_at(i));
+    JavaThread* java_thread = tlh.list()->find_JavaThread_from_java_tid(ids_ah->long_at(i));
     if (java_thread != NULL) {
       timeArray_h->long_at_put(i, os::thread_cpu_time((Thread*)java_thread,
                                                       user_sys_cpu_time != 0));
--- a/src/hotspot/share/services/memoryManager.hpp	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/hotspot/share/services/memoryManager.hpp	Mon Nov 27 17:04:45 2017 +0000
@@ -25,7 +25,10 @@
 #ifndef SHARE_VM_SERVICES_MEMORYMANAGER_HPP
 #define SHARE_VM_SERVICES_MEMORYMANAGER_HPP
 
+#include "gc/shared/gcCause.hpp"
 #include "memory/allocation.hpp"
+#include "oops/oopsHierarchy.hpp"
+#include "runtime/handles.hpp"
 #include "runtime/timer.hpp"
 #include "services/memoryUsage.hpp"
 
--- a/src/hotspot/share/services/threadService.cpp	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/hotspot/share/services/threadService.cpp	Mon Nov 27 17:04:45 2017 +0000
@@ -34,9 +34,9 @@
 #include "runtime/atomic.hpp"
 #include "runtime/handles.inline.hpp"
 #include "runtime/init.hpp"
-#include "runtime/thread.hpp"
+#include "runtime/thread.inline.hpp"
+#include "runtime/threadSMR.inline.hpp"
 #include "runtime/vframe.hpp"
-#include "runtime/thread.inline.hpp"
 #include "runtime/vmThread.hpp"
 #include "runtime/vm_operations.hpp"
 #include "services/threadService.hpp"
@@ -148,7 +148,7 @@
 // FIXME: JVMTI should call this function
 Handle ThreadService::get_current_contended_monitor(JavaThread* thread) {
   assert(thread != NULL, "should be non-NULL");
-  assert(Threads_lock->owned_by_self(), "must grab Threads_lock or be at safepoint");
+  debug_only(Thread::check_for_dangling_thread_pointer(thread);)
 
   ObjectMonitor *wait_obj = thread->current_waiting_monitor();
 
@@ -266,6 +266,7 @@
 
   int num_snapshots = dump_result.num_snapshots();
   assert(num_snapshots == num_threads, "Must have num_threads thread snapshots");
+  assert(num_snapshots == 0 || dump_result.t_list_has_been_set(), "ThreadsList must have been set if we have a snapshot");
   int i = 0;
   for (ThreadSnapshot* ts = dump_result.snapshots(); ts != NULL; i++, ts = ts->next()) {
     ThreadStackTrace* stacktrace = ts->get_stack_trace();
@@ -297,7 +298,9 @@
 }
 
 // Find deadlocks involving object monitors and concurrent locks if concurrent_locks is true
-DeadlockCycle* ThreadService::find_deadlocks_at_safepoint(bool concurrent_locks) {
+DeadlockCycle* ThreadService::find_deadlocks_at_safepoint(ThreadsList * t_list, bool concurrent_locks) {
+  assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
+
   // This code was modified from the original Threads::find_deadlocks code.
   int globalDfn = 0, thisDfn;
   ObjectMonitor* waitingToLockMonitor = NULL;
@@ -306,15 +309,16 @@
   JavaThread *currentThread, *previousThread;
   int num_deadlocks = 0;
 
-  for (JavaThread* p = Threads::first(); p != NULL; p = p->next()) {
-    // Initialize the depth-first-number
-    p->set_depth_first_number(-1);
+  // Initialize the depth-first-number for each JavaThread.
+  JavaThreadIterator jti(t_list);
+  for (JavaThread* jt = jti.first(); jt != NULL; jt = jti.next()) {
+    jt->set_depth_first_number(-1);
   }
 
   DeadlockCycle* deadlocks = NULL;
   DeadlockCycle* last = NULL;
   DeadlockCycle* cycle = new DeadlockCycle();
-  for (JavaThread* jt = Threads::first(); jt != NULL; jt = jt->next()) {
+  for (JavaThread* jt = jti.first(); jt != NULL; jt = jti.next()) {
     if (jt->depth_first_number() >= 0) {
       // this thread was already visited
       continue;
@@ -339,9 +343,8 @@
       if (waitingToLockMonitor != NULL) {
         address currentOwner = (address)waitingToLockMonitor->owner();
         if (currentOwner != NULL) {
-          currentThread = Threads::owning_thread_from_monitor_owner(
-                            currentOwner,
-                            false /* no locking needed */);
+          currentThread = Threads::owning_thread_from_monitor_owner(t_list,
+                                                                    currentOwner);
           if (currentThread == NULL) {
             // This function is called at a safepoint so the JavaThread
             // that owns waitingToLockMonitor should be findable, but
@@ -366,6 +369,8 @@
         if (concurrent_locks) {
           if (waitingToLockBlocker->is_a(SystemDictionary::abstract_ownable_synchronizer_klass())) {
             oop threadObj = java_util_concurrent_locks_AbstractOwnableSynchronizer::get_owner_threadObj(waitingToLockBlocker);
+            // This JavaThread (if there is one) is protected by the
+            // ThreadsListSetter in VM_FindDeadlocks::doit().
             currentThread = threadObj != NULL ? java_lang_Thread::thread(threadObj) : NULL;
           } else {
             currentThread = NULL;
@@ -414,7 +419,7 @@
   return deadlocks;
 }
 
-ThreadDumpResult::ThreadDumpResult() : _num_threads(0), _num_snapshots(0), _snapshots(NULL), _next(NULL), _last(NULL) {
+ThreadDumpResult::ThreadDumpResult() : _num_threads(0), _num_snapshots(0), _snapshots(NULL), _next(NULL), _last(NULL), _setter() {
 
   // Create a new ThreadDumpResult object and append to the list.
   // If GC happens before this function returns, Method*
@@ -422,7 +427,7 @@
   ThreadService::add_thread_dump(this);
 }
 
-ThreadDumpResult::ThreadDumpResult(int num_threads) : _num_threads(num_threads), _num_snapshots(0), _snapshots(NULL), _next(NULL), _last(NULL) {
+ThreadDumpResult::ThreadDumpResult(int num_threads) : _num_threads(num_threads), _num_snapshots(0), _snapshots(NULL), _next(NULL), _last(NULL), _setter() {
   // Create a new ThreadDumpResult object and append to the list.
   // If GC happens before this function returns, oops
   // will be visited.
@@ -467,6 +472,10 @@
   }
 }
 
+ThreadsList* ThreadDumpResult::t_list() {
+  return _setter.list();
+}
+
 StackFrameInfo::StackFrameInfo(javaVFrame* jvf, bool with_lock_info) {
   _method = jvf->method();
   _bci = jvf->bci();
@@ -683,6 +692,8 @@
     oop o = aos_objects->at(i);
     oop owner_thread_obj = java_util_concurrent_locks_AbstractOwnableSynchronizer::get_owner_threadObj(o);
     if (owner_thread_obj != NULL) {
+      // See comments in ThreadConcurrentLocks to see how this
+      // JavaThread* is protected.
       JavaThread* thread = java_lang_Thread::thread(owner_thread_obj);
       assert(o->is_instance(), "Must be an instanceOop");
       add_lock(thread, (instanceOop) o);
@@ -764,7 +775,7 @@
   memset((void*) _perf_recursion_counts, 0, sizeof(_perf_recursion_counts));
 }
 
-ThreadSnapshot::ThreadSnapshot(JavaThread* thread) {
+ThreadSnapshot::ThreadSnapshot(ThreadsList * t_list, JavaThread* thread) {
   _thread = thread;
   _threadObj = thread->threadObj();
   _stack_trace = NULL;
@@ -796,7 +807,7 @@
       _thread_status = java_lang_Thread::RUNNABLE;
     } else {
       _blocker_object = obj();
-      JavaThread* owner = ObjectSynchronizer::get_lock_owner(obj, false);
+      JavaThread* owner = ObjectSynchronizer::get_lock_owner(t_list, obj);
       if ((owner == NULL && _thread_status == java_lang_Thread::BLOCKED_ON_MONITOR_ENTER)
           || (owner != NULL && owner->is_attaching_via_jni())) {
         // ownership information of the monitor is not available
@@ -865,7 +876,7 @@
   delete _threads;
 }
 
-void DeadlockCycle::print_on(outputStream* st) const {
+void DeadlockCycle::print_on_with(ThreadsList * t_list, outputStream* st) const {
   st->cr();
   st->print_cr("Found one Java-level deadlock:");
   st->print("=============================");
@@ -895,9 +906,8 @@
         // No Java object associated - a JVMTI raw monitor
         owner_desc = " (JVMTI raw monitor),\n  which is held by";
       }
-      currentThread = Threads::owning_thread_from_monitor_owner(
-                        (address)waitingToLockMonitor->owner(),
-                        false /* no locking needed */);
+      currentThread = Threads::owning_thread_from_monitor_owner(t_list,
+                                                                (address)waitingToLockMonitor->owner());
       if (currentThread == NULL) {
         // The deadlock was detected at a safepoint so the JavaThread
         // that owns waitingToLockMonitor should be findable, but
@@ -915,6 +925,7 @@
              "Must be an AbstractOwnableSynchronizer");
       oop ownerObj = java_util_concurrent_locks_AbstractOwnableSynchronizer::get_owner_threadObj(waitingToLockBlocker);
       currentThread = java_lang_Thread::thread(ownerObj);
+      assert(currentThread != NULL, "AbstractOwnableSynchronizer owning thread is unexpectedly NULL");
     }
     st->print("%s \"%s\"", owner_desc, currentThread->get_thread_name());
   }
@@ -943,9 +954,7 @@
   int init_size = ThreadService::get_live_thread_count();
   _threads_array = new GrowableArray<instanceHandle>(init_size);
 
-  MutexLockerEx ml(Threads_lock);
-
-  for (JavaThread* jt = Threads::first(); jt != NULL; jt = jt->next()) {
+  for (JavaThreadIteratorWithHandle jtiwh; JavaThread *jt = jtiwh.next(); ) {
     // skips JavaThreads in the process of exiting
     // and also skips VM internal JavaThreads
     // Threads in _thread_new or _thread_new_trans state are included.
--- a/src/hotspot/share/services/threadService.hpp	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/hotspot/share/services/threadService.hpp	Mon Nov 27 17:04:45 2017 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2017, 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
@@ -32,6 +32,7 @@
 #include "runtime/objectMonitor.hpp"
 #include "runtime/objectMonitor.inline.hpp"
 #include "runtime/perfData.hpp"
+#include "runtime/thread.hpp"
 #include "services/management.hpp"
 #include "services/serviceUtil.hpp"
 
@@ -109,7 +110,7 @@
   static void   reset_contention_count_stat(JavaThread* thread);
   static void   reset_contention_time_stat(JavaThread* thread);
 
-  static DeadlockCycle*       find_deadlocks_at_safepoint(bool object_monitors_only);
+  static DeadlockCycle*       find_deadlocks_at_safepoint(ThreadsList * t_list, bool object_monitors_only);
 
   // GC support
   static void   oops_do(OopClosure* f);
@@ -189,6 +190,8 @@
 // Thread snapshot to represent the thread state and statistics
 class ThreadSnapshot : public CHeapObj<mtInternal> {
 private:
+  // This JavaThread* is protected by being stored in objects that are
+  // protected by a ThreadsListSetter (ThreadDumpResult).
   JavaThread* _thread;
   oop         _threadObj;
   java_lang_Thread::ThreadStatus _thread_status;
@@ -213,7 +216,7 @@
   // Dummy snapshot
   ThreadSnapshot() : _thread(NULL), _threadObj(NULL), _stack_trace(NULL), _concurrent_locks(NULL), _next(NULL),
                      _blocker_object(NULL), _blocker_object_owner(NULL) {};
-  ThreadSnapshot(JavaThread* thread);
+  ThreadSnapshot(ThreadsList * t_list, JavaThread* thread);
   ~ThreadSnapshot();
 
   java_lang_Thread::ThreadStatus thread_status() { return _thread_status; }
@@ -310,6 +313,12 @@
 private:
   GrowableArray<instanceOop>* _owned_locks;
   ThreadConcurrentLocks*      _next;
+  // This JavaThread* is protected in one of two different ways
+  // depending on the usage of the ThreadConcurrentLocks object:
+  // 1) by being stored in objects that are only allocated and used at a
+  // safepoint (ConcurrentLocksDump), or 2) by being stored in objects
+  // that are protected by a ThreadsListSetter (ThreadSnapshot inside
+  // ThreadDumpResult).
   JavaThread*                 _thread;
  public:
   ThreadConcurrentLocks(JavaThread* thread);
@@ -333,8 +342,12 @@
   void add_lock(JavaThread* thread, instanceOop o);
 
  public:
-  ConcurrentLocksDump(bool retain_map_on_free) : _map(NULL), _last(NULL), _retain_map_on_free(retain_map_on_free) {};
-  ConcurrentLocksDump() : _map(NULL), _last(NULL), _retain_map_on_free(false) {};
+  ConcurrentLocksDump(bool retain_map_on_free) : _map(NULL), _last(NULL), _retain_map_on_free(retain_map_on_free) {
+    assert(SafepointSynchronize::is_at_safepoint(), "Must be constructed at a safepoint.");
+  };
+  ConcurrentLocksDump() : _map(NULL), _last(NULL), _retain_map_on_free(false) {
+    assert(SafepointSynchronize::is_at_safepoint(), "Must be constructed at a safepoint.");
+  };
   ~ConcurrentLocksDump();
 
   void                        dump_at_safepoint();
@@ -349,6 +362,9 @@
   ThreadSnapshot*      _snapshots;
   ThreadSnapshot*      _last;
   ThreadDumpResult*    _next;
+  ThreadsListSetter    _setter;  // Helper to set hazard ptr in the originating thread
+                                 // which protects the JavaThreads in _snapshots.
+
  public:
   ThreadDumpResult();
   ThreadDumpResult(int num_threads);
@@ -360,6 +376,9 @@
   int                  num_threads()                    { return _num_threads; }
   int                  num_snapshots()                  { return _num_snapshots; }
   ThreadSnapshot*      snapshots()                      { return _snapshots; }
+  void                 set_t_list()                     { _setter.set(); }
+  ThreadsList*         t_list();
+  bool                 t_list_has_been_set()            { return _setter.target_needs_release(); }
   void                 oops_do(OopClosure* f);
   void                 metadata_do(void f(Metadata*));
 };
@@ -381,7 +400,7 @@
   bool           is_deadlock()              { return _is_deadlock; }
   int            num_threads()              { return _threads->length(); }
   GrowableArray<JavaThread*>* threads()     { return _threads; }
-  void           print_on(outputStream* st) const;
+  void           print_on_with(ThreadsList * t_list, outputStream* st) const;
 };
 
 // Utility class to get list of java threads.
--- a/src/hotspot/share/utilities/vmError.cpp	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/hotspot/share/utilities/vmError.cpp	Mon Nov 27 17:04:45 2017 +0000
@@ -36,6 +36,7 @@
 #include "runtime/init.hpp"
 #include "runtime/os.hpp"
 #include "runtime/thread.inline.hpp"
+#include "runtime/threadSMR.hpp"
 #include "runtime/vmThread.hpp"
 #include "runtime/vm_operations.hpp"
 #include "runtime/vm_version.hpp"
@@ -1655,7 +1656,12 @@
   char * const dataPtr = NULL;  // bad data pointer
   const void (*funcPtr)(void) = (const void(*)()) 0xF;  // bad function pointer
 
-  // Keep this in sync with test/runtime/ErrorHandling/ErrorHandler.java
+  // Keep this in sync with test/hotspot/jtreg/runtime/ErrorHandling/ErrorHandler.java
+  // which tests cases 1 thru 13.
+  // Case 14 is tested by test/hotspot/jtreg/runtime/ErrorHandling/SafeFetchInErrorHandlingTest.java.
+  // Case 15 is tested by test/hotspot/jtreg/runtime/ErrorHandling/SecondaryErrorTest.java.
+  // Case 16 is tested by test/hotspot/jtreg/runtime/ErrorHandling/ThreadsListHandleInErrorHandlingTest.java.
+  // Case 17 is tested by test/hotspot/jtreg/runtime/ErrorHandling/NestedThreadsListHandleInErrorHandlingTest.java.
   switch (how) {
     case  1: vmassert(str == NULL, "expected null");
     case  2: vmassert(num == 1023 && *str == 'X',
@@ -1683,6 +1689,17 @@
     case 13: (*funcPtr)(); break;
     case 14: crash_with_segfault(); break;
     case 15: crash_with_sigfpe(); break;
+    case 16: {
+      ThreadsListHandle tlh;
+      fatal("Force crash with an active ThreadsListHandle.");
+    }
+    case 17: {
+      ThreadsListHandle tlh;
+      {
+        ThreadsListHandle tlh2;
+        fatal("Force crash with a nested ThreadsListHandle.");
+      }
+    }
 
     default: tty->print_cr("ERROR: %d: unexpected test_num value.", how);
   }
--- a/src/java.base/macosx/native/libosxsecurity/KeystoreImpl.m	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/java.base/macosx/native/libosxsecurity/KeystoreImpl.m	Mon Nov 27 17:04:45 2017 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2017, 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
@@ -24,6 +24,7 @@
  */
 
 #import "apple_security_KeychainStore.h"
+#import "jni_util.h"
 
 #import <Security/Security.h>
 #import <Security/SecImportExport.h>
@@ -52,6 +53,11 @@
     }
 
     attribCString = malloc(itemAttrs[0].length + 1);
+    if (attribCString == NULL) {
+        JNU_ThrowOutOfMemoryError(env, "native heap");
+        goto errOut;
+    }
+
     strncpy(attribCString, itemAttrs[0].data, itemAttrs[0].length);
     attribCString[itemAttrs[0].length] = '\0';
     returnValue = (*env)->NewStringUTF(env, attribCString);
@@ -478,6 +484,8 @@
     // again later as a certificate.
     addIdentitiesToKeystore(env, this);
 
+    JNU_CHECK_EXCEPTION(env);
+
     // Scan current keychain for trusted certificates.
     addCertificatesToKeystore(env, this);
 
--- a/src/java.base/share/classes/java/io/InputStream.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/java.base/share/classes/java/io/InputStream.java	Mon Nov 27 17:04:45 2017 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1994, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 2017, 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
@@ -164,11 +164,9 @@
      * @see        java.io.InputStream#read()
      */
     public int read(byte b[], int off, int len) throws IOException {
-        if (b == null) {
-            throw new NullPointerException();
-        } else if (off < 0 || len < 0 || len > b.length - off) {
-            throw new IndexOutOfBoundsException();
-        } else if (len == 0) {
+        Objects.requireNonNull(b);
+        Objects.checkFromIndexSize(off, len, b.length);
+        if (len == 0) {
             return 0;
         }
 
@@ -302,8 +300,8 @@
      */
     public int readNBytes(byte[] b, int off, int len) throws IOException {
         Objects.requireNonNull(b);
-        if (off < 0 || len < 0 || len > b.length - off)
-            throw new IndexOutOfBoundsException();
+        Objects.checkFromIndexSize(off, len, b.length);
+
         int n = 0;
         while (n < len) {
             int count = read(b, off + n, len - n);
--- a/src/java.base/share/classes/java/io/OutputStream.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/java.base/share/classes/java/io/OutputStream.java	Mon Nov 27 17:04:45 2017 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1994, 2004, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 2017, 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
@@ -25,6 +25,8 @@
 
 package java.io;
 
+import java.util.Objects;
+
 /**
  * This abstract class is the superclass of all classes representing
  * an output stream of bytes. An output stream accepts output bytes
@@ -104,14 +106,9 @@
      *             stream is closed.
      */
     public void write(byte b[], int off, int len) throws IOException {
-        if (b == null) {
-            throw new NullPointerException();
-        } else if ((off < 0) || (off > b.length) || (len < 0) ||
-                   ((off + len) > b.length) || ((off + len) < 0)) {
-            throw new IndexOutOfBoundsException();
-        } else if (len == 0) {
-            return;
-        }
+        Objects.requireNonNull(b);
+        Objects.checkFromIndexSize(off, len, b.length);
+        // len == 0 condition implicitly handled by loop bounds
         for (int i = 0 ; i < len ; i++) {
             write(b[off + i]);
         }
--- a/src/java.base/share/classes/java/lang/ModuleLayer.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/java.base/share/classes/java/lang/ModuleLayer.java	Mon Nov 27 17:04:45 2017 +0000
@@ -766,7 +766,7 @@
 
 
     /**
-     * Returns an ordered stream of layers. The first element is is this layer,
+     * Returns an ordered stream of layers. The first element is this layer,
      * the remaining elements are the parent layers in DFS order.
      *
      * @implNote For now, the assumption is that the number of elements will
--- a/src/java.base/share/classes/java/lang/Package.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/java.base/share/classes/java/lang/Package.java	Mon Nov 27 17:04:45 2017 +0000
@@ -550,7 +550,8 @@
                                        URL sealbase) {
             if (spectitle == null && specversion == null &&
                     specvendor == null && impltitle == null &&
-                    implvendor == null && sealbase == null) {
+                    implversion == null && implvendor == null &&
+                    sealbase == null) {
                 return NULL_VERSION_INFO;
             }
             return new VersionInfo(spectitle, specversion, specvendor,
--- a/src/java.base/share/classes/java/lang/StackTraceElement.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/java.base/share/classes/java/lang/StackTraceElement.java	Mon Nov 27 17:04:45 2017 +0000
@@ -293,7 +293,7 @@
      * <li>
      *     "{@code acme@2.1/org.acme.Lib.test(Lib.java:80)}"
      * - The class of the execution point is defined in {@code acme} module
-     * loaded by by a built-in class loader such as the application class loader.
+     * loaded by a built-in class loader such as the application class loader.
      * </li>
      * <li>
      *     "{@code MyClass.mash(MyClass.java:9)}"
--- a/src/java.base/share/classes/java/lang/invoke/LambdaFormBuffer.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/java.base/share/classes/java/lang/invoke/LambdaFormBuffer.java	Mon Nov 27 17:04:45 2017 +0000
@@ -115,9 +115,9 @@
         return true;
     }
 
-    private static int indexOf(NamedFunction fn, NamedFunction[] fns) {
-        for (int i = 0; i < fns.length; i++) {
-            if (fns[i] == fn)  return i;
+    private static int indexOf(NamedFunction fn, List<NamedFunction> fns) {
+        for (int i = 0; i < fns.size(); i++) {
+            if (fns.get(i) == fn)  return i;
         }
         return -1;
     }
@@ -333,7 +333,7 @@
         if (oldFns.isEmpty())  return this;
         for (int i = arity; i < length; i++) {
             Name n = names[i];
-            int nfi = oldFns.indexOf(n.function);
+            int nfi = indexOf(n.function, oldFns);
             if (nfi >= 0 && Arrays.equals(n.arguments, forArguments)) {
                 changeName(i, new Name(newFns.get(nfi), n.arguments));
             }
--- a/src/java.base/share/classes/java/lang/invoke/MethodHandle.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/java.base/share/classes/java/lang/invoke/MethodHandle.java	Mon Nov 27 17:04:45 2017 +0000
@@ -886,9 +886,13 @@
      * to the target method handle.
      * (The array may also be null when zero elements are required.)
      * <p>
-     * If, when the adapter is called, the supplied array argument does
-     * not have the correct number of elements, the adapter will throw
-     * an {@link IllegalArgumentException} instead of invoking the target.
+     * When the adapter is called, the length of the supplied {@code array}
+     * argument is queried as if by {@code array.length} or {@code arraylength}
+     * bytecode. If the adapter accepts a zero-length trailing array argument,
+     * the supplied {@code array} argument can either be a zero-length array or
+     * {@code null}; otherwise, the adapter will throw a {@code NullPointerException}
+     * if the array is {@code null} and throw an {@link IllegalArgumentException}
+     * if the array does not have the correct number of elements.
      * <p>
      * Here are some simple examples of array-spreading method handles:
      * <blockquote><pre>{@code
@@ -902,7 +906,7 @@
 assert(!(boolean) eq2.invokeExact(new Object[]{ "me", "thee" }));
 // try to spread from anything but a 2-array:
 for (int n = 0; n <= 10; n++) {
-  Object[] badArityArgs = (n == 2 ? null : new Object[n]);
+  Object[] badArityArgs = (n == 2 ? new Object[0] : new Object[n]);
   try { assert((boolean) eq2.invokeExact(badArityArgs) && false); }
   catch (IllegalArgumentException ex) { } // OK
 }
--- a/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java	Mon Nov 27 17:04:45 2017 +0000
@@ -662,8 +662,10 @@
     }
 
     static void checkSpreadArgument(Object av, int n) {
-        if (av == null) {
-            if (n == 0)  return;
+        if (av == null && n == 0) {
+            return;
+        } else if (av == null) {
+            throw new NullPointerException("null array reference");
         } else if (av instanceof Object[]) {
             int len = ((Object[])av).length;
             if (len == n)  return;
--- a/src/java.base/share/classes/java/lang/invoke/MethodHandles.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/java.base/share/classes/java/lang/invoke/MethodHandles.java	Mon Nov 27 17:04:45 2017 +0000
@@ -2514,14 +2514,20 @@
     }
 
     /**
-     * Produces a method handle constructing arrays of a desired type.
+     * Produces a method handle constructing arrays of a desired type,
+     * as if by the {@code anewarray} bytecode.
      * The return type of the method handle will be the array type.
      * The type of its sole argument will be {@code int}, which specifies the size of the array.
+     *
+     * <p> If the returned method handle is invoked with a negative
+     * array size, a {@code NegativeArraySizeException} will be thrown.
+     *
      * @param arrayClass an array type
      * @return a method handle which can create arrays of the given type
      * @throws NullPointerException if the argument is {@code null}
      * @throws IllegalArgumentException if {@code arrayClass} is not an array type
      * @see java.lang.reflect.Array#newInstance(Class, int)
+     * @jvms 6.5 {@code anewarray} Instruction
      * @since 9
      */
     public static
@@ -2535,13 +2541,19 @@
     }
 
     /**
-     * Produces a method handle returning the length of an array.
+     * Produces a method handle returning the length of an array,
+     * as if by the {@code arraylength} bytecode.
      * The type of the method handle will have {@code int} as return type,
      * and its sole argument will be the array type.
+     *
+     * <p> If the returned method handle is invoked with a {@code null}
+     * array reference, a {@code NullPointerException} will be thrown.
+     *
      * @param arrayClass an array type
      * @return a method handle which can retrieve the length of an array of the given array type
      * @throws NullPointerException if the argument is {@code null}
      * @throws IllegalArgumentException if arrayClass is not an array type
+     * @jvms 6.5 {@code arraylength} Instruction
      * @since 9
      */
     public static
@@ -2550,14 +2562,24 @@
     }
 
     /**
-     * Produces a method handle giving read access to elements of an array.
+     * Produces a method handle giving read access to elements of an array,
+     * as if by the {@code aaload} bytecode.
      * The type of the method handle will have a return type of the array's
      * element type.  Its first argument will be the array type,
      * and the second will be {@code int}.
+     *
+     * <p> When the returned method handle is invoked,
+     * the array reference and array index are checked.
+     * A {@code NullPointerException} will be thrown if the array reference
+     * is {@code null} and an {@code ArrayIndexOutOfBoundsException} will be
+     * thrown if the index is negative or if it is greater than or equal to
+     * the length of the array.
+     *
      * @param arrayClass an array type
      * @return a method handle which can load values from the given array type
      * @throws NullPointerException if the argument is null
      * @throws  IllegalArgumentException if arrayClass is not an array type
+     * @jvms 6.5 {@code aaload} Instruction
      */
     public static
     MethodHandle arrayElementGetter(Class<?> arrayClass) throws IllegalArgumentException {
@@ -2565,14 +2587,24 @@
     }
 
     /**
-     * Produces a method handle giving write access to elements of an array.
+     * Produces a method handle giving write access to elements of an array,
+     * as if by the {@code astore} bytecode.
      * The type of the method handle will have a void return type.
      * Its last argument will be the array's element type.
      * The first and second arguments will be the array type and int.
+     *
+     * <p> When the returned method handle is invoked,
+     * the array reference and array index are checked.
+     * A {@code NullPointerException} will be thrown if the array reference
+     * is {@code null} and an {@code ArrayIndexOutOfBoundsException} will be
+     * thrown if the index is negative or if it is greater than or equal to
+     * the length of the array.
+     *
      * @param arrayClass the class of an array
      * @return a method handle which can store values into the array type
      * @throws NullPointerException if the argument is null
      * @throws IllegalArgumentException if arrayClass is not an array type
+     * @jvms 6.5 {@code aastore} Instruction
      */
     public static
     MethodHandle arrayElementSetter(Class<?> arrayClass) throws IllegalArgumentException {
@@ -2603,6 +2635,14 @@
      * and atomic update access modes compare values using their bitwise
      * representation (see {@link Float#floatToRawIntBits} and
      * {@link Double#doubleToRawLongBits}, respectively).
+     *
+     * <p> When the returned {@code VarHandle} is invoked,
+     * the array reference and array index are checked.
+     * A {@code NullPointerException} will be thrown if the array reference
+     * is {@code null} and an {@code ArrayIndexOutOfBoundsException} will be
+     * thrown if the index is negative or if it is greater than or equal to
+     * the length of the array.
+     *
      * @apiNote
      * Bitwise comparison of {@code float} values or {@code double} values,
      * as performed by the numeric and atomic update access modes, differ
--- a/src/java.base/share/classes/java/lang/invoke/VarForm.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/java.base/share/classes/java/lang/invoke/VarForm.java	Mon Nov 27 17:04:45 2017 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2017, 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
@@ -71,7 +71,7 @@
 
         // (Receiver, <Intermediates>, Value, Value)boolean
         l.add(value);
-        methodType_table[VarHandle.AccessType.COMPARE_AND_SWAP.ordinal()] =
+        methodType_table[VarHandle.AccessType.COMPARE_AND_SET.ordinal()] =
                 MethodType.methodType(boolean.class, l).erase();
 
         // (Receiver, <Intermediates>, Value, Value)Value
--- a/src/java.base/share/classes/java/lang/invoke/VarHandle.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/java.base/share/classes/java/lang/invoke/VarHandle.java	Mon Nov 27 17:04:45 2017 +0000
@@ -30,7 +30,6 @@
 import jdk.internal.vm.annotation.ForceInline;
 import jdk.internal.vm.annotation.Stable;
 
-import java.lang.reflect.Method;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -46,7 +45,7 @@
  * non-static fields, array elements, or components of an off-heap data
  * structure.  Access to such variables is supported under various
  * <em>access modes</em>, including plain read/write access, volatile
- * read/write access, and compare-and-swap.
+ * read/write access, and compare-and-set.
  *
  * <p>VarHandles are immutable and have no visible state.  VarHandles cannot be
  * subclassed by the user.
@@ -1529,7 +1528,7 @@
     enum AccessType {
         GET(Object.class),
         SET(void.class),
-        COMPARE_AND_SWAP(boolean.class),
+        COMPARE_AND_SET(boolean.class),
         COMPARE_AND_EXCHANGE(Object.class),
         GET_AND_UPDATE(Object.class);
 
@@ -1555,7 +1554,7 @@
                     i = fillParameters(ps, receiver, intermediate);
                     ps[i] = value;
                     return MethodType.methodType(void.class, ps);
-                case COMPARE_AND_SWAP:
+                case COMPARE_AND_SET:
                     ps = allocateParameters(2, receiver, intermediate);
                     i = fillParameters(ps, receiver, intermediate);
                     ps[i++] = value;
@@ -1652,7 +1651,7 @@
          * method
          * {@link VarHandle#compareAndSet VarHandle.compareAndSet}
          */
-        COMPARE_AND_SET("compareAndSet", AccessType.COMPARE_AND_SWAP),
+        COMPARE_AND_SET("compareAndSet", AccessType.COMPARE_AND_SET),
         /**
          * The access mode whose access is specified by the corresponding
          * method
@@ -1676,25 +1675,25 @@
          * method
          * {@link VarHandle#weakCompareAndSetPlain VarHandle.weakCompareAndSetPlain}
          */
-        WEAK_COMPARE_AND_SET_PLAIN("weakCompareAndSetPlain", AccessType.COMPARE_AND_SWAP),
+        WEAK_COMPARE_AND_SET_PLAIN("weakCompareAndSetPlain", AccessType.COMPARE_AND_SET),
         /**
          * The access mode whose access is specified by the corresponding
          * method
          * {@link VarHandle#weakCompareAndSet VarHandle.weakCompareAndSet}
          */
-        WEAK_COMPARE_AND_SET("weakCompareAndSet", AccessType.COMPARE_AND_SWAP),
+        WEAK_COMPARE_AND_SET("weakCompareAndSet", AccessType.COMPARE_AND_SET),
         /**
          * The access mode whose access is specified by the corresponding
          * method
          * {@link VarHandle#weakCompareAndSetAcquire VarHandle.weakCompareAndSetAcquire}
          */
-        WEAK_COMPARE_AND_SET_ACQUIRE("weakCompareAndSetAcquire", AccessType.COMPARE_AND_SWAP),
+        WEAK_COMPARE_AND_SET_ACQUIRE("weakCompareAndSetAcquire", AccessType.COMPARE_AND_SET),
         /**
          * The access mode whose access is specified by the corresponding
          * method
          * {@link VarHandle#weakCompareAndSetRelease VarHandle.weakCompareAndSetRelease}
          */
-        WEAK_COMPARE_AND_SET_RELEASE("weakCompareAndSetRelease", AccessType.COMPARE_AND_SWAP),
+        WEAK_COMPARE_AND_SET_RELEASE("weakCompareAndSetRelease", AccessType.COMPARE_AND_SET),
         /**
          * The access mode whose access is specified by the corresponding
          * method
--- a/src/java.base/share/classes/java/lang/invoke/VarHandles.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/java.base/share/classes/java/lang/invoke/VarHandles.java	Mon Nov 27 17:04:45 2017 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2017, 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
@@ -313,7 +313,7 @@
 //
 //            void set(Object value);
 //
-//            boolean compareAndSwap(Object actualValue, Object expectedValue);
+//            boolean compareAndSet(Object actualValue, Object expectedValue);
 //
 //            Object compareAndExchange(Object actualValue, Object expectedValue);
 //
--- a/src/java.base/share/classes/java/lang/module/ModuleDescriptor.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/java.base/share/classes/java/lang/module/ModuleDescriptor.java	Mon Nov 27 17:04:45 2017 +0000
@@ -1593,7 +1593,7 @@
         /**
          * Adds a dependence on a module with the given (and possibly empty)
          * set of modifiers. The dependence includes the version of the
-         * module that that was recorded at compile-time.
+         * module that was recorded at compile-time.
          *
          * @param  ms
          *         The set of modifiers
--- a/src/java.base/share/classes/java/lang/module/Resolver.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/java.base/share/classes/java/lang/module/Resolver.java	Mon Nov 27 17:04:45 2017 +0000
@@ -217,7 +217,7 @@
     Resolver bind() {
 
         // Scan the finders for all available service provider modules. As
-        // java.base uses services then then module finders will be scanned
+        // java.base uses services then the module finders will be scanned
         // anyway.
         Map<String, Set<ModuleReference>> availableProviders = new HashMap<>();
         for (ModuleReference mref : findAll()) {
--- a/src/java.base/share/classes/java/math/BigInteger.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/java.base/share/classes/java/math/BigInteger.java	Mon Nov 27 17:04:45 2017 +0000
@@ -2741,7 +2741,7 @@
          return z;
     }
 
-    // These methods are intended to be be replaced by virtual machine
+    // These methods are intended to be replaced by virtual machine
     // intrinsics.
     @HotSpotIntrinsicCandidate
     private static int[] implMontgomeryMultiply(int[] a, int[] b, int[] n, int len,
--- a/src/java.base/share/classes/java/util/List.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/java.base/share/classes/java/util/List.java	Mon Nov 27 17:04:45 2017 +0000
@@ -442,7 +442,8 @@
 
     /**
      * Sorts this list according to the order induced by the specified
-     * {@link Comparator}.
+     * {@link Comparator}.  The sort is <i>stable</i>: this method must not
+     * reorder equal elements.
      *
      * <p>All elements in this list must be <i>mutually comparable</i> using the
      * specified comparator (that is, {@code c.compare(e1, e2)} must not throw
--- a/src/java.base/share/classes/jdk/internal/loader/URLClassPath.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/java.base/share/classes/jdk/internal/loader/URLClassPath.java	Mon Nov 27 17:04:45 2017 +0000
@@ -687,7 +687,7 @@
     }
 
     /*
-     * Nested class class used to represent a Loader of resources from a JAR URL.
+     * Nested class used to represent a Loader of resources from a JAR URL.
      */
     static class JarLoader extends Loader {
         private JarFile jar;
--- a/src/java.base/share/classes/jdk/internal/misc/JavaLangAccess.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/java.base/share/classes/jdk/internal/misc/JavaLangAccess.java	Mon Nov 27 17:04:45 2017 +0000
@@ -58,7 +58,7 @@
     ConstantPool getConstantPool(Class<?> klass);
 
     /**
-     * Compare-And-Swap the AnnotationType instance corresponding to this class.
+     * Compare-And-Set the AnnotationType instance corresponding to this class.
      * (This method only applies to annotation types.)
      */
     boolean casAnnotationType(Class<?> klass, AnnotationType oldType, AnnotationType newType);
@@ -254,7 +254,7 @@
     ServicesCatalog getServicesCatalog(ModuleLayer layer);
 
     /**
-     * Returns an ordered stream of layers. The first element is is the
+     * Returns an ordered stream of layers. The first element is the
      * given layer, the remaining elements are its parents, in DFS order.
      */
     Stream<ModuleLayer> layers(ModuleLayer layer);
--- a/src/java.base/share/classes/jdk/internal/misc/Unsafe.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/java.base/share/classes/jdk/internal/misc/Unsafe.java	Mon Nov 27 17:04:45 2017 +0000
@@ -572,7 +572,7 @@
         checkPointer(o, offset);
 
         if (o != null) {
-            // If on heap, it it must be a primitive array
+            // If on heap, it must be a primitive array
             checkPrimitiveArray(o.getClass());
         }
     }
--- a/src/java.base/share/classes/jdk/internal/module/ModulePath.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/java.base/share/classes/jdk/internal/module/ModulePath.java	Mon Nov 27 17:04:45 2017 +0000
@@ -112,7 +112,7 @@
     }
 
     /**
-     * Returns a ModuleFinder that that locates modules on the file system by
+     * Returns a ModuleFinder that locates modules on the file system by
      * searching a sequence of directories and/or packaged modules. The modules
      * may be patched by the given ModulePatcher.
      */
@@ -121,7 +121,7 @@
     }
 
     /**
-     * Returns a ModuleFinder that that locates modules on the file system by
+     * Returns a ModuleFinder that locates modules on the file system by
      * searching a sequence of directories and/or packaged modules.
      */
     public static ModuleFinder of(Path... entries) {
@@ -129,7 +129,7 @@
     }
 
     /**
-     * Returns a ModuleFinder that that locates modules on the file system by
+     * Returns a ModuleFinder that locates modules on the file system by
      * searching a sequence of directories and/or packaged modules.
      *
      * @param version The release version to use for multi-release JAR files
--- a/src/java.base/share/classes/jdk/internal/module/Modules.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/java.base/share/classes/jdk/internal/module/Modules.java	Mon Nov 27 17:04:45 2017 +0000
@@ -65,7 +65,7 @@
      * Creates a new Module. The module has the given ModuleDescriptor and
      * is defined to the given class loader.
      *
-     * The resulting Module is in a larval state in that it does not not read
+     * The resulting Module is in a larval state in that it does not read
      * any other module and does not have any exports.
      *
      * The URI is for information purposes only.
--- a/src/java.base/share/classes/jdk/internal/module/SystemModulesMap.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/java.base/share/classes/jdk/internal/module/SystemModulesMap.java	Mon Nov 27 17:04:45 2017 +0000
@@ -59,7 +59,7 @@
     }
 
     /**
-     * Returns the array of of SystemModules class names. The elements
+     * Returns the array of SystemModules class names. The elements
      * correspond to the elements in the array returned by moduleNames().
      */
     static String[] classNames() {
--- a/src/java.base/share/classes/sun/net/idn/StringPrep.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/java.base/share/classes/sun/net/idn/StringPrep.java	Mon Nov 27 17:04:45 2017 +0000
@@ -212,7 +212,7 @@
 
         //indexes[INDEX_MAPPING_DATA_SIZE] store the size of mappingData in bytes
         mappingData = new char[indexes[INDEX_MAPPING_DATA_SIZE]/2];
-        // load the rest of the data data and initialize the data members
+        // load the rest of the data and initialize the data members
         reader.read(sprepBytes,mappingData);
 
         sprepTrieImpl           = new StringPrepTrieImpl();
--- a/src/java.base/share/classes/sun/net/www/MimeEntry.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/java.base/share/classes/sun/net/www/MimeEntry.java	Mon Nov 27 17:04:45 2017 +0000
@@ -252,7 +252,7 @@
             }
 
         case UNKNOWN:
-            // REMIND: What do do here?
+            // REMIND: What to do here?
             return null;
         }
 
--- a/src/java.base/share/classes/sun/security/provider/certpath/PolicyNodeImpl.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/java.base/share/classes/sun/security/provider/certpath/PolicyNodeImpl.java	Mon Nov 27 17:04:45 2017 +0000
@@ -306,7 +306,7 @@
     }
 
     /**
-     * Add all nodes at depth depth to set and return the Set.
+     * Add all nodes at depth to set and return the Set.
      * Internal recursion helper.
      */
     private void getPolicyNodes(int depth, Set<PolicyNodeImpl> set) {
--- a/src/java.base/share/classes/sun/security/x509/PrivateKeyUsageExtension.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/java.base/share/classes/sun/security/x509/PrivateKeyUsageExtension.java	Mon Nov 27 17:04:45 2017 +0000
@@ -195,7 +195,7 @@
     }
 
     /**
-     * Verify that that the current time is within the validity period.
+     * Verify that the current time is within the validity period.
      *
      * @exception CertificateExpiredException if the certificate has expired.
      * @exception CertificateNotYetValidException if the certificate is not
@@ -208,7 +208,7 @@
     }
 
     /**
-     * Verify that that the passed time is within the validity period.
+     * Verify that the passed time is within the validity period.
      *
      * @exception CertificateExpiredException if the certificate has expired
      * with respect to the <code>Date</code> supplied.
--- a/src/java.base/solaris/native/libjvm_dtrace/jvm_dtrace.c	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/java.base/solaris/native/libjvm_dtrace/jvm_dtrace.c	Mon Nov 27 17:04:45 2017 +0000
@@ -422,7 +422,7 @@
         print_debug("door_call failed\n");
     } else {
         /*
-         * door_call succeeded but the call didn't return the the expected jint.
+         * door_call succeeded but the call didn't return the expected jint.
          */
         if (door_args.data_size < sizeof(int)) {
             print_debug("Enqueue error - reason unknown as result is truncated!");
--- a/src/java.compiler/share/classes/javax/lang/model/util/AbstractAnnotationValueVisitor6.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/java.compiler/share/classes/javax/lang/model/util/AbstractAnnotationValueVisitor6.java	Mon Nov 27 17:04:45 2017 +0000
@@ -84,6 +84,7 @@
      * {@code v.visit(av, p)} is equivalent to {@code av.accept(v, p)}.
      * @param av {@inheritDoc}
      * @param p  {@inheritDoc}
+     * @return   {@inheritDoc}
      */
     public final R visit(AnnotationValue av, P p) {
         return av.accept(this, p);
@@ -96,6 +97,7 @@
      * {@code v.visit(av)} is equivalent to {@code av.accept(v,
      * null)}.
      * @param av {@inheritDoc}
+     * @return   {@inheritDoc}
      */
     public final R visit(AnnotationValue av) {
         return av.accept(this, null);
@@ -111,6 +113,7 @@
      *
      * @param av {@inheritDoc}
      * @param p  {@inheritDoc}
+     * @return   {@inheritDoc}
      */
     @Override
     public R visitUnknown(AnnotationValue av, P p) {
--- a/src/java.compiler/share/classes/javax/lang/model/util/AbstractElementVisitor6.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/java.compiler/share/classes/javax/lang/model/util/AbstractElementVisitor6.java	Mon Nov 27 17:04:45 2017 +0000
@@ -116,7 +116,7 @@
      *
      * @param e {@inheritDoc}
      * @param p {@inheritDoc}
-     * @return a visitor-specified result
+     * @return  {@inheritDoc}
      * @throws UnknownElementException
      *          a visitor implementation may optionally throw this exception
      */
@@ -133,7 +133,7 @@
      *
      * @param e  {@inheritDoc}
      * @param p  {@inheritDoc}
-     * @return the result of {@code visitUnknown}
+     * @return   {@inheritDoc}
      *
      * @since 9
      * @spec JPMS
--- a/src/java.compiler/share/classes/javax/lang/model/util/AbstractElementVisitor9.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/java.compiler/share/classes/javax/lang/model/util/AbstractElementVisitor9.java	Mon Nov 27 17:04:45 2017 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2017, 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
@@ -75,12 +75,14 @@
     }
 
     /**
-     * Visits a {@code ModuleElement} in a manner defined by a
+     * {@inheritDoc}
+     *
+     * @implSpec Visits a {@code ModuleElement} in a manner defined by a
      * subclass.
      *
      * @param t  {@inheritDoc}
      * @param p  {@inheritDoc}
-     * @return the result of the visit as defined by a subclass
+     * @return   {@inheritDoc}
      */
     @Override
     public abstract R visitModule(ModuleElement t, P p);
--- a/src/java.compiler/share/classes/javax/lang/model/util/ElementKindVisitor6.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/java.compiler/share/classes/javax/lang/model/util/ElementKindVisitor6.java	Mon Nov 27 17:04:45 2017 +0000
@@ -114,6 +114,8 @@
      *
      * The element argument has kind {@code PACKAGE}.
      *
+     * @implSpec This implementation calls {@code defaultAction}.
+     *
      * @param e {@inheritDoc}
      * @param p {@inheritDoc}
      * @return  {@inheritDoc}
@@ -125,7 +127,9 @@
     }
 
     /**
-     * Visits a type element, dispatching to the visit method for the
+     * {@inheritDoc}
+     *
+     * @implSpec This implementation dispatches to the visit method for the
      * specific {@linkplain ElementKind kind} of type, {@code
      * ANNOTATION_TYPE}, {@code CLASS}, {@code ENUM}, or {@code
      * INTERFACE}.
@@ -156,8 +160,9 @@
     }
 
     /**
-     * Visits an {@code ANNOTATION_TYPE} type element by calling
-     * {@code defaultAction}.
+     * Visits an {@code ANNOTATION_TYPE} type element.
+     *
+     * @implSpec This implementation calls {@code defaultAction}.
      *
      * @param e the element to visit
      * @param p a visitor-specified parameter
@@ -168,8 +173,9 @@
     }
 
     /**
-     * Visits a {@code CLASS} type element by calling {@code
-     * defaultAction}.
+     * Visits a {@code CLASS} type element.
+     *
+     * @implSpec This implementation calls {@code defaultAction}.
      *
      * @param e the element to visit
      * @param p a visitor-specified parameter
@@ -180,8 +186,9 @@
     }
 
     /**
-     * Visits an {@code ENUM} type element by calling {@code
-     * defaultAction}.
+     * Visits an {@code ENUM} type element.
+     *
+     * @implSpec This implementation calls {@code defaultAction}.
      *
      * @param e the element to visit
      * @param p a visitor-specified parameter
@@ -192,8 +199,9 @@
     }
 
     /**
-     * Visits an {@code INTERFACE} type element by calling {@code
-     * defaultAction}.
+     * Visits an {@code INTERFACE} type element.
+     *
+     * @implSpec This implementation calls {@code defaultAction}.
      *.
      * @param e the element to visit
      * @param p a visitor-specified parameter
@@ -204,7 +212,9 @@
     }
 
     /**
-     * Visits a variable element, dispatching to the visit method for
+     * Visits a variable element
+     *
+     * @implSpec This implementation dispatches to the visit method for
      * the specific {@linkplain ElementKind kind} of variable, {@code
      * ENUM_CONSTANT}, {@code EXCEPTION_PARAMETER}, {@code FIELD},
      * {@code LOCAL_VARIABLE}, {@code PARAMETER}, or {@code RESOURCE_VARIABLE}.
@@ -241,9 +251,10 @@
     }
 
     /**
-     * Visits an {@code ENUM_CONSTANT} variable element by calling
-     * {@code defaultAction}.
+     * Visits an {@code ENUM_CONSTANT} variable element.
      *
+     * @implSpec This implementation calls {@code defaultAction}.
+     *.
      * @param e the element to visit
      * @param p a visitor-specified parameter
      * @return  the result of {@code defaultAction}
@@ -253,9 +264,10 @@
     }
 
     /**
-     * Visits an {@code EXCEPTION_PARAMETER} variable element by calling
-     * {@code defaultAction}.
+     * Visits an {@code EXCEPTION_PARAMETER} variable element.
      *
+     * @implSpec This implementation calls {@code defaultAction}.
+     *.
      * @param e the element to visit
      * @param p a visitor-specified parameter
      * @return  the result of {@code defaultAction}
@@ -265,9 +277,10 @@
     }
 
     /**
-     * Visits a {@code FIELD} variable element by calling
-     * {@code defaultAction}.
+     * Visits a {@code FIELD} variable element.
      *
+     * @implSpec This implementation calls {@code defaultAction}.
+     *.
      * @param e the element to visit
      * @param p a visitor-specified parameter
      * @return  the result of {@code defaultAction}
@@ -277,8 +290,9 @@
     }
 
     /**
-     * Visits a {@code LOCAL_VARIABLE} variable element by calling
-     * {@code defaultAction}.
+     * Visits a {@code LOCAL_VARIABLE} variable element.
+     *
+     * @implSpec This implementation calls {@code defaultAction}.
      *
      * @param e the element to visit
      * @param p a visitor-specified parameter
@@ -289,8 +303,9 @@
     }
 
     /**
-     * Visits a {@code PARAMETER} variable element by calling
-     * {@code defaultAction}.
+     * Visits a {@code PARAMETER} variable element.
+     *
+     * @implSpec This implementation calls {@code defaultAction}.
      *
      * @param e the element to visit
      * @param p a visitor-specified parameter
@@ -301,8 +316,9 @@
     }
 
     /**
-     * Visits a {@code RESOURCE_VARIABLE} variable element by calling
-     * {@code visitUnknown}.
+     * Visits a {@code RESOURCE_VARIABLE} variable element.
+     *
+     * @implSpec This implementation calls {@code visitUnknown}.
      *
      * @param e the element to visit
      * @param p a visitor-specified parameter
@@ -315,7 +331,9 @@
     }
 
     /**
-     * Visits an executable element, dispatching to the visit method
+     * {@inheritDoc}
+     *
+     * @implSpec This implementation dispatches to the visit method
      * for the specific {@linkplain ElementKind kind} of executable,
      * {@code CONSTRUCTOR}, {@code INSTANCE_INIT}, {@code METHOD}, or
      * {@code STATIC_INIT}.
@@ -346,8 +364,9 @@
     }
 
     /**
-     * Visits a {@code CONSTRUCTOR} executable element by calling
-     * {@code defaultAction}.
+     * Visits a {@code CONSTRUCTOR} executable element.
+     *
+     * @implSpec This implementation calls {@code defaultAction}.
      *
      * @param e the element to visit
      * @param p a visitor-specified parameter
@@ -358,8 +377,9 @@
     }
 
     /**
-     * Visits an {@code INSTANCE_INIT} executable element by calling
-     * {@code defaultAction}.
+     * Visits an {@code INSTANCE_INIT} executable element.
+     *
+     * @implSpec This implementation calls {@code defaultAction}.
      *
      * @param e the element to visit
      * @param p a visitor-specified parameter
@@ -370,8 +390,9 @@
     }
 
     /**
-     * Visits a {@code METHOD} executable element by calling
-     * {@code defaultAction}.
+     * Visits a {@code METHOD} executable element.
+     *
+     * @implSpec This implementation calls {@code defaultAction}.
      *
      * @param e the element to visit
      * @param p a visitor-specified parameter
@@ -382,8 +403,9 @@
     }
 
     /**
-     * Visits a {@code STATIC_INIT} executable element by calling
-     * {@code defaultAction}.
+     * Visits a {@code STATIC_INIT} executable element.
+     *
+     * @implSpec This implementation calls {@code defaultAction}.
      *
      * @param e the element to visit
      * @param p a visitor-specified parameter
@@ -393,12 +415,13 @@
         return defaultAction(e, p);
     }
 
-
     /**
      * {@inheritDoc}
      *
      * The element argument has kind {@code TYPE_PARAMETER}.
      *
+     * @implSpec This implementation calls {@code defaultAction}.
+     *
      * @param e {@inheritDoc}
      * @param p {@inheritDoc}
      * @return  {@inheritDoc}
--- a/src/java.compiler/share/classes/javax/lang/model/util/ElementKindVisitor7.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/java.compiler/share/classes/javax/lang/model/util/ElementKindVisitor7.java	Mon Nov 27 17:04:45 2017 +0000
@@ -99,8 +99,9 @@
     }
 
     /**
-     * Visits a {@code RESOURCE_VARIABLE} variable element by calling
-     * {@code defaultAction}.
+     * {@inheritDoc}
+     *
+     * @implSpec This implementation calls {@code defaultAction}.
      *
      * @param e {@inheritDoc}
      * @param p {@inheritDoc}
--- a/src/java.compiler/share/classes/javax/lang/model/util/ElementKindVisitor9.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/java.compiler/share/classes/javax/lang/model/util/ElementKindVisitor9.java	Mon Nov 27 17:04:45 2017 +0000
@@ -98,8 +98,9 @@
     }
 
     /**
-     * Visits a {@code ModuleElement} by calling {@code
-     * defaultAction}.
+     * {@inheritDoc}
+     *
+     * @implSpec This implementation calls {@code defaultAction}.
      *
      * @param e the element to visit
      * @param p a visitor-specified parameter
--- a/src/java.compiler/share/classes/javax/lang/model/util/ElementScanner6.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/java.compiler/share/classes/javax/lang/model/util/ElementScanner6.java	Mon Nov 27 17:04:45 2017 +0000
@@ -164,7 +164,9 @@
     }
 
     /**
-     * {@inheritDoc} This implementation scans the enclosed elements.
+     * {@inheritDoc}
+     *
+     * @implSpec This implementation scans the enclosed elements.
      *
      * @param e  {@inheritDoc}
      * @param p  {@inheritDoc}
@@ -175,7 +177,9 @@
     }
 
     /**
-     * {@inheritDoc} This implementation scans the enclosed elements.
+     * {@inheritDoc}
+     *
+     * @implSpec This implementation scans the enclosed elements.
      *
      * @param e  {@inheritDoc}
      * @param p  {@inheritDoc}
@@ -188,7 +192,7 @@
     /**
      * {@inheritDoc}
      *
-     * This implementation scans the enclosed elements, unless the
+     * @implSpec This implementation scans the enclosed elements, unless the
      * element is a {@code RESOURCE_VARIABLE} in which case {@code
      * visitUnknown} is called.
      *
@@ -204,7 +208,9 @@
     }
 
     /**
-     * {@inheritDoc} This implementation scans the parameters.
+     * {@inheritDoc}
+     *
+     * @implSpec This implementation scans the parameters.
      *
      * @param e  {@inheritDoc}
      * @param p  {@inheritDoc}
@@ -215,7 +221,9 @@
     }
 
     /**
-     * {@inheritDoc} This implementation scans the enclosed elements.
+     * {@inheritDoc}
+     *
+     * @implSpec This implementation scans the enclosed elements.
      *
      * @param e  {@inheritDoc}
      * @param p  {@inheritDoc}
--- a/src/java.compiler/share/classes/javax/lang/model/util/ElementScanner7.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/java.compiler/share/classes/javax/lang/model/util/ElementScanner7.java	Mon Nov 27 17:04:45 2017 +0000
@@ -112,7 +112,9 @@
     }
 
     /**
-     * This implementation scans the enclosed elements.
+     * {@inheritDoc}
+     *
+     * @implSpec This implementation scans the enclosed elements.
      *
      * @param e  {@inheritDoc}
      * @param p  {@inheritDoc}
--- a/src/java.compiler/share/classes/javax/lang/model/util/ElementScanner9.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/java.compiler/share/classes/javax/lang/model/util/ElementScanner9.java	Mon Nov 27 17:04:45 2017 +0000
@@ -111,8 +111,9 @@
     }
 
     /**
-     * Visits a {@code ModuleElement} by scanning the enclosed
-     * elements.
+     * {@inheritDoc}
+     *
+     * @implSpec This implementation scans the enclosed elements.
      *
      * @param e the element to visit
      * @param p a visitor-specified parameter
--- a/src/java.compiler/share/classes/javax/lang/model/util/SimpleAnnotationValueVisitor6.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/java.compiler/share/classes/javax/lang/model/util/SimpleAnnotationValueVisitor6.java	Mon Nov 27 17:04:45 2017 +0000
@@ -113,9 +113,10 @@
     }
 
     /**
-     * The default action for visit methods.  The implementation in
-     * this class just returns {@link #DEFAULT_VALUE}; subclasses will
-     * commonly override this method.
+     * The default action for visit methods.
+     *
+     * @implSpec The implementation in this class just returns {@link
+     * #DEFAULT_VALUE}; subclasses will commonly override this method.
      *
      * @param o the value of the annotation
      * @param p a visitor-specified parameter
@@ -126,7 +127,9 @@
     }
 
     /**
-     * {@inheritDoc} This implementation calls {@code defaultAction}.
+     * {@inheritDoc}
+     *
+     * @implSpec This implementation calls {@code defaultAction}.
      *
      * @param b {@inheritDoc}
      * @param p {@inheritDoc}
@@ -137,7 +140,9 @@
     }
 
     /**
-     * {@inheritDoc} This implementation calls {@code defaultAction}.
+     * {@inheritDoc}
+     *
+     * @implSpec This implementation calls {@code defaultAction}.
      *
      * @param b {@inheritDoc}
      * @param p {@inheritDoc}
@@ -148,7 +153,9 @@
     }
 
     /**
-     * {@inheritDoc} This implementation calls {@code defaultAction}.
+     * {@inheritDoc}
+     *
+     * @implSpec This implementation calls {@code defaultAction}.
      *
      * @param c {@inheritDoc}
      * @param p {@inheritDoc}
@@ -159,7 +166,10 @@
     }
 
     /**
-     * {@inheritDoc} This implementation calls {@code defaultAction}.
+     * {@inheritDoc}
+     *
+     * @implSpec This implementation calls {@code defaultAction}.
+     *
      *
      * @param d {@inheritDoc}
      * @param p {@inheritDoc}
@@ -170,7 +180,10 @@
     }
 
     /**
-     * {@inheritDoc} This implementation calls {@code defaultAction}.
+     * {@inheritDoc}
+     *
+     * @implSpec This implementation calls {@code defaultAction}.
+     *
      *
      * @param f {@inheritDoc}
      * @param p {@inheritDoc}
@@ -181,7 +194,9 @@
     }
 
     /**
-     * {@inheritDoc} This implementation calls {@code defaultAction}.
+     * {@inheritDoc}
+     *
+     * @implSpec This implementation calls {@code defaultAction}.
      *
      * @param i {@inheritDoc}
      * @param p {@inheritDoc}
@@ -192,7 +207,9 @@
     }
 
     /**
-     * {@inheritDoc} This implementation calls {@code defaultAction}.
+     * {@inheritDoc}
+     *
+     * @implSpec This implementation calls {@code defaultAction}.
      *
      * @param i {@inheritDoc}
      * @param p {@inheritDoc}
@@ -203,7 +220,9 @@
     }
 
     /**
-     * {@inheritDoc} This implementation calls {@code defaultAction}.
+     * {@inheritDoc}
+     *
+     * @implSpec This implementation calls {@code defaultAction}.
      *
      * @param s {@inheritDoc}
      * @param p {@inheritDoc}
@@ -214,7 +233,9 @@
     }
 
     /**
-     * {@inheritDoc} This implementation calls {@code defaultAction}.
+     * {@inheritDoc}
+     *
+     * @implSpec This implementation calls {@code defaultAction}.
      *
      * @param s {@inheritDoc}
      * @param p {@inheritDoc}
@@ -225,7 +246,9 @@
     }
 
     /**
-     * {@inheritDoc} This implementation calls {@code defaultAction}.
+     * {@inheritDoc}
+     *
+     * @implSpec This implementation calls {@code defaultAction}.
      *
      * @param t {@inheritDoc}
      * @param p {@inheritDoc}
@@ -236,7 +259,9 @@
     }
 
     /**
-     * {@inheritDoc} This implementation calls {@code defaultAction}.
+     * {@inheritDoc}
+     *
+     * @implSpec This implementation calls {@code defaultAction}.
      *
      * @param c {@inheritDoc}
      * @param p {@inheritDoc}
@@ -247,7 +272,9 @@
     }
 
     /**
-     * {@inheritDoc} This implementation calls {@code defaultAction}.
+     * {@inheritDoc}
+     *
+     * @implSpec This implementation calls {@code defaultAction}.
      *
      * @param a {@inheritDoc}
      * @param p {@inheritDoc}
@@ -258,7 +285,9 @@
     }
 
     /**
-     * {@inheritDoc} This implementation calls {@code defaultAction}.
+     * {@inheritDoc}
+     *
+     * @implSpec This implementation calls {@code defaultAction}.
      *
      * @param vals {@inheritDoc}
      * @param p {@inheritDoc}
--- a/src/java.compiler/share/classes/javax/lang/model/util/SimpleElementVisitor6.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/java.compiler/share/classes/javax/lang/model/util/SimpleElementVisitor6.java	Mon Nov 27 17:04:45 2017 +0000
@@ -112,9 +112,10 @@
         DEFAULT_VALUE = defaultValue;
     }
     /**
-     * The default action for visit methods.  The implementation in
-     * this class just returns {@link #DEFAULT_VALUE}; subclasses will
-     * commonly override this method.
+     * The default action for visit methods.
+     *
+     * @implSpec The implementation in this class just returns {@link
+     * #DEFAULT_VALUE}; subclasses will commonly override this method.
      *
      * @param e the element to process
      * @param p a visitor-specified parameter
@@ -125,22 +126,26 @@
     }
 
     /**
-     * {@inheritDoc} This implementation calls {@code defaultAction}.
+     * {@inheritDoc}
+     *
+     * @implSpec This implementation calls {@code defaultAction}.
      *
      * @param e {@inheritDoc}
      * @param p {@inheritDoc}
-     * @return  the result of {@code defaultAction}
+     * @return  {@inheritDoc}
      */
     public R visitPackage(PackageElement e, P p) {
         return defaultAction(e, p);
     }
 
     /**
-     * {@inheritDoc} This implementation calls {@code defaultAction}.
+     * {@inheritDoc}
+     *
+     * @implSpec This implementation calls {@code defaultAction}.
      *
      * @param e {@inheritDoc}
      * @param p {@inheritDoc}
-     * @return  the result of {@code defaultAction}
+     * @return  {@inheritDoc}
      */
     public R visitType(TypeElement e, P p) {
         return defaultAction(e, p);
@@ -149,13 +154,13 @@
     /**
      * {@inheritDoc}
      *
-     * This implementation calls {@code defaultAction}, unless the
+     * @implSpec This implementation calls {@code defaultAction}, unless the
      * element is a {@code RESOURCE_VARIABLE} in which case {@code
      * visitUnknown} is called.
      *
      * @param e {@inheritDoc}
      * @param p {@inheritDoc}
-     * @return  the result of {@code defaultAction} or {@code visitUnknown}
+     * @return  {@inheritDoc}
      */
     public R visitVariable(VariableElement e, P p) {
         if (e.getKind() != ElementKind.RESOURCE_VARIABLE)
@@ -165,22 +170,26 @@
     }
 
     /**
-     * {@inheritDoc} This implementation calls {@code defaultAction}.
+     * {@inheritDoc}
+     *
+     * @implSpec This implementation calls {@code defaultAction}.
      *
      * @param e {@inheritDoc}
      * @param p {@inheritDoc}
-     * @return  the result of {@code defaultAction}
+     * @return  {@inheritDoc}
      */
     public R visitExecutable(ExecutableElement e, P p) {
         return defaultAction(e, p);
     }
 
     /**
-     * {@inheritDoc} This implementation calls {@code defaultAction}.
+     * {@inheritDoc}
+     *
+     * @implSpec This implementation calls {@code defaultAction}.
      *
      * @param e {@inheritDoc}
      * @param p {@inheritDoc}
-     * @return  the result of {@code defaultAction}
+     * @return  {@inheritDoc}
      */
     public R visitTypeParameter(TypeParameterElement e, P p) {
         return defaultAction(e, p);
--- a/src/java.compiler/share/classes/javax/lang/model/util/SimpleElementVisitor7.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/java.compiler/share/classes/javax/lang/model/util/SimpleElementVisitor7.java	Mon Nov 27 17:04:45 2017 +0000
@@ -95,11 +95,13 @@
     }
 
     /**
-     * This implementation calls {@code defaultAction}.
+     * {@inheritDoc}
+     *
+     * @implSpec This implementation calls {@code defaultAction}.
      *
      * @param e {@inheritDoc}
      * @param p {@inheritDoc}
-     * @return  the result of {@code defaultAction}
+     * @return  {@inheritDoc}
      */
     @Override
     public R visitVariable(VariableElement e, P p) {
--- a/src/java.compiler/share/classes/javax/lang/model/util/SimpleElementVisitor9.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/java.compiler/share/classes/javax/lang/model/util/SimpleElementVisitor9.java	Mon Nov 27 17:04:45 2017 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2017, 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
@@ -94,12 +94,14 @@
     }
 
     /**
-     * Visits a {@code ModuleElement} by calling {@code
+     * {@inheritDoc}
+     *
+     * @implSpec Visits a {@code ModuleElement} by calling {@code
      * defaultAction}.
      *
      * @param e the element to visit
      * @param p a visitor-specified parameter
-     * @return  the result of {@code defaultAction}
+     * @return  {@inheritDoc}
      */
     @Override
     public R visitModule(ModuleElement e, P p) {
--- a/src/java.compiler/share/classes/javax/lang/model/util/SimpleTypeVisitor6.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/java.compiler/share/classes/javax/lang/model/util/SimpleTypeVisitor6.java	Mon Nov 27 17:04:45 2017 +0000
@@ -113,9 +113,10 @@
     }
 
     /**
-     * The default action for visit methods.  The implementation in
-     * this class just returns {@link #DEFAULT_VALUE}; subclasses will
-     * commonly override this method.
+     * The default action for visit methods.
+     *
+     * @implSpec The implementation in this class just returns {@link
+     * #DEFAULT_VALUE}; subclasses will commonly override this method.
      *
      * @param e the type to process
      * @param p a visitor-specified parameter
@@ -126,7 +127,9 @@
     }
 
     /**
-     * {@inheritDoc} This implementation calls {@code defaultAction}.
+     * {@inheritDoc}
+     *
+     * @implSpec This implementation calls {@code defaultAction}.
      *
      * @param t {@inheritDoc}
      * @param p {@inheritDoc}
@@ -139,6 +142,8 @@
     /**
      * {@inheritDoc} This implementation calls {@code defaultAction}.
      *
+     * @implSpec This implementation calls {@code defaultAction}.
+     *
      * @param t {@inheritDoc}
      * @param p {@inheritDoc}
      * @return  the result of {@code defaultAction}
@@ -148,7 +153,9 @@
     }
 
     /**
-     * {@inheritDoc} This implementation calls {@code defaultAction}.
+     * {@inheritDoc}
+     *
+     * @implSpec This implementation calls {@code defaultAction}.
      *
      * @param t {@inheritDoc}
      * @param p {@inheritDoc}
@@ -159,7 +166,9 @@
     }
 
     /**
-     * {@inheritDoc} This implementation calls {@code defaultAction}.
+     * {@inheritDoc}
+     *
+     * @implSpec This implementation calls {@code defaultAction}.
      *
      * @param t {@inheritDoc}
      * @param p {@inheritDoc}
@@ -170,7 +179,9 @@
     }
 
     /**
-     * {@inheritDoc} This implementation calls {@code defaultAction}.
+     * {@inheritDoc}
+     *
+     * @implSpec This implementation calls {@code defaultAction}.
      *
      * @param t {@inheritDoc}
      * @param p {@inheritDoc}
@@ -181,7 +192,9 @@
     }
 
     /**
-     * {@inheritDoc} This implementation calls {@code defaultAction}.
+     * {@inheritDoc}
+     *
+     * @implSpec This implementation calls {@code defaultAction}.
      *
      * @param t {@inheritDoc}
      * @param p {@inheritDoc}
@@ -192,7 +205,9 @@
     }
 
     /**
-     * {@inheritDoc} This implementation calls {@code defaultAction}.
+     * {@inheritDoc}
+     *
+     * @implSpec This implementation calls {@code defaultAction}.
      *
      * @param t {@inheritDoc}
      * @param p {@inheritDoc}
@@ -203,7 +218,9 @@
     }
 
     /**
-     * {@inheritDoc} This implementation calls {@code defaultAction}.
+     * {@inheritDoc}
+     *
+     * @implSpec This implementation calls {@code defaultAction}.
      *
      * @param t {@inheritDoc}
      * @param p {@inheritDoc}
@@ -214,7 +231,9 @@
     }
 
     /**
-     * {@inheritDoc} This implementation calls {@code defaultAction}.
+     * {@inheritDoc}
+     *
+     * @implSpec This implementation calls {@code defaultAction}.
      *
      * @param t {@inheritDoc}
      * @param p {@inheritDoc}
--- a/src/java.compiler/share/classes/javax/lang/model/util/SimpleTypeVisitor7.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/java.compiler/share/classes/javax/lang/model/util/SimpleTypeVisitor7.java	Mon Nov 27 17:04:45 2017 +0000
@@ -95,8 +95,9 @@
     }
 
     /**
-     * This implementation visits a {@code UnionType} by calling
-     * {@code defaultAction}.
+     * {@inheritDoc}
+     *
+     * @implSpec This implementation calls {@code defaultAction}.
      *
      * @param t  {@inheritDoc}
      * @param p  {@inheritDoc}
--- a/src/java.compiler/share/classes/javax/lang/model/util/SimpleTypeVisitor8.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/java.compiler/share/classes/javax/lang/model/util/SimpleTypeVisitor8.java	Mon Nov 27 17:04:45 2017 +0000
@@ -93,8 +93,9 @@
     }
 
     /**
-     * This implementation visits an {@code IntersectionType} by calling
-     * {@code defaultAction}.
+     * {@inheritDoc}
+     *
+     * @implSpec This implementation calls {@code defaultAction}.
      *
      * @param t {@inheritDoc}
      * @param p {@inheritDoc}
--- a/src/java.compiler/share/classes/javax/lang/model/util/TypeKindVisitor6.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/java.compiler/share/classes/javax/lang/model/util/TypeKindVisitor6.java	Mon Nov 27 17:04:45 2017 +0000
@@ -105,7 +105,9 @@
     }
 
     /**
-     * Visits a primitive type, dispatching to the visit method for
+     * {@inheritDoc}
+     *
+     * @implSpec This implementation dispatches to the visit method for
      * the specific {@linkplain TypeKind kind} of primitive type:
      * {@code BOOLEAN}, {@code BYTE}, etc.
      *
@@ -147,8 +149,9 @@
     }
 
     /**
-     * Visits a {@code BOOLEAN} primitive type by calling
-     * {@code defaultAction}.
+     * Visits a {@code BOOLEAN} primitive type.
+     *
+     * @implSpec This implementation calls {@code defaultAction}.
      *
      * @param t the type to visit
      * @param p a visitor-specified parameter
@@ -159,8 +162,9 @@
     }
 
     /**
-     * Visits a {@code BYTE} primitive type by calling
-     * {@code defaultAction}.
+     * Visits a {@code BYTE} primitive type.
+     *
+     * @implSpec This implementation calls {@code defaultAction}.
      *
      * @param t the type to visit
      * @param p a visitor-specified parameter
@@ -171,8 +175,9 @@
     }
 
     /**
-     * Visits a {@code SHORT} primitive type by calling
-     * {@code defaultAction}.
+     * Visits a {@code SHORT} primitive type.
+     *
+     * @implSpec This implementation calls {@code defaultAction}.
      *
      * @param t the type to visit
      * @param p a visitor-specified parameter
@@ -183,8 +188,9 @@
     }
 
     /**
-     * Visits an {@code INT} primitive type by calling
-     * {@code defaultAction}.
+     * Visits an {@code INT} primitive type.
+     *
+     * @implSpec This implementation calls {@code defaultAction}.
      *
      * @param t the type to visit
      * @param p a visitor-specified parameter
@@ -195,8 +201,9 @@
     }
 
     /**
-     * Visits a {@code LONG} primitive type by calling
-     * {@code defaultAction}.
+     * Visits a {@code LONG} primitive type.
+     *
+     * @implSpec This implementation calls {@code defaultAction}.
      *
      * @param t the type to visit
      * @param p a visitor-specified parameter
@@ -207,8 +214,9 @@
     }
 
     /**
-     * Visits a {@code CHAR} primitive type by calling
-     * {@code defaultAction}.
+     * Visits a {@code CHAR} primitive type.
+     *
+     * @implSpec This implementation calls {@code defaultAction}.
      *
      * @param t the type to visit
      * @param p a visitor-specified parameter
@@ -219,8 +227,9 @@
     }
 
     /**
-     * Visits a {@code FLOAT} primitive type by calling
-     * {@code defaultAction}.
+     * Visits a {@code FLOAT} primitive type.
+     *
+     * @implSpec This implementation calls {@code defaultAction}.
      *
      * @param t the type to visit
      * @param p a visitor-specified parameter
@@ -231,8 +240,9 @@
     }
 
     /**
-     * Visits a {@code DOUBLE} primitive type by calling
-     * {@code defaultAction}.
+     * Visits a {@code DOUBLE} primitive type.
+     *
+     * @implSpec This implementation calls {@code defaultAction}.
      *
      * @param t the type to visit
      * @param p a visitor-specified parameter
@@ -243,7 +253,9 @@
     }
 
     /**
-     * Visits a {@link NoType} instance, dispatching to the visit method for
+     * {@inheritDoc}
+     *
+     * @implSpec This implementation dispatches to the visit method for
      * the specific {@linkplain TypeKind kind} of pseudo-type:
      * {@code VOID}, {@code PACKAGE}, or {@code NONE}.
      *
@@ -270,8 +282,9 @@
     }
 
     /**
-     * Visits a {@link TypeKind#VOID VOID} pseudo-type by calling
-     * {@code defaultAction}.
+     * Visits a {@link TypeKind#VOID VOID} pseudo-type.
+     *
+     * @implSpec This implementation calls {@code defaultAction}.
      *
      * @param t the type to visit
      * @param p a visitor-specified parameter
@@ -282,8 +295,9 @@
     }
 
     /**
-     * Visits a {@link TypeKind#PACKAGE PACKAGE} pseudo-type by calling
-     * {@code defaultAction}.
+     * Visits a {@link TypeKind#PACKAGE PACKAGE} pseudo-type.
+     *
+     * @implSpec This implementation calls {@code defaultAction}.
      *
      * @param t the type to visit
      * @param p a visitor-specified parameter
@@ -294,8 +308,9 @@
     }
 
     /**
-     * Visits a {@link TypeKind#NONE NONE} pseudo-type by calling
-     * {@code defaultAction}.
+     * Visits a {@link TypeKind#NONE NONE} pseudo-type.
+     *
+     * @implSpec This implementation calls {@code defaultAction}.
      *
      * @param t the type to visit
      * @param p a visitor-specified parameter
--- a/src/java.compiler/share/classes/javax/lang/model/util/TypeKindVisitor7.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/java.compiler/share/classes/javax/lang/model/util/TypeKindVisitor7.java	Mon Nov 27 17:04:45 2017 +0000
@@ -96,8 +96,9 @@
     }
 
     /**
-     * This implementation visits a {@code UnionType} by calling
-     * {@code defaultAction}.
+     * {@inheritDoc}
+     *
+     * @implSpec This implementation calls {@code defaultAction}.
      *
      * @param t  {@inheritDoc}
      * @param p  {@inheritDoc}
--- a/src/java.compiler/share/classes/javax/lang/model/util/TypeKindVisitor8.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/java.compiler/share/classes/javax/lang/model/util/TypeKindVisitor8.java	Mon Nov 27 17:04:45 2017 +0000
@@ -94,8 +94,9 @@
     }
 
     /**
-     * This implementation visits an {@code IntersectionType} by calling
-     * {@code defaultAction}.
+     * {@inheritDoc}
+     *
+     * @implSpec This implementation calls {@code defaultAction}.
      *
      * @param t  {@inheritDoc}
      * @param p  {@inheritDoc}
--- a/src/java.desktop/macosx/classes/sun/lwawt/LWLightweightFramePeer.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/java.desktop/macosx/classes/sun/lwawt/LWLightweightFramePeer.java	Mon Nov 27 17:04:45 2017 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2017, 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
@@ -34,10 +34,11 @@
 import java.awt.event.FocusEvent;
 
 import sun.awt.LightweightFrame;
+import sun.awt.OverrideNativeWindowHandle;
 import sun.swing.JLightweightFrame;
 import sun.swing.SwingAccessor;
 
-public class LWLightweightFramePeer extends LWWindowPeer {
+public class LWLightweightFramePeer extends LWWindowPeer implements OverrideNativeWindowHandle {
 
     public LWLightweightFramePeer(LightweightFrame target,
                                   PlatformComponent platformComponent,
@@ -116,4 +117,16 @@
     public void updateCursorImmediately() {
         SwingAccessor.getJLightweightFrameAccessor().updateCursor((JLightweightFrame)getLwTarget());
     }
+
+    // SwingNode
+    private volatile long overriddenWindowHandle = 0L;
+
+    @Override
+    public void overrideWindowHandle(final long handle) {
+        this.overriddenWindowHandle = handle;
+    }
+
+    public long getOverriddenWindowHandle() {
+        return overriddenWindowHandle;
+    }
 }
--- a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java	Mon Nov 27 17:04:45 2017 +0000
@@ -63,6 +63,7 @@
 import sun.awt.AWTAccessor.WindowAccessor;
 import sun.java2d.SurfaceData;
 import sun.java2d.opengl.CGLSurfaceData;
+import sun.lwawt.LWLightweightFramePeer;
 import sun.lwawt.LWToolkit;
 import sun.lwawt.LWWindowPeer;
 import sun.lwawt.LWWindowPeer.PeerType;
@@ -637,6 +638,20 @@
                     if (!isKeyWindow) {
                         CWrapper.NSWindow.makeKeyWindow(ptr);
                     }
+
+                    if (owner != null
+                            && owner.getPeer() instanceof LWLightweightFramePeer) {
+                        LWLightweightFramePeer peer =
+                                (LWLightweightFramePeer) owner.getPeer();
+
+                        long ownerWindowPtr = peer.getOverriddenWindowHandle();
+                        if (ownerWindowPtr != 0) {
+                            //Place window above JavaFX stage
+                            CWrapper.NSWindow.addChildWindow(
+                                    ownerWindowPtr, ptr,
+                                    CWrapper.NSWindow.NSWindowAbove);
+                        }
+                    }
                 });
             } else {
                 execute(ptr->{
--- a/src/java.desktop/share/classes/com/sun/imageio/plugins/png/PNGImageReader.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/png/PNGImageReader.java	Mon Nov 27 17:04:45 2017 +0000
@@ -269,11 +269,11 @@
 
             stream.flushBefore(stream.getStreamPosition());
 
-            if (width == 0) {
-                throw new IIOException("Image width == 0!");
+            if (width <= 0) {
+                throw new IIOException("Image width <= 0!");
             }
-            if (height == 0) {
-                throw new IIOException("Image height == 0!");
+            if (height <= 0) {
+                throw new IIOException("Image height <= 0!");
             }
             if (bitDepth != 1 && bitDepth != 2 && bitDepth != 4 &&
                 bitDepth != 8 && bitDepth != 16) {
--- a/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKGraphicsUtils.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKGraphicsUtils.java	Mon Nov 27 17:04:45 2017 +0000
@@ -47,34 +47,17 @@
             return;
         }
         int componentState = context.getComponentState();
-        if ((componentState & SynthConstants.DISABLED) ==
-                              SynthConstants.DISABLED){
-            if (!GTKLookAndFeel.is3()) {
-                Color orgColor = g.getColor();
-                g.setColor(context.getStyle().getColor(context,
-                        GTKColorType.WHITE));
-                x += 1;
-                y += 1;
-                super.paintText(context, g, text, x, y, mnemonicIndex);
+
+        String themeName = GTKLookAndFeel.getGtkThemeName();
+        if (themeName != null && themeName.startsWith("blueprint") &&
+            shouldShadowText(context.getRegion(), componentState)) {
 
-                g.setColor(orgColor);
-                x -= 1;
-                y -= 1;
-            }
-            super.paintText(context, g, text, x, y, mnemonicIndex);
+            g.setColor(Color.BLACK);
+            super.paintText(context, g, text, x+1, y+1, mnemonicIndex);
+            g.setColor(Color.WHITE);
         }
-        else {
-            String themeName = GTKLookAndFeel.getGtkThemeName();
-            if (themeName != null && themeName.startsWith("blueprint") &&
-                shouldShadowText(context.getRegion(), componentState)) {
 
-                g.setColor(Color.BLACK);
-                super.paintText(context, g, text, x+1, y+1, mnemonicIndex);
-                g.setColor(Color.WHITE);
-            }
-
-            super.paintText(context, g, text, x, y, mnemonicIndex);
-        }
+        super.paintText(context, g, text, x, y, mnemonicIndex);
     }
 
     /**
--- a/src/java.desktop/share/classes/java/awt/EventQueue.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/java.desktop/share/classes/java/awt/EventQueue.java	Mon Nov 27 17:04:45 2017 +0000
@@ -858,15 +858,13 @@
     private AWTEvent getCurrentEventImpl() {
         pushPopLock.lock();
         try {
-            if (fxAppThreadIsDispatchThread) {
+            if (Thread.currentThread() == dispatchThread
+                    || fxAppThreadIsDispatchThread) {
                 return (currentEvent != null)
                         ? currentEvent.get()
                         : null;
-            } else {
-                return (Thread.currentThread() == dispatchThread)
-                        ? currentEvent.get()
-                        : null;
             }
+            return null;
         } finally {
             pushPopLock.unlock();
         }
--- a/src/java.desktop/share/classes/java/awt/im/InputContext.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/java.desktop/share/classes/java/awt/im/InputContext.java	Mon Nov 27 17:04:45 2017 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, 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
@@ -55,8 +55,8 @@
  * <p>
  * The Java Platform supports input methods that have been developed in the Java
  * programming language, using the interfaces in the {@link java.awt.im.spi} package,
- * and installed into a Java SE Runtime Environment as extensions. Implementations
- * may also support using the native input methods of the platforms they run on;
+ * which can be made available by adding them to the application's class path.
+ * Implementations may also support using the native input methods of the platforms they run on;
  * however, not all platforms and locales provide input methods. Keyboard layouts
  * are provided by the host platform.
  *
--- a/src/java.desktop/share/classes/javax/swing/text/PlainView.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/java.desktop/share/classes/javax/swing/text/PlainView.java	Mon Nov 27 17:04:45 2017 +0000
@@ -646,7 +646,7 @@
         if (tabSize == 0) {
             return x;
         }
-        float ntabs = (x - tabBase) / tabSize;
+        int ntabs = (int) ((x - tabBase) / tabSize);
         return tabBase + ((ntabs + 1) * tabSize);
     }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/classes/sun/awt/OverrideNativeWindowHandle.java	Mon Nov 27 17:04:45 2017 +0000
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2017, 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+
+package sun.awt;
+
+/**
+ * Used for replacing window owner with another non-Swing window.
+ * It is useful in case of JavaFX-Swing interop:
+ * it helps to keep Swing dialogs above its owner(JavaFX stage).
+ */
+
+public interface OverrideNativeWindowHandle {
+
+    /**
+     * Replaces an owner window with a window with provided handle.
+     * @param handle native window handle
+     */
+    void overrideWindowHandle(final long handle);
+}
--- a/src/java.desktop/share/classes/sun/java2d/pisces/Curve.java	Fri Nov 24 17:19:47 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,290 +0,0 @@
-/*
- * Copyright (c) 2007, 2011, 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.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.
- */
-
-package sun.java2d.pisces;
-
-import java.util.Iterator;
-
-final class Curve {
-
-    float ax, ay, bx, by, cx, cy, dx, dy;
-    float dax, day, dbx, dby;
-
-    Curve() {
-    }
-
-    void set(float[] points, int type) {
-        switch(type) {
-        case 8:
-            set(points[0], points[1],
-                points[2], points[3],
-                points[4], points[5],
-                points[6], points[7]);
-            break;
-        case 6:
-            set(points[0], points[1],
-                points[2], points[3],
-                points[4], points[5]);
-            break;
-        default:
-            throw new InternalError("Curves can only be cubic or quadratic");
-        }
-    }
-
-    void set(float x1, float y1,
-             float x2, float y2,
-             float x3, float y3,
-             float x4, float y4)
-    {
-        ax = 3 * (x2 - x3) + x4 - x1;
-        ay = 3 * (y2 - y3) + y4 - y1;
-        bx = 3 * (x1 - 2 * x2 + x3);
-        by = 3 * (y1 - 2 * y2 + y3);
-        cx = 3 * (x2 - x1);
-        cy = 3 * (y2 - y1);
-        dx = x1;
-        dy = y1;
-        dax = 3 * ax; day = 3 * ay;
-        dbx = 2 * bx; dby = 2 * by;
-    }
-
-    void set(float x1, float y1,
-             float x2, float y2,
-             float x3, float y3)
-    {
-        ax = ay = 0f;
-
-        bx = x1 - 2 * x2 + x3;
-        by = y1 - 2 * y2 + y3;
-        cx = 2 * (x2 - x1);
-        cy = 2 * (y2 - y1);
-        dx = x1;
-        dy = y1;
-        dax = 0; day = 0;
-        dbx = 2 * bx; dby = 2 * by;
-    }
-
-    float xat(float t) {
-        return t * (t * (t * ax + bx) + cx) + dx;
-    }
-    float yat(float t) {
-        return t * (t * (t * ay + by) + cy) + dy;
-    }
-
-    float dxat(float t) {
-        return t * (t * dax + dbx) + cx;
-    }
-
-    float dyat(float t) {
-        return t * (t * day + dby) + cy;
-    }
-
-    int dxRoots(float[] roots, int off) {
-        return Helpers.quadraticRoots(dax, dbx, cx, roots, off);
-    }
-
-    int dyRoots(float[] roots, int off) {
-        return Helpers.quadraticRoots(day, dby, cy, roots, off);
-    }
-
-    int infPoints(float[] pts, int off) {
-        // inflection point at t if -f'(t)x*f''(t)y + f'(t)y*f''(t)x == 0
-        // Fortunately, this turns out to be quadratic, so there are at
-        // most 2 inflection points.
-        final float a = dax * dby - dbx * day;
-        final float b = 2 * (cy * dax - day * cx);
-        final float c = cy * dbx - cx * dby;
-
-        return Helpers.quadraticRoots(a, b, c, pts, off);
-    }
-
-    // finds points where the first and second derivative are
-    // perpendicular. This happens when g(t) = f'(t)*f''(t) == 0 (where
-    // * is a dot product). Unfortunately, we have to solve a cubic.
-    private int perpendiculardfddf(float[] pts, int off) {
-        assert pts.length >= off + 4;
-
-        // these are the coefficients of some multiple of g(t) (not g(t),
-        // because the roots of a polynomial are not changed after multiplication
-        // by a constant, and this way we save a few multiplications).
-        final float a = 2*(dax*dax + day*day);
-        final float b = 3*(dax*dbx + day*dby);
-        final float c = 2*(dax*cx + day*cy) + dbx*dbx + dby*dby;
-        final float d = dbx*cx + dby*cy;
-        return Helpers.cubicRootsInAB(a, b, c, d, pts, off, 0f, 1f);
-    }
-
-    // Tries to find the roots of the function ROC(t)-w in [0, 1). It uses
-    // a variant of the false position algorithm to find the roots. False
-    // position requires that 2 initial values x0,x1 be given, and that the
-    // function must have opposite signs at those values. To find such
-    // values, we need the local extrema of the ROC function, for which we
-    // need the roots of its derivative; however, it's harder to find the
-    // roots of the derivative in this case than it is to find the roots
-    // of the original function. So, we find all points where this curve's
-    // first and second derivative are perpendicular, and we pretend these
-    // are our local extrema. There are at most 3 of these, so we will check
-    // at most 4 sub-intervals of (0,1). ROC has asymptotes at inflection
-    // points, so roc-w can have at least 6 roots. This shouldn't be a
-    // problem for what we're trying to do (draw a nice looking curve).
-    int rootsOfROCMinusW(float[] roots, int off, final float w, final float err) {
-        // no OOB exception, because by now off<=6, and roots.length >= 10
-        assert off <= 6 && roots.length >= 10;
-        int ret = off;
-        int numPerpdfddf = perpendiculardfddf(roots, off);
-        float t0 = 0, ft0 = ROCsq(t0) - w*w;
-        roots[off + numPerpdfddf] = 1f; // always check interval end points
-        numPerpdfddf++;
-        for (int i = off; i < off + numPerpdfddf; i++) {
-            float t1 = roots[i], ft1 = ROCsq(t1) - w*w;
-            if (ft0 == 0f) {
-                roots[ret++] = t0;
-            } else if (ft1 * ft0 < 0f) { // have opposite signs
-                // (ROC(t)^2 == w^2) == (ROC(t) == w) is true because
-                // ROC(t) >= 0 for all t.
-                roots[ret++] = falsePositionROCsqMinusX(t0, t1, w*w, err);
-            }
-            t0 = t1;
-            ft0 = ft1;
-        }
-
-        return ret - off;
-    }
-
-    private static float eliminateInf(float x) {
-        return (x == Float.POSITIVE_INFINITY ? Float.MAX_VALUE :
-            (x == Float.NEGATIVE_INFINITY ? Float.MIN_VALUE : x));
-    }
-
-    // A slight modification of the false position algorithm on wikipedia.
-    // This only works for the ROCsq-x functions. It might be nice to have
-    // the function as an argument, but that would be awkward in java6.
-    // TODO: It is something to consider for java8 (or whenever lambda
-    // expressions make it into the language), depending on how closures
-    // and turn out. Same goes for the newton's method
-    // algorithm in Helpers.java
-    private float falsePositionROCsqMinusX(float x0, float x1,
-                                           final float x, final float err)
-    {
-        final int iterLimit = 100;
-        int side = 0;
-        float t = x1, ft = eliminateInf(ROCsq(t) - x);
-        float s = x0, fs = eliminateInf(ROCsq(s) - x);
-        float r = s, fr;
-        for (int i = 0; i < iterLimit && Math.abs(t - s) > err * Math.abs(t + s); i++) {
-            r = (fs * t - ft * s) / (fs - ft);
-            fr = ROCsq(r) - x;
-            if (sameSign(fr, ft)) {
-                ft = fr; t = r;
-                if (side < 0) {
-                    fs /= (1 << (-side));
-                    side--;
-                } else {
-                    side = -1;
-                }
-            } else if (fr * fs > 0) {
-                fs = fr; s = r;
-                if (side > 0) {
-                    ft /= (1 << side);
-                    side++;
-                } else {
-                    side = 1;
-                }
-            } else {
-                break;
-            }
-        }
-        return r;
-    }
-
-    private static boolean sameSign(double x, double y) {
-        // another way is to test if x*y > 0. This is bad for small x, y.
-        return (x < 0 && y < 0) || (x > 0 && y > 0);
-    }
-
-    // returns the radius of curvature squared at t of this curve
-    // see http://en.wikipedia.org/wiki/Radius_of_curvature_(applications)
-    private float ROCsq(final float t) {
-        // dx=xat(t) and dy=yat(t). These calls have been inlined for efficiency
-        final float dx = t * (t * dax + dbx) + cx;
-        final float dy = t * (t * day + dby) + cy;
-        final float ddx = 2 * dax * t + dbx;
-        final float ddy = 2 * day * t + dby;
-        final float dx2dy2 = dx*dx + dy*dy;
-        final float ddx2ddy2 = ddx*ddx + ddy*ddy;
-        final float ddxdxddydy = ddx*dx + ddy*dy;
-        return dx2dy2*((dx2dy2*dx2dy2) / (dx2dy2 * ddx2ddy2 - ddxdxddydy*ddxdxddydy));
-    }
-
-    // curve to be broken should be in pts
-    // this will change the contents of pts but not Ts
-    // TODO: There's no reason for Ts to be an array. All we need is a sequence
-    // of t values at which to subdivide. An array statisfies this condition,
-    // but is unnecessarily restrictive. Ts should be an Iterator<Float> instead.
-    // Doing this will also make dashing easier, since we could easily make
-    // LengthIterator an Iterator<Float> and feed it to this function to simplify
-    // the loop in Dasher.somethingTo.
-    static Iterator<Integer> breakPtsAtTs(final float[] pts, final int type,
-                                          final float[] Ts, final int numTs)
-    {
-        assert pts.length >= 2*type && numTs <= Ts.length;
-        return new Iterator<Integer>() {
-            // these prevent object creation and destruction during autoboxing.
-            // Because of this, the compiler should be able to completely
-            // eliminate the boxing costs.
-            final Integer i0 = 0;
-            final Integer itype = type;
-            int nextCurveIdx = 0;
-            Integer curCurveOff = i0;
-            float prevT = 0;
-
-            @Override public boolean hasNext() {
-                return nextCurveIdx < numTs + 1;
-            }
-
-            @Override public Integer next() {
-                Integer ret;
-                if (nextCurveIdx < numTs) {
-                    float curT = Ts[nextCurveIdx];
-                    float splitT = (curT - prevT) / (1 - prevT);
-                    Helpers.subdivideAt(splitT,
-                                        pts, curCurveOff,
-                                        pts, 0,
-                                        pts, type, type);
-                    prevT = curT;
-                    ret = i0;
-                    curCurveOff = itype;
-                } else {
-                    ret = curCurveOff;
-                }
-                nextCurveIdx++;
-                return ret;
-            }
-
-            @Override public void remove() {}
-        };
-    }
-}
-
--- a/src/java.desktop/share/classes/sun/java2d/pisces/Dasher.java	Fri Nov 24 17:19:47 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,575 +0,0 @@
-/*
- * Copyright (c) 2007, 2011, 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.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.
- */
-
-package sun.java2d.pisces;
-
-import sun.awt.geom.PathConsumer2D;
-
-/**
- * The {@code Dasher} class takes a series of linear commands
- * ({@code moveTo}, {@code lineTo}, {@code close} and
- * {@code end}) and breaks them into smaller segments according to a
- * dash pattern array and a starting dash phase.
- *
- * <p> Issues: in J2Se, a zero length dash segment as drawn as a very
- * short dash, whereas Pisces does not draw anything.  The PostScript
- * semantics are unclear.
- *
- */
-final class Dasher implements sun.awt.geom.PathConsumer2D {
-
-    private final PathConsumer2D out;
-    private final float[] dash;
-    private final float startPhase;
-    private final boolean startDashOn;
-    private final int startIdx;
-
-    private boolean starting;
-    private boolean needsMoveTo;
-
-    private int idx;
-    private boolean dashOn;
-    private float phase;
-
-    private float sx, sy;
-    private float x0, y0;
-
-    // temporary storage for the current curve
-    private float[] curCurvepts;
-
-    /**
-     * Constructs a {@code Dasher}.
-     *
-     * @param out an output {@code PathConsumer2D}.
-     * @param dash an array of {@code float}s containing the dash pattern
-     * @param phase a {@code float} containing the dash phase
-     */
-    public Dasher(PathConsumer2D out, float[] dash, float phase) {
-        if (phase < 0) {
-            throw new IllegalArgumentException("phase < 0 !");
-        }
-
-        this.out = out;
-
-        // Normalize so 0 <= phase < dash[0]
-        int idx = 0;
-        dashOn = true;
-        float d;
-        while (phase >= (d = dash[idx])) {
-            phase -= d;
-            idx = (idx + 1) % dash.length;
-            dashOn = !dashOn;
-        }
-
-        this.dash = dash;
-        this.startPhase = this.phase = phase;
-        this.startDashOn = dashOn;
-        this.startIdx = idx;
-        this.starting = true;
-
-        // we need curCurvepts to be able to contain 2 curves because when
-        // dashing curves, we need to subdivide it
-        curCurvepts = new float[8 * 2];
-    }
-
-    public void moveTo(float x0, float y0) {
-        if (firstSegidx > 0) {
-            out.moveTo(sx, sy);
-            emitFirstSegments();
-        }
-        needsMoveTo = true;
-        this.idx = startIdx;
-        this.dashOn = this.startDashOn;
-        this.phase = this.startPhase;
-        this.sx = this.x0 = x0;
-        this.sy = this.y0 = y0;
-        this.starting = true;
-    }
-
-    private void emitSeg(float[] buf, int off, int type) {
-        switch (type) {
-        case 8:
-            out.curveTo(buf[off+0], buf[off+1],
-                        buf[off+2], buf[off+3],
-                        buf[off+4], buf[off+5]);
-            break;
-        case 6:
-            out.quadTo(buf[off+0], buf[off+1],
-                       buf[off+2], buf[off+3]);
-            break;
-        case 4:
-            out.lineTo(buf[off], buf[off+1]);
-        }
-    }
-
-    private void emitFirstSegments() {
-        for (int i = 0; i < firstSegidx; ) {
-            emitSeg(firstSegmentsBuffer, i+1, (int)firstSegmentsBuffer[i]);
-            i += (((int)firstSegmentsBuffer[i]) - 1);
-        }
-        firstSegidx = 0;
-    }
-
-    // We don't emit the first dash right away. If we did, caps would be
-    // drawn on it, but we need joins to be drawn if there's a closePath()
-    // So, we store the path elements that make up the first dash in the
-    // buffer below.
-    private float[] firstSegmentsBuffer = new float[7];
-    private int firstSegidx = 0;
-    // precondition: pts must be in relative coordinates (relative to x0,y0)
-    // fullCurve is true iff the curve in pts has not been split.
-    private void goTo(float[] pts, int off, final int type) {
-        float x = pts[off + type - 4];
-        float y = pts[off + type - 3];
-        if (dashOn) {
-            if (starting) {
-                firstSegmentsBuffer = Helpers.widenArray(firstSegmentsBuffer,
-                                      firstSegidx, type - 2 + 1);
-                firstSegmentsBuffer[firstSegidx++] = type;
-                System.arraycopy(pts, off, firstSegmentsBuffer, firstSegidx, type - 2);
-                firstSegidx += type - 2;
-            } else {
-                if (needsMoveTo) {
-                    out.moveTo(x0, y0);
-                    needsMoveTo = false;
-                }
-                emitSeg(pts, off, type);
-            }
-        } else {
-            starting = false;
-            needsMoveTo = true;
-        }
-        this.x0 = x;
-        this.y0 = y;
-    }
-
-    public void lineTo(float x1, float y1) {
-        float dx = x1 - x0;
-        float dy = y1 - y0;
-
-        float len = (float) Math.sqrt(dx*dx + dy*dy);
-
-        if (len == 0) {
-            return;
-        }
-
-        // The scaling factors needed to get the dx and dy of the
-        // transformed dash segments.
-        float cx = dx / len;
-        float cy = dy / len;
-
-        while (true) {
-            float leftInThisDashSegment = dash[idx] - phase;
-            if (len <= leftInThisDashSegment) {
-                curCurvepts[0] = x1;
-                curCurvepts[1] = y1;
-                goTo(curCurvepts, 0, 4);
-                // Advance phase within current dash segment
-                phase += len;
-                if (len == leftInThisDashSegment) {
-                    phase = 0f;
-                    idx = (idx + 1) % dash.length;
-                    dashOn = !dashOn;
-                }
-                return;
-            }
-
-            float dashdx = dash[idx] * cx;
-            float dashdy = dash[idx] * cy;
-            if (phase == 0) {
-                curCurvepts[0] = x0 + dashdx;
-                curCurvepts[1] = y0 + dashdy;
-            } else {
-                float p = leftInThisDashSegment / dash[idx];
-                curCurvepts[0] = x0 + p * dashdx;
-                curCurvepts[1] = y0 + p * dashdy;
-            }
-
-            goTo(curCurvepts, 0, 4);
-
-            len -= leftInThisDashSegment;
-            // Advance to next dash segment
-            idx = (idx + 1) % dash.length;
-            dashOn = !dashOn;
-            phase = 0;
-        }
-    }
-
-    private LengthIterator li = null;
-
-    // preconditions: curCurvepts must be an array of length at least 2 * type,
-    // that contains the curve we want to dash in the first type elements
-    private void somethingTo(int type) {
-        if (pointCurve(curCurvepts, type)) {
-            return;
-        }
-        if (li == null) {
-            li = new LengthIterator(4, 0.01f);
-        }
-        li.initializeIterationOnCurve(curCurvepts, type);
-
-        int curCurveoff = 0; // initially the current curve is at curCurvepts[0...type]
-        float lastSplitT = 0;
-        float t = 0;
-        float leftInThisDashSegment = dash[idx] - phase;
-        while ((t = li.next(leftInThisDashSegment)) < 1) {
-            if (t != 0) {
-                Helpers.subdivideAt((t - lastSplitT) / (1 - lastSplitT),
-                                    curCurvepts, curCurveoff,
-                                    curCurvepts, 0,
-                                    curCurvepts, type, type);
-                lastSplitT = t;
-                goTo(curCurvepts, 2, type);
-                curCurveoff = type;
-            }
-            // Advance to next dash segment
-            idx = (idx + 1) % dash.length;
-            dashOn = !dashOn;
-            phase = 0;
-            leftInThisDashSegment = dash[idx];
-        }
-        goTo(curCurvepts, curCurveoff+2, type);
-        phase += li.lastSegLen();
-        if (phase >= dash[idx]) {
-            phase = 0f;
-            idx = (idx + 1) % dash.length;
-            dashOn = !dashOn;
-        }
-    }
-
-    private static boolean pointCurve(float[] curve, int type) {
-        for (int i = 2; i < type; i++) {
-            if (curve[i] != curve[i-2]) {
-                return false;
-            }
-        }
-        return true;
-    }
-
-    // Objects of this class are used to iterate through curves. They return
-    // t values where the left side of the curve has a specified length.
-    // It does this by subdividing the input curve until a certain error
-    // condition has been met. A recursive subdivision procedure would
-    // return as many as 1<<limit curves, but this is an iterator and we
-    // don't need all the curves all at once, so what we carry out a
-    // lazy inorder traversal of the recursion tree (meaning we only move
-    // through the tree when we need the next subdivided curve). This saves
-    // us a lot of memory because at any one time we only need to store
-    // limit+1 curves - one for each level of the tree + 1.
-    // NOTE: the way we do things here is not enough to traverse a general
-    // tree; however, the trees we are interested in have the property that
-    // every non leaf node has exactly 2 children
-    private static class LengthIterator {
-        private enum Side {LEFT, RIGHT};
-        // Holds the curves at various levels of the recursion. The root
-        // (i.e. the original curve) is at recCurveStack[0] (but then it
-        // gets subdivided, the left half is put at 1, so most of the time
-        // only the right half of the original curve is at 0)
-        private float[][] recCurveStack;
-        // sides[i] indicates whether the node at level i+1 in the path from
-        // the root to the current leaf is a left or right child of its parent.
-        private Side[] sides;
-        private int curveType;
-        private final int limit;
-        private final float ERR;
-        private final float minTincrement;
-        // lastT and nextT delimit the current leaf.
-        private float nextT;
-        private float lenAtNextT;
-        private float lastT;
-        private float lenAtLastT;
-        private float lenAtLastSplit;
-        private float lastSegLen;
-        // the current level in the recursion tree. 0 is the root. limit
-        // is the deepest possible leaf.
-        private int recLevel;
-        private boolean done;
-
-        // the lengths of the lines of the control polygon. Only its first
-        // curveType/2 - 1 elements are valid. This is an optimization. See
-        // next(float) for more detail.
-        private float[] curLeafCtrlPolyLengths = new float[3];
-
-        public LengthIterator(int reclimit, float err) {
-            this.limit = reclimit;
-            this.minTincrement = 1f / (1 << limit);
-            this.ERR = err;
-            this.recCurveStack = new float[reclimit+1][8];
-            this.sides = new Side[reclimit];
-            // if any methods are called without first initializing this object on
-            // a curve, we want it to fail ASAP.
-            this.nextT = Float.MAX_VALUE;
-            this.lenAtNextT = Float.MAX_VALUE;
-            this.lenAtLastSplit = Float.MIN_VALUE;
-            this.recLevel = Integer.MIN_VALUE;
-            this.lastSegLen = Float.MAX_VALUE;
-            this.done = true;
-        }
-
-        public void initializeIterationOnCurve(float[] pts, int type) {
-            System.arraycopy(pts, 0, recCurveStack[0], 0, type);
-            this.curveType = type;
-            this.recLevel = 0;
-            this.lastT = 0;
-            this.lenAtLastT = 0;
-            this.nextT = 0;
-            this.lenAtNextT = 0;
-            goLeft(); // initializes nextT and lenAtNextT properly
-            this.lenAtLastSplit = 0;
-            if (recLevel > 0) {
-                this.sides[0] = Side.LEFT;
-                this.done = false;
-            } else {
-                // the root of the tree is a leaf so we're done.
-                this.sides[0] = Side.RIGHT;
-                this.done = true;
-            }
-            this.lastSegLen = 0;
-        }
-
-        // 0 == false, 1 == true, -1 == invalid cached value.
-        private int cachedHaveLowAcceleration = -1;
-
-        private boolean haveLowAcceleration(float err) {
-            if (cachedHaveLowAcceleration == -1) {
-                final float len1 = curLeafCtrlPolyLengths[0];
-                final float len2 = curLeafCtrlPolyLengths[1];
-                // the test below is equivalent to !within(len1/len2, 1, err).
-                // It is using a multiplication instead of a division, so it
-                // should be a bit faster.
-                if (!Helpers.within(len1, len2, err*len2)) {
-                    cachedHaveLowAcceleration = 0;
-                    return false;
-                }
-                if (curveType == 8) {
-                    final float len3 = curLeafCtrlPolyLengths[2];
-                    // if len1 is close to 2 and 2 is close to 3, that probably
-                    // means 1 is close to 3 so the second part of this test might
-                    // not be needed, but it doesn't hurt to include it.
-                    if (!(Helpers.within(len2, len3, err*len3) &&
-                          Helpers.within(len1, len3, err*len3))) {
-                        cachedHaveLowAcceleration = 0;
-                        return false;
-                    }
-                }
-                cachedHaveLowAcceleration = 1;
-                return true;
-            }
-
-            return (cachedHaveLowAcceleration == 1);
-        }
-
-        // we want to avoid allocations/gc so we keep this array so we
-        // can put roots in it,
-        private float[] nextRoots = new float[4];
-
-        // caches the coefficients of the current leaf in its flattened
-        // form (see inside next() for what that means). The cache is
-        // invalid when it's third element is negative, since in any
-        // valid flattened curve, this would be >= 0.
-        private float[] flatLeafCoefCache = new float[] {0, 0, -1, 0};
-        // returns the t value where the remaining curve should be split in
-        // order for the left subdivided curve to have length len. If len
-        // is >= than the length of the uniterated curve, it returns 1.
-        public float next(final float len) {
-            final float targetLength = lenAtLastSplit + len;
-            while(lenAtNextT < targetLength) {
-                if (done) {
-                    lastSegLen = lenAtNextT - lenAtLastSplit;
-                    return 1;
-                }
-                goToNextLeaf();
-            }
-            lenAtLastSplit = targetLength;
-            final float leaflen = lenAtNextT - lenAtLastT;
-            float t = (targetLength - lenAtLastT) / leaflen;
-
-            // cubicRootsInAB is a fairly expensive call, so we just don't do it
-            // if the acceleration in this section of the curve is small enough.
-            if (!haveLowAcceleration(0.05f)) {
-                // We flatten the current leaf along the x axis, so that we're
-                // left with a, b, c which define a 1D Bezier curve. We then
-                // solve this to get the parameter of the original leaf that
-                // gives us the desired length.
-
-                if (flatLeafCoefCache[2] < 0) {
-                    float x = 0+curLeafCtrlPolyLengths[0],
-                          y = x+curLeafCtrlPolyLengths[1];
-                    if (curveType == 8) {
-                        float z = y + curLeafCtrlPolyLengths[2];
-                        flatLeafCoefCache[0] = 3*(x - y) + z;
-                        flatLeafCoefCache[1] = 3*(y - 2*x);
-                        flatLeafCoefCache[2] = 3*x;
-                        flatLeafCoefCache[3] = -z;
-                    } else if (curveType == 6) {
-                        flatLeafCoefCache[0] = 0f;
-                        flatLeafCoefCache[1] = y - 2*x;
-                        flatLeafCoefCache[2] = 2*x;
-                        flatLeafCoefCache[3] = -y;
-                    }
-                }
-                float a = flatLeafCoefCache[0];
-                float b = flatLeafCoefCache[1];
-                float c = flatLeafCoefCache[2];
-                float d = t*flatLeafCoefCache[3];
-
-                // we use cubicRootsInAB here, because we want only roots in 0, 1,
-                // and our quadratic root finder doesn't filter, so it's just a
-                // matter of convenience.
-                int n = Helpers.cubicRootsInAB(a, b, c, d, nextRoots, 0, 0, 1);
-                if (n == 1 && !Float.isNaN(nextRoots[0])) {
-                    t = nextRoots[0];
-                }
-            }
-            // t is relative to the current leaf, so we must make it a valid parameter
-            // of the original curve.
-            t = t * (nextT - lastT) + lastT;
-            if (t >= 1) {
-                t = 1;
-                done = true;
-            }
-            // even if done = true, if we're here, that means targetLength
-            // is equal to, or very, very close to the total length of the
-            // curve, so lastSegLen won't be too high. In cases where len
-            // overshoots the curve, this method will exit in the while
-            // loop, and lastSegLen will still be set to the right value.
-            lastSegLen = len;
-            return t;
-        }
-
-        public float lastSegLen() {
-            return lastSegLen;
-        }
-
-        // go to the next leaf (in an inorder traversal) in the recursion tree
-        // preconditions: must be on a leaf, and that leaf must not be the root.
-        private void goToNextLeaf() {
-            // We must go to the first ancestor node that has an unvisited
-            // right child.
-            recLevel--;
-            while(sides[recLevel] == Side.RIGHT) {
-                if (recLevel == 0) {
-                    done = true;
-                    return;
-                }
-                recLevel--;
-            }
-
-            sides[recLevel] = Side.RIGHT;
-            System.arraycopy(recCurveStack[recLevel], 0, recCurveStack[recLevel+1], 0, curveType);
-            recLevel++;
-            goLeft();
-        }
-
-        // go to the leftmost node from the current node. Return its length.
-        private void goLeft() {
-            float len = onLeaf();
-            if (len >= 0) {
-                lastT = nextT;
-                lenAtLastT = lenAtNextT;
-                nextT += (1 << (limit - recLevel)) * minTincrement;
-                lenAtNextT += len;
-                // invalidate caches
-                flatLeafCoefCache[2] = -1;
-                cachedHaveLowAcceleration = -1;
-            } else {
-                Helpers.subdivide(recCurveStack[recLevel], 0,
-                                  recCurveStack[recLevel+1], 0,
-                                  recCurveStack[recLevel], 0, curveType);
-                sides[recLevel] = Side.LEFT;
-                recLevel++;
-                goLeft();
-            }
-        }
-
-        // this is a bit of a hack. It returns -1 if we're not on a leaf, and
-        // the length of the leaf if we are on a leaf.
-        private float onLeaf() {
-            float[] curve = recCurveStack[recLevel];
-            float polyLen = 0;
-
-            float x0 = curve[0], y0 = curve[1];
-            for (int i = 2; i < curveType; i += 2) {
-                final float x1 = curve[i], y1 = curve[i+1];
-                final float len = Helpers.linelen(x0, y0, x1, y1);
-                polyLen += len;
-                curLeafCtrlPolyLengths[i/2 - 1] = len;
-                x0 = x1;
-                y0 = y1;
-            }
-
-            final float lineLen = Helpers.linelen(curve[0], curve[1], curve[curveType-2], curve[curveType-1]);
-            if (polyLen - lineLen < ERR || recLevel == limit) {
-                return (polyLen + lineLen)/2;
-            }
-            return -1;
-        }
-    }
-
-    @Override
-    public void curveTo(float x1, float y1,
-                        float x2, float y2,
-                        float x3, float y3)
-    {
-        curCurvepts[0] = x0;        curCurvepts[1] = y0;
-        curCurvepts[2] = x1;        curCurvepts[3] = y1;
-        curCurvepts[4] = x2;        curCurvepts[5] = y2;
-        curCurvepts[6] = x3;        curCurvepts[7] = y3;
-        somethingTo(8);
-    }
-
-    @Override
-    public void quadTo(float x1, float y1, float x2, float y2) {
-        curCurvepts[0] = x0;        curCurvepts[1] = y0;
-        curCurvepts[2] = x1;        curCurvepts[3] = y1;
-        curCurvepts[4] = x2;        curCurvepts[5] = y2;
-        somethingTo(6);
-    }
-
-    public void closePath() {
-        lineTo(sx, sy);
-        if (firstSegidx > 0) {
-            if (!dashOn || needsMoveTo) {
-                out.moveTo(sx, sy);
-            }
-            emitFirstSegments();
-        }
-        moveTo(sx, sy);
-    }
-
-    public void pathDone() {
-        if (firstSegidx > 0) {
-            out.moveTo(sx, sy);
-            emitFirstSegments();
-        }
-        out.pathDone();
-    }
-
-    @Override
-    public long getNativeConsumer() {
-        throw new InternalError("Dasher does not use a native consumer");
-    }
-}
-
--- a/src/java.desktop/share/classes/sun/java2d/pisces/Helpers.java	Fri Nov 24 17:19:47 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,458 +0,0 @@
-/*
- * Copyright (c) 2007, 2011, 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.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.
- */
-
-package sun.java2d.pisces;
-
-import java.util.Arrays;
-import static java.lang.Math.PI;
-import static java.lang.Math.cos;
-import static java.lang.Math.sqrt;
-import static java.lang.Math.cbrt;
-import static java.lang.Math.acos;
-
-
-final class Helpers {
-    private Helpers() {
-        throw new Error("This is a non instantiable class");
-    }
-
-    static boolean within(final float x, final float y, final float err) {
-        final float d = y - x;
-        return (d <= err && d >= -err);
-    }
-
-    static boolean within(final double x, final double y, final double err) {
-        final double d = y - x;
-        return (d <= err && d >= -err);
-    }
-
-    static int quadraticRoots(final float a, final float b,
-                              final float c, float[] zeroes, final int off)
-    {
-        int ret = off;
-        float t;
-        if (a != 0f) {
-            final float dis = b*b - 4*a*c;
-            if (dis > 0) {
-                final float sqrtDis = (float)Math.sqrt(dis);
-                // depending on the sign of b we use a slightly different
-                // algorithm than the traditional one to find one of the roots
-                // so we can avoid adding numbers of different signs (which
-                // might result in loss of precision).
-                if (b >= 0) {
-                    zeroes[ret++] = (2 * c) / (-b - sqrtDis);
-                    zeroes[ret++] = (-b - sqrtDis) / (2 * a);
-                } else {
-                    zeroes[ret++] = (-b + sqrtDis) / (2 * a);
-                    zeroes[ret++] = (2 * c) / (-b + sqrtDis);
-                }
-            } else if (dis == 0f) {
-                t = (-b) / (2 * a);
-                zeroes[ret++] = t;
-            }
-        } else {
-            if (b != 0f) {
-                t = (-c) / b;
-                zeroes[ret++] = t;
-            }
-        }
-        return ret - off;
-    }
-
-    // find the roots of g(t) = d*t^3 + a*t^2 + b*t + c in [A,B)
-    static int cubicRootsInAB(float d, float a, float b, float c,
-                              float[] pts, final int off,
-                              final float A, final float B)
-    {
-        if (d == 0) {
-            int num = quadraticRoots(a, b, c, pts, off);
-            return filterOutNotInAB(pts, off, num, A, B) - off;
-        }
-        // From Graphics Gems:
-        // http://tog.acm.org/resources/GraphicsGems/gems/Roots3And4.c
-        // (also from awt.geom.CubicCurve2D. But here we don't need as
-        // much accuracy and we don't want to create arrays so we use
-        // our own customized version).
-
-        /* normal form: x^3 + ax^2 + bx + c = 0 */
-        a /= d;
-        b /= d;
-        c /= d;
-
-        //  substitute x = y - A/3 to eliminate quadratic term:
-        //     x^3 +Px + Q = 0
-        //
-        // Since we actually need P/3 and Q/2 for all of the
-        // calculations that follow, we will calculate
-        // p = P/3
-        // q = Q/2
-        // instead and use those values for simplicity of the code.
-        double sq_A = a * a;
-        double p = 1.0/3 * (-1.0/3 * sq_A + b);
-        double q = 1.0/2 * (2.0/27 * a * sq_A - 1.0/3 * a * b + c);
-
-        /* use Cardano's formula */
-
-        double cb_p = p * p * p;
-        double D = q * q + cb_p;
-
-        int num;
-        if (D < 0) {
-            // see: http://en.wikipedia.org/wiki/Cubic_function#Trigonometric_.28and_hyperbolic.29_method
-            final double phi = 1.0/3 * acos(-q / sqrt(-cb_p));
-            final double t = 2 * sqrt(-p);
-
-            pts[ off+0 ] =  (float)( t * cos(phi));
-            pts[ off+1 ] =  (float)(-t * cos(phi + PI / 3));
-            pts[ off+2 ] =  (float)(-t * cos(phi - PI / 3));
-            num = 3;
-        } else {
-            final double sqrt_D = sqrt(D);
-            final double u = cbrt(sqrt_D - q);
-            final double v = - cbrt(sqrt_D + q);
-
-            pts[ off ] = (float)(u + v);
-            num = 1;
-
-            if (within(D, 0, 1e-8)) {
-                pts[off+1] = -(pts[off] / 2);
-                num = 2;
-            }
-        }
-
-        final float sub = 1.0f/3 * a;
-
-        for (int i = 0; i < num; ++i) {
-            pts[ off+i ] -= sub;
-        }
-
-        return filterOutNotInAB(pts, off, num, A, B) - off;
-    }
-
-    // These use a hardcoded factor of 2 for increasing sizes. Perhaps this
-    // should be provided as an argument.
-    static float[] widenArray(float[] in, final int cursize, final int numToAdd) {
-        if (in.length >= cursize + numToAdd) {
-            return in;
-        }
-        return Arrays.copyOf(in, 2 * (cursize + numToAdd));
-    }
-
-    static int[] widenArray(int[] in, final int cursize, final int numToAdd) {
-        if (in.length >= cursize + numToAdd) {
-            return in;
-        }
-        return Arrays.copyOf(in, 2 * (cursize + numToAdd));
-    }
-
-    static float evalCubic(final float a, final float b,
-                           final float c, final float d,
-                           final float t)
-    {
-        return t * (t * (t * a + b) + c) + d;
-    }
-
-    static float evalQuad(final float a, final float b,
-                          final float c, final float t)
-    {
-        return t * (t * a + b) + c;
-    }
-
-    // returns the index 1 past the last valid element remaining after filtering
-    static int filterOutNotInAB(float[] nums, final int off, final int len,
-                                final float a, final float b)
-    {
-        int ret = off;
-        for (int i = off; i < off + len; i++) {
-            if (nums[i] >= a && nums[i] < b) {
-                nums[ret++] = nums[i];
-            }
-        }
-        return ret;
-    }
-
-    static float polyLineLength(float[] poly, final int off, final int nCoords) {
-        assert nCoords % 2 == 0 && poly.length >= off + nCoords : "";
-        float acc = 0;
-        for (int i = off + 2; i < off + nCoords; i += 2) {
-            acc += linelen(poly[i], poly[i+1], poly[i-2], poly[i-1]);
-        }
-        return acc;
-    }
-
-    static float linelen(float x1, float y1, float x2, float y2) {
-        final float dx = x2 - x1;
-        final float dy = y2 - y1;
-        return (float)Math.sqrt(dx*dx + dy*dy);
-    }
-
-    static void subdivide(float[] src, int srcoff, float[] left, int leftoff,
-                          float[] right, int rightoff, int type)
-    {
-        switch(type) {
-        case 6:
-            Helpers.subdivideQuad(src, srcoff, left, leftoff, right, rightoff);
-            break;
-        case 8:
-            Helpers.subdivideCubic(src, srcoff, left, leftoff, right, rightoff);
-            break;
-        default:
-            throw new InternalError("Unsupported curve type");
-        }
-    }
-
-    static void isort(float[] a, int off, int len) {
-        for (int i = off + 1; i < off + len; i++) {
-            float ai = a[i];
-            int j = i - 1;
-            for (; j >= off && a[j] > ai; j--) {
-                a[j+1] = a[j];
-            }
-            a[j+1] = ai;
-        }
-    }
-
-    // Most of these are copied from classes in java.awt.geom because we need
-    // float versions of these functions, and Line2D, CubicCurve2D,
-    // QuadCurve2D don't provide them.
-    /**
-     * Subdivides the cubic curve specified by the coordinates
-     * stored in the {@code src} array at indices {@code srcoff}
-     * through ({@code srcoff}&nbsp;+&nbsp;7) and stores the
-     * resulting two subdivided curves into the two result arrays at the
-     * corresponding indices.
-     * Either or both of the {@code left} and {@code right}
-     * arrays may be {@code null} or a reference to the same array
-     * as the {@code src} array.
-     * Note that the last point in the first subdivided curve is the
-     * same as the first point in the second subdivided curve. Thus,
-     * it is possible to pass the same array for {@code left}
-     * and {@code right} and to use offsets, such as {@code rightoff}
-     * equals ({@code leftoff} + 6), in order
-     * to avoid allocating extra storage for this common point.
-     * @param src the array holding the coordinates for the source curve
-     * @param srcoff the offset into the array of the beginning of the
-     * the 6 source coordinates
-     * @param left the array for storing the coordinates for the first
-     * half of the subdivided curve
-     * @param leftoff the offset into the array of the beginning of the
-     * the 6 left coordinates
-     * @param right the array for storing the coordinates for the second
-     * half of the subdivided curve
-     * @param rightoff the offset into the array of the beginning of the
-     * the 6 right coordinates
-     * @since 1.7
-     */
-    static void subdivideCubic(float src[], int srcoff,
-                               float left[], int leftoff,
-                               float right[], int rightoff)
-    {
-        float x1 = src[srcoff + 0];
-        float y1 = src[srcoff + 1];
-        float ctrlx1 = src[srcoff + 2];
-        float ctrly1 = src[srcoff + 3];
-        float ctrlx2 = src[srcoff + 4];
-        float ctrly2 = src[srcoff + 5];
-        float x2 = src[srcoff + 6];
-        float y2 = src[srcoff + 7];
-        if (left != null) {
-            left[leftoff + 0] = x1;
-            left[leftoff + 1] = y1;
-        }
-        if (right != null) {
-            right[rightoff + 6] = x2;
-            right[rightoff + 7] = y2;
-        }
-        x1 = (x1 + ctrlx1) / 2.0f;
-        y1 = (y1 + ctrly1) / 2.0f;
-        x2 = (x2 + ctrlx2) / 2.0f;
-        y2 = (y2 + ctrly2) / 2.0f;
-        float centerx = (ctrlx1 + ctrlx2) / 2.0f;
-        float centery = (ctrly1 + ctrly2) / 2.0f;
-        ctrlx1 = (x1 + centerx) / 2.0f;
-        ctrly1 = (y1 + centery) / 2.0f;
-        ctrlx2 = (x2 + centerx) / 2.0f;
-        ctrly2 = (y2 + centery) / 2.0f;
-        centerx = (ctrlx1 + ctrlx2) / 2.0f;
-        centery = (ctrly1 + ctrly2) / 2.0f;
-        if (left != null) {
-            left[leftoff + 2] = x1;
-            left[leftoff + 3] = y1;
-            left[leftoff + 4] = ctrlx1;
-            left[leftoff + 5] = ctrly1;
-            left[leftoff + 6] = centerx;
-            left[leftoff + 7] = centery;
-        }
-        if (right != null) {
-            right[rightoff + 0] = centerx;
-            right[rightoff + 1] = centery;
-            right[rightoff + 2] = ctrlx2;
-            right[rightoff + 3] = ctrly2;
-            right[rightoff + 4] = x2;
-            right[rightoff + 5] = y2;
-        }
-    }
-
-
-    static void subdivideCubicAt(float t, float src[], int srcoff,
-                                 float left[], int leftoff,
-                                 float right[], int rightoff)
-    {
-        float x1 = src[srcoff + 0];
-        float y1 = src[srcoff + 1];
-        float ctrlx1 = src[srcoff + 2];
-        float ctrly1 = src[srcoff + 3];
-        float ctrlx2 = src[srcoff + 4];
-        float ctrly2 = src[srcoff + 5];
-        float x2 = src[srcoff + 6];
-        float y2 = src[srcoff + 7];
-        if (left != null) {
-            left[leftoff + 0] = x1;
-            left[leftoff + 1] = y1;
-        }
-        if (right != null) {
-            right[rightoff + 6] = x2;
-            right[rightoff + 7] = y2;
-        }
-        x1 = x1 + t * (ctrlx1 - x1);
-        y1 = y1 + t * (ctrly1 - y1);
-        x2 = ctrlx2 + t * (x2 - ctrlx2);
-        y2 = ctrly2 + t * (y2 - ctrly2);
-        float centerx = ctrlx1 + t * (ctrlx2 - ctrlx1);
-        float centery = ctrly1 + t * (ctrly2 - ctrly1);
-        ctrlx1 = x1 + t * (centerx - x1);
-        ctrly1 = y1 + t * (centery - y1);
-        ctrlx2 = centerx + t * (x2 - centerx);
-        ctrly2 = centery + t * (y2 - centery);
-        centerx = ctrlx1 + t * (ctrlx2 - ctrlx1);
-        centery = ctrly1 + t * (ctrly2 - ctrly1);
-        if (left != null) {
-            left[leftoff + 2] = x1;
-            left[leftoff + 3] = y1;
-            left[leftoff + 4] = ctrlx1;
-            left[leftoff + 5] = ctrly1;
-            left[leftoff + 6] = centerx;
-            left[leftoff + 7] = centery;
-        }
-        if (right != null) {
-            right[rightoff + 0] = centerx;
-            right[rightoff + 1] = centery;
-            right[rightoff + 2] = ctrlx2;
-            right[rightoff + 3] = ctrly2;
-            right[rightoff + 4] = x2;
-            right[rightoff + 5] = y2;
-        }
-    }
-
-    static void subdivideQuad(float src[], int srcoff,
-                              float left[], int leftoff,
-                              float right[], int rightoff)
-    {
-        float x1 = src[srcoff + 0];
-        float y1 = src[srcoff + 1];
-        float ctrlx = src[srcoff + 2];
-        float ctrly = src[srcoff + 3];
-        float x2 = src[srcoff + 4];
-        float y2 = src[srcoff + 5];
-        if (left != null) {
-            left[leftoff + 0] = x1;
-            left[leftoff + 1] = y1;
-        }
-        if (right != null) {
-            right[rightoff + 4] = x2;
-            right[rightoff + 5] = y2;
-        }
-        x1 = (x1 + ctrlx) / 2.0f;
-        y1 = (y1 + ctrly) / 2.0f;
-        x2 = (x2 + ctrlx) / 2.0f;
-        y2 = (y2 + ctrly) / 2.0f;
-        ctrlx = (x1 + x2) / 2.0f;
-        ctrly = (y1 + y2) / 2.0f;
-        if (left != null) {
-            left[leftoff + 2] = x1;
-            left[leftoff + 3] = y1;
-            left[leftoff + 4] = ctrlx;
-            left[leftoff + 5] = ctrly;
-        }
-        if (right != null) {
-            right[rightoff + 0] = ctrlx;
-            right[rightoff + 1] = ctrly;
-            right[rightoff + 2] = x2;
-            right[rightoff + 3] = y2;
-        }
-    }
-
-    static void subdivideQuadAt(float t, float src[], int srcoff,
-                                float left[], int leftoff,
-                                float right[], int rightoff)
-    {
-        float x1 = src[srcoff + 0];
-        float y1 = src[srcoff + 1];
-        float ctrlx = src[srcoff + 2];
-        float ctrly = src[srcoff + 3];
-        float x2 = src[srcoff + 4];
-        float y2 = src[srcoff + 5];
-        if (left != null) {
-            left[leftoff + 0] = x1;
-            left[leftoff + 1] = y1;
-        }
-        if (right != null) {
-            right[rightoff + 4] = x2;
-            right[rightoff + 5] = y2;
-        }
-        x1 = x1 + t * (ctrlx - x1);
-        y1 = y1 + t * (ctrly - y1);
-        x2 = ctrlx + t * (x2 - ctrlx);
-        y2 = ctrly + t * (y2 - ctrly);
-        ctrlx = x1 + t * (x2 - x1);
-        ctrly = y1 + t * (y2 - y1);
-        if (left != null) {
-            left[leftoff + 2] = x1;
-            left[leftoff + 3] = y1;
-            left[leftoff + 4] = ctrlx;
-            left[leftoff + 5] = ctrly;
-        }
-        if (right != null) {
-            right[rightoff + 0] = ctrlx;
-            right[rightoff + 1] = ctrly;
-            right[rightoff + 2] = x2;
-            right[rightoff + 3] = y2;
-        }
-    }
-
-    static void subdivideAt(float t, float src[], int srcoff,
-                            float left[], int leftoff,
-                            float right[], int rightoff, int size)
-    {
-        switch(size) {
-        case 8:
-            subdivideCubicAt(t, src, srcoff, left, leftoff, right, rightoff);
-            break;
-        case 6:
-            subdivideQuadAt(t, src, srcoff, left, leftoff, right, rightoff);
-            break;
-        }
-    }
-}
--- a/src/java.desktop/share/classes/sun/java2d/pisces/PiscesCache.java	Fri Nov 24 17:19:47 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,193 +0,0 @@
-/*
- * Copyright (c) 2007, 2011, 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.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.
- */
-
-package sun.java2d.pisces;
-
-import java.util.Arrays;
-
-/**
- * An object used to cache pre-rendered complex paths.
- */
-final class PiscesCache {
-
-    final int bboxX0, bboxY0, bboxX1, bboxY1;
-
-    // rowAARLE[i] holds the encoding of the pixel row with y = bboxY0+i.
-    // The format of each of the inner arrays is: rowAARLE[i][0,1] = (x0, n)
-    // where x0 is the first x in row i with nonzero alpha, and n is the
-    // number of RLE entries in this row. rowAARLE[i][j,j+1] for j>1 is
-    // (val,runlen)
-    final int[][] rowAARLE;
-
-    // RLE encodings are added in increasing y rows and then in increasing
-    // x inside those rows. Therefore, at any one time there is a well
-    // defined position (x,y) where a run length is about to be added (or
-    // the row terminated). x0,y0 is this (x,y)-(bboxX0,bboxY0). They
-    // are used to get indices into the current tile.
-    private int x0 = Integer.MIN_VALUE, y0 = Integer.MIN_VALUE;
-
-    // touchedTile[i][j] is the sum of all the alphas in the tile with
-    // y=i*TILE_SIZE+bboxY0 and x=j*TILE_SIZE+bboxX0.
-    private final int[][] touchedTile;
-
-    static final int TILE_SIZE_LG = 5;
-    static final int TILE_SIZE = 1 << TILE_SIZE_LG; // 32
-    private static final int INIT_ROW_SIZE = 8; // enough for 3 run lengths
-
-    PiscesCache(int minx, int miny, int maxx, int maxy) {
-        assert maxy >= miny && maxx >= minx;
-        bboxX0 = minx;
-        bboxY0 = miny;
-        bboxX1 = maxx + 1;
-        bboxY1 = maxy + 1;
-        // we could just leave the inner arrays as null and allocate them
-        // lazily (which would be beneficial for shapes with gaps), but we
-        // assume there won't be too many of those so we allocate everything
-        // up front (which is better for other cases)
-        rowAARLE = new int[bboxY1 - bboxY0 + 1][INIT_ROW_SIZE];
-        x0 = 0;
-        y0 = -1; // -1 makes the first assert in startRow succeed
-        // the ceiling of (maxy - miny + 1) / TILE_SIZE;
-        int nyTiles = (maxy - miny + TILE_SIZE) >> TILE_SIZE_LG;
-        int nxTiles = (maxx - minx + TILE_SIZE) >> TILE_SIZE_LG;
-
-        touchedTile = new int[nyTiles][nxTiles];
-    }
-
-    void addRLERun(int val, int runLen) {
-        if (runLen > 0) {
-            addTupleToRow(y0, val, runLen);
-            if (val != 0) {
-                // the x and y of the current row, minus bboxX0, bboxY0
-                int tx = x0 >> TILE_SIZE_LG;
-                int ty = y0 >> TILE_SIZE_LG;
-                int tx1 = (x0 + runLen - 1) >> TILE_SIZE_LG;
-                // while we forbid rows from starting before bboxx0, our users
-                // can still store rows that go beyond bboxx1 (although this
-                // shouldn't happen), so it's a good idea to check that i
-                // is not going out of bounds in touchedTile[ty]
-                if (tx1 >= touchedTile[ty].length) {
-                    tx1 = touchedTile[ty].length - 1;
-                }
-                if (tx <= tx1) {
-                    int nextTileXCoord = (tx + 1) << TILE_SIZE_LG;
-                    if (nextTileXCoord > x0+runLen) {
-                        touchedTile[ty][tx] += val * runLen;
-                    } else {
-                        touchedTile[ty][tx] += val * (nextTileXCoord - x0);
-                    }
-                    tx++;
-                }
-                // don't go all the way to tx1 - we need to handle the last
-                // tile as a special case (just like we did with the first
-                for (; tx < tx1; tx++) {
-//                    try {
-                    touchedTile[ty][tx] += (val << TILE_SIZE_LG);
-//                    } catch (RuntimeException e) {
-//                        System.out.println("x0, y0: " + x0 + ", " + y0);
-//                        System.out.printf("tx, ty, tx1: %d, %d, %d %n", tx, ty, tx1);
-//                        System.out.printf("bboxX/Y0/1: %d, %d, %d, %d %n",
-//                                bboxX0, bboxY0, bboxX1, bboxY1);
-//                        throw e;
-//                    }
-                }
-                // they will be equal unless x0>>TILE_SIZE_LG == tx1
-                if (tx == tx1) {
-                    int lastXCoord = Math.min(x0 + runLen, (tx + 1) << TILE_SIZE_LG);
-                    int txXCoord = tx << TILE_SIZE_LG;
-                    touchedTile[ty][tx] += val * (lastXCoord - txXCoord);
-                }
-            }
-            x0 += runLen;
-        }
-    }
-
-    void startRow(int y, int x) {
-        // rows are supposed to be added by increasing y.
-        assert y - bboxY0 > y0;
-        assert y <= bboxY1; // perhaps this should be < instead of <=
-
-        y0 = y - bboxY0;
-        // this should be a new, uninitialized row.
-        assert rowAARLE[y0][1] == 0;
-
-        x0 = x - bboxX0;
-        assert x0 >= 0 : "Input must not be to the left of bbox bounds";
-
-        // the way addTupleToRow is implemented it would work for this but it's
-        // not a good idea to use it because it is meant for adding
-        // RLE tuples, not the first tuple (which is special).
-        rowAARLE[y0][0] = x;
-        rowAARLE[y0][1] = 2;
-    }
-
-    int alphaSumInTile(int x, int y) {
-        x -= bboxX0;
-        y -= bboxY0;
-        return touchedTile[y>>TILE_SIZE_LG][x>>TILE_SIZE_LG];
-    }
-
-    int minTouched(int rowidx) {
-        return rowAARLE[rowidx][0];
-    }
-
-    int rowLength(int rowidx) {
-        return rowAARLE[rowidx][1];
-    }
-
-    private void addTupleToRow(int row, int a, int b) {
-        int end = rowAARLE[row][1];
-        rowAARLE[row] = Helpers.widenArray(rowAARLE[row], end, 2);
-        rowAARLE[row][end++] = a;
-        rowAARLE[row][end++] = b;
-        rowAARLE[row][1] = end;
-    }
-
-    void getBBox(int bbox[]) {
-        // Since we add +1 to bboxX1,bboxY1 so when PTG asks for bbox,
-        // we will give after -1
-        bbox[0] = bboxX0;
-        bbox[1] = bboxY0;
-        bbox[2] = bboxX1 - 1;
-        bbox[3] = bboxY1 - 1;
-    }
-
-    @Override
-    public String toString() {
-        String ret = "bbox = ["+
-                      bboxX0+", "+bboxY0+" => "+
-                      bboxX1+", "+bboxY1+"]\n";
-        for (int[] row : rowAARLE) {
-            if (row != null) {
-                ret += ("minTouchedX=" + row[0] +
-                        "\tRLE Entries: " + Arrays.toString(
-                                Arrays.copyOfRange(row, 2, row[1])) + "\n");
-            } else {
-                ret += "[]\n";
-            }
-        }
-        return ret;
-    }
-}
--- a/src/java.desktop/share/classes/sun/java2d/pisces/PiscesRenderingEngine.java	Fri Nov 24 17:19:47 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,656 +0,0 @@
-/*
- * Copyright (c) 2007, 2014, 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.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.
- */
-
-package sun.java2d.pisces;
-
-import java.awt.Shape;
-import java.awt.BasicStroke;
-import java.awt.geom.Path2D;
-import java.awt.geom.AffineTransform;
-import java.awt.geom.PathIterator;
-
-import sun.awt.geom.PathConsumer2D;
-import sun.java2d.pipe.Region;
-import sun.java2d.pipe.RenderingEngine;
-import sun.java2d.pipe.AATileGenerator;
-
-public class PiscesRenderingEngine extends RenderingEngine {
-    private static enum NormMode {OFF, ON_NO_AA, ON_WITH_AA}
-
-    /**
-     * Create a widened path as specified by the parameters.
-     * <p>
-     * The specified {@code src} {@link Shape} is widened according
-     * to the specified attribute parameters as per the
-     * {@link BasicStroke} specification.
-     *
-     * @param src the source path to be widened
-     * @param width the width of the widened path as per {@code BasicStroke}
-     * @param caps the end cap decorations as per {@code BasicStroke}
-     * @param join the segment join decorations as per {@code BasicStroke}
-     * @param miterlimit the miter limit as per {@code BasicStroke}
-     * @param dashes the dash length array as per {@code BasicStroke}
-     * @param dashphase the initial dash phase as per {@code BasicStroke}
-     * @return the widened path stored in a new {@code Shape} object
-     * @since 1.7
-     */
-    public Shape createStrokedShape(Shape src,
-                                    float width,
-                                    int caps,
-                                    int join,
-                                    float miterlimit,
-                                    float dashes[],
-                                    float dashphase)
-    {
-        final Path2D p2d = new Path2D.Float();
-
-        strokeTo(src,
-                 null,
-                 width,
-                 NormMode.OFF,
-                 caps,
-                 join,
-                 miterlimit,
-                 dashes,
-                 dashphase,
-                 new PathConsumer2D() {
-                     public void moveTo(float x0, float y0) {
-                         p2d.moveTo(x0, y0);
-                     }
-                     public void lineTo(float x1, float y1) {
-                         p2d.lineTo(x1, y1);
-                     }
-                     public void closePath() {
-                         p2d.closePath();
-                     }
-                     public void pathDone() {}
-                     public void curveTo(float x1, float y1,
-                                         float x2, float y2,
-                                         float x3, float y3) {
-                         p2d.curveTo(x1, y1, x2, y2, x3, y3);
-                     }
-                     public void quadTo(float x1, float y1, float x2, float y2) {
-                         p2d.quadTo(x1, y1, x2, y2);
-                     }
-                     public long getNativeConsumer() {
-                         throw new InternalError("Not using a native peer");
-                     }
-                 });
-        return p2d;
-    }
-
-    /**
-     * Sends the geometry for a widened path as specified by the parameters
-     * to the specified consumer.
-     * <p>
-     * The specified {@code src} {@link Shape} is widened according
-     * to the parameters specified by the {@link BasicStroke} object.
-     * Adjustments are made to the path as appropriate for the
-     * {@link java.awt.RenderingHints#VALUE_STROKE_NORMALIZE} hint if the
-     * {@code normalize} boolean parameter is true.
-     * Adjustments are made to the path as appropriate for the
-     * {@link java.awt.RenderingHints#VALUE_ANTIALIAS_ON} hint if the
-     * {@code antialias} boolean parameter is true.
-     * <p>
-     * The geometry of the widened path is forwarded to the indicated
-     * {@link PathConsumer2D} object as it is calculated.
-     *
-     * @param src the source path to be widened
-     * @param bs the {@code BasicSroke} object specifying the
-     *           decorations to be applied to the widened path
-     * @param normalize indicates whether stroke normalization should
-     *                  be applied
-     * @param antialias indicates whether or not adjustments appropriate
-     *                  to antialiased rendering should be applied
-     * @param consumer the {@code PathConsumer2D} instance to forward
-     *                 the widened geometry to
-     * @since 1.7
-     */
-    public void strokeTo(Shape src,
-                         AffineTransform at,
-                         BasicStroke bs,
-                         boolean thin,
-                         boolean normalize,
-                         boolean antialias,
-                         final PathConsumer2D consumer)
-    {
-        NormMode norm = (normalize) ?
-                ((antialias) ? NormMode.ON_WITH_AA : NormMode.ON_NO_AA)
-                : NormMode.OFF;
-        strokeTo(src, at, bs, thin, norm, antialias, consumer);
-    }
-
-    void strokeTo(Shape src,
-                  AffineTransform at,
-                  BasicStroke bs,
-                  boolean thin,
-                  NormMode normalize,
-                  boolean antialias,
-                  PathConsumer2D pc2d)
-    {
-        float lw;
-        if (thin) {
-            if (antialias) {
-                lw = userSpaceLineWidth(at, 0.5f);
-            } else {
-                lw = userSpaceLineWidth(at, 1.0f);
-            }
-        } else {
-            lw = bs.getLineWidth();
-        }
-        strokeTo(src,
-                 at,
-                 lw,
-                 normalize,
-                 bs.getEndCap(),
-                 bs.getLineJoin(),
-                 bs.getMiterLimit(),
-                 bs.getDashArray(),
-                 bs.getDashPhase(),
-                 pc2d);
-    }
-
-    private float userSpaceLineWidth(AffineTransform at, float lw) {
-
-        double widthScale;
-
-        if ((at.getType() & (AffineTransform.TYPE_GENERAL_TRANSFORM |
-                            AffineTransform.TYPE_GENERAL_SCALE)) != 0) {
-            widthScale = Math.sqrt(at.getDeterminant());
-        } else {
-            /* First calculate the "maximum scale" of this transform. */
-            double A = at.getScaleX();       // m00
-            double C = at.getShearX();       // m01
-            double B = at.getShearY();       // m10
-            double D = at.getScaleY();       // m11
-
-            /*
-             * Given a 2 x 2 affine matrix [ A B ] such that
-             *                             [ C D ]
-             * v' = [x' y'] = [Ax + Cy, Bx + Dy], we want to
-             * find the maximum magnitude (norm) of the vector v'
-             * with the constraint (x^2 + y^2 = 1).
-             * The equation to maximize is
-             *     |v'| = sqrt((Ax+Cy)^2+(Bx+Dy)^2)
-             * or  |v'| = sqrt((AA+BB)x^2 + 2(AC+BD)xy + (CC+DD)y^2).
-             * Since sqrt is monotonic we can maximize |v'|^2
-             * instead and plug in the substitution y = sqrt(1 - x^2).
-             * Trigonometric equalities can then be used to get
-             * rid of most of the sqrt terms.
-             */
-
-            double EA = A*A + B*B;          // x^2 coefficient
-            double EB = 2*(A*C + B*D);      // xy coefficient
-            double EC = C*C + D*D;          // y^2 coefficient
-
-            /*
-             * There is a lot of calculus omitted here.
-             *
-             * Conceptually, in the interests of understanding the
-             * terms that the calculus produced we can consider
-             * that EA and EC end up providing the lengths along
-             * the major axes and the hypot term ends up being an
-             * adjustment for the additional length along the off-axis
-             * angle of rotated or sheared ellipses as well as an
-             * adjustment for the fact that the equation below
-             * averages the two major axis lengths.  (Notice that
-             * the hypot term contains a part which resolves to the
-             * difference of these two axis lengths in the absence
-             * of rotation.)
-             *
-             * In the calculus, the ratio of the EB and (EA-EC) terms
-             * ends up being the tangent of 2*theta where theta is
-             * the angle that the long axis of the ellipse makes
-             * with the horizontal axis.  Thus, this equation is
-             * calculating the length of the hypotenuse of a triangle
-             * along that axis.
-             */
-
-            double hypot = Math.sqrt(EB*EB + (EA-EC)*(EA-EC));
-            /* sqrt omitted, compare to squared limits below. */
-            double widthsquared = ((EA + EC + hypot)/2.0);
-
-            widthScale = Math.sqrt(widthsquared);
-        }
-
-        return (float) (lw / widthScale);
-    }
-
-    void strokeTo(Shape src,
-                  AffineTransform at,
-                  float width,
-                  NormMode normalize,
-                  int caps,
-                  int join,
-                  float miterlimit,
-                  float dashes[],
-                  float dashphase,
-                  PathConsumer2D pc2d)
-    {
-        // We use strokerat and outat so that in Stroker and Dasher we can work only
-        // with the pre-transformation coordinates. This will repeat a lot of
-        // computations done in the path iterator, but the alternative is to
-        // work with transformed paths and compute untransformed coordinates
-        // as needed. This would be faster but I do not think the complexity
-        // of working with both untransformed and transformed coordinates in
-        // the same code is worth it.
-        // However, if a path's width is constant after a transformation,
-        // we can skip all this untransforming.
-
-        // If normalization is off we save some transformations by not
-        // transforming the input to pisces. Instead, we apply the
-        // transformation after the path processing has been done.
-        // We can't do this if normalization is on, because it isn't a good
-        // idea to normalize before the transformation is applied.
-        AffineTransform strokerat = null;
-        AffineTransform outat = null;
-
-        PathIterator pi = null;
-
-        if (at != null && !at.isIdentity()) {
-            final double a = at.getScaleX();
-            final double b = at.getShearX();
-            final double c = at.getShearY();
-            final double d = at.getScaleY();
-            final double det = a * d - c * b;
-            if (Math.abs(det) <= 2 * Float.MIN_VALUE) {
-                // this rendering engine takes one dimensional curves and turns
-                // them into 2D shapes by giving them width.
-                // However, if everything is to be passed through a singular
-                // transformation, these 2D shapes will be squashed down to 1D
-                // again so, nothing can be drawn.
-
-                // Every path needs an initial moveTo and a pathDone. If these
-                // are not there this causes a SIGSEGV in libawt.so (at the time
-                // of writing of this comment (September 16, 2010)). Actually,
-                // I am not sure if the moveTo is necessary to avoid the SIGSEGV
-                // but the pathDone is definitely needed.
-                pc2d.moveTo(0, 0);
-                pc2d.pathDone();
-                return;
-            }
-
-            // If the transform is a constant multiple of an orthogonal transformation
-            // then every length is just multiplied by a constant, so we just
-            // need to transform input paths to stroker and tell stroker
-            // the scaled width. This condition is satisfied if
-            // a*b == -c*d && a*a+c*c == b*b+d*d. In the actual check below, we
-            // leave a bit of room for error.
-            if (nearZero(a*b + c*d, 2) && nearZero(a*a+c*c - (b*b+d*d), 2)) {
-                double scale = Math.sqrt(a*a + c*c);
-                if (dashes != null) {
-                    dashes = java.util.Arrays.copyOf(dashes, dashes.length);
-                    for (int i = 0; i < dashes.length; i++) {
-                        dashes[i] = (float)(scale * dashes[i]);
-                    }
-                    dashphase = (float)(scale * dashphase);
-                }
-                width = (float)(scale * width);
-                pi = src.getPathIterator(at);
-                if (normalize != NormMode.OFF) {
-                    pi = new NormalizingPathIterator(pi, normalize);
-                }
-                // by now strokerat == null && outat == null. Input paths to
-                // stroker (and maybe dasher) will have the full transform at
-                // applied to them and nothing will happen to the output paths.
-            } else {
-                if (normalize != NormMode.OFF) {
-                    strokerat = at;
-                    pi = src.getPathIterator(at);
-                    pi = new NormalizingPathIterator(pi, normalize);
-                    // by now strokerat == at && outat == null. Input paths to
-                    // stroker (and maybe dasher) will have the full transform at
-                    // applied to them, then they will be normalized, and then
-                    // the inverse of *only the non translation part of at* will
-                    // be applied to the normalized paths. This won't cause problems
-                    // in stroker, because, suppose at = T*A, where T is just the
-                    // translation part of at, and A is the rest. T*A has already
-                    // been applied to Stroker/Dasher's input. Then Ainv will be
-                    // applied. Ainv*T*A is not equal to T, but it is a translation,
-                    // which means that none of stroker's assumptions about its
-                    // input will be violated. After all this, A will be applied
-                    // to stroker's output.
-                } else {
-                    outat = at;
-                    pi = src.getPathIterator(null);
-                    // outat == at && strokerat == null. This is because if no
-                    // normalization is done, we can just apply all our
-                    // transformations to stroker's output.
-                }
-            }
-        } else {
-            // either at is null or it's the identity. In either case
-            // we don't transform the path.
-            pi = src.getPathIterator(null);
-            if (normalize != NormMode.OFF) {
-                pi = new NormalizingPathIterator(pi, normalize);
-            }
-        }
-
-        // by now, at least one of outat and strokerat will be null. Unless at is not
-        // a constant multiple of an orthogonal transformation, they will both be
-        // null. In other cases, outat == at if normalization is off, and if
-        // normalization is on, strokerat == at.
-        pc2d = TransformingPathConsumer2D.transformConsumer(pc2d, outat);
-        pc2d = TransformingPathConsumer2D.deltaTransformConsumer(pc2d, strokerat);
-        pc2d = new Stroker(pc2d, width, caps, join, miterlimit);
-        if (dashes != null) {
-            pc2d = new Dasher(pc2d, dashes, dashphase);
-        }
-        pc2d = TransformingPathConsumer2D.inverseDeltaTransformConsumer(pc2d, strokerat);
-        pathTo(pi, pc2d);
-    }
-
-    private static boolean nearZero(double num, int nulps) {
-        return Math.abs(num) < nulps * Math.ulp(num);
-    }
-
-    private static class NormalizingPathIterator implements PathIterator {
-
-        private final PathIterator src;
-
-        // the adjustment applied to the current position.
-        private float curx_adjust, cury_adjust;
-        // the adjustment applied to the last moveTo position.
-        private float movx_adjust, movy_adjust;
-
-        // constants used in normalization computations
-        private final float lval, rval;
-
-        NormalizingPathIterator(PathIterator src, NormMode mode) {
-            this.src = src;
-            switch (mode) {
-            case ON_NO_AA:
-                // round to nearest (0.25, 0.25) pixel
-                lval = rval = 0.25f;
-                break;
-            case ON_WITH_AA:
-                // round to nearest pixel center
-                lval = 0f;
-                rval = 0.5f;
-                break;
-            case OFF:
-                throw new InternalError("A NormalizingPathIterator should " +
-                         "not be created if no normalization is being done");
-            default:
-                throw new InternalError("Unrecognized normalization mode");
-            }
-        }
-
-        public int currentSegment(float[] coords) {
-            int type = src.currentSegment(coords);
-
-            int lastCoord;
-            switch(type) {
-            case PathIterator.SEG_CUBICTO:
-                lastCoord = 4;
-                break;
-            case PathIterator.SEG_QUADTO:
-                lastCoord = 2;
-                break;
-            case PathIterator.SEG_LINETO:
-            case PathIterator.SEG_MOVETO:
-                lastCoord = 0;
-                break;
-            case PathIterator.SEG_CLOSE:
-                // we don't want to deal with this case later. We just exit now
-                curx_adjust = movx_adjust;
-                cury_adjust = movy_adjust;
-                return type;
-            default:
-                throw new InternalError("Unrecognized curve type");
-            }
-
-            // normalize endpoint
-            float x_adjust = (float)Math.floor(coords[lastCoord] + lval) +
-                         rval - coords[lastCoord];
-            float y_adjust = (float)Math.floor(coords[lastCoord+1] + lval) +
-                         rval - coords[lastCoord + 1];
-
-            coords[lastCoord    ] += x_adjust;
-            coords[lastCoord + 1] += y_adjust;
-
-            // now that the end points are done, normalize the control points
-            switch(type) {
-            case PathIterator.SEG_CUBICTO:
-                coords[0] += curx_adjust;
-                coords[1] += cury_adjust;
-                coords[2] += x_adjust;
-                coords[3] += y_adjust;
-                break;
-            case PathIterator.SEG_QUADTO:
-                coords[0] += (curx_adjust + x_adjust) / 2;
-                coords[1] += (cury_adjust + y_adjust) / 2;
-                break;
-            case PathIterator.SEG_LINETO:
-                break;
-            case PathIterator.SEG_MOVETO:
-                movx_adjust = x_adjust;
-                movy_adjust = y_adjust;
-                break;
-            case PathIterator.SEG_CLOSE:
-                throw new InternalError("This should be handled earlier.");
-            }
-            curx_adjust = x_adjust;
-            cury_adjust = y_adjust;
-            return type;
-        }
-
-        public int currentSegment(double[] coords) {
-            float[] tmp = new float[6];
-            int type = this.currentSegment(tmp);
-            for (int i = 0; i < 6; i++) {
-                coords[i] = tmp[i];
-            }
-            return type;
-        }
-
-        public int getWindingRule() {
-            return src.getWindingRule();
-        }
-
-        public boolean isDone() {
-            return src.isDone();
-        }
-
-        public void next() {
-            src.next();
-        }
-    }
-
-    static void pathTo(PathIterator pi, PathConsumer2D pc2d) {
-        RenderingEngine.feedConsumer(pi, pc2d);
-        pc2d.pathDone();
-    }
-
-    /**
-     * Construct an antialiased tile generator for the given shape with
-     * the given rendering attributes and store the bounds of the tile
-     * iteration in the bbox parameter.
-     * The {@code at} parameter specifies a transform that should affect
-     * both the shape and the {@code BasicStroke} attributes.
-     * The {@code clip} parameter specifies the current clip in effect
-     * in device coordinates and can be used to prune the data for the
-     * operation, but the renderer is not required to perform any
-     * clipping.
-     * If the {@code BasicStroke} parameter is null then the shape
-     * should be filled as is, otherwise the attributes of the
-     * {@code BasicStroke} should be used to specify a draw operation.
-     * The {@code thin} parameter indicates whether or not the
-     * transformed {@code BasicStroke} represents coordinates smaller
-     * than the minimum resolution of the antialiasing rasterizer as
-     * specified by the {@code getMinimumAAPenWidth()} method.
-     * <p>
-     * Upon returning, this method will fill the {@code bbox} parameter
-     * with 4 values indicating the bounds of the iteration of the
-     * tile generator.
-     * The iteration order of the tiles will be as specified by the
-     * pseudo-code:
-     * <pre>
-     *     for (y = bbox[1]; y < bbox[3]; y += tileheight) {
-     *         for (x = bbox[0]; x < bbox[2]; x += tilewidth) {
-     *         }
-     *     }
-     * </pre>
-     * If there is no output to be rendered, this method may return
-     * null.
-     *
-     * @param s the shape to be rendered (fill or draw)
-     * @param at the transform to be applied to the shape and the
-     *           stroke attributes
-     * @param clip the current clip in effect in device coordinates
-     * @param bs if non-null, a {@code BasicStroke} whose attributes
-     *           should be applied to this operation
-     * @param thin true if the transformed stroke attributes are smaller
-     *             than the minimum dropout pen width
-     * @param normalize true if the {@code VALUE_STROKE_NORMALIZE}
-     *                  {@code RenderingHint} is in effect
-     * @param bbox returns the bounds of the iteration
-     * @return the {@code AATileGenerator} instance to be consulted
-     *         for tile coverages, or null if there is no output to render
-     * @since 1.7
-     */
-    public AATileGenerator getAATileGenerator(Shape s,
-                                              AffineTransform at,
-                                              Region clip,
-                                              BasicStroke bs,
-                                              boolean thin,
-                                              boolean normalize,
-                                              int bbox[])
-    {
-        Renderer r;
-        NormMode norm = (normalize) ? NormMode.ON_WITH_AA : NormMode.OFF;
-        if (bs == null) {
-            PathIterator pi;
-            if (normalize) {
-                pi = new NormalizingPathIterator(s.getPathIterator(at), norm);
-            } else {
-                pi = s.getPathIterator(at);
-            }
-            r = new Renderer(3, 3,
-                             clip.getLoX(), clip.getLoY(),
-                             clip.getWidth(), clip.getHeight(),
-                             pi.getWindingRule());
-            pathTo(pi, r);
-        } else {
-            r = new Renderer(3, 3,
-                             clip.getLoX(), clip.getLoY(),
-                             clip.getWidth(), clip.getHeight(),
-                             PathIterator.WIND_NON_ZERO);
-            strokeTo(s, at, bs, thin, norm, true, r);
-        }
-        r.endRendering();
-        PiscesTileGenerator ptg = new PiscesTileGenerator(r, r.MAX_AA_ALPHA);
-        ptg.getBbox(bbox);
-        return ptg;
-    }
-
-    public AATileGenerator getAATileGenerator(double x, double y,
-                                              double dx1, double dy1,
-                                              double dx2, double dy2,
-                                              double lw1, double lw2,
-                                              Region clip,
-                                              int bbox[])
-    {
-        // REMIND: Deal with large coordinates!
-        double ldx1, ldy1, ldx2, ldy2;
-        boolean innerpgram = (lw1 > 0 && lw2 > 0);
-
-        if (innerpgram) {
-            ldx1 = dx1 * lw1;
-            ldy1 = dy1 * lw1;
-            ldx2 = dx2 * lw2;
-            ldy2 = dy2 * lw2;
-            x -= (ldx1 + ldx2) / 2.0;
-            y -= (ldy1 + ldy2) / 2.0;
-            dx1 += ldx1;
-            dy1 += ldy1;
-            dx2 += ldx2;
-            dy2 += ldy2;
-            if (lw1 > 1 && lw2 > 1) {
-                // Inner parallelogram was entirely consumed by stroke...
-                innerpgram = false;
-            }
-        } else {
-            ldx1 = ldy1 = ldx2 = ldy2 = 0;
-        }
-
-        Renderer r = new Renderer(3, 3,
-                clip.getLoX(), clip.getLoY(),
-                clip.getWidth(), clip.getHeight(),
-                PathIterator.WIND_EVEN_ODD);
-
-        r.moveTo((float) x, (float) y);
-        r.lineTo((float) (x+dx1), (float) (y+dy1));
-        r.lineTo((float) (x+dx1+dx2), (float) (y+dy1+dy2));
-        r.lineTo((float) (x+dx2), (float) (y+dy2));
-        r.closePath();
-
-        if (innerpgram) {
-            x += ldx1 + ldx2;
-            y += ldy1 + ldy2;
-            dx1 -= 2.0 * ldx1;
-            dy1 -= 2.0 * ldy1;
-            dx2 -= 2.0 * ldx2;
-            dy2 -= 2.0 * ldy2;
-            r.moveTo((float) x, (float) y);
-            r.lineTo((float) (x+dx1), (float) (y+dy1));
-            r.lineTo((float) (x+dx1+dx2), (float) (y+dy1+dy2));
-            r.lineTo((float) (x+dx2), (float) (y+dy2));
-            r.closePath();
-        }
-
-        r.pathDone();
-
-        r.endRendering();
-        PiscesTileGenerator ptg = new PiscesTileGenerator(r, r.MAX_AA_ALPHA);
-        ptg.getBbox(bbox);
-        return ptg;
-    }
-
-    /**
-     * Returns the minimum pen width that the antialiasing rasterizer
-     * can represent without dropouts occurring.
-     * @since 1.7
-     */
-    public float getMinimumAAPenSize() {
-        return 0.5f;
-    }
-
-    static {
-        if (PathIterator.WIND_NON_ZERO != Renderer.WIND_NON_ZERO ||
-            PathIterator.WIND_EVEN_ODD != Renderer.WIND_EVEN_ODD ||
-            BasicStroke.JOIN_MITER != Stroker.JOIN_MITER ||
-            BasicStroke.JOIN_ROUND != Stroker.JOIN_ROUND ||
-            BasicStroke.JOIN_BEVEL != Stroker.JOIN_BEVEL ||
-            BasicStroke.CAP_BUTT != Stroker.CAP_BUTT ||
-            BasicStroke.CAP_ROUND != Stroker.CAP_ROUND ||
-            BasicStroke.CAP_SQUARE != Stroker.CAP_SQUARE)
-        {
-            throw new InternalError("mismatched renderer constants");
-        }
-    }
-}
-
--- a/src/java.desktop/share/classes/sun/java2d/pisces/PiscesTileGenerator.java	Fri Nov 24 17:19:47 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,249 +0,0 @@
-/*
- * Copyright (c) 2007, 2011, 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.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.
- */
-
-package sun.java2d.pisces;
-
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-
-import sun.java2d.pipe.AATileGenerator;
-
-final class PiscesTileGenerator implements AATileGenerator {
-    public static final int TILE_SIZE = PiscesCache.TILE_SIZE;
-
-    // perhaps we should be using weak references here, but right now
-    // that's not necessary. The way the renderer is, this map will
-    // never contain more than one element - the one with key 64, since
-    // we only do 8x8 supersampling.
-    private static final Map<Integer, byte[]> alphaMapsCache = new
-                   ConcurrentHashMap<Integer, byte[]>();
-
-    PiscesCache cache;
-    int x, y;
-    final int maxalpha;
-    private final int maxTileAlphaSum;
-
-    // The alpha map used by this object (taken out of our map cache) to convert
-    // pixel coverage counts gotten from PiscesCache (which are in the range
-    // [0, maxalpha]) into alpha values, which are in [0,256).
-    byte alphaMap[];
-
-    public PiscesTileGenerator(Renderer r, int maxalpha) {
-        this.cache = r.getCache();
-        this.x = cache.bboxX0;
-        this.y = cache.bboxY0;
-        this.alphaMap = getAlphaMap(maxalpha);
-        this.maxalpha = maxalpha;
-        this.maxTileAlphaSum = TILE_SIZE*TILE_SIZE*maxalpha;
-    }
-
-    private static byte[] buildAlphaMap(int maxalpha) {
-        byte[] alMap = new byte[maxalpha+1];
-        int halfmaxalpha = maxalpha>>2;
-        for (int i = 0; i <= maxalpha; i++) {
-            alMap[i] = (byte) ((i * 255 + halfmaxalpha) / maxalpha);
-        }
-        return alMap;
-    }
-
-    public static byte[] getAlphaMap(int maxalpha) {
-        if (!alphaMapsCache.containsKey(maxalpha)) {
-            alphaMapsCache.put(maxalpha, buildAlphaMap(maxalpha));
-        }
-        return alphaMapsCache.get(maxalpha);
-    }
-
-    public void getBbox(int bbox[]) {
-        cache.getBBox(bbox);
-        //System.out.println("bbox["+bbox[0]+", "+bbox[1]+" => "+bbox[2]+", "+bbox[3]+"]");
-    }
-
-    /**
-     * Gets the width of the tiles that the generator batches output into.
-     * @return the width of the standard alpha tile
-     */
-    public int getTileWidth() {
-        return TILE_SIZE;
-    }
-
-    /**
-     * Gets the height of the tiles that the generator batches output into.
-     * @return the height of the standard alpha tile
-     */
-    public int getTileHeight() {
-        return TILE_SIZE;
-    }
-
-    /**
-     * Gets the typical alpha value that will characterize the current
-     * tile.
-     * The answer may be 0x00 to indicate that the current tile has
-     * no coverage in any of its pixels, or it may be 0xff to indicate
-     * that the current tile is completely covered by the path, or any
-     * other value to indicate non-trivial coverage cases.
-     * @return 0x00 for no coverage, 0xff for total coverage, or any other
-     *         value for partial coverage of the tile
-     */
-    public int getTypicalAlpha() {
-        int al = cache.alphaSumInTile(x, y);
-        // Note: if we have a filled rectangle that doesn't end on a tile
-        // border, we could still return 0xff, even though al!=maxTileAlphaSum
-        // This is because if we return 0xff, our users will fill a rectangle
-        // starting at x,y that has width = Math.min(TILE_SIZE, bboxX1-x),
-        // and height min(TILE_SIZE,bboxY1-y), which is what should happen.
-        // However, to support this, we would have to use 2 Math.min's
-        // and 2 multiplications per tile, instead of just 2 multiplications
-        // to compute maxTileAlphaSum. The savings offered would probably
-        // not be worth it, considering how rare this case is.
-        // Note: I have not tested this, so in the future if it is determined
-        // that it is worth it, it should be implemented. Perhaps this method's
-        // interface should be changed to take arguments the width and height
-        // of the current tile. This would eliminate the 2 Math.min calls that
-        // would be needed here, since our caller needs to compute these 2
-        // values anyway.
-        return (al == 0x00 ? 0x00 :
-            (al == maxTileAlphaSum ? 0xff : 0x80));
-    }
-
-    /**
-     * Skips the current tile and moves on to the next tile.
-     * Either this method, or the getAlpha() method should be called
-     * once per tile, but not both.
-     */
-    public void nextTile() {
-        if ((x += TILE_SIZE) >= cache.bboxX1) {
-            x = cache.bboxX0;
-            y += TILE_SIZE;
-        }
-    }
-
-    /**
-     * Gets the alpha coverage values for the current tile.
-     * Either this method, or the nextTile() method should be called
-     * once per tile, but not both.
-     */
-    public void getAlpha(byte tile[], int offset, int rowstride) {
-        // Decode run-length encoded alpha mask data
-        // The data for row j begins at cache.rowOffsetsRLE[j]
-        // and is encoded as a set of 2-byte pairs (val, runLen)
-        // terminated by a (0, 0) pair.
-
-        int x0 = this.x;
-        int x1 = x0 + TILE_SIZE;
-        int y0 = this.y;
-        int y1 = y0 + TILE_SIZE;
-        if (x1 > cache.bboxX1) x1 = cache.bboxX1;
-        if (y1 > cache.bboxY1) y1 = cache.bboxY1;
-        y0 -= cache.bboxY0;
-        y1 -= cache.bboxY0;
-
-        int idx = offset;
-        for (int cy = y0; cy < y1; cy++) {
-            int[] row = cache.rowAARLE[cy];
-            assert row != null;
-            int cx = cache.minTouched(cy);
-            if (cx > x1) cx = x1;
-
-            for (int i = x0; i < cx; i++) {
-                tile[idx++] = 0x00;
-            }
-
-            int pos = 2;
-            while (cx < x1 && pos < row[1]) {
-                byte val;
-                int runLen = 0;
-                assert row[1] > 2;
-                try {
-                    val = alphaMap[row[pos]];
-                    runLen = row[pos + 1];
-                    assert runLen > 0;
-                } catch (RuntimeException e0) {
-                    System.out.println("maxalpha = "+maxalpha);
-                    System.out.println("tile["+x0+", "+y0+
-                                       " => "+x1+", "+y1+"]");
-                    System.out.println("cx = "+cx+", cy = "+cy);
-                    System.out.println("idx = "+idx+", pos = "+pos);
-                    System.out.println("len = "+runLen);
-                    System.out.print(cache.toString());
-                    e0.printStackTrace();
-                    throw e0;
-                }
-
-                int rx0 = cx;
-                cx += runLen;
-                int rx1 = cx;
-                if (rx0 < x0) rx0 = x0;
-                if (rx1 > x1) rx1 = x1;
-                runLen = rx1 - rx0;
-                //System.out.println("M["+runLen+"]");
-                while (--runLen >= 0) {
-                    try {
-                        tile[idx++] = val;
-                    } catch (RuntimeException e) {
-                        System.out.println("maxalpha = "+maxalpha);
-                        System.out.println("tile["+x0+", "+y0+
-                                           " => "+x1+", "+y1+"]");
-                        System.out.println("cx = "+cx+", cy = "+cy);
-                        System.out.println("idx = "+idx+", pos = "+pos);
-                        System.out.println("rx0 = "+rx0+", rx1 = "+rx1);
-                        System.out.println("len = "+runLen);
-                        System.out.print(cache.toString());
-                        e.printStackTrace();
-                        throw e;
-                    }
-                }
-                pos += 2;
-            }
-            if (cx < x0) { cx = x0; }
-            while (cx < x1) {
-                tile[idx++] = 0x00;
-                cx++;
-            }
-            /*
-            for (int i = idx - (x1-x0); i < idx; i++) {
-                System.out.print(hex(tile[i], 2));
-            }
-            System.out.println();
-            */
-            idx += (rowstride - (x1-x0));
-        }
-        nextTile();
-    }
-
-    static String hex(int v, int d) {
-        String s = Integer.toHexString(v);
-        while (s.length() < d) {
-            s = "0"+s;
-        }
-        return s.substring(0, d);
-    }
-
-    /**
-     * Disposes this tile generator.
-     * No further calls will be made on this instance.
-     */
-    public void dispose() {}
-}
-
--- a/src/java.desktop/share/classes/sun/java2d/pisces/Renderer.java	Fri Nov 24 17:19:47 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,571 +0,0 @@
-/*
- * Copyright (c) 2007, 2011, 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.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.
- */
-
-package sun.java2d.pisces;
-
-import sun.awt.geom.PathConsumer2D;
-
-final class Renderer implements PathConsumer2D {
-
-    private class ScanlineIterator {
-
-        private int[] crossings;
-
-        // crossing bounds. The bounds are not necessarily tight (the scan line
-        // at minY, for example, might have no crossings). The x bounds will
-        // be accumulated as crossings are computed.
-        private final int maxY;
-        private int nextY;
-
-        // indices into the segment pointer lists. They indicate the "active"
-        // sublist in the segment lists (the portion of the list that contains
-        // all the segments that cross the next scan line).
-        private int edgeCount;
-        private int[] edgePtrs;
-
-        private static final int INIT_CROSSINGS_SIZE = 10;
-
-        // Preconditions: Only subpixel scanlines in the range
-        // (start <= subpixel_y <= end) will be evaluated. No
-        // edge may have a valid (i.e. inside the supplied clip)
-        // crossing that would be generated outside that range.
-        private ScanlineIterator(int start, int end) {
-            crossings = new int[INIT_CROSSINGS_SIZE];
-            edgePtrs = new int[INIT_CROSSINGS_SIZE];
-
-            nextY = start;
-            maxY = end;
-            edgeCount = 0;
-        }
-
-        private int next() {
-            int cury = nextY++;
-            int bucket = cury - boundsMinY;
-            int count = this.edgeCount;
-            int ptrs[] = this.edgePtrs;
-            int bucketcount = edgeBucketCounts[bucket];
-            if ((bucketcount & 0x1) != 0) {
-                int newCount = 0;
-                for (int i = 0; i < count; i++) {
-                    int ecur = ptrs[i];
-                    if (edges[ecur+YMAX] > cury) {
-                        ptrs[newCount++] = ecur;
-                    }
-                }
-                count = newCount;
-            }
-            ptrs = Helpers.widenArray(ptrs, count, bucketcount >> 1);
-            for (int ecur = edgeBuckets[bucket]; ecur != NULL; ecur = (int)edges[ecur+NEXT]) {
-                ptrs[count++] = ecur;
-                // REMIND: Adjust start Y if necessary
-            }
-            this.edgePtrs = ptrs;
-            this.edgeCount = count;
-//            if ((count & 0x1) != 0) {
-//                System.out.println("ODD NUMBER OF EDGES!!!!");
-//            }
-            int xings[] = this.crossings;
-            if (xings.length < count) {
-                this.crossings = xings = new int[ptrs.length];
-            }
-            for (int i = 0; i < count; i++) {
-                int ecur = ptrs[i];
-                float curx = edges[ecur+CURX];
-                int cross = ((int) curx) << 1;
-                edges[ecur+CURX] = curx + edges[ecur+SLOPE];
-                if (edges[ecur+OR] > 0) {
-                    cross |= 1;
-                }
-                int j = i;
-                while (--j >= 0) {
-                    int jcross = xings[j];
-                    if (jcross <= cross) {
-                        break;
-                    }
-                    xings[j+1] = jcross;
-                    ptrs[j+1] = ptrs[j];
-                }
-                xings[j+1] = cross;
-                ptrs[j+1] = ecur;
-            }
-            return count;
-        }
-
-        private boolean hasNext() {
-            return nextY < maxY;
-        }
-
-        private int curY() {
-            return nextY - 1;
-        }
-    }
-
-
-//////////////////////////////////////////////////////////////////////////////
-//  EDGE LIST
-//////////////////////////////////////////////////////////////////////////////
-// TODO(maybe): very tempting to use fixed point here. A lot of opportunities
-// for shifts and just removing certain operations altogether.
-
-    // common to all types of input path segments.
-    private static final int YMAX = 0;
-    private static final int CURX = 1;
-    // NEXT and OR are meant to be indices into "int" fields, but arrays must
-    // be homogenous, so every field is a float. However floats can represent
-    // exactly up to 26 bit ints, so we're ok.
-    private static final int OR   = 2;
-    private static final int SLOPE = 3;
-    private static final int NEXT = 4;
-
-    private float edgeMinY = Float.POSITIVE_INFINITY;
-    private float edgeMaxY = Float.NEGATIVE_INFINITY;
-    private float edgeMinX = Float.POSITIVE_INFINITY;
-    private float edgeMaxX = Float.NEGATIVE_INFINITY;
-
-    private static final int SIZEOF_EDGE = 5;
-    // don't just set NULL to -1, because we want NULL+NEXT to be negative.
-    private static final int NULL = -SIZEOF_EDGE;
-    private float[] edges = null;
-    private static final int INIT_NUM_EDGES = 8;
-    private int[] edgeBuckets = null;
-    private int[] edgeBucketCounts = null; // 2*newedges + (1 if pruning needed)
-    private int numEdges;
-
-    private static final float DEC_BND = 20f;
-    private static final float INC_BND = 8f;
-
-    // each bucket is a linked list. this method adds eptr to the
-    // start of the "bucket"th linked list.
-    private void addEdgeToBucket(final int eptr, final int bucket) {
-        edges[eptr+NEXT] = edgeBuckets[bucket];
-        edgeBuckets[bucket] = eptr;
-        edgeBucketCounts[bucket] += 2;
-    }
-
-    // Flattens using adaptive forward differencing. This only carries out
-    // one iteration of the AFD loop. All it does is update AFD variables (i.e.
-    // X0, Y0, D*[X|Y], COUNT; not variables used for computing scanline crossings).
-    private void quadBreakIntoLinesAndAdd(float x0, float y0,
-                                          final Curve c,
-                                          final float x2, final float y2)
-    {
-        final float QUAD_DEC_BND = 32;
-        final int countlg = 4;
-        int count = 1 << countlg;
-        int countsq = count * count;
-        float maxDD = Math.max(c.dbx / countsq, c.dby / countsq);
-        while (maxDD > QUAD_DEC_BND) {
-            maxDD /= 4;
-            count <<= 1;
-        }
-
-        countsq = count * count;
-        final float ddx = c.dbx / countsq;
-        final float ddy = c.dby / countsq;
-        float dx = c.bx / countsq + c.cx / count;
-        float dy = c.by / countsq + c.cy / count;
-
-        while (count-- > 1) {
-            float x1 = x0 + dx;
-            dx += ddx;
-            float y1 = y0 + dy;
-            dy += ddy;
-            addLine(x0, y0, x1, y1);
-            x0 = x1;
-            y0 = y1;
-        }
-        addLine(x0, y0, x2, y2);
-    }
-
-    // x0, y0 and x3,y3 are the endpoints of the curve. We could compute these
-    // using c.xat(0),c.yat(0) and c.xat(1),c.yat(1), but this might introduce
-    // numerical errors, and our callers already have the exact values.
-    // Another alternative would be to pass all the control points, and call c.set
-    // here, but then too many numbers are passed around.
-    private void curveBreakIntoLinesAndAdd(float x0, float y0,
-                                           final Curve c,
-                                           final float x3, final float y3)
-    {
-        final int countlg = 3;
-        int count = 1 << countlg;
-
-        // the dx and dy refer to forward differencing variables, not the last
-        // coefficients of the "points" polynomial
-        float dddx, dddy, ddx, ddy, dx, dy;
-        dddx = 2f * c.dax / (1 << (3 * countlg));
-        dddy = 2f * c.day / (1 << (3 * countlg));
-
-        ddx = dddx + c.dbx / (1 << (2 * countlg));
-        ddy = dddy + c.dby / (1 << (2 * countlg));
-        dx = c.ax / (1 << (3 * countlg)) + c.bx / (1 << (2 * countlg)) + c.cx / (1 << countlg);
-        dy = c.ay / (1 << (3 * countlg)) + c.by / (1 << (2 * countlg)) + c.cy / (1 << countlg);
-
-        // we use x0, y0 to walk the line
-        float x1 = x0, y1 = y0;
-        while (count > 0) {
-            while (Math.abs(ddx) > DEC_BND || Math.abs(ddy) > DEC_BND) {
-                dddx /= 8;
-                dddy /= 8;
-                ddx = ddx/4 - dddx;
-                ddy = ddy/4 - dddy;
-                dx = (dx - ddx) / 2;
-                dy = (dy - ddy) / 2;
-                count <<= 1;
-            }
-            // can only do this on even "count" values, because we must divide count by 2
-            while (count % 2 == 0 && Math.abs(dx) <= INC_BND && Math.abs(dy) <= INC_BND) {
-                dx = 2 * dx + ddx;
-                dy = 2 * dy + ddy;
-                ddx = 4 * (ddx + dddx);
-                ddy = 4 * (ddy + dddy);
-                dddx = 8 * dddx;
-                dddy = 8 * dddy;
-                count >>= 1;
-            }
-            count--;
-            if (count > 0) {
-                x1 += dx;
-                dx += ddx;
-                ddx += dddx;
-                y1 += dy;
-                dy += ddy;
-                ddy += dddy;
-            } else {
-                x1 = x3;
-                y1 = y3;
-            }
-            addLine(x0, y0, x1, y1);
-            x0 = x1;
-            y0 = y1;
-        }
-    }
-
-    private void addLine(float x1, float y1, float x2, float y2) {
-        float or = 1; // orientation of the line. 1 if y increases, 0 otherwise.
-        if (y2 < y1) {
-            or = y2; // no need to declare a temp variable. We have or.
-            y2 = y1;
-            y1 = or;
-            or = x2;
-            x2 = x1;
-            x1 = or;
-            or = 0;
-        }
-        final int firstCrossing = Math.max((int)Math.ceil(y1), boundsMinY);
-        final int lastCrossing = Math.min((int)Math.ceil(y2), boundsMaxY);
-        if (firstCrossing >= lastCrossing) {
-            return;
-        }
-        if (y1 < edgeMinY) { edgeMinY = y1; }
-        if (y2 > edgeMaxY) { edgeMaxY = y2; }
-
-        final float slope = (x2 - x1) / (y2 - y1);
-
-        if (slope > 0) { // <==> x1 < x2
-            if (x1 < edgeMinX) { edgeMinX = x1; }
-            if (x2 > edgeMaxX) { edgeMaxX = x2; }
-        } else {
-            if (x2 < edgeMinX) { edgeMinX = x2; }
-            if (x1 > edgeMaxX) { edgeMaxX = x1; }
-        }
-
-        final int ptr = numEdges * SIZEOF_EDGE;
-        edges = Helpers.widenArray(edges, ptr, SIZEOF_EDGE);
-        numEdges++;
-        edges[ptr+OR] = or;
-        edges[ptr+CURX] = x1 + (firstCrossing - y1) * slope;
-        edges[ptr+SLOPE] = slope;
-        edges[ptr+YMAX] = lastCrossing;
-        final int bucketIdx = firstCrossing - boundsMinY;
-        addEdgeToBucket(ptr, bucketIdx);
-        edgeBucketCounts[lastCrossing - boundsMinY] |= 1;
-    }
-
-// END EDGE LIST
-//////////////////////////////////////////////////////////////////////////////
-
-
-    public static final int WIND_EVEN_ODD = 0;
-    public static final int WIND_NON_ZERO = 1;
-
-    // Antialiasing
-    private final int SUBPIXEL_LG_POSITIONS_X;
-    private final int SUBPIXEL_LG_POSITIONS_Y;
-    private final int SUBPIXEL_POSITIONS_X;
-    private final int SUBPIXEL_POSITIONS_Y;
-    private final int SUBPIXEL_MASK_X;
-    private final int SUBPIXEL_MASK_Y;
-    final int MAX_AA_ALPHA;
-
-    // Cache to store RLE-encoded coverage mask of the current primitive
-    PiscesCache cache;
-
-    // Bounds of the drawing region, at subpixel precision.
-    private final int boundsMinX, boundsMinY, boundsMaxX, boundsMaxY;
-
-    // Current winding rule
-    private final int windingRule;
-
-    // Current drawing position, i.e., final point of last segment
-    private float x0, y0;
-
-    // Position of most recent 'moveTo' command
-    private float pix_sx0, pix_sy0;
-
-    public Renderer(int subpixelLgPositionsX, int subpixelLgPositionsY,
-                    int pix_boundsX, int pix_boundsY,
-                    int pix_boundsWidth, int pix_boundsHeight,
-                    int windingRule)
-    {
-        this.SUBPIXEL_LG_POSITIONS_X = subpixelLgPositionsX;
-        this.SUBPIXEL_LG_POSITIONS_Y = subpixelLgPositionsY;
-        this.SUBPIXEL_MASK_X = (1 << (SUBPIXEL_LG_POSITIONS_X)) - 1;
-        this.SUBPIXEL_MASK_Y = (1 << (SUBPIXEL_LG_POSITIONS_Y)) - 1;
-        this.SUBPIXEL_POSITIONS_X = 1 << (SUBPIXEL_LG_POSITIONS_X);
-        this.SUBPIXEL_POSITIONS_Y = 1 << (SUBPIXEL_LG_POSITIONS_Y);
-        this.MAX_AA_ALPHA = (SUBPIXEL_POSITIONS_X * SUBPIXEL_POSITIONS_Y);
-
-        this.windingRule = windingRule;
-
-        this.boundsMinX = pix_boundsX * SUBPIXEL_POSITIONS_X;
-        this.boundsMinY = pix_boundsY * SUBPIXEL_POSITIONS_Y;
-        this.boundsMaxX = (pix_boundsX + pix_boundsWidth) * SUBPIXEL_POSITIONS_X;
-        this.boundsMaxY = (pix_boundsY + pix_boundsHeight) * SUBPIXEL_POSITIONS_Y;
-
-        edges = new float[INIT_NUM_EDGES * SIZEOF_EDGE];
-        numEdges = 0;
-        edgeBuckets = new int[boundsMaxY - boundsMinY];
-        java.util.Arrays.fill(edgeBuckets, NULL);
-        edgeBucketCounts = new int[edgeBuckets.length + 1];
-    }
-
-    private float tosubpixx(float pix_x) {
-        return pix_x * SUBPIXEL_POSITIONS_X;
-    }
-    private float tosubpixy(float pix_y) {
-        return pix_y * SUBPIXEL_POSITIONS_Y;
-    }
-
-    public void moveTo(float pix_x0, float pix_y0) {
-        closePath();
-        this.pix_sx0 = pix_x0;
-        this.pix_sy0 = pix_y0;
-        this.y0 = tosubpixy(pix_y0);
-        this.x0 = tosubpixx(pix_x0);
-    }
-
-    public void lineTo(float pix_x1, float pix_y1) {
-        float x1 = tosubpixx(pix_x1);
-        float y1 = tosubpixy(pix_y1);
-        addLine(x0, y0, x1, y1);
-        x0 = x1;
-        y0 = y1;
-    }
-
-    private Curve c = new Curve();
-    @Override public void curveTo(float x1, float y1,
-                                  float x2, float y2,
-                                  float x3, float y3)
-    {
-        final float xe = tosubpixx(x3);
-        final float ye = tosubpixy(y3);
-        c.set(x0, y0, tosubpixx(x1), tosubpixy(y1), tosubpixx(x2), tosubpixy(y2), xe, ye);
-        curveBreakIntoLinesAndAdd(x0, y0, c, xe, ye);
-        x0 = xe;
-        y0 = ye;
-    }
-
-    @Override public void quadTo(float x1, float y1, float x2, float y2) {
-        final float xe = tosubpixx(x2);
-        final float ye = tosubpixy(y2);
-        c.set(x0, y0, tosubpixx(x1), tosubpixy(y1), xe, ye);
-        quadBreakIntoLinesAndAdd(x0, y0, c, xe, ye);
-        x0 = xe;
-        y0 = ye;
-    }
-
-    public void closePath() {
-        // lineTo expects its input in pixel coordinates.
-        lineTo(pix_sx0, pix_sy0);
-    }
-
-    public void pathDone() {
-        closePath();
-    }
-
-
-    @Override
-    public long getNativeConsumer() {
-        throw new InternalError("Renderer does not use a native consumer.");
-    }
-
-    private void _endRendering(final int pix_bboxx0, final int pix_bboxx1,
-                               int ymin, int ymax)
-    {
-        // Mask to determine the relevant bit of the crossing sum
-        // 0x1 if EVEN_ODD, all bits if NON_ZERO
-        int mask = (windingRule == WIND_EVEN_ODD) ? 0x1 : ~0x0;
-
-        // add 2 to better deal with the last pixel in a pixel row.
-        int width = pix_bboxx1 - pix_bboxx0;
-        int[] alpha = new int[width+2];
-
-        int bboxx0 = pix_bboxx0 << SUBPIXEL_LG_POSITIONS_X;
-        int bboxx1 = pix_bboxx1 << SUBPIXEL_LG_POSITIONS_X;
-
-        // Now we iterate through the scanlines. We must tell emitRow the coord
-        // of the first non-transparent pixel, so we must keep accumulators for
-        // the first and last pixels of the section of the current pixel row
-        // that we will emit.
-        // We also need to accumulate pix_bbox*, but the iterator does it
-        // for us. We will just get the values from it once this loop is done
-        int pix_maxX = Integer.MIN_VALUE;
-        int pix_minX = Integer.MAX_VALUE;
-
-        int y = boundsMinY; // needs to be declared here so we emit the last row properly.
-        ScanlineIterator it = this.new ScanlineIterator(ymin, ymax);
-        for ( ; it.hasNext(); ) {
-            int numCrossings = it.next();
-            int[] crossings = it.crossings;
-            y = it.curY();
-
-            if (numCrossings > 0) {
-                int lowx = crossings[0] >> 1;
-                int highx = crossings[numCrossings - 1] >> 1;
-                int x0 = Math.max(lowx, bboxx0);
-                int x1 = Math.min(highx, bboxx1);
-
-                pix_minX = Math.min(pix_minX, x0 >> SUBPIXEL_LG_POSITIONS_X);
-                pix_maxX = Math.max(pix_maxX, x1 >> SUBPIXEL_LG_POSITIONS_X);
-            }
-
-            int sum = 0;
-            int prev = bboxx0;
-            for (int i = 0; i < numCrossings; i++) {
-                int curxo = crossings[i];
-                int curx = curxo >> 1;
-                // to turn {0, 1} into {-1, 1}, multiply by 2 and subtract 1.
-                int crorientation = ((curxo & 0x1) << 1) - 1;
-                if ((sum & mask) != 0) {
-                    int x0 = Math.max(prev, bboxx0);
-                    int x1 = Math.min(curx, bboxx1);
-                    if (x0 < x1) {
-                        x0 -= bboxx0; // turn x0, x1 from coords to indeces
-                        x1 -= bboxx0; // in the alpha array.
-
-                        int pix_x = x0 >> SUBPIXEL_LG_POSITIONS_X;
-                        int pix_xmaxm1 = (x1 - 1) >> SUBPIXEL_LG_POSITIONS_X;
-
-                        if (pix_x == pix_xmaxm1) {
-                            // Start and end in same pixel
-                            alpha[pix_x] += (x1 - x0);
-                            alpha[pix_x+1] -= (x1 - x0);
-                        } else {
-                            int pix_xmax = x1 >> SUBPIXEL_LG_POSITIONS_X;
-                            alpha[pix_x] += SUBPIXEL_POSITIONS_X - (x0 & SUBPIXEL_MASK_X);
-                            alpha[pix_x+1] += (x0 & SUBPIXEL_MASK_X);
-                            alpha[pix_xmax] -= SUBPIXEL_POSITIONS_X - (x1 & SUBPIXEL_MASK_X);
-                            alpha[pix_xmax+1] -= (x1 & SUBPIXEL_MASK_X);
-                        }
-                    }
-                }
-                sum += crorientation;
-                prev = curx;
-            }
-
-            // even if this last row had no crossings, alpha will be zeroed
-            // from the last emitRow call. But this doesn't matter because
-            // maxX < minX, so no row will be emitted to the cache.
-            if ((y & SUBPIXEL_MASK_Y) == SUBPIXEL_MASK_Y) {
-                emitRow(alpha, y >> SUBPIXEL_LG_POSITIONS_Y, pix_minX, pix_maxX);
-                pix_minX = Integer.MAX_VALUE;
-                pix_maxX = Integer.MIN_VALUE;
-            }
-        }
-
-        // Emit final row
-        if (pix_maxX >= pix_minX) {
-            emitRow(alpha, y >> SUBPIXEL_LG_POSITIONS_Y, pix_minX, pix_maxX);
-        }
-    }
-
-    public void endRendering() {
-        int spminX = Math.max((int)Math.ceil(edgeMinX), boundsMinX);
-        int spmaxX = Math.min((int)Math.ceil(edgeMaxX), boundsMaxX);
-        int spminY = Math.max((int)Math.ceil(edgeMinY), boundsMinY);
-        int spmaxY = Math.min((int)Math.ceil(edgeMaxY), boundsMaxY);
-
-        int pminX = spminX >> SUBPIXEL_LG_POSITIONS_X;
-        int pmaxX = (spmaxX + SUBPIXEL_MASK_X) >> SUBPIXEL_LG_POSITIONS_X;
-        int pminY = spminY >> SUBPIXEL_LG_POSITIONS_Y;
-        int pmaxY = (spmaxY + SUBPIXEL_MASK_Y) >> SUBPIXEL_LG_POSITIONS_Y;
-
-        if (pminX > pmaxX || pminY > pmaxY) {
-            this.cache = new PiscesCache(boundsMinX >> SUBPIXEL_LG_POSITIONS_X,
-                                         boundsMinY >> SUBPIXEL_LG_POSITIONS_Y,
-                                         boundsMaxX >> SUBPIXEL_LG_POSITIONS_X,
-                                         boundsMaxY >> SUBPIXEL_LG_POSITIONS_Y);
-            return;
-        }
-
-        this.cache = new PiscesCache(pminX, pminY, pmaxX, pmaxY);
-        _endRendering(pminX, pmaxX, spminY, spmaxY);
-    }
-
-    public PiscesCache getCache() {
-        if (cache == null) {
-            throw new InternalError("cache not yet initialized");
-        }
-        return cache;
-    }
-
-    private void emitRow(int[] alphaRow, int pix_y, int pix_from, int pix_to) {
-        // Copy rowAA data into the cache if one is present
-        if (cache != null) {
-            if (pix_to >= pix_from) {
-                cache.startRow(pix_y, pix_from);
-
-                // Perform run-length encoding and store results in the cache
-                int from = pix_from - cache.bboxX0;
-                int to = pix_to - cache.bboxX0;
-
-                int runLen = 1;
-                int startVal = alphaRow[from];
-                for (int i = from + 1; i <= to; i++) {
-                    int nextVal = startVal + alphaRow[i];
-                    if (nextVal == startVal) {
-                        runLen++;
-                    } else {
-                        cache.addRLERun(startVal, runLen);
-                        runLen = 1;
-                        startVal = nextVal;
-                    }
-                }
-                cache.addRLERun(startVal, runLen);
-            }
-        }
-        java.util.Arrays.fill(alphaRow, 0);
-    }
-}
--- a/src/java.desktop/share/classes/sun/java2d/pisces/Stroker.java	Fri Nov 24 17:19:47 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1231 +0,0 @@
-/*
- * Copyright (c) 2007, 2015, 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.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.
- */
-
-package sun.java2d.pisces;
-
-import java.util.Arrays;
-import java.util.Iterator;
-import static java.lang.Math.ulp;
-import static java.lang.Math.sqrt;
-
-import sun.awt.geom.PathConsumer2D;
-
-// TODO: some of the arithmetic here is too verbose and prone to hard to
-// debug typos. We should consider making a small Point/Vector class that
-// has methods like plus(Point), minus(Point), dot(Point), cross(Point)and such
-final class Stroker implements PathConsumer2D {
-
-    private static final int MOVE_TO = 0;
-    private static final int DRAWING_OP_TO = 1; // ie. curve, line, or quad
-    private static final int CLOSE = 2;
-
-    /**
-     * Constant value for join style.
-     */
-    public static final int JOIN_MITER = 0;
-
-    /**
-     * Constant value for join style.
-     */
-    public static final int JOIN_ROUND = 1;
-
-    /**
-     * Constant value for join style.
-     */
-    public static final int JOIN_BEVEL = 2;
-
-    /**
-     * Constant value for end cap style.
-     */
-    public static final int CAP_BUTT = 0;
-
-    /**
-     * Constant value for end cap style.
-     */
-    public static final int CAP_ROUND = 1;
-
-    /**
-     * Constant value for end cap style.
-     */
-    public static final int CAP_SQUARE = 2;
-
-    private final PathConsumer2D out;
-
-    private final int capStyle;
-    private final int joinStyle;
-
-    private final float lineWidth2;
-
-    private final float[][] offset = new float[3][2];
-    private final float[] miter = new float[2];
-    private final float miterLimitSq;
-
-    private int prev;
-
-    // The starting point of the path, and the slope there.
-    private float sx0, sy0, sdx, sdy;
-    // the current point and the slope there.
-    private float cx0, cy0, cdx, cdy; // c stands for current
-    // vectors that when added to (sx0,sy0) and (cx0,cy0) respectively yield the
-    // first and last points on the left parallel path. Since this path is
-    // parallel, it's slope at any point is parallel to the slope of the
-    // original path (thought they may have different directions), so these
-    // could be computed from sdx,sdy and cdx,cdy (and vice versa), but that
-    // would be error prone and hard to read, so we keep these anyway.
-    private float smx, smy, cmx, cmy;
-
-    private final PolyStack reverse = new PolyStack();
-
-    /**
-     * Constructs a {@code Stroker}.
-     *
-     * @param pc2d an output {@code PathConsumer2D}.
-     * @param lineWidth the desired line width in pixels
-     * @param capStyle the desired end cap style, one of
-     * {@code CAP_BUTT}, {@code CAP_ROUND} or
-     * {@code CAP_SQUARE}.
-     * @param joinStyle the desired line join style, one of
-     * {@code JOIN_MITER}, {@code JOIN_ROUND} or
-     * {@code JOIN_BEVEL}.
-     * @param miterLimit the desired miter limit
-     */
-    public Stroker(PathConsumer2D pc2d,
-                   float lineWidth,
-                   int capStyle,
-                   int joinStyle,
-                   float miterLimit)
-    {
-        this.out = pc2d;
-
-        this.lineWidth2 = lineWidth / 2;
-        this.capStyle = capStyle;
-        this.joinStyle = joinStyle;
-
-        float limit = miterLimit * lineWidth2;
-        this.miterLimitSq = limit*limit;
-
-        this.prev = CLOSE;
-    }
-
-    private static void computeOffset(final float lx, final float ly,
-                                      final float w, final float[] m)
-    {
-        final float len = (float) sqrt(lx*lx + ly*ly);
-        if (len == 0) {
-            m[0] = m[1] = 0;
-        } else {
-            m[0] = (ly * w)/len;
-            m[1] = -(lx * w)/len;
-        }
-    }
-
-    // Returns true if the vectors (dx1, dy1) and (dx2, dy2) are
-    // clockwise (if dx1,dy1 needs to be rotated clockwise to close
-    // the smallest angle between it and dx2,dy2).
-    // This is equivalent to detecting whether a point q is on the right side
-    // of a line passing through points p1, p2 where p2 = p1+(dx1,dy1) and
-    // q = p2+(dx2,dy2), which is the same as saying p1, p2, q are in a
-    // clockwise order.
-    // NOTE: "clockwise" here assumes coordinates with 0,0 at the bottom left.
-    private static boolean isCW(final float dx1, final float dy1,
-                                final float dx2, final float dy2)
-    {
-        return dx1 * dy2 <= dy1 * dx2;
-    }
-
-    // pisces used to use fixed point arithmetic with 16 decimal digits. I
-    // didn't want to change the values of the constant below when I converted
-    // it to floating point, so that's why the divisions by 2^16 are there.
-    private static final float ROUND_JOIN_THRESHOLD = 1000/65536f;
-
-    private void drawRoundJoin(float x, float y,
-                               float omx, float omy, float mx, float my,
-                               boolean rev,
-                               float threshold)
-    {
-        if ((omx == 0 && omy == 0) || (mx == 0 && my == 0)) {
-            return;
-        }
-
-        float domx = omx - mx;
-        float domy = omy - my;
-        float len = domx*domx + domy*domy;
-        if (len < threshold) {
-            return;
-        }
-
-        if (rev) {
-            omx = -omx;
-            omy = -omy;
-            mx = -mx;
-            my = -my;
-        }
-        drawRoundJoin(x, y, omx, omy, mx, my, rev);
-    }
-
-    private void drawRoundJoin(float cx, float cy,
-                               float omx, float omy,
-                               float mx, float my,
-                               boolean rev)
-    {
-        // The sign of the dot product of mx,my and omx,omy is equal to the
-        // the sign of the cosine of ext
-        // (ext is the angle between omx,omy and mx,my).
-        final float cosext = omx * mx + omy * my;
-        // If it is >=0, we know that abs(ext) is <= 90 degrees, so we only
-        // need 1 curve to approximate the circle section that joins omx,omy
-        // and mx,my.
-        final int numCurves = (cosext >= 0f) ? 1 : 2;
-
-        switch (numCurves) {
-        case 1:
-            drawBezApproxForArc(cx, cy, omx, omy, mx, my, rev);
-            break;
-        case 2:
-            // we need to split the arc into 2 arcs spanning the same angle.
-            // The point we want will be one of the 2 intersections of the
-            // perpendicular bisector of the chord (omx,omy)->(mx,my) and the
-            // circle. We could find this by scaling the vector
-            // (omx+mx, omy+my)/2 so that it has length=lineWidth2 (and thus lies
-            // on the circle), but that can have numerical problems when the angle
-            // between omx,omy and mx,my is close to 180 degrees. So we compute a
-            // normal of (omx,omy)-(mx,my). This will be the direction of the
-            // perpendicular bisector. To get one of the intersections, we just scale
-            // this vector that its length is lineWidth2 (this works because the
-            // perpendicular bisector goes through the origin). This scaling doesn't
-            // have numerical problems because we know that lineWidth2 divided by
-            // this normal's length is at least 0.5 and at most sqrt(2)/2 (because
-            // we know the angle of the arc is > 90 degrees).
-            float nx = my - omy, ny = omx - mx;
-            float nlen = (float) sqrt(nx*nx + ny*ny);
-            float scale = lineWidth2/nlen;
-            float mmx = nx * scale, mmy = ny * scale;
-
-            // if (isCW(omx, omy, mx, my) != isCW(mmx, mmy, mx, my)) then we've
-            // computed the wrong intersection so we get the other one.
-            // The test above is equivalent to if (rev).
-            if (rev) {
-                mmx = -mmx;
-                mmy = -mmy;
-            }
-            drawBezApproxForArc(cx, cy, omx, omy, mmx, mmy, rev);
-            drawBezApproxForArc(cx, cy, mmx, mmy, mx, my, rev);
-            break;
-        }
-    }
-
-    // the input arc defined by omx,omy and mx,my must span <= 90 degrees.
-    private void drawBezApproxForArc(final float cx, final float cy,
-                                     final float omx, final float omy,
-                                     final float mx, final float my,
-                                     boolean rev)
-    {
-        final float cosext2 = (omx * mx + omy * my) / (2f * lineWidth2 * lineWidth2);
-
-        // check round off errors producing cos(ext) > 1 and a NaN below
-        // cos(ext) == 1 implies colinear segments and an empty join anyway
-        if (cosext2 >= 0.5f) {
-            // just return to avoid generating a flat curve:
-            return;
-        }
-
-        // cv is the length of P1-P0 and P2-P3 divided by the radius of the arc
-        // (so, cv assumes the arc has radius 1). P0, P1, P2, P3 are the points that
-        // define the bezier curve we're computing.
-        // It is computed using the constraints that P1-P0 and P3-P2 are parallel
-        // to the arc tangents at the endpoints, and that |P1-P0|=|P3-P2|.
-        float cv = (float) ((4.0 / 3.0) * sqrt(0.5 - cosext2) /
-                            (1.0 + sqrt(cosext2 + 0.5)));
-        // if clockwise, we need to negate cv.
-        if (rev) { // rev is equivalent to isCW(omx, omy, mx, my)
-            cv = -cv;
-        }
-        final float x1 = cx + omx;
-        final float y1 = cy + omy;
-        final float x2 = x1 - cv * omy;
-        final float y2 = y1 + cv * omx;
-
-        final float x4 = cx + mx;
-        final float y4 = cy + my;
-        final float x3 = x4 + cv * my;
-        final float y3 = y4 - cv * mx;
-
-        emitCurveTo(x1, y1, x2, y2, x3, y3, x4, y4, rev);
-    }
-
-    private void drawRoundCap(float cx, float cy, float mx, float my) {
-        final float C = 0.5522847498307933f;
-        // the first and second arguments of the following two calls
-        // are really will be ignored by emitCurveTo (because of the false),
-        // but we put them in anyway, as opposed to just giving it 4 zeroes,
-        // because it's just 4 additions and it's not good to rely on this
-        // sort of assumption (right now it's true, but that may change).
-        emitCurveTo(cx+mx,      cy+my,
-                    cx+mx-C*my, cy+my+C*mx,
-                    cx-my+C*mx, cy+mx+C*my,
-                    cx-my,      cy+mx,
-                    false);
-        emitCurveTo(cx-my,      cy+mx,
-                    cx-my-C*mx, cy+mx-C*my,
-                    cx-mx-C*my, cy-my+C*mx,
-                    cx-mx,      cy-my,
-                    false);
-    }
-
-    // Put the intersection point of the lines (x0, y0) -> (x1, y1)
-    // and (x0p, y0p) -> (x1p, y1p) in m[off] and m[off+1].
-    // If the lines are parallel, it will put a non finite number in m.
-    private void computeIntersection(final float x0, final float y0,
-                                     final float x1, final float y1,
-                                     final float x0p, final float y0p,
-                                     final float x1p, final float y1p,
-                                     final float[] m, int off)
-    {
-        float x10 = x1 - x0;
-        float y10 = y1 - y0;
-        float x10p = x1p - x0p;
-        float y10p = y1p - y0p;
-
-        float den = x10*y10p - x10p*y10;
-        float t = x10p*(y0-y0p) - y10p*(x0-x0p);
-        t /= den;
-        m[off++] = x0 + t*x10;
-        m[off] = y0 + t*y10;
-    }
-
-    private void drawMiter(final float pdx, final float pdy,
-                           final float x0, final float y0,
-                           final float dx, final float dy,
-                           float omx, float omy, float mx, float my,
-                           boolean rev)
-    {
-        if ((mx == omx && my == omy) ||
-            (pdx == 0 && pdy == 0) ||
-            (dx == 0 && dy == 0))
-        {
-            return;
-        }
-
-        if (rev) {
-            omx = -omx;
-            omy = -omy;
-            mx = -mx;
-            my = -my;
-        }
-
-        computeIntersection((x0 - pdx) + omx, (y0 - pdy) + omy, x0 + omx, y0 + omy,
-                            (dx + x0) + mx, (dy + y0) + my, x0 + mx, y0 + my,
-                            miter, 0);
-
-        float lenSq = (miter[0]-x0)*(miter[0]-x0) + (miter[1]-y0)*(miter[1]-y0);
-
-        // If the lines are parallel, lenSq will be either NaN or +inf
-        // (actually, I'm not sure if the latter is possible. The important
-        // thing is that -inf is not possible, because lenSq is a square).
-        // For both of those values, the comparison below will fail and
-        // no miter will be drawn, which is correct.
-        if (lenSq < miterLimitSq) {
-            emitLineTo(miter[0], miter[1], rev);
-        }
-    }
-
-    public void moveTo(float x0, float y0) {
-        if (prev == DRAWING_OP_TO) {
-            finish();
-        }
-        this.sx0 = this.cx0 = x0;
-        this.sy0 = this.cy0 = y0;
-        this.cdx = this.sdx = 1;
-        this.cdy = this.sdy = 0;
-        this.prev = MOVE_TO;
-    }
-
-    public void lineTo(float x1, float y1) {
-        float dx = x1 - cx0;
-        float dy = y1 - cy0;
-        if (dx == 0f && dy == 0f) {
-            dx = 1;
-        }
-        computeOffset(dx, dy, lineWidth2, offset[0]);
-        float mx = offset[0][0];
-        float my = offset[0][1];
-
-        drawJoin(cdx, cdy, cx0, cy0, dx, dy, cmx, cmy, mx, my);
-
-        emitLineTo(cx0 + mx, cy0 + my);
-        emitLineTo(x1 + mx, y1 + my);
-
-        emitLineTo(cx0 - mx, cy0 - my, true);
-        emitLineTo(x1 - mx, y1 - my, true);
-
-        this.cmx = mx;
-        this.cmy = my;
-        this.cdx = dx;
-        this.cdy = dy;
-        this.cx0 = x1;
-        this.cy0 = y1;
-        this.prev = DRAWING_OP_TO;
-    }
-
-    public void closePath() {
-        if (prev != DRAWING_OP_TO) {
-            if (prev == CLOSE) {
-                return;
-            }
-            emitMoveTo(cx0, cy0 - lineWidth2);
-            this.cmx = this.smx = 0;
-            this.cmy = this.smy = -lineWidth2;
-            this.cdx = this.sdx = 1;
-            this.cdy = this.sdy = 0;
-            finish();
-            return;
-        }
-
-        if (cx0 != sx0 || cy0 != sy0) {
-            lineTo(sx0, sy0);
-        }
-
-        drawJoin(cdx, cdy, cx0, cy0, sdx, sdy, cmx, cmy, smx, smy);
-
-        emitLineTo(sx0 + smx, sy0 + smy);
-
-        emitMoveTo(sx0 - smx, sy0 - smy);
-        emitReverse();
-
-        this.prev = CLOSE;
-        emitClose();
-    }
-
-    private void emitReverse() {
-        while(!reverse.isEmpty()) {
-            reverse.pop(out);
-        }
-    }
-
-    public void pathDone() {
-        if (prev == DRAWING_OP_TO) {
-            finish();
-        }
-
-        out.pathDone();
-        // this shouldn't matter since this object won't be used
-        // after the call to this method.
-        this.prev = CLOSE;
-    }
-
-    private void finish() {
-        if (capStyle == CAP_ROUND) {
-            drawRoundCap(cx0, cy0, cmx, cmy);
-        } else if (capStyle == CAP_SQUARE) {
-            emitLineTo(cx0 - cmy + cmx, cy0 + cmx + cmy);
-            emitLineTo(cx0 - cmy - cmx, cy0 + cmx - cmy);
-        }
-
-        emitReverse();
-
-        if (capStyle == CAP_ROUND) {
-            drawRoundCap(sx0, sy0, -smx, -smy);
-        } else if (capStyle == CAP_SQUARE) {
-            emitLineTo(sx0 + smy - smx, sy0 - smx - smy);
-            emitLineTo(sx0 + smy + smx, sy0 - smx + smy);
-        }
-
-        emitClose();
-    }
-
-    private void emitMoveTo(final float x0, final float y0) {
-        out.moveTo(x0, y0);
-    }
-
-    private void emitLineTo(final float x1, final float y1) {
-        out.lineTo(x1, y1);
-    }
-
-    private void emitLineTo(final float x1, final float y1,
-                            final boolean rev)
-    {
-        if (rev) {
-            reverse.pushLine(x1, y1);
-        } else {
-            emitLineTo(x1, y1);
-        }
-    }
-
-    private void emitQuadTo(final float x0, final float y0,
-                            final float x1, final float y1,
-                            final float x2, final float y2, final boolean rev)
-    {
-        if (rev) {
-            reverse.pushQuad(x0, y0, x1, y1);
-        } else {
-            out.quadTo(x1, y1, x2, y2);
-        }
-    }
-
-    private void emitCurveTo(final float x0, final float y0,
-                             final float x1, final float y1,
-                             final float x2, final float y2,
-                             final float x3, final float y3, final boolean rev)
-    {
-        if (rev) {
-            reverse.pushCubic(x0, y0, x1, y1, x2, y2);
-        } else {
-            out.curveTo(x1, y1, x2, y2, x3, y3);
-        }
-    }
-
-    private void emitClose() {
-        out.closePath();
-    }
-
-    private void drawJoin(float pdx, float pdy,
-                          float x0, float y0,
-                          float dx, float dy,
-                          float omx, float omy,
-                          float mx, float my)
-    {
-        if (prev != DRAWING_OP_TO) {
-            emitMoveTo(x0 + mx, y0 + my);
-            this.sdx = dx;
-            this.sdy = dy;
-            this.smx = mx;
-            this.smy = my;
-        } else {
-            boolean cw = isCW(pdx, pdy, dx, dy);
-            if (joinStyle == JOIN_MITER) {
-                drawMiter(pdx, pdy, x0, y0, dx, dy, omx, omy, mx, my, cw);
-            } else if (joinStyle == JOIN_ROUND) {
-                drawRoundJoin(x0, y0,
-                              omx, omy,
-                              mx, my, cw,
-                              ROUND_JOIN_THRESHOLD);
-            }
-            emitLineTo(x0, y0, !cw);
-        }
-        prev = DRAWING_OP_TO;
-    }
-
-    private static boolean within(final float x1, final float y1,
-                                  final float x2, final float y2,
-                                  final float ERR)
-    {
-        assert ERR > 0 : "";
-        // compare taxicab distance. ERR will always be small, so using
-        // true distance won't give much benefit
-        return (Helpers.within(x1, x2, ERR) &&  // we want to avoid calling Math.abs
-                Helpers.within(y1, y2, ERR)); // this is just as good.
-    }
-
-    private void getLineOffsets(float x1, float y1,
-                                float x2, float y2,
-                                float[] left, float[] right) {
-        computeOffset(x2 - x1, y2 - y1, lineWidth2, offset[0]);
-        left[0] = x1 + offset[0][0];
-        left[1] = y1 + offset[0][1];
-        left[2] = x2 + offset[0][0];
-        left[3] = y2 + offset[0][1];
-        right[0] = x1 - offset[0][0];
-        right[1] = y1 - offset[0][1];
-        right[2] = x2 - offset[0][0];
-        right[3] = y2 - offset[0][1];
-    }
-
-    private int computeOffsetCubic(float[] pts, final int off,
-                                   float[] leftOff, float[] rightOff)
-    {
-        // if p1=p2 or p3=p4 it means that the derivative at the endpoint
-        // vanishes, which creates problems with computeOffset. Usually
-        // this happens when this stroker object is trying to winden
-        // a curve with a cusp. What happens is that curveTo splits
-        // the input curve at the cusp, and passes it to this function.
-        // because of inaccuracies in the splitting, we consider points
-        // equal if they're very close to each other.
-        final float x1 = pts[off + 0], y1 = pts[off + 1];
-        final float x2 = pts[off + 2], y2 = pts[off + 3];
-        final float x3 = pts[off + 4], y3 = pts[off + 5];
-        final float x4 = pts[off + 6], y4 = pts[off + 7];
-
-        float dx4 = x4 - x3;
-        float dy4 = y4 - y3;
-        float dx1 = x2 - x1;
-        float dy1 = y2 - y1;
-
-        // if p1 == p2 && p3 == p4: draw line from p1->p4, unless p1 == p4,
-        // in which case ignore if p1 == p2
-        final boolean p1eqp2 = within(x1,y1,x2,y2, 6 * ulp(y2));
-        final boolean p3eqp4 = within(x3,y3,x4,y4, 6 * ulp(y4));
-        if (p1eqp2 && p3eqp4) {
-            getLineOffsets(x1, y1, x4, y4, leftOff, rightOff);
-            return 4;
-        } else if (p1eqp2) {
-            dx1 = x3 - x1;
-            dy1 = y3 - y1;
-        } else if (p3eqp4) {
-            dx4 = x4 - x2;
-            dy4 = y4 - y2;
-        }
-
-        // if p2-p1 and p4-p3 are parallel, that must mean this curve is a line
-        float dotsq = (dx1 * dx4 + dy1 * dy4);
-        dotsq = dotsq * dotsq;
-        float l1sq = dx1 * dx1 + dy1 * dy1, l4sq = dx4 * dx4 + dy4 * dy4;
-        if (Helpers.within(dotsq, l1sq * l4sq, 4 * ulp(dotsq))) {
-            getLineOffsets(x1, y1, x4, y4, leftOff, rightOff);
-            return 4;
-        }
-
-//      What we're trying to do in this function is to approximate an ideal
-//      offset curve (call it I) of the input curve B using a bezier curve Bp.
-//      The constraints I use to get the equations are:
-//
-//      1. The computed curve Bp should go through I(0) and I(1). These are
-//      x1p, y1p, x4p, y4p, which are p1p and p4p. We still need to find
-//      4 variables: the x and y components of p2p and p3p (i.e. x2p, y2p, x3p, y3p).
-//
-//      2. Bp should have slope equal in absolute value to I at the endpoints. So,
-//      (by the way, the operator || in the comments below means "aligned with".
-//      It is defined on vectors, so when we say I'(0) || Bp'(0) we mean that
-//      vectors I'(0) and Bp'(0) are aligned, which is the same as saying
-//      that the tangent lines of I and Bp at 0 are parallel. Mathematically
-//      this means (I'(t) || Bp'(t)) <==> (I'(t) = c * Bp'(t)) where c is some
-//      nonzero constant.)
-//      I'(0) || Bp'(0) and I'(1) || Bp'(1). Obviously, I'(0) || B'(0) and
-//      I'(1) || B'(1); therefore, Bp'(0) || B'(0) and Bp'(1) || B'(1).
-//      We know that Bp'(0) || (p2p-p1p) and Bp'(1) || (p4p-p3p) and the same
-//      is true for any bezier curve; therefore, we get the equations
-//          (1) p2p = c1 * (p2-p1) + p1p
-//          (2) p3p = c2 * (p4-p3) + p4p
-//      We know p1p, p4p, p2, p1, p3, and p4; therefore, this reduces the number
-//      of unknowns from 4 to 2 (i.e. just c1 and c2).
-//      To eliminate these 2 unknowns we use the following constraint:
-//
-//      3. Bp(0.5) == I(0.5). Bp(0.5)=(x,y) and I(0.5)=(xi,yi), and I should note
-//      that I(0.5) is *the only* reason for computing dxm,dym. This gives us
-//          (3) Bp(0.5) = (p1p + 3 * (p2p + p3p) + p4p)/8, which is equivalent to
-//          (4) p2p + p3p = (Bp(0.5)*8 - p1p - p4p) / 3
-//      We can substitute (1) and (2) from above into (4) and we get:
-//          (5) c1*(p2-p1) + c2*(p4-p3) = (Bp(0.5)*8 - p1p - p4p)/3 - p1p - p4p
-//      which is equivalent to
-//          (6) c1*(p2-p1) + c2*(p4-p3) = (4/3) * (Bp(0.5) * 2 - p1p - p4p)
-//
-//      The right side of this is a 2D vector, and we know I(0.5), which gives us
-//      Bp(0.5), which gives us the value of the right side.
-//      The left side is just a matrix vector multiplication in disguise. It is
-//
-//      [x2-x1, x4-x3][c1]
-//      [y2-y1, y4-y3][c2]
-//      which, is equal to
-//      [dx1, dx4][c1]
-//      [dy1, dy4][c2]
-//      At this point we are left with a simple linear system and we solve it by
-//      getting the inverse of the matrix above. Then we use [c1,c2] to compute
-//      p2p and p3p.
-
-        float x = 0.125f * (x1 + 3 * (x2 + x3) + x4);
-        float y = 0.125f * (y1 + 3 * (y2 + y3) + y4);
-        // (dxm,dym) is some tangent of B at t=0.5. This means it's equal to
-        // c*B'(0.5) for some constant c.
-        float dxm = x3 + x4 - x1 - x2, dym = y3 + y4 - y1 - y2;
-
-        // this computes the offsets at t=0, 0.5, 1, using the property that
-        // for any bezier curve the vectors p2-p1 and p4-p3 are parallel to
-        // the (dx/dt, dy/dt) vectors at the endpoints.
-        computeOffset(dx1, dy1, lineWidth2, offset[0]);
-        computeOffset(dxm, dym, lineWidth2, offset[1]);
-        computeOffset(dx4, dy4, lineWidth2, offset[2]);
-        float x1p = x1 + offset[0][0]; // start
-        float y1p = y1 + offset[0][1]; // point
-        float xi  = x + offset[1][0]; // interpolation
-        float yi  = y + offset[1][1]; // point
-        float x4p = x4 + offset[2][0]; // end
-        float y4p = y4 + offset[2][1]; // point
-
-        float invdet43 = 4f / (3f * (dx1 * dy4 - dy1 * dx4));
-
-        float two_pi_m_p1_m_p4x = 2*xi - x1p - x4p;
-        float two_pi_m_p1_m_p4y = 2*yi - y1p - y4p;
-        float c1 = invdet43 * (dy4 * two_pi_m_p1_m_p4x - dx4 * two_pi_m_p1_m_p4y);
-        float c2 = invdet43 * (dx1 * two_pi_m_p1_m_p4y - dy1 * two_pi_m_p1_m_p4x);
-
-        float x2p, y2p, x3p, y3p;
-        x2p = x1p + c1*dx1;
-        y2p = y1p + c1*dy1;
-        x3p = x4p + c2*dx4;
-        y3p = y4p + c2*dy4;
-
-        leftOff[0] = x1p; leftOff[1] = y1p;
-        leftOff[2] = x2p; leftOff[3] = y2p;
-        leftOff[4] = x3p; leftOff[5] = y3p;
-        leftOff[6] = x4p; leftOff[7] = y4p;
-
-        x1p = x1 - offset[0][0]; y1p = y1 - offset[0][1];
-        xi = xi - 2 * offset[1][0]; yi = yi - 2 * offset[1][1];
-        x4p = x4 - offset[2][0]; y4p = y4 - offset[2][1];
-
-        two_pi_m_p1_m_p4x = 2*xi - x1p - x4p;
-        two_pi_m_p1_m_p4y = 2*yi - y1p - y4p;
-        c1 = invdet43 * (dy4 * two_pi_m_p1_m_p4x - dx4 * two_pi_m_p1_m_p4y);
-        c2 = invdet43 * (dx1 * two_pi_m_p1_m_p4y - dy1 * two_pi_m_p1_m_p4x);
-
-        x2p = x1p + c1*dx1;
-        y2p = y1p + c1*dy1;
-        x3p = x4p + c2*dx4;
-        y3p = y4p + c2*dy4;
-
-        rightOff[0] = x1p; rightOff[1] = y1p;
-        rightOff[2] = x2p; rightOff[3] = y2p;
-        rightOff[4] = x3p; rightOff[5] = y3p;
-        rightOff[6] = x4p; rightOff[7] = y4p;
-        return 8;
-    }
-
-    // return the kind of curve in the right and left arrays.
-    private int computeOffsetQuad(float[] pts, final int off,
-                                  float[] leftOff, float[] rightOff)
-    {
-        final float x1 = pts[off + 0], y1 = pts[off + 1];
-        final float x2 = pts[off + 2], y2 = pts[off + 3];
-        final float x3 = pts[off + 4], y3 = pts[off + 5];
-
-        final float dx3 = x3 - x2;
-        final float dy3 = y3 - y2;
-        final float dx1 = x2 - x1;
-        final float dy1 = y2 - y1;
-
-        // this computes the offsets at t = 0, 1
-        computeOffset(dx1, dy1, lineWidth2, offset[0]);
-        computeOffset(dx3, dy3, lineWidth2, offset[1]);
-
-        leftOff[0]  = x1 + offset[0][0];  leftOff[1] = y1 + offset[0][1];
-        leftOff[4]  = x3 + offset[1][0];  leftOff[5] = y3 + offset[1][1];
-        rightOff[0] = x1 - offset[0][0]; rightOff[1] = y1 - offset[0][1];
-        rightOff[4] = x3 - offset[1][0]; rightOff[5] = y3 - offset[1][1];
-
-        float x1p = leftOff[0]; // start
-        float y1p = leftOff[1]; // point
-        float x3p = leftOff[4]; // end
-        float y3p = leftOff[5]; // point
-
-        // Corner cases:
-        // 1. If the two control vectors are parallel, we'll end up with NaN's
-        //    in leftOff (and rightOff in the body of the if below), so we'll
-        //    do getLineOffsets, which is right.
-        // 2. If the first or second two points are equal, then (dx1,dy1)==(0,0)
-        //    or (dx3,dy3)==(0,0), so (x1p, y1p)==(x1p+dx1, y1p+dy1)
-        //    or (x3p, y3p)==(x3p-dx3, y3p-dy3), which means that
-        //    computeIntersection will put NaN's in leftOff and right off, and
-        //    we will do getLineOffsets, which is right.
-        computeIntersection(x1p, y1p, x1p+dx1, y1p+dy1, x3p, y3p, x3p-dx3, y3p-dy3, leftOff, 2);
-        float cx = leftOff[2];
-        float cy = leftOff[3];
-
-        if (!(isFinite(cx) && isFinite(cy))) {
-            // maybe the right path is not degenerate.
-            x1p = rightOff[0];
-            y1p = rightOff[1];
-            x3p = rightOff[4];
-            y3p = rightOff[5];
-            computeIntersection(x1p, y1p, x1p+dx1, y1p+dy1, x3p, y3p, x3p-dx3, y3p-dy3, rightOff, 2);
-            cx = rightOff[2];
-            cy = rightOff[3];
-            if (!(isFinite(cx) && isFinite(cy))) {
-                // both are degenerate. This curve is a line.
-                getLineOffsets(x1, y1, x3, y3, leftOff, rightOff);
-                return 4;
-            }
-            // {left,right}Off[0,1,4,5] are already set to the correct values.
-            leftOff[2] = 2*x2 - cx;
-            leftOff[3] = 2*y2 - cy;
-            return 6;
-        }
-
-        // rightOff[2,3] = (x2,y2) - ((left_x2, left_y2) - (x2, y2))
-        // == 2*(x2, y2) - (left_x2, left_y2)
-        rightOff[2] = 2*x2 - cx;
-        rightOff[3] = 2*y2 - cy;
-        return 6;
-    }
-
-    private static boolean isFinite(float x) {
-        return (Float.NEGATIVE_INFINITY < x && x < Float.POSITIVE_INFINITY);
-    }
-
-    // This is where the curve to be processed is put. We give it
-    // enough room to store 2 curves: one for the current subdivision, the
-    // other for the rest of the curve.
-    private float[] middle = new float[2*8];
-    private float[] lp = new float[8];
-    private float[] rp = new float[8];
-    private static final int MAX_N_CURVES = 11;
-    private float[] subdivTs = new float[MAX_N_CURVES - 1];
-
-    // If this class is compiled with ecj, then Hotspot crashes when OSR
-    // compiling this function. See bugs 7004570 and 6675699
-    // TODO: until those are fixed, we should work around that by
-    // manually inlining this into curveTo and quadTo.
-/******************************* WORKAROUND **********************************
-    private void somethingTo(final int type) {
-        // need these so we can update the state at the end of this method
-        final float xf = middle[type-2], yf = middle[type-1];
-        float dxs = middle[2] - middle[0];
-        float dys = middle[3] - middle[1];
-        float dxf = middle[type - 2] - middle[type - 4];
-        float dyf = middle[type - 1] - middle[type - 3];
-        switch(type) {
-        case 6:
-            if ((dxs == 0f && dys == 0f) ||
-                (dxf == 0f && dyf == 0f)) {
-               dxs = dxf = middle[4] - middle[0];
-               dys = dyf = middle[5] - middle[1];
-            }
-            break;
-        case 8:
-            boolean p1eqp2 = (dxs == 0f && dys == 0f);
-            boolean p3eqp4 = (dxf == 0f && dyf == 0f);
-            if (p1eqp2) {
-                dxs = middle[4] - middle[0];
-                dys = middle[5] - middle[1];
-                if (dxs == 0f && dys == 0f) {
-                    dxs = middle[6] - middle[0];
-                    dys = middle[7] - middle[1];
-                }
-            }
-            if (p3eqp4) {
-                dxf = middle[6] - middle[2];
-                dyf = middle[7] - middle[3];
-                if (dxf == 0f && dyf == 0f) {
-                    dxf = middle[6] - middle[0];
-                    dyf = middle[7] - middle[1];
-                }
-            }
-        }
-        if (dxs == 0f && dys == 0f) {
-            // this happens iff the "curve" is just a point
-            lineTo(middle[0], middle[1]);
-            return;
-        }
-        // if these vectors are too small, normalize them, to avoid future
-        // precision problems.
-        if (Math.abs(dxs) < 0.1f && Math.abs(dys) < 0.1f) {
-            float len = (float) sqrt(dxs*dxs + dys*dys);
-            dxs /= len;
-            dys /= len;
-        }
-        if (Math.abs(dxf) < 0.1f && Math.abs(dyf) < 0.1f) {
-            float len = (float) sqrt(dxf*dxf + dyf*dyf);
-            dxf /= len;
-            dyf /= len;
-        }
-
-        computeOffset(dxs, dys, lineWidth2, offset[0]);
-        final float mx = offset[0][0];
-        final float my = offset[0][1];
-        drawJoin(cdx, cdy, cx0, cy0, dxs, dys, cmx, cmy, mx, my);
-
-        int nSplits = findSubdivPoints(middle, subdivTs, type, lineWidth2);
-
-        int kind = 0;
-        Iterator<Integer> it = Curve.breakPtsAtTs(middle, type, subdivTs, nSplits);
-        while(it.hasNext()) {
-            int curCurveOff = it.next();
-
-            switch (type) {
-            case 8:
-                kind = computeOffsetCubic(middle, curCurveOff, lp, rp);
-                break;
-            case 6:
-                kind = computeOffsetQuad(middle, curCurveOff, lp, rp);
-                break;
-            }
-            emitLineTo(lp[0], lp[1]);
-            switch(kind) {
-            case 8:
-                emitCurveTo(lp[0], lp[1], lp[2], lp[3], lp[4], lp[5], lp[6], lp[7], false);
-                emitCurveTo(rp[0], rp[1], rp[2], rp[3], rp[4], rp[5], rp[6], rp[7], true);
-                break;
-            case 6:
-                emitQuadTo(lp[0], lp[1], lp[2], lp[3], lp[4], lp[5], false);
-                emitQuadTo(rp[0], rp[1], rp[2], rp[3], rp[4], rp[5], true);
-                break;
-            case 4:
-                emitLineTo(lp[2], lp[3]);
-                emitLineTo(rp[0], rp[1], true);
-                break;
-            }
-            emitLineTo(rp[kind - 2], rp[kind - 1], true);
-        }
-
-        this.cmx = (lp[kind - 2] - rp[kind - 2]) / 2;
-        this.cmy = (lp[kind - 1] - rp[kind - 1]) / 2;
-        this.cdx = dxf;
-        this.cdy = dyf;
-        this.cx0 = xf;
-        this.cy0 = yf;
-        this.prev = DRAWING_OP_TO;
-    }
-****************************** END WORKAROUND *******************************/
-
-    // finds values of t where the curve in pts should be subdivided in order
-    // to get good offset curves a distance of w away from the middle curve.
-    // Stores the points in ts, and returns how many of them there were.
-    private static Curve c = new Curve();
-    private static int findSubdivPoints(float[] pts, float[] ts, final int type, final float w)
-    {
-        final float x12 = pts[2] - pts[0];
-        final float y12 = pts[3] - pts[1];
-        // if the curve is already parallel to either axis we gain nothing
-        // from rotating it.
-        if (y12 != 0f && x12 != 0f) {
-            // we rotate it so that the first vector in the control polygon is
-            // parallel to the x-axis. This will ensure that rotated quarter
-            // circles won't be subdivided.
-            final float hypot = (float) sqrt(x12 * x12 + y12 * y12);
-            final float cos = x12 / hypot;
-            final float sin = y12 / hypot;
-            final float x1 = cos * pts[0] + sin * pts[1];
-            final float y1 = cos * pts[1] - sin * pts[0];
-            final float x2 = cos * pts[2] + sin * pts[3];
-            final float y2 = cos * pts[3] - sin * pts[2];
-            final float x3 = cos * pts[4] + sin * pts[5];
-            final float y3 = cos * pts[5] - sin * pts[4];
-            switch(type) {
-            case 8:
-                final float x4 = cos * pts[6] + sin * pts[7];
-                final float y4 = cos * pts[7] - sin * pts[6];
-                c.set(x1, y1, x2, y2, x3, y3, x4, y4);
-                break;
-            case 6:
-                c.set(x1, y1, x2, y2, x3, y3);
-                break;
-            }
-        } else {
-            c.set(pts, type);
-        }
-
-        int ret = 0;
-        // we subdivide at values of t such that the remaining rotated
-        // curves are monotonic in x and y.
-        ret += c.dxRoots(ts, ret);
-        ret += c.dyRoots(ts, ret);
-        // subdivide at inflection points.
-        if (type == 8) {
-            // quadratic curves can't have inflection points
-            ret += c.infPoints(ts, ret);
-        }
-
-        // now we must subdivide at points where one of the offset curves will have
-        // a cusp. This happens at ts where the radius of curvature is equal to w.
-        ret += c.rootsOfROCMinusW(ts, ret, w, 0.0001f);
-
-        ret = Helpers.filterOutNotInAB(ts, 0, ret, 0.0001f, 0.9999f);
-        Helpers.isort(ts, 0, ret);
-        return ret;
-    }
-
-    @Override public void curveTo(float x1, float y1,
-                                  float x2, float y2,
-                                  float x3, float y3)
-    {
-        middle[0] = cx0; middle[1] = cy0;
-        middle[2] = x1;  middle[3] = y1;
-        middle[4] = x2;  middle[5] = y2;
-        middle[6] = x3;  middle[7] = y3;
-
-        // inlined version of somethingTo(8);
-        // See the TODO on somethingTo
-
-        // need these so we can update the state at the end of this method
-        final float xf = middle[6], yf = middle[7];
-        float dxs = middle[2] - middle[0];
-        float dys = middle[3] - middle[1];
-        float dxf = middle[6] - middle[4];
-        float dyf = middle[7] - middle[5];
-
-        boolean p1eqp2 = (dxs == 0f && dys == 0f);
-        boolean p3eqp4 = (dxf == 0f && dyf == 0f);
-        if (p1eqp2) {
-            dxs = middle[4] - middle[0];
-            dys = middle[5] - middle[1];
-            if (dxs == 0f && dys == 0f) {
-                dxs = middle[6] - middle[0];
-                dys = middle[7] - middle[1];
-            }
-        }
-        if (p3eqp4) {
-            dxf = middle[6] - middle[2];
-            dyf = middle[7] - middle[3];
-            if (dxf == 0f && dyf == 0f) {
-                dxf = middle[6] - middle[0];
-                dyf = middle[7] - middle[1];
-            }
-        }
-        if (dxs == 0f && dys == 0f) {
-            // this happens iff the "curve" is just a point
-            lineTo(middle[0], middle[1]);
-            return;
-        }
-
-        // if these vectors are too small, normalize them, to avoid future
-        // precision problems.
-        if (Math.abs(dxs) < 0.1f && Math.abs(dys) < 0.1f) {
-            float len = (float) sqrt(dxs*dxs + dys*dys);
-            dxs /= len;
-            dys /= len;
-        }
-        if (Math.abs(dxf) < 0.1f && Math.abs(dyf) < 0.1f) {
-            float len = (float) sqrt(dxf*dxf + dyf*dyf);
-            dxf /= len;
-            dyf /= len;
-        }
-
-        computeOffset(dxs, dys, lineWidth2, offset[0]);
-        final float mx = offset[0][0];
-        final float my = offset[0][1];
-        drawJoin(cdx, cdy, cx0, cy0, dxs, dys, cmx, cmy, mx, my);
-
-        int nSplits = findSubdivPoints(middle, subdivTs, 8, lineWidth2);
-
-        int kind = 0;
-        Iterator<Integer> it = Curve.breakPtsAtTs(middle, 8, subdivTs, nSplits);
-        while(it.hasNext()) {
-            int curCurveOff = it.next();
-
-            kind = computeOffsetCubic(middle, curCurveOff, lp, rp);
-            emitLineTo(lp[0], lp[1]);
-            switch(kind) {
-            case 8:
-                emitCurveTo(lp[0], lp[1], lp[2], lp[3], lp[4], lp[5], lp[6], lp[7], false);
-                emitCurveTo(rp[0], rp[1], rp[2], rp[3], rp[4], rp[5], rp[6], rp[7], true);
-                break;
-            case 4:
-                emitLineTo(lp[2], lp[3]);
-                emitLineTo(rp[0], rp[1], true);
-                break;
-            }
-            emitLineTo(rp[kind - 2], rp[kind - 1], true);
-        }
-
-        this.cmx = (lp[kind - 2] - rp[kind - 2]) / 2;
-        this.cmy = (lp[kind - 1] - rp[kind - 1]) / 2;
-        this.cdx = dxf;
-        this.cdy = dyf;
-        this.cx0 = xf;
-        this.cy0 = yf;
-        this.prev = DRAWING_OP_TO;
-    }
-
-    @Override public void quadTo(float x1, float y1, float x2, float y2) {
-        middle[0] = cx0; middle[1] = cy0;
-        middle[2] = x1;  middle[3] = y1;
-        middle[4] = x2;  middle[5] = y2;
-
-        // inlined version of somethingTo(8);
-        // See the TODO on somethingTo
-
-        // need these so we can update the state at the end of this method
-        final float xf = middle[4], yf = middle[5];
-        float dxs = middle[2] - middle[0];
-        float dys = middle[3] - middle[1];
-        float dxf = middle[4] - middle[2];
-        float dyf = middle[5] - middle[3];
-        if ((dxs == 0f && dys == 0f) || (dxf == 0f && dyf == 0f)) {
-            dxs = dxf = middle[4] - middle[0];
-            dys = dyf = middle[5] - middle[1];
-        }
-        if (dxs == 0f && dys == 0f) {
-            // this happens iff the "curve" is just a point
-            lineTo(middle[0], middle[1]);
-            return;
-        }
-        // if these vectors are too small, normalize them, to avoid future
-        // precision problems.
-        if (Math.abs(dxs) < 0.1f && Math.abs(dys) < 0.1f) {
-            float len = (float) sqrt(dxs*dxs + dys*dys);
-            dxs /= len;
-            dys /= len;
-        }
-        if (Math.abs(dxf) < 0.1f && Math.abs(dyf) < 0.1f) {
-            float len = (float) sqrt(dxf*dxf + dyf*dyf);
-            dxf /= len;
-            dyf /= len;
-        }
-
-        computeOffset(dxs, dys, lineWidth2, offset[0]);
-        final float mx = offset[0][0];
-        final float my = offset[0][1];
-        drawJoin(cdx, cdy, cx0, cy0, dxs, dys, cmx, cmy, mx, my);
-
-        int nSplits = findSubdivPoints(middle, subdivTs, 6, lineWidth2);
-
-        int kind = 0;
-        Iterator<Integer> it = Curve.breakPtsAtTs(middle, 6, subdivTs, nSplits);
-        while(it.hasNext()) {
-            int curCurveOff = it.next();
-
-            kind = computeOffsetQuad(middle, curCurveOff, lp, rp);
-            emitLineTo(lp[0], lp[1]);
-            switch(kind) {
-            case 6:
-                emitQuadTo(lp[0], lp[1], lp[2], lp[3], lp[4], lp[5], false);
-                emitQuadTo(rp[0], rp[1], rp[2], rp[3], rp[4], rp[5], true);
-                break;
-            case 4:
-                emitLineTo(lp[2], lp[3]);
-                emitLineTo(rp[0], rp[1], true);
-                break;
-            }
-            emitLineTo(rp[kind - 2], rp[kind - 1], true);
-        }
-
-        this.cmx = (lp[kind - 2] - rp[kind - 2]) / 2;
-        this.cmy = (lp[kind - 1] - rp[kind - 1]) / 2;
-        this.cdx = dxf;
-        this.cdy = dyf;
-        this.cx0 = xf;
-        this.cy0 = yf;
-        this.prev = DRAWING_OP_TO;
-    }
-
-    @Override public long getNativeConsumer() {
-        throw new InternalError("Stroker doesn't use a native consumer");
-    }
-
-    // a stack of polynomial curves where each curve shares endpoints with
-    // adjacent ones.
-    private static final class PolyStack {
-        float[] curves;
-        int end;
-        int[] curveTypes;
-        int numCurves;
-
-        private static final int INIT_SIZE = 50;
-
-        PolyStack() {
-            curves = new float[8 * INIT_SIZE];
-            curveTypes = new int[INIT_SIZE];
-            end = 0;
-            numCurves = 0;
-        }
-
-        public boolean isEmpty() {
-            return numCurves == 0;
-        }
-
-        private void ensureSpace(int n) {
-            if (end + n >= curves.length) {
-                int newSize = (end + n) * 2;
-                curves = Arrays.copyOf(curves, newSize);
-            }
-            if (numCurves >= curveTypes.length) {
-                int newSize = numCurves * 2;
-                curveTypes = Arrays.copyOf(curveTypes, newSize);
-            }
-        }
-
-        public void pushCubic(float x0, float y0,
-                              float x1, float y1,
-                              float x2, float y2)
-        {
-            ensureSpace(6);
-            curveTypes[numCurves++] = 8;
-            // assert(x0 == lastX && y0 == lastY)
-
-            // we reverse the coordinate order to make popping easier
-            curves[end++] = x2;    curves[end++] = y2;
-            curves[end++] = x1;    curves[end++] = y1;
-            curves[end++] = x0;    curves[end++] = y0;
-        }
-
-        public void pushQuad(float x0, float y0,
-                             float x1, float y1)
-        {
-            ensureSpace(4);
-            curveTypes[numCurves++] = 6;
-            // assert(x0 == lastX && y0 == lastY)
-            curves[end++] = x1;    curves[end++] = y1;
-            curves[end++] = x0;    curves[end++] = y0;
-        }
-
-        public void pushLine(float x, float y) {
-            ensureSpace(2);
-            curveTypes[numCurves++] = 4;
-            // assert(x0 == lastX && y0 == lastY)
-            curves[end++] = x;    curves[end++] = y;
-        }
-
-        @SuppressWarnings("unused")
-        public int pop(float[] pts) {
-            int ret = curveTypes[numCurves - 1];
-            numCurves--;
-            end -= (ret - 2);
-            System.arraycopy(curves, end, pts, 0, ret - 2);
-            return ret;
-        }
-
-        public void pop(PathConsumer2D io) {
-            numCurves--;
-            int type = curveTypes[numCurves];
-            end -= (type - 2);
-            switch(type) {
-            case 8:
-                io.curveTo(curves[end+0], curves[end+1],
-                           curves[end+2], curves[end+3],
-                           curves[end+4], curves[end+5]);
-                break;
-            case 6:
-                io.quadTo(curves[end+0], curves[end+1],
-                           curves[end+2], curves[end+3]);
-                 break;
-            case 4:
-                io.lineTo(curves[end], curves[end+1]);
-            }
-        }
-
-        @Override
-        public String toString() {
-            String ret = "";
-            int nc = numCurves;
-            int end = this.end;
-            while (nc > 0) {
-                nc--;
-                int type = curveTypes[numCurves];
-                end -= (type - 2);
-                switch(type) {
-                case 8:
-                    ret += "cubic: ";
-                    break;
-                case 6:
-                    ret += "quad: ";
-                    break;
-                case 4:
-                    ret += "line: ";
-                    break;
-                }
-                ret += Arrays.toString(Arrays.copyOfRange(curves, end, end+type-2)) + "\n";
-            }
-            return ret;
-        }
-    }
-}
--- a/src/java.desktop/share/classes/sun/java2d/pisces/TransformingPathConsumer2D.java	Fri Nov 24 17:19:47 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,393 +0,0 @@
-/*
- * Copyright (c) 2007, 2011, 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.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.
- */
-
-package sun.java2d.pisces;
-
-import sun.awt.geom.PathConsumer2D;
-import java.awt.geom.AffineTransform;
-
-final class TransformingPathConsumer2D {
-    public static PathConsumer2D
-        transformConsumer(PathConsumer2D out,
-                          AffineTransform at)
-    {
-        if (at == null) {
-            return out;
-        }
-        float Mxx = (float) at.getScaleX();
-        float Mxy = (float) at.getShearX();
-        float Mxt = (float) at.getTranslateX();
-        float Myx = (float) at.getShearY();
-        float Myy = (float) at.getScaleY();
-        float Myt = (float) at.getTranslateY();
-        if (Mxy == 0f && Myx == 0f) {
-            if (Mxx == 1f && Myy == 1f) {
-                if (Mxt == 0f && Myt == 0f) {
-                    return out;
-                } else {
-                    return new TranslateFilter(out, Mxt, Myt);
-                }
-            } else {
-                if (Mxt == 0f && Myt == 0f) {
-                    return new DeltaScaleFilter(out, Mxx, Myy);
-                } else {
-                    return new ScaleFilter(out, Mxx, Myy, Mxt, Myt);
-                }
-            }
-        } else if (Mxt == 0f && Myt == 0f) {
-            return new DeltaTransformFilter(out, Mxx, Mxy, Myx, Myy);
-        } else {
-            return new TransformFilter(out, Mxx, Mxy, Mxt, Myx, Myy, Myt);
-        }
-    }
-
-    public static PathConsumer2D
-        deltaTransformConsumer(PathConsumer2D out,
-                               AffineTransform at)
-    {
-        if (at == null) {
-            return out;
-        }
-        float Mxx = (float) at.getScaleX();
-        float Mxy = (float) at.getShearX();
-        float Myx = (float) at.getShearY();
-        float Myy = (float) at.getScaleY();
-        if (Mxy == 0f && Myx == 0f) {
-            if (Mxx == 1f && Myy == 1f) {
-                return out;
-            } else {
-                return new DeltaScaleFilter(out, Mxx, Myy);
-            }
-        } else {
-            return new DeltaTransformFilter(out, Mxx, Mxy, Myx, Myy);
-        }
-    }
-
-    public static PathConsumer2D
-        inverseDeltaTransformConsumer(PathConsumer2D out,
-                                      AffineTransform at)
-    {
-        if (at == null) {
-            return out;
-        }
-        float Mxx = (float) at.getScaleX();
-        float Mxy = (float) at.getShearX();
-        float Myx = (float) at.getShearY();
-        float Myy = (float) at.getScaleY();
-        if (Mxy == 0f && Myx == 0f) {
-            if (Mxx == 1f && Myy == 1f) {
-                return out;
-            } else {
-                return new DeltaScaleFilter(out, 1.0f/Mxx, 1.0f/Myy);
-            }
-        } else {
-            float det = Mxx * Myy - Mxy * Myx;
-            return new DeltaTransformFilter(out,
-                                            Myy / det,
-                                            -Mxy / det,
-                                            -Myx / det,
-                                            Mxx / det);
-        }
-    }
-
-    static final class TranslateFilter implements PathConsumer2D {
-        private final PathConsumer2D out;
-        private final float tx;
-        private final float ty;
-
-        TranslateFilter(PathConsumer2D out,
-                        float tx, float ty)
-        {
-            this.out = out;
-            this.tx = tx;
-            this.ty = ty;
-        }
-
-        public void moveTo(float x0, float y0) {
-            out.moveTo(x0 + tx, y0 + ty);
-        }
-
-        public void lineTo(float x1, float y1) {
-            out.lineTo(x1 + tx, y1 + ty);
-        }
-
-        public void quadTo(float x1, float y1,
-                           float x2, float y2)
-        {
-            out.quadTo(x1 + tx, y1 + ty,
-                       x2 + tx, y2 + ty);
-        }
-
-        public void curveTo(float x1, float y1,
-                            float x2, float y2,
-                            float x3, float y3)
-        {
-            out.curveTo(x1 + tx, y1 + ty,
-                        x2 + tx, y2 + ty,
-                        x3 + tx, y3 + ty);
-        }
-
-        public void closePath() {
-            out.closePath();
-        }
-
-        public void pathDone() {
-            out.pathDone();
-        }
-
-        public long getNativeConsumer() {
-            return 0;
-        }
-    }
-
-    static final class ScaleFilter implements PathConsumer2D {
-        private final PathConsumer2D out;
-        private final float sx;
-        private final float sy;
-        private final float tx;
-        private final float ty;
-
-        ScaleFilter(PathConsumer2D out,
-                    float sx, float sy, float tx, float ty)
-        {
-            this.out = out;
-            this.sx = sx;
-            this.sy = sy;
-            this.tx = tx;
-            this.ty = ty;
-        }
-
-        public void moveTo(float x0, float y0) {
-            out.moveTo(x0 * sx + tx, y0 * sy + ty);
-        }
-
-        public void lineTo(float x1, float y1) {
-            out.lineTo(x1 * sx + tx, y1 * sy + ty);
-        }
-
-        public void quadTo(float x1, float y1,
-                           float x2, float y2)
-        {
-            out.quadTo(x1 * sx + tx, y1 * sy + ty,
-                       x2 * sx + tx, y2 * sy + ty);
-        }
-
-        public void curveTo(float x1, float y1,
-                            float x2, float y2,
-                            float x3, float y3)
-        {
-            out.curveTo(x1 * sx + tx, y1 * sy + ty,
-                        x2 * sx + tx, y2 * sy + ty,
-                        x3 * sx + tx, y3 * sy + ty);
-        }
-
-        public void closePath() {
-            out.closePath();
-        }
-
-        public void pathDone() {
-            out.pathDone();
-        }
-
-        public long getNativeConsumer() {
-            return 0;
-        }
-    }
-
-    static final class TransformFilter implements PathConsumer2D {
-        private final PathConsumer2D out;
-        private final float Mxx;
-        private final float Mxy;
-        private final float Mxt;
-        private final float Myx;
-        private final float Myy;
-        private final float Myt;
-
-        TransformFilter(PathConsumer2D out,
-                        float Mxx, float Mxy, float Mxt,
-                        float Myx, float Myy, float Myt)
-        {
-            this.out = out;
-            this.Mxx = Mxx;
-            this.Mxy = Mxy;
-            this.Mxt = Mxt;
-            this.Myx = Myx;
-            this.Myy = Myy;
-            this.Myt = Myt;
-        }
-
-        public void moveTo(float x0, float y0) {
-            out.moveTo(x0 * Mxx + y0 * Mxy + Mxt,
-                       x0 * Myx + y0 * Myy + Myt);
-        }
-
-        public void lineTo(float x1, float y1) {
-            out.lineTo(x1 * Mxx + y1 * Mxy + Mxt,
-                       x1 * Myx + y1 * Myy + Myt);
-        }
-
-        public void quadTo(float x1, float y1,
-                           float x2, float y2)
-        {
-            out.quadTo(x1 * Mxx + y1 * Mxy + Mxt,
-                       x1 * Myx + y1 * Myy + Myt,
-                       x2 * Mxx + y2 * Mxy + Mxt,
-                       x2 * Myx + y2 * Myy + Myt);
-        }
-
-        public void curveTo(float x1, float y1,
-                            float x2, float y2,
-                            float x3, float y3)
-        {
-            out.curveTo(x1 * Mxx + y1 * Mxy + Mxt,
-                        x1 * Myx + y1 * Myy + Myt,
-                        x2 * Mxx + y2 * Mxy + Mxt,
-                        x2 * Myx + y2 * Myy + Myt,
-                        x3 * Mxx + y3 * Mxy + Mxt,
-                        x3 * Myx + y3 * Myy + Myt);
-        }
-
-        public void closePath() {
-            out.closePath();
-        }
-
-        public void pathDone() {
-            out.pathDone();
-        }
-
-        public long getNativeConsumer() {
-            return 0;
-        }
-    }
-
-    static final class DeltaScaleFilter implements PathConsumer2D {
-        private final float sx, sy;
-        private final PathConsumer2D out;
-
-        public DeltaScaleFilter(PathConsumer2D out, float Mxx, float Myy) {
-            sx = Mxx;
-            sy = Myy;
-            this.out = out;
-        }
-
-        public void moveTo(float x0, float y0) {
-            out.moveTo(x0 * sx, y0 * sy);
-        }
-
-        public void lineTo(float x1, float y1) {
-            out.lineTo(x1 * sx, y1 * sy);
-        }
-
-        public void quadTo(float x1, float y1,
-                           float x2, float y2)
-        {
-            out.quadTo(x1 * sx, y1 * sy,
-                       x2 * sx, y2 * sy);
-        }
-
-        public void curveTo(float x1, float y1,
-                            float x2, float y2,
-                            float x3, float y3)
-        {
-            out.curveTo(x1 * sx, y1 * sy,
-                        x2 * sx, y2 * sy,
-                        x3 * sx, y3 * sy);
-        }
-
-        public void closePath() {
-            out.closePath();
-        }
-
-        public void pathDone() {
-            out.pathDone();
-        }
-
-        public long getNativeConsumer() {
-            return 0;
-        }
-    }
-
-    static final class DeltaTransformFilter implements PathConsumer2D {
-        private PathConsumer2D out;
-        private final float Mxx;
-        private final float Mxy;
-        private final float Myx;
-        private final float Myy;
-
-        DeltaTransformFilter(PathConsumer2D out,
-                             float Mxx, float Mxy,
-                             float Myx, float Myy)
-        {
-            this.out = out;
-            this.Mxx = Mxx;
-            this.Mxy = Mxy;
-            this.Myx = Myx;
-            this.Myy = Myy;
-        }
-
-        public void moveTo(float x0, float y0) {
-            out.moveTo(x0 * Mxx + y0 * Mxy,
-                       x0 * Myx + y0 * Myy);
-        }
-
-        public void lineTo(float x1, float y1) {
-            out.lineTo(x1 * Mxx + y1 * Mxy,
-                       x1 * Myx + y1 * Myy);
-        }
-
-        public void quadTo(float x1, float y1,
-                           float x2, float y2)
-        {
-            out.quadTo(x1 * Mxx + y1 * Mxy,
-                       x1 * Myx + y1 * Myy,
-                       x2 * Mxx + y2 * Mxy,
-                       x2 * Myx + y2 * Myy);
-        }
-
-        public void curveTo(float x1, float y1,
-                            float x2, float y2,
-                            float x3, float y3)
-        {
-            out.curveTo(x1 * Mxx + y1 * Mxy,
-                        x1 * Myx + y1 * Myy,
-                        x2 * Mxx + y2 * Mxy,
-                        x2 * Myx + y2 * Myy,
-                        x3 * Mxx + y3 * Mxy,
-                        x3 * Myx + y3 * Myy);
-        }
-
-        public void closePath() {
-            out.closePath();
-        }
-
-        public void pathDone() {
-            out.pathDone();
-        }
-
-        public long getNativeConsumer() {
-            return 0;
-        }
-    }
-}
--- a/src/java.desktop/share/classes/sun/swing/JLightweightFrame.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/java.desktop/share/classes/sun/swing/JLightweightFrame.java	Mon Nov 27 17:04:45 2017 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2017, 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
@@ -54,6 +54,7 @@
 import sun.awt.AWTAccessor;
 import sun.awt.DisplayChangedListener;
 import sun.awt.LightweightFrame;
+import sun.awt.OverrideNativeWindowHandle;
 import sun.security.action.GetPropertyAction;
 import sun.swing.SwingUtilities2.RepaintListener;
 
@@ -526,6 +527,18 @@
         }
     }
 
+    //Called by reflection by SwingNode
+    public void overrideNativeWindowHandle(long handle, Runnable closeWindow) {
+        final Object peer = AWTAccessor.getComponentAccessor().getPeer(this);
+        if (peer instanceof OverrideNativeWindowHandle) {
+            ((OverrideNativeWindowHandle) peer).overrideWindowHandle(handle);
+        }
+        if (closeWindow != null) {
+            closeWindow.run();
+        }
+    }
+
+
     public <T extends DragGestureRecognizer> T createDragGestureRecognizer(
             Class<T> abstractRecognizerClass,
             DragSource ds, Component c, int srcActions,
--- a/src/java.desktop/unix/classes/sun/awt/X11/XLightweightFramePeer.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/java.desktop/unix/classes/sun/awt/X11/XLightweightFramePeer.java	Mon Nov 27 17:04:45 2017 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2017, 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,10 +29,11 @@
 import java.awt.dnd.DropTarget;
 
 import sun.awt.LightweightFrame;
+import sun.awt.OverrideNativeWindowHandle;
 import sun.swing.JLightweightFrame;
 import sun.swing.SwingAccessor;
 
-public class XLightweightFramePeer extends XFramePeer {
+public class XLightweightFramePeer extends XFramePeer implements OverrideNativeWindowHandle {
 
     XLightweightFramePeer(LightweightFrame target) {
         super(target);
@@ -80,4 +81,15 @@
     public void removeDropTarget(DropTarget dt) {
         getLwTarget().removeDropTarget(dt);
     }
+
+    private volatile long overriddenWindowHandle = 0L;
+
+    @Override
+    public void overrideWindowHandle(final long handle) {
+        overriddenWindowHandle = handle;
+    }
+
+    public long getOverriddenWindowHandle() {
+        return overriddenWindowHandle;
+    }
 }
--- a/src/java.desktop/unix/classes/sun/awt/X11/XWindowPeer.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/java.desktop/unix/classes/sun/awt/X11/XWindowPeer.java	Mon Nov 27 17:04:45 2017 +0000
@@ -1695,6 +1695,14 @@
             tpw = XlibUtil.getParentWindow(tpw);
             parent = XToolkit.windowToXWindow(tpw);
         }
+
+        if (parent instanceof XLightweightFramePeer) {
+            XLightweightFramePeer peer = (XLightweightFramePeer) parent;
+            long ownerWindowPtr = peer.getOverriddenWindowHandle();
+            if (ownerWindowPtr != 0) {
+                tpw = ownerWindowPtr;
+            }
+        }
         XlibWrapper.XSetTransientFor(XToolkit.getDisplay(), bpw, tpw);
         window.curRealTransientFor = parent;
     }
--- a/src/java.desktop/unix/classes/sun/java2d/jules/IdleTileCache.java	Fri Nov 24 17:19:47 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,109 +0,0 @@
-/*
- * Copyright (c) 2010, 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.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.
- */
-
-package sun.java2d.jules;
-
-import java.util.*;
-
-public class IdleTileCache {
-    static final int IDLE_TILE_SYNC_GRANULARITY = 16;
-    static final ArrayList<JulesTile> idleBuffers = new ArrayList<JulesTile>();
-
-    ArrayList<JulesTile> idleTileWorkerCacheList = new ArrayList<JulesTile>();
-    ArrayList<JulesTile> idleTileConsumerCacheList =
-              new ArrayList<JulesTile>(IDLE_TILE_SYNC_GRANULARITY);
-
-    /**
-     * Return a cached Tile, if possible from cache.
-     * Allowed caller: Rasterizer/Producer-Thread
-     *
-     * @param: maxCache - Specify the maximum amount of tiles needed
-     */
-    public JulesTile getIdleTileWorker(int maxCache) {
-        /* Try to fetch idle tiles from the global cache list */
-        if (idleTileWorkerCacheList.size() == 0) {
-            idleTileWorkerCacheList.ensureCapacity(maxCache);
-
-            synchronized (idleBuffers) {
-                for (int i = 0; i < maxCache && idleBuffers.size() > 0; i++) {
-                    idleTileWorkerCacheList.add(
-                            idleBuffers.remove(idleBuffers.size() - 1));
-                }
-            }
-        }
-
-        if (idleTileWorkerCacheList.size() > 0) {
-            return idleTileWorkerCacheList.remove(idleTileWorkerCacheList.size() - 1);
-        }
-
-        return new JulesTile();
-    }
-
-    /**
-     * Release tile and allow it to be re-used by another thread. Allowed
-     *  Allowed caller: MaskBlit/Consumer-Thread
-     */
-    public void releaseTile(JulesTile tile) {
-        if (tile != null && tile.hasBuffer()) {
-            idleTileConsumerCacheList.add(tile);
-
-            if (idleTileConsumerCacheList.size() > IDLE_TILE_SYNC_GRANULARITY) {
-                synchronized (idleBuffers) {
-                    idleBuffers.addAll(idleTileConsumerCacheList);
-                }
-                idleTileConsumerCacheList.clear();
-            }
-        }
-    }
-
-    /**
-     * Releases thread-local tiles cached for use by the rasterizing thread.
-     * Allowed caller: Rasterizer/Producer-Thread
-     */
-    public void disposeRasterizerResources() {
-        releaseTiles(idleTileWorkerCacheList);
-    }
-
-    /**
-     * Releases thread-local tiles cached for performance reasons. Allowed
-     * Allowed caller: MaskBlit/Consumer-Thread
-     */
-    public void disposeConsumerResources() {
-        releaseTiles(idleTileConsumerCacheList);
-    }
-
-    /**
-     * Release a list of tiles and allow it to be re-used by another thread.
-     * Thread safe.
-     */
-    public void releaseTiles(List<JulesTile> tileList) {
-        if (tileList.size() > 0) {
-            synchronized (idleBuffers) {
-                idleBuffers.addAll(tileList);
-            }
-            tileList.clear();
-        }
-    }
-}
--- a/src/java.desktop/unix/classes/sun/java2d/jules/JulesAATileGenerator.java	Fri Nov 24 17:19:47 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,328 +0,0 @@
-/*
- * Copyright (c) 2010, 2013, 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.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.
- */
-
-package sun.java2d.jules;
-
-import java.awt.*;
-import java.awt.geom.*;
-import java.util.concurrent.*;
-import sun.java2d.pipe.*;
-import sun.java2d.xr.*;
-
-public class JulesAATileGenerator implements AATileGenerator {
-    /* Threading stuff */
-    static final ExecutorService rasterThreadPool =
-                                          Executors.newCachedThreadPool();
-    static final int CPU_CNT = Runtime.getRuntime().availableProcessors();
-
-    static final boolean ENABLE_THREADING = false;
-    static final int THREAD_MIN = 16;
-    static final int THREAD_BEGIN = 16;
-
-    IdleTileCache tileCache;
-    TileWorker worker;
-    boolean threaded = false;
-    int rasterTileCnt;
-
-    /* Tiling */
-    static final int TILE_SIZE = 32;
-    static final int TILE_SIZE_FP = 32 << 16;
-    int left, right, top, bottom, width, height;
-    int leftFP, topFP;
-    int tileCnt, tilesX, tilesY;
-    int currTilePos = 0;
-    TrapezoidList traps;
-    TileTrapContainer[] tiledTrapArray;
-    JulesTile mainTile;
-
-    public JulesAATileGenerator(Shape s, AffineTransform at, Region clip,
-                                BasicStroke bs, boolean thin,
-                                boolean normalize, int[] bbox) {
-        JulesPathBuf buf = new JulesPathBuf();
-
-        if (bs == null) {
-            traps = buf.tesselateFill(s, at, clip);
-        } else {
-            traps = buf.tesselateStroke(s, bs, thin, false, true, at, clip);
-        }
-
-        calculateArea(bbox);
-        bucketSortTraps();
-        calculateTypicalAlpha();
-
-        threaded = ENABLE_THREADING &&
-                   rasterTileCnt >= THREAD_MIN && CPU_CNT >= 2;
-        if (threaded) {
-            tileCache = new IdleTileCache();
-            worker = new TileWorker(this, THREAD_BEGIN, tileCache);
-            rasterThreadPool.execute(worker);
-        }
-
-        mainTile = new JulesTile();
-    }
-
-    private static native long
-        rasterizeTrapezoidsNative(long pixmanImagePtr, int[] traps,
-                                  int[] trapPos, int trapCnt,
-                                  byte[] buffer, int xOff, int yOff);
-
-    private static native void freePixmanImgPtr(long pixmanImgPtr);
-
-    private void calculateArea(int[] bbox) {
-        tilesX = 0;
-        tilesY = 0;
-        tileCnt = 0;
-        bbox[0] = 0;
-        bbox[1] = 0;
-        bbox[2] = 0;
-        bbox[3] = 0;
-
-        if (traps.getSize() > 0) {
-            left = traps.getLeft();
-            right = traps.getRight();
-            top = traps.getTop();
-            bottom = traps.getBottom();
-            leftFP = left << 16;
-            topFP = top << 16;
-
-            bbox[0] = left;
-            bbox[1] = top;
-            bbox[2] = right;
-            bbox[3] = bottom;
-
-            width = right - left;
-            height = bottom - top;
-
-            if (width > 0 && height > 0) {
-                tilesX = (int) Math.ceil(((double) width) / TILE_SIZE);
-                tilesY = (int) Math.ceil(((double) height) / TILE_SIZE);
-                tileCnt = tilesY * tilesX;
-                tiledTrapArray = new TileTrapContainer[tileCnt];
-            } else {
-                // If there is no area touched by the traps, don't
-                // render them.
-                traps.setSize(0);
-            }
-        }
-    }
-
-
-    private void bucketSortTraps() {
-
-        for (int i = 0; i < traps.getSize(); i++) {
-            int top = traps.getTop(i) - XRUtils.XDoubleToFixed(this.top);
-            int bottom = traps.getBottom(i) - topFP;
-            int p1xLeft = traps.getP1XLeft(i) - leftFP;
-            int p2xLeft = traps.getP2XLeft(i) - leftFP;
-            int p1xRight = traps.getP1XRight(i) - leftFP;
-            int p2xRight = traps.getP2XRight(i) - leftFP;
-
-            int minLeft = Math.min(p1xLeft, p2xLeft);
-            int maxRight = Math.max(p1xRight, p2xRight);
-
-            maxRight = maxRight > 0 ? maxRight - 1 : maxRight;
-            bottom = bottom > 0 ? bottom - 1 : bottom;
-
-            int startTileY = top / TILE_SIZE_FP;
-            int endTileY = bottom / TILE_SIZE_FP;
-            int startTileX = minLeft / TILE_SIZE_FP;
-            int endTileX = maxRight / TILE_SIZE_FP;
-
-            for (int n = startTileY; n <= endTileY; n++) {
-
-                for (int m = startTileX; m <= endTileX; m++) {
-                    int trapArrayPos = n * tilesX + m;
-                    TileTrapContainer trapTileList = tiledTrapArray[trapArrayPos];
-                    if (trapTileList == null) {
-                        trapTileList = new TileTrapContainer(new GrowableIntArray(1, 16));
-                        tiledTrapArray[trapArrayPos] = trapTileList;
-                    }
-
-                    trapTileList.getTraps().addInt(i);
-                }
-            }
-        }
-    }
-
-    public void getAlpha(byte[] tileBuffer, int offset, int rowstride) {
-        JulesTile tile = null;
-
-        if (threaded) {
-            tile = worker.getPreRasterizedTile(currTilePos);
-        }
-
-        if (tile != null) {
-            System.arraycopy(tile.getImgBuffer(), 0,
-                             tileBuffer, 0, tileBuffer.length);
-            tileCache.releaseTile(tile);
-        } else {
-            mainTile.setImgBuffer(tileBuffer);
-            rasterizeTile(currTilePos, mainTile);
-        }
-
-        nextTile();
-    }
-
-    public void calculateTypicalAlpha() {
-        rasterTileCnt = 0;
-
-        for (int index = 0; index < tileCnt; index++) {
-
-            TileTrapContainer trapCont = tiledTrapArray[index];
-            if (trapCont != null) {
-                GrowableIntArray trapList = trapCont.getTraps();
-
-                int tileAlpha = 127;
-                if (trapList == null || trapList.getSize() == 0) {
-                    tileAlpha = 0;
-                } else if (doTrapsCoverTile(trapList, index)) {
-                    tileAlpha = 0xff;
-                }
-
-                if (tileAlpha == 127 || tileAlpha == 0xff) {
-                    rasterTileCnt++;
-                }
-
-                trapCont.setTileAlpha(tileAlpha);
-            }
-        }
-    }
-
-    /*
-     * Optimization for large fills. Foutunatly cairo does generate an y-sorted
-     * list of trapezoids. This makes it quite simple to check whether a tile is
-     * fully covered by traps by: - Checking whether the tile is fully covered by
-     * traps vertically (trap 2 starts where trap 1 ended) - Checking whether all
-     * traps cover the tile horizontally This also works, when a single tile
-     * coveres the whole tile.
-     */
-    protected boolean doTrapsCoverTile(GrowableIntArray trapList, int tileIndex) {
-
-        // Don't bother optimizing tiles with lots of traps, usually it won't
-        // succeed anyway.
-        if (trapList.getSize() > TILE_SIZE) {
-            return false;
-        }
-
-        int tileStartX = getXPos(tileIndex) * TILE_SIZE_FP + leftFP;
-        int tileStartY = getYPos(tileIndex) * TILE_SIZE_FP + topFP;
-        int tileEndX = tileStartX + TILE_SIZE_FP;
-        int tileEndY = tileStartY + TILE_SIZE_FP;
-
-        // Check whether first tile covers the beginning of the tile vertically
-        int firstTop = traps.getTop(trapList.getInt(0));
-        int firstBottom = traps.getBottom(trapList.getInt(0));
-        if (firstTop > tileStartY || firstBottom < tileStartY) {
-            return false;
-        }
-
-        // Initialize lastBottom with top, in order to pass the checks for the
-        // first iteration
-        int lastBottom = firstTop;
-
-        for (int i = 0; i < trapList.getSize(); i++) {
-            int trapPos = trapList.getInt(i);
-            if (traps.getP1XLeft(trapPos) > tileStartX ||
-                traps.getP2XLeft(trapPos) > tileStartX ||
-                traps.getP1XRight(trapPos) < tileEndX  ||
-                traps.getP2XRight(trapPos) < tileEndX  ||
-                 traps.getTop(trapPos) != lastBottom)
-            {
-                return false;
-            }
-            lastBottom = traps.getBottom(trapPos);
-        }
-
-        // When the last trap covered the tileEnd vertically, the tile is fully
-        // covered
-        return lastBottom >= tileEndY;
-    }
-
-    public int getTypicalAlpha() {
-        if (tiledTrapArray[currTilePos] == null) {
-            return 0;
-        } else {
-            return tiledTrapArray[currTilePos].getTileAlpha();
-        }
-    }
-
-    public void dispose() {
-        freePixmanImgPtr(mainTile.getPixmanImgPtr());
-
-        if (threaded) {
-            tileCache.disposeConsumerResources();
-            worker.disposeConsumerResources();
-        }
-    }
-
-    protected JulesTile rasterizeTile(int tileIndex, JulesTile tile) {
-        int tileOffsetX = left + getXPos(tileIndex) * TILE_SIZE;
-        int tileOffsetY = top + getYPos(tileIndex) * TILE_SIZE;
-        TileTrapContainer trapCont = tiledTrapArray[tileIndex];
-        GrowableIntArray trapList = trapCont.getTraps();
-
-        if (trapCont.getTileAlpha() == 127) {
-            long pixmanImgPtr =
-                 rasterizeTrapezoidsNative(tile.getPixmanImgPtr(),
-                                           traps.getTrapArray(),
-                                           trapList.getArray(),
-                                           trapList.getSize(),
-                                           tile.getImgBuffer(),
-                                           tileOffsetX, tileOffsetY);
-            tile.setPixmanImgPtr(pixmanImgPtr);
-        }
-
-        tile.setTilePos(tileIndex);
-        return tile;
-    }
-
-    protected int getXPos(int arrayPos) {
-        return arrayPos % tilesX;
-    }
-
-    protected int getYPos(int arrayPos) {
-        return arrayPos / tilesX;
-    }
-
-    public void nextTile() {
-        currTilePos++;
-    }
-
-    public int getTileHeight() {
-        return TILE_SIZE;
-    }
-
-    public int getTileWidth() {
-        return TILE_SIZE;
-    }
-
-    public int getTileCount() {
-        return tileCnt;
-    }
-
-    public TileTrapContainer getTrapContainer(int index) {
-        return tiledTrapArray[index];
-    }
-}
--- a/src/java.desktop/unix/classes/sun/java2d/jules/JulesPathBuf.java	Fri Nov 24 17:19:47 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,271 +0,0 @@
-/*
- * Copyright (c) 2010, 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.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.
- */
-
-package sun.java2d.jules;
-
-import java.awt.*;
-import java.awt.geom.*;
-import sun.awt.X11GraphicsEnvironment;
-import sun.java2d.pipe.*;
-import sun.java2d.xr.*;
-
-public class JulesPathBuf {
-    static final double[] emptyDash = new double[0];
-
-    private static final byte CAIRO_PATH_OP_MOVE_TO = 0;
-    private static final byte CAIRO_PATH_OP_LINE_TO = 1;
-    private static final byte CAIRO_PATH_OP_CURVE_TO = 2;
-    private static final byte CAIRO_PATH_OP_CLOSE_PATH = 3;
-
-    private static final int  CAIRO_FILL_RULE_WINDING = 0;
-    private static final int CAIRO_FILL_RULE_EVEN_ODD = 1;
-
-    GrowablePointArray points = new GrowablePointArray(128);
-    GrowableByteArray ops = new GrowableByteArray(1, 128);
-    int[] xTrapArray = new int[512];
-
-    private static final boolean isCairoAvailable;
-
-    static {
-        isCairoAvailable =
-           java.security.AccessController.doPrivileged(
-                          new java.security.PrivilegedAction<Boolean>() {
-            public Boolean run() {
-                boolean loadSuccess = false;
-                if (X11GraphicsEnvironment.isXRenderAvailable()) {
-                    try {
-                        System.loadLibrary("jules");
-                        loadSuccess = true;
-                        if (X11GraphicsEnvironment.isXRenderVerbose()) {
-                            System.out.println(
-                                       "Xrender: INFO: Jules library loaded");
-                        }
-                    } catch (UnsatisfiedLinkError ex) {
-                        loadSuccess = false;
-                        if (X11GraphicsEnvironment.isXRenderVerbose()) {
-                            System.out.println(
-                                "Xrender: INFO: Jules library not installed.");
-                        }
-                    }
-                }
-                return Boolean.valueOf(loadSuccess);
-            }
-        });
-    }
-
-    public static boolean isCairoAvailable() {
-        return isCairoAvailable;
-    }
-
-    public TrapezoidList tesselateFill(Shape s, AffineTransform at, Region clip) {
-        int windingRule = convertPathData(s, at);
-        xTrapArray[0] = 0;
-
-        xTrapArray = tesselateFillNative(points.getArray(), ops.getArray(),
-                                         points.getSize(), ops.getSize(),
-                                         xTrapArray, xTrapArray.length,
-                                         getCairoWindingRule(windingRule),
-                                         clip.getLoX(), clip.getLoY(),
-                                         clip.getHiX(), clip.getHiY());
-
-        return new TrapezoidList(xTrapArray);
-    }
-
-    public TrapezoidList tesselateStroke(Shape s, BasicStroke bs, boolean thin,
-                                         boolean adjust, boolean antialias,
-                                         AffineTransform at, Region clip) {
-
-        float lw;
-        if (thin) {
-            if (antialias) {
-                lw = 0.5f;
-            } else {
-                lw = 1.0f;
-            }
-        } else {
-            lw = bs.getLineWidth();
-        }
-
-        convertPathData(s, at);
-
-        double[] dashArray = floatToDoubleArray(bs.getDashArray());
-        xTrapArray[0] = 0;
-
-        xTrapArray =
-             tesselateStrokeNative(points.getArray(), ops.getArray(),
-                                   points.getSize(), ops.getSize(),
-                                   xTrapArray, xTrapArray.length, lw,
-                                   bs.getEndCap(), bs.getLineJoin(),
-                                   bs.getMiterLimit(), dashArray,
-                                   dashArray.length, bs.getDashPhase(),
-                                   1, 0, 0, 0, 1, 0,
-                                   clip.getLoX(), clip.getLoY(),
-                                   clip.getHiX(), clip.getHiY());
-
-        return new TrapezoidList(xTrapArray);
-    }
-
-    protected double[] floatToDoubleArray(float[] dashArrayFloat) {
-        double[] dashArrayDouble = emptyDash;
-        if (dashArrayFloat != null) {
-            dashArrayDouble = new double[dashArrayFloat.length];
-
-            for (int i = 0; i < dashArrayFloat.length; i++) {
-                dashArrayDouble[i] = dashArrayFloat[i];
-            }
-        }
-
-        return dashArrayDouble;
-    }
-
-    protected int convertPathData(Shape s, AffineTransform at) {
-        PathIterator pi = s.getPathIterator(at);
-
-        double[] coords = new double[6];
-        double currX = 0;
-        double currY = 0;
-
-        while (!pi.isDone()) {
-            int curOp = pi.currentSegment(coords);
-
-            int pointIndex;
-            switch (curOp) {
-
-            case PathIterator.SEG_MOVETO:
-                ops.addByte(CAIRO_PATH_OP_MOVE_TO);
-                pointIndex = points.getNextIndex();
-                points.setX(pointIndex, DoubleToCairoFixed(coords[0]));
-                points.setY(pointIndex, DoubleToCairoFixed(coords[1]));
-                currX = coords[0];
-                currY = coords[1];
-                break;
-
-            case PathIterator.SEG_LINETO:
-                ops.addByte(CAIRO_PATH_OP_LINE_TO);
-                pointIndex = points.getNextIndex();
-                points.setX(pointIndex, DoubleToCairoFixed(coords[0]));
-                points.setY(pointIndex, DoubleToCairoFixed(coords[1]));
-                currX = coords[0];
-                currY = coords[1];
-                break;
-
-                /**
-                 *    q0 = p0
-                 *    q1 = (p0+2*p1)/3
-                 *    q2 = (p2+2*p1)/3
-                 *    q3 = p2
-                 */
-            case PathIterator.SEG_QUADTO:
-                double x1 = coords[0];
-                double y1 = coords[1];
-                double x2, y2;
-                double x3 = coords[2];
-                double y3 = coords[3];
-
-                x2 = x1 + (x3 - x1) / 3;
-                y2 = y1 + (y3 - y1) / 3;
-                x1 = currX + 2 * (x1 - currX) / 3;
-                y1 =currY + 2 * (y1 - currY) / 3;
-
-                ops.addByte(CAIRO_PATH_OP_CURVE_TO);
-                pointIndex = points.getNextIndex();
-                points.setX(pointIndex, DoubleToCairoFixed(x1));
-                points.setY(pointIndex, DoubleToCairoFixed(y1));
-                pointIndex = points.getNextIndex();
-                points.setX(pointIndex, DoubleToCairoFixed(x2));
-                points.setY(pointIndex, DoubleToCairoFixed(y2));
-                pointIndex = points.getNextIndex();
-                points.setX(pointIndex, DoubleToCairoFixed(x3));
-                points.setY(pointIndex, DoubleToCairoFixed(y3));
-                currX = x3;
-                currY = y3;
-                break;
-
-            case PathIterator.SEG_CUBICTO:
-                ops.addByte(CAIRO_PATH_OP_CURVE_TO);
-                pointIndex = points.getNextIndex();
-                points.setX(pointIndex, DoubleToCairoFixed(coords[0]));
-                points.setY(pointIndex, DoubleToCairoFixed(coords[1]));
-                pointIndex = points.getNextIndex();
-                points.setX(pointIndex, DoubleToCairoFixed(coords[2]));
-                points.setY(pointIndex, DoubleToCairoFixed(coords[3]));
-                pointIndex = points.getNextIndex();
-                points.setX(pointIndex, DoubleToCairoFixed(coords[4]));
-                points.setY(pointIndex, DoubleToCairoFixed(coords[5]));
-                currX = coords[4];
-                currY = coords[5];
-                break;
-
-            case PathIterator.SEG_CLOSE:
-                ops.addByte(CAIRO_PATH_OP_CLOSE_PATH);
-                break;
-            }
-
-            pi.next();
-        }
-
-        return pi.getWindingRule();
-    }
-
-    private static native int[]
-         tesselateStrokeNative(int[] pointArray, byte[] ops,
-                               int pointCnt, int opCnt,
-                               int[] xTrapArray, int xTrapArrayLength,
-                               double lineWidth, int lineCap, int lineJoin,
-                               double miterLimit, double[] dashArray,
-                               int dashCnt, double offset,
-                               double m00, double m01, double m02,
-                               double m10, double m11, double m12,
-                               int clipLowX, int clipLowY,
-                               int clipWidth, int clipHeight);
-
-    private static native int[]
-        tesselateFillNative(int[] pointArray, byte[] ops, int pointCnt,
-                            int opCnt, int[] xTrapArray, int xTrapArrayLength,
-                            int windingRule, int clipLowX, int clipLowY,                                    int clipWidth, int clipHeight);
-
-    public void clear() {
-        points.clear();
-        ops.clear();
-        xTrapArray[0] = 0;
-    }
-
-    private static int DoubleToCairoFixed(double dbl) {
-        return (int) (dbl * 256);
-    }
-
-    private static int getCairoWindingRule(int j2dWindingRule) {
-        switch(j2dWindingRule) {
-        case PathIterator.WIND_EVEN_ODD:
-            return CAIRO_FILL_RULE_EVEN_ODD;
-
-        case PathIterator.WIND_NON_ZERO:
-            return CAIRO_FILL_RULE_WINDING;
-
-            default:
-                throw new IllegalArgumentException("Illegal Java2D winding rule specified");
-        }
-    }
-}
--- a/src/java.desktop/unix/classes/sun/java2d/jules/JulesRenderingEngine.java	Fri Nov 24 17:19:47 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,54 +0,0 @@
-/*
- * Copyright (c) 2010, 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.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.
- */
-
-package sun.java2d.jules;
-
-import java.awt.*;
-
-import java.awt.geom.*;
-import sun.java2d.pipe.*;
-import sun.java2d.pisces.*;
-
-public class JulesRenderingEngine extends PiscesRenderingEngine {
-
-    @Override
-    public AATileGenerator
-         getAATileGenerator(Shape s, AffineTransform at, Region clip,
-                            BasicStroke bs, boolean thin,
-                            boolean normalize, int[] bbox) {
-
-        if (JulesPathBuf.isCairoAvailable()) {
-            return new JulesAATileGenerator(s, at, clip, bs, thin,
-                                            normalize, bbox);
-        } else {
-            return super.getAATileGenerator(s, at, clip, bs, thin,
-                                            normalize, bbox);
-        }
-    }
-
-    public float getMinimumAAPenSize() {
-        return 0.5f;
-    }
-}
--- a/src/java.desktop/unix/classes/sun/java2d/jules/JulesShapePipe.java	Fri Nov 24 17:19:47 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,102 +0,0 @@
-/*
- * Copyright (c) 2010, 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.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.
- */
-
-package sun.java2d.jules;
-
-import java.awt.*;
-import sun.awt.*;
-import sun.java2d.*;
-import sun.java2d.pipe.*;
-import sun.java2d.xr.*;
-
-public class JulesShapePipe implements ShapeDrawPipe {
-
-    XRCompositeManager compMan;
-    JulesPathBuf buf = new JulesPathBuf();
-
-    public JulesShapePipe(XRCompositeManager compMan) {
-        this.compMan = compMan;
-    }
-
-    /**
-     * Common validate method, used by all XRRender functions to validate the
-     * destination context.
-     */
-    private final void validateSurface(SunGraphics2D sg2d) {
-        XRSurfaceData xrsd = (XRSurfaceData) sg2d.surfaceData;
-        xrsd.validateAsDestination(sg2d, sg2d.getCompClip());
-        xrsd.maskBuffer.validateCompositeState(sg2d.composite, sg2d.transform,
-                                               sg2d.paint, sg2d);
-    }
-
-    public void draw(SunGraphics2D sg2d, Shape s) {
-        try {
-            SunToolkit.awtLock();
-            validateSurface(sg2d);
-            XRSurfaceData xrsd = (XRSurfaceData) sg2d.surfaceData;
-
-            BasicStroke bs;
-
-            if (sg2d.stroke instanceof BasicStroke) {
-                bs = (BasicStroke) sg2d.stroke;
-            } else { //TODO: What happens in the case of a !BasicStroke??
-                s = sg2d.stroke.createStrokedShape(s);
-                bs = null;
-            }
-
-            boolean adjust =
-                (bs != null && sg2d.strokeHint != SunHints.INTVAL_STROKE_PURE);
-            boolean thin = (sg2d.strokeState <= SunGraphics2D.STROKE_THINDASHED);
-
-            TrapezoidList traps =
-                 buf.tesselateStroke(s, bs, thin, adjust, true,
-                                     sg2d.transform, sg2d.getCompClip());
-            compMan.XRCompositeTraps(xrsd.picture,
-                                     sg2d.transX, sg2d.transY, traps);
-
-            buf.clear();
-
-        } finally {
-            SunToolkit.awtUnlock();
-        }
-    }
-
-    public void fill(SunGraphics2D sg2d, Shape s) {
-        try {
-            SunToolkit.awtLock();
-            validateSurface(sg2d);
-
-            XRSurfaceData xrsd = (XRSurfaceData) sg2d.surfaceData;
-
-            TrapezoidList traps = buf.tesselateFill(s, sg2d.transform,
-                                                    sg2d.getCompClip());
-            compMan.XRCompositeTraps(xrsd.picture, 0, 0, traps);
-
-            buf.clear();
-        } finally {
-            SunToolkit.awtUnlock();
-        }
-    }
-}
--- a/src/java.desktop/unix/classes/sun/java2d/jules/JulesTile.java	Fri Nov 24 17:19:47 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,67 +0,0 @@
-/*
- * Copyright (c) 2010, 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.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.
- */
-
-package sun.java2d.jules;
-
-public class JulesTile {
-    byte[] imgBuffer;
-    long pixmanImgPtr = 0;
-    int tilePos;
-
-    public JulesTile() {
-    }
-
-    public byte[] getImgBuffer() {
-        if(imgBuffer == null) {
-            imgBuffer = new byte[1024];
-        }
-
-        return imgBuffer;
-    }
-
-    public long getPixmanImgPtr() {
-        return pixmanImgPtr;
-    }
-
-    public void setPixmanImgPtr(long pixmanImgPtr) {
-        this.pixmanImgPtr = pixmanImgPtr;
-    }
-
-    public boolean hasBuffer() {
-        return imgBuffer != null;
-    }
-
-    public int getTilePos() {
-        return tilePos;
-    }
-
-    public void setTilePos(int tilePos) {
-        this.tilePos = tilePos;
-    }
-
-    public void setImgBuffer(byte[] imgBuffer){
-        this.imgBuffer = imgBuffer;
-    }
-}
--- a/src/java.desktop/unix/classes/sun/java2d/jules/TileTrapContainer.java	Fri Nov 24 17:19:47 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,49 +0,0 @@
-/*
- * Copyright (c) 2010, 2012, 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.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.
- */
-
-package sun.java2d.jules;
-
-import sun.java2d.xr.GrowableIntArray;
-
-class TileTrapContainer {
-    int tileAlpha;
-    GrowableIntArray traps;
-
-    public TileTrapContainer(GrowableIntArray traps) {
-        this.traps = traps;
-    }
-
-    public void setTileAlpha(int tileAlpha) {
-        this.tileAlpha = tileAlpha;
-    }
-
-    public int getTileAlpha() {
-        return tileAlpha;
-    }
-
-    public GrowableIntArray getTraps() {
-        return traps;
-    }
-}
--- a/src/java.desktop/unix/classes/sun/java2d/jules/TileWorker.java	Fri Nov 24 17:19:47 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,146 +0,0 @@
-/*
- * Copyright (c) 2010, 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.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.
- */
-
-package sun.java2d.jules;
-
-import java.util.*;
-
-public class TileWorker implements Runnable {
-    static final int RASTERIZED_TILE_SYNC_GRANULARITY = 8;
-    final ArrayList<JulesTile> rasterizedTileConsumerCache =
-         new ArrayList<JulesTile>();
-    final LinkedList<JulesTile> rasterizedBuffers = new LinkedList<JulesTile>();
-
-    IdleTileCache tileCache;
-    JulesAATileGenerator tileGenerator;
-    int workerStartIndex;
-    volatile int consumerPos = 0;
-
-    /* Threading statistics */
-    int mainThreadCnt = 0;
-    int workerCnt = 0;
-    int doubled = 0;
-
-    public TileWorker(JulesAATileGenerator tileGenerator, int workerStartIndex, IdleTileCache tileCache) {
-        this.tileGenerator = tileGenerator;
-        this.workerStartIndex = workerStartIndex;
-        this.tileCache = tileCache;
-    }
-
-    public void run() {
-        ArrayList<JulesTile> tiles = new ArrayList<JulesTile>(16);
-
-        for (int i = workerStartIndex; i < tileGenerator.getTileCount(); i++) {
-            TileTrapContainer tile = tileGenerator.getTrapContainer(i);
-
-            if (tile != null && tile.getTileAlpha() == 127) {
-                JulesTile rasterizedTile =
-                      tileGenerator.rasterizeTile(i,
-                           tileCache.getIdleTileWorker(
-                               tileGenerator.getTileCount() - i - 1));
-                tiles.add(rasterizedTile);
-
-                if (tiles.size() > RASTERIZED_TILE_SYNC_GRANULARITY) {
-                    addRasterizedTiles(tiles);
-                    tiles.clear();
-                }
-            }
-
-            i = Math.max(i, consumerPos + RASTERIZED_TILE_SYNC_GRANULARITY / 2);
-        }
-        addRasterizedTiles(tiles);
-
-        tileCache.disposeRasterizerResources();
-    }
-
-    /**
-     * Returns a rasterized tile for the specified tilePos,
-     * or null if it isn't available.
-     * Allowed caller: MaskBlit/Consumer-Thread
-     */
-    public JulesTile getPreRasterizedTile(int tilePos) {
-        JulesTile tile = null;
-
-        if (rasterizedTileConsumerCache.size() == 0 &&
-            tilePos >= workerStartIndex)
-        {
-            synchronized (rasterizedBuffers) {
-                rasterizedTileConsumerCache.addAll(rasterizedBuffers);
-                rasterizedBuffers.clear();
-            }
-        }
-
-        while (tile == null && rasterizedTileConsumerCache.size() > 0) {
-            JulesTile t = rasterizedTileConsumerCache.get(0);
-
-            if (t.getTilePos() > tilePos) {
-                break;
-            }
-
-            if (t.getTilePos() < tilePos) {
-                tileCache.releaseTile(t);
-                doubled++;
-            }
-
-            if (t.getTilePos() <= tilePos) {
-                rasterizedTileConsumerCache.remove(0);
-            }
-
-            if (t.getTilePos() == tilePos) {
-                tile = t;
-            }
-        }
-
-        if (tile == null) {
-            mainThreadCnt++;
-
-            // If there are no tiles left, tell the producer the current
-            // position. This avoids producing tiles twice.
-            consumerPos = tilePos;
-        } else {
-            workerCnt++;
-        }
-
-        return tile;
-    }
-
-    private void addRasterizedTiles(ArrayList<JulesTile> tiles) {
-        synchronized (rasterizedBuffers) {
-            rasterizedBuffers.addAll(tiles);
-        }
-    }
-
-    /**
-     * Releases cached tiles.
-     * Allowed caller: MaskBlit/Consumer-Thread
-     */
-    public void disposeConsumerResources() {
-        synchronized (rasterizedBuffers) {
-            tileCache.releaseTiles(rasterizedBuffers);
-        }
-
-        tileCache.releaseTiles(rasterizedTileConsumerCache);
-    }
-}
--- a/src/java.desktop/unix/classes/sun/java2d/jules/TrapezoidList.java	Fri Nov 24 17:19:47 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,110 +0,0 @@
-/*
- * Copyright (c) 2010, 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.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.
- */
-
-package sun.java2d.jules;
-
-public class TrapezoidList {
-    public static final int TRAP_START_INDEX = 5;
-    public static final int TRAP_SIZE = 10;
-
-    int[] trapArray;
-
-    public TrapezoidList(int[] trapArray) {
-        this.trapArray = trapArray;
-    }
-
-    public final int[] getTrapArray() {
-        return trapArray;
-    }
-
-    public final int getSize() {
-        return trapArray[0];
-    }
-
-    public final void setSize(int size) {
-        trapArray[0] = 0;
-    }
-
-    public final int getLeft() {
-        return trapArray[1];
-    }
-
-    public final int getTop() {
-        return trapArray[2];
-    }
-
-    public final int getRight() {
-        return trapArray[3];
-    }
-
-    public final int getBottom() {
-        return trapArray[4];
-    }
-
-
-    private final int getTrapStartAddresse(int pos) {
-        return TRAP_START_INDEX + TRAP_SIZE * pos;
-    }
-
-    public final int getTop(int pos) {
-        return trapArray[getTrapStartAddresse(pos) + 0];
-    }
-
-    public final int getBottom(int pos) {
-        return trapArray[getTrapStartAddresse(pos) + 1];
-    }
-
-    public final int getP1XLeft(int pos) {
-        return trapArray[getTrapStartAddresse(pos) + 2];
-    }
-
-    public final int getP1YLeft(int pos) {
-        return trapArray[getTrapStartAddresse(pos) + 3];
-    }
-
-    public final int getP2XLeft(int pos) {
-        return trapArray[getTrapStartAddresse(pos) + 4];
-    }
-
-    public final int getP2YLeft(int pos) {
-        return trapArray[getTrapStartAddresse(pos) + 5];
-    }
-
-    public final int getP1XRight(int pos) {
-        return trapArray[getTrapStartAddresse(pos) + 6];
-    }
-
-    public final int getP1YRight(int pos) {
-        return trapArray[getTrapStartAddresse(pos) + 7];
-    }
-
-    public final int getP2XRight(int pos) {
-        return trapArray[getTrapStartAddresse(pos) + 8];
-    }
-
-    public final int getP2YRight(int pos) {
-        return trapArray[getTrapStartAddresse(pos) + 9];
-    }
-}
--- a/src/java.desktop/unix/classes/sun/java2d/xr/XRBackend.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/java.desktop/unix/classes/sun/java2d/xr/XRBackend.java	Mon Nov 27 17:04:45 2017 +0000
@@ -36,7 +36,6 @@
 import java.util.*;
 
 import sun.font.*;
-import sun.java2d.jules.*;
 import sun.java2d.pipe.*;
 
 public interface XRBackend {
@@ -110,7 +109,4 @@
 
     public void setGCMode(long gc, boolean copy);
 
-    public void renderCompositeTrapezoids(byte op, int src, int maskFormat,
-                                          int dst, int srcX, int srcY,
-                                          TrapezoidList trapList);
 }
--- a/src/java.desktop/unix/classes/sun/java2d/xr/XRBackendNative.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/java.desktop/unix/classes/sun/java2d/xr/XRBackendNative.java	Mon Nov 27 17:04:45 2017 +0000
@@ -29,7 +29,6 @@
 import java.util.*;
 
 import sun.font.*;
-import sun.java2d.jules.*;
 import sun.java2d.pipe.*;
 
 import static sun.java2d.xr.XRUtils.XDoubleToFixed;
@@ -315,16 +314,4 @@
                                              int sx, int sy, int dx, int dy,
                                              int w, int h);
 
-    public void renderCompositeTrapezoids(byte op, int src, int maskFormat,
-                                          int dst, int srcX, int srcY,
-                                          TrapezoidList trapList) {
-        renderCompositeTrapezoidsNative(op, src, getFormatPtr(maskFormat),
-                                        dst, srcX, srcY,
-                                        trapList.getTrapArray());
-    }
-
-    private static native void
-        renderCompositeTrapezoidsNative(byte op, int src, long maskFormat,
-                                        int dst, int srcX, int srcY,
-                                        int[] trapezoids);
 }
--- a/src/java.desktop/unix/classes/sun/java2d/xr/XRCompositeManager.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/java.desktop/unix/classes/sun/java2d/xr/XRCompositeManager.java	Mon Nov 27 17:04:45 2017 +0000
@@ -33,7 +33,6 @@
 
 import sun.font.*;
 import sun.java2d.*;
-import sun.java2d.jules.*;
 import sun.java2d.loops.*;
 
 /**
@@ -253,29 +252,6 @@
                 maskX, maskY, dstX, dstY, width, height);
     }
 
-    public void XRCompositeTraps(int dst, int srcX, int srcY,
-            TrapezoidList trapList) {
-        int renderReferenceX = 0;
-        int renderReferenceY = 0;
-
-        if (trapList.getP1YLeft(0) < trapList.getP2YLeft(0)) {
-            renderReferenceX = trapList.getP1XLeft(0);
-            renderReferenceY = trapList.getP1YLeft(0);
-        } else {
-            renderReferenceX = trapList.getP2XLeft(0);
-            renderReferenceY = trapList.getP2YLeft(0);
-        }
-
-        renderReferenceX = (int) Math.floor(XRUtils
-                .XFixedToDouble(renderReferenceX));
-        renderReferenceY = (int) Math.floor(XRUtils
-                .XFixedToDouble(renderReferenceY));
-
-        con.renderCompositeTrapezoids(compRule, getCurrentSource().picture,
-                XRUtils.PictStandardA8, dst, renderReferenceX,
-                renderReferenceY, trapList);
-    }
-
     public void XRRenderRectangles(XRSurfaceData dst, GrowableRectArray rects) {
         if (xorEnabled) {
             con.GCRectangles(dst.getXid(), dst.getGC(), rects);
--- a/src/java.desktop/unix/classes/sun/java2d/xr/XRSurfaceData.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/java.desktop/unix/classes/sun/java2d/xr/XRSurfaceData.java	Mon Nov 27 17:04:45 2017 +0000
@@ -33,7 +33,6 @@
 import sun.java2d.SunGraphics2D;
 import sun.java2d.SurfaceData;
 import sun.java2d.SurfaceDataProxy;
-import sun.java2d.jules.*;
 import sun.java2d.loops.*;
 import sun.java2d.pipe.*;
 import sun.java2d.x11.*;
@@ -146,29 +145,21 @@
             }
         }
 
-        if (sg2d.antialiasHint == SunHints.INTVAL_ANTIALIAS_ON &&
-            JulesPathBuf.isCairoAvailable())
-        {
-            sg2d.shapepipe = aaShapePipe;
-            sg2d.drawpipe = aaPixelToShapeConv;
-            sg2d.fillpipe = aaPixelToShapeConv;
+        if (txPipe != null) {
+            if (sg2d.transformState >= SunGraphics2D.TRANSFORM_TRANSLATESCALE) {
+                sg2d.drawpipe = txPipe;
+                sg2d.fillpipe = txPipe;
+            } else if (sg2d.strokeState != SunGraphics2D.STROKE_THIN) {
+                sg2d.drawpipe = txPipe;
+                sg2d.fillpipe = nonTxPipe;
+            } else {
+                sg2d.drawpipe = nonTxPipe;
+                sg2d.fillpipe = nonTxPipe;
+            }
+            sg2d.shapepipe = nonTxPipe;
         } else {
-            if (txPipe != null) {
-                if (sg2d.transformState >= SunGraphics2D.TRANSFORM_TRANSLATESCALE) {
-                    sg2d.drawpipe = txPipe;
-                    sg2d.fillpipe = txPipe;
-                } else if (sg2d.strokeState != SunGraphics2D.STROKE_THIN) {
-                    sg2d.drawpipe = txPipe;
-                    sg2d.fillpipe = nonTxPipe;
-                } else {
-                    sg2d.drawpipe = nonTxPipe;
-                    sg2d.fillpipe = nonTxPipe;
-                }
-                sg2d.shapepipe = nonTxPipe;
-            } else {
-                if (!validated) {
-                    super.validatePipe(sg2d);
-                }
+            if (!validated) {
+                super.validatePipe(sg2d);
             }
         }
 
@@ -528,11 +519,6 @@
                 xrtextpipe = maskBuffer.getTextRenderer();
                 xrDrawImage = new XRDrawImage();
 
-                if (JulesPathBuf.isCairoAvailable()) {
-                    aaShapePipe =
-                       new JulesShapePipe(XRCompositeManager.getInstance(this));
-                    aaPixelToShapeConv = new PixelToShapeConverter(aaShapePipe);
-                }
             } finally {
                 SunToolkit.awtUnlock();
             }
--- a/src/java.desktop/unix/native/libawt_xawt/java2d/x11/XRBackendNative.c	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/java.desktop/unix/native/libawt_xawt/java2d/x11/XRBackendNative.c	Mon Nov 27 17:04:45 2017 +0000
@@ -1110,20 +1110,3 @@
       free(xRects);
     }
 }
-
-JNIEXPORT void JNICALL
-Java_sun_java2d_xr_XRBackendNative_renderCompositeTrapezoidsNative
- (JNIEnv *env, jclass cls, jbyte op, jint src, jlong maskFmt,
- jint dst, jint srcX, jint srcY, jintArray  trapArray) {
-    jint *traps;
-
-    if ((traps = (jint *) (*env)->GetPrimitiveArrayCritical(env, trapArray, NULL)) == NULL) {
-      return;
-    }
-
-    XRenderCompositeTrapezoids(awt_display, op, (Picture) src, (Picture) dst,
-                               (XRenderPictFormat *) jlong_to_ptr(maskFmt),
-                               srcX, srcY, (XTrapezoid *) (traps+5), traps[0]);
-
-    (*env)->ReleasePrimitiveArrayCritical(env, trapArray, traps, JNI_ABORT);
-}
--- a/src/java.desktop/windows/classes/sun/awt/windows/TranslucentWindowPainter.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/java.desktop/windows/classes/sun/awt/windows/TranslucentWindowPainter.java	Mon Nov 27 17:04:45 2017 +0000
@@ -26,10 +26,12 @@
 
 import java.awt.AlphaComposite;
 import java.awt.Color;
+import java.awt.Graphics;
 import java.awt.Graphics2D;
 import java.awt.GraphicsConfiguration;
 import java.awt.Image;
 import java.awt.Window;
+import java.awt.geom.AffineTransform;
 import java.awt.image.BufferedImage;
 import java.awt.image.DataBufferInt;
 import java.awt.image.VolatileImage;
@@ -38,6 +40,7 @@
 import sun.java2d.DestSurfaceProvider;
 import sun.java2d.InvalidPipeException;
 import sun.java2d.Surface;
+import sun.java2d.pipe.Region;
 import sun.java2d.pipe.RenderQueue;
 import sun.java2d.pipe.BufferedContext;
 import sun.java2d.pipe.hw.AccelGraphicsConfig;
@@ -117,6 +120,12 @@
     protected abstract boolean update(Image bb);
 
     /**
+     * Create (if needed), clears back buffer (if requested) and return
+     * graphics for this class depending upon the buffer type
+     */
+    protected abstract Graphics getGraphics(boolean clear);
+
+    /**
      * Flushes the resources associated with the painter. They will be
      * recreated as needed.
      */
@@ -130,10 +139,9 @@
      */
     public void updateWindow(boolean repaint) {
         boolean done = false;
-        Image bb = getBackBuffer(repaint);
         while (!done) {
             if (repaint) {
-                Graphics2D g = (Graphics2D)bb.getGraphics();
+                Graphics2D g = (Graphics2D) getGraphics(repaint);
                 try {
                     window.paintAll(g);
                 } finally {
@@ -141,10 +149,9 @@
                 }
             }
 
-            done = update(bb);
+            done = update(getBackBuffer(false));
             if (!done) {
                 repaint = true;
-                bb = getBackBuffer(true);
             }
         }
     }
@@ -178,8 +185,12 @@
 
         @Override
         protected Image getBackBuffer(boolean clear) {
-            int w = window.getWidth();
-            int h = window.getHeight();
+            GraphicsConfiguration gc = peer.getGraphicsConfiguration();
+            AffineTransform transform = gc.getDefaultTransform();
+            int w = Region.clipRound(
+                    window.getWidth() * transform.getScaleX());
+            int h = Region.clipRound(
+                    window.getHeight() * transform.getScaleY());
             if (backBuffer == null ||
                 backBuffer.getWidth() != w ||
                 backBuffer.getHeight() != h)
@@ -236,6 +247,19 @@
                 backBuffer = null;
             }
         }
+
+        @Override
+        protected Graphics getGraphics(boolean clear) {
+            Graphics g = getBackBuffer(clear).getGraphics();
+            /*
+             * This graphics object returned by BuffereImage is not scaled to
+             * graphics configuration, but this graphics object can be used by
+             * components inside this TranslucentWindow. So need to scale this
+             * before returning.
+             */
+            ((Graphics2D)g).transform(peer.getGraphicsConfiguration().getDefaultTransform());
+            return g;
+        }
     }
 
     /**
@@ -283,6 +307,11 @@
                 viBB = null;
             }
         }
+
+        @Override
+        protected Graphics getGraphics(boolean clear) {
+            return getBackBuffer(clear).getGraphics();
+        }
     }
 
     /**
--- a/src/java.desktop/windows/classes/sun/awt/windows/WLightweightFramePeer.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/java.desktop/windows/classes/sun/awt/windows/WLightweightFramePeer.java	Mon Nov 27 17:04:45 2017 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2017, 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
@@ -32,10 +32,11 @@
 import java.awt.event.MouseEvent;
 
 import sun.awt.LightweightFrame;
+import sun.awt.OverrideNativeWindowHandle;
 import sun.swing.JLightweightFrame;
 import sun.swing.SwingAccessor;
 
-public class WLightweightFramePeer extends WFramePeer {
+public class WLightweightFramePeer extends WFramePeer implements OverrideNativeWindowHandle {
 
     public WLightweightFramePeer(LightweightFrame target) {
         super(target);
@@ -50,6 +51,13 @@
         return getLwTarget().getGraphics();
     }
 
+    private native void overrideNativeHandle(long hwnd);
+
+    @Override
+    public void overrideWindowHandle(final long handle) {
+        overrideNativeHandle(handle);
+    }
+
     @Override
     public void show() {
         super.show();
--- a/src/java.desktop/windows/classes/sun/awt/windows/WWindowPeer.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/java.desktop/windows/classes/sun/awt/windows/WWindowPeer.java	Mon Nov 27 17:04:45 2017 +0000
@@ -717,7 +717,7 @@
 
     public final Graphics getTranslucentGraphics() {
         synchronized (getStateLock()) {
-            return isOpaque ? null : painter.getBackBuffer(false).getGraphics();
+            return isOpaque ? null : painter.getGraphics(false);
         }
     }
 
--- a/src/java.desktop/windows/native/libawt/windows/awt_Component.cpp	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/java.desktop/windows/native/libawt/windows/awt_Component.cpp	Mon Nov 27 17:04:45 2017 +0000
@@ -3893,25 +3893,34 @@
         if ( m_bitsCandType & bits )
             SetCandidateWindow(iCandType, x - p.x, y - p.y);
     }
-    if (m_bitsCandType != 0) {
-        // REMIND: is there any chance GetProxyFocusOwner() returns NULL here?
-        ::DefWindowProc(ImmGetHWnd(),
-                        WM_IME_NOTIFY, IMN_OPENCANDIDATE, m_bitsCandType);
-    }
 }
 
 void AwtComponent::SetCandidateWindow(int iCandType, int x, int y)
 {
     HWND hwnd = ImmGetHWnd();
     HIMC hIMC = ImmGetContext(hwnd);
-    CANDIDATEFORM cf;
-    cf.dwIndex = iCandType;
-    cf.dwStyle = CFS_POINT;
-    cf.ptCurrentPos.x = x;
-    cf.ptCurrentPos.y = y;
-
-    ImmSetCandidateWindow(hIMC, &cf);
-    ImmReleaseContext(hwnd, hIMC);
+    if (hIMC) {
+        CANDIDATEFORM cf;
+        cf.dwStyle = CFS_POINT;
+        ImmGetCandidateWindow(hIMC, 0, &cf);
+        if (x != cf.ptCurrentPos.x || y != cf.ptCurrentPos.y) {
+            cf.dwIndex = iCandType;
+            cf.dwStyle = CFS_POINT;
+            cf.ptCurrentPos = {x, y};
+            cf.rcArea = {0, 0, 0, 0};
+            ImmSetCandidateWindow(hIMC, &cf);
+        }
+        COMPOSITIONFORM cfr;
+        cfr.dwStyle = CFS_POINT;
+        ImmGetCompositionWindow(hIMC, &cfr);
+        if (x != cfr.ptCurrentPos.x || y != cfr.ptCurrentPos.y) {
+            cfr.dwStyle = CFS_POINT;
+            cfr.ptCurrentPos = {x, y};
+            cfr.rcArea = {0, 0, 0, 0};
+            ImmSetCompositionWindow(hIMC, &cfr);
+        }
+        ImmReleaseContext(hwnd, hIMC);
+    }
 }
 
 MsgRouting AwtComponent::WmImeSetContext(BOOL fSet, LPARAM *lplParam)
@@ -3939,17 +3948,14 @@
 MsgRouting AwtComponent::WmImeNotify(WPARAM subMsg, LPARAM bitsCandType)
 {
     if (!m_useNativeCompWindow) {
-        if (subMsg == IMN_OPENCANDIDATE) {
+        if (subMsg == IMN_OPENCANDIDATE || subMsg == IMN_CHANGECANDIDATE) {
             m_bitsCandType = bitsCandType;
             InquireCandidatePosition();
         } else if (subMsg == IMN_OPENSTATUSWINDOW ||
-                   subMsg == WM_IME_STARTCOMPOSITION) {
-            m_bitsCandType = 0;
-            InquireCandidatePosition();
-        } else if (subMsg == IMN_SETCANDIDATEPOS) {
+                   subMsg == WM_IME_STARTCOMPOSITION ||
+                   subMsg == IMN_SETCANDIDATEPOS) {
             InquireCandidatePosition();
         }
-        return mrConsume;
     }
     return mrDoDefault;
 }
--- a/src/java.desktop/windows/native/libawt/windows/awt_Dialog.cpp	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/java.desktop/windows/native/libawt/windows/awt_Dialog.cpp	Mon Nov 27 17:04:45 2017 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2017, 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
@@ -118,7 +118,8 @@
         if (parent != NULL) {
             JNI_CHECK_PEER_GOTO(parent, done);
             awtParent = (AwtWindow *)pData;
-            hwndParent = awtParent->GetHWnd();
+            HWND oHWnd = awtParent->GetOverriddenHWnd();
+            hwndParent = oHWnd ? oHWnd : awtParent->GetHWnd();
         } else {
             // There is no way to prevent a parentless dialog from showing on
             //  the taskbar other than to specify an invisible parent and set
--- a/src/java.desktop/windows/native/libawt/windows/awt_Font.cpp	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/java.desktop/windows/native/libawt/windows/awt_Font.cpp	Mon Nov 27 17:04:45 2017 +0000
@@ -283,6 +283,7 @@
             // Ask peer class for the text component font name
             jstring jTextComponentFontName = GetTextComponentFontName(env, font);
             if (jTextComponentFontName == NULL) {
+                delete awtFont;
                 return NULL;
             }
             LPCWSTR textComponentFontName = JNU_GetStringPlatformChars(env, jTextComponentFontName, NULL);
--- a/src/java.desktop/windows/native/libawt/windows/awt_Frame.cpp	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/java.desktop/windows/native/libawt/windows/awt_Frame.cpp	Mon Nov 27 17:04:45 2017 +0000
@@ -169,7 +169,8 @@
             JNI_CHECK_PEER_GOTO(parent, done);
             {
                 AwtFrame* parent = (AwtFrame *)pData;
-                hwndParent = parent->GetHWnd();
+                HWND oHWnd = parent->GetOverriddenHWnd();
+                hwndParent = oHWnd ? oHWnd : parent->GetHWnd();
             }
         }
 
--- a/src/java.desktop/windows/native/libawt/windows/awt_Window.cpp	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/java.desktop/windows/native/libawt/windows/awt_Window.cpp	Mon Nov 27 17:04:45 2017 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2017, 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
@@ -164,6 +164,11 @@
     jfloat scaleY;
 };
 
+struct OverrideHandle {
+    jobject frame;
+    HWND handle;
+};
+
 /************************************************************************
  * AwtWindow fields
  */
@@ -242,6 +247,7 @@
     prevScaleRec.screen = -1;
     prevScaleRec.scaleX = -1.0f;
     prevScaleRec.scaleY = -1.0f;
+    m_overriddenHwnd = NULL;
 }
 
 AwtWindow::~AwtWindow()
@@ -2571,6 +2577,24 @@
    delete rfs;
 }
 
+void AwtWindow::_OverrideHandle(void *param)
+{
+    JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
+
+    OverrideHandle* oh = (OverrideHandle *) param;
+    jobject self = oh->frame;
+    AwtWindow *f = NULL;
+
+    PDATA pData;
+    JNI_CHECK_PEER_GOTO(self, ret);
+    f = (AwtWindow *)pData;
+    f->OverrideHWnd(oh->handle);
+ret:
+    env->DeleteGlobalRef(self);
+
+    delete oh;
+}
+
 /*
  * This is AwtWindow-specific function that is not intended for reusing
  */
@@ -3946,4 +3970,25 @@
 
     CATCH_BAD_ALLOC;
 }
+
+/*
+ * Class:     sun_awt_windows_WLightweightFramePeer
+ * Method:    overrideNativeHandle
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL Java_sun_awt_windows_WLightweightFramePeer_overrideNativeHandle
+  (JNIEnv *env, jobject self, jlong hwnd)
+{
+    TRY;
+
+    OverrideHandle *oh = new OverrideHandle;
+    oh->frame = env->NewGlobalRef(self);
+    oh->handle = (HWND) hwnd;
+
+    AwtToolkit::GetInstance().SyncCall(AwtFrame::_OverrideHandle, oh);
+    // global ref and oh are deleted in _OverrideHandle()
+
+    CATCH_BAD_ALLOC;
+}
+
 } /* extern "C" */
--- a/src/java.desktop/windows/native/libawt/windows/awt_Window.h	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/java.desktop/windows/native/libawt/windows/awt_Window.h	Mon Nov 27 17:04:45 2017 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2017, 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
@@ -245,6 +245,7 @@
     static void _SetFullScreenExclusiveModeState(void* param);
     static void _GetNativeWindowSize(void* param);
     static void _WindowDPIChange(void* param);
+    static void _OverrideHandle(void *param);
 
     inline static BOOL IsResizing() {
         return sm_resizing;
@@ -260,6 +261,9 @@
 
     static void FocusedWindowChanged(HWND from, HWND to);
 
+    inline HWND GetOverriddenHWnd() { return m_overriddenHwnd; }
+    inline void OverrideHWnd(HWND hwnd) { m_overriddenHwnd = hwnd; }
+
 private:
     static int ms_instanceCounter;
     static HHOOK ms_hCBTFilter;
@@ -311,6 +315,9 @@
     // The tooltip that appears when hovering the icon
     HWND securityTooltipWindow;
 
+    //Allows substitute parent window with JavaFX stage to make it below a dialog
+    HWND m_overriddenHwnd;
+
     UINT warningWindowWidth;
     UINT warningWindowHeight;
     void InitSecurityWarningSize(JNIEnv *env);
--- a/src/java.management.rmi/share/classes/javax/management/remote/rmi/RMIConnectorServer.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/java.management.rmi/share/classes/javax/management/remote/rmi/RMIConnectorServer.java	Mon Nov 27 17:04:45 2017 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2017, 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
@@ -102,6 +102,26 @@
         "jmx.remote.rmi.server.socket.factory";
 
     /**
+     * Name of the attribute that specifies a list of class names acceptable
+     * as parameters to the {@link RMIServer#newClient(java.lang.Object) RMIServer.newClient()}
+     * remote method call.
+     * <p>
+     * This list of classes should correspond to the transitive closure of the
+     * credentials class (or classes) used by the installed {@linkplain JMXAuthenticator}
+     * associated with the {@linkplain RMIServer} implementation.
+     * <p>
+     * If the attribute is not set, or is null, then any class is
+     * deemed acceptable.
+     *
+     * @deprecated Use {@link #CREDENTIALS_FILTER_PATTERN} with a
+     * {@linkplain java.io.ObjectInputFilter.Config#createFilter
+     * filter pattern} string instead.
+     */
+    @Deprecated(since="10", forRemoval=true)
+    public static final String CREDENTIAL_TYPES =
+            "jmx.remote.rmi.server.credential.types";
+
+    /**
     * Name of the attribute that specifies an
     * {@link ObjectInputFilter} pattern string to filter classes acceptable
     * for {@link RMIServer#newClient(java.lang.Object) RMIServer.newClient()}
--- a/src/java.xml.bind/share/classes/com/sun/xml/internal/bind/AnyTypeAdapter.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/java.xml.bind/share/classes/com/sun/xml/internal/bind/AnyTypeAdapter.java	Mon Nov 27 17:04:45 2017 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, 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
@@ -30,7 +30,7 @@
 /**
  * {@link XmlAdapter} useful for mapping interfaces.
  *
- * See <a href="https://jaxb.dev.java.net/guide/Mapping_interfaces.html">The JAXB user's guide</a>
+ * See <a href="https://javaee.github.io/jaxb-v2/doc/user-guide/ch03.html#annotating-your-classes-mapping-interfaces">The JAXB user's guide</a>
  * for more about this adapter class.
  *
  * @author Kohsuke Kawaguchi
--- a/src/java.xml.bind/share/classes/com/sun/xml/internal/bind/CycleRecoverable.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/java.xml.bind/share/classes/com/sun/xml/internal/bind/CycleRecoverable.java	Mon Nov 27 17:04:45 2017 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, 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
@@ -32,14 +32,13 @@
  * to handle cycles in the object graph.
  *
  * <p>
- * As discussed in <a href="https://jaxb.dev.java.net/guide/Mapping_cyclic_references_to_XML.html">
+ * As discussed in <a href="https://javaee.github.io/jaxb-v2/doc/user-guide/ch03.html#annotating-your-classes-mapping-cyclic-references-to-xml">
  * the users' guide</a>, normally a cycle in the object graph causes the marshaller to report an error,
  * and when an error is found, the JAXB RI recovers by cutting the cycle arbitrarily.
  * This is not always a desired behavior.
  *
  * <p>
  * Implementing this interface allows user application to change this behavior.
- * Also see <a href="http://forums.java.net/jive/thread.jspa?threadID=13670">this related discussion</a>.
  *
  * @since JAXB 2.1 EA2
  * @author Kohsuke Kawaguchi
--- a/src/java.xml.bind/share/classes/javax/xml/bind/ContextFinder.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/java.xml.bind/share/classes/javax/xml/bind/ContextFinder.java	Mon Nov 27 17:04:45 2017 +0000
@@ -182,6 +182,9 @@
                                    Map properties) throws JAXBException {
 
         try {
+
+            ModuleUtil.delegateAddOpensToImplModule(contextPathClasses, spFactory);
+
             /*
              * javax.xml.bind.context.factory points to a class which has a
              * static method called 'createContext' that
@@ -215,8 +218,6 @@
                 throw handleClassCastException(context.getClass(), JAXBContext.class);
             }
 
-            ModuleUtil.delegateAddOpensToImplModule(contextPathClasses, spFactory);
-
             return (JAXBContext) context;
         } catch (InvocationTargetException x) {
             // throw if it is exception not to be wrapped
@@ -274,6 +275,7 @@
                                    Map properties,
                                    Class spFactory) throws JAXBException {
         try {
+            ModuleUtil.delegateAddOpensToImplModule(classes,  spFactory);
 
             Method m = spFactory.getMethod("createContext", Class[].class, Map.class);
             Object obj = instantiateProviderIfNecessary(spFactory);
@@ -282,7 +284,6 @@
                 // the cast would fail, so generate an exception with a nice message
                 throw handleClassCastException(context.getClass(), JAXBContext.class);
             }
-            ModuleUtil.delegateAddOpensToImplModule(classes,  spFactory);
             return (JAXBContext) context;
 
         } catch (NoSuchMethodException | IllegalAccessException e) {
@@ -328,9 +329,8 @@
                 JAXBContextFactory.class, logger, EXCEPTION_HANDLER);
 
         if (obj != null) {
-            JAXBContext context = obj.createContext(contextPath, classLoader, properties);
             ModuleUtil.delegateAddOpensToImplModule(contextPathClasses, obj.getClass());
-            return context;
+            return obj.createContext(contextPath, classLoader, properties);
         }
 
         // to ensure backwards compatibility
@@ -385,9 +385,8 @@
                 ServiceLoaderUtil.firstByServiceLoader(JAXBContextFactory.class, logger, EXCEPTION_HANDLER);
 
         if (factory != null) {
-            JAXBContext context = factory.createContext(classes, properties);
             ModuleUtil.delegateAddOpensToImplModule(classes, factory.getClass());
-            return context;
+            return factory.createContext(classes, properties);
         }
 
         // to ensure backwards compatibility
--- a/src/java.xml.bind/share/classes/javax/xml/bind/ModuleUtil.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/java.xml.bind/share/classes/javax/xml/bind/ModuleUtil.java	Mon Nov 27 17:04:45 2017 +0000
@@ -130,9 +130,6 @@
      */
     static void delegateAddOpensToImplModule(Class[] classes, Class<?> factorySPI) throws JAXBException {
         final Module implModule = factorySPI.getModule();
-        if (!implModule.isNamed()) {
-            return;
-        }
 
         Module jaxbModule = JAXBContext.class.getModule();
 
--- a/src/java.xml.bind/share/classes/javax/xml/bind/Unmarshaller.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/java.xml.bind/share/classes/javax/xml/bind/Unmarshaller.java	Mon Nov 27 17:04:45 2017 +0000
@@ -251,7 +251,7 @@
  *     <tr>
  *       <th scope="col">JAXBElement Property</th>
  *       <th scope="col">Value</th>
- *     </tr>
+ *       </tr>
  *     <tr>
  *       <th scope="col">name</th>
  *       <th scope="col">{@code xml element name}</th>
--- a/src/java.xml.bind/share/classes/javax/xml/bind/annotation/adapters/package-info.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/java.xml.bind/share/classes/javax/xml/bind/annotation/adapters/package-info.java	Mon Nov 27 17:04:45 2017 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2017, 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
@@ -34,7 +34,7 @@
  * </ul>
  *
  * <h2>Related Documentation</h2>
- * <p>
+ *
  * For overviews, tutorials, examples, guides, and tool documentation,
  * please see:
  * <ul>
--- a/src/java.xml.bind/share/classes/javax/xml/bind/attachment/AttachmentUnmarshaller.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/java.xml.bind/share/classes/javax/xml/bind/attachment/AttachmentUnmarshaller.java	Mon Nov 27 17:04:45 2017 +0000
@@ -78,7 +78,7 @@
     *     <tr>
     *       <th scope="col">MIME Type</th>
     *       <th scope="col">Java Type</th>
-    *     </tr>
+    *       </tr>
     *     <tr>
     *       <th scope="col">{@code DataHandler.getContentType()}</th>
     *       <th scope="col">{@code instanceof DataHandler.getContent()}</th>
--- a/src/java.xml.ws/share/classes/com/sun/xml/internal/messaging/saaj/LazyEnvelopeSource.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/java.xml.ws/share/classes/com/sun/xml/internal/messaging/saaj/LazyEnvelopeSource.java	Mon Nov 27 17:04:45 2017 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2017, 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
@@ -26,7 +26,6 @@
 package com.sun.xml.internal.messaging.saaj;
 
 import javax.xml.namespace.QName;
-import javax.xml.soap.SOAPException;
 import javax.xml.stream.XMLStreamException;
 import javax.xml.stream.XMLStreamReader;
 import javax.xml.stream.XMLStreamWriter;
--- a/src/java.xml.ws/share/classes/com/sun/xml/internal/messaging/saaj/soap/MessageImpl.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/java.xml.ws/share/classes/com/sun/xml/internal/messaging/saaj/soap/MessageImpl.java	Mon Nov 27 17:04:45 2017 +0000
@@ -890,7 +890,7 @@
         needsSave();
     }
 
-    static private final Iterator<AttachmentPart> nullIter = Collections.<AttachmentPart>EMPTY_LIST.iterator();
+    static private final Iterator<AttachmentPart> nullIter = Collections.EMPTY_LIST.<AttachmentPart>iterator();
 
     @Override
     public Iterator<AttachmentPart> getAttachments() {
--- a/src/java.xml.ws/share/classes/com/sun/xml/internal/messaging/saaj/soap/SOAPDocumentFragment.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/java.xml.ws/share/classes/com/sun/xml/internal/messaging/saaj/soap/SOAPDocumentFragment.java	Mon Nov 27 17:04:45 2017 +0000
@@ -43,6 +43,11 @@
         this.documentFragment = soapDocument.getDomDocument().createDocumentFragment();
     }
 
+    public SOAPDocumentFragment(SOAPDocumentImpl soapDocument, DocumentFragment documentFragment) {
+        this.soapDocument = soapDocument;
+        this.documentFragment = documentFragment;
+    }
+
     public SOAPDocumentFragment() {}
 
     @Override
@@ -192,7 +197,7 @@
     }
     @Override
     public Document getOwnerDocument() {
-        return documentFragment.getOwnerDocument();
+        return soapDocument;
     }
     @Override
     public Object getFeature(String feature, String version) {
@@ -231,4 +236,8 @@
     public Document getSoapDocument() {
         return soapDocument;
     }
+
+    public Node getDomNode() {
+        return documentFragment;
+    }
 }
--- a/src/java.xml.ws/share/classes/com/sun/xml/internal/messaging/saaj/soap/SOAPDocumentImpl.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/java.xml.ws/share/classes/com/sun/xml/internal/messaging/saaj/soap/SOAPDocumentImpl.java	Mon Nov 27 17:04:45 2017 +0000
@@ -220,8 +220,8 @@
         if (importedNode instanceof javax.xml.soap.Node) {
             Node newSoapNode = createSoapNode(importedNode.getClass(), newNode);
             newNode.setUserData(SAAJ_NODE, newSoapNode, null);
-            if (deep && importedNode.hasChildNodes()) {
-                NodeList childNodes = importedNode.getChildNodes();
+            if (deep && newSoapNode.hasChildNodes()) {
+                NodeList childNodes = newSoapNode.getChildNodes();
                 for (int i = 0; i < childNodes.getLength(); i++) {
                     registerChildNodes(childNodes.item(i), deep);
                 }
@@ -233,8 +233,12 @@
         return findIfPresent(newNode);
     }
 
-    //If the parentNode is not registered to domToSoap, create soap wapper for parentNode and register it to domToSoap
-    //If deep = true, also register all children of parentNode to domToSoap map.
+    /**
+     * If the parentNode is not registered to domToSoap, create soap wapper for parentNode and register it to domToSoap
+     * If deep = true, also register all children transitively of parentNode to domToSoap map.
+     * @param parentNode node to wrap
+     * @param deep wrap child nodes transitively
+     */
     public void registerChildNodes(Node parentNode, boolean deep) {
         if (parentNode.getUserData(SAAJ_NODE) == null) {
             if (parentNode instanceof Element) {
@@ -251,6 +255,8 @@
                         new SOAPTextImpl(this, (CharacterData) parentNode);
                         break;
                 }
+            } else if (parentNode instanceof DocumentFragment) {
+                new SOAPDocumentFragment(this, (DocumentFragment) parentNode);
             }
         }
         if (deep) {
@@ -412,7 +418,11 @@
 
     @Override
     public NamedNodeMap getAttributes() {
-        return new NamedNodeMapImpl(document.getAttributes(), this);
+        NamedNodeMap attributes = document.getAttributes();
+        if (attributes == null) {
+            return null;
+        }
+        return new NamedNodeMapImpl(attributes, this);
     }
 
     @Override
@@ -624,6 +634,8 @@
             return ((SOAPCommentImpl)node).getDomElement();
         } else if (node instanceof CDATAImpl) {
             return ((CDATAImpl) node).getDomElement();
+        } else if (node instanceof SOAPDocumentFragment) {
+            return ((SOAPDocumentFragment)node).getDomNode();
         }
         return node;
     }
@@ -636,6 +648,8 @@
             return new SOAPCommentImpl(this, (Comment) node);
         } else if (CDATAImpl.class.isAssignableFrom(nodeType)) {
             return new CDATAImpl(this, (CDATASection) node);
+        } else if (SOAPDocumentFragment.class.isAssignableFrom(nodeType)) {
+            return new SOAPDocumentFragment(this, (DocumentFragment) node);
         }
         try {
             Constructor<Node> constructor = nodeType.getConstructor(SOAPDocumentImpl.class, Element.class);
--- a/src/java.xml.ws/share/classes/com/sun/xml/internal/messaging/saaj/soap/SOAPPartImpl.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/java.xml.ws/share/classes/com/sun/xml/internal/messaging/saaj/soap/SOAPPartImpl.java	Mon Nov 27 17:04:45 2017 +0000
@@ -618,7 +618,7 @@
 
     @Override
     public Document getOwnerDocument() {
-        return document.getDomDocument().getOwnerDocument();
+        return document;
     }
 
     @Override
--- a/src/java.xml.ws/share/classes/com/sun/xml/internal/messaging/saaj/soap/impl/CDATAImpl.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/java.xml.ws/share/classes/com/sun/xml/internal/messaging/saaj/soap/impl/CDATAImpl.java	Mon Nov 27 17:04:45 2017 +0000
@@ -46,20 +46,19 @@
 
     @Override
     protected CDATASection createN(SOAPDocumentImpl ownerDoc, String text) {
-        CDATASection c = ownerDoc.getDomDocument().createCDATASection(text);
-//        ownerDoc.register(this);
-        return c;
+        return ownerDoc.getDomDocument().createCDATASection(text);
     }
 
     @Override
     protected CDATASection createN(SOAPDocumentImpl ownerDoc, CharacterData data) {
-        CDATASection c = (CDATASection) data;
-        return c;
+        return (CDATASection) data;
     }
 
     @Override
     public Text splitText(int offset) throws DOMException {
-        return getDomElement().splitText(offset);
+        Text text = getDomElement().splitText(offset);
+        getSoapDocument().registerChildNodes(text, true);
+        return text;
     }
 
     @Override
@@ -74,7 +73,9 @@
 
     @Override
     public Text replaceWholeText(String content) throws DOMException {
-        return getDomElement().replaceWholeText(content);
+        Text text = getDomElement().replaceWholeText(content);
+        getSoapDocument().registerChildNodes(text, true);
+        return text;
     }
 
     @Override
--- a/src/java.xml.ws/share/classes/com/sun/xml/internal/messaging/saaj/soap/impl/ElementImpl.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/java.xml.ws/share/classes/com/sun/xml/internal/messaging/saaj/soap/impl/ElementImpl.java	Mon Nov 27 17:04:45 2017 +0000
@@ -1720,7 +1720,11 @@
 
     @Override
     public NamedNodeMap getAttributes() {
-        return new NamedNodeMapImpl(element.getAttributes(), soapDocument);
+        NamedNodeMap attributes = element.getAttributes();
+        if (attributes == null) {
+            return null;
+        }
+        return new NamedNodeMapImpl(attributes, soapDocument);
     }
 
     public Element getDomElement() {
--- a/src/java.xml.ws/share/classes/com/sun/xml/internal/messaging/saaj/soap/impl/NamedNodeMapImpl.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/java.xml.ws/share/classes/com/sun/xml/internal/messaging/saaj/soap/impl/NamedNodeMapImpl.java	Mon Nov 27 17:04:45 2017 +0000
@@ -30,6 +30,8 @@
 import org.w3c.dom.NamedNodeMap;
 import org.w3c.dom.Node;
 
+import java.util.Objects;
+
 /**
  * {@link NamedNodeMap} wrapper, finding SOAP elements automatically when possible.
  *
@@ -48,6 +50,8 @@
      * @param soapDocument soap document to find soap elements
      */
     public NamedNodeMapImpl(NamedNodeMap namedNodeMap, SOAPDocumentImpl soapDocument) {
+        Objects.requireNonNull(namedNodeMap);
+        Objects.requireNonNull(soapDocument);
         this.namedNodeMap = namedNodeMap;
         this.soapDocument = soapDocument;
     }
--- a/src/java.xml.ws/share/classes/com/sun/xml/internal/messaging/saaj/soap/impl/SOAPCommentImpl.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/java.xml.ws/share/classes/com/sun/xml/internal/messaging/saaj/soap/impl/SOAPCommentImpl.java	Mon Nov 27 17:04:45 2017 +0000
@@ -45,15 +45,12 @@
 
     @Override
     protected Comment createN(SOAPDocumentImpl ownerDoc, String text) {
-        Comment c = ownerDoc.getDomDocument().createComment(text);
-//        ownerDoc.register(this);
-        return c;
+        return ownerDoc.getDomDocument().createComment(text);
     }
 
     @Override
     protected Comment createN(SOAPDocumentImpl ownerDoc, CharacterData data) {
-        Comment c = (Comment) data;
-        return c;
+        return (Comment) data;
     }
 
     @Override
--- a/src/java.xml.ws/share/classes/com/sun/xml/internal/messaging/saaj/soap/impl/SOAPTextImpl.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/java.xml.ws/share/classes/com/sun/xml/internal/messaging/saaj/soap/impl/SOAPTextImpl.java	Mon Nov 27 17:04:45 2017 +0000
@@ -42,20 +42,19 @@
 
     @Override
     protected Text createN(SOAPDocumentImpl ownerDoc, String text) {
-        Text t = ownerDoc.getDomDocument().createTextNode(text);
-//        ownerDoc.register(this);
-        return t;
+        return ownerDoc.getDomDocument().createTextNode(text);
     }
 
     @Override
     protected Text createN(SOAPDocumentImpl ownerDoc, CharacterData data) {
-        Text t = (Text) data;
-        return t;
+        return (Text) data;
     }
 
     @Override
     public Text splitText(int offset) throws DOMException {
-        return getDomElement().splitText(offset);
+        Text text = getDomElement().splitText(offset);
+        getSoapDocument().registerChildNodes(text, true);
+        return text;
     }
 
     @Override
@@ -70,7 +69,9 @@
 
     @Override
     public Text replaceWholeText(String content) throws DOMException {
-        return getDomElement().replaceWholeText(content);
+        Text text = getDomElement().replaceWholeText(content);
+        getSoapDocument().registerChildNodes(text, true);
+        return text;
     }
 
     @Override
--- a/src/java.xml.ws/share/classes/com/sun/xml/internal/messaging/saaj/soap/impl/TextImpl.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/java.xml.ws/share/classes/com/sun/xml/internal/messaging/saaj/soap/impl/TextImpl.java	Mon Nov 27 17:04:45 2017 +0000
@@ -136,62 +136,62 @@
 
     @Override
     public Node getParentNode() {
-        return domNode.getParentNode();
+        return soapDocument.findIfPresent(domNode.getParentNode());
     }
 
     @Override
     public NodeList getChildNodes() {
-        return domNode.getChildNodes();
+        return new NodeListImpl(soapDocument, domNode.getChildNodes());
     }
 
     @Override
     public Node getFirstChild() {
-        return domNode.getFirstChild();
+        return soapDocument.findIfPresent(domNode.getFirstChild());
     }
 
     @Override
     public Node getLastChild() {
-        return domNode.getLastChild();
+        return soapDocument.findIfPresent(domNode.getLastChild());
     }
 
     @Override
     public Node getPreviousSibling() {
-        return domNode.getPreviousSibling();
+        return soapDocument.findIfPresent(domNode.getPreviousSibling());
     }
 
     @Override
     public Node getNextSibling() {
-        return domNode.getNextSibling();
+        return soapDocument.findIfPresent(domNode.getNextSibling());
     }
 
     @Override
     public NamedNodeMap getAttributes() {
-        return domNode.getAttributes();
+        return new NamedNodeMapImpl(domNode.getAttributes(), soapDocument);
     }
 
     @Override
     public Document getOwnerDocument() {
-        return domNode.getOwnerDocument();
+        return soapDocument;
     }
 
     @Override
     public Node insertBefore(Node newChild, Node refChild) throws DOMException {
-        return domNode.insertBefore(newChild, refChild);
+        return soapDocument.findIfPresent(domNode.insertBefore(newChild, refChild));
     }
 
     @Override
     public Node replaceChild(Node newChild, Node oldChild) throws DOMException {
-        return domNode.replaceChild(newChild, oldChild);
+        return soapDocument.findIfPresent(domNode.replaceChild(newChild, oldChild));
     }
 
     @Override
     public Node removeChild(Node oldChild) throws DOMException {
-        return domNode.removeChild(oldChild);
+        return soapDocument.findIfPresent(domNode.removeChild(oldChild));
     }
 
     @Override
     public Node appendChild(Node newChild) throws DOMException {
-        return domNode.appendChild(newChild);
+        return soapDocument.findIfPresent(domNode.appendChild(newChild));
     }
 
     @Override
@@ -339,4 +339,7 @@
         domNode.replaceData(offset, count, arg);
     }
 
+    public SOAPDocumentImpl getSoapDocument() {
+        return soapDocument;
+    }
 }
--- a/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/protocol/soap/ServerMUTube.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/protocol/soap/ServerMUTube.java	Mon Nov 27 17:04:45 2017 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, 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
@@ -30,6 +30,8 @@
 import com.sun.xml.internal.ws.client.HandlerConfiguration;
 import javax.xml.namespace.QName;
 import java.util.Set;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
 
 /**
  * @author Rama Pulavarthi
@@ -40,6 +42,7 @@
     private ServerTubeAssemblerContext tubeContext;
     private final Set<String> roles;
     private final Set<QName> handlerKnownHeaders;
+    private final Lock lock = new ReentrantLock();
 
     public ServerMUTube(ServerTubeAssemblerContext tubeContext, Tube next) {
         super(tubeContext.getEndpoint().getBinding(), next);
@@ -69,7 +72,13 @@
      */
     @Override
     public NextAction processRequest(Packet request) {
-        Set<QName> misUnderstoodHeaders = getMisUnderstoodHeaders(request.getMessage().getHeaders(),roles, handlerKnownHeaders);
+        Set<QName> misUnderstoodHeaders=null;
+        lock.lock();
+        try{
+            misUnderstoodHeaders = getMisUnderstoodHeaders(request.getMessage().getHeaders(),roles, handlerKnownHeaders);
+        } finally {
+            lock.unlock();
+        }
         if((misUnderstoodHeaders == null)  || misUnderstoodHeaders.isEmpty()) {
             return doInvoke(super.next, request);
         }
--- a/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/util/version.properties	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/util/version.properties	Mon Nov 27 17:04:45 2017 +0000
@@ -23,7 +23,7 @@
 # questions.
 #
 
-build-id=2.3.0-SNAPSHOT
-build-version=JAX-WS RI 2.3.0-SNAPSHOT
-major-version=2.3.0
-svn-revision=3012ef421cf43774943c57736dac2207aeea9f07
+build-id=2.3.1-SNAPSHOT
+build-version=JAX-WS RI 2.3.1-SNAPSHOT
+major-version=2.3.1
+svn-revision=6a0b290fe358f9de4deeec2d1ec3f6e76afa8005
--- a/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/util/xml/XmlCatalogUtil.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/util/xml/XmlCatalogUtil.java	Mon Nov 27 17:04:45 2017 +0000
@@ -27,7 +27,6 @@
 
 import com.sun.istack.internal.Nullable;
 import com.sun.xml.internal.ws.server.ServerRtException;
-import java.io.File;
 import java.net.URI;
 import java.net.URL;
 import java.util.ArrayList;
--- a/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/util/xml/XmlUtil.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/util/xml/XmlUtil.java	Mon Nov 27 17:04:45 2017 +0000
@@ -85,11 +85,8 @@
         "http://xml.org/sax/properties/lexical-handler";
 
     private static final String DISALLOW_DOCTYPE_DECL = "http://apache.org/xml/features/disallow-doctype-decl";
-
     private static final String EXTERNAL_GE = "http://xml.org/sax/features/external-general-entities";
-
     private static final String EXTERNAL_PE = "http://xml.org/sax/features/external-parameter-entities";
-
     private static final String LOAD_EXTERNAL_DTD = "http://apache.org/xml/features/nonvalidating/load-external-dtd";
 
     private static final Logger LOGGER = Logger.getLogger(XmlUtil.class.getName());
@@ -341,15 +338,15 @@
             factory.setFeature(featureToSet, securityOn);
             factory.setNamespaceAware(true);
             if (securityOn) {
-                factory.setExpandEntityReferences(false);
-                featureToSet = DISALLOW_DOCTYPE_DECL;
-                factory.setFeature(featureToSet, true);
-                featureToSet = EXTERNAL_GE;
-                factory.setFeature(featureToSet, false);
-                featureToSet = EXTERNAL_PE;
-                factory.setFeature(featureToSet, false);
-                featureToSet = LOAD_EXTERNAL_DTD;
-                factory.setFeature(featureToSet, false);
+               factory.setExpandEntityReferences(false);
+               featureToSet = DISALLOW_DOCTYPE_DECL;
+               factory.setFeature(featureToSet, true);
+               featureToSet = EXTERNAL_GE;
+               factory.setFeature(featureToSet, false);
+               featureToSet = EXTERNAL_PE;
+               factory.setFeature(featureToSet, false);
+               featureToSet = LOAD_EXTERNAL_DTD;
+               factory.setFeature(featureToSet, false);
             }
         } catch (ParserConfigurationException e) {
             LOGGER.log(Level.WARNING, "Factory [{0}] doesn't support "+featureToSet+" feature!", new Object[] {factory.getClass().getName()} );
--- a/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/wsdl/writer/WSDLGenerator.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/wsdl/writer/WSDLGenerator.java	Mon Nov 27 17:04:45 2017 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, 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
@@ -309,7 +309,7 @@
     private static class CommentFilter implements XmlSerializer {
         final XmlSerializer serializer;
         private static final String VERSION_COMMENT =
-                " Generated by JAX-WS RI (http://jax-ws.java.net). RI's version is " + RuntimeVersion.VERSION + ". ";
+                " Generated by JAX-WS RI (http://javaee.github.io/metro-jax-ws). RI's version is " + RuntimeVersion.VERSION + ". ";
 
         CommentFilter(XmlSerializer serializer) {
             this.serializer = serializer;
--- a/src/java.xml.ws/share/classes/javax/xml/soap/Detail.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/java.xml.ws/share/classes/javax/xml/soap/Detail.java	Mon Nov 27 17:04:45 2017 +0000
@@ -54,7 +54,7 @@
  *    Name name = se.createName("GetLastTradePrice", "WOMBAT",
  *                                "http://www.wombat.org/trader");
  *    d.addDetailEntry(name);
- *    Iterator it = d.getDetailEntries();
+ *    Iterator<DetailEntry> it = d.getDetailEntries();
  * }</pre>
  *
  * @since 1.6
--- a/src/java.xml.ws/share/classes/javax/xml/soap/SAAJMetaFactory.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/java.xml.ws/share/classes/javax/xml/soap/SAAJMetaFactory.java	Mon Nov 27 17:04:45 2017 +0000
@@ -28,7 +28,7 @@
 /**
 * The access point for the implementation classes of the factories defined in the
 * SAAJ API. The {@code newInstance} methods defined on factories {@link SOAPFactory} and
-* {@link MessageFactory} in SAAJ 1.3 defer to instances of this class to do the actual object creation.
+* {@link MessageFactory} in SAAJ 1.4 defer to instances of this class to do the actual object creation.
 * The implementations of {@code newInstance()} methods (in {@link SOAPFactory} and {@link MessageFactory})
 * that existed in SAAJ 1.2 have been updated to also delegate to the SAAJMetaFactory when the SAAJ 1.2
 * defined lookup fails to locate the Factory implementation class name.
--- a/src/java.xml.ws/share/classes/javax/xml/soap/SAAJResult.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/java.xml.ws/share/classes/javax/xml/soap/SAAJResult.java	Mon Nov 27 17:04:45 2017 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2017, 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
@@ -73,7 +73,7 @@
      * internally. The {@code SOAPPart} returned by {@link DOMResult#getNode()}
      * is not guaranteed to be well-formed.
      *
-     * @param protocol - the name of the SOAP protocol that the resulting SAAJ
+     * @param protocol the name of the SOAP protocol that the resulting SAAJ
      *                      tree should support
      *
      * @throws SOAPException if a {@code SOAPMessage} supporting the
@@ -95,7 +95,7 @@
      * after the transformation can be guaranteed only by means outside SAAJ
      * specification.
      *
-     * @param message - the message whose {@code SOAPPart} will be
+     * @param message the message whose {@code SOAPPart} will be
      *                  populated as a result of some transformation or
      *                  marshalling operation
      *
@@ -114,7 +114,7 @@
      * incoming data can be guaranteed by means outside of the SAAJ
      * specification.
      *
-     * @param rootNode - the root to which the results will be appended
+     * @param rootNode the root to which the results will be appended
      *
      * @since 1.6, SAAJ 1.3
      */
--- a/src/java.xml.ws/share/classes/javax/xml/soap/SOAPFactory.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/java.xml.ws/share/classes/javax/xml/soap/SOAPFactory.java	Mon Nov 27 17:04:45 2017 +0000
@@ -64,7 +64,7 @@
      * part of the tree rooted in {@code domElement} violates SOAP rules, a
      * {@code SOAPException} will be thrown.
      *
-     * @param domElement - the {@code Element} to be copied.
+     * @param domElement the {@code Element} to be copied.
      *
      * @return a new {@code SOAPElement} that is a copy of {@code domElement}.
      *
--- a/src/java.xml.ws/share/classes/javax/xml/soap/SOAPFault.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/java.xml.ws/share/classes/javax/xml/soap/SOAPFault.java	Mon Nov 27 17:04:45 2017 +0000
@@ -468,7 +468,7 @@
      * this {@code SOAPFault} object. The Node element
      * is optional in SOAP 1.2.
      *
-     * @param uri - the URI of the Node
+     * @param uri the URI of the Node
      *
      * @exception SOAPException  if there was an error in setting the
      *            Node for this  {@code SOAPFault} object.
@@ -500,7 +500,7 @@
      * this {@code SOAPFault} object. The Role element
      * is optional in SOAP 1.2.
      *
-     * @param uri - the URI of the Role
+     * @param uri the URI of the Role
      *
      * @exception SOAPException  if there was an error in setting the
      *            Role for this  {@code SOAPFault} object.
--- a/src/java.xml.ws/share/classes/javax/xml/soap/SOAPHeader.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/java.xml.ws/share/classes/javax/xml/soap/SOAPHeader.java	Mon Nov 27 17:04:45 2017 +0000
@@ -188,11 +188,11 @@
 
     /**
      * Creates a new Upgrade {@code SOAPHeaderElement} object initialized
-     * with the specified String Iterator of supported SOAP URIs and adds
-     * it to this {@code SOAPHeader} object.
+     * with the specified List of supported SOAP URIs and adds it to this
+     * {@code SOAPHeader} object.
      * This operation is supported on both SOAP 1.1 and SOAP 1.2 header.
      *
-     * @param supportedSOAPURIs an URI Strings {@code Iterator} of SOAP
+     * @param supportedSOAPURIs an {@code Iterator} object with the URIs of SOAP
      *          versions supported.
      * @return the new {@code SOAPHeaderElement} object that was
      *          inserted into this {@code SOAPHeader} object
--- a/src/java.xml.ws/share/classes/javax/xml/soap/SOAPHeaderElement.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/java.xml.ws/share/classes/javax/xml/soap/SOAPHeaderElement.java	Mon Nov 27 17:04:45 2017 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2017, 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
@@ -60,7 +60,7 @@
      * Sets the {@code Role} associated with this {@code SOAPHeaderElement}
      * object to the specified {@code Role}.
      *
-     * @param uri - the URI of the {@code Role}
+     * @param uri the URI of the {@code Role}
      *
      * @throws SOAPException if there is an error in setting the role
      *
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.xml.ws/share/classes/javax/xml/ws/wsdl_customizationschema_2_0.xsd	Mon Nov 27 17:04:45 2017 +0000
@@ -0,0 +1,458 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (c) 2005, 2017, 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.  Oracle designates this
+ particular file as subject to the "Classpath" exception as provided
+ by Oracle in the LICENSE file that accompanied this code.
+
+ 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.
+-->
+
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
+           xmlns:jaxws="http://java.sun.com/xml/ns/jaxws"
+           elementFormDefault="qualified"
+           targetNamespace="http://java.sun.com/xml/ns/jaxws"
+           attributeFormDefault="unqualified">
+  <xsd:annotation>
+    <xsd:documentation>
+
+      DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+      
+      Copyright (c) 2006-2017 Oracle and/or its affiliates. All rights reserved.
+      
+      The contents of this file are subject to the terms of either the GNU
+      General Public License Version 2 only ("GPL") or the Common Development
+      and Distribution License("CDDL") (collectively, the "License").  You
+      may not use this file except in compliance with the License.  You can
+      obtain a copy of the License at
+      https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
+      or packager/legal/LICENSE.txt.  See the License for the specific
+      language governing permissions and limitations under the License.
+      
+      When distributing the software, include this License Header Notice in each
+      file and include the License file at packager/legal/LICENSE.txt.
+      
+      GPL Classpath Exception:
+      Oracle designates this particular file as subject to the "Classpath"
+      exception as provided by Oracle in the GPL Version 2 section of the License
+      file that accompanied this code.
+      
+      Modifications:
+      If applicable, add the following below the License Header, with the fields
+      enclosed by brackets [] replaced by your own identifying information:
+      "Portions Copyright [year] [name of copyright owner]"
+      
+      Contributor(s):
+      If you wish your version of this file to be governed by only the CDDL or
+      only the GPL Version 2, indicate your decision by adding "[Contributor]
+      elects to include this software in this distribution under the [CDDL or GPL
+      Version 2] license."  If you don't indicate a single choice of license, a
+      recipient has the option to distribute your version of this file under
+      either the CDDL, the GPL Version 2 or to extend the choice of license to
+      its licensees as provided above.  However, if you add GPL Version 2 code
+      and therefore, elected the GPL Version 2 license, then the option applies
+      only if the new code is made subject to such option by the copyright
+      holder.
+      
+    </xsd:documentation>
+  </xsd:annotation>
+
+    <xs:annotation>
+        <xs:documentation>
+            Schema for JAX-WS 2.0 WSDL customization.
+        </xs:documentation>
+    </xs:annotation>
+
+    <xs:group name="declaration">
+        <xs:annotation>
+            <xs:documentation>
+                TODO
+            </xs:documentation>
+        </xs:annotation>
+        <xs:choice>
+            <xs:element ref="jaxws:package"/>
+            <xs:element ref="jaxws:enableWrapperStyle"/>
+            <xs:element ref="jaxws:enableAsyncMapping"/>
+            <xs:element ref="jaxws:enableMIMEContent"/>
+            <xs:element ref="jaxws:class"/>
+            <xs:element ref="jaxws:method"/>
+            <xs:element ref="jaxws:parameter"/>
+            <xs:element ref="jaxws:provider"/>
+            <xs:any namespace="##other" processContents="lax" />
+        </xs:choice>
+    </xs:group>
+    
+    <xs:element name="bindings">
+        <xs:annotation>
+            <xs:documentation>
+                WSDL customization binding declaration.
+
+                There are two ways to specify binding declarations.
+
+                1. All binding declarations pertainingto a given WSDL document are grouped together in a standalone
+                document, called an external binding file.
+
+                2. The second approach consists in embeddeding binding declarations directly inside a WSDL document. In
+                either case, the jaxws:bindings element is used as a container for JAX-WS binding declarations. It
+                contains a (possibly empty) list of binding declarations, in any order.
+
+                A binding declaration embedded in a WSDL document can only affect the WSDL element it extends. When a
+                jaxws:bindings element is used as a WSDL extension, it MUST NOT have a node attribute. Moreover, it MUST
+                NOT have an element whose qualified name is jaxws:bindings amongs its children.
+            </xs:documentation>
+        </xs:annotation>
+        <xs:complexType>
+            <xs:sequence>
+                <xs:choice minOccurs="0" maxOccurs="unbounded">
+                    <xs:group ref="jaxws:declaration"/>
+                    <xs:element ref="jaxws:bindings"/>
+                </xs:choice>               
+            </xs:sequence>
+
+            <xs:attribute name="wsdlLocation" type="xs:anyURI">
+                <xs:annotation>
+                    <xs:documentation>
+                        Location of the remote WSDL to associate binding declarations with. It MUST NOT be present if
+                        the jaxws:bindings element is used as an extension inside a WSDL document or one of its ancestor
+                        jaxws:bindings elements already contains this attribute.
+                    </xs:documentation>
+                </xs:annotation>
+
+            </xs:attribute>
+
+            <xs:attribute name="node" type="xs:string">
+                <xs:annotation>
+                    <xs:documentation>
+                        The value of the string is an XPATH 1.0 compliant string that resolves to a node in a remote
+                        WSDL to associate binding declarations with. The remote WSDL is specified by the
+                        wsdlLocation attribute occuring in the current element or in a parent of this element.
+
+                        The node attribute can be used to customize the inlined schema inside the WSDL, in this case the
+                        node attribute must point to the xs:schema node inside the WSDL. Further jaxb:bindings should be
+                        used as the child of jaxws:bindings.
+
+                        Example:
+                        <!--
+                        <jaxws:bindings wsdlLocation="..."
+                                        xmlns:xs="http://www.w3.org/2001/XMLSchema"
+                                        xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
+                                        xmlns:jaxws="http://java.sun.com/xml/ns/jaxws"
+                                        xmlns:jaxb="http://java.sun.com/xml/ns/jaxb">
+                            <jaxws:bindings
+                                    node="wsdl:definitions/wsdl:types/xs:schema[@targetNamespace='urn:test:types']">
+                                <jaxb:schemaBindings>
+                                    <jaxb:package name="client.types"/>
+                                </jaxb:schemaBindings>
+                                <jaxb:bindings node="//xs:complexType[@name='class']">
+                                    <jaxb:class name="Clazz"/>
+                                </jaxb:bindings>
+                            </jaxws:bindings>
+                        </jaxws:bindings>
+                        -->
+                        NOTE: It MUST NOT be present if the jaxws:bindings appears inside a WSDL document.
+                    </xs:documentation>
+                </xs:annotation>
+            </xs:attribute>
+
+            <xs:attribute name="version" type="xs:token" default="2.0">
+                <xs:annotation>
+                    <xs:documentation>
+                        Used to indicate the version of WSDL customization declarations. Only valid on root level
+                        bindings element.
+                        If this is absent, it will implicitly be assumed to be 2.0.
+                    </xs:documentation>
+                </xs:annotation>
+            </xs:attribute>
+        </xs:complexType>
+
+    </xs:element>
+
+    <xs:complexType name="tJavaDoc">
+        <xs:annotation></xs:annotation>
+        <xs:sequence>
+            <xs:element name="javadoc" type="xs:string" minOccurs="0"/>
+        </xs:sequence>
+    </xs:complexType>
+
+    <xs:element name="package">
+        <xs:annotation>
+            <xs:documentation>
+                If absent, the default package name is computed from the targetNamespace of the WSDL in scope. The rules
+                of targetNamespace to Java package name is described in the JAXB specification.
+
+                Appears in the context of a WSDL document, either as an extension to the wsdl:definitions element or in
+                an external binding file at a place where there is a WSDL document in scope.
+
+                Scope:
+                wsd;definitions
+
+                Example:
+                <!--
+                <jaxws:bindings wsdlLocation="..."
+                                xmlns:xs="http://www.w3.org/2001/XMLSchema"
+                                xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
+                                xmlns:jaxws="http://java.sun.com/xml/ns/jaxws"
+                                xmlns:jaxb="http://java.sun.com/xml/ns/jaxb">
+                    <jaxws:package></jaxws:package>
+                </jaxws:bindings>
+                -->
+            </xs:documentation>
+        </xs:annotation>
+
+        <xs:complexType>
+            <xs:complexContent>
+                <xs:extension base="jaxws:tJavaDoc">
+                    <xs:attribute name="name" type="xs:string" use="required"/>
+                </xs:extension>
+            </xs:complexContent>
+        </xs:complexType>
+    </xs:element>
+
+
+    <xs:element name="enableWrapperStyle" type="xs:boolean">
+        <xs:annotation>
+            <xs:documentation>
+                enableWrapperStyle can be used to disable wrapper style Java method generation. If absent the default
+                value of enableWrapperStyle is true. Setting it to true may not result into wrapper style method
+                generation unless the wrapper style rules are satisfied as defined in JAX-WS 2.1 specification 2.3.1.2.
+
+                Scope:
+                wsd;definitions, wsdl:portType, wsdl:portType/wsdl:operation.
+
+                Example:
+                <jaxws:bindings wsdlLocation="..."
+                                xmlns:xs="http://www.w3.org/2001/XMLSchema"
+                                xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
+                                xmlns:jaxws="http://java.sun.com/xml/ns/jaxws"
+                                xmlns:jaxb="http://java.sun.com/xml/ns/jaxb">
+                    <!-- Turn off wrapper style Java method signature generation -->
+                    <jaxws:enableWrapperStyle>false</jaxws:enableWrapperStyle>
+                </jaxws:bindings>
+            </xs:documentation>
+        </xs:annotation>
+    </xs:element>
+
+    <xs:element name="enableAsyncMapping" type="xs:boolean">
+        <xs:annotation>
+            <xs:documentation>
+                enableAsyncMapping can be used to enable async method generation in the entpoint interface generated
+                from a WSDL. If absent the default value of enableAsyncMapping is false. See JAX-WS 2.1 spec
+                section 2.3.4.2.
+
+                Scope:
+                wsd;definitions, wsdl:portType, wsdl:portType/wsdl:operation.
+
+                Note: These generated async methods can be used only on the client side.
+
+                Example:
+                <jaxws:bindings wsdlLocation="..."
+                                xmlns:xs="http://www.w3.org/2001/XMLSchema"
+                                xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
+                                xmlns:jaxws="http://java.sun.com/xml/ns/jaxws"
+                                xmlns:jaxb="http://java.sun.com/xml/ns/jaxb">
+                    <!-- Generate async methods in the generated Java endpoint interface for all the portTypes and
+                    operations in the WSDL's scope.  -->
+                    <jaxws:enableAsyncMapping>false</jaxws:enableAsyncMapping>
+                </jaxws:bindings>
+            </xs:documentation>
+        </xs:annotation>
+    </xs:element>
+
+    <xs:element name="enableMIMEContent" type="xs:boolean">
+        <xs:annotation>
+            <xs:documentation>
+                If present the use of the mime:content information is enabled as defined in the JAX-WS 2.1 spec
+                section 2.6.3.1
+
+                Scope:
+                wsdl:definitions, wsdl:binding, wsdl:binding/wsdl:operation
+
+                Example:
+                <jaxws:bindings wsdlLocation="..."
+                                xmlns:xs="http://www.w3.org/2001/XMLSchema"
+                                xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
+                                xmlns:jaxws="http://java.sun.com/xml/ns/jaxws"
+                                xmlns:jaxb="http://java.sun.com/xml/ns/jaxb">
+
+                    <!-- Enables MIME content for all the bindings in the WSDL's scope.  -->
+                    <jaxws:enableMIMEContent>false</jaxws:enableMIMEContent>
+                </jaxws:bindings>
+            </xs:documentation>
+        </xs:annotation>
+    </xs:element>
+
+    <xs:element name="class">
+        <xs:annotation>
+            <xs:documentation>
+                Customizes the name of generated classes for the SEI, service class or the fault class.
+
+                Scope:
+                wsd;portType - The name of generated SEI (Service Endpoint Interface)
+                wsdl:portType/wsdl:operation/wsdl:fault - The generated fault class name.
+                wsdl:service - Name of the generated Service class.
+
+                Example:
+
+                <jaxws:bindings wsdlLocation="..."
+                                xmlns:xs="http://www.w3.org/2001/XMLSchema"
+                                xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
+                                xmlns:jaxws="http://java.sun.com/xml/ns/jaxws"
+                                xmlns:jaxb="http://java.sun.com/xml/ns/jaxb">
+
+                    <!-- Customize the generated SEI class name -->
+                    <jaxws:bindings node="wsdl:definitions/wsdl:portType[@name='Hello']">
+                        <jaxws:class name="HelloWorld"/>
+                    </jaxws:bindings>
+
+                    <!-- customize the generated Service class name -->
+                    <jaxws:bindings node="wsdl:definitions/wsdl:service[@name='Hello']">
+                        <jaxws:class name="CustomService"/>
+                    </jaxws:bindings>
+
+                    <!-- customize the generated fault class name -->
+                    <jaxws:bindings
+                            node="wsdl:definitions/wsdl:portType[@name='Hello']/wsdl:operation[@name='Foo']/wsdl:fault[@name='FooFault']">
+                        <jaxws:class name="FooException"/>
+                    </jaxws:bindings>
+                </jaxws:bindings>
+            </xs:documentation>
+        </xs:annotation>
+        <xs:complexType>
+            <xs:complexContent>
+                <xs:extension base="jaxws:tJavaDoc">
+                    <xs:attribute name="name" type="xs:string" use="required"/>
+                </xs:extension>
+            </xs:complexContent>
+        </xs:complexType>
+    </xs:element>
+
+    <xs:element name="method">
+        <xs:annotation>
+            <xs:documentation>
+                Customizes the name of Java method in the generated classes.
+
+                Scope:
+                wsd;portType/wsdl:operation - name of Java methods corresponding to wsdl:operation
+                wsdl:service/wsdl:port - Name of the port getter in the generated Service class
+
+                Example:
+
+                <jaxws:bindings wsdlLocation="..."
+                                xmlns:xs="http://www.w3.org/2001/XMLSchema"
+                                xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
+                                xmlns:jaxws="http://java.sun.com/xml/ns/jaxws"
+                                xmlns:jaxb="http://java.sun.com/xml/ns/jaxb">
+
+                    <!-- Renames Java method from hello() to helloWorld() -->
+                    <jaxws:bindings node="wsdl:definitions/wsdl:portType[@name='Hello']/wsdl:operation[@name='Hello']">
+                        <jaxws:class name="helloWorld"/>
+                    </jaxws:bindings>
+
+                    <!-- Renames the generated port getter method form getHelloPort(), which is default for "HelloPort",
+                     to getCustomizedPort -->
+                    <jaxws:bindings node="wsdl:definitions/wsdl:service[@name='Hello']/wsdl:port[@name='HelloPort']">
+                        <jaxws:method name="getCustomizedPort"/>
+                    </jaxws:bindings>
+
+                </jaxws:bindings>
+            </xs:documentation>
+        </xs:annotation>
+
+        <xs:complexType>
+            <xs:complexContent>
+                <xs:extension base="jaxws:tJavaDoc">
+                    <xs:attribute name="name" type="xs:string" use="required"/>
+                </xs:extension>
+            </xs:complexContent>
+        </xs:complexType>
+    </xs:element>
+
+    <xs:element name="parameter">
+        <xs:annotation>
+            <xs:documentation>
+                Customizes the name of the Java method parameters in the generated SEI.
+
+                Scope:
+                wsd;portType/wsdl:operation
+                wsdl:binding/wsdl:operation To rename wsdl:header (additional header parameters, this support is
+                optional as JAX-WS 2.1 spec makes additional header mapping optional.
+                Example:
+
+                <jaxws:bindings wsdlLocation="..."
+                                xmlns:xs="http://www.w3.org/2001/XMLSchema"
+                                xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
+                                xmlns:jaxws="http://java.sun.com/xml/ns/jaxws"
+                                xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
+                                xmlns:types1="urn:test:types">
+
+                    <!-- Rename a wrapper child parameter 'argument' to 'helloArgument'-->
+                    <jaxws:bindings node="wsdl:definitions/wsdl:portType[@name='Hello']/wsdl:operation[@name='Hello']">
+                        <jaxws:parameter
+                                part="wsdl:definitions/wsdl:message[@name='HelloRequest']/wsdl:part[@name='parameters']"
+                                childElementName="types1:argument" name="helloArgument"/>
+                    </jaxws:bindings>
+
+                    <!-- Rename a BARE parameter 'in' to 'fooRequest'-->
+                    <jaxws:bindings node="wsdl:definitions/wsdl:portType[@name='Hello']/wsdl:operation[@name='Foo']">
+                        <jaxws:enableWrapperStyle>false</jaxws:enableWrapperStyle>
+                        <jaxws:parameter part="wsdl:definitions/wsdl:message[@name='FooRequest']/wsdl:part[@name='in']"
+                                         name="fooRequest"/>
+                    </jaxws:bindings>
+                </jaxws:bindings>
+
+            </xs:documentation>
+        </xs:annotation>
+        <xs:complexType>
+            <xs:attribute name="part" type="xs:string" use="required">
+                <xs:annotation>
+                    <xs:documentation>
+                        A XPath expression identifying a wsdl:part child of a wsdl:message.
+                    </xs:documentation>
+                </xs:annotation>
+            </xs:attribute>
+            <xs:attribute name="childElementName" type="xs:QName" use="optional">
+                <xs:annotation>
+                    <xs:documentation>
+                        The qualified name of a child element information item of the global type definition or global
+                        element declaration referred to by the wsdl:part identified by the previous attribute. It is
+                        optional and you need it only to rename parameters corresponding to wrapper style operation.
+                    </xs:documentation>
+                </xs:annotation>
+            </xs:attribute>
+            <xs:attribute name="name" type="xs:string" use="required">
+                <xs:annotation>
+                    <xs:documentation>
+                        The name of the Java formal parameter corresponding to the parameter identified by the previous
+                        two attributes.
+                    </xs:documentation>
+                </xs:annotation>
+            </xs:attribute>
+        </xs:complexType>
+    </xs:element>
+
+    <xs:element name="provider">
+        <xs:annotation>
+            <xs:documentation>
+                This binding declaration specifies that the annotated port will be used with the
+                javax.xml.ws.Provider interface.
+            </xs:documentation>
+        </xs:annotation>
+    </xs:element>
+
+</xs:schema>
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java	Mon Nov 27 17:04:45 2017 +0000
@@ -3918,6 +3918,8 @@
                     todo = todo.tail;
                     if (current == whatPackage.modle)
                         return ; //OK
+                    if ((current.flags() & Flags.AUTOMATIC_MODULE) != 0)
+                        continue; //for automatic modules, don't look into their dependencies
                     for (RequiresDirective req : current.requires) {
                         if (req.isTransitive()) {
                             todo = todo.prepend(req.module);
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java	Mon Nov 27 17:04:45 2017 +0000
@@ -2269,17 +2269,22 @@
 
             /**
              * Erasure destroys the implementation parameter subtype
-             * relationship for intersection types
+             * relationship for intersection types.
+             * Have similar problems for union types too.
              */
-            boolean interfaceParameterIsIntersectionType() {
+            boolean interfaceParameterIsIntersectionOrUnionType() {
                 List<Type> tl = tree.getDescriptorType(types).getParameterTypes();
                 for (; tl.nonEmpty(); tl = tl.tail) {
                     Type pt = tl.head;
-                    if (pt.getKind() == TypeKind.TYPEVAR) {
-                        TypeVar tv = (TypeVar) pt;
-                        if (tv.bound.getKind() == TypeKind.INTERSECTION) {
+                    switch (pt.getKind()) {
+                        case INTERSECTION:
+                        case UNION:
                             return true;
-                        }
+                        case TYPEVAR:
+                            TypeVar tv = (TypeVar) pt;
+                            if (tv.bound.getKind() == TypeKind.INTERSECTION) {
+                                return true;
+                            }
                     }
                 }
                 return false;
@@ -2290,7 +2295,7 @@
              * (i.e. var args need to be expanded or "super" is used)
              */
             final boolean needsConversionToLambda() {
-                return interfaceParameterIsIntersectionType() ||
+                return interfaceParameterIsIntersectionOrUnionType() ||
                         isSuper ||
                         needsVarArgsConversion() ||
                         isArrayOp() ||
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java	Mon Nov 27 17:04:45 2017 +0000
@@ -3226,7 +3226,7 @@
             JCVariableDecl indexdef = make.VarDef(index, make.Literal(INT, 0));
             indexdef.init.type = indexdef.type = syms.intType.constType(0);
 
-            List<JCStatement> loopinit = List.of(arraycachedef, lencachedef, indexdef);
+            List<JCStatement> loopinit = List.of(lencachedef, indexdef);
             JCBinary cond = makeBinary(LT, make.Ident(index), make.Ident(lencache));
 
             JCExpressionStatement step = make.Exec(makeUnary(PREINC, make.Ident(index)));
@@ -3236,18 +3236,27 @@
                                                     make.Ident(index)).setType(elemtype);
             JCVariableDecl loopvardef = (JCVariableDecl)make.VarDef(tree.var.mods,
                                                   tree.var.name,
-                                                  tree.var.vartype,
-                                                  loopvarinit).setType(tree.var.type);
+                                                  tree.var.vartype, null).setType(tree.var.type);
             loopvardef.sym = tree.var.sym;
+
+            JCStatement loopVarAssign = make.Assignment(tree.var.sym, loopvarinit);
             JCBlock body = make.
-                Block(0, List.of(loopvardef, tree.body));
-
+                Block(0, List.of(loopVarAssign, tree.body));
+
+            arraycachedef = translate(arraycachedef);
             result = translate(make.
                                ForLoop(loopinit,
                                        cond,
                                        List.of(step),
                                        body));
             patchTargets(body, tree, result);
+            JCStatement nullAssignToArr = make.Assignment(arraycache, make.Literal(BOT, null).setType(syms.botType));
+            JCStatement nullAssignToLoopVar = tree.var.type.isPrimitive() ?
+                    null :
+                    make.Assignment(tree.var.sym, make.Literal(BOT, null).setType(syms.botType));
+            result = nullAssignToLoopVar == null ?
+                    make.Block(0, List.of(arraycachedef, loopvardef, (JCStatement)result, nullAssignToArr)):
+                    make.Block(0, List.of(arraycachedef, loopvardef, (JCStatement)result, nullAssignToArr, nullAssignToLoopVar));
         }
         /** Patch up break and continue targets. */
         private void patchTargets(JCTree body, final JCTree src, final JCTree dest) {
@@ -3322,16 +3331,25 @@
             JCVariableDecl indexDef = (JCVariableDecl)make.VarDef(tree.var.mods,
                                                   tree.var.name,
                                                   tree.var.vartype,
-                                                  vardefinit).setType(tree.var.type);
+                                                  null).setType(tree.var.type);
             indexDef.sym = tree.var.sym;
-            JCBlock body = make.Block(0, List.of(indexDef, tree.body));
+            JCStatement loopVarAssign = make.Assignment(tree.var.sym, vardefinit);
+            JCBlock body = make.Block(0, List.of(loopVarAssign, tree.body));
             body.endpos = TreeInfo.endPos(tree.body);
+            init = translate(init);
             result = translate(make.
-                ForLoop(List.of(init),
+                ForLoop(List.nil(),
                         cond,
                         List.nil(),
                         body));
             patchTargets(body, tree, result);
+            JCStatement nullAssignToIterator = make.Assignment(itvar, make.Literal(BOT, null).setType(syms.botType));
+            JCStatement nullAssignToLoopVar = tree.var.type.isPrimitive() ?
+                    null :
+                    make.Assignment(tree.var.sym, make.Literal(BOT, null).setType(syms.botType));
+            result = nullAssignToLoopVar == null ?
+                    make.Block(0, List.of(init, indexDef, (JCStatement)result, nullAssignToIterator)):
+                    make.Block(0, List.of(init, indexDef, (JCStatement)result, nullAssignToIterator, nullAssignToLoopVar));
         }
 
     public void visitVarDef(JCVariableDecl tree) {
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransTypes.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransTypes.java	Mon Nov 27 17:04:45 2017 +0000
@@ -253,8 +253,7 @@
                    boolean hypothetical,
                    ListBuffer<JCTree> bridges) {
         make.at(pos);
-        Type origType = types.memberType(origin.type, meth);
-        Type origErasure = erasure(origType);
+        Type implTypeErasure = erasure(impl.type);
 
         // Create a bridge method symbol and a bridge definition without a body.
         Type bridgeType = meth.erasure(types);
@@ -281,7 +280,7 @@
                 : make.Super(types.supertype(origin.type).tsym.erasure(types), origin);
 
             // The type returned from the original method.
-            Type calltype = erasure(impl.type.getReturnType());
+            Type calltype = implTypeErasure.getReturnType();
 
             // Construct a call of  this.impl(params), or super.impl(params),
             // casting params and possibly results as needed.
@@ -289,9 +288,9 @@
                 make.Apply(
                            null,
                            make.Select(receiver, impl).setType(calltype),
-                           translateArgs(make.Idents(md.params), origErasure.getParameterTypes(), null))
+                           translateArgs(make.Idents(md.params), implTypeErasure.getParameterTypes(), null))
                 .setType(calltype);
-            JCStatement stat = (origErasure.getReturnType().hasTag(VOID))
+            JCStatement stat = (implTypeErasure.getReturnType().hasTag(VOID))
                 ? make.Exec(call)
                 : make.Return(coerce(call, bridgeType.getReturnType()));
             md.body = make.Block(0, List.of(stat));
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/Oop.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/Oop.java	Mon Nov 27 17:04:45 2017 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2017, 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
@@ -202,8 +202,7 @@
 
   public boolean verify() { return true;}
 
-  // Package-private routine to speed up ObjectHeap.newOop
-  static Klass getKlassForOopHandle(OopHandle handle) {
+  public static Klass getKlassForOopHandle(OopHandle handle) {
     if (handle == null) {
       return null;
     }
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/java_lang_Class.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/java_lang_Class.java	Mon Nov 27 17:04:45 2017 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2017, 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
@@ -41,6 +41,7 @@
 
   // java.lang.Class fields
   static int klassOffset;
+  static int arrayKlassOffset;
   static IntField oopSizeField;
 
   static {
@@ -56,6 +57,7 @@
     // find them from InstanceKlass for java.lang.Class.
     Type jlc = db.lookupType("java_lang_Class");
     klassOffset = (int) jlc.getCIntegerField("_klass_offset").getValue();
+    arrayKlassOffset = (int) jlc.getCIntegerField("_array_klass_offset").getValue();
     int oopSizeOffset = (int) jlc.getCIntegerField("_oop_size_offset").getValue();
     oopSizeField = new IntField(new NamedFieldIdentifier("oop_size"), oopSizeOffset, true);
   }
@@ -69,4 +71,23 @@
   public static long getOopSize(Oop aClass) {
     return java_lang_Class.oopSizeField.getValue(aClass);
   }
+
+  /**
+   * Returns the Java name for this Java mirror
+   */
+  public static String asExternalName(Oop aClass) {
+    Klass k = java_lang_Class.asKlass(aClass);
+    if (k == null) { // primitive array
+      BasicType type = BasicType.T_VOID;
+      ArrayKlass ak = (ArrayKlass)Metadata.instantiateWrapperFor(
+                             aClass.getHandle().getAddressAt(arrayKlassOffset));
+      if (ak != null) {
+        type = BasicType.intToBasicType(ak.getElementType());
+      }
+      return type.getName();
+    } else {
+      return k.getName().asString();
+    }
+  }
+
 }
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/BasicType.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/BasicType.java	Mon Nov 27 17:04:45 2017 +0000
@@ -133,6 +133,27 @@
     return tIllegal;
   }
 
+  public static BasicType intToBasicType(int i) {
+    switch(i) {
+      case tBoolean:     return T_BOOLEAN;
+      case tChar:        return T_CHAR;
+      case tFloat:       return T_FLOAT;
+      case tDouble:      return T_DOUBLE;
+      case tByte:        return T_BYTE;
+      case tShort:       return T_SHORT;
+      case tInt:         return T_INT;
+      case tLong:        return T_LONG;
+      case tObject:      return T_OBJECT;
+      case tArray:       return T_ARRAY;
+      case tVoid:        return T_VOID;
+      case tAddress:     return T_ADDRESS;
+      case tNarrowOop:   return T_NARROWOOP;
+      case tMetadata:    return T_METADATA;
+      case tNarrowKlass: return T_NARROWKLASS;
+      default:           return T_ILLEGAL;
+    }
+  }
+
   public static BasicType charToBasicType(char c) {
     switch( c ) {
     case 'B': return T_BYTE;
@@ -158,6 +179,28 @@
     return type;
   }
 
+  public String getName() {
+    switch (type) {
+      case tBoolean:     return "boolean";
+      case tChar:        return "char";
+      case tFloat:       return "float";
+      case tDouble:      return "double";
+      case tByte:        return "byte";
+      case tShort:       return "short";
+      case tInt:         return "int";
+      case tLong:        return "long";
+      case tObject:      return "object";
+      case tArray:       return "array";
+      case tVoid:        return "void";
+      case tAddress:     return "address";
+      case tNarrowOop:   return "narrow oop";
+      case tMetadata:    return "metadata";
+      case tNarrowKlass: return "narrow klass";
+      case tConflict:    return "conflict";
+      default:           return "ILLEGAL TYPE";
+    }
+  }
+
   //-- Internals only below this point
   private BasicType(int type) {
     this.type = type;
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/CompiledVFrame.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/CompiledVFrame.java	Mon Nov 27 17:04:45 2017 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2017, 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
@@ -127,12 +127,12 @@
   }
 
   /** Returns List<MonitorInfo> */
-  public List   getMonitors() {
+  public List<MonitorInfo> getMonitors() {
     List monitors = getScope().getMonitors();
     if (monitors == null) {
-      return new ArrayList();
+      return new ArrayList<>();
     }
-    List result = new ArrayList(monitors.size());
+    List<MonitorInfo> result = new ArrayList<>(monitors.size());
     for (int i = 0; i < monitors.size(); i++) {
       MonitorValue mv = (MonitorValue) monitors.get(i);
       ScopeValue ov = mv.owner();
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/InterpretedVFrame.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/InterpretedVFrame.java	Mon Nov 27 17:04:45 2017 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2017, 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
@@ -108,8 +108,8 @@
   }
 
   /** Returns List<MonitorInfo> */
-  public List   getMonitors() {
-    List result = new ArrayList(5);
+  public List<MonitorInfo> getMonitors() {
+    List<MonitorInfo> result = new ArrayList<>(5);
     for (BasicObjectLock current = getFrame().interpreterFrameMonitorEnd();
          current.address().lessThan(getFrame().interpreterFrameMonitorBegin().address());
          current = getFrame().nextMonitorInInterpreterFrame(current)) {
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/JavaVFrame.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/JavaVFrame.java	Mon Nov 27 17:04:45 2017 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2017, 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,14 +28,19 @@
 import java.util.*;
 import sun.jvm.hotspot.oops.*;
 import sun.jvm.hotspot.utilities.*;
+import sun.jvm.hotspot.debugger.*;
 
 public abstract class JavaVFrame extends VFrame {
+
+  private static final String ADDRESS_FORMAT = VM.getVM().isLP64() ? "0x%016x"
+                                                                   : "0x%08x";
+
   /** JVM state */
   public abstract Method getMethod();
   public abstract int    getBCI();
   public abstract StackValueCollection getLocals();
   public abstract StackValueCollection getExpressions();
-  public abstract List   getMonitors();    // List<MonitorInfo>
+  public abstract List<MonitorInfo> getMonitors();
 
   /** Test operation */
   public boolean isJavaFrame() { return true; }
@@ -49,9 +54,112 @@
   // FIXME: not yet implemented
   //  public Address getPendingMonitor(int frameCount);
 
+  public void printLockedObjectClassName(PrintStream tty,
+                                         OopHandle hobj, String lockState) {
+    if (hobj.asLongValue() != 0L) {
+      tty.format("\t- %s <" + ADDRESS_FORMAT + "> ",
+                 lockState, hobj.asLongValue());
+
+      Klass klass = Oop.getKlassForOopHandle(hobj);
+      String klassName = klass.getName().asString();
+      tty.print("(a ");
+      if (klassName.equals("java/lang/Class")) {
+        Oop obj = VM.getVM().getObjectHeap().newOop(hobj);
+        klassName = java_lang_Class.asExternalName(obj);
+        tty.print("java.lang.Class for ");
+      }
+      tty.println(klassName.replace('/', '.') + ")");
+    }
+  }
+
+  private String identifyLockState(MonitorInfo monitor, String waitingState) {
+    Mark mark = new Mark(monitor.owner());
+    if (mark.hasMonitor() &&
+        ( // we have marked ourself as pending on this monitor
+          mark.monitor().equals(thread.getCurrentPendingMonitor()) ||
+          // we are not the owner of this monitor
+          !mark.monitor().isEntered(thread)
+        )) {
+      return waitingState;
+    }
+    return "locked";
+  }
+
   /** Printing used during stack dumps */
-  // FIXME: not yet implemented
-  //  void print_lock_info(int frame_count);
+  public void printLockInfo(PrintStream tty, int frameCount) {
+    // If this is the first frame and it is java.lang.Object.wait(...)
+    // then print out the receiver. Locals are not always available,
+    // e.g., compiled native frames have no scope so there are no locals.
+    if (frameCount == 0) {
+      if (getMethod().getName().asString().equals("wait") &&
+          getMethod().getMethodHolder().getName().asString().equals("java/lang/Object")) {
+        String waitState = "waiting on"; // assume we are waiting
+        // If earlier in the output we reported java.lang.Thread.State ==
+        // "WAITING (on object monitor)" and now we report "waiting on", then
+        // we are still waiting for notification or timeout. Otherwise if
+        // we earlier reported java.lang.Thread.State == "BLOCKED (on object
+        // monitor)", then we are actually waiting to re-lock the monitor.
+        // At this level we can't distinguish the two cases to report
+        // "waited on" rather than "waiting on" for the second case.
+        StackValueCollection locs = getLocals();
+        if (!locs.isEmpty()) {
+          StackValue sv = locs.get(0);
+          if (sv.getType() == BasicType.getTObject()) {
+            OopHandle o = sv.getObject();
+            printLockedObjectClassName(tty, o, waitState);
+          }
+        } else {
+          tty.println("\t- " + waitState + " <no object reference available>");
+        }
+      } else if (thread.getCurrentParkBlocker() != null) {
+        Oop obj = thread.getCurrentParkBlocker();
+        Klass k = obj.getKlass();
+        tty.format("\t- parking to wait for <" + ADDRESS_FORMAT + "> (a %s)",
+                   obj.getHandle().asLongValue(), k.getName().asString());
+        tty.println();
+      }
+    }
+
+    // Print out all monitors that we have locked, or are trying to lock,
+    // including re-locking after being notified or timing out in a wait().
+    List<MonitorInfo> mons = getMonitors();
+    if (!mons.isEmpty()) {
+      boolean foundFirstMonitor = false;
+      for (int index = mons.size() - 1; index >= 0; index--) {
+        MonitorInfo monitor = mons.get(index);
+        if (monitor.eliminated() && isCompiledFrame()) { // Eliminated in compiled code
+          if (monitor.ownerIsScalarReplaced()) {
+            Klass k = Oop.getKlassForOopHandle(monitor.ownerKlass());
+            tty.println("\t- eliminated <owner is scalar replaced> (a " + k.getName().asString() + ")");
+          } else if (monitor.owner() != null) {
+            printLockedObjectClassName(tty, monitor.owner(), "eliminated");
+          }
+          continue;
+        }
+        if (monitor.owner() != null) {
+          // the monitor is associated with an object, i.e., it is locked
+          String lockState = "locked";
+          if (!foundFirstMonitor && frameCount == 0) {
+            // If this is the first frame and we haven't found an owned
+            // monitor before, then we need to see if we have completed
+            // the lock or if we are blocked trying to acquire it. Only
+            // an inflated monitor that is first on the monitor list in
+            // the first frame can block us on a monitor enter.
+            lockState = identifyLockState(monitor, "waiting to lock");
+          } else if (frameCount != 0) {
+            // This is not the first frame so we either own this monitor
+            // or we owned the monitor before and called wait(). Because
+            // wait() could have been called on any monitor in a lower
+            // numbered frame on the stack, we have to check all the
+            // monitors on the list for this frame.
+            lockState = identifyLockState(monitor, "waiting to re-lock in wait()");
+          }
+          printLockedObjectClassName(tty, monitor.owner(), lockState);
+          foundFirstMonitor = true;
+        }
+      }
+    }
+  }
 
   /** Printing operations */
 
@@ -73,22 +181,6 @@
 
     printStackValuesOn(tty, "locals",      getLocals());
     printStackValuesOn(tty, "expressions", getExpressions());
-
-    // List<MonitorInfo>
-    // FIXME: not yet implemented
-    //    List list = getMonitors();
-    //    if (list.isEmpty()) {
-    //      return;
-    //    }
-    //    for (int index = 0; index < list.size(); index++) {
-    //      MonitorInfo monitor = (MonitorInfo) list.get(index);
-    //      tty.print("\t  obj\t");
-    //      monitor.getOwner().printValueOn(tty);
-    //      tty.println();
-    //      tty.print("\t  ");
-    //      monitor.lock().printOn(tty);
-    //      tty.println();
-    //    }
   }
 
   public void printActivation(int index) {
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/StackTrace.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/StackTrace.java	Mon Nov 27 17:04:45 2017 +0000
@@ -76,6 +76,8 @@
                 if (cur.isJavaThread()) {
                     cur.printThreadInfoOn(tty);
                     try {
+                        int count = 0;
+
                         for (JavaVFrame vf = cur.getLastJavaVFrameDbg(); vf != null; vf = vf.javaSender()) {
                             Method method = vf.getMethod();
                             tty.print(" - " + method.externalNameAndSignature() +
@@ -109,6 +111,7 @@
                             }
 
                             tty.println(")");
+                            vf.printLockInfo(tty, count++);
                         }
                     } catch (Exception e) {
                         tty.println("Error occurred during stack walking:");
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ui/classbrowser/HTMLGenerator.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ui/classbrowser/HTMLGenerator.java	Mon Nov 27 17:04:45 2017 +0000
@@ -1910,6 +1910,7 @@
       buf.append(thread.getThreadState().toString());
       buf.br();
       buf.beginTag("pre");
+      int count = 0;
       for (JavaVFrame vf = thread.getLastJavaVFrameDbg(); vf != null; vf = vf.javaSender()) {
          Method method = vf.getMethod();
          buf.append(" - ");
@@ -1954,6 +1955,19 @@
          }
          buf.append(")");
          buf.br();
+
+         ByteArrayOutputStream bytes = new ByteArrayOutputStream();
+         PrintStream printStream = new PrintStream(bytes);
+         try (printStream) {
+             vf.printLockInfo(printStream, count++);
+             for (String line : bytes.toString().split("\n")) {
+                 if (genHTML) {
+                     line = line.replace("<", "&lt;").replace(">", "&gt;");
+                 }
+                 buf.append(line);
+                 buf.br();
+             }
+         }
       }
 
       buf.endTag("pre");
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractExecutableMemberWriter.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractExecutableMemberWriter.java	Mon Nov 27 17:04:45 2017 +0000
@@ -358,6 +358,6 @@
             }
         }
         buf.append(")");
-        return foundTypeVariable ? writer.getName(buf.toString()) : null;
+        return foundTypeVariable ? configuration.links.getName(buf.toString()) : null;
     }
 }
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractIndexWriter.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractIndexWriter.java	Mon Nov 27 17:04:45 2017 +0000
@@ -222,6 +222,7 @@
      *
      * @param mdle the module to be documented
      * @param dlTree the content tree to which the description will be added
+     * @param si the search index item
      */
     protected void addDescription(ModuleElement mdle, Content dlTree, SearchIndexItem si) {
         String moduleName = utils.getFullyQualifiedName(mdle);
@@ -316,7 +317,7 @@
             name = name + utils.flatSignature(ee);
             si.setLabel(name);
             if (!((utils.signature(ee)).equals(utils.flatSignature(ee)))) {
-                si.setUrl(getName(getAnchor(ee)));
+                si.setUrl(links.getName(getAnchor(ee)));
             }
 
         }  else {
@@ -364,7 +365,7 @@
         List<? extends DocTree> tags;
         Content span = HtmlTree.SPAN(HtmlStyle.deprecatedLabel, getDeprecatedPhrase(element));
         HtmlTree div = new HtmlTree(HtmlTag.DIV);
-        div.addStyle(HtmlStyle.deprecationBlock);
+        div.setStyle(HtmlStyle.deprecationBlock);
         if (utils.isDeprecated(element)) {
             div.addContent(span);
             tags = utils.getBlockTags(element, DocTree.Kind.DEPRECATED);
@@ -420,7 +421,7 @@
      * @return a content tree for the marker anchor
      */
     public Content getMarkerAnchorForIndex(String anchorNameForIndex) {
-        return getMarkerAnchor(getNameForIndex(anchorNameForIndex), null);
+        return links.createAnchor(getNameForIndex(anchorNameForIndex), null);
     }
 
     /**
@@ -430,7 +431,7 @@
      * @return a valid HTML name string.
      */
     public String getNameForIndex(String unicode) {
-        return "I:" + getName(unicode);
+        return "I:" + links.getName(unicode);
     }
 
     /**
@@ -452,6 +453,13 @@
     }
 
     /**
+     * Creates a search index file.
+     *
+     * @param searchIndexFile   the file to be generated
+     * @param searchIndexZip    the zip file to be generated
+     * @param searchIndexJS     the file for the JavaScript to be generated
+     * @param searchIndex       the search index items
+     * @param varName           the variable name to write in the JavaScript file
      * @throws DocFileIOException if there is a problem creating the search index file
      */
     protected void createSearchIndexFile(DocPath searchIndexFile, DocPath searchIndexZip,
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractMemberWriter.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractMemberWriter.java	Mon Nov 27 17:04:45 2017 +0000
@@ -25,6 +25,9 @@
 
 package jdk.javadoc.internal.doclets.formats.html;
 
+import jdk.javadoc.internal.doclets.formats.html.markup.Table;
+import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader;
+
 import java.util.*;
 import java.util.stream.Collectors;
 
@@ -36,17 +39,17 @@
 import javax.lang.model.type.TypeMirror;
 
 import com.sun.source.doctree.DocTree;
-import jdk.javadoc.internal.doclets.formats.html.markup.HtmlAttr;
+import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlConstants;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
+import jdk.javadoc.internal.doclets.formats.html.markup.Links;
 import jdk.javadoc.internal.doclets.formats.html.markup.StringContent;
 import jdk.javadoc.internal.doclets.toolkit.Content;
 import jdk.javadoc.internal.doclets.toolkit.MemberSummaryWriter;
 import jdk.javadoc.internal.doclets.toolkit.Resources;
 import jdk.javadoc.internal.doclets.toolkit.taglets.DeprecatedTaglet;
-import jdk.javadoc.internal.doclets.toolkit.util.MethodTypes;
 import jdk.javadoc.internal.doclets.toolkit.util.Utils;
 import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberMap;
 
@@ -72,11 +75,9 @@
     protected final SubWriterHolderWriter writer;
     protected final Contents contents;
     protected final Resources resources;
+    protected final Links links;
 
     protected final TypeElement typeElement;
-    protected Map<String, Integer> typeMap = new LinkedHashMap<>();
-    protected Set<MethodTypes> methodTypes = EnumSet.noneOf(MethodTypes.class);
-    private int methodTypesOr = 0;
     public final boolean nodepr;
 
     protected boolean printedSummaryHeader = false;
@@ -89,6 +90,7 @@
         this.utils = configuration.utils;
         this.contents = configuration.contents;
         this.resources = configuration.resources;
+        this.links = configuration.links;
     }
 
     public AbstractMemberWriter(SubWriterHolderWriter writer) {
@@ -109,14 +111,7 @@
      *
      * @return a string for the table summary
      */
-    public abstract String getTableSummary();
-
-    /**
-     * Get the caption for the member summary table.
-     *
-     * @return a string for the table caption
-     */
-    public abstract Content getCaption();
+    private String getTableSummaryX() { return null; }
 
     /**
      * Get the summary table header for the member.
@@ -126,6 +121,27 @@
      */
     public abstract TableHeader getSummaryTableHeader(Element member);
 
+    private Table summaryTable;
+
+    private Table getSummaryTable() {
+        if (summaryTable == null) {
+            summaryTable = createSummaryTable();
+        }
+        return summaryTable;
+    }
+
+    /**
+     * Create the summary table for this element.
+     * The table should be created and initialized if needed, and configured
+     * so that it is ready to add content with {@link Table#addRows(Content[])}
+     * and similar methods.
+     *
+     * @return the summary table
+     */
+    protected abstract Table createSummaryTable();
+
+
+
     /**
      * Add inherited summary label for the member.
      *
@@ -229,7 +245,7 @@
      * Add the modifier for the member. The modifiers are ordered as specified
      * by <em>The Java Language Specification</em>.
      *
-     * @param member the member for which teh modifier will be added.
+     * @param member the member for which the modifier will be added.
      * @param htmltree the content tree to which the modifier information will be added.
      */
     protected void addModifiers(Element member, Content htmltree) {
@@ -420,51 +436,41 @@
         List<? extends Element> members = mems;
         boolean printedUseTableHeader = false;
         if (members.size() > 0) {
-            Content caption = writer.getTableCaption(heading);
-            Content table = (configuration.isOutputHtml5())
-                    ? HtmlTree.TABLE(HtmlStyle.useSummary, caption)
-                    : HtmlTree.TABLE(HtmlStyle.useSummary, tableSummary, caption);
-            Content tbody = new HtmlTree(HtmlTag.TBODY);
-            boolean altColor = true;
+            Table useTable = new Table(configuration.htmlVersion, HtmlStyle.useSummary)
+                    .setSummary(tableSummary)
+                    .setCaption(heading)
+                    .setRowScopeColumn(1)
+                    .setColumnStyles(HtmlStyle.colFirst, HtmlStyle.colSecond, HtmlStyle.colLast);
             for (Element element : members) {
-                TypeElement te = utils.getEnclosingTypeElement(element);
+                TypeElement te = (typeElement == null)
+                        ? utils.getEnclosingTypeElement(element)
+                        : typeElement;
                 if (!printedUseTableHeader) {
-                    table.addContent(getSummaryTableHeader(element).toContent());
+                    useTable.setHeader(getSummaryTableHeader(element));
                     printedUseTableHeader = true;
                 }
-                HtmlTree tr = new HtmlTree(HtmlTag.TR);
-                tr.addStyle(altColor ? HtmlStyle.altColor : HtmlStyle.rowColor);
-                altColor = !altColor;
-                HtmlTree tdFirst = new HtmlTree(HtmlTag.TD);
-                tdFirst.addStyle(HtmlStyle.colFirst);
-                writer.addSummaryType(this, element, tdFirst);
-                tr.addContent(tdFirst);
-                HtmlTree thType = new HtmlTree(HtmlTag.TH);
-                thType.addStyle(HtmlStyle.colSecond);
-                thType.addAttr(HtmlAttr.SCOPE, "row");
+                Content summaryType = new ContentBuilder();
+                addSummaryType(element, summaryType);
+                Content typeContent = new ContentBuilder();
                 if (te != null
                         && !utils.isConstructor(element)
                         && !utils.isClass(element)
                         && !utils.isInterface(element)
                         && !utils.isAnnotationType(element)) {
                     HtmlTree name = new HtmlTree(HtmlTag.SPAN);
-                    name.addStyle(HtmlStyle.typeNameLabel);
+                    name.setStyle(HtmlStyle.typeNameLabel);
                     name.addContent(name(te) + ".");
-                    thType.addContent(name);
+                    typeContent.addContent(name);
                 }
                 addSummaryLink(utils.isClass(element) || utils.isInterface(element)
                         ? LinkInfoImpl.Kind.CLASS_USE
                         : LinkInfoImpl.Kind.MEMBER,
-                        te, element, thType);
-                tr.addContent(thType);
-                HtmlTree tdDesc = new HtmlTree(HtmlTag.TD);
-                tdDesc.addStyle(HtmlStyle.colLast);
-                writer.addSummaryLinkComment(this, element, tdDesc);
-                tr.addContent(tdDesc);
-                tbody.addContent(tr);
+                        te, element, typeContent);
+                Content desc = new ContentBuilder();
+                writer.addSummaryLinkComment(this, element, desc);
+                useTable.addRow(summaryType, typeContent, desc);
             }
-            table.addContent(tbody);
-            contentTree.addContent(table);
+            contentTree.addContent(useTable.toContent());
         }
     }
 
@@ -515,81 +521,26 @@
      * @param tElement the class that is being documented
      * @param member the member being documented
      * @param firstSentenceTags the first sentence tags to be added to the summary
-     * @param tableContents the list of contents to which the documentation will be added
-     * @param counter the counter for determining id and style for the table row
      */
+    @Override
     public void addMemberSummary(TypeElement tElement, Element member,
-            List<? extends DocTree> firstSentenceTags, List<Content> tableContents, int counter,
-            VisibleMemberMap.Kind vmmKind) {
-        HtmlTree tdSummaryType = new HtmlTree(HtmlTag.TD);
-        tdSummaryType.addStyle(HtmlStyle.colFirst);
-        writer.addSummaryType(this, member, tdSummaryType);
-        HtmlTree tr = HtmlTree.TR(tdSummaryType);
-        HtmlTree thSummaryLink = new HtmlTree(HtmlTag.TH);
-        setSummaryColumnStyleAndScope(thSummaryLink);
-        addSummaryLink(tElement, member, thSummaryLink);
-        tr.addContent(thSummaryLink);
-        HtmlTree tdDesc = new HtmlTree(HtmlTag.TD);
-        tdDesc.addStyle(HtmlStyle.colLast);
-        writer.addSummaryLinkComment(this, member, firstSentenceTags, tdDesc);
-        tr.addContent(tdDesc);
-        if (utils.isMethod(member) && !utils.isAnnotationType(member)
-                && vmmKind != VisibleMemberMap.Kind.PROPERTIES) {
-            int methodType = utils.isStatic(member) ? MethodTypes.STATIC.tableTabs().value() :
-                    MethodTypes.INSTANCE.tableTabs().value();
-            if (utils.isInterface(member.getEnclosingElement())) {
-                methodType = utils.isAbstract(member)
-                        ? methodType | MethodTypes.ABSTRACT.tableTabs().value()
-                        : methodType | MethodTypes.DEFAULT.tableTabs().value();
-            } else {
-                methodType = utils.isAbstract(member)
-                        ? methodType | MethodTypes.ABSTRACT.tableTabs().value()
-                        : methodType | MethodTypes.CONCRETE.tableTabs().value();
-            }
-            if (utils.isDeprecated(member) || utils.isDeprecated(typeElement)) {
-                methodType = methodType | MethodTypes.DEPRECATED.tableTabs().value();
-            }
-            methodTypesOr = methodTypesOr | methodType;
-            String tableId = "i" + counter;
-            typeMap.put(tableId, methodType);
-            tr.addAttr(HtmlAttr.ID, tableId);
+            List<? extends DocTree> firstSentenceTags) {
+        if (tElement != typeElement) {
+            throw new IllegalStateException();
         }
-        if (counter%2 == 0)
-            tr.addStyle(HtmlStyle.altColor);
-        else
-            tr.addStyle(HtmlStyle.rowColor);
-        tableContents.add(tr);
-    }
-
-    /**
-     * Generate the method types set and return true if the method summary table
-     * needs to show tabs.
-     *
-     * @return true if the table should show tabs
-     */
-    public boolean showTabs() {
-        int value;
-        for (MethodTypes type : EnumSet.allOf(MethodTypes.class)) {
-            value = type.tableTabs().value();
-            if ((value & methodTypesOr) == value) {
-                methodTypes.add(type);
-            }
-        }
-        boolean showTabs = methodTypes.size() > 1;
-        if (showTabs) {
-            methodTypes.add(MethodTypes.ALL);
-        }
-        return showTabs;
-    }
-
-    /**
-     * Set the style and scope attribute for the summary column.
-     *
-     * @param thTree the column for which the style and scope attribute will be set
-     */
-    public void setSummaryColumnStyleAndScope(HtmlTree thTree) {
-        thTree.addStyle(HtmlStyle.colSecond);
-        thTree.addAttr(HtmlAttr.SCOPE, "row");
+        Table table = getSummaryTable();
+        List<Content> rowContents = new ArrayList<>();
+        Content summaryType = new ContentBuilder();
+        addSummaryType(member, summaryType);
+        if (!summaryType.isEmpty())
+            rowContents.add(summaryType);
+        Content summaryLink = new ContentBuilder();
+        addSummaryLink(tElement, member, summaryLink);
+        rowContents.add(summaryLink);
+        Content desc = new ContentBuilder();
+        writer.addSummaryLinkComment(this, member, firstSentenceTags, desc);
+        rowContents.add(desc);
+        table.addRow(member, rowContents);
     }
 
     /**
@@ -601,6 +552,7 @@
      * @param isLast true if this is the last member in the list
      * @param linksTree the content tree to which the summary will be added
      */
+    @Override
     public void addInheritedMemberSummary(TypeElement tElement,
             Element nestedClass, boolean isFirst, boolean isLast,
             Content linksTree) {
@@ -614,6 +566,7 @@
      * @param tElement the class the inherited member belongs to
      * @return a content tree for the inherited summary header
      */
+    @Override
     public Content getInheritedSummaryHeader(TypeElement tElement) {
         Content inheritedTree = writer.getMemberTreeHeader();
         writer.addInheritedSummaryHeader(this, tElement, inheritedTree);
@@ -625,6 +578,7 @@
      *
      * @return a content tree for the inherited summary links
      */
+    @Override
     public Content getInheritedSummaryLinksTree() {
         return new HtmlTree(HtmlTag.CODE);
     }
@@ -633,11 +587,18 @@
      * Get the summary table tree for the given class.
      *
      * @param tElement the class for which the summary table is generated
-     * @param tableContents list of contents to be displayed in the summary table
      * @return a content tree for the summary table
      */
-    public Content getSummaryTableTree(TypeElement tElement, List<Content> tableContents) {
-        return writer.getSummaryTableTree(this, tElement, tableContents, showTabs());
+    @Override
+    public Content getSummaryTableTree(TypeElement tElement) {
+        if (tElement != typeElement) {
+            throw new IllegalStateException();
+        }
+        Table table = getSummaryTable();
+        if (table.needsScript()) {
+            writer.getMainBodyScript().append(table.getScript());
+        }
+        return table.toContent();
     }
 
     /**
@@ -646,6 +607,7 @@
      * @param memberTree the content tree of member to be documented
      * @return a content tree that will be added to the class documentation
      */
+    @Override
     public Content getMemberTree(Content memberTree) {
         return writer.getMemberTree(memberTree);
     }
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractModuleIndexWriter.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractModuleIndexWriter.java	Mon Nov 27 17:04:45 2017 +0000
@@ -203,7 +203,7 @@
         HtmlTree htmlTree = (configuration.allowTag(HtmlTag.NAV))
                 ? HtmlTree.NAV()
                 : new HtmlTree(HtmlTag.DIV);
-        htmlTree.addStyle(HtmlStyle.indexNav);
+        htmlTree.setStyle(HtmlStyle.indexNav);
         HtmlTree ul = new HtmlTree(HtmlTag.UL);
         addAllClassesLink(ul);
         addAllPackagesLink(ul);
@@ -226,7 +226,7 @@
         HtmlTree htmlTree = (configuration.allowTag(HtmlTag.NAV))
                 ? HtmlTree.NAV()
                 : new HtmlTree(HtmlTag.DIV);
-        htmlTree.addStyle(HtmlStyle.indexNav);
+        htmlTree.setStyle(HtmlStyle.indexNav);
         HtmlTree ul = new HtmlTree(HtmlTag.UL);
         addAllClassesLink(ul);
         addAllPackagesLink(ul);
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractPackageIndexWriter.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractPackageIndexWriter.java	Mon Nov 27 17:04:45 2017 +0000
@@ -146,7 +146,7 @@
             HtmlTree htmlTree = (configuration.allowTag(HtmlTag.NAV))
                     ? HtmlTree.NAV()
                     : new HtmlTree(HtmlTag.DIV);
-            htmlTree.addStyle(HtmlStyle.indexNav);
+            htmlTree.setStyle(HtmlStyle.indexNav);
             HtmlTree ul = new HtmlTree(HtmlTag.UL);
             addAllClassesLink(ul);
             if (configuration.showModules  && configuration.modules.size() > 1) {
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractTreeWriter.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractTreeWriter.java	Mon Nov 27 17:04:45 2017 +0000
@@ -88,7 +88,7 @@
             Content ul = new HtmlTree(HtmlTag.UL);
             for (TypeElement local : collection) {
                 HtmlTree li = new HtmlTree(HtmlTag.LI);
-                li.addStyle(HtmlStyle.circle);
+                li.setStyle(HtmlStyle.circle);
                 addPartialInfo(local, li);
                 addExtendsImplements(parent, local, li);
                 addLevelInfo(local, classtree.directSubClasses(local, isEnum),
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeFieldWriterImpl.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeFieldWriterImpl.java	Mon Nov 27 17:04:45 2017 +0000
@@ -25,16 +25,21 @@
 
 package jdk.javadoc.internal.doclets.formats.html;
 
+import jdk.javadoc.internal.doclets.formats.html.markup.Table;
+
+import java.util.Arrays;
+
 import javax.lang.model.element.Element;
 import javax.lang.model.element.ExecutableElement;
 import javax.lang.model.element.TypeElement;
 import javax.lang.model.type.TypeMirror;
 
-import jdk.javadoc.internal.doclets.formats.html.TableHeader;
+import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlConstants;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
+import jdk.javadoc.internal.doclets.formats.html.markup.Links;
 import jdk.javadoc.internal.doclets.formats.html.markup.StringContent;
 import jdk.javadoc.internal.doclets.toolkit.AnnotationTypeFieldWriter;
 import jdk.javadoc.internal.doclets.toolkit.Content;
@@ -104,7 +109,7 @@
     public void addAnnotationDetailsTreeHeader(TypeElement typeElement,
             Content memberDetailsTree) {
         if (!writer.printedAnnotationFieldHeading) {
-            memberDetailsTree.addContent(writer.getMarkerAnchor(
+            memberDetailsTree.addContent(links.createAnchor(
                     SectionName.ANNOTATION_TYPE_FIELD_DETAIL));
             Content heading = HtmlTree.HEADING(HtmlConstants.DETAILS_HEADING,
                     contents.fieldDetailsLabel);
@@ -118,8 +123,7 @@
      */
     public Content getAnnotationDocTreeHeader(Element member,
             Content annotationDetailsTree) {
-        annotationDetailsTree.addContent(
-                writer.getMarkerAnchor(name(member)));
+        annotationDetailsTree.addContent(links.createAnchor(name(member)));
         Content annotationDocTree = writer.getMemberTreeHeader();
         Content heading = new HtmlTree(HtmlConstants.MEMBER_HEADING);
         heading.addContent(name(member));
@@ -200,51 +204,58 @@
     /**
      * {@inheritDoc}
      */
-    public String getTableSummary() {
-        return configuration.getText("doclet.Member_Table_Summary",
-                configuration.getText("doclet.Field_Summary"),
-                configuration.getText("doclet.fields"));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Content getCaption() {
-        return configuration.getContent("doclet.Fields");
-    }
-
-    /**
-     * {@inheritDoc}
-     */
     @Override
     public TableHeader getSummaryTableHeader(Element member) {
         return new TableHeader(contents.modifierAndTypeLabel, contents.fields,
                 contents.descriptionLabel);
     }
 
+    @Override
+    protected Table createSummaryTable() {
+        String summary = resources.getText("doclet.Member_Table_Summary",
+            resources.getText("doclet.Field_Summary"),
+            resources.getText("doclet.fields"));
+        Content caption = contents.getContent("doclet.Fields");
+
+        TableHeader header = new TableHeader(contents.modifierAndTypeLabel, contents.fields,
+            contents.descriptionLabel);
+
+        return new Table(configuration.htmlVersion, HtmlStyle.memberSummary)
+                .setSummary(summary)
+                .setCaption(caption)
+                .setHeader(header)
+                .setRowScopeColumn(1)
+                .setColumnStyles(HtmlStyle.colFirst, HtmlStyle.colSecond, HtmlStyle.colLast)
+                .setUseTBody(false);  // temporary? compatibility mode for TBody
+    }
+
     /**
      * {@inheritDoc}
      */
+    @Override
     public void addSummaryAnchor(TypeElement typeElement, Content memberTree) {
-        memberTree.addContent(writer.getMarkerAnchor(
+        memberTree.addContent(links.createAnchor(
                 SectionName.ANNOTATION_TYPE_FIELD_SUMMARY));
     }
 
     /**
      * {@inheritDoc}
      */
+    @Override
     public void addInheritedSummaryAnchor(TypeElement typeElement, Content inheritedTree) {
     }
 
     /**
      * {@inheritDoc}
      */
+    @Override
     public void addInheritedSummaryLabel(TypeElement typeElement, Content inheritedTree) {
     }
 
     /**
      * {@inheritDoc}
      */
+    @Override
     protected void addSummaryLink(LinkInfoImpl.Kind context, TypeElement typeElement, Element member,
             Content tdSummary) {
         Content memberLink = HtmlTree.SPAN(HtmlStyle.memberNameLink,
@@ -281,7 +292,7 @@
      */
     protected Content getNavSummaryLink(TypeElement typeElement, boolean link) {
         if (link) {
-            return writer.getHyperLink(
+            return Links.createLink(
                     SectionName.ANNOTATION_TYPE_FIELD_SUMMARY,
                     contents.navField);
         } else {
@@ -294,7 +305,7 @@
      */
     protected void addNavDetailLink(boolean link, Content liNav) {
         if (link) {
-            liNav.addContent(writer.getHyperLink(
+            liNav.addContent(Links.createLink(
                     SectionName.ANNOTATION_TYPE_FIELD_DETAIL,
                     contents.navField));
         } else {
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeOptionalMemberWriterImpl.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeOptionalMemberWriterImpl.java	Mon Nov 27 17:04:45 2017 +0000
@@ -25,17 +25,17 @@
 
 package jdk.javadoc.internal.doclets.formats.html;
 
-import java.util.Arrays;
-import java.util.List;
+
+import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader;
 
 import javax.lang.model.element.AnnotationValue;
 import javax.lang.model.element.Element;
 import javax.lang.model.element.ExecutableElement;
 import javax.lang.model.element.TypeElement;
 
-import jdk.javadoc.internal.doclets.formats.html.TableHeader;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlConstants;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
+import jdk.javadoc.internal.doclets.formats.html.markup.Links;
 import jdk.javadoc.internal.doclets.formats.html.markup.StringContent;
 import jdk.javadoc.internal.doclets.toolkit.AnnotationTypeOptionalMemberWriter;
 import jdk.javadoc.internal.doclets.toolkit.Content;
@@ -71,6 +71,7 @@
     /**
      * {@inheritDoc}
      */
+    @Override
     public Content getMemberSummaryHeader(TypeElement typeElement,
             Content memberSummaryTree) {
         memberSummaryTree.addContent(
@@ -83,6 +84,7 @@
     /**
      * {@inheritDoc}
      */
+    @Override
     public void addMemberTree(Content memberSummaryTree, Content memberTree) {
         writer.addMemberTree(memberSummaryTree, memberTree);
     }
@@ -90,6 +92,7 @@
     /**
      * {@inheritDoc}
      */
+    @Override
     public void addDefaultValueInfo(Element member, Content annotationDocTree) {
         if (utils.isAnnotationType(member)) {
             ExecutableElement ee = (ExecutableElement)member;
@@ -107,6 +110,7 @@
     /**
      * {@inheritDoc}
      */
+    @Override
     public void addSummaryLabel(Content memberTree) {
         Content label = HtmlTree.HEADING(HtmlConstants.SUMMARY_HEADING,
                 contents.annotateTypeOptionalMemberSummaryLabel);
@@ -116,7 +120,8 @@
     /**
      * {@inheritDoc}
      */
-    public String getTableSummary() {
+    @Override
+    protected String getTableSummary() {
         return resources.getText("doclet.Member_Table_Summary",
                 resources.getText("doclet.Annotation_Type_Optional_Member_Summary"),
                 resources.getText("doclet.annotation_type_optional_members"));
@@ -125,8 +130,9 @@
     /**
      * {@inheritDoc}
      */
-    public Content getCaption() {
-        return configuration.getContent("doclet.Annotation_Type_Optional_Members");
+    @Override
+    protected Content getCaption() {
+        return contents.getContent("doclet.Annotation_Type_Optional_Members");
     }
 
     /**
@@ -141,17 +147,19 @@
     /**
      * {@inheritDoc}
      */
+    @Override
     public void addSummaryAnchor(TypeElement typeElement, Content memberTree) {
-        memberTree.addContent(writer.getMarkerAnchor(
+        memberTree.addContent(links.createAnchor(
                 SectionName.ANNOTATION_TYPE_OPTIONAL_ELEMENT_SUMMARY));
     }
 
     /**
      * {@inheritDoc}
      */
+    @Override
     protected Content getNavSummaryLink(TypeElement typeElement, boolean link) {
         if (link) {
-            return writer.getHyperLink(
+            return Links.createLink(
                     SectionName.ANNOTATION_TYPE_OPTIONAL_ELEMENT_SUMMARY,
                     contents.navAnnotationTypeOptionalMember);
         } else {
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeRequiredMemberWriterImpl.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeRequiredMemberWriterImpl.java	Mon Nov 27 17:04:45 2017 +0000
@@ -25,6 +25,8 @@
 
 package jdk.javadoc.internal.doclets.formats.html;
 
+import jdk.javadoc.internal.doclets.formats.html.markup.Table;
+
 import java.util.Arrays;
 import java.util.List;
 
@@ -33,11 +35,12 @@
 import javax.lang.model.element.TypeElement;
 import javax.lang.model.type.TypeMirror;
 
-import jdk.javadoc.internal.doclets.formats.html.TableHeader;
+import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlConstants;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
+import jdk.javadoc.internal.doclets.formats.html.markup.Links;
 import jdk.javadoc.internal.doclets.formats.html.markup.StringContent;
 import jdk.javadoc.internal.doclets.toolkit.AnnotationTypeRequiredMemberWriter;
 import jdk.javadoc.internal.doclets.toolkit.Content;
@@ -108,7 +111,7 @@
     public void addAnnotationDetailsTreeHeader(TypeElement te,
             Content memberDetailsTree) {
         if (!writer.printedAnnotationHeading) {
-            memberDetailsTree.addContent(writer.getMarkerAnchor(
+            memberDetailsTree.addContent(links.createAnchor(
                     SectionName.ANNOTATION_TYPE_ELEMENT_DETAIL));
             Content heading = HtmlTree.HEADING(HtmlConstants.DETAILS_HEADING,
                     contents.annotationTypeDetailsLabel);
@@ -120,11 +123,11 @@
     /**
      * {@inheritDoc}
      */
-    public Content getAnnotationDocTreeHeader(Element member,
-            Content annotationDetailsTree) {
+    @Override
+    public Content getAnnotationDocTreeHeader(Element member, Content annotationDetailsTree) {
         String simpleName = name(member);
-        annotationDetailsTree.addContent(writer.getMarkerAnchor(simpleName +
-                utils.signature((ExecutableElement) member)));
+        annotationDetailsTree.addContent(links.createAnchor(
+                simpleName + utils.signature((ExecutableElement) member)));
         Content annotationDocTree = writer.getMemberTreeHeader();
         Content heading = new HtmlTree(HtmlConstants.MEMBER_HEADING);
         heading.addContent(simpleName);
@@ -203,24 +206,30 @@
     }
 
     /**
-     * {@inheritDoc}
+     * Get the summary for the member summary table.
+     *
+     * @return a string for the table summary
      */
-    public String getTableSummary() {
-        return configuration.getText("doclet.Member_Table_Summary",
-                configuration.getText("doclet.Annotation_Type_Required_Member_Summary"),
-                configuration.getText("doclet.annotation_type_required_members"));
+    // Overridden by AnnotationTypeOptionalMemberWriterImpl
+    protected String getTableSummary() {
+        return resources.getText("doclet.Member_Table_Summary",
+                resources.getText("doclet.Annotation_Type_Required_Member_Summary"),
+                resources.getText("doclet.annotation_type_required_members"));
+    }
+
+    /**
+     * Get the caption for the summary table.
+     * @return the caption
+     */
+    // Overridden by AnnotationTypeOptionalMemberWriterImpl
+    protected Content getCaption() {
+        return contents.getContent("doclet.Annotation_Type_Required_Members");
     }
 
     /**
      * {@inheritDoc}
      */
-    public Content getCaption() {
-        return configuration.getContent("doclet.Annotation_Type_Required_Members");
-    }
-
-    /**
-     * {@inheritDoc}
-     */
+    @Override
     public TableHeader getSummaryTableHeader(Element member) {
         return new TableHeader(contents.modifierAndTypeLabel,
                 contents.annotationTypeRequiredMemberLabel, contents.descriptionLabel);
@@ -229,8 +238,22 @@
     /**
      * {@inheritDoc}
      */
+    @Override
+    protected Table createSummaryTable() {
+        return new Table(configuration.htmlVersion, HtmlStyle.memberSummary)
+                .setSummary(getTableSummary())
+                .setCaption(getCaption())
+                .setHeader(getSummaryTableHeader(typeElement))
+                .setRowScopeColumn(1)
+                .setColumnStyles(HtmlStyle.colFirst, HtmlStyle.colSecond, HtmlStyle.colLast)
+                .setUseTBody(false);  // temporary? compatibility mode for TBody
+    }
+
+    /**
+     * {@inheritDoc}
+     */
     public void addSummaryAnchor(TypeElement typeElement, Content memberTree) {
-        memberTree.addContent(writer.getMarkerAnchor(
+        memberTree.addContent(links.createAnchor(
                 SectionName.ANNOTATION_TYPE_REQUIRED_ELEMENT_SUMMARY));
     }
 
@@ -285,7 +308,7 @@
      */
     protected Content getNavSummaryLink(TypeElement typeElement, boolean link) {
         if (link) {
-            return writer.getHyperLink(
+            return Links.createLink(
                     SectionName.ANNOTATION_TYPE_REQUIRED_ELEMENT_SUMMARY,
                     contents.navAnnotationTypeRequiredMember);
         } else {
@@ -298,7 +321,7 @@
      */
     protected void addNavDetailLink(boolean link, Content liNav) {
         if (link) {
-            liNav.addContent(writer.getHyperLink(
+            liNav.addContent(Links.createLink(
                     SectionName.ANNOTATION_TYPE_ELEMENT_DETAIL,
                     contents.navAnnotationTypeMember));
         } else {
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeWriterImpl.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeWriterImpl.java	Mon Nov 27 17:04:45 2017 +0000
@@ -37,6 +37,7 @@
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
+import jdk.javadoc.internal.doclets.formats.html.markup.Links;
 import jdk.javadoc.internal.doclets.formats.html.markup.StringContent;
 import jdk.javadoc.internal.doclets.toolkit.AnnotationTypeWriter;
 import jdk.javadoc.internal.doclets.toolkit.Content;
@@ -108,7 +109,7 @@
      */
     @Override
     protected Content getNavLinkPackage() {
-        Content linkContent = getHyperLink(DocPaths.PACKAGE_SUMMARY,
+        Content linkContent = Links.createLink(DocPaths.PACKAGE_SUMMARY,
                 contents.packageLabel);
         Content li = HtmlTree.LI(linkContent);
         return li;
@@ -132,7 +133,7 @@
      */
     @Override
     protected Content getNavLinkClassUse() {
-        Content linkContent = getHyperLink(DocPaths.CLASS_USE.resolve(filename), contents.useLabel);
+        Content linkContent = Links.createLink(DocPaths.CLASS_USE.resolve(filename), contents.useLabel);
         Content li = HtmlTree.LI(linkContent);
         return li;
     }
@@ -191,7 +192,7 @@
         }
         bodyTree.addContent(HtmlConstants.START_OF_CLASS_DATA);
         HtmlTree div = new HtmlTree(HtmlTag.DIV);
-        div.addStyle(HtmlStyle.header);
+        div.setStyle(HtmlStyle.header);
         if (configuration.showModules) {
             ModuleElement mdle = configuration.docEnv.getElementUtils().getModuleOf(annotationType);
             Content typeModuleLabel = HtmlTree.SPAN(HtmlStyle.moduleLabelInType, contents.moduleLabel);
@@ -346,7 +347,7 @@
      */
     @Override
     protected Content getNavLinkTree() {
-        Content treeLinkContent = getHyperLink(DocPaths.PACKAGE_TREE,
+        Content treeLinkContent = Links.createLink(DocPaths.PACKAGE_TREE,
                 contents.treeLabel, "", "");
         Content li = HtmlTree.LI(treeLinkContent);
         return li;
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassUseWriter.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassUseWriter.java	Mon Nov 27 17:04:45 2017 +0000
@@ -25,6 +25,8 @@
 
 package jdk.javadoc.internal.doclets.formats.html;
 
+import jdk.javadoc.internal.doclets.formats.html.markup.Table;
+
 import java.text.MessageFormat;
 import java.util.ArrayList;
 import java.util.Collections;
@@ -45,6 +47,7 @@
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
+import jdk.javadoc.internal.doclets.formats.html.markup.Links;
 import jdk.javadoc.internal.doclets.formats.html.markup.StringContent;
 import jdk.javadoc.internal.doclets.toolkit.Content;
 import jdk.javadoc.internal.doclets.toolkit.util.ClassTree;
@@ -245,7 +248,7 @@
     protected void generateClassUseFile() throws DocFileIOException {
         HtmlTree body = getClassUseHeader();
         HtmlTree div = new HtmlTree(HtmlTag.DIV);
-        div.addStyle(HtmlStyle.classUseContainer);
+        div.setStyle(HtmlStyle.classUseContainer);
         if (pkgSet.size() > 0) {
             addClassUse(div);
         } else {
@@ -276,7 +279,7 @@
      */
     protected void addClassUse(Content contentTree) {
         HtmlTree ul = new HtmlTree(HtmlTag.UL);
-        ul.addStyle(HtmlStyle.blockList);
+        ul.setStyle(HtmlStyle.blockList);
         if (configuration.packages.size() > 1) {
             addPackageList(ul);
             addPackageAnnotationList(ul);
@@ -291,25 +294,19 @@
      * @param contentTree the content tree to which the packages elements will be added
      */
     protected void addPackageList(Content contentTree) {
-        Content caption = getTableCaption(configuration.getContent(
+        Content caption = getTableCaption(contents.getContent(
                 "doclet.ClassUse_Packages.that.use.0",
                 getLink(new LinkInfoImpl(configuration,
                         LinkInfoImpl.Kind.CLASS_USE_HEADER, typeElement))));
-        Content table = (configuration.isOutputHtml5())
-                ? HtmlTree.TABLE(HtmlStyle.useSummary, caption)
-                : HtmlTree.TABLE(HtmlStyle.useSummary, packageUseTableSummary, caption);
-        table.addContent(getPackageTableHeader().toContent());
-        Content tbody = new HtmlTree(HtmlTag.TBODY);
-        boolean altColor = true;
+        Table table = new Table(configuration.htmlVersion, HtmlStyle.useSummary)
+                .setSummary(packageUseTableSummary)
+                .setCaption(caption)
+                .setHeader(getPackageTableHeader())
+                .setColumnStyles(HtmlStyle.colFirst, HtmlStyle.colLast);
         for (PackageElement pkg : pkgSet) {
-            HtmlTree tr = new HtmlTree(HtmlTag.TR);
-            tr.addStyle(altColor ? HtmlStyle.altColor : HtmlStyle.rowColor);
-            altColor = !altColor;
-            addPackageUse(pkg, tr);
-            tbody.addContent(tr);
+            addPackageUse(pkg, table);
         }
-        table.addContent(tbody);
-        Content li = HtmlTree.LI(HtmlStyle.blockList, table);
+        Content li = HtmlTree.LI(HtmlStyle.blockList, table.toContent());
         contentTree.addContent(li);
     }
 
@@ -324,30 +321,22 @@
                 pkgToPackageAnnotations.isEmpty()) {
             return;
         }
-        Content caption = getTableCaption(configuration.getContent(
+        Content caption = getTableCaption(contents.getContent(
                 "doclet.ClassUse_PackageAnnotation",
                 getLink(new LinkInfoImpl(configuration,
                         LinkInfoImpl.Kind.CLASS_USE_HEADER, typeElement))));
-        Content table = (configuration.isOutputHtml5())
-                ? HtmlTree.TABLE(HtmlStyle.useSummary, caption)
-                : HtmlTree.TABLE(HtmlStyle.useSummary, packageUseTableSummary, caption);
-        table.addContent(getPackageTableHeader().toContent());
-        Content tbody = new HtmlTree(HtmlTag.TBODY);
-        boolean altColor = true;
+
+        Table table = new Table(configuration.htmlVersion, HtmlStyle.useSummary)
+                .setSummary(packageUseTableSummary)
+                .setCaption(caption)
+                .setHeader(getPackageTableHeader())
+                .setColumnStyles(HtmlStyle.colFirst, HtmlStyle.colLast);
         for (PackageElement pkg : pkgToPackageAnnotations) {
-            HtmlTree tr = new HtmlTree(HtmlTag.TR);
-            tr.addStyle(altColor ? HtmlStyle.altColor : HtmlStyle.rowColor);
-            altColor = !altColor;
-            Content thFirst = HtmlTree.TH_ROW_SCOPE(HtmlStyle.colFirst, getPackageLink(pkg));
-            tr.addContent(thFirst);
-            HtmlTree tdLast = new HtmlTree(HtmlTag.TD);
-            tdLast.addStyle(HtmlStyle.colLast);
-            addSummaryComment(pkg, tdLast);
-            tr.addContent(tdLast);
-            tbody.addContent(tr);
+            Content summary = new ContentBuilder();
+            addSummaryComment(pkg, summary);
+            table.addRow(getPackageLink(pkg), summary);
         }
-        table.addContent(tbody);
-        Content li = HtmlTree.LI(HtmlStyle.blockList, table);
+        Content li = HtmlTree.LI(HtmlStyle.blockList, table.toContent());
         contentTree.addContent(li);
     }
 
@@ -358,9 +347,9 @@
      */
     protected void addClassList(Content contentTree) {
         HtmlTree ul = new HtmlTree(HtmlTag.UL);
-        ul.addStyle(HtmlStyle.blockList);
+        ul.setStyle(HtmlStyle.blockList);
         for (PackageElement pkg : pkgSet) {
-            Content markerAnchor = getMarkerAnchor(getPackageAnchorName(pkg));
+            Content markerAnchor = links.createAnchor(getPackageAnchorName(pkg));
             HtmlTree htmlTree = (configuration.allowTag(HtmlTag.SECTION))
                     ? HtmlTree.SECTION(markerAnchor)
                     : HtmlTree.LI(HtmlStyle.blockList, markerAnchor);
@@ -385,16 +374,14 @@
      * Add the package use information.
      *
      * @param pkg the package that uses the given class
-     * @param contentTree the content tree to which the package use information will be added
+     * @param table the table to which the package use information will be added
      */
-    protected void addPackageUse(PackageElement pkg, Content contentTree) {
-        Content thFirst = HtmlTree.TH_ROW_SCOPE(HtmlStyle.colFirst,
-                getHyperLink(getPackageAnchorName(pkg), new StringContent(utils.getPackageName(pkg))));
-        contentTree.addContent(thFirst);
-        HtmlTree tdLast = new HtmlTree(HtmlTag.TD);
-        tdLast.addStyle(HtmlStyle.colLast);
-        addSummaryComment(pkg, tdLast);
-        contentTree.addContent(tdLast);
+    protected void addPackageUse(PackageElement pkg, Table table) {
+        Content pkgLink =
+                links.createLink(getPackageAnchorName(pkg), new StringContent(utils.getPackageName(pkg)));
+        Content summary = new ContentBuilder();
+        addSummaryComment(pkg, summary);
+        table.addRow(pkgLink, summary);
     }
 
     /**
@@ -528,7 +515,7 @@
      */
     protected Content getNavLinkPackage() {
         Content linkContent =
-                getHyperLink(DocPath.parent.resolve(DocPaths.PACKAGE_SUMMARY), contents.packageLabel);
+                Links.createLink(DocPath.parent.resolve(DocPaths.PACKAGE_SUMMARY), contents.packageLabel);
         Content li = HtmlTree.LI(linkContent);
         return li;
     }
@@ -563,8 +550,8 @@
      */
     protected Content getNavLinkTree() {
         Content linkContent = utils.isEnclosingPackageIncluded(typeElement)
-                ? getHyperLink(DocPath.parent.resolve(DocPaths.PACKAGE_TREE), contents.treeLabel)
-                : getHyperLink(pathToRoot.resolve(DocPaths.OVERVIEW_TREE), contents.treeLabel);
+                ? Links.createLink(DocPath.parent.resolve(DocPaths.PACKAGE_TREE), contents.treeLabel)
+                : Links.createLink(pathToRoot.resolve(DocPaths.OVERVIEW_TREE), contents.treeLabel);
         Content li = HtmlTree.LI(linkContent);
         return li;
     }
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriterImpl.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriterImpl.java	Mon Nov 27 17:04:45 2017 +0000
@@ -40,6 +40,7 @@
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
+import jdk.javadoc.internal.doclets.formats.html.markup.Links;
 import jdk.javadoc.internal.doclets.formats.html.markup.StringContent;
 import jdk.javadoc.internal.doclets.toolkit.ClassWriter;
 import jdk.javadoc.internal.doclets.toolkit.Content;
@@ -119,7 +120,7 @@
      */
     @Override
     protected Content getNavLinkPackage() {
-        Content linkContent = getHyperLink(DocPaths.PACKAGE_SUMMARY,
+        Content linkContent = Links.createLink(DocPaths.PACKAGE_SUMMARY,
                 contents.packageLabel);
         Content li = HtmlTree.LI(linkContent);
         return li;
@@ -143,7 +144,7 @@
      */
     @Override
     protected Content getNavLinkClassUse() {
-        Content linkContent = getHyperLink(DocPaths.CLASS_USE.resolve(filename), contents.useLabel);
+        Content linkContent = Links.createLink(DocPaths.CLASS_USE.resolve(filename), contents.useLabel);
         Content li = HtmlTree.LI(linkContent);
         return li;
     }
@@ -202,7 +203,7 @@
         }
         bodyTree.addContent(HtmlConstants.START_OF_CLASS_DATA);
         HtmlTree div = new HtmlTree(HtmlTag.DIV);
-        div.addStyle(HtmlStyle.header);
+        div.setStyle(HtmlStyle.header);
         if (configuration.showModules) {
             ModuleElement mdle = configuration.docEnv.getElementUtils().getModuleOf(typeElement);
             Content classModuleLabel = HtmlTree.SPAN(HtmlStyle.moduleLabelInType, contents.moduleLabel);
@@ -380,13 +381,13 @@
     private Content getClassInheritenceTree(TypeMirror type) {
         TypeMirror sup;
         HtmlTree classTreeUl = new HtmlTree(HtmlTag.UL);
-        classTreeUl.addStyle(HtmlStyle.inheritance);
+        classTreeUl.setStyle(HtmlStyle.inheritance);
         Content liTree = null;
         do {
             sup = utils.getFirstVisibleSuperClass(type);
             if (sup != null) {
                 HtmlTree ul = new HtmlTree(HtmlTag.UL);
-                ul.addStyle(HtmlStyle.inheritance);
+                ul.setStyle(HtmlStyle.inheritance);
                 ul.addContent(getTreeForClassHelper(type));
                 if (liTree != null)
                     ul.addContent(liTree);
@@ -659,7 +660,7 @@
      */
     @Override
     protected Content getNavLinkTree() {
-        Content treeLinkContent = getHyperLink(DocPaths.PACKAGE_TREE,
+        Content treeLinkContent = Links.createLink(DocPaths.PACKAGE_TREE,
                 contents.treeLabel, "", "");
         Content li = HtmlTree.LI(treeLinkContent);
         return li;
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConstantsSummaryWriterImpl.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConstantsSummaryWriterImpl.java	Mon Nov 27 17:04:45 2017 +0000
@@ -25,6 +25,9 @@
 
 package jdk.javadoc.internal.doclets.formats.html;
 
+import jdk.javadoc.internal.doclets.formats.html.markup.Table;
+import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader;
+
 import java.util.*;
 
 import javax.lang.model.element.Modifier;
@@ -37,6 +40,7 @@
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
+import jdk.javadoc.internal.doclets.formats.html.markup.Links;
 import jdk.javadoc.internal.doclets.formats.html.markup.StringContent;
 import jdk.javadoc.internal.doclets.toolkit.ConstantsSummaryWriter;
 import jdk.javadoc.internal.doclets.toolkit.Content;
@@ -75,7 +79,7 @@
     /**
      * The HTML tree for main tag.
      */
-    private HtmlTree mainTree = HtmlTree.MAIN();
+    private final HtmlTree mainTree = HtmlTree.MAIN();
 
     /**
      * The HTML tree for constant values summary.
@@ -99,6 +103,7 @@
     /**
      * {@inheritDoc}
      */
+    @Override
     public Content getHeader() {
         String label = configuration.getText("doclet.Constants_Summary");
         HtmlTree bodyTree = getBody(true, getWindowTitle(label));
@@ -116,6 +121,7 @@
     /**
      * {@inheritDoc}
      */
+    @Override
     public Content getContentsHeader() {
         return new HtmlTree(HtmlTag.UL);
     }
@@ -123,19 +129,19 @@
     /**
      * {@inheritDoc}
      */
+    @Override
     public void addLinkToPackageContent(PackageElement pkg,
             Set<PackageElement> printedPackageHeaders, Content contentListTree) {
         //add link to summary
         Content link;
         if (pkg.isUnnamed()) {
-            link = getHyperLink(getDocLink(
-                    SectionName.UNNAMED_PACKAGE_ANCHOR),
+            link = Links.createLink(SectionName.UNNAMED_PACKAGE_ANCHOR,
                     contents.defaultPackageLabel, "", "");
         } else {
             String parsedPackageName = utils.parsePackageName(pkg);
             Content packageNameContent = getPackageLabel(parsedPackageName);
             packageNameContent.addContent(".*");
-            link = getHyperLink(DocLink.fragment(parsedPackageName),
+            link = Links.createLink(DocLink.fragment(parsedPackageName),
                     packageNameContent, "", "");
             PackageElement abbrevPkg = configuration.workArounds.getAbbreviatedPackageElement(pkg);
             printedPackageHeaders.add(abbrevPkg);
@@ -146,6 +152,7 @@
     /**
      * {@inheritDoc}
      */
+    @Override
     public void addContentsList(Content contentTree, Content contentListTree) {
         Content titleContent = contents.constantsSummaryTitle;
         Content pHeading = HtmlTree.HEADING(HtmlConstants.TITLE_HEADING, true,
@@ -169,27 +176,28 @@
     /**
      * {@inheritDoc}
      */
+    @Override
     public Content getConstantSummaries() {
         HtmlTree summariesDiv = new HtmlTree(HtmlTag.DIV);
-        summariesDiv.addStyle(HtmlStyle.constantValuesContainer);
+        summariesDiv.setStyle(HtmlStyle.constantValuesContainer);
         return summariesDiv;
     }
 
     /**
      * {@inheritDoc}
      */
+    @Override
     public void addPackageName(PackageElement pkg, Content summariesTree, boolean first) {
         Content pkgNameContent;
         if (!first && configuration.allowTag(HtmlTag.SECTION)) {
             summariesTree.addContent(summaryTree);
         }
         if (pkg.isUnnamed()) {
-            summariesTree.addContent(getMarkerAnchor(
-                    SectionName.UNNAMED_PACKAGE_ANCHOR));
+            summariesTree.addContent(links.createAnchor(SectionName.UNNAMED_PACKAGE_ANCHOR));
             pkgNameContent = contents.defaultPackageLabel;
         } else {
             String parsedPackageName = utils.parsePackageName(pkg);
-            summariesTree.addContent(getMarkerAnchor(parsedPackageName));
+            summariesTree.addContent(links.createAnchor(parsedPackageName));
             pkgNameContent = getPackageLabel(parsedPackageName);
         }
         Content headingContent = new StringContent(".*");
@@ -206,15 +214,17 @@
     /**
      * {@inheritDoc}
      */
+    @Override
     public Content getClassConstantHeader() {
         HtmlTree ul = new HtmlTree(HtmlTag.UL);
-        ul.addStyle(HtmlStyle.blockList);
+        ul.setStyle(HtmlStyle.blockList);
         return ul;
     }
 
     /**
      * {@inheritDoc}
      */
+    @Override
     public void addClassConstant(Content summariesTree, Content classConstantTree) {
         if (configuration.allowTag(HtmlTag.SECTION)) {
             summaryTree.addContent(classConstantTree);
@@ -224,12 +234,13 @@
     }
 
     /**
-     * Get the table caption and header for the constant summary table
-     *
-     * @param typeElement the TypeElement to be documented
-     * @return constant members header content
+     * {@inheritDoc}
      */
-    public Content getConstantMembersHeader(TypeElement typeElement) {
+    @Override
+    public void addConstantMembers(TypeElement typeElement, Collection<VariableElement> fields,
+            Content classConstantTree) {
+        currentTypeElement = typeElement;
+
         //generate links backward only to public classes.
         Content classlink = (utils.isPublic(typeElement) || utils.isProtected(typeElement)) ?
             getLink(new LinkInfoImpl(configuration,
@@ -237,75 +248,38 @@
             new StringContent(utils.getFullyQualifiedName(typeElement));
 
         PackageElement enclosingPackage  = utils.containingPackage(typeElement);
+        Content caption = new ContentBuilder();
         if (!enclosingPackage.isUnnamed()) {
-            Content cb = new ContentBuilder();
-            cb.addContent(enclosingPackage.getQualifiedName());
-            cb.addContent(".");
-            cb.addContent(classlink);
-            return getClassName(cb);
-        } else {
-            return getClassName(classlink);
+            caption.addContent(enclosingPackage.getQualifiedName());
+            caption.addContent(".");
         }
-    }
-
-    /**
-     * Get the class name in the table caption and the table header.
-     *
-     * @param classStr the class name to print.
-     * @return the table caption and header
-     */
-    protected Content getClassName(Content classStr) {
-        Content caption = getTableCaption(classStr);
-        Content table = (configuration.isOutputHtml5())
-                ? HtmlTree.TABLE(HtmlStyle.constantsSummary, caption)
-                : HtmlTree.TABLE(HtmlStyle.constantsSummary, constantsTableSummary, caption);
-        table.addContent(constantsTableHeader.toContent());
-        return table;
-    }
+        caption.addContent(classlink);
 
-    /**
-     * {@inheritDoc}
-     */
-    public void addConstantMembers(TypeElement typeElement, Collection<VariableElement> fields,
-            Content classConstantTree) {
-        currentTypeElement = typeElement;
-        Content tbody = new HtmlTree(HtmlTag.TBODY);
-        boolean altColor = true;
+        Table table = new Table(configuration.htmlVersion, HtmlStyle.constantsSummary)
+                .setSummary(constantsTableSummary)
+                .setCaption(caption)
+                .setHeader(constantsTableHeader)
+                .setRowScopeColumn(1)
+                .setColumnStyles(HtmlStyle.colFirst, HtmlStyle.colSecond, HtmlStyle.colLast);
+
         for (VariableElement field : fields) {
-            HtmlTree tr = new HtmlTree(HtmlTag.TR);
-            tr.addStyle(altColor ? HtmlStyle.altColor : HtmlStyle.rowColor);
-            addConstantMember(field, tr);
-            tbody.addContent(tr);
-            altColor = !altColor;
+            table.addRow(getTypeColumn(field), getNameColumn(field), getValue(field));
         }
-        Content table = getConstantMembersHeader(typeElement);
-        table.addContent(tbody);
-        Content li = HtmlTree.LI(HtmlStyle.blockList, table);
+        Content li = HtmlTree.LI(HtmlStyle.blockList, table.toContent());
         classConstantTree.addContent(li);
     }
 
     /**
-     * Add the row for the constant summary table.
-     *
-     * @param member the field to be documented.
-     * @param trTree an htmltree object for the table row
-     */
-    private void addConstantMember(VariableElement member, HtmlTree trTree) {
-        trTree.addContent(getTypeColumn(member));
-        trTree.addContent(getNameColumn(member));
-        trTree.addContent(getValue(member));
-    }
-
-    /**
      * Get the type column for the constant summary table row.
      *
      * @param member the field to be documented.
      * @return the type column of the constant table row
      */
     private Content getTypeColumn(VariableElement member) {
-        Content anchor = getMarkerAnchor(currentTypeElement.getQualifiedName() +
-                "." + member.getSimpleName());
-        Content tdType = HtmlTree.TD(HtmlStyle.colFirst, anchor);
+        Content anchor = links.createAnchor(
+                currentTypeElement.getQualifiedName() + "." + member.getSimpleName());
+        Content typeContent = new ContentBuilder();
+        typeContent.addContent(anchor);
         Content code = new HtmlTree(HtmlTag.CODE);
         for (Modifier mod : member.getModifiers()) {
             Content modifier = new StringContent(mod.toString());
@@ -315,8 +289,8 @@
         Content type = getLink(new LinkInfoImpl(configuration,
                 LinkInfoImpl.Kind.CONSTANT_SUMMARY, member.asType()));
         code.addContent(type);
-        tdType.addContent(code);
-        return tdType;
+        typeContent.addContent(code);
+        return typeContent;
     }
 
     /**
@@ -328,8 +302,7 @@
     private Content getNameColumn(VariableElement member) {
         Content nameContent = getDocLink(LinkInfoImpl.Kind.CONSTANT_SUMMARY,
                 member, member.getSimpleName(), false);
-        Content code = HtmlTree.CODE(nameContent);
-        return HtmlTree.TH_ROW_SCOPE(HtmlStyle.colSecond, code);
+        return HtmlTree.CODE(nameContent);
     }
 
     /**
@@ -341,13 +314,13 @@
     private Content getValue(VariableElement member) {
         String value = utils.constantValueExpresion(member);
         Content valueContent = new StringContent(value);
-        Content code = HtmlTree.CODE(valueContent);
-        return HtmlTree.TD(HtmlStyle.colLast, code);
+        return HtmlTree.CODE(valueContent);
     }
 
     /**
      * {@inheritDoc}
      */
+    @Override
     public void addConstantSummaries(Content contentTree, Content summariesTree) {
         if (configuration.allowTag(HtmlTag.SECTION) && summaryTree != null) {
             summariesTree.addContent(summaryTree);
@@ -363,6 +336,7 @@
     /**
      * {@inheritDoc}
      */
+    @Override
     public void addFooter(Content contentTree) {
         Content htmlTree = (configuration.allowTag(HtmlTag.FOOTER))
                 ? HtmlTree.FOOTER()
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConstructorWriterImpl.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConstructorWriterImpl.java	Mon Nov 27 17:04:45 2017 +0000
@@ -25,18 +25,20 @@
 
 package jdk.javadoc.internal.doclets.formats.html;
 
+import jdk.javadoc.internal.doclets.formats.html.markup.Table;
+import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader;
+
 import java.util.*;
 
 import javax.lang.model.element.Element;
 import javax.lang.model.element.ExecutableElement;
 import javax.lang.model.element.TypeElement;
 
-import jdk.javadoc.internal.doclets.formats.html.TableHeader;
-import jdk.javadoc.internal.doclets.formats.html.markup.HtmlAttr;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlConstants;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
+import jdk.javadoc.internal.doclets.formats.html.markup.Links;
 import jdk.javadoc.internal.doclets.formats.html.markup.StringContent;
 import jdk.javadoc.internal.doclets.toolkit.ConstructorWriter;
 import jdk.javadoc.internal.doclets.toolkit.Content;
@@ -105,6 +107,7 @@
     /**
      * {@inheritDoc}
      */
+    @Override
     public void addMemberTree(Content memberSummaryTree, Content memberTree) {
         writer.addMemberTree(memberSummaryTree, memberTree);
     }
@@ -117,7 +120,7 @@
             Content memberDetailsTree) {
         memberDetailsTree.addContent(HtmlConstants.START_OF_CONSTRUCTOR_DETAILS);
         Content constructorDetailsTree = writer.getMemberTreeHeader();
-        constructorDetailsTree.addContent(writer.getMarkerAnchor(
+        constructorDetailsTree.addContent(links.createAnchor(
                 SectionName.CONSTRUCTOR_DETAIL));
         Content heading = HtmlTree.HEADING(HtmlConstants.DETAILS_HEADING,
                 contents.constructorDetailsLabel);
@@ -133,10 +136,9 @@
             Content constructorDetailsTree) {
         String erasureAnchor;
         if ((erasureAnchor = getErasureAnchor(constructor)) != null) {
-            constructorDetailsTree.addContent(writer.getMarkerAnchor((erasureAnchor)));
+            constructorDetailsTree.addContent(links.createAnchor((erasureAnchor)));
         }
-        constructorDetailsTree.addContent(
-                writer.getMarkerAnchor(writer.getAnchor(constructor)));
+        constructorDetailsTree.addContent(links.createAnchor(writer.getAnchor(constructor)));
         Content constructorDocTree = writer.getMemberTreeHeader();
         Content heading = new HtmlTree(HtmlConstants.MEMBER_HEADING);
         heading.addContent(name(constructor));
@@ -169,15 +171,6 @@
      * {@inheritDoc}
      */
     @Override
-    public void setSummaryColumnStyleAndScope(HtmlTree thTree) {
-        thTree.addStyle(HtmlStyle.colConstructorName);
-        thTree.addAttr(HtmlAttr.SCOPE, "row");
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
     public void addDeprecated(ExecutableElement constructor, Content constructorDocTree) {
         addDeprecatedInfo(constructor, constructorDocTree);
     }
@@ -243,24 +236,6 @@
      * {@inheritDoc}
      */
     @Override
-    public String getTableSummary() {
-        return resources.getText("doclet.Member_Table_Summary",
-                resources.getText("doclet.Constructor_Summary"),
-                resources.getText("doclet.constructors"));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public Content getCaption() {
-        return contents.constructors;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
     public TableHeader getSummaryTableHeader(Element member) {
         if (foundNonPubConstructor) {
             return new TableHeader(contents.modifierLabel, contents.constructorLabel,
@@ -270,13 +245,39 @@
         }
     }
 
+    @Override
+    protected Table createSummaryTable() {
+        List<HtmlStyle> bodyRowStyles;
+        int rowScopeColumn;
+
+        if (foundNonPubConstructor) {
+            bodyRowStyles = Arrays.asList(HtmlStyle.colFirst, HtmlStyle.colConstructorName,
+                    HtmlStyle.colLast);
+            rowScopeColumn = 1;
+        } else {
+            bodyRowStyles = Arrays.asList(HtmlStyle.colConstructorName, HtmlStyle.colLast);
+            rowScopeColumn = 0;
+        }
+
+        String summary =  resources.getText("doclet.Member_Table_Summary",
+                resources.getText("doclet.Constructor_Summary"),
+                resources.getText("doclet.constructors"));
+
+        return new Table(configuration.htmlVersion, HtmlStyle.memberSummary)
+                .setSummary(summary)
+                .setCaption(contents.constructors)
+                .setHeader(getSummaryTableHeader(typeElement))
+                .setRowScopeColumn(rowScopeColumn)
+                .setColumnStyles(bodyRowStyles)
+                .setUseTBody(false);  // temporary? compatibility mode for TBody
+    }
+
     /**
      * {@inheritDoc}
      */
     @Override
     public void addSummaryAnchor(TypeElement typeElement, Content memberTree) {
-        memberTree.addContent(writer.getMarkerAnchor(
-                SectionName.CONSTRUCTOR_SUMMARY));
+        memberTree.addContent(links.createAnchor(SectionName.CONSTRUCTOR_SUMMARY));
     }
 
     /**
@@ -299,7 +300,7 @@
     @Override
     protected Content getNavSummaryLink(TypeElement typeElement, boolean link) {
         if (link) {
-            return writer.getHyperLink(SectionName.CONSTRUCTOR_SUMMARY,
+            return Links.createLink(SectionName.CONSTRUCTOR_SUMMARY,
                     contents.navConstructor);
         } else {
             return contents.navConstructor;
@@ -312,7 +313,7 @@
     @Override
     protected void addNavDetailLink(boolean link, Content liNav) {
         if (link) {
-            liNav.addContent(writer.getHyperLink(
+            liNav.addContent(Links.createLink(
                     SectionName.CONSTRUCTOR_DETAIL,
                     contents.navConstructor));
         } else {
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/Contents.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/Contents.java	Mon Nov 27 17:04:45 2017 +0000
@@ -28,6 +28,7 @@
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
+import jdk.javadoc.internal.doclets.formats.html.markup.Comment;
 import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder;
 import jdk.javadoc.internal.doclets.formats.html.markup.FixedStringContent;
 import jdk.javadoc.internal.doclets.formats.html.markup.RawHtml;
@@ -137,6 +138,7 @@
     public final Content navProperty;
     public final Content navServices;
     public final Content nestedClassSummary;
+    public final Content newPage;
     public final Content nextClassLabel;
     public final Content nextLabel;
     public final Content nextLetter;
@@ -269,6 +271,7 @@
         navProperty = getContent("doclet.navProperty");
         navServices = getContent("doclet.navServices");
         nestedClassSummary = getContent("doclet.Nested_Class_Summary");
+        newPage = new Comment(resources.getText("doclet.New_Page"));
         nextClassLabel = getNonBreakContent("doclet.Next_Class");
         nextLabel = getNonBreakContent("doclet.Next");
         nextLetter = getContent("doclet.Next_Letter");
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/DeprecatedListWriter.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/DeprecatedListWriter.java	Mon Nov 27 17:04:45 2017 +0000
@@ -25,6 +25,9 @@
 
 package jdk.javadoc.internal.doclets.formats.html;
 
+import jdk.javadoc.internal.doclets.formats.html.markup.Table;
+import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader;
+
 import java.util.EnumMap;
 import java.util.List;
 import java.util.SortedSet;
@@ -34,6 +37,7 @@
 import javax.lang.model.element.PackageElement;
 
 import com.sun.source.doctree.DocTree;
+import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlConstants;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
@@ -281,7 +285,7 @@
         htmlTree.addContent(getContentsList(deprapi));
         String memberTableSummary;
         HtmlTree div = new HtmlTree(HtmlTag.DIV);
-        div.addStyle(HtmlStyle.contentContainer);
+        div.setStyle(HtmlStyle.contentContainer);
         for (DeprElementKind kind : DeprElementKind.values()) {
             if (deprapi.hasDocumentation(kind)) {
                 addAnchor(deprapi, kind, div);
@@ -321,7 +325,7 @@
     private void addIndexLink(DeprecatedAPIListBuilder builder,
             DeprElementKind kind, Content contentTree) {
         if (builder.hasDocumentation(kind)) {
-            Content li = HtmlTree.LI(getHyperLink(getAnchorName(kind),
+            Content li = HtmlTree.LI(links.createLink(getAnchorName(kind),
                     contents.getContent(getHeadingKey(kind))));
             contentTree.addContent(li);
         }
@@ -358,7 +362,7 @@
      */
     private void addAnchor(DeprecatedAPIListBuilder builder, DeprElementKind kind, Content htmlTree) {
         if (builder.hasDocumentation(kind)) {
-            htmlTree.addContent(getMarkerAnchor(getAnchorName(kind)));
+            htmlTree.addContent(links.createAnchor(getAnchorName(kind)));
         }
     }
 
@@ -404,49 +408,42 @@
     protected void addDeprecatedAPI(SortedSet<Element> deprList, String headingKey,
             String tableSummary, TableHeader tableHeader, Content contentTree) {
         if (deprList.size() > 0) {
-            Content caption = getTableCaption(configuration.getContent(headingKey));
-            Content table = (configuration.isOutputHtml5())
-                    ? HtmlTree.TABLE(HtmlStyle.deprecatedSummary, caption)
-                    : HtmlTree.TABLE(HtmlStyle.deprecatedSummary, tableSummary, caption);
-            table.addContent(tableHeader.toContent());
-            Content tbody = new HtmlTree(HtmlTag.TBODY);
-            boolean altColor = true;
+            Content caption = contents.getContent(headingKey);
+            Table table = new Table(configuration.htmlVersion, HtmlStyle.deprecatedSummary)
+                    .setSummary(tableSummary)
+                    .setCaption(caption)
+                    .setHeader(tableHeader)
+                    .setColumnStyles(HtmlStyle.colDeprecatedItemName, HtmlStyle.colLast);
             for (Element e : deprList) {
-                HtmlTree thRow;
+                Content link;
                 switch (e.getKind()) {
                     case MODULE:
-                        ModuleElement m = (ModuleElement)e;
-                        thRow = HtmlTree.TH_ROW_SCOPE(HtmlStyle.colFirst,
-                        getModuleLink(m, new StringContent(m.getQualifiedName())));
+                        ModuleElement m = (ModuleElement) e;
+                        link = getModuleLink(m, new StringContent(m.getQualifiedName()));
                         break;
                     case PACKAGE:
-                        PackageElement pkg = (PackageElement)e;
-                        thRow = HtmlTree.TH_ROW_SCOPE(HtmlStyle.colFirst,
-                        getPackageLink(pkg, getPackageName(pkg)));
+                        PackageElement pkg = (PackageElement) e;
+                        link = getPackageLink(pkg, getPackageName(pkg));
                         break;
                     default:
-                        thRow = getDeprecatedLink(e);
+                        link = getDeprecatedLink(e);
                 }
-                HtmlTree tr = HtmlTree.TR(thRow);
-                HtmlTree tdDesc = new HtmlTree(HtmlTag.TD);
-                tdDesc.addStyle(HtmlStyle.colLast);
+                Content desc = new ContentBuilder();
                 List<? extends DocTree> tags = utils.getDeprecatedTrees(e);
                 if (!tags.isEmpty()) {
-                    addInlineDeprecatedComment(e, tags.get(0), tdDesc);
+                    addInlineDeprecatedComment(e, tags.get(0), desc);
+                } else {
+                    desc.addContent(HtmlTree.EMPTY);
                 }
-                tr.addContent(tdDesc);
-                tr.addStyle(altColor ? HtmlStyle.altColor : HtmlStyle.rowColor);
-                altColor = !altColor;
-                tbody.addContent(tr);
+                table.addRow(link, desc);
             }
-            table.addContent(tbody);
-            Content li = HtmlTree.LI(HtmlStyle.blockList, table);
+            Content li = HtmlTree.LI(HtmlStyle.blockList, table.toContent());
             Content ul = HtmlTree.UL(HtmlStyle.blockList, li);
             contentTree.addContent(ul);
         }
     }
 
-    protected HtmlTree getDeprecatedLink(Element e) {
+    protected Content getDeprecatedLink(Element e) {
         AbstractMemberWriter writer;
         switch (e.getKind()) {
             case INTERFACE:
@@ -470,6 +467,6 @@
             default:
                 writer = new AnnotationTypeOptionalMemberWriterImpl(this, null);
         }
-        return HtmlTree.TH_ROW_SCOPE(HtmlStyle.colDeprecatedItemName, writer.getDeprecatedLink(e));
+        return writer.getDeprecatedLink(e);
     }
 }
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/EnumConstantWriterImpl.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/EnumConstantWriterImpl.java	Mon Nov 27 17:04:45 2017 +0000
@@ -25,20 +25,19 @@
 
 package jdk.javadoc.internal.doclets.formats.html;
 
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
+
+import jdk.javadoc.internal.doclets.formats.html.markup.Table;
+import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader;
 
 import javax.lang.model.element.Element;
 import javax.lang.model.element.TypeElement;
 import javax.lang.model.element.VariableElement;
 
-import jdk.javadoc.internal.doclets.formats.html.TableHeader;
-import jdk.javadoc.internal.doclets.formats.html.markup.HtmlAttr;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlConstants;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
+import jdk.javadoc.internal.doclets.formats.html.markup.Links;
 import jdk.javadoc.internal.doclets.formats.html.markup.StringContent;
 import jdk.javadoc.internal.doclets.toolkit.Content;
 import jdk.javadoc.internal.doclets.toolkit.EnumConstantWriter;
@@ -81,6 +80,7 @@
     /**
      * {@inheritDoc}
      */
+    @Override
     public void addMemberTree(Content memberSummaryTree, Content memberTree) {
         writer.addMemberTree(memberSummaryTree, memberTree);
     }
@@ -93,7 +93,7 @@
             Content memberDetailsTree) {
         memberDetailsTree.addContent(HtmlConstants.START_OF_ENUM_CONSTANT_DETAILS);
         Content enumConstantsDetailsTree = writer.getMemberTreeHeader();
-        enumConstantsDetailsTree.addContent(writer.getMarkerAnchor(
+        enumConstantsDetailsTree.addContent(links.createAnchor(
                 SectionName.ENUM_CONSTANT_DETAIL));
         Content heading = HtmlTree.HEADING(HtmlConstants.DETAILS_HEADING,
                 contents.enumConstantDetailLabel);
@@ -107,8 +107,7 @@
     @Override
     public Content getEnumConstantsTreeHeader(VariableElement enumConstant,
             Content enumConstantsDetailsTree) {
-        enumConstantsDetailsTree.addContent(
-                writer.getMarkerAnchor(name(enumConstant)));
+        enumConstantsDetailsTree.addContent(links.createAnchor(name(enumConstant)));
         Content enumConstantsTree = writer.getMemberTreeHeader();
         Content heading = new HtmlTree(HtmlConstants.MEMBER_HEADING);
         heading.addContent(name(enumConstant));
@@ -196,24 +195,6 @@
      * {@inheritDoc}
      */
     @Override
-    public String getTableSummary() {
-        return resources.getText("doclet.Member_Table_Summary",
-                resources.getText("doclet.Enum_Constant_Summary"),
-                resources.getText("doclet.enum_constants"));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public Content getCaption() {
-        return configuration.getContent("doclet.Enum_Constants");
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
     public TableHeader getSummaryTableHeader(Element member) {
         return new TableHeader(contents.enumConstantLabel, contents.descriptionLabel);
     }
@@ -222,9 +203,25 @@
      * {@inheritDoc}
      */
     @Override
+    protected Table createSummaryTable() {
+        String summary = resources.getText("doclet.Member_Table_Summary",
+            resources.getText("doclet.Enum_Constant_Summary"),
+            resources.getText("doclet.enum_constants"));
+
+        return new Table(configuration.htmlVersion, HtmlStyle.memberSummary)
+                .setSummary(summary)
+                .setCaption(contents.getContent("doclet.Enum_Constants"))
+                .setHeader(getSummaryTableHeader(typeElement))
+                .setColumnStyles(HtmlStyle.colFirst, HtmlStyle.colLast)
+                .setUseTBody(false);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
     public void addSummaryAnchor(TypeElement typeElement, Content memberTree) {
-        memberTree.addContent(writer.getMarkerAnchor(
-                SectionName.ENUM_CONSTANT_SUMMARY));
+        memberTree.addContent(links.createAnchor(SectionName.ENUM_CONSTANT_SUMMARY));
     }
 
     /**
@@ -257,15 +254,6 @@
      * {@inheritDoc}
      */
     @Override
-    public void setSummaryColumnStyleAndScope(HtmlTree thTree) {
-        thTree.addStyle(HtmlStyle.colFirst);
-        thTree.addAttr(HtmlAttr.SCOPE, "row");
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
     protected void addInheritedSummaryLink(TypeElement typeElement, Element member, Content linksTree) {
     }
 
@@ -293,10 +281,10 @@
     protected Content getNavSummaryLink(TypeElement typeElement, boolean link) {
         if (link) {
             if (typeElement == null) {
-                return writer.getHyperLink(SectionName.ENUM_CONSTANT_SUMMARY,
+                return Links.createLink(SectionName.ENUM_CONSTANT_SUMMARY,
                         contents.navEnum);
             } else {
-                return writer.getHyperLink(
+                return links.createLink(
                         SectionName.ENUM_CONSTANTS_INHERITANCE,
                         configuration.getClassName(typeElement), contents.navEnum);
             }
@@ -311,7 +299,7 @@
     @Override
     protected void addNavDetailLink(boolean link, Content liNav) {
         if (link) {
-            liNav.addContent(writer.getHyperLink(
+            liNav.addContent(Links.createLink(
                     SectionName.ENUM_CONSTANT_DETAIL,
                     contents.navEnum));
         } else {
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/FieldWriterImpl.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/FieldWriterImpl.java	Mon Nov 27 17:04:45 2017 +0000
@@ -25,15 +25,21 @@
 
 package jdk.javadoc.internal.doclets.formats.html;
 
+import jdk.javadoc.internal.doclets.formats.html.markup.Table;
+import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader;
+
+import java.util.Arrays;
+import java.util.List;
+
 import javax.lang.model.element.Element;
 import javax.lang.model.element.TypeElement;
 import javax.lang.model.element.VariableElement;
 
-import jdk.javadoc.internal.doclets.formats.html.TableHeader;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlConstants;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
+import jdk.javadoc.internal.doclets.formats.html.markup.Links;
 import jdk.javadoc.internal.doclets.formats.html.markup.StringContent;
 import jdk.javadoc.internal.doclets.toolkit.Content;
 import jdk.javadoc.internal.doclets.toolkit.FieldWriter;
@@ -78,6 +84,7 @@
     /**
      * {@inheritDoc}
      */
+    @Override
     public void addMemberTree(Content memberSummaryTree, Content memberTree) {
         writer.addMemberTree(memberSummaryTree, memberTree);
     }
@@ -89,7 +96,7 @@
     public Content getFieldDetailsTreeHeader(TypeElement typeElement, Content memberDetailsTree) {
         memberDetailsTree.addContent(HtmlConstants.START_OF_FIELD_DETAILS);
         Content fieldDetailsTree = writer.getMemberTreeHeader();
-        fieldDetailsTree.addContent(writer.getMarkerAnchor(
+        fieldDetailsTree.addContent(links.createAnchor(
                 SectionName.FIELD_DETAIL));
         Content heading = HtmlTree.HEADING(HtmlConstants.DETAILS_HEADING,
                 contents.fieldDetailsLabel);
@@ -102,7 +109,7 @@
      */
     @Override
     public Content getFieldDocTreeHeader(VariableElement field, Content fieldDetailsTree) {
-        fieldDetailsTree.addContent(writer.getMarkerAnchor(name(field)));
+        fieldDetailsTree.addContent(links.createAnchor(name(field)));
         Content fieldTree = writer.getMemberTreeHeader();
         Content heading = new HtmlTree(HtmlConstants.MEMBER_HEADING);
         heading.addContent(name(field));
@@ -192,35 +199,35 @@
      * {@inheritDoc}
      */
     @Override
-    public String getTableSummary() {
-        return resources.getText("doclet.Member_Table_Summary",
-                resources.getText("doclet.Field_Summary"),
-                resources.getText("doclet.fields"));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public Content getCaption() {
-        return contents.fields;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
     public TableHeader getSummaryTableHeader(Element member) {
         return new TableHeader(contents.modifierAndTypeLabel, contents.fieldLabel,
                 contents.descriptionLabel);
     }
 
+    @Override
+    protected Table createSummaryTable() {
+        String summary =  resources.getText("doclet.Member_Table_Summary",
+                resources.getText("doclet.Field_Summary"),
+                resources.getText("doclet.fields"));
+
+        List<HtmlStyle> bodyRowStyles = Arrays.asList(HtmlStyle.colFirst, HtmlStyle.colSecond,
+                HtmlStyle.colLast);
+
+        return new Table(configuration.htmlVersion, HtmlStyle.memberSummary)
+                .setSummary(summary)
+                .setCaption(contents.fields)
+                .setHeader(getSummaryTableHeader(typeElement))
+                .setRowScopeColumn(1)
+                .setColumnStyles(bodyRowStyles)
+                .setUseTBody(false);  // temporary? compatibility mode for TBody
+    }
+
     /**
      * {@inheritDoc}
      */
     @Override
     public void addSummaryAnchor(TypeElement typeElement, Content memberTree) {
-        memberTree.addContent(writer.getMarkerAnchor(
+        memberTree.addContent(links.createAnchor(
                 SectionName.FIELD_SUMMARY));
     }
 
@@ -229,7 +236,7 @@
      */
     @Override
     public void addInheritedSummaryAnchor(TypeElement typeElement, Content inheritedTree) {
-        inheritedTree.addContent(writer.getMarkerAnchor(
+        inheritedTree.addContent(links.createAnchor(
                 SectionName.FIELDS_INHERITANCE, configuration.getClassName(typeElement)));
     }
 
@@ -303,11 +310,11 @@
     protected Content getNavSummaryLink(TypeElement typeElement, boolean link) {
         if (link) {
             if (typeElement == null) {
-                return writer.getHyperLink(
+                return Links.createLink(
                         SectionName.FIELD_SUMMARY,
                         contents.navField);
             } else {
-                return writer.getHyperLink(
+                return links.createLink(
                         SectionName.FIELDS_INHERITANCE,
                         configuration.getClassName(typeElement), contents.navField);
             }
@@ -322,7 +329,7 @@
     @Override
     protected void addNavDetailLink(boolean link, Content liNav) {
         if (link) {
-            liNav.addContent(writer.getHyperLink(
+            liNav.addContent(Links.createLink(
                     SectionName.FIELD_DETAIL,
                     contents.navField));
         } else {
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/FrameOutputWriter.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/FrameOutputWriter.java	Mon Nov 27 17:04:45 2017 +0000
@@ -25,20 +25,19 @@
 
 package jdk.javadoc.internal.doclets.formats.html;
 
-import jdk.javadoc.internal.doclets.formats.html.markup.Comment;
+import jdk.javadoc.internal.doclets.formats.html.markup.Head;
 import jdk.javadoc.internal.doclets.formats.html.markup.DocType;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlAttr;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlDocument;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
-import jdk.javadoc.internal.doclets.formats.html.markup.RawHtml;
-import jdk.javadoc.internal.doclets.formats.html.markup.StringContent;
+import jdk.javadoc.internal.doclets.formats.html.markup.Script;
 import jdk.javadoc.internal.doclets.toolkit.Content;
+import jdk.javadoc.internal.doclets.toolkit.util.DocFile;
 import jdk.javadoc.internal.doclets.toolkit.util.DocFileIOException;
 import jdk.javadoc.internal.doclets.toolkit.util.DocPath;
 import jdk.javadoc.internal.doclets.toolkit.util.DocPaths;
-import jdk.javadoc.internal.doclets.toolkit.util.DocletConstants;
 
 
 /**
@@ -99,12 +98,12 @@
         HtmlTree body = new HtmlTree(HtmlTag.BODY);
         body.addAttr(HtmlAttr.ONLOAD, "loadFrames()");
         String topFilePath = configuration.topFile.getPath();
-        String javaScriptRefresh = "\nif (targetPage == \"\" || targetPage == \"undefined\")\n" +
-                "     window.location.replace('" + topFilePath + "');\n";
-        RawHtml scriptContent = new RawHtml(javaScriptRefresh.replace("\n", DocletConstants.NL));
-        HtmlTree scriptTree = HtmlTree.SCRIPT();
-        scriptTree.addContent(scriptContent);
-        body.addContent(scriptTree);
+        Script script = new Script(
+                "\nif (targetPage == \"\" || targetPage == \"undefined\")\n" +
+                "     window.location.replace(")
+                .appendStringLiteral(topFilePath, '\'')
+                .append(");\n");
+        body.addContent(script.asContent());
         Content noScript = HtmlTree.NOSCRIPT(contents.noScriptMessage);
         body.addContent(noScript);
         if (configuration.allowTag(HtmlTag.MAIN)) {
@@ -129,24 +128,20 @@
      * @throws DocFileIOException if there is an error writing the frames document
      */
     private void printFramesDocument(String title, HtmlTree body) throws DocFileIOException {
-        Content htmlDocType = configuration.isOutputHtml5()
-                ? DocType.HTML5
-                : DocType.TRANSITIONAL;
-        Content htmlComment = new Comment(configuration.getText("doclet.New_Page"));
-        Content head = new HtmlTree(HtmlTag.HEAD);
-        head.addContent(getGeneratedBy(!configuration.notimestamp));
-        Content windowTitle = HtmlTree.TITLE(new StringContent(title));
-        head.addContent(windowTitle);
-        Content meta = HtmlTree.META("Content-Type", CONTENT_TYPE, configuration.charset);
-        head.addContent(meta);
-        addStyleSheetProperties(configuration, head);
-        head.addContent(getFramesJavaScript());
-        Content htmlTree = HtmlTree.HTML(configuration.getLocale().getLanguage(),
-                head, body);
-        Content htmlDocument = new HtmlDocument(htmlDocType,
-                htmlComment, htmlTree);
-        write(htmlDocument);
-    }
+        DocType htmlDocType = DocType.forVersion(configuration.htmlVersion);
+        Content htmlComment = contents.newPage;
+        Head head = new Head(path, configuration.htmlVersion, configuration.docletVersion)
+                .setTimestamp(!configuration.notimestamp, false)
+                .setTitle(title)
+                .setCharset(configuration.charset)
+                .setStylesheets(configuration.getMainStylesheet(), configuration.getAdditionalStylesheets())
+                .addDefaultScript(false)
+                .addScript(getFramesScript());
+
+        Content htmlTree = HtmlTree.HTML(configuration.getLocale().getLanguage(), head.toContent(), body);
+        HtmlDocument htmlDocument = new HtmlDocument(htmlDocType, htmlComment, htmlTree);
+        htmlDocument.write(DocFile.createFileForOutput(configuration, path));
+   }
 
     /**
      * Get the frame sizes and their contents.
@@ -156,8 +151,8 @@
     protected Content getFrameDetails() {
         HtmlTree leftContainerDiv = new HtmlTree(HtmlTag.DIV);
         HtmlTree rightContainerDiv = new HtmlTree(HtmlTag.DIV);
-        leftContainerDiv.addStyle(HtmlStyle.leftContainer);
-        rightContainerDiv.addStyle(HtmlStyle.rightContainer);
+        leftContainerDiv.setStyle(HtmlStyle.leftContainer);
+        rightContainerDiv.setStyle(HtmlStyle.rightContainer);
         if (configuration.showModules && configuration.modules.size() > 1) {
             addAllModulesFrameTag(leftContainerDiv);
         } else if (noOfPackages > 1) {
@@ -214,7 +209,67 @@
     private void addClassFrameTag(Content contentTree) {
         HtmlTree frame = HtmlTree.IFRAME(configuration.topFile.getPath(), "classFrame",
                 configuration.getText("doclet.Package_class_and_interface_descriptions"));
-        frame.addStyle(HtmlStyle.rightIframe);
+        frame.setStyle(HtmlStyle.rightIframe);
         contentTree.addContent(frame);
     }
+
+    /**
+     * Returns a content tree for the SCRIPT tag for the main page(index.html).
+     *
+     * @return a content for the SCRIPT tag
+     */
+    protected Script getFramesScript() {
+        return new Script("\n" +
+                "    tmpTargetPage = \"\" + window.location.search;\n" +
+                "    if (tmpTargetPage != \"\" && tmpTargetPage != \"undefined\")\n" +
+                "        tmpTargetPage = tmpTargetPage.substring(1);\n" +
+                "    if (tmpTargetPage.indexOf(\":\") != -1 || (tmpTargetPage != \"\" && !validURL(tmpTargetPage)))\n" +
+                "        tmpTargetPage = \"undefined\";\n" +
+                "    targetPage = tmpTargetPage;\n" +
+                "    function validURL(url) {\n" +
+                "        try {\n" +
+                "            url = decodeURIComponent(url);\n" +
+                "        }\n" +
+                "        catch (error) {\n" +
+                "            return false;\n" +
+                "        }\n" +
+                "        var pos = url.indexOf(\".html\");\n" +
+                "        if (pos == -1 || pos != url.length - 5)\n" +
+                "            return false;\n" +
+                "        var allowNumber = false;\n" +
+                "        var allowSep = false;\n" +
+                "        var seenDot = false;\n" +
+                "        for (var i = 0; i < url.length - 5; i++) {\n" +
+                "            var ch = url.charAt(i);\n" +
+                "            if ('a' <= ch && ch <= 'z' ||\n" +
+                "                    'A' <= ch && ch <= 'Z' ||\n" +
+                "                    ch == '$' ||\n" +
+                "                    ch == '_' ||\n" +
+                "                    ch.charCodeAt(0) > 127) {\n" +
+                "                allowNumber = true;\n" +
+                "                allowSep = true;\n" +
+                "            } else if ('0' <= ch && ch <= '9'\n" +
+                "                    || ch == '-') {\n" +
+                "                if (!allowNumber)\n" +
+                "                     return false;\n" +
+                "            } else if (ch == '/' || ch == '.') {\n" +
+                "                if (!allowSep)\n" +
+                "                    return false;\n" +
+                "                allowNumber = false;\n" +
+                "                allowSep = false;\n" +
+                "                if (ch == '.')\n" +
+                "                     seenDot = true;\n" +
+                "                if (ch == '/' && seenDot)\n" +
+                "                     return false;\n" +
+                "            } else {\n" +
+                "                return false;\n" +
+                "            }\n" +
+                "        }\n" +
+                "        return true;\n" +
+                "    }\n" +
+                "    function loadFrames() {\n" +
+                "        if (targetPage != \"\" && targetPage != \"undefined\")\n" +
+                "             top.classFrame.location = top.targetPage;\n" +
+                "    }\n");
+    }
 }
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HelpWriter.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HelpWriter.java	Mon Nov 27 17:04:45 2017 +0000
@@ -29,6 +29,7 @@
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
+import jdk.javadoc.internal.doclets.formats.html.markup.Links;
 import jdk.javadoc.internal.doclets.formats.html.markup.StringContent;
 import jdk.javadoc.internal.doclets.toolkit.Content;
 import jdk.javadoc.internal.doclets.toolkit.util.DocFileIOException;
@@ -124,7 +125,7 @@
         }
         HtmlTree htmlTree;
         HtmlTree ul = new HtmlTree(HtmlTag.UL);
-        ul.addStyle(HtmlStyle.blockList);
+        ul.setStyle(HtmlStyle.blockList);
         if (configuration.createoverview) {
             Content overviewHeading = HtmlTree.HEADING(HtmlConstants.CONTENT_HEADING,
                 contents.overviewLabel);
@@ -132,7 +133,7 @@
                     ? HtmlTree.SECTION(overviewHeading)
                     : HtmlTree.LI(HtmlStyle.blockList, overviewHeading);
             Content line3 = contents.getContent("doclet.Help_line_3",
-                    getHyperLink(DocPaths.overviewSummary(configuration.frames),
+                    Links.createLink(DocPaths.overviewSummary(configuration.frames),
                     configuration.getText("doclet.Overview")));
             Content overviewPara = HtmlTree.P(line3);
             htmlTree.addContent(overviewPara);
@@ -282,7 +283,7 @@
                     ? HtmlTree.SECTION(treeHead)
                     : HtmlTree.LI(HtmlStyle.blockList, treeHead);
             Content line17 = contents.getContent("doclet.Help_line_17_with_tree_link",
-                    getHyperLink(DocPaths.OVERVIEW_TREE,
+                    Links.createLink(DocPaths.OVERVIEW_TREE,
                     configuration.getText("doclet.Class_Hierarchy")),
                     HtmlTree.CODE(new StringContent("java.lang.Object")));
             Content treePara = HtmlTree.P(line17);
@@ -307,7 +308,7 @@
                     ? HtmlTree.SECTION(dHead)
                     : HtmlTree.LI(HtmlStyle.blockList, dHead);
             Content line20 = contents.getContent("doclet.Help_line_20_with_deprecated_api_link",
-                    getHyperLink(DocPaths.DEPRECATED_LIST,
+                    Links.createLink(DocPaths.DEPRECATED_LIST,
                     configuration.getText("doclet.Deprecated_API")));
             Content dPara = HtmlTree.P(line20);
             htmlTree.addContent(dPara);
@@ -320,10 +321,10 @@
         if (configuration.createindex) {
             Content indexlink;
             if (configuration.splitindex) {
-                indexlink = getHyperLink(DocPaths.INDEX_FILES.resolve(DocPaths.indexN(1)),
+                indexlink = Links.createLink(DocPaths.INDEX_FILES.resolve(DocPaths.indexN(1)),
                         configuration.getText("doclet.Index"));
             } else {
-                indexlink = getHyperLink(DocPaths.INDEX_ALL,
+                indexlink = Links.createLink(DocPaths.INDEX_ALL,
                         configuration.getText("doclet.Index"));
             }
             Content indexHead = HtmlTree.HEADING(HtmlConstants.CONTENT_HEADING,
@@ -377,7 +378,7 @@
                 ? HtmlTree.SECTION(allclassesHead)
                 : HtmlTree.LI(HtmlStyle.blockList, allclassesHead);
         Content line27 = contents.getContent("doclet.Help_line_27",
-                getHyperLink(DocPaths.AllClasses(configuration.frames),
+                Links.createLink(DocPaths.AllClasses(configuration.frames),
                 resources.getText("doclet.All_Classes")));
         Content allclassesPara = HtmlTree.P(line27);
         htmlTree.addContent(allclassesPara);
@@ -405,7 +406,7 @@
                 ? HtmlTree.SECTION(constHead)
                 : HtmlTree.LI(HtmlStyle.blockList, constHead);
         Content line29 = contents.getContent("doclet.Help_line_29",
-                getHyperLink(DocPaths.CONSTANT_VALUES,
+                Links.createLink(DocPaths.CONSTANT_VALUES,
                 resources.getText("doclet.Constants_Summary")));
         Content constPara = HtmlTree.P(line29);
         htmlTree.addContent(constPara);
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlConfiguration.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlConfiguration.java	Mon Nov 27 17:04:45 2017 +0000
@@ -27,6 +27,7 @@
 
 import java.net.*;
 import java.util.*;
+import java.util.stream.Collectors;
 
 import javax.lang.model.element.Element;
 import javax.lang.model.element.PackageElement;
@@ -43,6 +44,7 @@
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlConstants;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlVersion;
+import jdk.javadoc.internal.doclets.formats.html.markup.Links;
 import jdk.javadoc.internal.doclets.toolkit.BaseConfiguration;
 import jdk.javadoc.internal.doclets.toolkit.Content;
 import jdk.javadoc.internal.doclets.toolkit.DocletException;
@@ -82,12 +84,6 @@
 public class HtmlConfiguration extends BaseConfiguration {
 
     /**
-     * The build date.  Note: For now, we will use
-     * a version number instead of a date.
-     */
-    public static final String BUILD_DATE = System.getProperty("java.version");
-
-    /**
      * Argument for command line option "-header".
      */
     public String header = "";
@@ -244,13 +240,16 @@
 
     protected Set<Character> tagSearchIndexKeys;
 
-    protected Contents contents;
+    protected final Contents contents;
 
-    protected Messages messages;
+    protected final Messages messages;
+
+    protected Links links;
 
     /**
-     * Constructor. Initializes resource for the
-     * {@link jdk.javadoc.internal.tool.Messager Messager}.
+     * Creates an object to hold the configuration for a doclet.
+     *
+     * @param doclet the doclet
      */
     public HtmlConfiguration(Doclet doclet) {
         super(doclet);
@@ -260,30 +259,28 @@
 
         messages = new Messages(this);
         contents = new Contents(this);
+
+        String v;
+        try {
+            ResourceBundle rb = ResourceBundle.getBundle(versionBundleName, getLocale());
+            try {
+                v = rb.getString("release");
+            } catch (MissingResourceException e) {
+                v = defaultDocletVersion;
+            }
+        } catch (MissingResourceException e) {
+            v = defaultDocletVersion;
+        }
+        docletVersion = v;
     }
 
-    private final String versionRBName = "jdk.javadoc.internal.tool.resources.version";
-    private ResourceBundle versionRB;
+    private static final String versionBundleName = "jdk.javadoc.internal.tool.resources.version";
+    private static final String defaultDocletVersion = System.getProperty("java.version");
+    public final String docletVersion;
 
-    /**
-     * Return the build date for the doclet.
-     * @return the build date
-     */
     @Override
-    public String getDocletSpecificBuildDate() {
-        if (versionRB == null) {
-            try {
-                versionRB = ResourceBundle.getBundle(versionRBName, getLocale());
-            } catch (MissingResourceException e) {
-                return BUILD_DATE;
-            }
-        }
-
-        try {
-            return versionRB.getString("release");
-        } catch (MissingResourceException e) {
-            return BUILD_DATE;
-        }
+    public String getDocletVersion() {
+        return docletVersion;
     }
 
     @Override
@@ -359,6 +356,7 @@
         setTopFile(docEnv);
         workArounds.initDocLint(doclintOpts.values(), tagletManager.getCustomTagNames(),
                 Utils.toLowerCase(htmlVersion.name()));
+        links = new Links(htmlVersion);
         return true;
     }
 
@@ -480,6 +478,16 @@
         return null;
     }
 
+    public DocFile getMainStylesheet() {
+        return stylesheetfile.isEmpty() ? null : DocFile.createFileForInput(this, stylesheetfile);
+    }
+
+    public List<DocFile> getAdditionalStylesheets() {
+        return additionalStylesheets.stream()
+                .map(ssf -> DocFile.createFileForInput(this, ssf))
+                .collect(Collectors.toList());
+    }
+
     /**
      * {@inheritDoc}
      */
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java	Mon Nov 27 17:04:45 2017 +0000
@@ -25,7 +25,9 @@
 
 package jdk.javadoc.internal.doclets.formats.html;
 
-import java.text.SimpleDateFormat;
+import jdk.javadoc.internal.doclets.formats.html.markup.Head;
+import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader;
+
 import java.util.*;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
@@ -65,17 +67,17 @@
 import com.sun.source.doctree.TextTree;
 import com.sun.source.util.SimpleDocTreeVisitor;
 
-import jdk.javadoc.internal.doclets.formats.html.markup.Comment;
 import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder;
 import jdk.javadoc.internal.doclets.formats.html.markup.DocType;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlAttr;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlConstants;
-import jdk.javadoc.internal.doclets.formats.html.markup.HtmlDocWriter;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlDocument;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
+import jdk.javadoc.internal.doclets.formats.html.markup.Links;
 import jdk.javadoc.internal.doclets.formats.html.markup.RawHtml;
+import jdk.javadoc.internal.doclets.formats.html.markup.Script;
 import jdk.javadoc.internal.doclets.formats.html.markup.StringContent;
 import jdk.javadoc.internal.doclets.toolkit.AnnotationTypeWriter;
 import jdk.javadoc.internal.doclets.toolkit.ClassWriter;
@@ -92,9 +94,7 @@
 import jdk.javadoc.internal.doclets.toolkit.util.DocPath;
 import jdk.javadoc.internal.doclets.toolkit.util.DocPaths;
 import jdk.javadoc.internal.doclets.toolkit.util.DocletConstants;
-import jdk.javadoc.internal.doclets.toolkit.util.GroupTypes;
 import jdk.javadoc.internal.doclets.toolkit.util.ImplementedMethods;
-import jdk.javadoc.internal.doclets.toolkit.util.TableTabTypes.TableTabs;
 import jdk.javadoc.internal.doclets.toolkit.util.Utils;
 import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberMap;
 
@@ -116,7 +116,7 @@
  * @author Robert Field
  * @author Bhavesh Patel (Modified)
  */
-public class HtmlDocletWriter extends HtmlDocWriter {
+public class HtmlDocletWriter {
 
     /**
      * Relative path from the file getting generated to the destination
@@ -153,6 +153,8 @@
 
     protected final Resources resources;
 
+    protected final Links links;
+
     /**
      * To check whether annotation heading is printed or not.
      */
@@ -178,20 +180,31 @@
     final static Pattern IMPROPER_HTML_CHARS = Pattern.compile(".*[&<>].*");
 
     /**
+     * The window title of this file.
+     */
+    protected String winTitle;
+
+    protected Script mainBodyScript;
+
+    /**
      * Constructor to construct the HtmlStandardWriter object.
      *
-     * @param path File to be generated.
+     * @param configuration the configuration for this doclet
+     * @param path the file to be generated.
      */
     public HtmlDocletWriter(HtmlConfiguration configuration, DocPath path) {
-        super(configuration, path);
         this.configuration = configuration;
         this.contents = configuration.contents;
         this.messages = configuration.messages;
         this.resources = configuration.resources;
+        this.links = configuration.links;
         this.utils = configuration.utils;
         this.path = path;
         this.pathToRoot = path.parent().invert();
         this.filename = path.basename();
+
+        messages.notice("doclet.Generating_0",
+            DocFile.createFileForOutput(configuration, path).getPath());
     }
 
     /**
@@ -258,19 +271,18 @@
      * @return a content tree for the script
      */
     public Content getAllClassesLinkScript(String id) {
-        HtmlTree script = HtmlTree.SCRIPT();
-        String scriptCode = "<!--\n" +
-                "  allClassesLink = document.getElementById(\"" + id + "\");\n" +
+        Script script = new Script("<!--\n" +
+                "  allClassesLink = document.getElementById(")
+                .appendStringLiteral(id)
+                .append(");\n" +
                 "  if(window==top) {\n" +
                 "    allClassesLink.style.display = \"block\";\n" +
                 "  }\n" +
                 "  else {\n" +
                 "    allClassesLink.style.display = \"none\";\n" +
                 "  }\n" +
-                "  //-->\n";
-        Content scriptContent = new RawHtml(scriptCode.replace("\n", DocletConstants.NL));
-        script.addContent(scriptContent);
-        Content div = HtmlTree.DIV(script);
+                "  //-->\n");
+        Content div = HtmlTree.DIV(script.asContent());
         Content div_noscript = HtmlTree.DIV(contents.noScriptMessage);
         Content noScript = HtmlTree.NOSCRIPT(div_noscript);
         div.addContent(noScript);
@@ -359,7 +371,7 @@
      */
     public Content getTargetPackageLink(PackageElement pkg, String target,
             Content label) {
-        return getHyperLink(pathString(pkg, DocPaths.PACKAGE_SUMMARY), label, "", target);
+        return Links.createLink(pathString(pkg, DocPaths.PACKAGE_SUMMARY), label, "", target);
     }
 
     /**
@@ -373,7 +385,7 @@
      */
     public Content getTargetModulePackageLink(PackageElement pkg, String target,
             Content label, ModuleElement mdle) {
-        return getHyperLink(pathString(pkg, DocPaths.PACKAGE_SUMMARY),
+        return Links.createLink(pathString(pkg, DocPaths.PACKAGE_SUMMARY),
                 label, "", target);
     }
 
@@ -386,7 +398,7 @@
      * @return a content for the target module link
      */
     public Content getTargetModuleLink(String target, Content label, ModuleElement mdle) {
-        return getHyperLink(pathToRoot.resolve(
+        return Links.createLink(pathToRoot.resolve(
                 DocPaths.moduleSummary(mdle)), label, "", target);
     }
 
@@ -403,35 +415,19 @@
      */
     public void printHtmlDocument(List<String> metakeywords, boolean includeScript,
             Content body) throws DocFileIOException {
-        Content htmlDocType = configuration.isOutputHtml5()
-                ? DocType.HTML5
-                : DocType.TRANSITIONAL;
-        Content htmlComment = new Comment(configuration.getText("doclet.New_Page"));
-        Content head = new HtmlTree(HtmlTag.HEAD);
-        head.addContent(getGeneratedBy(!configuration.notimestamp));
-        head.addContent(getTitle());
-        Content meta = HtmlTree.META("Content-Type", CONTENT_TYPE, configuration.charset);
-        head.addContent(meta);
-        if (!configuration.notimestamp) {
-            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
-            meta = HtmlTree.META(configuration.isOutputHtml5()
-                    ? "dc.created"
-                    : "date", dateFormat.format(new Date()));
-            head.addContent(meta);
-        }
-        if (metakeywords != null) {
-            for (String metakeyword : metakeywords) {
-                meta = HtmlTree.META("keywords", metakeyword);
-                head.addContent(meta);
-            }
-        }
-        addStyleSheetProperties(head);
-        addScriptProperties(head);
-        Content htmlTree = HtmlTree.HTML(configuration.getLocale().getLanguage(),
-                head, body);
-        Content htmlDocument = new HtmlDocument(htmlDocType,
-                htmlComment, htmlTree);
-        write(htmlDocument);
+        DocType htmlDocType = DocType.forVersion(configuration.htmlVersion);
+        Content htmlComment = contents.newPage;
+        Head head = new Head(path, configuration.htmlVersion, configuration.docletVersion)
+                .setTimestamp(!configuration.notimestamp)
+                .setTitle(winTitle)
+                .setCharset(configuration.charset)
+                .addKeywords(metakeywords)
+                .setStylesheets(configuration.getMainStylesheet(), configuration.getAdditionalStylesheets())
+                .setIndex(configuration.createindex, mainBodyScript);
+
+        Content htmlTree = HtmlTree.HTML(configuration.getLocale().getLanguage(), head.toContent(), body);
+        HtmlDocument htmlDocument = new HtmlDocument(htmlDocType, htmlComment, htmlTree);
+        htmlDocument.write(DocFile.createFileForOutput(configuration, path));
     }
 
     /**
@@ -503,37 +499,37 @@
                     : htmlTree;
             String allClassesId = "allclasses_";
             HtmlTree navDiv = new HtmlTree(HtmlTag.DIV);
-            fixedNavDiv.addStyle(HtmlStyle.fixedNav);
+            fixedNavDiv.setStyle(HtmlStyle.fixedNav);
             Content skipNavLinks = configuration.getContent("doclet.Skip_navigation_links");
             if (header) {
                 fixedNavDiv.addContent(HtmlConstants.START_OF_TOP_NAVBAR);
-                navDiv.addStyle(HtmlStyle.topNav);
+                navDiv.setStyle(HtmlStyle.topNav);
                 allClassesId += "navbar_top";
-                Content a = getMarkerAnchor(SectionName.NAVBAR_TOP);
+                Content a = links.createAnchor(SectionName.NAVBAR_TOP);
                 //WCAG - Hyperlinks should contain text or an image with alt text - for AT tools
                 navDiv.addContent(a);
-                Content skipLinkContent = HtmlTree.DIV(HtmlStyle.skipNav, getHyperLink(
-                    getDocLink(SectionName.SKIP_NAVBAR_TOP), skipNavLinks,
-                    skipNavLinks.toString(), ""));
+                Content skipLinkContent = HtmlTree.DIV(HtmlStyle.skipNav,
+                        Links.createLink(SectionName.SKIP_NAVBAR_TOP, skipNavLinks,
+                        skipNavLinks.toString(), ""));
                 navDiv.addContent(skipLinkContent);
             } else {
                 tree.addContent(HtmlConstants.START_OF_BOTTOM_NAVBAR);
-                navDiv.addStyle(HtmlStyle.bottomNav);
+                navDiv.setStyle(HtmlStyle.bottomNav);
                 allClassesId += "navbar_bottom";
-                Content a = getMarkerAnchor(SectionName.NAVBAR_BOTTOM);
+                Content a = links.createAnchor(SectionName.NAVBAR_BOTTOM);
                 navDiv.addContent(a);
-                Content skipLinkContent = HtmlTree.DIV(HtmlStyle.skipNav, getHyperLink(
-                    getDocLink(SectionName.SKIP_NAVBAR_BOTTOM), skipNavLinks,
-                    skipNavLinks.toString(), ""));
+                Content skipLinkContent = HtmlTree.DIV(HtmlStyle.skipNav,
+                        Links.createLink(SectionName.SKIP_NAVBAR_BOTTOM, skipNavLinks,
+                        skipNavLinks.toString(), ""));
                 navDiv.addContent(skipLinkContent);
             }
             if (header) {
-                navDiv.addContent(getMarkerAnchor(SectionName.NAVBAR_TOP_FIRSTROW));
+                navDiv.addContent(links.createAnchor(SectionName.NAVBAR_TOP_FIRSTROW));
             } else {
-                navDiv.addContent(getMarkerAnchor(SectionName.NAVBAR_BOTTOM_FIRSTROW));
+                navDiv.addContent(links.createAnchor(SectionName.NAVBAR_BOTTOM_FIRSTROW));
             }
             HtmlTree navList = new HtmlTree(HtmlTag.UL);
-            navList.addStyle(HtmlStyle.navList);
+            navList.setStyle(HtmlStyle.navList);
             navList.addAttr(HtmlAttr.TITLE,
                             configuration.getText("doclet.Navigation"));
             if (configuration.createoverview) {
@@ -601,21 +597,19 @@
             subDiv.addContent(getAllClassesLinkScript(allClassesId));
             addSummaryDetailLinks(subDiv);
             if (header) {
-                subDiv.addContent(getMarkerAnchor(SectionName.SKIP_NAVBAR_TOP));
+                subDiv.addContent(links.createAnchor(SectionName.SKIP_NAVBAR_TOP));
                 fixedNavDiv.addContent(subDiv);
                 fixedNavDiv.addContent(HtmlConstants.END_OF_TOP_NAVBAR);
                 tree.addContent(fixedNavDiv);
                 HtmlTree paddingDiv = HtmlTree.DIV(HtmlStyle.navPadding, Contents.SPACE);
                 tree.addContent(paddingDiv);
-                HtmlTree scriptTree = HtmlTree.SCRIPT();
-                String scriptCode = "<!--\n"
+                Script script = new Script(
+                        "<!--\n"
                         + "$('.navPadding').css('padding-top', $('.fixedNav').css(\"height\"));\n"
-                        + "//-->\n";
-                RawHtml scriptContent = new RawHtml(scriptCode.replace("\n", DocletConstants.NL));
-                scriptTree.addContent(scriptContent);
-                tree.addContent(scriptTree);
+                        + "//-->\n");
+                tree.addContent(script.asContent());
             } else {
-                subDiv.addContent(getMarkerAnchor(SectionName.SKIP_NAVBAR_BOTTOM));
+                subDiv.addContent(links.createAnchor(SectionName.SKIP_NAVBAR_BOTTOM));
                 tree.addContent(subDiv);
                 tree.addContent(HtmlConstants.END_OF_BOTTOM_NAVBAR);
             }
@@ -657,7 +651,7 @@
      * @return a content tree for the link
      */
     protected Content getNavLinkContents() {
-        Content linkContent = getHyperLink(pathToRoot.resolve(DocPaths.overviewSummary(configuration.frames)),
+        Content linkContent = Links.createLink(pathToRoot.resolve(DocPaths.overviewSummary(configuration.frames)),
                 contents.overviewLabel, "", "");
         Content li = HtmlTree.LI(linkContent);
         return li;
@@ -726,7 +720,7 @@
     public Content getNavLinkPrevious(DocPath prev) {
         Content li;
         if (prev != null) {
-            li = HtmlTree.LI(getHyperLink(prev, contents.prevLabel, "", ""));
+            li = HtmlTree.LI(Links.createLink(prev, contents.prevLabel, "", ""));
         }
         else
             li = HtmlTree.LI(contents.prevLabel);
@@ -743,7 +737,7 @@
     public Content getNavLinkNext(DocPath next) {
         Content li;
         if (next != null) {
-            li = HtmlTree.LI(getHyperLink(next, contents.nextLabel, "", ""));
+            li = HtmlTree.LI(Links.createLink(next, contents.nextLabel, "", ""));
         }
         else
             li = HtmlTree.LI(contents.nextLabel);
@@ -758,7 +752,7 @@
      */
     protected Content getNavShowLists(DocPath link) {
         DocLink dl = new DocLink(link, path.getPath(), null);
-        Content framesContent = getHyperLink(dl, contents.framesLabel, "", "_top");
+        Content framesContent = Links.createLink(dl, contents.framesLabel, "", "_top");
         Content li = HtmlTree.LI(framesContent);
         return li;
     }
@@ -779,7 +773,7 @@
      * @return a content tree for the link
      */
     protected Content getNavHideLists(DocPath link) {
-        Content noFramesContent = getHyperLink(link, contents.noFramesLabel, "", "_top");
+        Content noFramesContent = Links.createLink(link, contents.noFramesLabel, "", "_top");
         Content li = HtmlTree.LI(noFramesContent);
         return li;
     }
@@ -797,7 +791,7 @@
         DocPath docPath = packages.size() == 1 && configuration.getSpecifiedTypeElements().isEmpty()
                 ? pathString(packages.get(0), DocPaths.PACKAGE_TREE)
                 : pathToRoot.resolve(DocPaths.OVERVIEW_TREE);
-        return HtmlTree.LI(getHyperLink(docPath, contents.treeLabel, "", ""));
+        return HtmlTree.LI(Links.createLink(docPath, contents.treeLabel, "", ""));
     }
 
     /**
@@ -807,7 +801,7 @@
      * @return a content tree for the link
      */
     protected Content getNavLinkMainTree(String label) {
-        Content mainTreeContent = getHyperLink(pathToRoot.resolve(DocPaths.OVERVIEW_TREE),
+        Content mainTreeContent = Links.createLink(pathToRoot.resolve(DocPaths.OVERVIEW_TREE),
                 new StringContent(label));
         Content li = HtmlTree.LI(mainTreeContent);
         return li;
@@ -829,7 +823,7 @@
      * @return a content tree for the link
      */
     protected Content getNavLinkDeprecated() {
-        Content linkContent = getHyperLink(pathToRoot.resolve(DocPaths.DEPRECATED_LIST),
+        Content linkContent = Links.createLink(pathToRoot.resolve(DocPaths.DEPRECATED_LIST),
                 contents.deprecatedLabel, "", "");
         Content li = HtmlTree.LI(linkContent);
         return li;
@@ -843,7 +837,7 @@
      * @return a content tree for the link
      */
     protected Content getNavLinkClassIndex() {
-        Content allClassesContent = getHyperLink(pathToRoot.resolve(
+        Content allClassesContent = Links.createLink(pathToRoot.resolve(
                 DocPaths.AllClasses(configuration.frames)),
                 contents.allClassesLabel, "", "");
         Content li = HtmlTree.LI(allClassesContent);
@@ -856,7 +850,7 @@
      * @return a content tree for the link
      */
     protected Content getNavLinkIndex() {
-        Content linkContent = getHyperLink(pathToRoot.resolve(
+        Content linkContent = Links.createLink(pathToRoot.resolve(
                 (configuration.splitindex
                     ? DocPaths.INDEX_FILES.resolve(DocPaths.indexN(1))
                     : DocPaths.INDEX_ALL)),
@@ -881,7 +875,7 @@
             DocFile file = DocFile.createFileForInput(configuration, helpfile);
             helpfilenm = DocPath.create(file.getName());
         }
-        Content linkContent = getHyperLink(pathToRoot.resolve(helpfilenm),
+        Content linkContent = Links.createLink(pathToRoot.resolve(helpfilenm),
                 contents.helpLabel, "", "");
         Content li = HtmlTree.LI(linkContent);
         return li;
@@ -914,118 +908,6 @@
     }
 
     /**
-     * Get table header.
-     *
-     * @param caption the table caption
-     * @param tableSummary the summary for the table
-     * @param tableStyle the table style
-     * @return a content object
-     */
-    public Content getTableHeader(Content caption, String tableSummary, HtmlStyle tableStyle) {
-        Content table = (configuration.isOutputHtml5())
-                ? HtmlTree.TABLE(tableStyle, caption)
-                : HtmlTree.TABLE(tableStyle, tableSummary, caption);
-        return table;
-    }
-
-    /**
-     * Get the summary table caption.
-     *
-     * @param groupTypes the group types for table tabs
-     * @return the caption for the summary table
-     */
-    public Content getTableCaption(GroupTypes groupTypes) {
-        Content tabbedCaption = new HtmlTree(HtmlTag.CAPTION);
-        Map<String, TableTabs> groups = groupTypes.getGroupTypes();
-        for (String group : groups.keySet()) {
-            Content captionSpan;
-            Content span;
-            TableTabs tab = groups.get(group);
-            if (tab.isDefaultTab()) {
-                captionSpan = HtmlTree.SPAN(new StringContent(tab.resourceKey()));
-                span = HtmlTree.SPAN(tab.tabId(),
-                        HtmlStyle.activeTableTab, captionSpan);
-            } else {
-                captionSpan = HtmlTree.SPAN(getGroupTypeLinks(groupTypes, group));
-                span = HtmlTree.SPAN(tab.tabId(),
-                        HtmlStyle.tableTab, captionSpan);
-            }
-            Content tabSpan = HtmlTree.SPAN(HtmlStyle.tabEnd, Contents.SPACE);
-            span.addContent(tabSpan);
-            tabbedCaption.addContent(span);
-        }
-        return tabbedCaption;
-    }
-
-    /**
-     * Get the group type links for the table caption.
-     *
-     * @param groupTypes the group types for table tabs
-     * @param groupName the group name to be displayed as link
-     * @return the content tree for the group type link
-     */
-    public Content getGroupTypeLinks(GroupTypes groupTypes, String groupName) {
-        String jsShow = "javascript:showGroups(" + groupTypes.getTableTab(groupName).value() + ");";
-        HtmlTree link = HtmlTree.A(jsShow, new StringContent(groupTypes.getTableTab(groupName).resourceKey()));
-        return link;
-    }
-
-    /**
-     * Returns true if the table tabs needs to be displayed.
-     *
-     * @param groupTypes the group types for table tabs
-     * @return true if the tabs should be displayed
-     */
-    public boolean showTabs(GroupTypes groupTypes) {
-        return groupTypes.getGroupTypes().size() > 1;
-    }
-
-    /**
-     * Get the marker anchor which will be added to the documentation tree.
-     *
-     * @param anchorName the anchor name attribute
-     * @return a content tree for the marker anchor
-     */
-    public Content getMarkerAnchor(String anchorName) {
-        return getMarkerAnchor(getName(anchorName), null);
-    }
-
-    /**
-     * Get the marker anchor which will be added to the documentation tree.
-     *
-     * @param sectionName the section name anchor attribute for page
-     * @return a content tree for the marker anchor
-     */
-    public Content getMarkerAnchor(SectionName sectionName) {
-        return getMarkerAnchor(sectionName.getName(), null);
-    }
-
-    /**
-     * Get the marker anchor which will be added to the documentation tree.
-     *
-     * @param sectionName the section name anchor attribute for page
-     * @param anchorName the anchor name combined with section name attribute for the page
-     * @return a content tree for the marker anchor
-     */
-    public Content getMarkerAnchor(SectionName sectionName, String anchorName) {
-        return getMarkerAnchor(sectionName.getName() + getName(anchorName), null);
-    }
-
-    /**
-     * Get the marker anchor which will be added to the documentation tree.
-     *
-     * @param anchorName the anchor name or id attribute
-     * @param anchorContent the content that should be added to the anchor
-     * @return a content tree for the marker anchor
-     */
-    public Content getMarkerAnchor(String anchorName, Content anchorContent) {
-        if (anchorContent == null)
-            anchorContent = new Comment(" ");
-        Content markerAnchor = HtmlTree.A(configuration.htmlVersion, anchorName, anchorContent);
-        return markerAnchor;
-    }
-
-    /**
      * Returns a packagename content.
      *
      * @param packageElement the package to check
@@ -1117,12 +999,12 @@
             }
         }
         if (included || packageElement == null) {
-            return getHyperLink(pathString(packageElement, DocPaths.PACKAGE_SUMMARY),
+            return Links.createLink(pathString(packageElement, DocPaths.PACKAGE_SUMMARY),
                     label);
         } else {
             DocLink crossPkgLink = getCrossPackageLink(utils.getPackageName(packageElement));
             if (crossPkgLink != null) {
-                return getHyperLink(crossPkgLink, label);
+                return Links.createLink(crossPkgLink, label);
             } else {
                 return label;
             }
@@ -1139,7 +1021,7 @@
     public Content getModuleLink(ModuleElement mdle, Content label) {
         boolean included = utils.isIncluded(mdle);
         return (included)
-                ? getHyperLink(pathToRoot.resolve(DocPaths.moduleSummary(mdle)), label, "", "")
+                ? Links.createLink(pathToRoot.resolve(DocPaths.moduleSummary(mdle)), label, "", "")
                 : label;
     }
 
@@ -1169,7 +1051,7 @@
         DocPath href = pathToRoot
                 .resolve(DocPaths.SOURCE_OUTPUT)
                 .resolve(DocPath.forClass(utils, te));
-        Content linkContent = getHyperLink(href
+        Content linkContent = Links.createLink(href
                 .fragment(SourceToHTMLConverter.getAnchorName(utils, typeElement)), label, "", "");
         htmltree.addContent(linkContent);
     }
@@ -1208,12 +1090,11 @@
      * be null or empty string if no member is being referenced.
      * @param label the label for the external link.
      * @param strong true if the link should be strong.
-     * @param style the style of the link.
      * @param code true if the label should be code font.
+     * @return the link
      */
     public Content getCrossClassLink(String qualifiedClassName, String refMemName,
-                                    Content label, boolean strong, String style,
-                                    boolean code) {
+                                    Content label, boolean strong, boolean code) {
         String className = "";
         String packageName = qualifiedClassName == null ? "" : qualifiedClassName;
         int periodIndex;
@@ -1234,10 +1115,10 @@
                 */
                 DocLink link = configuration.extern.getExternalLink(packageName, pathToRoot,
                                 className + ".html", refMemName);
-                return getHyperLink(link,
+                return Links.createLink(link,
                     (label == null) || label.isEmpty() ? defaultLabel : label,
-                    strong, style,
-                    configuration.getText("doclet.Href_Class_Or_Interface_Title", packageName),
+                    strong,
+                    resources.getText("doclet.Href_Class_Or_Interface_Title", packageName),
                     "");
             }
         }
@@ -1324,6 +1205,18 @@
     }
 
     /**
+     * Get the enclosed name of the package
+     *
+     * @param te  TypeElement
+     * @return the name
+     */
+    public String getEnclosingPackageName(TypeElement te) {
+
+        PackageElement encl = configuration.utils.containingPackage(te);
+        return (encl.isUnnamed()) ? "" : (encl.getQualifiedName() + ".");
+    }
+
+    /**
      * Add the class link, with only class name as the strong link and prefixing
      * plain package name.
      *
@@ -1418,12 +1311,12 @@
             ExecutableElement ee = (ExecutableElement)element;
             return getLink(new LinkInfoImpl(configuration, context, typeElement)
                 .label(label)
-                .where(getName(getAnchor(ee, isProperty)))
+                .where(links.getName(getAnchor(ee, isProperty)))
                 .strong(strong));
         } else if (utils.isVariableElement(element) || utils.isTypeElement(element)) {
             return getLink(new LinkInfoImpl(configuration, context, typeElement)
                 .label(label)
-                .where(getName(element.getSimpleName().toString()))
+                .where(links.getName(element.getSimpleName().toString()))
                 .strong(strong));
         } else {
             return label;
@@ -1449,10 +1342,10 @@
             ExecutableElement emd = (ExecutableElement) element;
             return getLink(new LinkInfoImpl(configuration, context, typeElement)
                 .label(label)
-                .where(getName(getAnchor(emd))));
+                .where(links.getName(getAnchor(emd))));
         } else if (utils.isVariableElement(element) || utils.isTypeElement(element)) {
             return getLink(new LinkInfoImpl(configuration, context, typeElement)
-                .label(label).where(getName(element.getSimpleName().toString())));
+                .label(label).where(links.getName(element.getSimpleName().toString())));
         } else {
             return label;
         }
@@ -1523,10 +1416,10 @@
                 DocLink packageCrossLink = getCrossPackageLink(refClassName);
                 if (packageCrossLink != null) {
                     // Package cross link found
-                    return getHyperLink(packageCrossLink,
+                    return Links.createLink(packageCrossLink,
                         (label.isEmpty() ? text : label));
                 } else if ((classCrossLink = getCrossClassLink(refClassName,
-                        refMemName, label, false, "", !isLinkPlain)) != null) {
+                        refMemName, label, false, !isLinkPlain)) != null) {
                     // Class cross link found (possibly to a member in the class)
                     return classCrossLink;
                 } else {
@@ -2136,76 +2029,6 @@
         return text;
     }
 
-    static final Set<String> blockTags = new HashSet<>();
-    static {
-        for (HtmlTag t: HtmlTag.values()) {
-            if (t.blockType == HtmlTag.BlockType.BLOCK)
-                blockTags.add(t.value);
-        }
-    }
-
-    /**
-     * Add a link to the stylesheet file.
-     *
-     * @param head the content tree to which the files will be added
-     */
-    public void addStyleSheetProperties(Content head) {
-        String stylesheetfile = configuration.stylesheetfile;
-        DocPath stylesheet;
-        if (stylesheetfile.isEmpty()) {
-            stylesheet = DocPaths.STYLESHEET;
-        } else {
-            DocFile file = DocFile.createFileForInput(configuration, stylesheetfile);
-            stylesheet = DocPath.create(file.getName());
-        }
-        HtmlTree link = HtmlTree.LINK("stylesheet", "text/css",
-                pathToRoot.resolve(stylesheet).getPath(),
-                "Style");
-        head.addContent(link);
-        addStylesheets(configuration, head);
-        if (configuration.createindex) {
-            HtmlTree jq_link = HtmlTree.LINK("stylesheet", "text/css",
-                    pathToRoot.resolve(DocPaths.JQUERY_FILES.resolve(DocPaths.JQUERY_STYLESHEET_FILE)).getPath(),
-                    "Style");
-            head.addContent(jq_link);
-        }
-    }
-
-    /**
-     * Add a link to the JavaScript file.
-     *
-     * @param head the content tree to which the files will be added
-     */
-    public void addScriptProperties(Content head) {
-        HtmlTree javascript = HtmlTree.SCRIPT(pathToRoot.resolve(DocPaths.JAVASCRIPT).getPath());
-        head.addContent(javascript);
-        if (configuration.createindex) {
-            if (pathToRoot != null && script != null) {
-                String ptrPath = pathToRoot.isEmpty() ? "." : pathToRoot.getPath();
-                script.addContent(new RawHtml("var pathtoroot = \"" + ptrPath + "/\";loadScripts(document, \'script\');"));
-            }
-            addJQueryFile(head, DocPaths.JSZIP_MIN);
-            addJQueryFile(head, DocPaths.JSZIPUTILS_MIN);
-            head.addContent(new RawHtml("<!--[if IE]>"));
-            addJQueryFile(head, DocPaths.JSZIPUTILS_IE_MIN);
-            head.addContent(new RawHtml("<![endif]-->"));
-            addJQueryFile(head, DocPaths.JQUERY_JS_1_10);
-            addJQueryFile(head, DocPaths.JQUERY_JS);
-        }
-    }
-
-    /**
-     * Add a link to the JQuery javascript file.
-     *
-     * @param head the content tree to which the files will be added
-     * @param filePath the DocPath of the file that needs to be added
-     */
-    private void addJQueryFile(Content head, DocPath filePath) {
-        HtmlTree jqyeryScriptFile = HtmlTree.SCRIPT(
-                pathToRoot.resolve(DocPaths.JQUERY_FILES.resolve(filePath)).getPath());
-        head.addContent(jqyeryScriptFile);
-    }
-
     /**
      * According to
      * <cite>The Java&trade; Language Specification</cite>,
@@ -2251,7 +2074,7 @@
     }
 
     /**
-     * Adds the annotatation types for the given element.
+     * Adds the annotation types for the given element.
      *
      * @param element the package to write annotations for
      * @param htmltree the content tree to which the annotation types will be added
@@ -2614,4 +2437,53 @@
     protected TableHeader getPackageTableHeader() {
         return new TableHeader(contents.packageLabel, contents.descriptionLabel);
     }
+
+    /**
+     * Returns an HtmlTree for the SCRIPT tag.
+     *
+     * @return an HtmlTree for the SCRIPT tag
+     */
+    protected Script getWinTitleScript() {
+        Script script = new Script();
+        if (winTitle != null && winTitle.length() > 0) {
+            script.append("<!--\n" +
+                    "    try {\n" +
+                    "        if (location.href.indexOf('is-external=true') == -1) {\n" +
+                    "            parent.document.title=")
+                    .appendStringLiteral(winTitle)
+                    .append(";\n" +
+                    "        }\n" +
+                    "    }\n" +
+                    "    catch(err) {\n" +
+                    "    }\n" +
+                    "//-->\n");
+        }
+        return script;
+    }
+
+    /**
+     * Returns an HtmlTree for the BODY tag.
+     *
+     * @param includeScript  set true if printing windowtitle script
+     * @param title title for the window
+     * @return an HtmlTree for the BODY tag
+     */
+    public HtmlTree getBody(boolean includeScript, String title) {
+        HtmlTree body = new HtmlTree(HtmlTag.BODY);
+        // Set window title string which is later printed
+        this.winTitle = title;
+        // Don't print windowtitle script for overview-frame, allclasses-frame
+        // and package-frame
+        if (includeScript) {
+            this.mainBodyScript = getWinTitleScript();
+            body.addContent(mainBodyScript.asContent());
+            Content noScript = HtmlTree.NOSCRIPT(HtmlTree.DIV(contents.noScriptMessage));
+            body.addContent(noScript);
+        }
+        return body;
+    }
+
+    Script getMainBodyScript() {
+        return mainBodyScript;
+    }
 }
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlSerialFieldWriter.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlSerialFieldWriter.java	Mon Nov 27 17:04:45 2017 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2017, 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
@@ -75,7 +75,7 @@
      */
     public Content getSerializableFieldsHeader() {
         HtmlTree ul = new HtmlTree(HtmlTag.UL);
-        ul.addStyle(HtmlStyle.blockList);
+        ul.setStyle(HtmlStyle.blockList);
         return ul;
     }
 
@@ -88,9 +88,9 @@
     public Content getFieldsContentHeader(boolean isLastContent) {
         HtmlTree li = new HtmlTree(HtmlTag.LI);
         if (isLastContent)
-            li.addStyle(HtmlStyle.blockListLast);
+            li.setStyle(HtmlStyle.blockListLast);
         else
-            li.addStyle(HtmlStyle.blockList);
+            li.setStyle(HtmlStyle.blockList);
         return li;
     }
 
@@ -104,7 +104,7 @@
      */
     public Content getSerializableFields(String heading, Content serializableFieldsTree) {
         HtmlTree li = new HtmlTree(HtmlTag.LI);
-        li.addStyle(HtmlStyle.blockList);
+        li.setStyle(HtmlStyle.blockList);
         if (serializableFieldsTree.isValid()) {
             Content headingContent = new StringContent(heading);
             Content serialHeading = HtmlTree.HEADING(HtmlConstants.SERIALIZED_MEMBER_HEADING,
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlSerialMethodWriter.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlSerialMethodWriter.java	Mon Nov 27 17:04:45 2017 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2017, 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
@@ -66,7 +66,7 @@
      */
     public Content getSerializableMethodsHeader() {
         HtmlTree ul = new HtmlTree(HtmlTag.UL);
-        ul.addStyle(HtmlStyle.blockList);
+        ul.setStyle(HtmlStyle.blockList);
         return ul;
     }
 
@@ -79,9 +79,9 @@
     public Content getMethodsContentHeader(boolean isLastContent) {
         HtmlTree li = new HtmlTree(HtmlTag.LI);
         if (isLastContent)
-            li.addStyle(HtmlStyle.blockListLast);
+            li.setStyle(HtmlStyle.blockListLast);
         else
-            li.addStyle(HtmlStyle.blockList);
+            li.setStyle(HtmlStyle.blockList);
         return li;
     }
 
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/IndexRedirectWriter.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/IndexRedirectWriter.java	Mon Nov 27 17:04:45 2017 +0000
@@ -25,15 +25,17 @@
 
 package jdk.javadoc.internal.doclets.formats.html;
 
-import jdk.javadoc.internal.doclets.formats.html.markup.Comment;
+import jdk.javadoc.internal.doclets.formats.html.markup.Head;
 import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder;
 import jdk.javadoc.internal.doclets.formats.html.markup.DocType;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlAttr;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlDocument;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
+import jdk.javadoc.internal.doclets.formats.html.markup.Script;
 import jdk.javadoc.internal.doclets.formats.html.markup.StringContent;
 import jdk.javadoc.internal.doclets.toolkit.Content;
+import jdk.javadoc.internal.doclets.toolkit.util.DocFile;
 import jdk.javadoc.internal.doclets.toolkit.util.DocFileIOException;
 import jdk.javadoc.internal.doclets.toolkit.util.DocPath;
 import jdk.javadoc.internal.doclets.toolkit.util.DocPaths;
@@ -64,41 +66,33 @@
      * @throws DocFileIOException if there is a problem generating the file
      */
     void generateIndexFile() throws DocFileIOException {
-        Content htmlDocType = configuration.isOutputHtml5()
-                ? DocType.HTML5
-                : DocType.TRANSITIONAL;
-        Content htmlComment = new Comment(configuration.getText("doclet.New_Page"));
-        Content head = new HtmlTree(HtmlTag.HEAD);
-        head.addContent(getGeneratedBy(!configuration.notimestamp));
+        DocType htmlDocType = DocType.forVersion(configuration.htmlVersion);
+        Content htmlComment = contents.newPage;
+        Head head = new Head(path, configuration.htmlVersion, configuration.docletVersion)
+                .setTimestamp(true, false)
+                .addDefaultScript(false);
 
         String title = (configuration.windowtitle.length() > 0)
                 ? configuration.windowtitle
-                : configuration.getText("doclet.Generated_Docs_Untitled");
+                : resources.getText("doclet.Generated_Docs_Untitled");
 
-        Content windowTitle = HtmlTree.TITLE(new StringContent(title));
-        head.addContent(windowTitle);
-        Content metaContentType = HtmlTree.META("Content", CONTENT_TYPE, configuration.charset);
-        head.addContent(metaContentType);
+        head.setTitle(title)
+                .setCharset(configuration.charset);
 
         String topFilePath = configuration.topFile.getPath();
-        String javaScriptRefresh = "window.location.replace('" + topFilePath + "')";
-        HtmlTree scriptTree = HtmlTree.SCRIPT();
-        scriptTree.addContent(javaScriptRefresh);
-        head.addContent(scriptTree);
-        HtmlTree metaRefresh = new HtmlTree(HtmlTag.META);
-        metaRefresh.addAttr(HtmlAttr.HTTP_EQUIV, "Refresh");
-        metaRefresh.addAttr(HtmlAttr.CONTENT, "0;" + topFilePath);
-        if (configuration.isOutputHtml5()) {
-            head.addContent(HtmlTree.NOSCRIPT(metaRefresh));
-        } else {
-            head.addContent(metaRefresh);
-        }
-
-        addStyleSheetProperties(configuration, head);
+        Script script = new Script("window.location.replace(")
+                .appendStringLiteral(topFilePath, '\'')
+                .append(")");
+        HtmlTree metaRefresh = new HtmlTree(HtmlTag.META)
+                .addAttr(HtmlAttr.HTTP_EQUIV, "Refresh")
+                .addAttr(HtmlAttr.CONTENT, "0;" + topFilePath);
+        head.addContent(
+                script.asContent(),
+                configuration.isOutputHtml5() ? HtmlTree.NOSCRIPT(metaRefresh) : metaRefresh);
 
         ContentBuilder bodyContent = new ContentBuilder();
         bodyContent.addContent(HtmlTree.NOSCRIPT(
-                HtmlTree.P(configuration.getContent("doclet.No_Script_Message"))));
+                HtmlTree.P(contents.getContent("doclet.No_Script_Message"))));
 
         bodyContent.addContent(HtmlTree.P(HtmlTree.A(topFilePath, new StringContent(topFilePath))));
 
@@ -110,11 +104,8 @@
             body.addContent(bodyContent);
         }
 
-        Content htmlTree = HtmlTree.HTML(configuration.getLocale().getLanguage(),
-                head, body);
-        Content htmlDocument = new HtmlDocument(htmlDocType,
-                htmlComment, htmlTree);
-        write(htmlDocument);
-
+        Content htmlTree = HtmlTree.HTML(configuration.getLocale().getLanguage(), head.toContent(), body);
+        HtmlDocument htmlDocument = new HtmlDocument(htmlDocType, htmlComment, htmlTree);
+        htmlDocument.write(DocFile.createFileForOutput(configuration, path));
     }
 }
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/LinkFactoryImpl.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/LinkFactoryImpl.java	Mon Nov 27 17:04:45 2017 +0000
@@ -33,6 +33,7 @@
 import javax.lang.model.type.TypeMirror;
 
 import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder;
+import jdk.javadoc.internal.doclets.formats.html.markup.Links;
 import jdk.javadoc.internal.doclets.toolkit.BaseConfiguration;
 import jdk.javadoc.internal.doclets.toolkit.Content;
 import jdk.javadoc.internal.doclets.toolkit.util.DocPath;
@@ -92,11 +93,12 @@
                 DocPath filename = getPath(classLinkInfo);
                 if (linkInfo.linkToSelf ||
                                 !(DocPath.forName(utils, typeElement)).equals(m_writer.filename)) {
-                        link.addContent(m_writer.getHyperLink(
+                        link.addContent(Links.createLink(
                                 filename.fragment(classLinkInfo.where),
-                            label,
-                            classLinkInfo.isStrong, classLinkInfo.styleName,
-                            title, classLinkInfo.target));
+                                label,
+                                classLinkInfo.isStrong,
+                                title,
+                                classLinkInfo.target));
                         if (noLabel && !classLinkInfo.excludeTypeParameterLinks) {
                             link.addContent(getTypeParameterLinks(linkInfo));
                         }
@@ -106,8 +108,7 @@
         } else {
             Content crossLink = m_writer.getCrossClassLink(
                 typeElement.getQualifiedName().toString(), classLinkInfo.where,
-                label, classLinkInfo.isStrong, classLinkInfo.styleName,
-                true);
+                label, classLinkInfo.isStrong, true);
             if (crossLink != null) {
                 link.addContent(crossLink);
                 if (noLabel && !classLinkInfo.excludeTypeParameterLinks) {
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/LinkInfoImpl.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/LinkInfoImpl.java	Mon Nov 27 17:04:45 2017 +0000
@@ -231,11 +231,6 @@
     public String where = "";
 
     /**
-     * String style of text defined in style sheet.
-     */
-    public String styleName = "";
-
-    /**
      * The value of the target.
      */
     public String target = "";
@@ -316,15 +311,6 @@
     }
 
     /**
-     * Set the style to be used for the link.
-     * @param styleName  String style of text defined in style sheet.
-     */
-    public LinkInfoImpl styleName(String styleName) {
-        this.styleName = styleName;
-        return this;
-    }
-
-    /**
      * Set the target to be used for the link.
      * @param target the target name.
      */
@@ -443,7 +429,6 @@
         return "LinkInfoImpl{" +
                 "context=" + context +
                 ", where=" + where +
-                ", styleName=" + styleName +
                 ", target=" + target +
                 super.toString() + '}';
     }
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/MethodWriterImpl.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/MethodWriterImpl.java	Mon Nov 27 17:04:45 2017 +0000
@@ -25,8 +25,9 @@
 
 package jdk.javadoc.internal.doclets.formats.html;
 
-import java.util.Arrays;
-import java.util.List;
+import jdk.javadoc.internal.doclets.formats.html.markup.Table;
+import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader;
+
 import java.util.SortedSet;
 import java.util.TreeSet;
 
@@ -35,11 +36,11 @@
 import javax.lang.model.element.TypeElement;
 import javax.lang.model.type.TypeMirror;
 
-import jdk.javadoc.internal.doclets.formats.html.TableHeader;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlConstants;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
+import jdk.javadoc.internal.doclets.formats.html.markup.Links;
 import jdk.javadoc.internal.doclets.formats.html.markup.StringContent;
 import jdk.javadoc.internal.doclets.toolkit.Content;
 import jdk.javadoc.internal.doclets.toolkit.MemberSummaryWriter;
@@ -96,6 +97,7 @@
     /**
      * {@inheritDoc}
      */
+    @Override
     public void addMemberTree(Content memberSummaryTree, Content memberTree) {
         writer.addMemberTree(memberSummaryTree, memberTree);
     }
@@ -107,8 +109,7 @@
     public Content getMethodDetailsTreeHeader(TypeElement typeElement, Content memberDetailsTree) {
         memberDetailsTree.addContent(HtmlConstants.START_OF_METHOD_DETAILS);
         Content methodDetailsTree = writer.getMemberTreeHeader();
-        methodDetailsTree.addContent(writer.getMarkerAnchor(
-                SectionName.METHOD_DETAIL));
+        methodDetailsTree.addContent(links.createAnchor(SectionName.METHOD_DETAIL));
         Content heading = HtmlTree.HEADING(HtmlConstants.DETAILS_HEADING,
                 contents.methodDetailLabel);
         methodDetailsTree.addContent(heading);
@@ -122,10 +123,9 @@
     public Content getMethodDocTreeHeader(ExecutableElement method, Content methodDetailsTree) {
         String erasureAnchor;
         if ((erasureAnchor = getErasureAnchor(method)) != null) {
-            methodDetailsTree.addContent(writer.getMarkerAnchor((erasureAnchor)));
+            methodDetailsTree.addContent(links.createAnchor((erasureAnchor)));
         }
-        methodDetailsTree.addContent(
-                writer.getMarkerAnchor(writer.getAnchor(method)));
+        methodDetailsTree.addContent(links.createAnchor(writer.getAnchor(method)));
         Content methodDocTree = writer.getMemberTreeHeader();
         Content heading = new HtmlTree(HtmlConstants.MEMBER_HEADING);
         heading.addContent(name(method));
@@ -242,36 +242,44 @@
      * {@inheritDoc}
      */
     @Override
-    public String getTableSummary() {
-        return resources.getText("doclet.Member_Table_Summary",
-                resources.getText("doclet.Method_Summary"),
-                resources.getText("doclet.methods"));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public Content getCaption() {
-        return contents.methods;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
     public TableHeader getSummaryTableHeader(Element member) {
         return new TableHeader(contents.modifierAndTypeLabel, contents.methodLabel,
                 contents.descriptionLabel);
     }
 
+    @Override
+    protected Table createSummaryTable() {
+        String summary =  resources.getText("doclet.Member_Table_Summary",
+                resources.getText("doclet.Method_Summary"),
+                resources.getText("doclet.methods"));
+
+        return new Table(configuration.htmlVersion, HtmlStyle.memberSummary)
+                .setSummary(summary)
+                .setHeader(getSummaryTableHeader(typeElement))
+                .setRowScopeColumn(1)
+                .setColumnStyles(HtmlStyle.colFirst, HtmlStyle.colSecond, HtmlStyle.colLast)
+                .setDefaultTab(resources.getText("doclet.All_Methods"))
+                .addTab(resources.getText("doclet.Static_Methods"), utils::isStatic)
+                .addTab(resources.getText("doclet.Instance_Methods"), e -> !utils.isStatic(e))
+                .addTab(resources.getText("doclet.Abstract_Methods"), utils::isAbstract)
+                .addTab(resources.getText("doclet.Concrete_Methods"),
+                        e -> !utils.isAbstract(e) && !utils.isInterface(e.getEnclosingElement()))
+                .addTab(resources.getText("doclet.Default_Methods"),
+                        e -> !utils.isAbstract(e) && utils.isInterface(e.getEnclosingElement()))
+                .addTab(resources.getText("doclet.Deprecated_Methods"),
+                        e -> utils.isDeprecated(e) || utils.isDeprecated(typeElement))
+                .setTabScriptVariable("methods")
+                .setTabScript(i -> "show(" + i + ");")
+                .setUseTBody(false)
+                .setPutIdFirst(true);
+    }
+
     /**
      * {@inheritDoc}
      */
     @Override
     public void addSummaryAnchor(TypeElement typeElement, Content memberTree) {
-        memberTree.addContent(writer.getMarkerAnchor(
-                SectionName.METHOD_SUMMARY));
+        memberTree.addContent(links.createAnchor(SectionName.METHOD_SUMMARY));
     }
 
     /**
@@ -279,7 +287,7 @@
      */
     @Override
     public void addInheritedSummaryAnchor(TypeElement typeElement, Content inheritedTree) {
-        inheritedTree.addContent(writer.getMarkerAnchor(
+        inheritedTree.addContent(links.createAnchor(
                 SectionName.METHODS_INHERITANCE, configuration.getClassName(typeElement)));
     }
 
@@ -355,7 +363,7 @@
             Content methlink = writer.getLink(
                     new LinkInfoImpl(writer.configuration, LinkInfoImpl.Kind.MEMBER,
                     holder)
-                    .where(writer.getName(writer.getAnchor(method))).label(method.getSimpleName()));
+                    .where(writer.links.getName(writer.getAnchor(method))).label(method.getSimpleName()));
             Content codeMethLink = HtmlTree.CODE(methlink);
             Content dd = HtmlTree.DD(codeMethLink);
             dd.addContent(Contents.SPACE);
@@ -425,11 +433,11 @@
     protected Content getNavSummaryLink(TypeElement typeElement, boolean link) {
         if (link) {
             if (typeElement == null) {
-                return writer.getHyperLink(
+                return Links.createLink(
                         SectionName.METHOD_SUMMARY,
                         contents.navMethod);
             } else {
-                return writer.getHyperLink(
+                return links.createLink(
                         SectionName.METHODS_INHERITANCE,
                         configuration.getClassName(typeElement), contents.navMethod);
             }
@@ -444,7 +452,7 @@
     @Override
     protected void addNavDetailLink(boolean link, Content liNav) {
         if (link) {
-            liNav.addContent(writer.getHyperLink(
+            liNav.addContent(Links.createLink(
                     SectionName.METHOD_DETAIL, contents.navMethod));
         } else {
             liNav.addContent(contents.navMethod);
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleFrameWriter.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleFrameWriter.java	Mon Nov 27 17:04:45 2017 +0000
@@ -36,6 +36,7 @@
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
+import jdk.javadoc.internal.doclets.formats.html.markup.Links;
 import jdk.javadoc.internal.doclets.formats.html.markup.StringContent;
 import jdk.javadoc.internal.doclets.toolkit.Content;
 import jdk.javadoc.internal.doclets.toolkit.util.DocFileIOException;
@@ -100,10 +101,10 @@
                 ? HtmlTree.MAIN()
                 : body;
         Content heading = HtmlTree.HEADING(HtmlConstants.TITLE_HEADING, HtmlStyle.bar,
-                mdlgen.getHyperLink(DocPaths.moduleSummary(moduleElement), mdlLabel, "", "classFrame"));
+                Links.createLink(DocPaths.moduleSummary(moduleElement), mdlLabel, "", "classFrame"));
         htmlTree.addContent(heading);
         HtmlTree div = new HtmlTree(HtmlTag.DIV);
-        div.addStyle(HtmlStyle.indexContainer);
+        div.setStyle(HtmlStyle.indexContainer);
         mdlgen.addClassListing(div);
         htmlTree.addContent(div);
         if (configuration.allowTag(HtmlTag.MAIN)) {
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleIndexFrameWriter.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleIndexFrameWriter.java	Mon Nov 27 17:04:45 2017 +0000
@@ -31,14 +31,17 @@
 import javax.lang.model.element.ModuleElement;
 import javax.lang.model.element.PackageElement;
 
+import jdk.javadoc.internal.doclets.formats.html.markup.HtmlAttr;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlConstants;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
+import jdk.javadoc.internal.doclets.formats.html.markup.Links;
 import jdk.javadoc.internal.doclets.formats.html.markup.RawHtml;
 import jdk.javadoc.internal.doclets.formats.html.markup.StringContent;
 import jdk.javadoc.internal.doclets.toolkit.Content;
 import jdk.javadoc.internal.doclets.toolkit.util.DocFileIOException;
+import jdk.javadoc.internal.doclets.toolkit.util.DocLink;
 import jdk.javadoc.internal.doclets.toolkit.util.DocPath;
 import jdk.javadoc.internal.doclets.toolkit.util.DocPaths;
 
@@ -110,6 +113,17 @@
         return li;
     }
 
+    private Content getModuleFramesHyperLink(ModuleElement mdle, Content label, String target) {
+        DocLink mdlLink = new DocLink(DocPaths.moduleFrame(mdle));
+        DocLink mtFrameLink = new DocLink(DocPaths.moduleTypeFrame(mdle));
+        DocLink cFrameLink = new DocLink(DocPaths.moduleSummary(mdle));
+        HtmlTree anchor = HtmlTree.A(mdlLink.toString(), label);
+        String onclickStr = "updateModuleFrame('" + mtFrameLink + "','" + cFrameLink + "');";
+        anchor.addAttr(HtmlAttr.TARGET, target);
+        anchor.addAttr(HtmlAttr.ONCLICK, onclickStr);
+        return anchor;
+    }
+
     /**
      * {@inheritDoc}
      */
@@ -138,7 +152,7 @@
      * @param ul the Content object to which the all classes link should be added
      */
     protected void addAllClassesLink(Content ul) {
-        Content linkContent = getHyperLink(DocPaths.ALLCLASSES_FRAME,
+        Content linkContent = Links.createLink(DocPaths.ALLCLASSES_FRAME,
                 contents.allClassesLabel, "", "packageFrame");
         Content li = HtmlTree.LI(linkContent);
         ul.addContent(li);
@@ -151,7 +165,7 @@
      * @param ul the Content object to which the all packages link should be added
      */
     protected void addAllPackagesLink(Content ul) {
-        Content linkContent = getHyperLink(DocPaths.OVERVIEW_FRAME,
+        Content linkContent = Links.createLink(DocPaths.OVERVIEW_FRAME,
                 contents.allPackagesLabel, "", "packageListFrame");
         Content li = HtmlTree.LI(linkContent);
         ul.addContent(li);
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleIndexWriter.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleIndexWriter.java	Mon Nov 27 17:04:45 2017 +0000
@@ -25,13 +25,15 @@
 
 package jdk.javadoc.internal.doclets.formats.html;
 
+import jdk.javadoc.internal.doclets.formats.html.markup.Table;
+import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader;
+
 import java.util.*;
 
 import javax.lang.model.element.ModuleElement;
 import javax.lang.model.element.PackageElement;
 
-
-import jdk.javadoc.internal.doclets.formats.html.markup.HtmlAttr;
+import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
@@ -40,8 +42,6 @@
 import jdk.javadoc.internal.doclets.toolkit.util.DocFileIOException;
 import jdk.javadoc.internal.doclets.toolkit.util.DocPath;
 import jdk.javadoc.internal.doclets.toolkit.util.DocPaths;
-import jdk.javadoc.internal.doclets.toolkit.util.Group;
-import jdk.javadoc.internal.doclets.toolkit.util.GroupTypes;
 
 /**
  * Generate the module index page "overview-summary.html" for the right-hand
@@ -57,28 +57,6 @@
 public class ModuleIndexWriter extends AbstractModuleIndexWriter {
 
     /**
-     * Map representing the group of modules as specified on the command line.
-     *
-     * @see Group
-     */
-    private final Map<String, SortedSet<ModuleElement>> groupModuleMap;
-
-    /**
-     * List to store the order groups, which has elements to be displayed, as specified on the command line.
-     */
-    private final List<String> groupList = new ArrayList<>();
-
-    private final GroupTypes groupTypes;
-
-    private int groupTypesOr = 0;
-
-    protected Map<String, Integer> groupTypeMap = new LinkedHashMap<>();
-
-    boolean altColor = true;
-
-    int counter = 0;
-
-    /**
      * HTML tree for main tag.
      */
     private final HtmlTree htmlTree = HtmlTree.MAIN();
@@ -90,11 +68,6 @@
      */
     public ModuleIndexWriter(HtmlConfiguration configuration, DocPath filename) {
         super(configuration, filename);
-        groupModuleMap = configuration.group.groupModules(configuration.modules);
-        configuration.group.getGroupList().stream()
-                .filter(groupModuleMap::containsKey)
-                .forEach(groupList::add);
-        groupTypes = new GroupTypes(groupList, resources.getText("doclet.All_Modules"));
     }
 
     /**
@@ -128,7 +101,7 @@
         HtmlTree htmltree = (configuration.allowTag(HtmlTag.NAV))
                 ? HtmlTree.NAV()
                 : new HtmlTree(HtmlTag.DIV);
-        htmltree.addStyle(HtmlStyle.indexNav);
+        htmltree.setStyle(HtmlStyle.indexNav);
         HtmlTree ul = new HtmlTree(HtmlTag.UL);
         addAllClassesLink(ul);
         if (configuration.showModules) {
@@ -144,68 +117,53 @@
      *
      * @param body the content tree to which the module list will be added
      */
+    @Override
     protected void addModulesList(Content body) {
-        if (!groupList.isEmpty()) {
-            Content caption;
-            TreeMap<ModuleElement, String> groupMap = new TreeMap<>(utils.makeModuleComparator());
-            Content tbody = new HtmlTree(HtmlTag.TBODY);
+        Map<String, SortedSet<ModuleElement>> groupModuleMap
+                = configuration.group.groupModules(configuration.modules);
+
+        if (!groupModuleMap.keySet().isEmpty()) {
             String tableSummary = configuration.getText("doclet.Member_Table_Summary",
                     configuration.getText("doclet.Module_Summary"), configuration.getText("doclet.modules"));
-            for (String groupname : groupList) {
-                for (ModuleElement mdle : groupModuleMap.get(groupname)) {
-                    groupMap.put(mdle, groupname);
+            TableHeader header = new TableHeader(contents.moduleLabel, contents.descriptionLabel);
+            Table table =  new Table(configuration.htmlVersion, HtmlStyle.overviewSummary)
+                    .setSummary(tableSummary)
+                    .setHeader(header)
+                    .setColumnStyles(HtmlStyle.colFirst, HtmlStyle.colLast)
+                    .setDefaultTab(resources.getText("doclet.All_Modules"))
+                    .setTabScriptVariable("groups")
+                    .setTabScript(i -> "showGroups(" + i + ");")
+                    .setTabId(i -> (i == 0) ? "t0" : ("t" + (1 << (i - 1))));
+
+            // add the tabs in command-line order
+            for (String groupName : configuration.group.getGroupList()) {
+                Set<ModuleElement> groupModules = groupModuleMap.get(groupName);
+                if (groupModules != null) {
+                    table.addTab(groupName, groupModules::contains);
                 }
             }
-            if (!groupMap.isEmpty()) {
-                addModulesList(groupMap, tbody);
+
+            for (ModuleElement mdle : configuration.modules) {
+                if (!mdle.isUnnamed()) {
+                    if (!(configuration.nodeprecated && utils.isDeprecated(mdle))) {
+                        Content moduleLinkContent = getModuleLink(mdle, new StringContent(mdle.getQualifiedName().toString()));
+                        Content summaryContent = new ContentBuilder();
+                        addSummaryComment(mdle, summaryContent);
+                        table.addRow(mdle, moduleLinkContent, summaryContent);
+                    }
+                }
             }
-            if (showTabs(groupTypes)) {
-                caption = getTableCaption(groupTypes);
-                generateGroupTypesScript(groupTypeMap, groupTypes.getGroupTypes());
-            } else {
-                caption = getTableCaption((groupList.size() == 1) ? new StringContent(groupList.get(0)) : contents.modulesLabel);
-            }
-            Content table = getTableHeader(caption, tableSummary, HtmlStyle.overviewSummary);
-            Content header = new TableHeader(contents.moduleLabel, contents.descriptionLabel).toContent();
-            table.addContent(header);
-            table.addContent(tbody);
-            Content div = HtmlTree.DIV(HtmlStyle.contentContainer, table);
+
+            Content div = HtmlTree.DIV(HtmlStyle.contentContainer, table.toContent());
             if (configuration.allowTag(HtmlTag.MAIN)) {
                 htmlTree.addContent(div);
             } else {
                 body.addContent(div);
             }
-        }
-    }
 
-    /**
-     * Adds list of modules in the index table. Generate link to each module.
-     *
-     * @param map map of module elements and group names
-     * @param tbody the documentation tree to which the list will be added
-     */
-    protected void addModulesList(TreeMap<ModuleElement, String> map, Content tbody) {
-        String groupname;
-        for (ModuleElement mdle : map.keySet()) {
-            if (!mdle.isUnnamed()) {
-                groupname = map.get(mdle);
-                Content moduleLinkContent = getModuleLink(mdle, new StringContent(mdle.getQualifiedName().toString()));
-                Content thModule = HtmlTree.TH_ROW_SCOPE(HtmlStyle.colFirst, moduleLinkContent);
-                HtmlTree tdSummary = new HtmlTree(HtmlTag.TD);
-                tdSummary.addStyle(HtmlStyle.colLast);
-                addSummaryComment(mdle, tdSummary);
-                HtmlTree tr = HtmlTree.TR(thModule);
-                tr.addContent(tdSummary);
-                tr.addStyle(altColor ? HtmlStyle.altColor : HtmlStyle.rowColor);
-                int groupType = groupTypes.getTableTab(groupname).value();
-                groupTypesOr = groupTypesOr | groupType;
-                String tableId = "i" + counter;
-                counter++;
-                groupTypeMap.put(tableId, groupType);
-                tr.addAttr(HtmlAttr.ID, tableId);
-                tbody.addContent(tr);
+            if (table.needsScript()) {
+                mainBodyScript.append(table.getScript());
             }
-            altColor = !altColor;
         }
     }
 
@@ -221,7 +179,7 @@
         addConfigurationTitle(body);
         if (!utils.getFullBody(configuration.overviewElement).isEmpty()) {
             HtmlTree div = new HtmlTree(HtmlTag.DIV);
-            div.addStyle(HtmlStyle.contentContainer);
+            div.setStyle(HtmlStyle.contentContainer);
             addOverviewComment(div);
             if (configuration.allowTag(HtmlTag.MAIN)) {
                 htmlTree.addContent(div);
@@ -265,13 +223,13 @@
      */
     @Override
     protected void addNavigationBarHeader(Content body) {
-        Content htmlTree = (configuration.allowTag(HtmlTag.HEADER))
+        Content tree = (configuration.allowTag(HtmlTag.HEADER))
                 ? HtmlTree.HEADER()
                 : body;
-        addTop(htmlTree);
-        addNavLinks(true, htmlTree);
+        addTop(tree);
+        addNavLinks(true, tree);
         if (configuration.allowTag(HtmlTag.HEADER)) {
-            body.addContent(htmlTree);
+            body.addContent(tree);
         }
     }
 
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModulePackageIndexFrameWriter.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModulePackageIndexFrameWriter.java	Mon Nov 27 17:04:45 2017 +0000
@@ -37,6 +37,7 @@
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
+import jdk.javadoc.internal.doclets.formats.html.markup.Links;
 import jdk.javadoc.internal.doclets.formats.html.markup.RawHtml;
 import jdk.javadoc.internal.doclets.formats.html.markup.StringContent;
 import jdk.javadoc.internal.doclets.toolkit.Content;
@@ -142,12 +143,12 @@
         Content pkgLabel;
         if (!pkg.isUnnamed()) {
             pkgLabel = getPackageLabel(utils.getPackageName(pkg));
-            packageLinkContent = getHyperLink(pathString(pkg,
+            packageLinkContent = Links.createLink(pathString(pkg,
                      DocPaths.PACKAGE_FRAME), pkgLabel, "",
                     "packageFrame");
         } else {
             pkgLabel = new StringContent("<unnamed package>");
-            packageLinkContent = getHyperLink(DocPaths.PACKAGE_FRAME,
+            packageLinkContent = Links.createLink(DocPaths.PACKAGE_FRAME,
                     pkgLabel, "", "packageFrame");
         }
         Content li = HtmlTree.LI(packageLinkContent);
@@ -188,7 +189,7 @@
      * @param ul the Content object to which the all classes link should be added
      */
     protected void addAllClassesLink(Content ul) {
-        Content linkContent = getHyperLink(DocPaths.ALLCLASSES_FRAME,
+        Content linkContent = Links.createLink(DocPaths.ALLCLASSES_FRAME,
                 contents.allClassesLabel, "", "packageFrame");
         Content li = HtmlTree.LI(linkContent);
         ul.addContent(li);
@@ -201,7 +202,7 @@
      * @param ul the Content object to which the all packages link should be added
      */
     protected void addAllPackagesLink(Content ul) {
-        Content linkContent = getHyperLink(DocPaths.OVERVIEW_FRAME,
+        Content linkContent = Links.createLink(DocPaths.OVERVIEW_FRAME,
                 contents.allPackagesLabel, "", "packageListFrame");
         Content li = HtmlTree.LI(linkContent);
         ul.addContent(li);
@@ -214,7 +215,7 @@
      * @param ul the Content object to which the all modules link should be added
      */
     protected void addAllModulesLink(Content ul) {
-        Content linkContent = getHyperLink(DocPaths.MODULE_OVERVIEW_FRAME,
+        Content linkContent = Links.createLink(DocPaths.MODULE_OVERVIEW_FRAME,
                 contents.allModulesLabel, "", "packageListFrame");
         Content li = HtmlTree.LI(linkContent);
         ul.addContent(li);
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleWriterImpl.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleWriterImpl.java	Mon Nov 27 17:04:45 2017 +0000
@@ -25,9 +25,11 @@
 
 package jdk.javadoc.internal.doclets.formats.html;
 
+import jdk.javadoc.internal.doclets.formats.html.markup.Table;
+import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader;
+
+import java.util.ArrayList;
 import java.util.Collections;
-import java.util.EnumSet;
-import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -43,11 +45,12 @@
 
 import com.sun.source.doctree.DocTree;
 import jdk.javadoc.doclet.DocletEnvironment.ModuleMode;
-import jdk.javadoc.internal.doclets.formats.html.markup.HtmlAttr;
+import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlConstants;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
+import jdk.javadoc.internal.doclets.formats.html.markup.Links;
 import jdk.javadoc.internal.doclets.formats.html.markup.RawHtml;
 import jdk.javadoc.internal.doclets.formats.html.markup.StringContent;
 import jdk.javadoc.internal.doclets.toolkit.Content;
@@ -55,7 +58,6 @@
 import jdk.javadoc.internal.doclets.toolkit.util.CommentHelper;
 import jdk.javadoc.internal.doclets.toolkit.util.DocFileIOException;
 import jdk.javadoc.internal.doclets.toolkit.util.DocPaths;
-import jdk.javadoc.internal.doclets.toolkit.util.ModulePackageTypes;
 
 /**
  * Class to generate file for each module contents in the right-hand frame. This will list all the
@@ -157,12 +159,6 @@
     private final Map<TypeElement, Content> providesTrees
             = new TreeMap<>(utils.makeAllClassesComparator());
 
-    private int packageTypesOr = 0;
-
-    protected Set<ModulePackageTypes> modulePackageTypes = EnumSet.noneOf(ModulePackageTypes.class);
-
-    protected Map<String, Integer> typeMap = new LinkedHashMap<>();
-
     /**
      * The HTML tree for main tag.
      */
@@ -208,7 +204,7 @@
             bodyTree.addContent(htmlTree);
         }
         HtmlTree div = new HtmlTree(HtmlTag.DIV);
-        div.addStyle(HtmlStyle.header);
+        div.setStyle(HtmlStyle.header);
         Content annotationContent = new HtmlTree(HtmlTag.P);
         addAnnotationInfo(mdle, annotationContent);
         div.addContent(annotationContent);
@@ -234,7 +230,7 @@
     @Override
     public Content getContentHeader() {
         HtmlTree div = new HtmlTree(HtmlTag.DIV);
-        div.addStyle(HtmlStyle.contentContainer);
+        div.setStyle(HtmlStyle.contentContainer);
         return div;
     }
 
@@ -244,7 +240,7 @@
     @Override
     public Content getSummaryHeader() {
         HtmlTree li = new HtmlTree(HtmlTag.LI);
-        li.addStyle(HtmlStyle.blockList);
+        li.setStyle(HtmlStyle.blockList);
         return li;
     }
 
@@ -460,26 +456,12 @@
     public void addSummaryHeader(Content startMarker, SectionName markerAnchor, Content heading,
             Content htmltree) {
         htmltree.addContent(startMarker);
-        htmltree.addContent(getMarkerAnchor(markerAnchor));
+        htmltree.addContent(links.createAnchor(markerAnchor));
         htmltree.addContent(HtmlTree.HEADING(HtmlTag.H3, heading));
     }
 
     /**
-     * Get a table.
-     *
-     * @param text the table caption
-     * @param tableSummary the summary for the table
-     * @param tableStyle the table style
-     * @param tableHeader the table header
-     * @return a content object
-     */
-    Content getTable(String text, String tableSummary, HtmlStyle tableStyle,
-            TableHeader tableHeader) {
-        return getTable(getTableCaption(new RawHtml(text)), tableSummary, tableStyle, tableHeader);
-    }
-
-    /**
-     * Get a table.
+     * Get a table, with two columns.
      *
      * @param caption the table caption
      * @param tableSummary the summary for the table
@@ -487,13 +469,32 @@
      * @param tableHeader the table header
      * @return a content object
      */
-    Content getTable(Content caption, String tableSummary, HtmlStyle tableStyle,
+    private Table getTable2(Content caption, String tableSummary, HtmlStyle tableStyle,
             TableHeader tableHeader) {
-        Content table = (configuration.isOutputHtml5())
-                ? HtmlTree.TABLE(tableStyle, caption)
-                : HtmlTree.TABLE(tableStyle, tableSummary, caption);
-        table.addContent(tableHeader.toContent());
-        return table;
+        return new Table(configuration.htmlVersion, tableStyle)
+                .setSummary(tableSummary)
+                .setCaption(caption)
+                .setHeader(tableHeader)
+                .setColumnStyles(HtmlStyle.colFirst, HtmlStyle.colLast);
+    }
+
+    /**
+     * Get a table, with three columns, with the second column being the defining column.
+     *
+     * @param caption the table caption
+     * @param tableSummary the summary for the table
+     * @param tableStyle the table style
+     * @param tableHeader the table header
+     * @return a content object
+     */
+    private Table getTable3(Content caption, String tableSummary, HtmlStyle tableStyle,
+            TableHeader tableHeader) {
+        return new Table(configuration.htmlVersion, tableStyle)
+                .setSummary(tableSummary)
+                .setCaption(caption)
+                .setHeader(tableHeader)
+                .setRowScopeColumn(1)
+                .setColumnStyles(HtmlStyle.colFirst, HtmlStyle.colSecond, HtmlStyle.colLast);
     }
 
     /**
@@ -506,33 +507,31 @@
                     new TableHeader(contents.modifierLabel, contents.moduleLabel,
                             contents.descriptionLabel);
             HtmlTree li = new HtmlTree(HtmlTag.LI);
-            li.addStyle(HtmlStyle.blockList);
+            li.setStyle(HtmlStyle.blockList);
             addSummaryHeader(HtmlConstants.START_OF_MODULES_SUMMARY, SectionName.MODULES,
                     contents.navModules, li);
             if (display(requires)) {
-                String text = configuration.getText("doclet.Requires_Summary");
-                String tableSummary = configuration.getText("doclet.Member_Table_Summary",
+                String text = resources.getText("doclet.Requires_Summary");
+                String tableSummary = resources.getText("doclet.Member_Table_Summary",
                         text,
-                        configuration.getText("doclet.modules"));
-                Content table = getTable(text, tableSummary, HtmlStyle.requiresSummary,
-                        requiresTableHeader);
-                Content tbody = new HtmlTree(HtmlTag.TBODY);
-                addModulesList(requires, tbody);
-                table.addContent(tbody);
-                li.addContent(table);
+                        resources.getText("doclet.modules"));
+                Content caption = getTableCaption(new StringContent(text));
+                Table table = getTable3(caption, tableSummary, HtmlStyle.requiresSummary,
+                            requiresTableHeader);
+                addModulesList(requires, table);
+                li.addContent(table.toContent());
             }
             // Display indirect modules table in both "api" and "all" mode.
             if (display(indirectModules)) {
-                String amrText = configuration.getText("doclet.Indirect_Requires_Summary");
-                String amrTableSummary = configuration.getText("doclet.Member_Table_Summary",
+                String amrText = resources.getText("doclet.Indirect_Requires_Summary");
+                String amrTableSummary = resources.getText("doclet.Member_Table_Summary",
                         amrText,
                         configuration.getText("doclet.modules"));
-                Content amrTable = getTable(amrText, amrTableSummary, HtmlStyle.requiresSummary,
-                        requiresTableHeader);
-                Content amrTbody = new HtmlTree(HtmlTag.TBODY);
-                addModulesList(indirectModules, amrTbody);
-                amrTable.addContent(amrTbody);
-                li.addContent(amrTable);
+                Content amrCaption = getTableCaption(new StringContent(amrText));
+                Table amrTable = getTable3(amrCaption, amrTableSummary, HtmlStyle.requiresSummary,
+                            requiresTableHeader);
+                addModulesList(indirectModules, amrTable);
+                li.addContent(amrTable.toContent());
             }
             HtmlTree ul = HtmlTree.UL(HtmlStyle.blockList, li);
             summaryContentTree.addContent(ul);
@@ -545,21 +544,13 @@
      * @param mdleMap map of modules and modifiers
      * @param tbody the content tree to which the list will be added
      */
-    public void addModulesList(Map<ModuleElement, Content> mdleMap, Content tbody) {
-        boolean altColor = true;
+    private void addModulesList(Map<ModuleElement, Content> mdleMap, Table table) {
         for (ModuleElement m : mdleMap.keySet()) {
-            Content tdModifiers = HtmlTree.TD(HtmlStyle.colFirst, mdleMap.get(m));
-            Content moduleLinkContent = getModuleLink(m, new StringContent(m.getQualifiedName()));
-            Content thModule = HtmlTree.TH_ROW_SCOPE(HtmlStyle.colSecond, moduleLinkContent);
-            HtmlTree tdSummary = new HtmlTree(HtmlTag.TD);
-            tdSummary.addStyle(HtmlStyle.colLast);
-            addSummaryComment(m, tdSummary);
-            HtmlTree tr = HtmlTree.TR(tdModifiers);
-            tr.addContent(thModule);
-            tr.addContent(tdSummary);
-            tr.addStyle(altColor ? HtmlStyle.altColor : HtmlStyle.rowColor);
-            tbody.addContent(tr);
-            altColor = !altColor;
+            Content modifiers = mdleMap.get(m);
+            Content moduleLink = getModuleLink(m, new StringContent(m.getQualifiedName()));
+            Content moduleSummary = new ContentBuilder();
+            addSummaryComment(m, moduleSummary);
+            table.addRow(modifiers, moduleLink, moduleSummary);
         }
     }
 
@@ -568,42 +559,38 @@
         if (display(exportedPackages) || display(openedPackages) || display(concealedPackages)
                 || display(indirectPackages) || display(indirectOpenPackages)) {
             HtmlTree li = new HtmlTree(HtmlTag.LI);
-            li.addStyle(HtmlStyle.blockList);
+            li.setStyle(HtmlStyle.blockList);
             addSummaryHeader(HtmlConstants.START_OF_PACKAGES_SUMMARY, SectionName.PACKAGES,
                     contents.navPackages, li);
-            String tableSummary = configuration.getText("doclet.Member_Table_Summary",
-                    configuration.getText("doclet.Packages_Summary"),
-                    configuration.getText("doclet.packages"));
             if (display(exportedPackages) || display(openedPackages) || display(concealedPackages)) {
+                String tableSummary = resources.getText("doclet.Member_Table_Summary",
+                        resources.getText("doclet.Packages_Summary"),
+                        resources.getText("doclet.packages"));
                 addPackageSummary(tableSummary, li);
             }
             TableHeader indirectPackagesHeader =
                     new TableHeader(contents.fromLabel, contents.packagesLabel);
             if (display(indirectPackages)) {
-                String aepText = configuration.getText("doclet.Indirect_Exports_Summary");
-                String aepTableSummary = configuration.getText("doclet.Indirect_Packages_Table_Summary",
+                String aepText = resources.getText("doclet.Indirect_Exports_Summary");
+                String aepTableSummary = resources.getText("doclet.Indirect_Packages_Table_Summary",
                         aepText,
-                        configuration.getText("doclet.modules"),
-                        configuration.getText("doclet.packages"));
-                Content aepTable = getTable(aepText, aepTableSummary, HtmlStyle.packagesSummary,
-                        indirectPackagesHeader);
-                Content aepTbody = new HtmlTree(HtmlTag.TBODY);
-                addIndirectPackages(aepTbody, indirectPackages);
-                aepTable.addContent(aepTbody);
-                li.addContent(aepTable);
+                        resources.getText("doclet.modules"),
+                        resources.getText("doclet.packages"));
+                Table aepTable = getTable2(new StringContent(aepText), aepTableSummary,
+                        HtmlStyle.packagesSummary, indirectPackagesHeader);
+                addIndirectPackages(aepTable, indirectPackages);
+                li.addContent(aepTable.toContent());
             }
             if (display(indirectOpenPackages)) {
-                String aopText = configuration.getText("doclet.Indirect_Opens_Summary");
-                String aopTableSummary = configuration.getText("doclet.Indirect_Packages_Table_Summary",
+                String aopText = resources.getText("doclet.Indirect_Opens_Summary");
+                String aopTableSummary = resources.getText("doclet.Indirect_Packages_Table_Summary",
                         aopText,
-                        configuration.getText("doclet.modules"),
-                        configuration.getText("doclet.packages"));
-                Content aopTable = getTable(aopText, aopTableSummary, HtmlStyle.packagesSummary,
-                        indirectPackagesHeader);
-                Content aopTbody = new HtmlTree(HtmlTag.TBODY);
-                addIndirectPackages(aopTbody, indirectOpenPackages);
-                aopTable.addContent(aopTbody);
-                li.addContent(aopTable);
+                        resources.getText("doclet.modules"),
+                        resources.getText("doclet.packages"));
+                Table aopTable = getTable2(new StringContent(aopText), aopTableSummary,
+                        HtmlStyle.packagesSummary, indirectPackagesHeader);
+                addIndirectPackages(aopTable, indirectOpenPackages);
+                li.addContent(aopTable.toContent());
             }
             HtmlTree ul = HtmlTree.UL(HtmlStyle.blockList, li);
             summaryContentTree.addContent(ul);
@@ -617,79 +604,31 @@
      * @param li
      */
     public void addPackageSummary(String tableSummary, HtmlTree li) {
-        Content caption;
-        Content tbody = getPackageTableRows();
-        if (showTabs()) {
-            caption = getTableCaption();
-            generateTableTabTypesScript(typeMap, modulePackageTypes, "packages");
-        } else {
-            ModulePackageTypes type = modulePackageTypes.iterator().next();
-            caption = getTableCaption(configuration.getContent(type.tableTabs().resourceKey()));
-        }
-        TableHeader header = (configuration.docEnv.getModuleMode() == ModuleMode.ALL)
-                ? new TableHeader(contents.packageLabel, contents.moduleLabel, contents.descriptionLabel)
-                : new TableHeader(contents.packageLabel, contents.descriptionLabel);
-        Content table = getTable(caption, tableSummary, HtmlStyle.packagesSummary, header);
-        table.addContent(tbody);
-        li.addContent(table);
-    }
-
-    /**
-     * Returns true if the table tabs needs to be displayed.
-     *
-     * @return true if the tabs should be displayed
-     */
-    public boolean showTabs() {
-        int value;
-        for (ModulePackageTypes type : EnumSet.allOf(ModulePackageTypes.class)) {
-            value = type.tableTabs().value();
-            if ((value & packageTypesOr) == value) {
-                modulePackageTypes.add(type);
-            }
-        }
-        boolean showTabs = modulePackageTypes.size() > 1;
-        if (showTabs) {
-            modulePackageTypes.add(ModulePackageTypes.ALL);
-        }
-        return showTabs;
-    }
+        Table table = new Table(configuration.htmlVersion, HtmlStyle.packagesSummary)
+                .setSummary(tableSummary)
+                .setDefaultTab(resources.getText("doclet.All_Packages"))
+                .addTab(resources.getText("doclet.Exported_Packages_Summary"),
+                        e -> exportedPackages.containsKey((PackageElement) e))
+                .addTab(resources.getText("doclet.Opened_Packages_Summary"),
+                        e -> openedPackages.containsKey((PackageElement) e))
+                .addTab(resources.getText("doclet.Concealed_Packages_Summary"),
+                        e -> concealedPackages.contains((PackageElement) e))
+                .setTabScript(i -> String.format("showPkgs(%d);", i))
+                .setTabScriptVariable("packages");
 
-    /**
-     * Get the summary table caption.
-     *
-     * @return the caption for the summary table
-     */
-    public Content getTableCaption() {
-        Content tabbedCaption = new HtmlTree(HtmlTag.CAPTION);
-        for (ModulePackageTypes type : modulePackageTypes) {
-            Content captionSpan;
-            Content span;
-            if (type.tableTabs().isDefaultTab()) {
-                captionSpan = HtmlTree.SPAN(configuration.getContent(type.tableTabs().resourceKey()));
-                span = HtmlTree.SPAN(type.tableTabs().tabId(),
-                        HtmlStyle.activeTableTab, captionSpan);
-            } else {
-                captionSpan = HtmlTree.SPAN(getPackageTypeLinks(type));
-                span = HtmlTree.SPAN(type.tableTabs().tabId(),
-                        HtmlStyle.tableTab, captionSpan);
-            }
-            Content tabSpan = HtmlTree.SPAN(HtmlStyle.tabEnd, Contents.SPACE);
-            span.addContent(tabSpan);
-            tabbedCaption.addContent(span);
+        if (configuration.docEnv.getModuleMode() == ModuleMode.API) {
+            table.setHeader(new TableHeader(contents.packageLabel, contents.descriptionLabel))
+                    .setColumnStyles(HtmlStyle.colFirst, HtmlStyle.colLast);
+        } else {
+            table.setHeader(new TableHeader(contents.packageLabel, contents.moduleLabel, contents.descriptionLabel))
+                    .setColumnStyles(HtmlStyle.colFirst, HtmlStyle.colSecond, HtmlStyle.colLast);
         }
-        return tabbedCaption;
-    }
 
-    /**
-     * Get the package type links for the table caption.
-     *
-     * @param packageType the package type to be displayed as link
-     * @return the content tree for the package type link
-     */
-    public Content getPackageTypeLinks(ModulePackageTypes packageType) {
-        String jsShow = "javascript:showPkgs(" + packageType.tableTabs().value() + ");";
-        HtmlTree link = HtmlTree.A(jsShow, configuration.getContent(packageType.tableTabs().resourceKey()));
-        return link;
+        addPackageTableRows(table);
+        li.addContent(table.toContent());
+        if (table.needsScript()) {
+            mainBodyScript.append(table.getScript());
+        }
     }
 
     /**
@@ -697,109 +636,70 @@
      *
      * @return a content object
      */
-    public Content getPackageTableRows() {
-        Content tbody = new HtmlTree(HtmlTag.TBODY);
-        boolean altColor = true;
-        int counter = 0;
-        counter = addPackageTableRows(tbody, counter, ModulePackageTypes.EXPORTED, exportedPackages);
-        counter = addPackageTableRows(tbody, counter, ModulePackageTypes.OPENED, openedPackages);
+    private void addPackageTableRows(Table table) {
+        addPackageTableRows(table, exportedPackages);
+        addPackageTableRows(table, openedPackages);
         // Show concealed packages only in "all" mode.
         if (moduleMode == ModuleMode.ALL) {
             for (PackageElement pkg : concealedPackages) {
                 Content pkgLinkContent = getPackageLink(pkg, new StringContent(utils.getPackageName(pkg)));
-                Content thPackage = HtmlTree.TH_ROW_SCOPE(HtmlStyle.colFirst, pkgLinkContent);
-                HtmlTree tdModules = new HtmlTree(HtmlTag.TD);
-                tdModules.addStyle(HtmlStyle.colSecond);
-                tdModules.addContent(configuration.getText("doclet.None"));
-                HtmlTree tdSummary = new HtmlTree(HtmlTag.TD);
-                tdSummary.addStyle(HtmlStyle.colLast);
-                addSummaryComment(pkg, tdSummary);
-                HtmlTree tr = HtmlTree.TR(thPackage);
-                tr.addContent(tdModules);
-                tr.addContent(tdSummary);
-                tr.addStyle(altColor ? HtmlStyle.altColor : HtmlStyle.rowColor);
-                int pkgType = ModulePackageTypes.CONCEALED.tableTabs().value();
-                packageTypesOr = packageTypesOr | pkgType;
-                String tableId = "i" + counter;
-                counter++;
-                typeMap.put(tableId, pkgType);
-                tr.addAttr(HtmlAttr.ID, tableId);
-                tbody.addContent(tr);
-                altColor = !altColor;
+                Content noModules = new StringContent(resources.getText("doclet.None"));
+                Content summary = new ContentBuilder();
+                addSummaryComment(pkg, summary);
+                table.addRow(pkg, pkgLinkContent, noModules, summary);
             }
         }
-        return tbody;
     }
 
-    public int addPackageTableRows(Content tbody, int counter, ModulePackageTypes pType,
-            Map<PackageElement,SortedSet<ModuleElement>> ap) {
-        boolean altColor = true;
+    private void addPackageTableRows(Table table, Map<PackageElement,SortedSet<ModuleElement>> ap) {
         for (Map.Entry<PackageElement, SortedSet<ModuleElement>> entry : ap.entrySet()) {
+            List<Content> row = new ArrayList<>();
             PackageElement pkg = entry.getKey();
             SortedSet<ModuleElement> mdleList = entry.getValue();
             Content pkgLinkContent = getPackageLink(pkg, new StringContent(utils.getPackageName(pkg)));
-            Content thPackage = HtmlTree.TH_ROW_SCOPE(HtmlStyle.colFirst, pkgLinkContent);
-            HtmlTree tr = HtmlTree.TR(thPackage);
+            row.add(pkgLinkContent);
+
             if (moduleMode == ModuleMode.ALL) {
-                HtmlTree tdModules = new HtmlTree(HtmlTag.TD);
-                tdModules.addStyle(HtmlStyle.colSecond);
+                Content modules = new ContentBuilder();
                 if (!mdleList.isEmpty()) {
-                    int sep = 0;
                     for (ModuleElement m : mdleList) {
-                        if (sep > 0) {
-                            tdModules.addContent(new HtmlTree(HtmlTag.BR));
+                        if (!modules.isEmpty()) {
+                            modules.addContent(new HtmlTree(HtmlTag.BR));
                         }
-                        tdModules.addContent(getModuleLink(m, new StringContent(m.getQualifiedName())));
-                        sep++;
+                        modules.addContent(getModuleLink(m, new StringContent(m.getQualifiedName())));
                     }
                 } else {
-                    tdModules.addContent(configuration.getText("doclet.All_Modules"));
+                    Content allModules = new StringContent(resources.getText("doclet.All_Modules"));
+                    modules.addContent(allModules);
                 }
-                tr.addContent(tdModules);
+                row.add(modules);
             }
-            HtmlTree tdSummary = new HtmlTree(HtmlTag.TD);
-            tdSummary.addStyle(HtmlStyle.colLast);
-            addSummaryComment(pkg, tdSummary);
-            tr.addContent(tdSummary);
-            tr.addStyle(altColor ? HtmlStyle.altColor : HtmlStyle.rowColor);
-            int pkgType = pType.tableTabs().value();
-            packageTypesOr = packageTypesOr | pkgType;
-            String tableId = "i" + counter;
-            counter++;
-            typeMap.put(tableId, pkgType);
-            tr.addAttr(HtmlAttr.ID, tableId);
-            tbody.addContent(tr);
-            altColor = !altColor;
+            Content summary = new ContentBuilder();
+            addSummaryComment(pkg, summary);
+            row.add(summary);
+            table.addRow(pkg, row);
         }
-        return counter;
     }
 
     /**
      * Add the indirect packages for the module being documented.
      *
-     * @param tbody the content tree to which the table will be added
+     * @param table the table to which the content rows will be added
      * @param ip indirect packages to be added
      */
-    public void addIndirectPackages(Content tbody, Map<ModuleElement, SortedSet<PackageElement>> ip) {
-        boolean altColor = true;
+    public void addIndirectPackages(Table table, Map<ModuleElement, SortedSet<PackageElement>> ip) {
         for (Map.Entry<ModuleElement, SortedSet<PackageElement>> entry : ip.entrySet()) {
             ModuleElement m = entry.getKey();
             SortedSet<PackageElement> pkgList = entry.getValue();
             Content moduleLinkContent = getModuleLink(m, new StringContent(m.getQualifiedName()));
-            Content thModule = HtmlTree.TH_ROW_SCOPE(HtmlStyle.colFirst, moduleLinkContent);
-            HtmlTree tdPackages = new HtmlTree(HtmlTag.TD);
-            tdPackages.addStyle(HtmlStyle.colLast);
+            Content packages = new ContentBuilder();
             String sep = "";
             for (PackageElement pkg : pkgList) {
-                tdPackages.addContent(sep);
-                tdPackages.addContent(getPackageLink(pkg, new StringContent(utils.getPackageName(pkg))));
+                packages.addContent(sep);
+                packages.addContent(getPackageLink(pkg, new StringContent(utils.getPackageName(pkg))));
                 sep = " ";
             }
-            HtmlTree tr = HtmlTree.TR(thModule);
-            tr.addContent(tdPackages);
-            tr.addStyle(altColor ? HtmlStyle.altColor : HtmlStyle.rowColor);
-            tbody.addContent(tr);
-            altColor = !altColor;
+            table.addRow(moduleLinkContent, packages);
         }
     }
 
@@ -814,7 +714,7 @@
 
         if (haveProvides || haveUses) {
             HtmlTree li = new HtmlTree(HtmlTag.LI);
-            li.addStyle(HtmlStyle.blockList);
+            li.setStyle(HtmlStyle.blockList);
             addSummaryHeader(HtmlConstants.START_OF_SERVICES_SUMMARY, SectionName.SERVICES,
                     contents.navServices, li);
             TableHeader usesProvidesTableHeader =
@@ -822,27 +722,25 @@
             if (haveProvides) {
                 String label = resources.getText("doclet.Provides_Summary");
                 String tableSummary = resources.getText("doclet.Member_Table_Summary",
-                        label, resources.getText("doclet.types"));
-                Content table = getTable(label, tableSummary, HtmlStyle.providesSummary,
+                        label,
+                        resources.getText("doclet.types"));
+                Table table = getTable2(new StringContent(label), tableSummary, HtmlStyle.providesSummary,
                         usesProvidesTableHeader);
-                Content tbody = new HtmlTree(HtmlTag.TBODY);
-                addProvidesList(tbody);
-                if (!tbody.isEmpty()) {
-                    table.addContent(tbody);
-                    li.addContent(table);
+                addProvidesList(table);
+                if (!table.isEmpty()) {
+                    li.addContent(table.toContent());
                 }
             }
             if (haveUses){
                 String label = resources.getText("doclet.Uses_Summary");
                 String tableSummary = resources.getText("doclet.Member_Table_Summary",
-                        label, resources.getText("doclet.types"));
-                Content table = getTable(label, tableSummary, HtmlStyle.usesSummary,
+                        label,
+                        resources.getText("doclet.types"));
+                Table table = getTable2(new StringContent(label), tableSummary, HtmlStyle.usesSummary,
                         usesProvidesTableHeader);
-                Content tbody = new HtmlTree(HtmlTag.TBODY);
-                addUsesList(tbody);
-                if (!tbody.isEmpty()) {
-                    table.addContent(tbody);
-                    li.addContent(table);
+                addUsesList(table);
+                if (!table.isEmpty()) {
+                    li.addContent(table.toContent());
                 }
             }
             HtmlTree ul = HtmlTree.UL(HtmlStyle.blockList, li);
@@ -853,44 +751,34 @@
     /**
      * Add the uses list for the module.
      *
-     * @param tbody the content tree to which the directive will be added
+     * @param table the table to which the services used will be added
      */
-    public void addUsesList(Content tbody) {
-        boolean altColor = true;
+    public void addUsesList(Table table) {
         Content typeLinkContent;
-        Content thType;
-        HtmlTree tdSummary;
         Content description;
         for (TypeElement t : uses) {
             if (!displayServiceDirective(t, usesTrees)) {
                 continue;
             }
             typeLinkContent = getLink(new LinkInfoImpl(configuration, LinkInfoImpl.Kind.PACKAGE, t));
-            thType = HtmlTree.TH_ROW_SCOPE(HtmlStyle.colFirst, typeLinkContent);
-            tdSummary = new HtmlTree(HtmlTag.TD);
-            tdSummary.addStyle(HtmlStyle.colLast);
+            Content summary = new ContentBuilder();
             if (display(usesTrees)) {
                 description = usesTrees.get(t);
                 if (description != null) {
-                    tdSummary.addContent(description);
+                    summary.addContent(description);
                 }
             }
-            addSummaryComment(t, tdSummary);
-            HtmlTree tr = HtmlTree.TR(thType);
-            tr.addContent(tdSummary);
-            tr.addStyle(altColor ? HtmlStyle.altColor : HtmlStyle.rowColor);
-            tbody.addContent(tr);
-            altColor = !altColor;
+            addSummaryComment(t, summary);
+            table.addRow(typeLinkContent, summary);
         }
     }
 
     /**
      * Add the provides list for the module.
      *
-     * @param tbody the content tree to which the directive will be added
+     * @param table the table to which the services provided will be added
      */
-    public void addProvidesList(Content tbody) {
-        boolean altColor = true;
+    public void addProvidesList(Table table) {
         SortedSet<TypeElement> implSet;
         Content description;
         for (Map.Entry<TypeElement, SortedSet<TypeElement>> entry : provides.entrySet()) {
@@ -900,36 +788,30 @@
             }
             implSet = entry.getValue();
             Content srvLinkContent = getLink(new LinkInfoImpl(configuration, LinkInfoImpl.Kind.PACKAGE, srv));
-            HtmlTree thType = HtmlTree.TH_ROW_SCOPE(HtmlStyle.colFirst, srvLinkContent);
-            HtmlTree tdDesc = new HtmlTree(HtmlTag.TD);
-            tdDesc.addStyle(HtmlStyle.colLast);
+            Content desc = new ContentBuilder();
             if (display(providesTrees)) {
                 description = providesTrees.get(srv);
                 if (description != null) {
-                    tdDesc.addContent(description);
+                    desc.addContent(description);
                 }
             }
-            addSummaryComment(srv, tdDesc);
+            addSummaryComment(srv, desc);
             // Only display the implementation details in the "all" mode.
             if (moduleMode == ModuleMode.ALL && !implSet.isEmpty()) {
-                tdDesc.addContent(new HtmlTree(HtmlTag.BR));
-                tdDesc.addContent("(");
+                desc.addContent(new HtmlTree(HtmlTag.BR));
+                desc.addContent("(");
                 HtmlTree implSpan = HtmlTree.SPAN(HtmlStyle.implementationLabel, contents.implementation);
-                tdDesc.addContent(implSpan);
-                tdDesc.addContent(Contents.SPACE);
+                desc.addContent(implSpan);
+                desc.addContent(Contents.SPACE);
                 String sep = "";
                 for (TypeElement impl : implSet) {
-                    tdDesc.addContent(sep);
-                    tdDesc.addContent(getLink(new LinkInfoImpl(configuration, LinkInfoImpl.Kind.PACKAGE, impl)));
+                    desc.addContent(sep);
+                    desc.addContent(getLink(new LinkInfoImpl(configuration, LinkInfoImpl.Kind.PACKAGE, impl)));
                     sep = ", ";
                 }
-                tdDesc.addContent(")");
+                desc.addContent(")");
             }
-            HtmlTree tr = HtmlTree.TR(thType);
-            tr.addContent(tdDesc);
-            tr.addStyle(altColor ? HtmlStyle.altColor : HtmlStyle.rowColor);
-            tbody.addContent(tr);
-            altColor = !altColor;
+            table.addRow(srvLinkContent, desc);
         }
     }
 
@@ -943,7 +825,7 @@
         if (utils.isDeprecated(mdle)) {
             CommentHelper ch = utils.getCommentHelper(mdle);
             HtmlTree deprDiv = new HtmlTree(HtmlTag.DIV);
-            deprDiv.addStyle(HtmlStyle.deprecationBlock);
+            deprDiv.setStyle(HtmlStyle.deprecationBlock);
             Content deprPhrase = HtmlTree.SPAN(HtmlStyle.deprecatedLabel, getDeprecatedPhrase(mdle));
             deprDiv.addContent(deprPhrase);
             if (!deprs.isEmpty()) {
@@ -965,7 +847,7 @@
             Content tree = configuration.allowTag(HtmlTag.SECTION) ? HtmlTree.SECTION() : moduleContentTree;
             addDeprecationInfo(tree);
             tree.addContent(HtmlConstants.START_OF_MODULE_DESCRIPTION);
-            tree.addContent(getMarkerAnchor(SectionName.MODULE_DESCRIPTION));
+            tree.addContent(links.createAnchor(SectionName.MODULE_DESCRIPTION));
             addInlineComment(mdle, tree);
             if (configuration.allowTag(HtmlTag.SECTION)) {
                 moduleContentTree.addContent(tree);
@@ -1009,20 +891,20 @@
         Content ulNav = HtmlTree.UL(HtmlStyle.subNavList, li);
         Content liNav = new HtmlTree(HtmlTag.LI);
         liNav.addContent(!utils.getFullBody(mdle).isEmpty() && !configuration.nocomment
-                ? getHyperLink(SectionName.MODULE_DESCRIPTION, contents.navModuleDescription)
+                ? Links.createLink(SectionName.MODULE_DESCRIPTION, contents.navModuleDescription)
                 : contents.navModuleDescription);
         addNavGap(liNav);
         liNav.addContent((display(requires) || display(indirectModules))
-                ? getHyperLink(SectionName.MODULES, contents.navModules)
+                ? Links.createLink(SectionName.MODULES, contents.navModules)
                 : contents.navModules);
         addNavGap(liNav);
         liNav.addContent((display(exportedPackages) || display(openedPackages) || display(concealedPackages)
                 || display(indirectPackages) || display(indirectOpenPackages))
-                ? getHyperLink(SectionName.PACKAGES, contents.navPackages)
+                ? Links.createLink(SectionName.PACKAGES, contents.navPackages)
                 : contents.navPackages);
         addNavGap(liNav);
         liNav.addContent((displayServices(uses, usesTrees) || displayServices(provides.keySet(), providesTrees))
-                ? getHyperLink(SectionName.SERVICES, contents.navServices)
+                ? Links.createLink(SectionName.SERVICES, contents.navServices)
                 : contents.navServices);
         ulNav.addContent(liNav);
         return ulNav;
@@ -1078,7 +960,7 @@
         if (utils.isDeprecated(pkg)) {
             deprs = utils.getDeprecatedTrees(pkg);
             HtmlTree deprDiv = new HtmlTree(HtmlTag.DIV);
-            deprDiv.addStyle(HtmlStyle.deprecationBlock);
+            deprDiv.setStyle(HtmlStyle.deprecationBlock);
             Content deprPhrase = HtmlTree.SPAN(HtmlStyle.deprecatedLabel, getDeprecatedPhrase(pkg));
             deprDiv.addContent(deprPhrase);
             if (!deprs.isEmpty()) {
@@ -1114,7 +996,7 @@
         if (prevModule == null) {
             li = HtmlTree.LI(contents.prevModuleLabel);
         } else {
-            li = HtmlTree.LI(getHyperLink(pathToRoot.resolve(DocPaths.moduleSummary(
+            li = HtmlTree.LI(Links.createLink(pathToRoot.resolve(DocPaths.moduleSummary(
                     prevModule)), contents.prevModuleLabel, "", ""));
         }
         return li;
@@ -1131,7 +1013,7 @@
         if (nextModule == null) {
             li = HtmlTree.LI(contents.nextModuleLabel);
         } else {
-            li = HtmlTree.LI(getHyperLink(pathToRoot.resolve(DocPaths.moduleSummary(
+            li = HtmlTree.LI(Links.createLink(pathToRoot.resolve(DocPaths.moduleSummary(
                     nextModule)), contents.nextModuleLabel, "", ""));
         }
         return li;
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/NestedClassWriterImpl.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/NestedClassWriterImpl.java	Mon Nov 27 17:04:45 2017 +0000
@@ -25,13 +25,19 @@
 
 package jdk.javadoc.internal.doclets.formats.html;
 
+import jdk.javadoc.internal.doclets.formats.html.markup.Table;
+import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader;
+
+import java.util.Arrays;
+import java.util.List;
+
 import javax.lang.model.element.Element;
 import javax.lang.model.element.TypeElement;
 
-import jdk.javadoc.internal.doclets.formats.html.TableHeader;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlConstants;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
+import jdk.javadoc.internal.doclets.formats.html.markup.Links;
 import jdk.javadoc.internal.doclets.formats.html.markup.StringContent;
 import jdk.javadoc.internal.doclets.toolkit.Content;
 import jdk.javadoc.internal.doclets.toolkit.MemberSummaryWriter;
@@ -94,33 +100,29 @@
      * {@inheritDoc}
      */
     @Override
-    public String getTableSummary() {
-        return resources.getText("doclet.Member_Table_Summary",
-                resources.getText("doclet.Nested_Class_Summary"),
-                resources.getText("doclet.nested_classes"));
-    }
+    public TableHeader getSummaryTableHeader(Element member) {
+        Content label = utils.isInterface(member) ?
+                contents.interfaceLabel : contents.classLabel;
 
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public Content getCaption() {
-        return configuration.getContent("doclet.Nested_Classes");
+        return new TableHeader(contents.modifierAndTypeLabel, label, contents.descriptionLabel);
     }
 
-    /**
-     * {@inheritDoc}
-     */
     @Override
-    public TableHeader getSummaryTableHeader(Element member) {
-        if (utils.isInterface(member)) {
-            return new TableHeader(contents.modifierAndTypeLabel, contents.interfaceLabel,
-                    contents.descriptionLabel);
+    protected Table createSummaryTable() {
+        String summary =  resources.getText("doclet.Member_Table_Summary",
+                resources.getText("doclet.Nested_Class_Summary"),
+                resources.getText("doclet.nested_classes"));
+
+        List<HtmlStyle> bodyRowStyles = Arrays.asList(HtmlStyle.colFirst, HtmlStyle.colSecond,
+                HtmlStyle.colLast);
 
-        } else {
-            return new TableHeader(contents.modifierAndTypeLabel, contents.classLabel,
-                    contents.descriptionLabel);
-        }
+        return new Table(configuration.htmlVersion, HtmlStyle.memberSummary)
+                .setSummary(summary)
+                .setCaption(contents.getContent("doclet.Nested_Classes"))
+                .setHeader(getSummaryTableHeader(typeElement))
+                .setRowScopeColumn(1)
+                .setColumnStyles(bodyRowStyles)
+                .setUseTBody(false);  // temporary? compatibility mode for TBody
     }
 
     /**
@@ -128,7 +130,7 @@
      */
     @Override
     public void addSummaryAnchor(TypeElement typeElement, Content memberTree) {
-        memberTree.addContent(writer.getMarkerAnchor(
+        memberTree.addContent(links.createAnchor(
                 SectionName.NESTED_CLASS_SUMMARY));
     }
 
@@ -137,7 +139,7 @@
      */
     @Override
     public void addInheritedSummaryAnchor(TypeElement typeElement, Content inheritedTree) {
-        inheritedTree.addContent(writer.getMarkerAnchor(
+        inheritedTree.addContent(links.createAnchor(
                 SectionName.NESTED_CLASSES_INHERITANCE,
                 utils.getFullyQualifiedName(typeElement)));
     }
@@ -211,11 +213,11 @@
     protected Content getNavSummaryLink(TypeElement typeElement, boolean link) {
         if (link) {
             if (typeElement == null) {
-                return writer.getHyperLink(
+                return Links.createLink(
                         SectionName.NESTED_CLASS_SUMMARY,
                         contents.navNested);
             } else {
-                return writer.getHyperLink(
+                return links.createLink(
                         SectionName.NESTED_CLASSES_INHERITANCE,
                         utils.getFullyQualifiedName(typeElement), contents.navNested);
             }
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageFrameWriter.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageFrameWriter.java	Mon Nov 27 17:04:45 2017 +0000
@@ -108,7 +108,7 @@
                 packgen.getTargetPackageLink(packageElement, "classFrame", pkgNameContent));
         htmlTree.addContent(heading);
         HtmlTree div = new HtmlTree(HtmlTag.DIV);
-        div.addStyle(HtmlStyle.indexContainer);
+        div.setStyle(HtmlStyle.indexContainer);
         packgen.addClassListing(div);
         htmlTree.addContent(div);
         if (configuration.allowTag(HtmlTag.MAIN)) {
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageIndexFrameWriter.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageIndexFrameWriter.java	Mon Nov 27 17:04:45 2017 +0000
@@ -33,6 +33,7 @@
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
+import jdk.javadoc.internal.doclets.formats.html.markup.Links;
 import jdk.javadoc.internal.doclets.formats.html.markup.RawHtml;
 import jdk.javadoc.internal.doclets.formats.html.markup.StringContent;
 import jdk.javadoc.internal.doclets.toolkit.Content;
@@ -109,11 +110,11 @@
         Content packageLabel;
         if (pe.isUnnamed()) {
             packageLabel = new StringContent("<unnamed package>");
-            packageLinkContent = getHyperLink(DocPaths.PACKAGE_FRAME,
+            packageLinkContent = Links.createLink(DocPaths.PACKAGE_FRAME,
                     packageLabel, "", "packageFrame");
         } else {
             packageLabel = getPackageLabel(pe.getQualifiedName());
-            packageLinkContent = getHyperLink(pathString(pe,
+            packageLinkContent = Links.createLink(pathString(pe,
                      DocPaths.PACKAGE_FRAME), packageLabel, "",
                     "packageFrame");
         }
@@ -152,7 +153,7 @@
      */
     @Override
     protected void addAllClassesLink(Content ul) {
-        Content linkContent = getHyperLink(DocPaths.ALLCLASSES_FRAME,
+        Content linkContent = Links.createLink(DocPaths.ALLCLASSES_FRAME,
                 contents.allClassesLabel, "", "packageFrame");
         Content li = HtmlTree.LI(linkContent);
         ul.addContent(li);
@@ -166,7 +167,7 @@
      */
     @Override
     protected void addAllModulesLink(Content ul) {
-        Content linkContent = getHyperLink(DocPaths.MODULE_OVERVIEW_FRAME,
+        Content linkContent = Links.createLink(DocPaths.MODULE_OVERVIEW_FRAME,
                 contents.allModulesLabel, "", "packageListFrame");
         Content li = HtmlTree.LI(linkContent);
         ul.addContent(li);
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageIndexWriter.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageIndexWriter.java	Mon Nov 27 17:04:45 2017 +0000
@@ -25,21 +25,21 @@
 
 package jdk.javadoc.internal.doclets.formats.html;
 
+import jdk.javadoc.internal.doclets.formats.html.markup.Table;
+
 import java.util.*;
 
 import javax.lang.model.element.PackageElement;
 
-import jdk.javadoc.internal.doclets.formats.html.markup.HtmlAttr;
+import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
-import jdk.javadoc.internal.doclets.formats.html.markup.StringContent;
 import jdk.javadoc.internal.doclets.toolkit.Content;
 import jdk.javadoc.internal.doclets.toolkit.util.DocFileIOException;
 import jdk.javadoc.internal.doclets.toolkit.util.DocPath;
 import jdk.javadoc.internal.doclets.toolkit.util.DocPaths;
 import jdk.javadoc.internal.doclets.toolkit.util.Group;
-import jdk.javadoc.internal.doclets.toolkit.util.GroupTypes;
 
 /**
  * Generate the package index page "overview-summary.html" for the right-hand
@@ -56,29 +56,6 @@
  */
 public class PackageIndexWriter extends AbstractPackageIndexWriter {
 
-
-    /**
-     * Map representing the group of packages as specified on the command line.
-     *
-     * @see Group
-     */
-    private final Map<String, SortedSet<PackageElement>> groupPackageMap;
-
-    /**
-     * List to store the order groups, which has elements to be displayed, as specified on the command line.
-     */
-    private final List<String> groupList = new ArrayList<>();
-
-    private final GroupTypes groupTypes;
-
-    private int groupTypesOr = 0;
-
-    protected Map<String, Integer> groupTypeMap = new LinkedHashMap<>();
-
-    boolean altColor = true;
-
-    int counter = 0;
-
     /**
      * HTML tree for main tag.
      */
@@ -95,11 +72,6 @@
      */
     public PackageIndexWriter(HtmlConfiguration configuration, DocPath filename) {
         super(configuration, filename);
-        groupPackageMap = configuration.group.groupPackages(packages);
-        configuration.group.getGroupList().stream()
-                .filter(groupPackageMap::containsKey)
-                .forEachOrdered(groupList::add);
-        groupTypes = new GroupTypes(groupList, resources.getText("doclet.All_Packages"));
     }
 
     /**
@@ -130,68 +102,50 @@
      */
     @Override
     protected void addPackagesList(Content body) {
-        if (!groupList.isEmpty()) {
-            Content caption;
-            TreeMap<PackageElement, String> groupMap = new TreeMap<>(utils.makePackageComparator());
-            Content tbody = new HtmlTree(HtmlTag.TBODY);
+        Map<String, SortedSet<PackageElement>> groupPackageMap
+                = configuration.group.groupPackages(packages);
+
+        if (!groupPackageMap.keySet().isEmpty()) {
             String tableSummary = configuration.getText("doclet.Member_Table_Summary",
                     configuration.getText("doclet.Package_Summary"), configuration.getText("doclet.packages"));
-            for (String groupname : groupList) {
-                for (PackageElement pkg : groupPackageMap.get(groupname)) {
-                    groupMap.put(pkg, groupname);
+            Table table =  new Table(configuration.htmlVersion, HtmlStyle.overviewSummary)
+                    .setSummary(tableSummary)
+                    .setHeader(getPackageTableHeader())
+                    .setColumnStyles(HtmlStyle.colFirst, HtmlStyle.colLast)
+                    .setDefaultTab(resources.getText("doclet.All_Packages"))
+                    .setTabScriptVariable("groups")
+                    .setTabScript(i -> "showGroups(" + i + ");")
+                    .setTabId(i -> (i == 0) ? "t0" : ("t" + (1 << (i - 1))));
+
+            // add the tabs in command-line order
+            for (String groupName : configuration.group.getGroupList()) {
+                Set<PackageElement> groupPackages = groupPackageMap.get(groupName);
+                if (groupPackages != null) {
+                    table.addTab(groupName, groupPackages::contains);
                 }
             }
-            if (!groupMap.isEmpty()) {
-                addPackagesList(groupMap, tbody);
+
+            for (PackageElement pkg : configuration.packages) {
+                if (!pkg.isUnnamed()) {
+                    if (!(configuration.nodeprecated && utils.isDeprecated(pkg))) {
+                        Content packageLinkContent = getPackageLink(pkg, getPackageName(pkg));
+                        Content summaryContent = new ContentBuilder();
+                        addSummaryComment(pkg, summaryContent);
+                        table.addRow(pkg, packageLinkContent, summaryContent);
+                    }
+                }
             }
-            if (showTabs(groupTypes)) {
-                caption = getTableCaption(groupTypes);
-                generateGroupTypesScript(groupTypeMap, groupTypes.getGroupTypes());
-            } else {
-                caption = getTableCaption((groupList.size() == 1) ? new StringContent(groupList.get(0)) : contents.packagesLabel);
-            }
-            Content table = getTableHeader(caption, tableSummary, HtmlStyle.overviewSummary);
-            table.addContent(getPackageTableHeader().toContent());
-            table.addContent(tbody);
-            Content div = HtmlTree.DIV(HtmlStyle.contentContainer, table);
+
+            Content div = HtmlTree.DIV(HtmlStyle.contentContainer, table.toContent());
             if (configuration.allowTag(HtmlTag.MAIN)) {
                 htmlTree.addContent(div);
             } else {
                 body.addContent(div);
             }
-        }
-    }
 
-    /**
-     * Adds list of packages in the index table. Generate link to each package.
-     *
-     * @param map map of package elements and group names
-     * @param tbody the documentation tree to which the list will be added
-     */
-    protected void addPackagesList(TreeMap<PackageElement, String> map, Content tbody) {
-        String groupname;
-        for (PackageElement pkg : map.keySet()) {
-            if (!pkg.isUnnamed()) {
-                if (!(configuration.nodeprecated && utils.isDeprecated(pkg))) {
-                    groupname = map.get(pkg);
-                    Content packageLinkContent = getPackageLink(pkg, getPackageName(pkg));
-                    Content thPackage = HtmlTree.TH_ROW_SCOPE(HtmlStyle.colFirst, packageLinkContent);
-                    HtmlTree tdSummary = new HtmlTree(HtmlTag.TD);
-                    tdSummary.addStyle(HtmlStyle.colLast);
-                    addSummaryComment(pkg, tdSummary);
-                    HtmlTree tr = HtmlTree.TR(thPackage);
-                    tr.addContent(tdSummary);
-                    tr.addStyle(altColor ? HtmlStyle.altColor : HtmlStyle.rowColor);
-                    int groupType = groupTypes.getTableTab(groupname).value();
-                    groupTypesOr = groupTypesOr | groupType;
-                    String tableId = "i" + counter;
-                    counter++;
-                    groupTypeMap.put(tableId, groupType);
-                    tr.addAttr(HtmlAttr.ID, tableId);
-                    tbody.addContent(tr);
-                }
+            if (table.needsScript()) {
+                getMainBodyScript().append(table.getScript());
             }
-            altColor = !altColor;
         }
     }
 
@@ -207,7 +161,7 @@
         addConfigurationTitle(body);
         if (!utils.getFullBody(configuration.overviewElement).isEmpty()) {
             HtmlTree div = new HtmlTree(HtmlTag.DIV);
-            div.addStyle(HtmlStyle.contentContainer);
+            div.setStyle(HtmlStyle.contentContainer);
             addOverviewComment(div);
             if (configuration.allowTag(HtmlTag.MAIN)) {
                 htmlTree.addContent(div);
@@ -251,13 +205,13 @@
      */
     @Override
     protected void addNavigationBarHeader(Content body) {
-        Content htmlTree = (configuration.allowTag(HtmlTag.HEADER))
+        Content tree = (configuration.allowTag(HtmlTag.HEADER))
                 ? HtmlTree.HEADER()
                 : body;
-        addTop(htmlTree);
-        addNavLinks(true, htmlTree);
+        addTop(tree);
+        addNavLinks(true, tree);
         if (configuration.allowTag(HtmlTag.HEADER)) {
-            body.addContent(htmlTree);
+            body.addContent(tree);
         }
     }
 
@@ -269,13 +223,13 @@
      */
     @Override
     protected void addNavigationBarFooter(Content body) {
-        Content htmlTree = (configuration.allowTag(HtmlTag.FOOTER))
+        Content tree = (configuration.allowTag(HtmlTag.FOOTER))
                 ? HtmlTree.FOOTER()
                 : body;
-        addNavLinks(false, htmlTree);
-        addBottom(htmlTree);
+        addNavLinks(false, tree);
+        addBottom(tree);
         if (configuration.allowTag(HtmlTag.FOOTER)) {
-            body.addContent(htmlTree);
+            body.addContent(tree);
         }
     }
 }
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageTreeWriter.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageTreeWriter.java	Mon Nov 27 17:04:45 2017 +0000
@@ -31,6 +31,7 @@
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
+import jdk.javadoc.internal.doclets.formats.html.markup.Links;
 import jdk.javadoc.internal.doclets.toolkit.Content;
 import jdk.javadoc.internal.doclets.toolkit.util.ClassTree;
 import jdk.javadoc.internal.doclets.toolkit.util.DocFileIOException;
@@ -126,7 +127,7 @@
         }
         htmlTree.addContent(div);
         HtmlTree divTree = new HtmlTree(HtmlTag.DIV);
-        divTree.addStyle(HtmlStyle.contentContainer);
+        divTree.setStyle(HtmlStyle.contentContainer);
         addTree(classtree.baseClasses(), "doclet.Class_Hierarchy", divTree);
         addTree(classtree.baseInterfaces(), "doclet.Interface_Hierarchy", divTree);
         addTree(classtree.baseAnnotationTypes(), "doclet.Annotation_Type_Hierarchy", divTree);
@@ -176,7 +177,7 @@
                 contents.packageHierarchies);
         div.addContent(span);
         HtmlTree ul = new HtmlTree (HtmlTag.UL);
-        ul.addStyle(HtmlStyle.horizontal);
+        ul.setStyle(HtmlStyle.horizontal);
         ul.addContent(getNavLinkMainTree(configuration.getText("doclet.All_Packages")));
         div.addContent(ul);
     }
@@ -231,7 +232,7 @@
      */
     @Override
     protected Content getNavLinkPackage() {
-        Content linkContent = getHyperLink(DocPaths.PACKAGE_SUMMARY,
+        Content linkContent = Links.createLink(DocPaths.PACKAGE_SUMMARY,
                 contents.packageLabel);
         Content li = HtmlTree.LI(linkContent);
         return li;
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageUseWriter.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageUseWriter.java	Mon Nov 27 17:04:45 2017 +0000
@@ -25,6 +25,9 @@
 
 package jdk.javadoc.internal.doclets.formats.html;
 
+import jdk.javadoc.internal.doclets.formats.html.markup.Table;
+import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader;
+
 import java.util.*;
 
 import javax.lang.model.element.PackageElement;
@@ -35,6 +38,7 @@
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
+import jdk.javadoc.internal.doclets.formats.html.markup.Links;
 import jdk.javadoc.internal.doclets.formats.html.markup.StringContent;
 import jdk.javadoc.internal.doclets.toolkit.Content;
 import jdk.javadoc.internal.doclets.toolkit.util.ClassUseMapper;
@@ -121,7 +125,7 @@
     protected void generatePackageUseFile() throws DocFileIOException {
         HtmlTree body = getPackageUseHeader();
         HtmlTree div = new HtmlTree(HtmlTag.DIV);
-        div.addStyle(HtmlStyle.contentContainer);
+        div.setStyle(HtmlStyle.contentContainer);
         if (usingPackageToUsedClasses.isEmpty()) {
             div.addContent(contents.getContent("doclet.ClassUse_No.usage.of.0", utils.getPackageName(packageElement)));
         } else {
@@ -151,7 +155,7 @@
      */
     protected void addPackageUse(Content contentTree) {
         HtmlTree ul = new HtmlTree(HtmlTag.UL);
-        ul.addStyle(HtmlStyle.blockList);
+        ul.setStyle(HtmlStyle.blockList);
         if (configuration.packages.size() > 1) {
             addPackageList(ul);
         }
@@ -165,25 +169,27 @@
      * @param contentTree the content tree to which the package list will be added
      */
     protected void addPackageList(Content contentTree) {
-        Content caption = getTableCaption(configuration.getContent(
+        Content caption = contents.getContent(
                 "doclet.ClassUse_Packages.that.use.0",
-                getPackageLink(packageElement, utils.getPackageName(packageElement))));
-        Content table = (configuration.isOutputHtml5())
-                ? HtmlTree.TABLE(HtmlStyle.useSummary, caption)
-                : HtmlTree.TABLE(HtmlStyle.useSummary, packageUseTableSummary, caption);
-        table.addContent(getPackageTableHeader().toContent());
-        Content tbody = new HtmlTree(HtmlTag.TBODY);
-        boolean altColor = true;
+                getPackageLink(packageElement, utils.getPackageName(packageElement)));
+        Table table = new Table(configuration.htmlVersion, HtmlStyle.useSummary)
+                .setSummary(packageUseTableSummary)
+                .setCaption(caption)
+                .setHeader(getPackageTableHeader())
+                .setColumnStyles(HtmlStyle.colFirst, HtmlStyle.colLast);
         for (String pkgname: usingPackageToUsedClasses.keySet()) {
             PackageElement pkg = utils.elementUtils.getPackageElement(pkgname);
-            HtmlTree tr = new HtmlTree(HtmlTag.TR);
-            tr.addStyle(altColor ? HtmlStyle.altColor : HtmlStyle.rowColor);
-            altColor = !altColor;
-            addPackageUse(pkg, tr);
-            tbody.addContent(tr);
+            Content packageLink = links.createLink(utils.getPackageName(pkg),
+                    new StringContent(utils.getPackageName(pkg)));
+            Content summary = new ContentBuilder();
+            if (pkg != null && !pkg.isUnnamed()) {
+                addSummaryComment(pkg, summary);
+            } else {
+                summary.addContent(Contents.SPACE);
+            }
+            table.addRow(packageLink, summary);
         }
-        table.addContent(tbody);
-        Content li = HtmlTree.LI(HtmlStyle.blockList, table);
+        Content li = HtmlTree.LI(HtmlStyle.blockList, table.toContent());
         contentTree.addContent(li);
     }
 
@@ -198,86 +204,46 @@
         for (String packageName : usingPackageToUsedClasses.keySet()) {
             PackageElement usingPackage = utils.elementUtils.getPackageElement(packageName);
             HtmlTree li = new HtmlTree(HtmlTag.LI);
-            li.addStyle(HtmlStyle.blockList);
+            li.setStyle(HtmlStyle.blockList);
             if (usingPackage != null) {
-                li.addContent(getMarkerAnchor(utils.getPackageName(usingPackage)));
+                li.addContent(links.createAnchor(utils.getPackageName(usingPackage)));
             }
-            String tableSummary = configuration.getText("doclet.Use_Table_Summary",
-                                                        configuration.getText("doclet.classes"));
-            Content caption = getTableCaption(configuration.getContent(
+            String tableSummary = resources.getText("doclet.Use_Table_Summary",
+                                                        resources.getText("doclet.classes"));
+            Content caption = contents.getContent(
                     "doclet.ClassUse_Classes.in.0.used.by.1",
                     getPackageLink(packageElement, utils.getPackageName(packageElement)),
-                    getPackageLink(usingPackage, utils.getPackageName(usingPackage))));
-            Content table = (configuration.isOutputHtml5())
-                    ? HtmlTree.TABLE(HtmlStyle.useSummary, caption)
-                    : HtmlTree.TABLE(HtmlStyle.useSummary, tableSummary, caption);
-            table.addContent(classTableHeader.toContent());
-            Content tbody = new HtmlTree(HtmlTag.TBODY);
-            boolean altColor = true;
+                    getPackageLink(usingPackage, utils.getPackageName(usingPackage)));
+            Table table = new Table(configuration.htmlVersion, HtmlStyle.useSummary)
+                    .setSummary(tableSummary)
+                    .setCaption(caption)
+                    .setHeader(classTableHeader)
+                    .setColumnStyles(HtmlStyle.colFirst, HtmlStyle.colLast);
             for (TypeElement te : usingPackageToUsedClasses.get(packageName)) {
-                HtmlTree tr = new HtmlTree(HtmlTag.TR);
-                tr.addStyle(altColor ? HtmlStyle.altColor : HtmlStyle.rowColor);
-                altColor = !altColor;
-                addClassRow(te, usingPackage, tr);
-                tbody.addContent(tr);
+                DocPath dp = pathString(te,
+                        DocPaths.CLASS_USE.resolve(DocPath.forName(utils, te)));
+                Content stringContent = new StringContent(utils.getSimpleName(te));
+                Content typeContent = Links.createLink(dp.fragment(getPackageAnchorName(usingPackage)),
+                        stringContent);
+                Content summary = new ContentBuilder();
+                addIndexComment(te, summary);
+
+                table.addRow(typeContent, summary);
             }
-            table.addContent(tbody);
-            li.addContent(table);
+            li.addContent(table.toContent());
             contentTree.addContent(li);
         }
     }
 
     /**
-     * Add a row for the class that uses the given package.
-     *
-     * @param usedClass the class that uses the given package
-     * @param pkg  the package to which the class belongs
-     * @param contentTree the content tree to which the row will be added
-     */
-    protected void addClassRow(TypeElement usedClass, PackageElement pkg,
-            Content contentTree) {
-        DocPath dp = pathString(usedClass,
-                DocPaths.CLASS_USE.resolve(DocPath.forName(utils, usedClass)));
-        StringContent stringContent = new StringContent(utils.getSimpleName(usedClass));
-        Content thType = HtmlTree.TH_ROW_SCOPE(HtmlStyle.colFirst,
-                getHyperLink(dp.fragment(getPackageAnchorName(pkg)), stringContent));
-        contentTree.addContent(thType);
-        HtmlTree tdDesc = new HtmlTree(HtmlTag.TD);
-        tdDesc.addStyle(HtmlStyle.colLast);
-        addIndexComment(usedClass, tdDesc);
-        contentTree.addContent(tdDesc);
-    }
-
-    /**
-     * Add the package use information.
-     *
-     * @param pkg the package that used the given package
-     * @param contentTree the content tree to which the information will be added
-     */
-    protected void addPackageUse(PackageElement pkg, Content contentTree) {
-        Content thFirst = HtmlTree.TH_ROW_SCOPE(HtmlStyle.colFirst,
-                getHyperLink(utils.getPackageName(pkg),
-                new StringContent(utils.getPackageName(pkg))));
-        contentTree.addContent(thFirst);
-        HtmlTree tdLast = new HtmlTree(HtmlTag.TD);
-        tdLast.addStyle(HtmlStyle.colLast);
-        if (pkg != null && !pkg.isUnnamed()) {
-            addSummaryComment(pkg, tdLast);
-        } else {
-            tdLast.addContent(Contents.SPACE);
-        }
-        contentTree.addContent(tdLast);
-    }
-
-    /**
      * Get the header for the package use listing.
      *
      * @return a content tree representing the package use header
      */
-    protected HtmlTree getPackageUseHeader() {
-        String packageText = configuration.getText("doclet.Package");
+    private HtmlTree getPackageUseHeader() {
+        String packageText = resources.getText("doclet.Package");
         String name = packageElement.isUnnamed() ? "" : utils.getPackageName(packageElement);
-        String title = configuration.getText("doclet.Window_ClassUse_Header", packageText, name);
+        String title = resources.getText("doclet.Window_ClassUse_Header", packageText, name);
         HtmlTree bodyTree = getBody(true, getWindowTitle(title));
         HtmlTree htmlTree = (configuration.allowTag(HtmlTag.HEADER))
                 ? HtmlTree.HEADER()
@@ -322,7 +288,7 @@
      */
     @Override
     protected Content getNavLinkPackage() {
-        Content linkContent = getHyperLink(DocPaths.PACKAGE_SUMMARY,
+        Content linkContent = Links.createLink(DocPaths.PACKAGE_SUMMARY,
                 contents.packageLabel);
         Content li = HtmlTree.LI(linkContent);
         return li;
@@ -346,7 +312,7 @@
      */
     @Override
     protected Content getNavLinkTree() {
-        Content linkContent = getHyperLink(DocPaths.PACKAGE_TREE,
+        Content linkContent = Links.createLink(DocPaths.PACKAGE_TREE,
                 contents.treeLabel);
         Content li = HtmlTree.LI(linkContent);
         return li;
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageWriterImpl.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageWriterImpl.java	Mon Nov 27 17:04:45 2017 +0000
@@ -25,6 +25,9 @@
 
 package jdk.javadoc.internal.doclets.formats.html;
 
+import jdk.javadoc.internal.doclets.formats.html.markup.Table;
+import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader;
+
 import java.util.*;
 
 import javax.lang.model.element.ModuleElement;
@@ -32,11 +35,12 @@
 import javax.lang.model.element.TypeElement;
 
 import com.sun.source.doctree.DocTree;
+import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlConstants;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
-import jdk.javadoc.internal.doclets.formats.html.markup.RawHtml;
+import jdk.javadoc.internal.doclets.formats.html.markup.Links;
 import jdk.javadoc.internal.doclets.formats.html.markup.StringContent;
 import jdk.javadoc.internal.doclets.toolkit.Content;
 import jdk.javadoc.internal.doclets.toolkit.PackageSummaryWriter;
@@ -124,7 +128,7 @@
             bodyTree.addContent(htmlTree);
         }
         HtmlTree div = new HtmlTree(HtmlTag.DIV);
-        div.addStyle(HtmlStyle.header);
+        div.setStyle(HtmlStyle.header);
         if (configuration.showModules) {
             ModuleElement mdle = configuration.docEnv.getElementUtils().getModuleOf(packageElement);
             Content classModuleLabel = HtmlTree.SPAN(HtmlStyle.moduleLabelInPackage, contents.moduleLabel);
@@ -157,7 +161,7 @@
     @Override
     public Content getContentHeader() {
         HtmlTree div = new HtmlTree(HtmlTag.DIV);
-        div.addStyle(HtmlStyle.contentContainer);
+        div.setStyle(HtmlStyle.contentContainer);
         return div;
     }
 
@@ -171,7 +175,7 @@
         if (utils.isDeprecated(packageElement)) {
             CommentHelper ch = utils.getCommentHelper(packageElement);
             HtmlTree deprDiv = new HtmlTree(HtmlTag.DIV);
-            deprDiv.addStyle(HtmlStyle.deprecationBlock);
+            deprDiv.setStyle(HtmlStyle.deprecationBlock);
             Content deprPhrase = HtmlTree.SPAN(HtmlStyle.deprecatedLabel, getDeprecatedPhrase(packageElement));
             deprDiv.addContent(deprPhrase);
             if (!deprs.isEmpty()) {
@@ -190,7 +194,7 @@
     @Override
     public Content getSummaryHeader() {
         HtmlTree ul = new HtmlTree(HtmlTag.UL);
-        ul.addStyle(HtmlStyle.blockList);
+        ul.setStyle(HtmlStyle.blockList);
         return ul;
     }
 
@@ -278,47 +282,34 @@
         addClassesSummary(annoTypes, label, tableSummary, tableHeader, summaryContentTree);
     }
 
-    /**
-     * {@inheritDoc}
-     */
     public void addClassesSummary(SortedSet<TypeElement> classes, String label,
             String tableSummary, TableHeader tableHeader, Content summaryContentTree) {
         if(!classes.isEmpty()) {
-            Content caption = getTableCaption(new RawHtml(label));
-            Content table = (configuration.isOutputHtml5())
-                    ? HtmlTree.TABLE(HtmlStyle.typeSummary, caption)
-                    : HtmlTree.TABLE(HtmlStyle.typeSummary, tableSummary, caption);
-            table.addContent(tableHeader.toContent());
-            Content tbody = new HtmlTree(HtmlTag.TBODY);
-            boolean altColor = false;
+            Table table = new Table(configuration.htmlVersion, HtmlStyle.typeSummary)
+                    .setSummary(tableSummary)
+                    .setCaption(getTableCaption(new StringContent(label)))
+                    .setHeader(tableHeader)
+                    .setColumnStyles(HtmlStyle.colFirst, HtmlStyle.colLast);
+
             for (TypeElement klass : classes) {
-                if (!utils.isCoreClass(klass) ||
-                    !configuration.isGeneratedDoc(klass)) {
+                if (!utils.isCoreClass(klass) || !configuration.isGeneratedDoc(klass)) {
                     continue;
                 }
-                altColor = !altColor;
-                Content classContent = getLink(new LinkInfoImpl(
+                Content classLink = getLink(new LinkInfoImpl(
                         configuration, LinkInfoImpl.Kind.PACKAGE, klass));
-                Content thClass = HtmlTree.TH_ROW_SCOPE(HtmlStyle.colFirst, classContent);
-                HtmlTree tr = HtmlTree.TR(thClass);
-                tr.addStyle(altColor ? HtmlStyle.altColor : HtmlStyle.rowColor);
-
-                HtmlTree tdClassDescription = new HtmlTree(HtmlTag.TD);
-                tdClassDescription.addStyle(HtmlStyle.colLast);
+                ContentBuilder description = new ContentBuilder();
                 if (utils.isDeprecated(klass)) {
-                    tdClassDescription.addContent(getDeprecatedPhrase(klass));
+                    description.addContent(getDeprecatedPhrase(klass));
                     List<? extends DocTree> tags = utils.getDeprecatedTrees(klass);
                     if (!tags.isEmpty()) {
-                        addSummaryDeprecatedComment(klass, tags.get(0), tdClassDescription);
+                        addSummaryDeprecatedComment(klass, tags.get(0), description);
                     }
                 } else {
-                    addSummaryComment(klass, tdClassDescription);
+                    addSummaryComment(klass, description);
                 }
-                tr.addContent(tdClassDescription);
-                tbody.addContent(tr);
+                table.addRow(classLink, description);
             }
-            table.addContent(tbody);
-            Content li = HtmlTree.LI(HtmlStyle.blockList, table);
+            Content li = HtmlTree.LI(HtmlStyle.blockList, table.toContent());
             summaryContentTree.addContent(li);
         }
     }
@@ -330,7 +321,7 @@
     public void addPackageDescription(Content packageContentTree) {
         if (!utils.getBody(packageElement).isEmpty()) {
             Content tree = configuration.allowTag(HtmlTag.SECTION) ? sectionTree : packageContentTree;
-            tree.addContent(getMarkerAnchor(SectionName.PACKAGE_DESCRIPTION));
+            tree.addContent(links.createAnchor(SectionName.PACKAGE_DESCRIPTION));
             addDeprecationInfo(tree);
             addInlineComment(packageElement, tree);
         }
@@ -394,7 +385,7 @@
      */
     @Override
     protected Content getNavLinkClassUse() {
-        Content useLink = getHyperLink(DocPaths.PACKAGE_USE,
+        Content useLink = Links.createLink(DocPaths.PACKAGE_USE,
                 contents.useLabel, "", "");
         Content li = HtmlTree.LI(useLink);
         return li;
@@ -411,8 +402,8 @@
         if (prev == null) {
             li = HtmlTree.LI(contents.prevPackageLabel);
         } else {
-            DocPath path = DocPath.relativePath(packageElement, prev);
-            li = HtmlTree.LI(getHyperLink(path.resolve(DocPaths.PACKAGE_SUMMARY),
+            DocPath p = DocPath.relativePath(packageElement, prev);
+            li = HtmlTree.LI(Links.createLink(p.resolve(DocPaths.PACKAGE_SUMMARY),
                 contents.prevPackageLabel, "", ""));
         }
         return li;
@@ -429,8 +420,8 @@
         if (next == null) {
             li = HtmlTree.LI(contents.nextPackageLabel);
         } else {
-            DocPath path = DocPath.relativePath(packageElement, next);
-            li = HtmlTree.LI(getHyperLink(path.resolve(DocPaths.PACKAGE_SUMMARY),
+            DocPath p = DocPath.relativePath(packageElement, next);
+            li = HtmlTree.LI(Links.createLink(p.resolve(DocPaths.PACKAGE_SUMMARY),
                 contents.nextPackageLabel, "", ""));
         }
         return li;
@@ -444,7 +435,7 @@
      */
     @Override
     protected Content getNavLinkTree() {
-        Content useLink = getHyperLink(DocPaths.PACKAGE_TREE,
+        Content useLink = Links.createLink(DocPaths.PACKAGE_TREE,
                 contents.treeLabel, "", "");
         Content li = HtmlTree.LI(useLink);
         return li;
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PropertyWriterImpl.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PropertyWriterImpl.java	Mon Nov 27 17:04:45 2017 +0000
@@ -26,15 +26,18 @@
 package jdk.javadoc.internal.doclets.formats.html;
 
 
+import jdk.javadoc.internal.doclets.formats.html.markup.Table;
+import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader;
+
 import javax.lang.model.element.Element;
 import javax.lang.model.element.ExecutableElement;
 import javax.lang.model.element.TypeElement;
 
-import jdk.javadoc.internal.doclets.formats.html.TableHeader;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlConstants;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
+import jdk.javadoc.internal.doclets.formats.html.markup.Links;
 import jdk.javadoc.internal.doclets.formats.html.markup.StringContent;
 import jdk.javadoc.internal.doclets.toolkit.Content;
 import jdk.javadoc.internal.doclets.toolkit.MemberSummaryWriter;
@@ -72,11 +75,6 @@
         return memberTree;
     }
 
-    @Override
-    public boolean showTabs() {
-        return false;
-    }
-
     /**
      * {@inheritDoc}
      */
@@ -93,8 +91,7 @@
             Content memberDetailsTree) {
         memberDetailsTree.addContent(HtmlConstants.START_OF_PROPERTY_DETAILS);
         Content propertyDetailsTree = writer.getMemberTreeHeader();
-        propertyDetailsTree.addContent(writer.getMarkerAnchor(
-                SectionName.PROPERTY_DETAIL));
+        propertyDetailsTree.addContent(links.createAnchor(SectionName.PROPERTY_DETAIL));
         Content heading = HtmlTree.HEADING(HtmlConstants.DETAILS_HEADING,
                 contents.propertyDetailsLabel);
         propertyDetailsTree.addContent(heading);
@@ -107,8 +104,7 @@
     @Override
     public Content getPropertyDocTreeHeader(ExecutableElement property,
             Content propertyDetailsTree) {
-        propertyDetailsTree.addContent(
-                writer.getMarkerAnchor(name(property)));
+        propertyDetailsTree.addContent(links.createAnchor(name(property)));
         Content propertyDocTree = writer.getMemberTreeHeader();
         Content heading = new HtmlTree(HtmlConstants.MEMBER_HEADING);
         heading.addContent(utils.getPropertyLabel(name(property)));
@@ -218,24 +214,6 @@
      * {@inheritDoc}
      */
     @Override
-    public String getTableSummary() {
-        return resources.getText("doclet.Member_Table_Summary",
-                resources.getText("doclet.Property_Summary"),
-                resources.getText("doclet.properties"));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public Content getCaption() {
-        return contents.properties;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
     public TableHeader getSummaryTableHeader(Element member) {
         return new TableHeader(contents.typeLabel, contents.propertyLabel,
                 contents.descriptionLabel);
@@ -245,9 +223,26 @@
      * {@inheritDoc}
      */
     @Override
+    protected Table createSummaryTable() {
+        String summary = resources.getText("doclet.Member_Table_Summary",
+            resources.getText("doclet.Property_Summary"),
+            resources.getText("doclet.properties"));
+
+        return new Table(configuration.htmlVersion, HtmlStyle.memberSummary)
+                .setSummary(summary)
+                .setCaption(contents.properties)
+                .setHeader(getSummaryTableHeader(typeElement))
+                .setColumnStyles(HtmlStyle.colFirst, HtmlStyle.colSecond, HtmlStyle.colLast)
+                .setRowScopeColumn(1)
+                .setUseTBody(false);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
     public void addSummaryAnchor(TypeElement typeElement, Content memberTree) {
-        memberTree.addContent(writer.getMarkerAnchor(
-                SectionName.PROPERTY_SUMMARY));
+        memberTree.addContent(links.createAnchor(SectionName.PROPERTY_SUMMARY));
     }
 
     /**
@@ -255,7 +250,7 @@
      */
     @Override
     public void addInheritedSummaryAnchor(TypeElement typeElement, Content inheritedTree) {
-        inheritedTree.addContent(writer.getMarkerAnchor(
+        inheritedTree.addContent(links.createAnchor(
                 SectionName.PROPERTIES_INHERITANCE,
                 configuration.getClassName(typeElement)));
     }
@@ -270,12 +265,12 @@
         Content label;
         if (configuration.summarizeOverriddenMethods) {
             label = new StringContent(utils.isClass(typeElement)
-                    ? configuration.getText("doclet.Properties_Declared_In_Class")
-                    : configuration.getText("doclet.Properties_Declared_In_Interface"));
+                    ? resources.getText("doclet.Properties_Declared_In_Class")
+                    : resources.getText("doclet.Properties_Declared_In_Interface"));
         } else {
             label = new StringContent(utils.isClass(typeElement)
-                    ? configuration.getText("doclet.Properties_Inherited_From_Class")
-                    : configuration.getText("doclet.Properties_Inherited_From_Interface"));
+                    ? resources.getText("doclet.Properties_Inherited_From_Class")
+                    : resources.getText("doclet.Properties_Inherited_From_Interface"));
         }
         Content labelHeading = HtmlTree.HEADING(HtmlConstants.INHERITED_SUMMARY_HEADING,
                 label);
@@ -337,13 +332,13 @@
     protected Content getNavSummaryLink(TypeElement typeElement, boolean link) {
         if (link) {
             if (typeElement == null) {
-                return writer.getHyperLink(
-                SectionName.PROPERTY_SUMMARY,
-                contents.navProperty);
+                return Links.createLink(
+                        SectionName.PROPERTY_SUMMARY,
+                        contents.navProperty);
             } else {
-                return writer.getHyperLink(
-                SectionName.PROPERTIES_INHERITANCE,
-                configuration.getClassName(typeElement), contents.navProperty);
+                return links.createLink(
+                        SectionName.PROPERTIES_INHERITANCE,
+                        configuration.getClassName(typeElement), contents.navProperty);
             }
         } else {
             return contents.navProperty;
@@ -356,7 +351,7 @@
     @Override
     protected void addNavDetailLink(boolean link, Content liNav) {
         if (link) {
-            liNav.addContent(writer.getHyperLink(
+            liNav.addContent(Links.createLink(
                     SectionName.PROPERTY_DETAIL,
                     contents.navProperty));
         } else {
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SerializedFormWriterImpl.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SerializedFormWriterImpl.java	Mon Nov 27 17:04:45 2017 +0000
@@ -102,7 +102,7 @@
      */
     public Content getSerializedSummariesHeader() {
         HtmlTree ul = new HtmlTree(HtmlTag.UL);
-        ul.addStyle(HtmlStyle.blockList);
+        ul.setStyle(HtmlStyle.blockList);
         return ul;
     }
 
@@ -117,7 +117,7 @@
             htmlTree = HtmlTree.SECTION();
         } else {
             htmlTree = new HtmlTree(HtmlTag.LI);
-            htmlTree.addStyle(HtmlStyle.blockList);
+            htmlTree.setStyle(HtmlStyle.blockList);
         }
         return htmlTree;
     }
@@ -143,7 +143,7 @@
      */
     public Content getClassSerializedHeader() {
         HtmlTree ul = new HtmlTree(HtmlTag.UL);
-        ul.addStyle(HtmlStyle.blockList);
+        ul.setStyle(HtmlStyle.blockList);
         return ul;
     }
 
@@ -168,7 +168,7 @@
                 ? getLink(new LinkInfoImpl(configuration, LinkInfoImpl.Kind.DEFAULT, typeElement)
                         .label(configuration.getClassName(typeElement)))
                 : new StringContent(utils.getFullyQualifiedName(typeElement));
-        Content li = HtmlTree.LI(HtmlStyle.blockList, getMarkerAnchor(
+        Content li = HtmlTree.LI(HtmlStyle.blockList, links.createAnchor(
                 utils.getFullyQualifiedName(typeElement)));
         Content superClassLink = typeElement.getSuperclass() != null
                 ? getLink(new LinkInfoImpl(configuration, LinkInfoImpl.Kind.SERIALIZED_FORM,
@@ -194,7 +194,7 @@
      */
     public Content getSerialUIDInfoHeader() {
         HtmlTree dl = new HtmlTree(HtmlTag.DL);
-        dl.addStyle(HtmlStyle.nameValue);
+        dl.setStyle(HtmlStyle.nameValue);
         return dl;
     }
 
@@ -221,7 +221,7 @@
      */
     public Content getClassContentHeader() {
         HtmlTree ul = new HtmlTree(HtmlTag.UL);
-        ul.addStyle(HtmlStyle.blockList);
+        ul.setStyle(HtmlStyle.blockList);
         return ul;
     }
 
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SingleIndexWriter.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SingleIndexWriter.java	Mon Nov 27 17:04:45 2017 +0000
@@ -102,7 +102,7 @@
             body.addContent(htmlTree);
         }
         HtmlTree divTree = new HtmlTree(HtmlTag.DIV);
-        divTree.addStyle(HtmlStyle.contentContainer);
+        divTree.setStyle(HtmlStyle.contentContainer);
         elements = new TreeSet<>(indexbuilder.getIndexMap().keySet());
         elements.addAll(configuration.tagSearchIndexKeys);
         addLinksForIndexes(divTree);
@@ -141,7 +141,7 @@
         for (Object ch : elements) {
             String unicode = ch.toString();
             contentTree.addContent(
-                    getHyperLink(getNameForIndex(unicode),
+                    links.createLink(getNameForIndex(unicode),
                             new StringContent(unicode)));
             contentTree.addContent(Contents.SPACE);
         }
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SourceToHTMLConverter.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SourceToHTMLConverter.java	Mon Nov 27 17:04:45 2017 +0000
@@ -25,6 +25,8 @@
 
 package jdk.javadoc.internal.doclets.formats.html;
 
+import jdk.javadoc.internal.doclets.formats.html.markup.Head;
+
 import java.io.*;
 import java.util.List;
 
@@ -42,6 +44,7 @@
 import jdk.javadoc.internal.doclets.formats.html.markup.StringContent;
 import jdk.javadoc.internal.doclets.toolkit.Content;
 import jdk.javadoc.internal.doclets.toolkit.Messages;
+import jdk.javadoc.internal.doclets.toolkit.Resources;
 import jdk.javadoc.internal.doclets.toolkit.util.DocFile;
 import jdk.javadoc.internal.doclets.toolkit.util.DocFileIOException;
 import jdk.javadoc.internal.doclets.toolkit.util.DocPath;
@@ -77,6 +80,7 @@
 
     private final HtmlConfiguration configuration;
     private final Messages messages;
+    private final Resources resources;
     private final Utils utils;
 
     private final DocletEnvironment docEnv;
@@ -93,6 +97,7 @@
                                   DocPath outputdir) {
         this.configuration  = configuration;
         this.messages = configuration.getMessages();
+        this.resources = configuration.resources;
         this.utils = configuration.utils;
         this.docEnv = rd;
         this.outputdir = outputdir;
@@ -193,7 +198,7 @@
             body.addContent((configuration.allowTag(HtmlTag.MAIN)) ? HtmlTree.MAIN(div) : div);
             writeToFile(body, outputdir.resolve(DocPath.forClass(utils, te)));
         } catch (IOException e) {
-            String message = configuration.resources.getText("doclet.exception.read.file", fo.getName());
+            String message = resources.getText("doclet.exception.read.file", fo.getName());
             throw new SimpleDocletException(message, e);
         }
     }
@@ -205,24 +210,18 @@
      * @param path the path for the file.
      */
     private void writeToFile(Content body, DocPath path) throws DocFileIOException {
-        Content htmlDocType = configuration.isOutputHtml5()
-                ? DocType.HTML5
-                : DocType.TRANSITIONAL;
-        Content head = new HtmlTree(HtmlTag.HEAD);
-        head.addContent(HtmlTree.TITLE(new StringContent(
-                configuration.getText("doclet.Window_Source_title"))));
-        addStyleSheetProperties(head);
+        DocType htmlDocType = DocType.forVersion(configuration.htmlVersion);
+        Head head = new Head(path, configuration.htmlVersion, configuration.docletVersion)
+//                .setTimestamp(!configuration.notimestamp) // temporary: compatibility!
+                .setTitle(resources.getText("doclet.Window_Source_title"))
+//                .setCharset(configuration.charset) // temporary: compatibility!
+                .addDefaultScript(false)
+                .setStylesheets(configuration.getMainStylesheet(), configuration.getAdditionalStylesheets());
         Content htmlTree = HtmlTree.HTML(configuration.getLocale().getLanguage(),
-                head, body);
-        Content htmlDocument = new HtmlDocument(htmlDocType, htmlTree);
+                head.toContent(), body);
+        HtmlDocument htmlDocument = new HtmlDocument(htmlDocType, htmlTree);
         messages.notice("doclet.Generating_0", path.getPath());
-        DocFile df = DocFile.createFileForOutput(configuration, path);
-        try (Writer w = df.openWriter()) {
-            htmlDocument.write(w, true);
-        } catch (IOException e) {
-            throw new DocFileIOException(df, DocFileIOException.Mode.WRITE, e);
-        }
-
+        htmlDocument.write(DocFile.createFileForOutput(configuration, path));
     }
 
     /**
@@ -275,7 +274,7 @@
      */
     private static void addLineNo(Content pre, int lineno) {
         HtmlTree span = new HtmlTree(HtmlTag.SPAN);
-        span.addStyle(HtmlStyle.sourceLineNo);
+        span.setStyle(HtmlStyle.sourceLineNo);
         if (lineno < 10) {
             span.addContent("00" + Integer.toString(lineno));
         } else if (lineno < 100) {
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SplitIndexWriter.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SplitIndexWriter.java	Mon Nov 27 17:04:45 2017 +0000
@@ -35,6 +35,7 @@
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
+import jdk.javadoc.internal.doclets.formats.html.markup.Links;
 import jdk.javadoc.internal.doclets.formats.html.markup.StringContent;
 import jdk.javadoc.internal.doclets.toolkit.Content;
 import jdk.javadoc.internal.doclets.toolkit.util.DocFileIOException;
@@ -145,7 +146,7 @@
             body.addContent(htmlTree);
         }
         HtmlTree divTree = new HtmlTree(HtmlTag.DIV);
-        divTree.addStyle(HtmlStyle.contentContainer);
+        divTree.setStyle(HtmlStyle.contentContainer);
         addLinksForIndexes(divTree);
         if (configuration.tagSearchIndexMap.get(unicode) == null) {
             addContents(unicode, indexbuilder.getMemberList(unicode), divTree);
@@ -176,7 +177,7 @@
     protected void addLinksForIndexes(Content contentTree) {
         for (int i = 0; i < indexElements.size(); i++) {
             int j = i + 1;
-            contentTree.addContent(getHyperLink(DocPaths.indexN(j),
+            contentTree.addContent(Links.createLink(DocPaths.indexN(j),
                     new StringContent(indexElements.get(i).toString())));
             contentTree.addContent(Contents.SPACE);
         }
@@ -194,7 +195,7 @@
             return HtmlTree.LI(prevletterLabel);
         }
         else {
-            Content prevLink = getHyperLink(DocPaths.indexN(prev),
+            Content prevLink = Links.createLink(DocPaths.indexN(prev),
                     prevletterLabel);
             return HtmlTree.LI(prevLink);
         }
@@ -212,7 +213,7 @@
             return HtmlTree.LI(nextletterLabel);
         }
         else {
-            Content nextLink = getHyperLink(DocPaths.indexN(next),
+            Content nextLink = Links.createLink(DocPaths.indexN(next),
                     nextletterLabel);
             return HtmlTree.LI(nextLink);
         }
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SubWriterHolderWriter.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SubWriterHolderWriter.java	Mon Nov 27 17:04:45 2017 +0000
@@ -36,7 +36,6 @@
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
 import jdk.javadoc.internal.doclets.toolkit.Content;
 import jdk.javadoc.internal.doclets.toolkit.util.DocPath;
-import jdk.javadoc.internal.doclets.toolkit.util.MethodTypes;
 
 /**
  * This abstract class exists to provide functionality needed in the
@@ -73,7 +72,7 @@
      * Add the summary header.
      *
      * @param mw the writer for the member being documented
-     * @param typeElement the te to be documented
+     * @param typeElement the type element to be documented
      * @param memberTree the content tree to which the summary header will be added
      */
     public void addSummaryHeader(AbstractMemberWriter mw, TypeElement typeElement,
@@ -83,74 +82,6 @@
     }
 
     /**
-     * Get the summary table.
-     *
-     * @param mw the writer for the member being documented
-     * @param typeElement the te to be documented
-     * @param tableContents list of summary table contents
-     * @param showTabs true if the table needs to show tabs
-     * @return the content tree for the summary table
-     */
-    public Content getSummaryTableTree(AbstractMemberWriter mw, TypeElement typeElement,
-            List<Content> tableContents, boolean showTabs) {
-        Content caption;
-        if (showTabs) {
-            caption = getTableCaption(mw.methodTypes);
-            generateTableTabTypesScript(mw.typeMap, mw.methodTypes, "methods");
-        }
-        else {
-            caption = getTableCaption(mw.getCaption());
-        }
-        Content table = (configuration.isOutputHtml5())
-                ? HtmlTree.TABLE(HtmlStyle.memberSummary, caption)
-                : HtmlTree.TABLE(HtmlStyle.memberSummary, mw.getTableSummary(), caption);
-        table.addContent(mw.getSummaryTableHeader(typeElement).toContent());
-        for (Content tableContent : tableContents) {
-            table.addContent(tableContent);
-        }
-        return table;
-    }
-
-    /**
-     * Get the summary table caption.
-     *
-     * @param methodTypes set comprising of method types to show as table caption
-     * @return the caption for the summary table
-     */
-    public Content getTableCaption(Set<MethodTypes> methodTypes) {
-        Content tabbedCaption = new HtmlTree(HtmlTag.CAPTION);
-        for (MethodTypes type : methodTypes) {
-            Content captionSpan;
-            Content span;
-            if (type.tableTabs().isDefaultTab()) {
-                captionSpan = HtmlTree.SPAN(configuration.getContent(type.tableTabs().resourceKey()));
-                span = HtmlTree.SPAN(type.tableTabs().tabId(),
-                        HtmlStyle.activeTableTab, captionSpan);
-            } else {
-                captionSpan = HtmlTree.SPAN(getMethodTypeLinks(type));
-                span = HtmlTree.SPAN(type.tableTabs().tabId(),
-                        HtmlStyle.tableTab, captionSpan);
-            }
-            Content tabSpan = HtmlTree.SPAN(HtmlStyle.tabEnd, Contents.SPACE);
-            span.addContent(tabSpan);
-            tabbedCaption.addContent(span);
-        }
-        return tabbedCaption;
-    }
-
-    /**
-     * Get the method type links for the table caption.
-     *
-     * @param methodType the method type to be displayed as link
-     * @return the content tree for the method type link
-     */
-    public Content getMethodTypeLinks(MethodTypes methodType) {
-        String jsShow = "javascript:show(" + methodType.tableTabs().value() +");";
-        HtmlTree link = HtmlTree.A(jsShow, configuration.getContent(methodType.tableTabs().resourceKey()));
-        return link;
-    }
-
-    /**
      * Add the inherited summary header.
      *
      * @param mw the writer for the member being documented
@@ -205,17 +136,6 @@
     }
 
     /**
-     * Add the summary type for the member.
-     *
-     * @param mw the writer for the member being documented
-     * @param member the member to be documented
-     * @param tdSummaryType the content tree to which the type will be added
-     */
-    public void addSummaryType(AbstractMemberWriter mw, Element member, Content tdSummaryType) {
-        mw.addSummaryType(member, tdSummaryType);
-    }
-
-    /**
      * Add the summary link for the member.
      *
      * @param mw the writer for the member being documented
@@ -264,7 +184,7 @@
      */
     public Content getContentHeader() {
         HtmlTree div = new HtmlTree(HtmlTag.DIV);
-        div.addStyle(HtmlStyle.contentContainer);
+        div.setStyle(HtmlStyle.contentContainer);
         return div;
     }
 
@@ -300,7 +220,7 @@
      */
     public Content getMemberTreeHeader() {
         HtmlTree li = new HtmlTree(HtmlTag.LI);
-        li.addStyle(HtmlStyle.blockList);
+        li.setStyle(HtmlStyle.blockList);
         return li;
     }
 
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/TableHeader.java	Fri Nov 24 17:19:47 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,112 +0,0 @@
-/*
- * Copyright (c) 2017, 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.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.
- */
-
-package jdk.javadoc.internal.doclets.formats.html;
-
-import java.util.Arrays;
-import java.util.List;
-import java.util.stream.Collectors;
-
-import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
-import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
-import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
-import jdk.javadoc.internal.doclets.toolkit.Content;
-
-/**
- * A row header for an HTML table.
- *
- * The header contains a list of {@code <th>} cells, providing the column headers.
- * The attribute {@code scope="col"} is automatically added to each header cell.
- * In addition, a series of style class names can be specified, to be applied one per cell.
- *
- */
-public class TableHeader {
-
-    /**
-     * The content to be put in each of the {@code <th>} cells in the header row.
-     */
-    private final List<Content> cellContents;
-    /**
-     * The style class names for each of the {@code <th>} cells in the header row.
-     * If not set, default style names will be used.
-     */
-    private List<HtmlStyle> styles;
-
-    /**
-     * Creates a header row, with localized content for each cell.
-     * Resources keys will be converted to content using {@link Contents#getContent(String)}.
-     * @param contents a factory to get the content for each header cell.
-     * @param colHeaderKeys the resource keys for the content in each cell.
-     */
-    TableHeader(Contents contents, String... colHeaderKeys) {
-        this.cellContents = Arrays.stream(colHeaderKeys)
-                .map((key) -> contents.getContent(key))
-                .collect(Collectors.toList());
-    }
-
-    /**
-     * Creates a header row, with specified content for each cell.
-     * @param headerCellContents a content object for each header cell
-     */
-    TableHeader(Content... headerCellContents) {
-        this.cellContents = Arrays.asList(headerCellContents);
-    }
-
-    /**
-     * Set the style class names for each header cell.
-     * The number of names must match the number of cells given to the constructor.
-     * @param styles the style class names
-     * @return this object
-     */
-    TableHeader styles(HtmlStyle... styles) {
-        if (styles.length != cellContents.size()) {
-            throw new IllegalStateException();
-        }
-        this.styles = Arrays.asList(styles);
-        return this;
-    }
-
-    /**
-     * Converts this header to a {@link Content} object, for use in an {@link HtmlTree}.
-     * @returns a Content object
-     */
-    Content toContent() {
-        String scope = "col";
-        Content tr = new HtmlTree(HtmlTag.TR);
-        int i = 0;
-        for (Content cellContent : cellContents) {
-            HtmlStyle style = (styles != null) ? styles.get(i)
-                    : (i == 0) ? HtmlStyle.colFirst
-                    : (i == (cellContents.size() - 1)) ? HtmlStyle.colLast
-                    : (i == 1) ? HtmlStyle.colSecond : null;
-            Content cell = (style == null) ? HtmlTree.TH(scope, cellContent)
-                    : HtmlTree.TH(style, scope, cellContent);
-            tr.addContent(cell);
-            i++;
-        }
-        return tr;
-    }
-
-}
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/TagletWriterImpl.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/TagletWriterImpl.java	Mon Nov 27 17:04:45 2017 +0000
@@ -40,6 +40,7 @@
 import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
+import jdk.javadoc.internal.doclets.formats.html.markup.Links;
 import jdk.javadoc.internal.doclets.formats.html.markup.RawHtml;
 import jdk.javadoc.internal.doclets.formats.html.markup.StringContent;
 import jdk.javadoc.internal.doclets.toolkit.BaseConfiguration;
@@ -105,7 +106,7 @@
         }
         String desc = ch.getText(itt.getDescription());
 
-        String anchorName = htmlWriter.getName(tagText);
+        String anchorName = configuration.links.getName(tagText);
         Content result = HtmlTree.A_ID(HtmlStyle.searchTagResult, anchorName, new StringContent(tagText));
         if (configuration.createindex && !tagText.isEmpty()) {
             SearchIndexItem si = new SearchIndexItem();
@@ -287,7 +288,7 @@
                     ((ClassWriterImpl) htmlWriter).getTypeElement().getQualifiedName() + "." +
                     utils.getSimpleName(holder);
             DocLink link = constantsPath.fragment(whichConstant);
-            body.addContent(htmlWriter.getHyperLink(link,
+            body.addContent(Links.createLink(link,
                     new StringContent(configuration.getText("doclet.Constants_Summary"))));
         }
         if (utils.isClass(holder) && utils.isSerializable((TypeElement)holder)) {
@@ -297,7 +298,7 @@
                 appendSeparatorIfNotEmpty(body);
                 DocPath serialPath = htmlWriter.pathToRoot.resolve(DocPaths.SERIALIZED_FORM);
                 DocLink link = serialPath.fragment(utils.getFullyQualifiedName(holder));
-                body.addContent(htmlWriter.getHyperLink(link,
+                body.addContent(Links.createLink(link,
                         new StringContent(configuration.getText("doclet.Serialized_Form"))));
             }
         }
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/TreeWriter.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/TreeWriter.java	Mon Nov 27 17:04:45 2017 +0000
@@ -33,6 +33,7 @@
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
+import jdk.javadoc.internal.doclets.formats.html.markup.Links;
 import jdk.javadoc.internal.doclets.formats.html.markup.StringContent;
 import jdk.javadoc.internal.doclets.toolkit.Content;
 import jdk.javadoc.internal.doclets.toolkit.util.ClassTree;
@@ -112,7 +113,7 @@
                 : body;
         htmlTree.addContent(div);
         HtmlTree divTree = new HtmlTree(HtmlTag.DIV);
-        divTree.addStyle(HtmlStyle.contentContainer);
+        divTree.setStyle(HtmlStyle.contentContainer);
         addTree(classtree.baseClasses(), "doclet.Class_Hierarchy", divTree);
         addTree(classtree.baseInterfaces(), "doclet.Interface_Hierarchy", divTree);
         addTree(classtree.baseAnnotationTypes(), "doclet.Annotation_Type_Hierarchy", divTree);
@@ -149,7 +150,7 @@
                     contents.packageHierarchies);
             contentTree.addContent(span);
             HtmlTree ul = new HtmlTree(HtmlTag.UL);
-            ul.addStyle(HtmlStyle.horizontal);
+            ul.setStyle(HtmlStyle.horizontal);
             int i = 0;
             for (PackageElement pkg : packages) {
                 // If the package name length is 0 or if -nodeprecated option
@@ -161,7 +162,7 @@
                     continue;
                 }
                 DocPath link = pathString(pkg, DocPaths.PACKAGE_TREE);
-                Content li = HtmlTree.LI(getHyperLink(link,
+                Content li = HtmlTree.LI(Links.createLink(link,
                         new StringContent(utils.getPackageName(pkg))));
                 if (i < packages.size() - 1) {
                     li.addContent(", ");
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/ContentBuilder.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/ContentBuilder.java	Mon Nov 27 17:04:45 2017 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2017, 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
@@ -39,6 +39,14 @@
 public class ContentBuilder extends Content {
     protected List<Content> contents = Collections.emptyList();
 
+    public ContentBuilder() { }
+
+    public ContentBuilder(Content... contents) {
+        for (Content c : contents) {
+            addContent(c);
+        }
+    }
+
     @Override
     public void addContent(Content content) {
         nullCheck(content);
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/DocType.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/DocType.java	Mon Nov 27 17:04:45 2017 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2017, 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
@@ -25,14 +25,8 @@
 
 package jdk.javadoc.internal.doclets.formats.html.markup;
 
-import java.io.IOException;
-import java.io.Writer;
-
-import jdk.javadoc.internal.doclets.toolkit.Content;
-import jdk.javadoc.internal.doclets.toolkit.util.DocletConstants;
-
 /**
- * Class for generating document type for HTML pages of javadoc output.
+ *  Supported DOCTYPE declarations.
  *
  *  <p><b>This is NOT part of any supported API.
  *  If you write code that depends on this, you do so at your own risk.
@@ -41,67 +35,22 @@
  *
  * @author Bhavesh Patel
  */
-public class DocType extends Content {
-
-    private String docType;
-
-    public static final DocType TRANSITIONAL =
-            new DocType("Transitional", "http://www.w3.org/TR/html4/loose.dtd");
-
-    public static final DocType HTML5 = new DocType();
+public enum DocType {
+    HTML4_TRANSITIONAL("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" "
+            + "\"http://www.w3.org/TR/html4/loose.dtd\">"),
+    HTML5("<!DOCTYPE HTML>");
 
-    /**
-     * Constructor to construct a DocType object.
-     *
-     * @param type the doctype to be added
-     * @param dtd the dtd of the doctype
-     */
-    private DocType(String type, String dtd) {
-        docType = "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 " + type +
-                "//EN\" \"" + dtd + "\">" + DocletConstants.NL;
-    }
+    public final String text;
 
-    /**
-     * Constructor to construct a DocType object.
-     */
-    private DocType() {
-        docType = "<!DOCTYPE HTML>" + DocletConstants.NL;
+    DocType(String text) {
+        this.text = text;
     }
 
-    /**
-     * This method is not supported by the class.
-     *
-     * @param content content that needs to be added
-     * @throws UnsupportedOperationException always
-     */
-    public void addContent(Content content) {
-        throw new UnsupportedOperationException();
-    }
-
-    /**
-     * This method is not supported by the class.
-     *
-     * @param stringContent string content that needs to be added
-     * @throws UnsupportedOperationException always
-     */
-    @Override
-    public void addContent(CharSequence stringContent) {
-        throw new UnsupportedOperationException();
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public boolean isEmpty() {
-        return (docType.length() == 0);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public boolean write(Writer out, boolean atNewline) throws IOException {
-        out.write(docType);
-        return true; // guaranteed by constructor
+    public static DocType forVersion(HtmlVersion v) {
+        switch (v) {
+            case HTML4: return HTML4_TRANSITIONAL;
+            case HTML5: return HTML5;
+            default: throw new IllegalArgumentException();
+        }
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/Head.java	Mon Nov 27 17:04:45 2017 +0000
@@ -0,0 +1,327 @@
+/*
+ * Copyright (c) 2003, 2017, 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+
+package jdk.javadoc.internal.doclets.formats.html.markup;
+
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Calendar;
+import java.util.Collections;
+import java.util.Date;
+import java.util.GregorianCalendar;
+import java.util.List;
+import java.util.TimeZone;
+
+import jdk.javadoc.internal.doclets.toolkit.Content;
+import jdk.javadoc.internal.doclets.toolkit.util.DocFile;
+import jdk.javadoc.internal.doclets.toolkit.util.DocPath;
+import jdk.javadoc.internal.doclets.toolkit.util.DocPaths;
+
+/**
+ * A builder for HTML HEAD elements.
+ *
+ * Many methods return the current object, to facilitate fluent builder-style usage.
+ *
+ *  <p><b>This is NOT part of any supported API.
+ *  If you write code that depends on this, you do so at your own risk.
+ *  This code and its internal interfaces are subject to change or
+ *  deletion without notice.</b>
+ */
+public class Head {
+    private final HtmlVersion htmlVersion;
+    private final String docletVersion;
+    private final DocPath pathToRoot;
+    private String title;
+    private String charset;
+    private final List<String> keywords;
+    private boolean showTimestamp;
+    private boolean showGeneratedBy;    // temporary: for compatibility
+    private boolean showMetaCreated;    // temporary: for compatibility
+    private DocFile mainStylesheetFile;
+    private List<DocFile> additionalStylesheetFiles = Collections.emptyList();
+    private boolean index;
+    private Script mainBodyScript;
+    private final List<Script> scripts;
+    private final List<Content> extraContent;
+    boolean addDefaultScript = true;
+
+    private static final Calendar calendar = new GregorianCalendar(TimeZone.getDefault());
+
+    /**
+     * Creates a {@code Head} object, for a given file and HTML version.
+     * The file is used to help determine the relative paths to stylesheet and script files.
+     * The HTML version is used to determine the the appropriate form of a META element
+     * recording the time the file was created.
+     * The doclet version should also be provided for recording in the file.
+     * @param path the path for the file that will include this HEAD element
+     * @param htmlVersion the HTML version
+     * @param docletVersion a string identifying the doclet version
+     */
+    public Head(DocPath path, HtmlVersion htmlVersion, String docletVersion) {
+        this.htmlVersion = htmlVersion;
+        this.docletVersion = docletVersion;
+        pathToRoot = path.parent().invert();
+        keywords = new ArrayList<>();
+        scripts = new ArrayList<>();
+        extraContent = new ArrayList<>();
+    }
+
+    /**
+     * Sets the title to appear in the TITLE element.
+     *
+     * @param title the title
+     * @return this object
+     */
+    public Head setTitle(String title) {
+        this.title = title;
+        return this;
+    }
+
+    /**
+     * Sets the charset to be declared in a META [@code Content-TYPE} element.
+     *
+     * @param charset the charset
+     * @return this object
+     */
+    // For temporary compatibility, this is currently optional.
+    // Eventually, this should be a required call.
+    public Head setCharset(String charset) {
+        this.charset = charset;
+        return this;
+    }
+
+    /**
+     * Adds a list of keywords to appear in META [@code keywords} elements.
+     *
+     * @param keywords the list of keywords, or null if none need to be added
+     * @return this object
+     */
+    public Head addKeywords(List<String> keywords) {
+        if (keywords != null) {
+            this.keywords.addAll(keywords);
+        }
+        return this;
+    }
+
+    /**
+     * Sets whether or not timestamps should be recorded in the HEAD element.
+     * The timestamp will be recorded in a comment, and in an appropriate META
+     * element, depending on the HTML version specified when this object was created.
+     *
+     * @param timestamp true if timestamps should be be added.
+     * @return this object
+     */
+    // For temporary backwards compatibiility, if this method is not called,
+    // no 'Generated by javadoc' comment will be added.
+    public Head setTimestamp(boolean timestamp) {
+        showTimestamp = timestamp;
+        showGeneratedBy = true;
+        showMetaCreated = timestamp;
+        return this;
+    }
+
+    /**
+     * Sets whether or not timestamps should be recorded in the HEAD element.
+     * The timestamp will be recorded in a comment, and possibly in an appropriate META
+     * element, depending on the HTML version specified when this object was created.
+     *
+     * @param timestamp true if timestamps should be be added.
+     * @param metaCreated  true if a META element should be added containing the timestamp
+     * @return this object
+     */
+    // This method is for temporary compatibility. In time, all clients should use
+    // {@code setTimestamp(boolean)}.
+    public Head setTimestamp(boolean timestamp, boolean metaCreated) {
+        showTimestamp = timestamp;
+        showGeneratedBy = true;
+        showMetaCreated = metaCreated;
+        return this;
+    }
+
+    /**
+     * Sets the main and any additional stylesheets to be listed in the HEAD element.
+     *
+     * @param main the main stylesheet, or null to use the default
+     * @param additional a list of any additional stylesheets to be included
+     * @return  this object
+     */
+    public Head setStylesheets(DocFile main, List<DocFile> additional) {
+        this.mainStylesheetFile = main;
+        this.additionalStylesheetFiles = additional;
+        return this;
+    }
+
+    /**
+     * Sets whether or not to include the supporting scripts and stylesheets for the
+     * "search" feature.
+     * If the feature is enabled, a {@code Script} must be provided into which some
+     * JavaScript code will be injected, to be executed during page loading. The value
+     * will be ignored if the feature is not enabled.
+     *
+     * @param index true if the supporting files are to be included
+     * @param mainBodyScript the {@code Script} object, or null
+     * @return this object
+     */
+    public Head setIndex(boolean index, Script mainBodyScript) {
+        this.index = index;
+        this.mainBodyScript = mainBodyScript;
+        return this;
+    }
+
+    /**
+     * Adds a script to be included in the HEAD element.
+     *
+     * @param script the script
+     * @return this object
+     */
+    public Head addScript(Script script) {
+        scripts.add(script);
+        return this;
+    }
+
+    /**
+     * Specifies whether or not to add a reference to a default script to be included
+     * in the HEAD element.
+     * The default script will normally be included; this method may be used to prevent that.
+     *
+     * @param addDefaultScript whether or not a default script will be included
+     * @return this object
+     */
+    public Head addDefaultScript(boolean addDefaultScript) {
+        this.addDefaultScript = addDefaultScript;
+        return this;
+    }
+
+    /**
+     * Adds additional content to be included in the HEAD element.
+     *
+     * @param contents the content
+     * @return this object
+     */
+    public Head addContent(Content... contents) {
+        extraContent.addAll(Arrays.asList(contents));
+        return this;
+    }
+
+    /**
+     * Returns the HTML for the HEAD element.
+     *
+     * @return the HTML
+     */
+    public Content toContent() {
+        Date now = showTimestamp ? calendar.getTime() : null;
+
+        HtmlTree tree = new HtmlTree(HtmlTag.HEAD);
+        if (showGeneratedBy) {
+            tree.addContent(getGeneratedBy(showTimestamp, now));
+        }
+        tree.addContent(HtmlTree.TITLE(title));
+
+        if (charset != null) { // compatibility; should this be allowed?
+            tree.addContent(HtmlTree.META("Content-Type", "text/html", charset));
+        }
+
+        if (showMetaCreated) {
+            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
+            tree.addContent(HtmlTree.META(
+                    (htmlVersion == HtmlVersion.HTML5) ? "dc.created" : "date",
+                    dateFormat.format(now)));
+        }
+
+        for (String k : keywords) {
+            tree.addContent(HtmlTree.META("keywords", k));
+        }
+
+        for (Content c : extraContent) {
+            tree.addContent(c);
+        }
+
+        addStylesheets(tree);
+        addScripts(tree);
+
+        return tree;
+    }
+
+    private Comment getGeneratedBy(boolean timestamp, Date now) {
+        String text = "Generated by javadoc"; // marker string, deliberately not localized
+        if (timestamp) {
+            text += " ("+ docletVersion + ") on " + now;
+        }
+        return new Comment(text);
+    }
+
+    private void addStylesheets(HtmlTree tree) {
+        DocPath mainStylesheet;
+        if (mainStylesheetFile == null) {
+            mainStylesheet = DocPaths.STYLESHEET;
+        } else {
+            mainStylesheet = DocPath.create(mainStylesheetFile.getName());
+        }
+        addStylesheet(tree, mainStylesheet);
+
+        for (DocFile file : additionalStylesheetFiles) {
+            addStylesheet(tree, DocPath.create(file.getName()));
+        }
+
+        if (index) {
+            addStylesheet(tree, DocPaths.JQUERY_FILES.resolve(DocPaths.JQUERY_STYLESHEET_FILE));
+        }
+    }
+
+    private void addStylesheet(HtmlTree tree, DocPath stylesheet) {
+        tree.addContent(HtmlTree.LINK("stylesheet", "text/css",
+                pathToRoot.resolve(stylesheet).getPath(), "Style"));
+    }
+
+    private void addScripts(HtmlTree tree) {
+        if (addDefaultScript) {
+            tree.addContent(HtmlTree.SCRIPT(pathToRoot.resolve(DocPaths.JAVASCRIPT).getPath()));
+        }
+        if (index) {
+            if (pathToRoot != null && mainBodyScript != null) {
+                String ptrPath = pathToRoot.isEmpty() ? "." : pathToRoot.getPath();
+                mainBodyScript.append("var pathtoroot = ")
+                        .appendStringLiteral(ptrPath + "/")
+                        .append(";loadScripts(document, \'script\');");
+            }
+            addJQueryFile(tree, DocPaths.JSZIP_MIN);
+            addJQueryFile(tree, DocPaths.JSZIPUTILS_MIN);
+            tree.addContent(new RawHtml("<!--[if IE]>"));
+            addJQueryFile(tree, DocPaths.JSZIPUTILS_IE_MIN);
+            tree.addContent(new RawHtml("<![endif]-->"));
+            addJQueryFile(tree, DocPaths.JQUERY_JS_1_10);
+            addJQueryFile(tree, DocPaths.JQUERY_JS);
+        }
+        for (Script script : scripts) {
+            tree.addContent(script.asContent());
+        }
+    }
+
+    private void addJQueryFile(HtmlTree tree, DocPath filePath) {
+        DocPath jqueryFile = pathToRoot.resolve(DocPaths.JQUERY_FILES.resolve(filePath));
+        tree.addContent(HtmlTree.SCRIPT(jqueryFile.getPath()));
+    }
+}
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlDocWriter.java	Fri Nov 24 17:19:47 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,354 +0,0 @@
-/*
- * Copyright (c) 1997, 2017, 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.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.
- */
-
-package jdk.javadoc.internal.doclets.formats.html.markup;
-
-import java.util.*;
-
-import javax.lang.model.element.ModuleElement;
-import javax.lang.model.element.PackageElement;
-import javax.lang.model.element.TypeElement;
-
-import jdk.javadoc.internal.doclets.formats.html.HtmlConfiguration;
-import jdk.javadoc.internal.doclets.formats.html.SectionName;
-import jdk.javadoc.internal.doclets.toolkit.Content;
-import jdk.javadoc.internal.doclets.toolkit.Messages;
-import jdk.javadoc.internal.doclets.toolkit.util.DocFile;
-import jdk.javadoc.internal.doclets.toolkit.util.DocLink;
-import jdk.javadoc.internal.doclets.toolkit.util.DocPath;
-import jdk.javadoc.internal.doclets.toolkit.util.DocPaths;
-
-
-/**
- * Class for the Html Format Code Generation specific to JavaDoc.
- * This Class contains methods related to the Html Code Generation which
- * are used by the Sub-Classes in the package jdk.javadoc.internal.tool.standard.
- *
- *  <p><b>This is NOT part of any supported API.
- *  If you write code that depends on this, you do so at your own risk.
- *  This code and its internal interfaces are subject to change or
- *  deletion without notice.</b>
- *
- * @author Atul M Dambalkar
- * @author Robert Field
- */
-public abstract class HtmlDocWriter extends HtmlWriter {
-
-    public static final String CONTENT_TYPE = "text/html";
-
-    private final HtmlConfiguration configuration;
-    private final DocPath pathToRoot;
-
-    /**
-     * Constructor. Initializes the destination file name through the super
-     * class HtmlWriter.
-     *
-     * @param configuration the configuration for this doclet
-     * @param filename String file name.
-     */
-    public HtmlDocWriter(HtmlConfiguration configuration, DocPath filename) {
-        super(configuration, filename);
-        this.configuration = configuration;
-        this.pathToRoot = filename.parent().invert();
-        Messages messages = configuration.getMessages();
-        messages.notice("doclet.Generating_0",
-            DocFile.createFileForOutput(configuration, filename).getPath());
-    }
-
-    public Content getHyperLink(DocPath link, String label) {
-        return getHyperLink(link, new StringContent(label), false, "", "", "");
-    }
-
-    /**
-     * Get Html Hyper Link Content.
-     *
-     * @param where      Position of the link in the file. Character '#' is not
-     *                   needed.
-     * @param label      Tag for the link.
-     * @return a content tree for the hyper link
-     */
-    public Content getHyperLink(String where,
-                               Content label) {
-        return getHyperLink(getDocLink(where), label, "", "");
-    }
-
-    /**
-     * Get Html Hyper Link Content.
-     *
-     * @param sectionName      The section name to which the link will be created.
-     * @param label            Tag for the link.
-     * @return a content tree for the hyper link
-     */
-    public Content getHyperLink(SectionName sectionName,
-                               Content label) {
-        return getHyperLink(getDocLink(sectionName), label, "", "");
-    }
-
-    /**
-     * Get Html Hyper Link Content.
-     *
-     * @param sectionName      The section name combined with where to which the link
-     *                         will be created.
-     * @param where            The fragment combined with sectionName to which the link
-     *                         will be created.
-     * @param label            Tag for the link.
-     * @return a content tree for the hyper link
-     */
-    public Content getHyperLink(SectionName sectionName, String where,
-                               Content label) {
-        return getHyperLink(getDocLink(sectionName, where), label, "", "");
-    }
-
-    /**
-     * Get the link.
-     *
-     * @param where      Position of the link in the file.
-     * @return a DocLink object for the hyper link
-     */
-    public DocLink getDocLink(String where) {
-        return DocLink.fragment(getName(where));
-    }
-
-    /**
-     * Get the link.
-     *
-     * @param sectionName      The section name to which the link will be created.
-     * @return a DocLink object for the hyper link
-     */
-    public DocLink getDocLink(SectionName sectionName) {
-        return DocLink.fragment(sectionName.getName());
-    }
-
-    /**
-     * Get the link.
-     *
-     * @param sectionName      The section name combined with where to which the link
-     *                         will be created.
-     * @param where            The fragment combined with sectionName to which the link
-     *                         will be created.
-     * @return a DocLink object for the hyper link
-     */
-    public DocLink getDocLink(SectionName sectionName, String where) {
-        return DocLink.fragment(sectionName.getName() + getName(where));
-    }
-
-    /**
-     * Convert the name to a valid HTML name.
-     *
-     * @param name the name that needs to be converted to valid HTML name.
-     * @return a valid HTML name string.
-     */
-    public String getName(String name) {
-        /* The HTML 4 spec at http://www.w3.org/TR/html4/types.html#h-6.2 mentions
-         * that the name/id should begin with a letter followed by other valid characters.
-         * The HTML 5 spec (draft) is more permissive on names/ids where the only restriction
-         * is that it should be at least one character long and should not contain spaces.
-         * The spec draft is @ http://www.w3.org/html/wg/drafts/html/master/dom.html#the-id-attribute.
-         *
-         * For HTML 4, we need to check for non-characters at the beginning of the name and
-         * substitute it accordingly, "_" and "$" can appear at the beginning of a member name.
-         * The method substitutes "$" with "Z:Z:D" and will prefix "_" with "Z:Z".
-         */
-
-        if (configuration.isOutputHtml5()) {
-            return name.replaceAll(" +", "");
-        }
-
-        StringBuilder sb = new StringBuilder();
-        for (int i = 0; i < name.length(); i++) {
-            char ch = name.charAt(i);
-            switch (ch) {
-                case '(':
-                case ')':
-                case '<':
-                case '>':
-                case ',':
-                    sb.append('-');
-                    break;
-                case ' ':
-                case '[':
-                    break;
-                case ']':
-                    sb.append(":A");
-                    break;
-                // Any appearance of $ needs to be substituted with ":D" and not with hyphen
-                // since a field name "P$$ and a method P(), both valid member names, can end
-                // up as "P--". A member name beginning with $ needs to be substituted with
-                // "Z:Z:D".
-                case '$':
-                    if (i == 0)
-                        sb.append("Z:Z");
-                    sb.append(":D");
-                    break;
-                // A member name beginning with _ needs to be prefixed with "Z:Z" since valid anchor
-                // names can only begin with a letter.
-                case '_':
-                    if (i == 0)
-                        sb.append("Z:Z");
-                    sb.append(ch);
-                    break;
-                default:
-                    sb.append(ch);
-            }
-        }
-        return sb.toString();
-    }
-
-    /**
-     * Get Html hyperlink.
-     *
-     * @param link       path of the file.
-     * @param label      Tag for the link.
-     * @return a content tree for the hyper link
-     */
-    public Content getHyperLink(DocPath link, Content label) {
-        return getHyperLink(link, label, "", "");
-    }
-
-    public Content getHyperLink(DocLink link, Content label) {
-        return getHyperLink(link, label, "", "");
-    }
-
-    public Content getHyperLink(DocPath link,
-                               Content label, boolean strong,
-                               String stylename, String title, String target) {
-        return getHyperLink(new DocLink(link), label, strong,
-                stylename, title, target);
-    }
-
-    public Content getHyperLink(DocLink link,
-                               Content label, boolean strong,
-                               String stylename, String title, String target) {
-        Content body = label;
-        if (strong) {
-            body = HtmlTree.SPAN(HtmlStyle.typeNameLink, body);
-        }
-        if (stylename != null && stylename.length() != 0) {
-            HtmlTree t = new HtmlTree(HtmlTag.FONT, body);
-            t.addAttr(HtmlAttr.CLASS, stylename);
-            body = t;
-        }
-        HtmlTree l = HtmlTree.A(link.toString(), body);
-        if (title != null && title.length() != 0) {
-            l.addAttr(HtmlAttr.TITLE, title);
-        }
-        if (target != null && target.length() != 0) {
-            l.addAttr(HtmlAttr.TARGET, target);
-        }
-        return l;
-    }
-
-    /**
-     * Get Html Hyper Link.
-     *
-     * @param link       String name of the file.
-     * @param label      Tag for the link.
-     * @param title      String that describes the link's content for accessibility.
-     * @param target     Target frame.
-     * @return a content tree for the hyper link.
-     */
-    public Content getHyperLink(DocPath link, Content label, String title, String target) {
-        return getHyperLink(new DocLink(link), label, title, target);
-    }
-
-    public Content getHyperLink(DocLink link, Content label, String title, String target) {
-        HtmlTree anchor = HtmlTree.A(link.toString(), label);
-        if (title != null && title.length() != 0) {
-            anchor.addAttr(HtmlAttr.TITLE, title);
-        }
-        if (target != null && target.length() != 0) {
-            anchor.addAttr(HtmlAttr.TARGET, target);
-        }
-        return anchor;
-    }
-
-    public Content getModuleFramesHyperLink(ModuleElement mdle, Content label, String target) {
-        DocLink mdlLink = new DocLink(DocPaths.moduleFrame(mdle));
-        DocLink mtFrameLink = new DocLink(DocPaths.moduleTypeFrame(mdle));
-        DocLink cFrameLink = new DocLink(DocPaths.moduleSummary(mdle));
-        HtmlTree anchor = HtmlTree.A(mdlLink.toString(), label);
-        String onclickStr = "updateModuleFrame('" + mtFrameLink + "','" + cFrameLink + "');";
-        anchor.addAttr(HtmlAttr.TARGET, target);
-        anchor.addAttr(HtmlAttr.ONCLICK, onclickStr);
-        return anchor;
-    }
-
-    /**
-     * Get the enclosed name of the package
-     *
-     * @param te  TypeElement
-     * @return the name
-     */
-    public String getEnclosingPackageName(TypeElement te) {
-
-        PackageElement encl = configuration.utils.containingPackage(te);
-        return (encl.isUnnamed()) ? "" : (encl.getQualifiedName() + ".");
-    }
-
-    /**
-     * Returns a link to the stylesheet file.
-     *
-     * @param configuration the configuration for this doclet
-     * @param head HtmlTree to which the stylesheet links will be added
-     */
-    public void addStyleSheetProperties(HtmlConfiguration configuration, Content head) {
-        String stylesheetfile = configuration.stylesheetfile;
-        DocPath stylesheet;
-        if (stylesheetfile.isEmpty()) {
-            stylesheet = DocPaths.STYLESHEET;
-        } else {
-            DocFile file = DocFile.createFileForInput(configuration, stylesheetfile);
-            stylesheet = DocPath.create(file.getName());
-        }
-        HtmlTree link = HtmlTree.LINK("stylesheet", "text/css",
-                pathToRoot.resolve(stylesheet).getPath(),
-                "Style");
-        head.addContent(link);
-        addStylesheets(configuration, head);
-    }
-
-    protected void addStylesheets(HtmlConfiguration configuration, Content tree) {
-        List<String> stylesheets = configuration.additionalStylesheets;
-        if (!stylesheets.isEmpty()) {
-            stylesheets.forEach((ssheet) -> {
-                DocFile file = DocFile.createFileForInput(configuration, ssheet);
-                DocPath ssheetPath = DocPath.create(file.getName());
-                HtmlTree slink = HtmlTree.LINK("stylesheet", "text/css", pathToRoot.resolve(ssheetPath).getPath(),
-                        "Style");
-                tree.addContent(slink);
-            });
-        }
-    }
-
-    protected Comment getGeneratedBy(boolean timestamp) {
-        String text = "Generated by javadoc"; // marker string, deliberately not localized
-        if (timestamp) {
-            Calendar calendar = new GregorianCalendar(TimeZone.getDefault());
-            Date today = calendar.getTime();
-            text += " ("+ configuration.getDocletSpecificBuildDate() + ") on " + today;
-        }
-        return new Comment(text);
-    }
-}
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlDocument.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlDocument.java	Mon Nov 27 17:04:45 2017 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2017, 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
@@ -26,10 +26,14 @@
 package jdk.javadoc.internal.doclets.formats.html.markup;
 
 import java.io.IOException;
+import java.io.StringWriter;
 import java.io.Writer;
 import java.util.*;
 
 import jdk.javadoc.internal.doclets.toolkit.Content;
+import jdk.javadoc.internal.doclets.toolkit.util.DocFile;
+import jdk.javadoc.internal.doclets.toolkit.util.DocFileIOException;
+import jdk.javadoc.internal.doclets.toolkit.util.DocletConstants;
 
 /**
  * Class for generating an HTML document for javadoc output.
@@ -41,9 +45,9 @@
  *
  * @author Bhavesh Patel
  */
-public class HtmlDocument extends Content {
-
-    private List<Content> docContent = Collections.emptyList();
+public class HtmlDocument {
+    private final DocType docType;
+    private final List<Content> docContent;
 
     /**
      * Constructor to construct an HTML document.
@@ -52,11 +56,9 @@
      * @param docComment comment for the document
      * @param htmlTree HTML tree of the document
      */
-    public HtmlDocument(Content docType, Content docComment, Content htmlTree) {
-        docContent = new ArrayList<>();
-        addContent(nullCheck(docType));
-        addContent(nullCheck(docComment));
-        addContent(nullCheck(htmlTree));
+    public HtmlDocument(DocType docType, Content docComment, Content htmlTree) {
+        this.docType = docType;
+        docContent = Arrays.asList(docComment, htmlTree);
     }
 
     /**
@@ -65,46 +67,41 @@
      * @param docType document type for the HTML document
      * @param htmlTree HTML tree of the document
      */
-    public HtmlDocument(Content docType, Content htmlTree) {
-        docContent = new ArrayList<>();
-        addContent(nullCheck(docType));
-        addContent(nullCheck(htmlTree));
-    }
-
-    /**
-     * Adds content for the HTML document.
-     *
-     * @param htmlContent html content to be added
-     */
-    public final void addContent(Content htmlContent) {
-        if (htmlContent.isValid())
-            docContent.add(htmlContent);
+    public HtmlDocument(DocType docType, Content htmlTree) {
+        this.docType = docType;
+        docContent = Collections.singletonList(htmlTree);
     }
 
     /**
-     * This method is not supported by the class.
+     * Writes the content of this document to the specified file.
      *
-     * @param stringContent string content that needs to be added
-     * @throws UnsupportedOperationException always
+     * @param docFile the file
+     * @throws DocFileIOException if an {@code IOException} occurs while writing the file
      */
-    @Override
-    public void addContent(CharSequence stringContent) {
-        throw new UnsupportedOperationException();
+    public void write(DocFile docFile) throws DocFileIOException {
+        try (Writer writer = docFile.openWriter()) {
+            write(writer);
+        } catch (IOException e) {
+            throw new DocFileIOException(docFile, DocFileIOException.Mode.WRITE, e);
+        }
     }
 
-    /**
-     * {@inheritDoc}
-     */
-    public boolean isEmpty() {
-        return (docContent.isEmpty());
+    @Override
+    public String toString() {
+        try (Writer writer = new StringWriter()) {
+            write(writer);
+            return writer.toString();
+        } catch (IOException e) {
+            throw new Error(e);
+        }
     }
 
-    /**
-     * {@inheritDoc}
-     */
-    public boolean write(Writer out,  boolean atNewline) throws IOException {
-        for (Content c : docContent)
-            atNewline = c.write(out, atNewline);
-        return atNewline;
+    private void write(Writer writer) throws IOException {
+        writer.write(docType.text);
+        writer.write(DocletConstants.NL);
+        boolean atNewline = true;
+        for (Content c : docContent) {
+            atNewline = c.write(writer, atNewline);
+        }
     }
 }
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlTree.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlTree.java	Mon Nov 27 17:04:45 2017 +0000
@@ -52,7 +52,7 @@
  */
 public class HtmlTree extends Content {
 
-    private HtmlTag htmlTag;
+    public final HtmlTag htmlTag;
     private Map<HtmlAttr,String> attrs = Collections.emptyMap();
     private List<Content> content = Collections.emptyList();
     public static final Content EMPTY = new StringContent("");
@@ -74,8 +74,20 @@
      */
     public HtmlTree(HtmlTag tag, Content... contents) {
         this(tag);
-        for (Content content: contents)
-            addContent(content);
+        for (Content c: contents)
+            addContent(c);
+    }
+
+    /**
+     * Constructor to construct HtmlTree object.
+     *
+     * @param tag HTML tag for the HtmlTree object
+     * @param contents contents to be added to the tree
+     */
+    public HtmlTree(HtmlTag tag, List<Content> contents) {
+        this(tag);
+        for (Content c: contents)
+            addContent(c);
     }
 
     /**
@@ -83,28 +95,47 @@
      *
      * @param attrName name of the attribute
      * @param attrValue value of the attribute
+     * @return this object
      */
-    public void addAttr(HtmlAttr attrName, String attrValue) {
+    public HtmlTree addAttr(HtmlAttr attrName, String attrValue) {
         if (attrs.isEmpty())
             attrs = new LinkedHashMap<>(3);
         attrs.put(nullCheck(attrName), escapeHtmlChars(attrValue));
+        return this;
     }
 
-    public void setTitle(Content body) {
+    /**
+     * Sets the "title" attribute for this tag.
+     * Any HTML tags in the content will be removed.
+     *
+     * @param body the content for the title attribute
+     * @return this object
+     */
+    public HtmlTree setTitle(Content body) {
         addAttr(HtmlAttr.TITLE, stripHtml(body));
-    }
-
-    public void setRole(Role role) {
-        addAttr(HtmlAttr.ROLE, role.toString());
+        return this;
     }
 
     /**
-     * Adds a style for the HTML tag.
+     * Sets the "role" attribute for this tag.
+     *
+     * @param role the role
+     * @return this object
+     */
+    public HtmlTree setRole(Role role) {
+        addAttr(HtmlAttr.ROLE, role.toString());
+        return this;
+    }
+
+    /**
+     * Sets the style for the HTML tag.
      *
      * @param style style to be added
+     * @return this object
      */
-    public void addStyle(HtmlStyle style) {
+    public HtmlTree setStyle(HtmlStyle style) {
         addAttr(HtmlAttr.CLASS, style.toString());
+        return this;
     }
 
     /**
@@ -112,10 +143,11 @@
      *
      * @param tagContent tag content to be added
      */
+    @Override
     public void addContent(Content tagContent) {
         if (tagContent instanceof ContentBuilder) {
-            for (Content content: ((ContentBuilder)tagContent).contents) {
-                addContent(content);
+            for (Content c: ((ContentBuilder)tagContent).contents) {
+                addContent(c);
             }
         }
         else if (tagContent == HtmlTree.EMPTY || tagContent.isValid()) {
@@ -126,9 +158,9 @@
     }
 
     /**
-     * This method adds a string content to the htmltree. If the last content member
+     * Adds String content to the HTML tree. If the last content member
      * added is a StringContent, append the string to that StringContent or else
-     * create a new StringContent and add it to the html tree.
+     * create a new StringContent and add it to the HTML tree.
      *
      * @param stringContent string content that needs to be added
      */
@@ -145,6 +177,10 @@
             addContent(new StringContent(stringContent));
     }
 
+    /**
+     * {@inheritDoc}
+     */
+    @Override
     public int charCount() {
         int n = 0;
         for (Content c : content)
@@ -153,7 +189,7 @@
     }
 
     /**
-     * Given a string, escape all special html characters and
+     * Given a string, escape all special HTML characters and
      * return the result.
      *
      * @param s The string to check.
@@ -302,7 +338,7 @@
     public static HtmlTree A_ID(HtmlStyle styleClass, String id, Content body) {
         HtmlTree htmltree = A_ID(id, body);
         if (styleClass != null)
-            htmltree.addStyle(styleClass);
+            htmltree.setStyle(styleClass);
         return htmltree;
     }
 
@@ -361,7 +397,7 @@
     public static HtmlTree DIV(HtmlStyle styleClass, Content body) {
         HtmlTree htmltree = new HtmlTree(HtmlTag.DIV, nullCheck(body));
         if (styleClass != null)
-            htmltree.addStyle(styleClass);
+            htmltree.setStyle(styleClass);
         return htmltree;
     }
 
@@ -424,7 +460,7 @@
         if (printTitle)
             htmltree.setTitle(body);
         if (styleClass != null)
-            htmltree.addStyle(styleClass);
+            htmltree.setStyle(styleClass);
         return htmltree;
     }
 
@@ -546,7 +582,7 @@
     public static HtmlTree LI(HtmlStyle styleClass, Content body) {
         HtmlTree htmltree = new HtmlTree(HtmlTag.LI, nullCheck(body));
         if (styleClass != null)
-            htmltree.addStyle(styleClass);
+            htmltree.setStyle(styleClass);
         return htmltree;
     }
 
@@ -601,7 +637,7 @@
     public static HtmlTree MAIN(HtmlStyle styleClass, Content body) {
         HtmlTree htmltree = HtmlTree.MAIN(body);
         if (styleClass != null) {
-            htmltree.addStyle(styleClass);
+            htmltree.setStyle(styleClass);
         }
         return htmltree;
     }
@@ -678,31 +714,20 @@
     public static HtmlTree P(HtmlStyle styleClass, Content body) {
         HtmlTree htmltree = new HtmlTree(HtmlTag.P, nullCheck(body));
         if (styleClass != null)
-            htmltree.addStyle(styleClass);
+            htmltree.setStyle(styleClass);
         return htmltree;
     }
 
     /**
      * Generates a SCRIPT tag with the type and src attributes.
      *
-     * @param type type of link
      * @param src the path for the script
      * @return an HtmlTree object for the SCRIPT tag
      */
     public static HtmlTree SCRIPT(String src) {
-        HtmlTree htmltree = HtmlTree.SCRIPT();
-        htmltree.addAttr(HtmlAttr.SRC, nullCheck(src));
-        return htmltree;
-    }
-
-    /**
-     * Generates a SCRIPT tag with the type attribute.
-     *
-     * @return an HtmlTree object for the SCRIPT tag
-     */
-    public static HtmlTree SCRIPT() {
         HtmlTree htmltree = new HtmlTree(HtmlTag.SCRIPT);
         htmltree.addAttr(HtmlAttr.TYPE, "text/javascript");
+        htmltree.addAttr(HtmlAttr.SRC, nullCheck(src));
         return htmltree;
     }
 
@@ -760,7 +785,7 @@
     public static HtmlTree SPAN(HtmlStyle styleClass, Content body) {
         HtmlTree htmltree = new HtmlTree(HtmlTag.SPAN, nullCheck(body));
         if (styleClass != null)
-            htmltree.addStyle(styleClass);
+            htmltree.setStyle(styleClass);
         return htmltree;
     }
 
@@ -777,7 +802,7 @@
         HtmlTree htmltree = new HtmlTree(HtmlTag.SPAN, nullCheck(body));
         htmltree.addAttr(HtmlAttr.ID, nullCheck(id));
         if (styleClass != null)
-            htmltree.addStyle(styleClass);
+            htmltree.setStyle(styleClass);
         return htmltree;
     }
 
@@ -792,7 +817,7 @@
     public static HtmlTree TABLE(HtmlStyle styleClass, String summary, Content body) {
         HtmlTree htmltree = new HtmlTree(HtmlTag.TABLE, nullCheck(body));
         if (styleClass != null)
-            htmltree.addStyle(styleClass);
+            htmltree.setStyle(styleClass);
         htmltree.addAttr(HtmlAttr.SUMMARY, nullCheck(summary));
         return htmltree;
     }
@@ -807,7 +832,7 @@
     public static HtmlTree TABLE(HtmlStyle styleClass, Content body) {
         HtmlTree htmltree = new HtmlTree(HtmlTag.TABLE, nullCheck(body));
         if (styleClass != null) {
-            htmltree.addStyle(styleClass);
+            htmltree.setStyle(styleClass);
         }
         return htmltree;
     }
@@ -822,7 +847,7 @@
     public static HtmlTree TD(HtmlStyle styleClass, Content body) {
         HtmlTree htmltree = new HtmlTree(HtmlTag.TD, nullCheck(body));
         if (styleClass != null)
-            htmltree.addStyle(styleClass);
+            htmltree.setStyle(styleClass);
         return htmltree;
     }
 
@@ -847,7 +872,7 @@
     public static HtmlTree TH(HtmlStyle styleClass, String scope, Content body) {
         HtmlTree htmltree = new HtmlTree(HtmlTag.TH, nullCheck(body));
         if (styleClass != null)
-            htmltree.addStyle(styleClass);
+            htmltree.setStyle(styleClass);
         htmltree.addAttr(HtmlAttr.SCOPE, nullCheck(scope));
         return htmltree;
     }
@@ -880,8 +905,8 @@
      * @param body content for the tag
      * @return an HtmlTree object for the TITLE tag
      */
-    public static HtmlTree TITLE(Content body) {
-        HtmlTree htmltree = new HtmlTree(HtmlTag.TITLE, nullCheck(body));
+    public static HtmlTree TITLE(String body) {
+        HtmlTree htmltree = new HtmlTree(HtmlTag.TITLE, new StringContent(body));
         return htmltree;
     }
 
@@ -910,13 +935,14 @@
         for (Content c : more) {
             htmlTree.addContent(nullCheck(c));
         }
-        htmlTree.addStyle(nullCheck(styleClass));
+        htmlTree.setStyle(nullCheck(styleClass));
         return htmlTree;
     }
 
     /**
      * {@inheritDoc}
      */
+    @Override
     public boolean isEmpty() {
         return (!hasContent() && !hasAttrs());
     }
@@ -956,6 +982,7 @@
      *
      * @return true if the HTML tree is valid
      */
+    @Override
     public boolean isValid() {
         switch (htmlTag) {
             case A :
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlWriter.java	Fri Nov 24 17:19:47 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,367 +0,0 @@
-/*
- * Copyright (c) 1997, 2017, 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.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.
- */
-
-package jdk.javadoc.internal.doclets.formats.html.markup;
-
-import java.io.*;
-import java.util.*;
-
-import jdk.javadoc.internal.doclets.formats.html.HtmlConfiguration;
-import jdk.javadoc.internal.doclets.toolkit.Content;
-import jdk.javadoc.internal.doclets.toolkit.Resources;
-import jdk.javadoc.internal.doclets.toolkit.util.DocFile;
-import jdk.javadoc.internal.doclets.toolkit.util.DocFileIOException;
-import jdk.javadoc.internal.doclets.toolkit.util.DocPath;
-import jdk.javadoc.internal.doclets.toolkit.util.DocletConstants;
-import jdk.javadoc.internal.doclets.toolkit.util.TableTabTypes;
-import jdk.javadoc.internal.doclets.toolkit.util.TableTabTypes.TableTabs;
-
-
-/**
- * Class for the Html format code generation.
- * Initializes PrintWriter with FileWriter, to enable print
- * related methods to generate the code to the named File through FileWriter.
- *
- *  <p><b>This is NOT part of any supported API.
- *  If you write code that depends on this, you do so at your own risk.
- *  This code and its internal interfaces are subject to change or
- *  deletion without notice.</b>
- *
- * @author Atul M Dambalkar
- * @author Bhavesh Patel (Modified)
- */
-public class HtmlWriter {
-
-    /**
-     * The window title of this file.
-     */
-    protected String winTitle;
-
-    /**
-     * The configuration.
-     */
-    protected HtmlConfiguration configuration;
-
-    private final DocFile docFile;
-
-    protected Content script;
-
-
-    /**
-     * Constructor.
-     *
-     * @param configuration the configuration
-     * @param path the directory path to be created for this file,
-     *             or null if none to be created
-     */
-    public HtmlWriter(HtmlConfiguration configuration, DocPath path) {
-        this.configuration = configuration;
-        docFile = DocFile.createFileForOutput(configuration, path);
-
-        // The following should be converted to shared Content objects
-        // and moved to Contents, but that will require additional
-        // changes at the use sites.
-        Resources resources = configuration.getResources();
-    }
-
-    public void write(Content c) throws DocFileIOException {
-        try (Writer writer = docFile.openWriter()) {
-            c.write(writer, true);
-        } catch (IOException e) {
-            throw new DocFileIOException(docFile, DocFileIOException.Mode.WRITE, e);
-        }
-    }
-
-    /**
-     * Returns an HtmlTree for the SCRIPT tag.
-     *
-     * @return an HtmlTree for the SCRIPT tag
-     */
-    protected HtmlTree getWinTitleScript(){
-        HtmlTree scriptTree = HtmlTree.SCRIPT();
-        if(winTitle != null && winTitle.length() > 0) {
-            String scriptCode = "<!--\n" +
-                    "    try {\n" +
-                    "        if (location.href.indexOf('is-external=true') == -1) {\n" +
-                    "            parent.document.title=\"" + escapeJavaScriptChars(winTitle) + "\";\n" +
-                    "        }\n" +
-                    "    }\n" +
-                    "    catch(err) {\n" +
-                    "    }\n" +
-                    "//-->\n";
-            RawHtml scriptContent = new RawHtml(scriptCode.replace("\n", DocletConstants.NL));
-            scriptTree.addContent(scriptContent);
-        }
-        return scriptTree;
-    }
-
-    /**
-     * Returns a String with escaped special JavaScript characters.
-     *
-     * @param s String that needs to be escaped
-     * @return a valid escaped JavaScript string
-     */
-    private static String escapeJavaScriptChars(String s) {
-        StringBuilder sb = new StringBuilder();
-        for (int i = 0; i < s.length(); i++) {
-            char ch = s.charAt(i);
-            switch (ch) {
-                case '\b':
-                    sb.append("\\b");
-                    break;
-                case '\t':
-                    sb.append("\\t");
-                    break;
-                case '\n':
-                    sb.append("\\n");
-                    break;
-                case '\f':
-                    sb.append("\\f");
-                    break;
-                case '\r':
-                    sb.append("\\r");
-                    break;
-                case '"':
-                    sb.append("\\\"");
-                    break;
-                case '\'':
-                    sb.append("\\\'");
-                    break;
-                case '\\':
-                    sb.append("\\\\");
-                    break;
-                default:
-                    if (ch < 32 || ch >= 127) {
-                        sb.append(String.format("\\u%04X", (int)ch));
-                    } else {
-                        sb.append(ch);
-                    }
-                    break;
-            }
-        }
-        return sb.toString();
-    }
-
-    /**
-     * Returns a content tree for the SCRIPT tag for the main page(index.html).
-     *
-     * @return a content for the SCRIPT tag
-     */
-    protected Content getFramesJavaScript() {
-        HtmlTree scriptTree = HtmlTree.SCRIPT();
-        String scriptCode = "\n" +
-                "    tmpTargetPage = \"\" + window.location.search;\n" +
-                "    if (tmpTargetPage != \"\" && tmpTargetPage != \"undefined\")\n" +
-                "        tmpTargetPage = tmpTargetPage.substring(1);\n" +
-                "    if (tmpTargetPage.indexOf(\":\") != -1 || (tmpTargetPage != \"\" && !validURL(tmpTargetPage)))\n" +
-                "        tmpTargetPage = \"undefined\";\n" +
-                "    targetPage = tmpTargetPage;\n" +
-                "    function validURL(url) {\n" +
-                "        try {\n" +
-                "            url = decodeURIComponent(url);\n" +
-                "        }\n" +
-                "        catch (error) {\n" +
-                "            return false;\n" +
-                "        }\n" +
-                "        var pos = url.indexOf(\".html\");\n" +
-                "        if (pos == -1 || pos != url.length - 5)\n" +
-                "            return false;\n" +
-                "        var allowNumber = false;\n" +
-                "        var allowSep = false;\n" +
-                "        var seenDot = false;\n" +
-                "        for (var i = 0; i < url.length - 5; i++) {\n" +
-                "            var ch = url.charAt(i);\n" +
-                "            if ('a' <= ch && ch <= 'z' ||\n" +
-                "                    'A' <= ch && ch <= 'Z' ||\n" +
-                "                    ch == '$' ||\n" +
-                "                    ch == '_' ||\n" +
-                "                    ch.charCodeAt(0) > 127) {\n" +
-                "                allowNumber = true;\n" +
-                "                allowSep = true;\n" +
-                "            } else if ('0' <= ch && ch <= '9'\n" +
-                "                    || ch == '-') {\n" +
-                "                if (!allowNumber)\n" +
-                "                     return false;\n" +
-                "            } else if (ch == '/' || ch == '.') {\n" +
-                "                if (!allowSep)\n" +
-                "                    return false;\n" +
-                "                allowNumber = false;\n" +
-                "                allowSep = false;\n" +
-                "                if (ch == '.')\n" +
-                "                     seenDot = true;\n" +
-                "                if (ch == '/' && seenDot)\n" +
-                "                     return false;\n" +
-                "            } else {\n" +
-                "                return false;\n" +
-                "            }\n" +
-                "        }\n" +
-                "        return true;\n" +
-                "    }\n" +
-                "    function loadFrames() {\n" +
-                "        if (targetPage != \"\" && targetPage != \"undefined\")\n" +
-                "             top.classFrame.location = top.targetPage;\n" +
-                "    }\n";
-        RawHtml scriptContent = new RawHtml(scriptCode.replace("\n", DocletConstants.NL));
-        scriptTree.addContent(scriptContent);
-        return scriptTree;
-    }
-
-    /**
-     * Returns an HtmlTree for the BODY tag.
-     *
-     * @param includeScript  set true if printing windowtitle script
-     * @param title title for the window
-     * @return an HtmlTree for the BODY tag
-     */
-    public HtmlTree getBody(boolean includeScript, String title) {
-        HtmlTree body = new HtmlTree(HtmlTag.BODY);
-        // Set window title string which is later printed
-        this.winTitle = title;
-        // Don't print windowtitle script for overview-frame, allclasses-frame
-        // and package-frame
-        if (includeScript) {
-            this.script = getWinTitleScript();
-            body.addContent(script);
-            Content noScript = HtmlTree.NOSCRIPT(
-                    HtmlTree.DIV(configuration.getContent("doclet.No_Script_Message")));
-            body.addContent(noScript);
-        }
-        return body;
-    }
-
-    /**
-     * Generated javascript variables for the document.
-     *
-     * @param typeMap map comprising of method and type relationship
-     * @param tabTypes set comprising of all table tab types for this class
-     * @param elementName packages or methods table for which tabs need to be displayed
-     */
-    public void generateTableTabTypesScript(Map<String,Integer> typeMap,
-            Set<? extends TableTabTypes> tabTypes, String elementName) {
-        String sep = "";
-        StringBuilder vars = new StringBuilder("var ");
-        vars.append(elementName)
-                .append(" = {");
-        for (Map.Entry<String,Integer> entry : typeMap.entrySet()) {
-            vars.append(sep);
-            sep = ",";
-            vars.append("\"")
-                    .append(entry.getKey())
-                    .append("\":")
-                    .append(entry.getValue());
-        }
-        vars.append("};").append(DocletConstants.NL);
-        sep = "";
-        vars.append("var tabs = {");
-        for (TableTabTypes entry : tabTypes) {
-            vars.append(sep);
-            sep = ",";
-            vars.append(entry.tableTabs().value())
-                    .append(":")
-                    .append("[")
-                    .append("\"")
-                    .append(entry.tableTabs().tabId())
-                    .append("\"")
-                    .append(sep)
-                    .append("\"")
-                    .append(configuration.getText(entry.tableTabs().resourceKey()))
-                    .append("\"]");
-        }
-        vars.append("};")
-                .append(DocletConstants.NL);
-        addStyles(HtmlStyle.altColor, vars);
-        addStyles(HtmlStyle.rowColor, vars);
-        addStyles(HtmlStyle.tableTab, vars);
-        addStyles(HtmlStyle.activeTableTab, vars);
-        script.addContent(new RawHtml(vars));
-    }
-
-    /**
-     * Generated javascript variables for the document.
-     *
-     * @param groupTypeMap map comprising of group relationship
-     * @param groupTypes map comprising of all table tab types
-     */
-    public void generateGroupTypesScript(Map<String,Integer> groupTypeMap,
-            Map<String,TableTabs> groupTypes) {
-        String sep = "";
-        StringBuilder vars = new StringBuilder("var groups");
-        vars.append(" = {");
-        for (Map.Entry<String,Integer> entry : groupTypeMap.entrySet()) {
-            vars.append(sep);
-            sep = ",";
-            vars.append("\"")
-                    .append(entry.getKey())
-                    .append("\":")
-                    .append(entry.getValue());
-        }
-        vars.append("};").append(DocletConstants.NL);
-        sep = "";
-        vars.append("var tabs = {");
-        for (String group : groupTypes.keySet()) {
-            TableTabs tab = groupTypes.get(group);
-            vars.append(sep);
-            sep = ",";
-            vars.append(tab.value())
-                    .append(":")
-                    .append("[")
-                    .append("\"")
-                    .append(tab.tabId())
-                    .append("\"")
-                    .append(sep)
-                    .append("\"")
-                    .append(new StringContent(tab.resourceKey()))
-                    .append("\"]");
-        }
-        vars.append("};")
-                .append(DocletConstants.NL);
-        addStyles(HtmlStyle.altColor, vars);
-        addStyles(HtmlStyle.rowColor, vars);
-        addStyles(HtmlStyle.tableTab, vars);
-        addStyles(HtmlStyle.activeTableTab, vars);
-        script.addContent(new RawHtml(vars));
-    }
-
-    /**
-     * Adds javascript style variables to the document.
-     *
-     * @param style style to be added as a javascript variable
-     * @param vars variable string to which the style variable will be added
-     */
-    public void addStyles(HtmlStyle style, StringBuilder vars) {
-        vars.append("var ").append(style).append(" = \"").append(style)
-                .append("\";").append(DocletConstants.NL);
-    }
-
-    /**
-     * Returns an HtmlTree for the TITLE tag.
-     *
-     * @return an HtmlTree for the TITLE tag
-     */
-    public HtmlTree getTitle() {
-        HtmlTree title = HtmlTree.TITLE(new StringContent(winTitle));
-        return title;
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/Links.java	Mon Nov 27 17:04:45 2017 +0000
@@ -0,0 +1,340 @@
+/*
+ * Copyright (c) 1997, 2017, 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+
+package jdk.javadoc.internal.doclets.formats.html.markup;
+
+import jdk.javadoc.internal.doclets.formats.html.SectionName;
+import jdk.javadoc.internal.doclets.toolkit.Content;
+import jdk.javadoc.internal.doclets.toolkit.util.DocLink;
+import jdk.javadoc.internal.doclets.toolkit.util.DocPath;
+
+/**
+ * Factory for HTML A elements, both links (with a {@code href} attribute)
+ * and anchors (with an {@code id} or {@code name} attribute).
+ *
+ * Most methods in this class are static factory methods.
+ * The exceptions are those methods that directly or indirectly depend on the HTML version
+ * being used, when determining valid HTML names (ids),
+ * and those methods that generate anchors.
+ *
+ *  <p><b>This is NOT part of any supported API.
+ *  If you write code that depends on this, you do so at your own risk.
+ *  This code and its internal interfaces are subject to change or
+ *  deletion without notice.</b>
+ */
+public class Links {
+
+    private final HtmlVersion version;
+
+    /**
+     * Creates a {@code Links} object for a specific HTML version.
+     * The version is used by the {@link #getName(String) getName} method
+     * to help determine valid HTML names (ids), and to determine whether
+     * to use an {@code id} or {@code name} attribute when creating anchors.
+     *
+     * @param version the HTML version
+     */
+    public Links(HtmlVersion version) {
+        this.version = version;
+    }
+
+    /**
+     * Creates an anchor of the form {@code <a id="name"><!-- --></a>}.
+     * In HTML4, a {@code name} attribute will be generated instead of an {@code id} attribute.
+     *
+     * @param name the value for the {@code id} or {@code name} attribute
+     * @return a content tree for the anchor
+     */
+    public Content createAnchor(String name) {
+        return createAnchor(getName(name), null);
+    }
+
+    /**
+     * Creates an anchor of the form {@code <a id="sectionName"><!-- --></a>}.
+     * In HTML4, a {@code name} attribute will be generated instead of an {@code id} attribute.
+     *
+     * @param sectionName the value for the {@code id} or {@code name} attribute
+     * @return a content tree for the anchor
+     */
+    public Content createAnchor(SectionName sectionName) {
+        return createAnchor(sectionName.getName(), null);
+    }
+
+    /**
+     * Creates an anchor of the form {@code <a id="sectionNameName"><!-- --></a>}.
+     * In HTML4, a {@code name} attribute will be generated instead of an {@code id} attribute.
+     *
+     * @param sectionName the first part of the value for the {@code id} or {@code name} attribute
+     * @param name the second part of the value for the {@code id} or {@code name} attribute
+     * @return a content tree for the anchor
+     */
+    public Content createAnchor(SectionName sectionName, String name) {
+        return createAnchor(sectionName.getName() + getName(name), null);
+    }
+
+    /**
+     * Creates an anchor of the form {@code <a id="anchorName">content</a>}.
+     * In HTML4, a {@code name} attribute will be generated instead of an {@code id} attribute.
+     *
+     * @param name the value for the {@code id} or {@code name} attribute
+     * @param content the content that should be added to the anchor,
+     *              or null, to use an empty comment
+     * @return a content tree for the marker anchor
+     */
+    public Content createAnchor(String name, Content content) {
+        return HtmlTree.A(version, name, (content == null ? EMPTY_COMMENT : content));
+    }
+
+    private static final Content EMPTY_COMMENT = new Comment(" ");
+
+    /**
+     * Creates a link of the form {@code <a href="#where">label</a>}.
+     *
+     * @param where      the position of the link in the file
+     * @param label      the content for the link
+     * @return a content tree for the link
+     */
+    public Content createLink(String where, Content label) {
+        DocLink l = DocLink.fragment(getName(where));
+        return Links.createLink(l, label, "", "");
+    }
+
+    /**
+     * Creates a link of the form {@code <a href="#sectionName">label</a>}.
+     *
+     * @param sectionName   the section name to which the link will be created
+     * @param label         the content for the link
+     * @return a content tree for the link
+     */
+    public static Content createLink(SectionName sectionName, Content label) {
+        DocLink l =  DocLink.fragment(sectionName.getName());
+        return Links.createLink(l, label, "", "");
+    }
+
+    /**
+     * Creates a link of the form {@code <a href="#sectionNameWhere">label</a>}.
+     *
+     * @param sectionName   the section name combined with where to which the link
+     *                      will be created
+     * @param where         the fragment combined with sectionName to which the link
+     *                      will be created
+     * @param label         the content for the link
+     * @return a content tree for the link
+     */
+    public Content createLink(SectionName sectionName, String where, Content label) {
+        DocLink l =  DocLink.fragment(sectionName.getName() + getName(where));
+        return Links.createLink(l, label, "", "");
+    }
+
+    /**
+     * Creates a link of the form {@code <a href="#stylename" title="title" target="target">label</a>}.
+     *
+     * @param sectionName   the section name to which the link will be created
+     * @param label     the content for the link
+     * @param title     the title for the link
+     * @param target    the target for the link, or null
+     * @return a content tree for the link
+     */
+    public static Content createLink(SectionName sectionName, Content label, String title, String target) {
+        DocLink l = DocLink.fragment(sectionName.getName());
+        return createLink(l, label, title, target);
+    }
+
+    /**
+     * Creates a link of the form {@code <a href="path">label</a>}.
+     *
+     * @param path   the path for the link
+     * @param label  the content for the link
+     * @return a content tree for the link
+     */
+    public static Content createLink(DocPath path, String label) {
+        return Links.createLink(path, new StringContent(label), false, "", "");
+    }
+
+    /**
+     * Creates a link of the form {@code <a href="path">label</a>}.
+     *
+     * @param path   the path for the link
+     * @param label  the content for the link
+     * @return a content tree for the link
+     */
+    public static Content createLink(DocPath path, Content label) {
+        return Links.createLink(path, label, "", "");
+    }
+
+    /**
+     * Creates a link of the form {@code <a href="path" title="title" target="target">label</a>}.
+     * If {@code strong} is set, the label will be wrapped in
+     *      {@code <span style="typeNameLink">...</span>}.
+     *
+     * @param path      the path for the link
+     * @param label     the content for the link
+     * @param strong    whether to wrap the {@code label} in a SPAN element
+     * @param title     the title for the link
+     * @param target    the target for the link, or null
+     * @return a content tree for the link
+     */
+    public static Content createLink(DocPath path, Content label, boolean strong,
+            String title, String target) {
+        return createLink(new DocLink(path), label, strong, title, target);
+    }
+
+    /**
+     * Creates a link of the form {@code <a href="path" title="title" target="target">label</a>}.
+     *
+     * @param path      the path for the link
+     * @param label     the content for the link
+     * @param title     the title for the link
+     * @param target    the target for the link, or null
+     * @return a content tree for the link
+     */
+    public static Content createLink(DocPath path, Content label, String title, String target) {
+        return Links.createLink(new DocLink(path), label, title, target);
+    }
+
+    /**
+     * Creates a link of the form {@code <a href="link">label</a>}.
+     *
+     * @param link      the details for the link
+     * @param label     the content for the link
+     * @return a content tree for the link
+     */
+    public static Content createLink(DocLink link, Content label) {
+        return Links.createLink(link, label, "", "");
+    }
+
+    /**
+     * Creates a link of the form {@code <a href="path" title="title" target="target">label</a>}.
+     *
+     * @param link      the details for the link
+     * @param label     the content for the link
+     * @param title     the title for the link
+     * @param target    the target for the link, or null
+     * @return a content tree for the link
+     */
+    public static Content createLink(DocLink link, Content label, String title, String target) {
+        HtmlTree anchor = HtmlTree.A(link.toString(), label);
+        if (title != null && title.length() != 0) {
+            anchor.addAttr(HtmlAttr.TITLE, title);
+        }
+        if (target != null && target.length() != 0) {
+            anchor.addAttr(HtmlAttr.TARGET, target);
+        }
+        return anchor;
+    }
+
+    /**
+     * Creates a link of the form {@code <a href="link" title="title" target="target">label</a>}.
+     * If {@code strong} is set, the label will be wrapped in
+     *      {@code <span style="typeNameLink">...</span>}.
+     *
+     * @param link      the details for the link
+     * @param label     the content for the link
+     * @param strong    whether to wrap the {@code label} in a SPAN element
+     * @param title     the title for the link
+     * @param target    the target for the link, or null
+     * @return a content tree for the link
+     */
+    public static Content createLink(DocLink link, Content label, boolean strong,
+            String title, String target) {
+        Content body = label;
+        if (strong) {
+            body = HtmlTree.SPAN(HtmlStyle.typeNameLink, body);
+        }
+        HtmlTree l = HtmlTree.A(link.toString(), body);
+        if (title != null && title.length() != 0) {
+            l.addAttr(HtmlAttr.TITLE, title);
+        }
+        if (target != null && target.length() != 0) {
+            l.addAttr(HtmlAttr.TARGET, target);
+        }
+        return l;
+    }
+
+
+    /**
+     * Converts a name to a valid HTML name (id).
+     * This depends on the HTML version specified when the {@code Links} object was created.
+     *
+     * @param name the string that needs to be converted to a valid HTML name
+     * @return a valid HTML name
+     */
+    public String getName(String name) {
+        /* The HTML 4 spec at http://www.w3.org/TR/html4/types.html#h-6.2 mentions
+         * that the name/id should begin with a letter followed by other valid characters.
+         * The HTML 5 spec (draft) is more permissive on names/ids where the only restriction
+         * is that it should be at least one character long and should not contain spaces.
+         * The spec draft is @ http://www.w3.org/html/wg/drafts/html/master/dom.html#the-id-attribute.
+         *
+         * For HTML 4, we need to check for non-characters at the beginning of the name and
+         * substitute it accordingly, "_" and "$" can appear at the beginning of a member name.
+         * The method substitutes "$" with "Z:Z:D" and will prefix "_" with "Z:Z".
+         */
+
+        if (version == HtmlVersion.HTML5) {
+            return name.replaceAll(" +", "");
+        }
+
+        StringBuilder sb = new StringBuilder();
+        for (int i = 0; i < name.length(); i++) {
+            char ch = name.charAt(i);
+            switch (ch) {
+                case '(':
+                case ')':
+                case '<':
+                case '>':
+                case ',':
+                    sb.append('-');
+                    break;
+                case ' ':
+                case '[':
+                    break;
+                case ']':
+                    sb.append(":A");
+                    break;
+                // Any appearance of $ needs to be substituted with ":D" and not with hyphen
+                // since a field name "P$$ and a method P(), both valid member names, can end
+                // up as "P--". A member name beginning with $ needs to be substituted with
+                // "Z:Z:D".
+                case '$':
+                    if (i == 0)
+                        sb.append("Z:Z");
+                    sb.append(":D");
+                    break;
+                // A member name beginning with _ needs to be prefixed with "Z:Z" since valid anchor
+                // names can only begin with a letter.
+                case '_':
+                    if (i == 0)
+                        sb.append("Z:Z");
+                    sb.append(ch);
+                    break;
+                default:
+                    sb.append(ch);
+            }
+        }
+        return sb.toString();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/Script.java	Mon Nov 27 17:04:45 2017 +0000
@@ -0,0 +1,224 @@
+/*
+ * Copyright (c) 2003, 2017, 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+
+package jdk.javadoc.internal.doclets.formats.html.markup;
+
+import java.io.IOException;
+import java.io.Writer;
+
+import jdk.javadoc.internal.doclets.toolkit.Content;
+import jdk.javadoc.internal.doclets.toolkit.util.DocletConstants;
+
+/**
+ * A builder for HTML script elements.
+ *
+ *  <p><b>This is NOT part of any supported API.
+ *  If you write code that depends on this, you do so at your own risk.
+ *  This code and its internal interfaces are subject to change or
+ *  deletion without notice.</b>
+ */
+public class Script  {
+    private final StringBuilder sb;
+
+    /**
+     * Creates an empty script.
+     */
+    public Script() {
+        sb = new StringBuilder();
+    }
+
+    /**
+     * Creates a new script containing the specified code.
+     *
+     * @param code the code
+     */
+    public Script(String code) {
+        this();
+        append(code);
+    }
+
+    /**
+     * Appends the given code to the script.
+     *
+     * @param code the code
+     * @return this object
+     */
+    public Script append(CharSequence code) {
+        sb.append(code);
+        return this;
+    }
+
+    /**
+     * Appends the given text as a string constant to the string.
+     * Characters within the string will be escaped as needed.
+     *
+     * @param text the text
+     * @return this object
+     */
+    public Script appendStringLiteral(CharSequence text) {
+        sb.append(stringLiteral(text, '"'));
+        return this;
+    }
+
+    /**
+     * Appends the given text as a string constant to the string.
+     * Characters within the string will be escaped as needed.
+     *
+     * @param text the text
+     * @param quoteChar the quote character to use
+     * @return this object
+     */
+    // The ability to specify the quote character is for backwards
+    // compatibility. Ideally, we should simplify the code so that
+    // the same quote character is always used.
+    public Script appendStringLiteral(CharSequence text, char quoteChar) {
+        sb.append(stringLiteral(text, quoteChar));
+        return this;
+    }
+
+    /**
+     * Returns a "live" view of the script as a {@code Content} object.
+     * Any later modifications to the script will be reflected in the
+     * object that is returned.
+     * @return the script, as a {@code Content} object.
+     */
+    public Content asContent() {
+        ScriptContent scriptContent = new ScriptContent(sb);
+        HtmlTree tree = new HtmlTree(HtmlTag.SCRIPT) {
+            @Override
+            public void addContent(CharSequence s) {
+                throw new UnsupportedOperationException();
+            }
+            @Override
+            public void addContent(Content c) {
+                if (c != scriptContent) {
+                    throw new IllegalArgumentException();
+                }
+                super.addContent(scriptContent);
+            }
+        };
+        tree.addAttr(HtmlAttr.TYPE, "text/javascript");
+        tree.addContent(scriptContent);
+        return tree;
+    }
+
+    /**
+     * Returns a JavaScript string literal containing a specified string,
+     * escaping the characters of that string as needed.
+     *
+     * @param s the string
+     * @return a string literal containing the string
+     */
+    public static String stringLiteral(CharSequence s) {
+        return stringLiteral(s, '"');
+    }
+
+    /**
+     * Returns a JavaScript string literal containing a specified string,
+     * escaping the characters of that string as needed.
+     *
+     * @param s the string
+     * @param quoteChar the quote character to use for the literal
+     * @return a string literal containing the string
+     */
+    // The ability to specify the quote character is for backwards
+    // compatibility. Ideally, we should simplify the code so that
+    // the same quote character is always used.
+    public static String stringLiteral(CharSequence s, char quoteChar) {
+        if (quoteChar != '"' && quoteChar != '\'') {
+            throw new IllegalArgumentException();
+        }
+        StringBuilder sb = new StringBuilder();
+        sb.append(quoteChar);
+        for (int i = 0; i < s.length(); i++) {
+            char ch = s.charAt(i);
+            switch (ch) {
+                case '\b':
+                    sb.append("\\b");
+                    break;
+                case '\t':
+                    sb.append("\\t");
+                    break;
+                case '\n':
+                    sb.append("\\n");
+                    break;
+                case '\f':
+                    sb.append("\\f");
+                    break;
+                case '\r':
+                    sb.append("\\r");
+                    break;
+                case '"':
+                    sb.append("\\\"");
+                    break;
+                case '\'':
+                    sb.append("\\\'");
+                    break;
+                case '\\':
+                    sb.append("\\\\");
+                    break;
+                default:
+                    if (ch < 32 || ch >= 127) {
+                        sb.append(String.format("\\u%04X", (int)ch));
+                    } else {
+                        sb.append(ch);
+                    }
+                    break;
+            }
+        }
+        sb.append(quoteChar);
+        return sb.toString();
+    }
+
+    private static class ScriptContent extends Content {
+        private final StringBuilder sb;
+
+        ScriptContent(StringBuilder sb) {
+            this.sb = sb;
+        }
+
+        @Override
+        public void addContent(Content content) {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public void addContent(CharSequence code) {
+            sb.append(code);
+        }
+
+        @Override
+        public boolean write(Writer writer, boolean atNewline) throws IOException {
+            String s = sb.toString();
+            writer.write(s.replace("\n", DocletConstants.NL));
+            return s.endsWith("\n");
+        }
+
+        @Override
+        public boolean isEmpty() {
+            return false;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/Table.java	Mon Nov 27 17:04:45 2017 +0000
@@ -0,0 +1,593 @@
+/*
+ * Copyright (c) 2003, 2017, 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+
+package jdk.javadoc.internal.doclets.formats.html.markup;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.function.Function;
+import java.util.function.IntFunction;
+import java.util.function.Predicate;
+
+import javax.lang.model.element.Element;
+
+import jdk.javadoc.internal.doclets.formats.html.Contents;
+import jdk.javadoc.internal.doclets.toolkit.Content;
+import jdk.javadoc.internal.doclets.toolkit.util.DocletConstants;
+
+/**
+ * A builder for HTML tables, such as the summary tables for various
+ * types of element.
+ *
+ * <p>The table should be used in three phases:
+ * <ol>
+ * <li>Configuration: the overall characteristics of the table should be specified
+ * <li>Population: the content for the cells in each row should be added
+ * <li>Generation: the HTML content and any associated JavaScript can be accessed
+ * </ol>
+ *
+ * Many methods return the current object, to facilitate fluent builder-style usage.
+ *
+ *  <p><b>This is NOT part of any supported API.
+ *  If you write code that depends on this, you do so at your own risk.
+ *  This code and its internal interfaces are subject to change or
+ *  deletion without notice.</b>
+ */
+public class Table {
+    private final HtmlVersion version;
+    private final HtmlStyle tableStyle;
+    private String summary;
+    private Content caption;
+    private Map<String, Predicate<Element>> tabMap;
+    private String defaultTab;
+    private Set<String> tabs;
+    private HtmlStyle activeTabStyle = HtmlStyle.activeTableTab;
+    private HtmlStyle tabStyle = HtmlStyle.tableTab;
+    private HtmlStyle tabEnd = HtmlStyle.tabEnd;
+    private IntFunction<String> tabScript;
+    private String tabScriptVariable;
+    private Function<Integer, String> tabId = (i -> "t" + i);
+    private TableHeader header;
+    private List<HtmlStyle> columnStyles;
+    private int rowScopeColumnIndex;
+    private List<HtmlStyle> stripedStyles = Arrays.asList(HtmlStyle.altColor, HtmlStyle.rowColor);
+    private final List<Content> bodyRows;
+    private final List<Integer> bodyRowMasks;
+    private String rowIdPrefix = "i";
+
+    // compatibility flags
+    private boolean putIdFirst = false;
+    private boolean useTBody = true;
+
+    /**
+     * Creates a builder for an HTML table.
+     *
+     * @param version   the version of HTML, used to determine is a {@code summary}
+     *                  attribute is needed
+     * @param style     the style class for the {@code <table>} tag
+     */
+    public Table(HtmlVersion version, HtmlStyle style) {
+        this.version = version;
+        this.tableStyle = style;
+        bodyRows = new ArrayList<>();
+        bodyRowMasks = new ArrayList<>();
+    }
+
+    /**
+     * Sets the summary for the table.
+     * This is ignored if the HTML version for the table is not {@link HtmlVersion#HTML4}.
+     *
+     * @param summary the summary
+     * @return this object
+     */
+    public Table setSummary(String summary) {
+        if (version == HtmlVersion.HTML4) {
+            this.summary = summary;
+        }
+        return this;
+    }
+
+    /**
+     * Sets the caption for the table.
+     * This is ignored if the table is configured to provide tabs to select
+     * different subsets of rows within the table.
+     * The caption should be suitable for use as the content of a {@code <caption>}
+     * element.
+     *
+     * <b>For compatibility, the code currently accepts a {@code <caption>} element
+     * as well. This should be removed when all clients rely on using the {@code <caption>}
+     * element being generated by this class.</b>
+     *
+     * @param captionContent the caption
+     * @return this object
+     */
+    public Table setCaption(Content captionContent) {
+        if (captionContent instanceof HtmlTree
+                && ((HtmlTree) captionContent).htmlTag == HtmlTag.CAPTION) {
+            caption = captionContent;
+        } else {
+            caption = getCaption(captionContent);
+        }
+        return this;
+    }
+
+    /**
+     * Adds a tab to the table.
+     * Tabs provide a way to display subsets of rows, as determined by a
+     * predicate for the tab, and an element associated with each row.
+     * Tabs will appear left-to-right in the order they are added.
+     *
+     * @param name      the name of the tab
+     * @param predicate the predicate
+     * @return this object
+     */
+    public Table addTab(String name, Predicate<Element> predicate) {
+        if (tabMap == null) {
+            tabMap = new LinkedHashMap<>();     // preserves order that tabs are added
+            tabs = new HashSet<>();             // order not significant
+        }
+        tabMap.put(name, predicate);
+        return this;
+    }
+
+    /**
+     * Sets the name for the default tab, which displays all the rows in the table.
+     * This tab will appear first in the left-to-right list of displayed tabs.
+     *
+     * @param name the name
+     * @return this object
+     */
+    public Table setDefaultTab(String name) {
+        defaultTab = name;
+        return this;
+    }
+
+    /**
+     * Sets the function used to generate the JavaScript to be used when a tab is selected.
+     * When the function is invoked, the argument will be an integer value containing
+     * the bit mask identifying the rows to be selected.
+     *
+     * @param f the function
+     * @return this object
+     */
+    public Table setTabScript(IntFunction<String> f) {
+        tabScript = f;
+        return this;
+    }
+
+    /**
+     * Sets the name of the JavaScript variable used to contain the data for each tab.
+     *
+     * @param name the name
+     * @return this object
+     */
+    public Table setTabScriptVariable(String name) {
+        tabScriptVariable = name;
+        return this;
+    }
+
+    /**
+     * Sets the name of the styles used to display the tabs.
+     *
+     * @param activeTabStyle    the style for the active tab
+     * @param tabStyle          the style for other tabs
+     * @param tabEnd            the style for the padding that appears within each tab
+     * @return  this object
+     */
+    public Table setTabStyles(HtmlStyle activeTabStyle, HtmlStyle tabStyle, HtmlStyle tabEnd) {
+        this.activeTabStyle = activeTabStyle;
+        this.tabStyle = tabStyle;
+        this.tabEnd = tabEnd;
+        return this;
+    }
+
+    /**
+     * Sets the JavaScript function used to generate the {@code id} attribute for each tag.
+     * The default is to use <code>t</code><i>N</i> where <i>N</i> is the index of the tab,
+     * counting from 0 (for the default tab), and then from 1 upwards for additional tabs.
+     *
+     * @param f the function
+     * @return this object
+     */
+    public Table setTabId(Function<Integer,String> f) {
+        tabId = f;
+        return this;
+    }
+
+    /**
+     * Sets the header for the table.
+     *
+     * <p>Notes:
+     * <ul>
+     * <li>This currently does not use a {@code <thead>} tag, but probably should, eventually
+     * <li>The column styles are not currently applied to the header, but probably should, eventually
+     * </ul>
+     *
+     * @param header the header
+     * @return this object
+     */
+    public Table setHeader(TableHeader header) {
+        this.header = header;
+        return this;
+    }
+
+    /**
+     * Sets the styles used for {@code <tr>} tags, to give a "striped" appearance.
+     * The defaults are currently {@code rowColor} and {@code altColor}.
+     *
+     * @param evenRowStyle  the style to use for even-numbered rows
+     * @param oddRowStyle   the style to use for odd-numbered rows
+     * @return
+     */
+    public Table setStripedStyles(HtmlStyle evenRowStyle, HtmlStyle oddRowStyle) {
+        stripedStyles = Arrays.asList(evenRowStyle, oddRowStyle);
+        return this;
+    }
+
+    /**
+     * Sets the column used to indicate which cell in a row should be declared
+     * as a header cell with the {@code scope} attribute set to {@code row}.
+     *
+     * @param columnIndex the column index
+     * @return this object
+     */
+    public Table setRowScopeColumn(int columnIndex) {
+        rowScopeColumnIndex = columnIndex;
+        return this;
+    }
+
+    /**
+     * Sets the styles for be used for the cells in each row.
+     *
+     * <p>Note:
+     * <ul>
+     * <li>The column styles are not currently applied to the header, but probably should, eventually
+     * </ul>
+     *
+     * @param styles the styles
+     * @return this object
+     */
+    public Table setColumnStyles(HtmlStyle... styles) {
+        return setColumnStyles(Arrays.asList(styles));
+    }
+
+    /**
+     * Sets the styles for be used for the cells in each row.
+     *
+     * <p>Note:
+     * <ul>
+     * <li>The column styles are not currently applied to the header, but probably should, eventually
+     * </ul>
+     *
+     * @param styles the styles
+     * @return this object
+     */
+    public Table setColumnStyles(List<HtmlStyle> styles) {
+        columnStyles = styles;
+        return this;
+    }
+
+    /**
+     * Sets the prefix used for the {@code id} attribute for each row in the table.
+     * The default is "i".
+     *
+     * <p>Note:
+     * <ul>
+     * <li>The prefix should probably be a value such that the generated ids cannot
+     *      clash with any other id, such as those that might be created for fields within
+     *      a class.
+     * </ul>
+     *
+     * @param prefix the prefix
+     * @return  this object
+     */
+    public Table setRowIdPrefix(String prefix) {
+        rowIdPrefix = prefix;
+        return this;
+    }
+
+    /**
+     * Sets whether the {@code id} attribute should appear first in a {@code <tr>} tag.
+     * The default is {@code false}.
+     *
+     * <b>This is a compatibility feature that should be removed when all tables use a
+     * consistent policy.</b>
+     *
+     * @param first whether to put {@code id} attributes first
+     * @return this object
+     */
+    public Table setPutIdFirst(boolean first) {
+        this.putIdFirst = first;
+        return this;
+    }
+
+    /**
+     * Sets whether or not to use an explicit {@code <tbody>} element to enclose the rows
+     * of a table.
+     * The default is {@code true}.
+     *
+     * <b>This is a compatibility feature that should be removed when all tables use a
+     * consistent policy.</b>
+     *
+     * @param use whether o use a {@code <tbody> element
+     * @return this object
+     */
+    public Table setUseTBody(boolean use) {
+        this.useTBody = use;
+        return this;
+    }
+
+    /**
+     * Add a row of data to the table.
+     * Each item of content should be suitable for use as the content of a
+     * {@code <th>} or {@code <td>} cell.
+     * This method should not be used when the table has tabs: use a method
+     * that takes an {@code Element} parameter instead.
+     *
+     * @param contents the contents for the row
+     */
+    public void addRow(Content... contents) {
+        addRow(null, Arrays.asList(contents));
+    }
+
+    /**
+     * Add a row of data to the table.
+     * Each item of content should be suitable for use as the content of a
+     * {@code <th>} or {@code <td> cell}.
+     * This method should not be used when the table has tabs: use a method
+     * that takes an {@code element} parameter instead.
+     *
+     * @param contents the contents for the row
+     */
+    public void addRow(List<Content> contents) {
+        addRow(null, contents);
+    }
+
+    /**
+     * Add a row of data to the table.
+     * Each item of content should be suitable for use as the content of a
+     * {@code <th>} or {@code <td>} cell.
+     *
+     * If tabs have been added to the table, the specified element will be used
+     * to determine whether the row should be displayed when any particular tab
+     * is selected, using the predicate specified when the tab was
+     * {@link #add(String,Predicate) added}.
+     *
+     * @param element the element
+     * @param contents the contents for the row
+     * @throws NullPointerException if tabs have previously been added to the table
+     *      and {@code element} is null
+     */
+    public void addRow(Element element, Content... contents) {
+        addRow(element, Arrays.asList(contents));
+    }
+
+    /**
+     * Add a row of data to the table.
+     * Each item of content should be suitable for use as the content of a
+     * {@code <th>} or {@code <td>} cell.
+     *
+     * If tabs have been added to the table, the specified element will be used
+     * to determine whether the row should be displayed when any particular tab
+     * is selected, using the predicate specified when the tab was
+     * {@link #add(String,Predicate) added}.
+     *
+     * @param element the element
+     * @param contents the contents for the row
+     * @throws NullPointerException if tabs have previously been added to the table
+     *      and {@code element} is null
+     */
+    public void addRow(Element element, List<Content> contents) {
+        if (tabMap != null && element == null) {
+            throw new NullPointerException();
+        }
+
+        HtmlTree row = new HtmlTree(HtmlTag.TR);
+
+        if (putIdFirst && tabMap != null) {
+            int index = bodyRows.size();
+            row.addAttr(HtmlAttr.ID, (rowIdPrefix + index));
+        }
+
+        if (stripedStyles != null) {
+            int rowIndex = bodyRows.size();
+            row.addAttr(HtmlAttr.CLASS, stripedStyles.get(rowIndex % 2).name());
+        }
+        int colIndex = 0;
+        for (Content c : contents) {
+            HtmlStyle cellStyle = (columnStyles == null || colIndex > columnStyles.size())
+                    ? null
+                    : columnStyles.get(colIndex);
+            HtmlTree cell = (colIndex == rowScopeColumnIndex)
+                    ? HtmlTree.TH(cellStyle, "row", c)
+                    : HtmlTree.TD(cellStyle, c);
+            row.addContent(cell);
+            colIndex++;
+        }
+        bodyRows.add(row);
+
+        if (tabMap != null) {
+            if (!putIdFirst) {
+                int index = bodyRows.size() - 1;
+                row.addAttr(HtmlAttr.ID, (rowIdPrefix + index));
+            }
+            int mask = 0;
+            int maskBit = 1;
+            for (Map.Entry<String, Predicate<Element>> e : tabMap.entrySet()) {
+                String name = e.getKey();
+                Predicate<Element> predicate = e.getValue();
+                if (predicate.test(element)) {
+                    tabs.add(name);
+                    mask |= maskBit;
+                }
+                maskBit = (maskBit << 1);
+            }
+            bodyRowMasks.add(mask);
+        }
+    }
+
+    /**
+     * Returns whether or not the table is empty.
+     * The table is empty if it has no (body) rows.
+     *
+     * @return true if the table has no rows
+     */
+    public boolean isEmpty() {
+        return bodyRows.isEmpty();
+    }
+
+    /**
+     * Returns the HTML for the table.
+     *
+     * @return the HTML
+     */
+    public Content toContent() {
+        HtmlTree table = new HtmlTree(HtmlTag.TABLE);
+        table.setStyle(tableStyle);
+        if (summary != null) {
+            table.addAttr(HtmlAttr.SUMMARY, summary);
+        }
+        if (tabMap != null) {
+            if (tabs.size() == 1) {
+                String tabName = tabs.iterator().next();
+                table.addContent(getCaption(new StringContent(tabName)));
+            } else {
+                ContentBuilder cb = new ContentBuilder();
+                int tabIndex = 0;
+                HtmlTree defaultTabSpan = new HtmlTree(HtmlTag.SPAN,
+                            HtmlTree.SPAN(new StringContent(defaultTab)),
+                            HtmlTree.SPAN(tabEnd, Contents.SPACE))
+                        .addAttr(HtmlAttr.ID, tabId.apply(tabIndex))
+                        .setStyle(activeTabStyle);
+                cb.addContent(defaultTabSpan);
+                for (String tabName : tabMap.keySet()) {
+                    tabIndex++;
+                    if (tabs.contains(tabName)) {
+                        String script = "javascript:" + tabScript.apply(1 << (tabIndex - 1));
+                        HtmlTree link = HtmlTree.A(script, new StringContent(tabName));
+                        HtmlTree tabSpan = new HtmlTree(HtmlTag.SPAN,
+                                    HtmlTree.SPAN(link), HtmlTree.SPAN(tabEnd, Contents.SPACE))
+                                .addAttr(HtmlAttr.ID, tabId.apply(tabIndex))
+                                .setStyle(tabStyle);
+                        cb.addContent(tabSpan);
+                    }
+                }
+                table.addContent(HtmlTree.CAPTION(cb));
+            }
+        } else {
+            table.addContent(caption);
+        }
+        table.addContent(header.toContent());
+        if (useTBody) {
+            Content tbody = new HtmlTree(HtmlTag.TBODY);
+            bodyRows.forEach(row -> tbody.addContent(row));
+            table.addContent(tbody);
+        } else {
+            bodyRows.forEach(row -> table.addContent(row));
+        }
+        return table;
+    }
+
+    /**
+     * Returns whether or not the table needs JavaScript support.
+     * It requires such support if tabs have been added.
+     *
+     * @return true if JavaScript is required
+     */
+    public boolean needsScript() {
+        return (tabs != null) && (tabs.size() > 1);
+    }
+
+    /**
+     * Returns the script to be used in conjunction with the table.
+     *
+     * @return the script
+     */
+    public String getScript() {
+        if (tabMap == null)
+            throw new IllegalStateException();
+
+        StringBuilder sb = new StringBuilder();
+
+        // Add the variable defining the bitmask for each row
+        sb.append("var ").append(tabScriptVariable).append(" = {");
+        int rowIndex = 0;
+        for (int mask : bodyRowMasks) {
+            if (rowIndex > 0) {
+                sb.append(",");
+            }
+            sb.append("\"").append(rowIdPrefix).append(rowIndex).append("\":").append(mask);
+            rowIndex++;
+        }
+        sb.append("};\n");
+
+        // Add the variable defining the tabs
+        sb.append("var tabs = {");
+        appendTabInfo(sb, 65535, tabId.apply(0), defaultTab);
+        int tabIndex = 1;
+        int maskBit = 1;
+        for (String tabName: tabMap.keySet()) {
+            if (tabs.contains(tabName)) {
+                sb.append(",");
+                appendTabInfo(sb, maskBit, tabId.apply(tabIndex), tabName);
+            }
+            tabIndex++;
+            maskBit = (maskBit << 1);
+        }
+        sb.append("};\n");
+
+        // Add the variables defining the stylenames
+        appendStyleInfo(sb,
+                stripedStyles.get(0), stripedStyles.get(1), tabStyle, activeTabStyle);
+        return sb.toString();
+    }
+
+    private void appendTabInfo(StringBuilder sb, int value, String id, String name) {
+        sb.append(value)
+                .append(":[")
+                .append(Script.stringLiteral(id))
+                .append(",")
+                .append(Script.stringLiteral(name))
+                .append("]");
+    }
+
+    private void appendStyleInfo(StringBuilder sb, HtmlStyle... styles) {
+        for (HtmlStyle style : styles) {
+            sb.append("var ").append(style).append(" = \"").append(style).append("\";\n");
+        }
+
+    }
+
+    private HtmlTree getCaption(Content title) {
+        return new HtmlTree(HtmlTag.CAPTION,
+                HtmlTree.SPAN(title),
+                HtmlTree.SPAN(tabEnd, Contents.SPACE));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/TableHeader.java	Mon Nov 27 17:04:45 2017 +0000
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2017, 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+
+package jdk.javadoc.internal.doclets.formats.html.markup;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import jdk.javadoc.internal.doclets.formats.html.Contents;
+import jdk.javadoc.internal.doclets.toolkit.Content;
+
+/**
+ * A row header for an HTML table.
+ *
+ * The header contains a list of {@code <th>} cells, providing the column headers.
+ * The attribute {@code scope="col"} is automatically added to each header cell.
+ * In addition, a series of style class names can be specified, to be applied one per cell.
+ *
+ *  <p><b>This is NOT part of any supported API.
+ *  If you write code that depends on this, you do so at your own risk.
+ *  This code and its internal interfaces are subject to change or
+ *  deletion without notice.</b>
+ */
+public class TableHeader {
+
+    /**
+     * The content to be put in each of the {@code <th>} cells in the header row.
+     */
+    private final List<Content> cellContents;
+    /**
+     * The style class names for each of the {@code <th>} cells in the header row.
+     * If not set, default style names will be used.
+     */
+    private List<HtmlStyle> styles;
+
+    /**
+     * Creates a header row, with localized content for each cell.
+     * Resources keys will be converted to content using {@link Contents#getContent(String)}.
+     * @param contents a factory to get the content for each header cell.
+     * @param colHeaderKeys the resource keys for the content in each cell.
+     */
+    public TableHeader(Contents contents, String... colHeaderKeys) {
+        this.cellContents = Arrays.stream(colHeaderKeys)
+                .map((key) -> contents.getContent(key))
+                .collect(Collectors.toList());
+    }
+
+    /**
+     * Creates a header row, with specified content for each cell.
+     * @param headerCellContents a content object for each header cell
+     */
+    public TableHeader(Content... headerCellContents) {
+        this.cellContents = Arrays.asList(headerCellContents);
+    }
+
+    /**
+     * Set the style class names for each header cell.
+     * The number of names must match the number of cells given to the constructor.
+     * @param styles the style class names
+     * @return this object
+     */
+    public TableHeader styles(HtmlStyle... styles) {
+        if (styles.length != cellContents.size()) {
+            throw new IllegalStateException();
+        }
+        this.styles = Arrays.asList(styles);
+        return this;
+    }
+
+    /**
+     * Converts this header to a {@link Content} object, for use in an {@link HtmlTree}.
+     * @return a Content object
+     */
+    public Content toContent() {
+        String scope = "col";
+        Content tr = new HtmlTree(HtmlTag.TR);
+        int i = 0;
+        for (Content cellContent : cellContents) {
+            HtmlStyle style = (styles != null) ? styles.get(i)
+                    : (i == 0) ? HtmlStyle.colFirst
+                    : (i == (cellContents.size() - 1)) ? HtmlStyle.colLast
+                    : (i == 1) ? HtmlStyle.colSecond : null;
+            Content cell = (style == null) ? HtmlTree.TH(scope, cellContent)
+                    : HtmlTree.TH(style, scope, cellContent);
+            tr.addContent(cell);
+            i++;
+        }
+        return tr;
+    }
+
+}
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/package-info.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/package-info.java	Mon Nov 27 17:04:45 2017 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2017, 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
@@ -24,12 +24,17 @@
  */
 
 /**
-    This package contains classes that write HTML markup tags.
-
-    <p><b>This is NOT part of any supported API.
-    If you write code that depends on this, you do so at your own risk.
-    This code and its internal interfaces are subject to change or
-    deletion without notice.</b>
+ * This package contains classes that create and write HTML markup tags.
+ *
+ * The primary low level classes are {@link HtmlTree} and subtypes
+ * of {@code Content}. In addition, there are mid-level builders
+ * like {@link TableHeader} and {@link Table} to help build more
+ * complex HTML trees.
+ *
+ *  <p><b>This is NOT part of any supported API.
+ *  If you write code that depends on this, you do so at your own risk.
+ *  This code and its internal interfaces are subject to change or
+ *  deletion without notice.</b>
  */
 
 package jdk.javadoc.internal.doclets.formats.html.markup;
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/AbstractDoclet.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/AbstractDoclet.java	Mon Nov 27 17:04:45 2017 +0000
@@ -201,7 +201,7 @@
             return;
         }
         messages.notice("doclet.build_version",
-            configuration.getDocletSpecificBuildDate());
+            configuration.getDocletVersion());
         ClassTree classtree = new ClassTree(configuration, configuration.nodeprecated);
 
         generateClassFiles(docEnv, classtree);
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/BaseConfiguration.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/BaseConfiguration.java	Mon Nov 27 17:04:45 2017 +0000
@@ -307,11 +307,11 @@
     public abstract Resources getResources();
 
     /**
-     * Return the build date for the doclet.
+     * Returns a string identifying the version of the doclet.
      *
-     * @return the build date
+     * @return a version string
      */
-    public abstract String getDocletSpecificBuildDate();
+    public abstract String getDocletVersion();
 
     /**
      * This method should be defined in all those doclets (configurations),
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/Content.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/Content.java	Mon Nov 27 17:04:45 2017 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2017, 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
@@ -76,6 +76,10 @@
     /**
      * Writes content to a writer.
      *
+     * @param writer the writer
+     * @param atNewline whether the writer has just written a newline
+     * @return  whether the writer has just written a newline
+     * @throws IOException if an error occurs while writing the output
      */
     public abstract boolean write(Writer writer, boolean atNewline) throws IOException ;
 
@@ -107,6 +111,7 @@
     /**
      * Checks for null values.
      *
+     * @param <T> the type of the item being checked
      * @param t reference type to check for null values
      * @return the reference type if not null or else throws a null pointer exception
      */
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/MemberSummaryWriter.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/MemberSummaryWriter.java	Mon Nov 27 17:04:45 2017 +0000
@@ -25,7 +25,6 @@
 
 package jdk.javadoc.internal.doclets.toolkit;
 
-import java.io.*;
 import java.util.*;
 
 import javax.lang.model.element.Element;
@@ -62,11 +61,9 @@
      * Get the summary table for the given class.
      *
      * @param typeElement the class the summary table belongs to
-     * @param tableContents list of contents that will be added to the summary table
      * @return a content tree for the member summary table
      */
-    public Content getSummaryTableTree(TypeElement typeElement,
-            List<Content> tableContents);
+    public Content getSummaryTableTree(TypeElement typeElement);
 
     /**
      * Add the member summary for the given class and member.
@@ -74,12 +71,9 @@
      * @param typeElement the class the summary belongs to
      * @param member the member that is documented
      * @param firstSentenceTags the tags for the sentence being documented
-     * @param tableContents list of contents to which the summary will be added
-     * @param counter the counter for determining id and style for the table row
      */
     public void addMemberSummary(TypeElement typeElement, Element member,
-            List<? extends DocTree> firstSentenceTags, List<Content> tableContents, int counter,
-            VisibleMemberMap.Kind vmmKind);
+            List<? extends DocTree> firstSentenceTags);
 
     /**
      * Get the inherited member summary header for the given class.
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/MemberSummaryBuilder.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/MemberSummaryBuilder.java	Mon Nov 27 17:04:45 2017 +0000
@@ -333,8 +333,6 @@
             VisibleMemberMap visibleMemberMap, LinkedList<Content> summaryTreeList) {
         SortedSet<Element> members = asSortedSet(visibleMemberMap.getLeafMembers());
         if (!members.isEmpty()) {
-            List<Content> tableContents = new LinkedList<>();
-            int counter = 0;
             for (Element member : members) {
                 final Element property = visibleMemberMap.getPropertyElement(member);
                 if (property != null) {
@@ -355,11 +353,9 @@
                         firstSentenceTags = utils.getFirstSentenceTrees(inheritedDoc.holder);
                     }
                 }
-                writer.addMemberSummary(typeElement, member, firstSentenceTags,
-                        tableContents, counter, visibleMemberMap.kind);
-                counter++;
+                writer.addMemberSummary(typeElement, member, firstSentenceTags);
             }
-            summaryTreeList.add(writer.getSummaryTableTree(typeElement, tableContents));
+            summaryTreeList.add(writer.getSummaryTableTree(typeElement));
         }
     }
 
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Extern.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Extern.java	Mon Nov 27 17:04:45 2017 +0000
@@ -223,7 +223,7 @@
             }
             return true;
         } catch (Fault f) {
-            reporter.print(Diagnostic.Kind.WARNING, f.getMessage());
+            reporter.print(Diagnostic.Kind.ERROR, f.getMessage());
             return false;
         }
     }
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/GroupTypes.java	Fri Nov 24 17:19:47 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,67 +0,0 @@
-/*
- * Copyright (c) 2017, 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.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.
- */
-
-package jdk.javadoc.internal.doclets.toolkit.util;
-
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-
-import jdk.javadoc.internal.doclets.toolkit.util.TableTabTypes.TableTabs;
-
-/**
- * Enum representing group types.
- *
- *  <p><b>This is NOT part of any supported API.
- *  If you write code that depends on this, you do so at your own risk.
- *  This code and its internal interfaces are subject to change or
- *  deletion without notice.</b>
- *
- * @author Bhavesh Patel
- */
-public class GroupTypes {
-
-    private final Map<String,TableTabs> tabs = new LinkedHashMap<>();
-
-    private int value = 1;
-
-    public GroupTypes(List<String> groupList, String allLabel) {
-        if (groupList.size() > 1) {
-            tabs.put(allLabel, TableTabs.tab(65535, allLabel, "t0", true));
-        }
-        groupList.forEach((groupname) -> {
-            tabs.put(groupname, TableTabs.tab(value, groupname, "t" + value, false));
-            value = 2 * value;
-        });
-    }
-
-    public Map<String,TableTabs> getGroupTypes() {
-        return tabs;
-    }
-
-    public TableTabs getTableTab(String groupName) {
-        return tabs.get(groupName);
-    }
-}
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/MethodTypes.java	Fri Nov 24 17:19:47 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,52 +0,0 @@
-/*
- * Copyright (c) 2012, 2015, 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.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.
- */
-
-package jdk.javadoc.internal.doclets.toolkit.util;
-
-/**
- * Enum representing method types.
- *
- * @author Bhavesh Patel
- */
-public enum MethodTypes implements TableTabTypes {
-
-    ALL(TableTabs.tab(0xffff, "doclet.All_Methods", "t0", true)),
-    STATIC(TableTabs.tab(0x1, "doclet.Static_Methods", "t1", false)),
-    INSTANCE(TableTabs.tab(0x2, "doclet.Instance_Methods", "t2", false)),
-    ABSTRACT(TableTabs.tab(0x4, "doclet.Abstract_Methods", "t3", false)),
-    CONCRETE(TableTabs.tab(0x8, "doclet.Concrete_Methods", "t4", false)),
-    DEFAULT(TableTabs.tab(0x10, "doclet.Default_Methods", "t5", false)),
-    DEPRECATED(TableTabs.tab(0x20, "doclet.Deprecated_Methods", "t6", false));
-
-    private final TableTabs tabs;
-
-    private MethodTypes(TableTabs t) {
-        this.tabs = t;
-    }
-
-    public TableTabs tableTabs() {
-        return this.tabs;
-    }
-    }
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/ModulePackageTypes.java	Fri Nov 24 17:19:47 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,55 +0,0 @@
-/*
- * Copyright (c) 2016, 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.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.
- */
-
-package jdk.javadoc.internal.doclets.toolkit.util;
-
-import jdk.javadoc.internal.doclets.toolkit.util.TableTabTypes.TableTabs;
-
-/**
- * Enum representing module package types.
- *
- *  <p><b>This is NOT part of any supported API.
- *  If you write code that depends on this, you do so at your own risk.
- *  This code and its internal interfaces are subject to change or
- *  deletion without notice.</b>
- *
- * @author Bhavesh Patel
- */
-public enum ModulePackageTypes implements TableTabTypes {
-    ALL(TableTabs.tab(0xffff, "doclet.All_Packages", "t0", true)),
-    EXPORTED(TableTabs.tab(0x1, "doclet.Exported_Packages_Summary", "t1", false)),
-    OPENED(TableTabs.tab(0x2, "doclet.Opened_Packages_Summary", "t2", false)),
-    CONCEALED(TableTabs.tab(0x4, "doclet.Concealed_Packages_Summary", "t3", false));
-
-    private final TableTabs tabs;
-
-    private ModulePackageTypes(TableTabs t) {
-        this.tabs = t;
-    }
-
-    public TableTabs tableTabs() {
-        return this.tabs;
-    }
-}
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/TableTabTypes.java	Fri Nov 24 17:19:47 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,76 +0,0 @@
-/*
- * Copyright (c) 2016, 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.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.
- */
-
-package jdk.javadoc.internal.doclets.toolkit.util;
-
-/**
- * Interface representing table tab types.
- *
- *  <p><b>This is NOT part of any supported API.
- *  If you write code that depends on this, you do so at your own risk.
- *  This code and its internal interfaces are subject to change or
- *  deletion without notice.</b>
- *
- * @author Bhavesh Patel
- */
-public interface TableTabTypes {
-
-    TableTabs tableTabs();
-
-    public static final class TableTabs {
-
-        private final int value;
-        private final String resourceKey;
-        private final String tabId;
-        private final boolean isDefaultTab;
-
-        private TableTabs(int v, String k, String id, boolean dt) {
-            this.value = v;
-            this.resourceKey = k;
-            this.tabId = id;
-            this.isDefaultTab = dt;
-        }
-
-        public static TableTabs tab(int value, String resourceKey, String tabId, boolean isDefaultTab) {
-            return new TableTabs(value, resourceKey, tabId, isDefaultTab);
-        }
-
-        public int value() {
-            return this.value;
-        }
-
-        public String resourceKey() {
-            return this.resourceKey;
-        }
-
-        public String tabId() {
-            return this.tabId;
-        }
-
-        public boolean isDefaultTab() {
-            return this.isDefaultTab;
-        }
-    }
-}
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/ToolOption.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/ToolOption.java	Mon Nov 27 17:04:45 2017 +0000
@@ -150,6 +150,7 @@
         @Override
         public void process(Helper helper, String arg) throws InvalidValueException {
             Option.SOURCE.process(helper.getOptionHelper(), primaryName, arg);
+            Option.TARGET.process(helper.getOptionHelper(), Option.TARGET.primaryName, arg);
         }
     },
 
--- a/src/jdk.jcmd/share/classes/sun/tools/jstat/ExpressionResolver.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/jdk.jcmd/share/classes/sun/tools/jstat/ExpressionResolver.java	Mon Nov 27 17:04:45 2017 +0000
@@ -69,8 +69,10 @@
             // look it up
             Monitor m = vm.findByName(id.getName());
             if (m == null) {
-                System.err.println("Warning: Unresolved Symbol: "
-                                   + id.getName() + " substituted NaN");
+                if (debug) {
+                    System.err.println("Warning: Unresolved Symbol: "
+                                       + id.getName() + " substituted NaN");
+                }
                 return new Literal(Double.valueOf(Double.NaN));
             }
             if (m.getVariability() == Variability.CONSTANT) {
--- a/src/jdk.jdeps/share/classes/com/sun/tools/javap/AnnotationWriter.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/jdk.jdeps/share/classes/com/sun/tools/javap/AnnotationWriter.java	Mon Nov 27 17:04:45 2017 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2017, 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
@@ -61,24 +61,45 @@
 
     public void write(Annotation annot) {
         write(annot, false);
+        println();
+        indent(+1);
+        write(annot, true);
+        indent(-1);
     }
 
     public void write(Annotation annot, boolean resolveIndices) {
         writeDescriptor(annot.type_index, resolveIndices);
-        boolean showParens = annot.num_element_value_pairs > 0 || !resolveIndices;
-        if (showParens)
+        if (resolveIndices) {
+            boolean showParens = annot.num_element_value_pairs > 0;
+            if (showParens) {
+                println("(");
+                indent(+1);
+            }
+            for (int i = 0; i < annot.num_element_value_pairs; i++) {
+                write(annot.element_value_pairs[i], true);
+                println();
+            }
+            if (showParens) {
+                indent(-1);
+                print(")");
+            }
+        } else {
             print("(");
-        for (int i = 0; i < annot.num_element_value_pairs; i++) {
-            if (i > 0)
-                print(",");
-            write(annot.element_value_pairs[i], resolveIndices);
+            for (int i = 0; i < annot.num_element_value_pairs; i++) {
+                if (i > 0)
+                    print(",");
+                write(annot.element_value_pairs[i], false);
+            }
+            print(")");
         }
-        if (showParens)
-            print(")");
     }
 
     public void write(TypeAnnotation annot) {
         write(annot, true, false);
+        println();
+        indent(+1);
+        write(annot.annotation, true);
+        indent(-1);
     }
 
     public void write(TypeAnnotation annot, boolean showOffsets, boolean resolveIndices) {
@@ -194,10 +215,6 @@
         }
     }
 
-    public void write(Annotation.element_value_pair pair) {
-        write(pair, false);
-    }
-
     public void write(Annotation.element_value_pair pair, boolean resolveIndices) {
         writeIndex(pair.element_name_index, resolveIndices);
         print("=");
@@ -206,6 +223,10 @@
 
     public void write(Annotation.element_value value) {
         write(value, false);
+        println();
+        indent(+1);
+        write(value, true);
+        indent(-1);
     }
 
     public void write(Annotation.element_value value, boolean resolveIndices) {
@@ -240,39 +261,79 @@
             value.accept(this, resolveIndices);
         }
 
+        @Override
         public Void visitPrimitive(Primitive_element_value ev, Boolean resolveIndices) {
-            if (resolveIndices)
-                writeIndex(ev.const_value_index, resolveIndices);
-            else
+            if (resolveIndices) {
+                int index = ev.const_value_index;
+                switch (ev.tag) {
+                    case 'B':
+                        print("(byte) ");
+                        print(constantWriter.stringValue(index));
+                        break;
+                    case 'C':
+                        print("'");
+                        print(constantWriter.charValue(index));
+                        print("'");
+                        break;
+                    case 'D':
+                    case 'F':
+                    case 'I':
+                    case 'J':
+                        print(constantWriter.stringValue(index));
+                        break;
+                    case 'S':
+                        print("(short) ");
+                        print(constantWriter.stringValue(index));
+                        break;
+                    case 'Z':
+                        print(constantWriter.booleanValue(index));
+                        break;
+                    case 's':
+                        print("\"");
+                        print(constantWriter.stringValue(index));
+                        print("\"");
+                        break;
+                    default:
+                        print(((char) ev.tag) + "#" + ev.const_value_index);
+                        break;
+                }
+            } else {
                 print(((char) ev.tag) + "#" + ev.const_value_index);
+            }
             return null;
         }
 
+        @Override
         public Void visitEnum(Enum_element_value ev, Boolean resolveIndices) {
             if (resolveIndices) {
                 writeIndex(ev.type_name_index, resolveIndices);
                 print(".");
                 writeIndex(ev.const_name_index, resolveIndices);
-            } else
+            } else {
                 print(((char) ev.tag) + "#" + ev.type_name_index + ".#" + ev.const_name_index);
+            }
             return null;
         }
 
+        @Override
         public Void visitClass(Class_element_value ev, Boolean resolveIndices) {
             if (resolveIndices) {
+                print("class ");
                 writeIndex(ev.class_info_index, resolveIndices);
-                print(".class");
-            } else
+            } else {
                 print(((char) ev.tag) + "#" + ev.class_info_index);
+            }
             return null;
         }
 
+        @Override
         public Void visitAnnotation(Annotation_element_value ev, Boolean resolveIndices) {
             print((char) ev.tag);
             AnnotationWriter.this.write(ev.annotation_value, resolveIndices);
             return null;
         }
 
+        @Override
         public Void visitArray(Array_element_value ev, Boolean resolveIndices) {
             print("[");
             for (int i = 0; i < ev.num_values; i++) {
@@ -286,6 +347,6 @@
 
     }
 
-    private ClassWriter classWriter;
-    private ConstantWriter constantWriter;
+    private final ClassWriter classWriter;
+    private final ConstantWriter constantWriter;
 }
--- a/src/jdk.jdeps/share/classes/com/sun/tools/javap/ConstantWriter.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/jdk.jdeps/share/classes/com/sun/tools/javap/ConstantWriter.java	Mon Nov 27 17:04:45 2017 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2017, 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
@@ -253,6 +253,38 @@
         }
     }
 
+    String booleanValue(int constant_pool_index) {
+        ClassFile classFile = classWriter.getClassFile();
+        try {
+            CPInfo info = classFile.constant_pool.get(constant_pool_index);
+            if (info instanceof CONSTANT_Integer_info) {
+                int value = ((CONSTANT_Integer_info) info).value;
+               switch (value) {
+                   case 0: return "false";
+                   case 1: return "true";
+               }
+            }
+            return "#" + constant_pool_index;
+        } catch (ConstantPool.InvalidIndex e) {
+            return report(e);
+        }
+    }
+
+    String charValue(int constant_pool_index) {
+        ClassFile classFile = classWriter.getClassFile();
+        try {
+            CPInfo info = classFile.constant_pool.get(constant_pool_index);
+            if (info instanceof CONSTANT_Integer_info) {
+                int value = ((CONSTANT_Integer_info) info).value;
+                return String.valueOf((char) value);
+            } else {
+                return "#" + constant_pool_index;
+            }
+        } catch (ConstantPool.InvalidIndex e) {
+            return report(e);
+        }
+    }
+
     String stringValue(int constant_pool_index) {
         ClassFile classFile = classWriter.getClassFile();
         try {
--- a/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/ConsoleIOContext.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/ConsoleIOContext.java	Mon Nov 27 17:04:45 2017 +0000
@@ -923,7 +923,7 @@
 
                             @Override
                             public void perform(ConsoleReader in) throws IOException {
-                                repl.processCompleteSource("import " + type + ";");
+                                repl.processSource("import " + type + ";");
                                 in.println("Imported: " + type);
                                 performToVar(in, stype);
                             }
@@ -1028,7 +1028,7 @@
 
                             @Override
                             public void perform(ConsoleReader in) throws IOException {
-                                repl.processCompleteSource("import " + type + ";");
+                                repl.processSource("import " + type + ";");
                                 in.println("Imported: " + type);
                                 performToMethod(in, stype, codeToCursor);
                             }
@@ -1052,7 +1052,7 @@
 
                         @Override
                         public void perform(ConsoleReader in) throws IOException {
-                            repl.processCompleteSource("import " + fqn + ";");
+                            repl.processSource("import " + fqn + ";");
                             in.println("Imported: " + fqn);
                             in.redrawLine();
                         }
--- a/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java	Mon Nov 27 17:04:45 2017 +0000
@@ -27,6 +27,7 @@
 
 import java.io.BufferedReader;
 import java.io.BufferedWriter;
+import java.io.EOFException;
 import java.io.File;
 import java.io.FileNotFoundException;
 import java.io.FileReader;
@@ -36,6 +37,9 @@
 import java.io.PrintStream;
 import java.io.Reader;
 import java.io.StringReader;
+import java.lang.module.ModuleDescriptor;
+import java.lang.module.ModuleFinder;
+import java.lang.module.ModuleReference;
 import java.nio.charset.Charset;
 import java.nio.file.FileSystems;
 import java.nio.file.Files;
@@ -55,6 +59,7 @@
 import java.util.Locale;
 import java.util.Map;
 import java.util.Map.Entry;
+import java.util.Optional;
 import java.util.Scanner;
 import java.util.Set;
 import java.util.function.Consumer;
@@ -77,10 +82,12 @@
 import jdk.jshell.JShell.Subscription;
 import jdk.jshell.MethodSnippet;
 import jdk.jshell.Snippet;
+import jdk.jshell.Snippet.Kind;
 import jdk.jshell.Snippet.Status;
 import jdk.jshell.SnippetEvent;
 import jdk.jshell.SourceCodeAnalysis;
 import jdk.jshell.SourceCodeAnalysis.CompletionInfo;
+import jdk.jshell.SourceCodeAnalysis.Completeness;
 import jdk.jshell.SourceCodeAnalysis.Suggestion;
 import jdk.jshell.TypeDeclSnippet;
 import jdk.jshell.UnresolvedReferenceException;
@@ -89,6 +96,7 @@
 import static java.nio.file.StandardOpenOption.CREATE;
 import static java.nio.file.StandardOpenOption.TRUNCATE_EXISTING;
 import static java.nio.file.StandardOpenOption.WRITE;
+import java.util.AbstractMap.SimpleEntry;
 import java.util.MissingResourceException;
 import java.util.ResourceBundle;
 import java.util.ServiceLoader;
@@ -108,6 +116,7 @@
 import static java.util.Arrays.stream;
 import static java.util.stream.Collectors.joining;
 import static java.util.stream.Collectors.toList;
+import static jdk.jshell.Snippet.SubKind.TEMP_VAR_EXPRESSION_SUBKIND;
 import static jdk.jshell.Snippet.SubKind.VAR_VALUE_SUBKIND;
 import static java.util.stream.Collectors.toMap;
 import static jdk.internal.jshell.debug.InternalDebugControl.DBG_COMPA;
@@ -199,6 +208,7 @@
     private boolean isCurrentlyRunningStartup = false;
     private String executionControlSpec = null;
     private EditorSetting editor = BUILT_IN_EDITOR;
+    private int exitCode = 0;
 
     private static final String[] EDITOR_ENV_VARS = new String[] {
         "JSHELLEDITOR", "VISUAL", "EDITOR"};
@@ -215,6 +225,7 @@
 
     static final Pattern BUILTIN_FILE_PATTERN = Pattern.compile("\\w+");
     static final String BUILTIN_FILE_PATH_FORMAT = "/jdk/jshell/tool/resources/%s.jsh";
+    static final String INT_PREFIX = "int $$exit$$ = ";
 
     // match anything followed by whitespace
     private static final Pattern OPTION_PRE_PATTERN =
@@ -360,6 +371,7 @@
                             .stream()
                             .collect(joining(", ")));
                 }
+                exitCode = 1;
                 return null;
             }
         }
@@ -420,7 +432,12 @@
                     .collect(toList())
             );
 
-            return failed ? null : opts;
+            if (failed) {
+                exitCode = 1;
+                return null;
+            } else {
+                return opts;
+            }
         }
 
         void addOptions(OptionKind kind, Collection<String> vals) {
@@ -533,6 +550,7 @@
                     (options.has(argS) ? 1 : 0) +
                     (options.has(argV) ? 1 : 0)) > 1) {
                 msg("jshell.err.opt.feedback.one");
+                exitCode = 1;
                 return null;
             } else if (options.has(argFeedback)) {
                 feedbackMode = options.valueOf(argFeedback);
@@ -547,10 +565,12 @@
                 List<String> sts = options.valuesOf(argStart);
                 if (options.has("no-startup")) {
                     msg("jshell.err.opt.startup.conflict");
+                    exitCode = 1;
                     return null;
                 }
                 initialStartup = Startup.fromFileList(sts, "--startup", new InitMessageHandler());
                 if (initialStartup == null) {
+                    exitCode = 1;
                     return null;
                 }
             } else if (options.has(argNoStart)) {
@@ -861,13 +881,15 @@
      *
      * @param args the command-line arguments
      * @throws Exception catastrophic fatal exception
+     * @return the exit code
      */
-    public void start(String[] args) throws Exception {
+    public int start(String[] args) throws Exception {
         OptionParserCommandLine commandLineArgs = new OptionParserCommandLine();
         options = commandLineArgs.parse(args);
         if (options == null) {
-            // Abort
-            return;
+            // A null means end immediately, this may be an error or because
+            // of options like --version.  Exit code has been set.
+            return exitCode;
         }
         startup = commandLineArgs.startup();
         // initialize editor settings
@@ -879,7 +901,7 @@
             // Display just the cause (not a exception backtrace)
             cmderr.println(ex.getMessage());
             //abort
-            return;
+            return 1;
         }
         // Read replay history from last jshell session into previous history
         replayableHistoryPrevious = ReplayableHistory.fromPrevious(prefs);
@@ -887,7 +909,7 @@
         for (String loadFile : commandLineArgs.nonOptions()) {
             if (!runFile(loadFile, "jshell")) {
                 // Load file failed -- abort
-                return;
+                return 1;
             }
         }
         // if we survived that...
@@ -930,6 +952,7 @@
             }
         }
         closeState();
+        return exitCode;
     }
 
     private EditorSetting configEditor() {
@@ -1067,6 +1090,7 @@
             // The feedback mode to use was specified on the command line, use it
             if (!setFeedback(initmh, new ArgTokenizer("--feedback", initMode))) {
                 regenerateOnDeath = false;
+                exitCode = 1;
             }
         } else {
             String fb = prefs.get(FEEDBACK_KEY);
@@ -1101,55 +1125,23 @@
 
     /**
      * Main loop
+     *
      * @param in the line input/editing context
      */
     private void run(IOContext in) {
         IOContext oldInput = input;
         input = in;
         try {
-            String incomplete = "";
+            // remaining is the source left after one snippet is evaluated
+            String remaining = "";
             while (live) {
-                String prompt;
-                if (interactive()) {
-                    prompt = testPrompt
-                                    ? incomplete.isEmpty()
-                                            ? "\u0005" //ENQ
-                                            : "\u0006" //ACK
-                                    : incomplete.isEmpty()
-                                            ? feedback.getPrompt(currentNameSpace.tidNext())
-                                            : feedback.getContinuationPrompt(currentNameSpace.tidNext())
-                    ;
-                } else {
-                    prompt = "";
-                }
-                String raw;
-                try {
-                    raw = in.readLine(prompt, incomplete);
-                } catch (InputInterruptedException ex) {
-                    //input interrupted - clearing current state
-                    incomplete = "";
-                    continue;
-                }
-                if (raw == null) {
-                    //EOF
-                    if (in.interactiveOutput()) {
-                        // End after user ctrl-D
-                        regenerateOnDeath = false;
-                    }
-                    break;
-                }
-                String trimmed = trimEnd(raw);
-                if (!trimmed.isEmpty() || !incomplete.isEmpty()) {
-                    String line = incomplete + trimmed;
-
-                    // No commands in the middle of unprocessed source
-                    if (incomplete.isEmpty() && line.startsWith("/") && !line.startsWith("//") && !line.startsWith("/*")) {
-                        processCommand(line.trim());
-                    } else {
-                        incomplete = processSourceCatchingReset(line);
-                    }
-                }
+                // Get a line(s) of input
+                String src = getInput(remaining);
+                // Process the snippet or command, returning the remaining source
+                remaining = processInput(src);
             }
+        } catch (EOFException ex) {
+            // Just exit loop
         } catch (IOException ex) {
             errormsg("jshell.err.unexpected.exception", ex);
         } finally {
@@ -1157,20 +1149,125 @@
         }
     }
 
+    /**
+     * Process an input command or snippet.
+     *
+     * @param src the source to process
+     * @return any remaining input to processed
+     */
+    private String processInput(String src) {
+        if (isCommand(src)) {
+            // It is a command
+            processCommand(src.trim());
+            // No remaining input after a command
+            return "";
+        } else {
+            // It is a snipet. Separate the source from the remaining. Evaluate
+            // the source
+            CompletionInfo an = analysis.analyzeCompletion(src);
+            if (processSourceCatchingReset(trimEnd(an.source()))) {
+                // Snippet was successful use any leftover source
+                return an.remaining();
+            } else {
+                // Snippet failed, throw away any remaining source
+                return "";
+            }
+        }
+    }
+
+    /**
+     * Get the input line (or, if incomplete, lines).
+     *
+     * @param initial leading input (left over after last snippet)
+     * @return the complete input snippet or command
+     * @throws IOException on unexpected I/O error
+     */
+    private String getInput(String initial) throws IOException{
+        String src = initial;
+        while (live) { // loop while incomplete (and live)
+            if (!src.isEmpty()) {
+                // We have some source, see if it is complete, if so, use it
+                String check;
+
+                if (isCommand(src)) {
+                    // A command can only be incomplete if it is a /exit with
+                    // an argument
+                    int sp = src.indexOf(" ");
+                    if (sp < 0) return src;
+                    check = src.substring(sp).trim();
+                    if (check.isEmpty()) return src;
+                    String cmd = src.substring(0, sp);
+                    Command[] match = findCommand(cmd, c -> c.kind.isRealCommand);
+                    if (match.length != 1 || !match[0].command.equals("/exit")) {
+                        // A command with no snippet arg, so no multi-line input
+                        return src;
+                    }
+                } else {
+                    // For a snippet check the whole source
+                    check = src;
+                }
+                Completeness comp = analysis.analyzeCompletion(check).completeness();
+                if (comp.isComplete() || comp == Completeness.EMPTY) {
+                    return src;
+                }
+            }
+            String prompt = interactive()
+                    ? testPrompt
+                            ? src.isEmpty()
+                                    ? "\u0005" //ENQ -- test prompt
+                                    : "\u0006" //ACK -- test continuation prompt
+                            : src.isEmpty()
+                                    ? feedback.getPrompt(currentNameSpace.tidNext())
+                                    : feedback.getContinuationPrompt(currentNameSpace.tidNext())
+                    : "" // Non-interactive -- no prompt
+                    ;
+            String line;
+            try {
+                line = input.readLine(prompt, src);
+            } catch (InputInterruptedException ex) {
+                //input interrupted - clearing current state
+                src = "";
+                continue;
+            }
+            if (line == null) {
+                //EOF
+                if (input.interactiveOutput()) {
+                    // End after user ctrl-D
+                    regenerateOnDeath = false;
+                }
+                throw new EOFException(); // no more input
+            }
+            src = src.isEmpty()
+                    ? line
+                    : src + "\n" + line;
+        }
+        throw new EOFException(); // not longer live
+    }
+
+    private boolean isCommand(String line) {
+        return line.startsWith("/") && !line.startsWith("//") && !line.startsWith("/*");
+    }
+
     private void addToReplayHistory(String s) {
         if (!isCurrentlyRunningStartup) {
             replayableHistory.add(s);
         }
     }
 
-    private String processSourceCatchingReset(String src) {
+    /**
+     * Process a source snippet.
+     *
+     * @param src the snippet source to process
+     * @return true on success, false on failure
+     */
+    private boolean processSourceCatchingReset(String src) {
         try {
             input.beforeUserCode();
             return processSource(src);
         } catch (IllegalStateException ex) {
             hard("Resetting...");
             live = false; // Make double sure
-            return "";
+            return false;
         } finally {
             input.afterUserCode();
         }
@@ -1644,8 +1741,19 @@
                 arg -> cmdImports(),
                 EMPTY_COMPLETION_PROVIDER));
         registerCommand(new Command("/exit",
-                arg -> cmdExit(),
-                EMPTY_COMPLETION_PROVIDER));
+                arg -> cmdExit(arg),
+                (sn, c, a) -> {
+                    if (analysis == null || sn.isEmpty()) {
+                        // No completions if uninitialized or snippet not started
+                        return Collections.emptyList();
+                    } else {
+                        // Give exit code an int context by prefixing the arg
+                        List<Suggestion> suggestions = analysis.completionSuggestions(INT_PREFIX + sn,
+                                INT_PREFIX.length() + c, a);
+                        a[0] -= INT_PREFIX.length();
+                        return suggestions;
+                    }
+                }));
         registerCommand(new Command("/env",
                 arg -> cmdEnv(arg),
                 envCompletion()));
@@ -1728,24 +1836,40 @@
     }
 
     public List<String> commandDocumentation(String code, int cursor, boolean shortDescription) {
-        code = code.substring(0, cursor);
-        int space = code.indexOf(' ');
-        String prefix = space != (-1) ? code.substring(0, space) : code;
+        code = code.substring(0, cursor).replaceAll("\\h+", " ");
+        String stripped = code.replaceFirst("/help ", "");
+        boolean inHelp = !code.equals(stripped);
+        int space = stripped.indexOf(' ');
+        String prefix = space != (-1) ? stripped.substring(0, space) : stripped;
         List<String> result = new ArrayList<>();
 
-        List<Entry<String, Command>> toShow =
-                commands.entrySet()
+        List<Entry<String, String>> toShow;
+
+        if (stripped.matches("/set .*") || stripped.matches("set .*")) {
+            String setSubcommand = stripped.replaceFirst("/?set ([^ ]*)($| .*)", "$1");
+            toShow =
+                Arrays.stream(SET_SUBCOMMANDS)
+                       .filter(s -> s.startsWith(setSubcommand))
+                       .map(s -> new SimpleEntry<>("/set " + s, "help.set." + s))
+                       .collect(Collectors.toList());
+        } else {
+            toShow =
+                commands.values()
                         .stream()
-                        .filter(e -> e.getKey().startsWith(prefix))
-                        .filter(e -> e.getValue().kind.showInHelp)
-                        .sorted((e1, e2) -> e1.getKey().compareTo(e2.getKey()))
+                        .filter(c -> c.command.startsWith(prefix)
+                                     || c.command.substring(1).startsWith(prefix))
+                        .filter(c -> c.kind.showInHelp ||
+                                     (inHelp && c.kind == CommandKind.HELP_SUBJECT))
+                        .sorted((c1, c2) -> c1.command.compareTo(c2.command))
+                        .map(c -> new SimpleEntry<>(c.command, c.helpKey))
                         .collect(Collectors.toList());
-
-        if (toShow.size() == 1) {
-            result.add(getResourceString(toShow.get(0).getValue().helpKey + (shortDescription ? ".summary" : "")));
+        }
+
+        if (toShow.size() == 1 && !inHelp) {
+            result.add(getResourceString(toShow.get(0).getValue() + (shortDescription ? ".summary" : "")));
         } else {
-            for (Entry<String, Command> e : toShow) {
-                result.add(e.getKey() + "\n" +getResourceString(e.getValue().helpKey + (shortDescription ? ".summary" : "")));
+            for (Entry<String, String> e : toShow) {
+                result.add(e.getKey() + "\n" + getResourceString(e.getValue() + (shortDescription ? ".summary" : "")));
             }
         }
 
@@ -2124,10 +2248,83 @@
         return true;
     }
 
-    private boolean cmdExit() {
+    private boolean cmdExit(String arg) {
+        if (!arg.trim().isEmpty()) {
+            debug("Compiling exit: %s", arg);
+            List<SnippetEvent> events = state.eval(arg);
+            for (SnippetEvent e : events) {
+                // Only care about main snippet
+                if (e.causeSnippet() == null) {
+                    Snippet sn = e.snippet();
+
+                    // Show any diagnostics
+                    List<Diag> diagnostics = state.diagnostics(sn).collect(toList());
+                    String source = sn.source();
+                    displayDiagnostics(source, diagnostics);
+
+                    // Show any exceptions
+                    if (e.exception() != null && e.status() != Status.REJECTED) {
+                        if (displayException(e.exception())) {
+                            // Abort: an exception occurred (reported)
+                            return false;
+                        }
+                    }
+
+                    if (e.status() != Status.VALID) {
+                        // Abort: can only use valid snippets, diagnostics have been reported (above)
+                        return false;
+                    }
+                    String typeName;
+                    if (sn.kind() == Kind.EXPRESSION) {
+                        typeName = ((ExpressionSnippet) sn).typeName();
+                    } else if (sn.subKind() == TEMP_VAR_EXPRESSION_SUBKIND) {
+                        typeName = ((VarSnippet) sn).typeName();
+                    } else {
+                        // Abort: not an expression
+                        errormsg("jshell.err.exit.not.expression", arg);
+                        return false;
+                    }
+                    switch (typeName) {
+                        case "int":
+                        case "Integer":
+                        case "byte":
+                        case "Byte":
+                        case "short":
+                        case "Short":
+                            try {
+                                int i = Integer.parseInt(e.value());
+                                /**
+                                addToReplayHistory("/exit " + arg);
+                                replayableHistory.storeHistory(prefs);
+                                closeState();
+                                try {
+                                    input.close();
+                                } catch (Exception exc) {
+                                    // ignore
+                                }
+                                * **/
+                                exitCode = i;
+                                break;
+                            } catch (NumberFormatException exc) {
+                                // Abort: bad value
+                                errormsg("jshell.err.exit.bad.value", arg, e.value());
+                                return false;
+                            }
+                        default:
+                            // Abort: bad type
+                            errormsg("jshell.err.exit.bad.type", arg, typeName);
+                            return false;
+                    }
+                }
+            }
+        }
         regenerateOnDeath = false;
         live = false;
-        fluffmsg("jshell.msg.goodbye");
+        if (exitCode == 0) {
+            fluffmsg("jshell.msg.goodbye");
+        } else {
+            fluffmsg("jshell.msg.goodbye.value", exitCode);
+        }
         return true;
     }
 
@@ -2674,7 +2871,7 @@
                         }
                         String tsrc = trimNewlines(an.source());
                         if (!failed && !currSrcs.contains(tsrc)) {
-                            failed = processCompleteSource(tsrc);
+                            failed = processSource(tsrc);
                         }
                         nextSrcs.add(tsrc);
                         if (an.remaining().isEmpty()) {
@@ -2771,8 +2968,56 @@
         return null;
     }
 
-    // Read a built-in file from resources
-    static String readResource(String name) throws IOException {
+    // Read a built-in file from resources or compute it
+    static String readResource(String name) throws Exception {
+        // Class to compute imports by following requires for a module
+        class ComputeImports {
+            final String base;
+            ModuleFinder finder = ModuleFinder.ofSystem();
+
+            ComputeImports(String base) {
+                this.base = base;
+            }
+
+            Set<ModuleDescriptor> modules() {
+                Set<ModuleDescriptor> closure = new HashSet<>();
+                moduleClosure(finder.find(base), closure);
+                return closure;
+            }
+
+            void moduleClosure(Optional<ModuleReference> omr, Set<ModuleDescriptor> closure) {
+                if (omr.isPresent()) {
+                    ModuleDescriptor mdesc = omr.get().descriptor();
+                    if (closure.add(mdesc)) {
+                        for (ModuleDescriptor.Requires req : mdesc.requires()) {
+                            if (!req.modifiers().contains(ModuleDescriptor.Requires.Modifier.STATIC)) {
+                                moduleClosure(finder.find(req.name()), closure);
+                            }
+                        }
+                    }
+                }
+            }
+
+            Set<String> packages() {
+                return modules().stream().flatMap(md -> md.exports().stream())
+                        .filter(e -> !e.isQualified()).map(Object::toString).collect(Collectors.toSet());
+            }
+
+            String imports() {
+                Set<String> si = packages();
+                String[] ai = si.toArray(new String[si.size()]);
+                Arrays.sort(ai);
+                return Arrays.stream(ai)
+                        .map(p -> String.format("import %s.*;\n", p))
+                        .collect(Collectors.joining());
+            }
+        }
+
+        if (name.equals("JAVASE")) {
+            // The built-in JAVASE is computed as the imports of all the packages in Java SE
+            return new ComputeImports("java.se").imports();
+        }
+
         // Attempt to find the file as a resource
         String spec = String.format(BUILTIN_FILE_PATH_FORMAT, name);
 
@@ -3066,7 +3311,50 @@
                 .collect(toList());
     }
 
-    void displayDiagnostics(String source, Diag diag, List<String> toDisplay) {
+    /**
+     * Print out a snippet exception.
+     *
+     * @param exception the exception to print
+     * @return true on fatal exception
+     */
+    private boolean displayException(Exception exception) {
+        if (exception instanceof EvalException) {
+            printEvalException((EvalException) exception);
+            return true;
+        } else if (exception instanceof UnresolvedReferenceException) {
+            printUnresolvedException((UnresolvedReferenceException) exception);
+            return false;
+        } else {
+            error("Unexpected execution exception: %s", exception);
+            return true;
+        }
+    }
+
+    /**
+     * Display a list of diagnostics.
+     *
+     * @param source the source line with the error/warning
+     * @param diagnostics the diagnostics to display
+     */
+    private void displayDiagnostics(String source, List<Diag> diagnostics) {
+        for (Diag d : diagnostics) {
+            errormsg(d.isError() ? "jshell.msg.error" : "jshell.msg.warning");
+            List<String> disp = new ArrayList<>();
+            displayableDiagnostic(source, d, disp);
+            disp.stream()
+                    .forEach(l -> error("%s", l));
+        }
+    }
+
+    /**
+     * Convert a diagnostic into a list of pretty displayable strings with
+     * source context.
+     *
+     * @param source the source line for the error/warning
+     * @param diag the diagnostic to convert
+     * @param toDisplay a list that the displayable strings are added to
+     */
+    private void displayableDiagnostic(String source, Diag diag, List<String> toDisplay) {
         for (String line : diag.getMessage(null).split("\\r?\\n")) { // TODO: Internationalize
             if (!line.trim().startsWith("location:")) {
                 toDisplay.add(line);
@@ -3117,21 +3405,13 @@
                 diag.getStartPosition(), diag.getEndPosition());
     }
 
-    private String processSource(String srcInput) throws IllegalStateException {
-        while (true) {
-            CompletionInfo an = analysis.analyzeCompletion(srcInput);
-            if (!an.completeness().isComplete()) {
-                return an.remaining();
-            }
-            boolean failed = processCompleteSource(an.source());
-            if (failed || an.remaining().isEmpty()) {
-                return "";
-            }
-            srcInput = an.remaining();
-        }
-    }
-    //where
-    boolean processCompleteSource(String source) throws IllegalStateException {
+    /**
+     * Process a source snippet.
+     *
+     * @param source the input source
+     * @return true if the snippet succeeded
+     */
+    boolean processSource(String source) {
         debug("Compiling: %s", source);
         boolean failed = false;
         boolean isActive = false;
@@ -3152,7 +3432,7 @@
             addToReplayHistory(source);
         }
 
-        return failed;
+        return !failed;
     }
 
     // Handle incoming snippet events -- return true on failure
@@ -3166,23 +3446,11 @@
         String source = sn.source();
         if (ste.causeSnippet() == null) {
             // main event
-            for (Diag d : diagnostics) {
-                errormsg(d.isError()? "jshell.msg.error" : "jshell.msg.warning");
-                List<String> disp = new ArrayList<>();
-                displayDiagnostics(source, d, disp);
-                disp.stream()
-                        .forEach(l -> error("%s", l));
-            }
+            displayDiagnostics(source, diagnostics);
 
             if (ste.status() != Status.REJECTED) {
                 if (ste.exception() != null) {
-                    if (ste.exception() instanceof EvalException) {
-                        printEvalException((EvalException) ste.exception());
-                        return true;
-                    } else if (ste.exception() instanceof UnresolvedReferenceException) {
-                        printUnresolvedException((UnresolvedReferenceException) ste.exception());
-                    } else {
-                        error("Unexpected execution exception: %s", ste.exception());
+                    if (displayException(ste.exception())) {
                         return true;
                     }
                 } else {
@@ -3319,7 +3587,7 @@
             this.value = value;
             this.errorLines = new ArrayList<>();
             for (Diag d : errors) {
-                displayDiagnostics(sn.source(), d, errorLines);
+                displayableDiagnostic(sn.source(), d, errorLines);
             }
             if (resolve) {
                 // resolve needs error lines indented
@@ -3617,6 +3885,7 @@
         scannerIn.close();
     }
 
+    @Override
     public int readUserInput() {
         return -1;
     }
@@ -3648,6 +3917,7 @@
     public void close() {
     }
 
+    @Override
     public int readUserInput() {
         return -1;
     }
--- a/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellToolBuilder.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellToolBuilder.java	Mon Nov 27 17:04:45 2017 +0000
@@ -229,7 +229,8 @@
     /**
      * Run an instance of the Java shell tool as configured by the other methods
      * in this interface.  This call is not destructive, more than one call of
-     * this method may be made from a configured builder.
+     * this method may be made from a configured builder. The  exit code from
+     * the Java shell tool is ignored.
      *
      * @param arguments the command-line arguments (including options), if any
      * @throws Exception an unexpected fatal exception
@@ -240,6 +241,20 @@
     }
 
     /**
+     * Run an instance of the Java shell tool as configured by the other methods
+     * in this interface.  This call is not destructive, more than one call of
+     * this method may be made from a configured builder.
+     *
+     * @param arguments the command-line arguments (including options), if any
+     * @throws Exception an unexpected fatal exception
+     * @return the exit code
+     */
+    @Override
+    public int start(String... arguments) throws Exception {
+        return rawTool().start(arguments);
+    }
+
+    /**
      * Persistence stored in Preferences.
      */
     private static class PreferencesStorage implements PersistentStorage {
--- a/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellToolProvider.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellToolProvider.java	Mon Nov 27 17:04:45 2017 +0000
@@ -62,7 +62,8 @@
      * @param err start-up errors and execution "standard" error; use System.err
      * if null
      * @param arguments arguments to pass to the tool
-     * @return 0 for success; nonzero otherwise
+     * @return the exit status with which the tool explicitly exited (if any),
+     * otherwise 0 for success or 1 for failure
      * @throws NullPointerException if the array of arguments contains
      * any {@code null} elements.
      */
@@ -85,13 +86,12 @@
                                 ? (PrintStream) err
                                 : new PrintStream(err);
         try {
-            JavaShellToolBuilder
+            return JavaShellToolBuilder
                     .builder()
                     .in(xin, null)
                     .out(xout)
                     .err(xerr)
-                    .run(arguments);
-            return 0;
+                    .start(arguments);
         } catch (Throwable ex) {
             xerr.println(ex.getMessage());
             return 1;
@@ -109,13 +109,14 @@
     }
 
     /**
-     * Launch the tool.
+     * Launch the tool and exit.
      * @param arguments the command-line arguments (including options), if any
      * @throws Exception an unexpected fatal exception
      */
     public static void main(String[] arguments) throws Exception {
-        JavaShellToolBuilder
-                .builder()
-                .run(arguments);
+        System.exit(
+                JavaShellToolBuilder
+                        .builder()
+                        .start(arguments));
     }
 }
--- a/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/resources/l10n.properties	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/resources/l10n.properties	Mon Nov 27 17:04:45 2017 +0000
@@ -108,6 +108,10 @@
 jshell.err.end.snippet.range.less.than.start = End of snippet range less than start: {0} - {1}
 jshell.err.range.requires.id = Snippet ranges require snippet ids: {0}
 
+jshell.err.exit.not.expression = The argument to /exit must be a valid integer expression, it is not an expression: {0}
+jshell.err.exit.bad.type = The argument to /exit must be a valid integer expression. The type is {1} : {0}
+jshell.err.exit.bad.value = The argument to /exit has bad value is {1} : {0}
+
 jshell.err.drop.arg =\
 In the /drop argument, please specify an import, variable, method, or class to drop.\n\
 Specify by id or name. Use /list to see ids. Use /reset to reset all state.
@@ -115,6 +119,7 @@
 jshell.msg.native.method = Native Method
 jshell.msg.unknown.source = Unknown Source
 jshell.msg.goodbye = Goodbye
+jshell.msg.goodbye.value = Goodbye ({0})
 
 jshell.msg.help.for.help = Type /help for help.
 
@@ -378,10 +383,17 @@
 List the current active jshell imports.
 
 help.exit.summary = exit jshell
-help.exit.args =
+help.exit.args =[<integer-expression-snippet>]
 help.exit =\
 Leave the jshell tool.  No work is saved.\n\
-Save any work before using this command
+Save any work before using this command\n\
+\n\
+/exit\n\t\
+    Leave the jshell tool.  The exit status is zero.\n\n\
+/exit <integer-expression-snippet>\n\t\
+    Evaluate the snippet.  If the snippet fails or is not an integer expression,\n\t\
+    display the error.  Otherwise leave the jshell tool with the\n\t\
+    value of the expression as the exit status
 
 help.reset.summary = reset jshell
 help.reset.args = \
@@ -643,6 +655,9 @@
 /set mode -retain\n\n\
 See these commands for more detail -- for example /help /set editor
 
+help.set.format.summary = \
+Set the format for reporting a snippet event.
+
 help.set.format = \
 Set the format for reporting a snippet event:\n\
 \n\t\
@@ -730,6 +745,9 @@
 /set format mymode\n\
 shows the format settings for the mode mymode\n
 
+help.set.truncation.summary = \
+Set the max length of a displayed value.
+
 help.set.truncation = \
 Set the max length of a displayed value:\n\
 \n\t\
@@ -770,6 +788,9 @@
 /set truncation mymode\n\
 shows the truncation settings for the mode mymode\n
 
+help.set.feedback.summary = \
+Set the feedback mode describing displayed feedback for entered snippets and commands.
+
 help.set.feedback = \
 Set the feedback mode describing displayed feedback for entered snippets and commands:\n\
 \n\t\
@@ -792,6 +813,9 @@
 \n\
 The form without <mode> or -retain displays the current feedback mode and available modes.\n
 
+help.set.mode.summary = \
+Create a user-defined feedback mode, optionally copying from an existing mode.
+
 help.set.mode = \
 Create a user-defined feedback mode, optionally copying from an existing mode:\n\
 \n\t\
@@ -844,6 +868,9 @@
 \n\
 shows the mode, prompt, format, and truncation settings for the mode mymode
 
+help.set.prompt.summary = \
+Set the prompts.
+
 help.set.prompt = \
 Set the prompts.  Both the normal prompt and the continuation-prompt must be set:\n\
 \n\t\
@@ -865,6 +892,9 @@
 /set prompt mymode\n\
 shows the prompts set for the mode mymode\n
 
+help.set.editor.summary =\
+Specify the command to launch for the /edit command.
+
 help.set.editor =\
 Specify the command to launch for the /edit command:\n\
 \n\t\
@@ -906,6 +936,9 @@
 \n\
 The form without <command> or options shows the editor setting.\n
 
+help.set.start.summary =\
+Set the start-up configuration.
+
 help.set.start =\
 Set the start-up configuration -- a sequence of snippets and commands read at start-up:\n\
 \n\t\
--- a/src/jdk.jshell/share/classes/jdk/jshell/tool/JavaShellToolBuilder.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/jdk.jshell/share/classes/jdk/jshell/tool/JavaShellToolBuilder.java	Mon Nov 27 17:04:45 2017 +0000
@@ -186,10 +186,29 @@
     /**
      * Run an instance of the Java shell tool as configured by the other methods
      * in this interface.  This call is not destructive, more than one call of
-     * this method may be made from a configured builder.
+     * this method may be made from a configured builder. The  exit code from
+     * the Java shell tool is ignored.
      *
      * @param arguments the command-line arguments (including options), if any
      * @throws Exception an unexpected fatal exception
      */
     void run(String... arguments) throws Exception;
+
+    /**
+     * Run an instance of the Java shell tool as configured by the other methods
+     * in this interface.  This call is not destructive, more than one call of
+     * this method may be made from a configured builder.
+     *
+     * @implSpec The default implementation always returns zero. Implementations
+     * of this interface should override this method, returning the exit status.
+     *
+     * @param arguments the command-line arguments (including options), if any
+     * @throws Exception an unexpected fatal exception
+     * @return the exit status with which the tool explicitly exited (if any),
+     * otherwise 0 for success or 1 for failure
+     */
+    default int start(String... arguments) throws Exception {
+        run(arguments);
+        return 0;
+    }
 }
--- a/src/jdk.jshell/share/classes/jdk/jshell/tool/package-info.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/jdk.jshell/share/classes/jdk/jshell/tool/package-info.java	Mon Nov 27 17:04:45 2017 +0000
@@ -28,23 +28,23 @@
  * Allows configuration of the tool before launching. A builder is used
  * to configure and launch the tool.
  * <p>
- * At the simplest, a builder is retrieved, and the builder is used to run the
+ * At the simplest, a builder is retrieved, and the builder is used to start the
  * tool:
  * <pre>
  * {@code
  *       JavaShellToolBuilder
  *             .builder()
- *             .run();
+ *             .start();
  * }
  * </pre>
- * The builder can be configured and the run can have arguments:
+ * The builder can be configured and the start can have arguments:
  * <pre>
  * {@code
  *       JavaShellToolBuilder
  *             .builder()
  *             .out(myCommandPrintStream, myOutputPrintStream)
  *             .locale(Locale.CANADA)
- *             .run("--feedback", "silent", "MyStart");
+ *             .start("--feedback", "silent", "MyStart");
  * }
  * </pre>
  *
--- a/src/jdk.jshell/share/classes/jdk/jshell/tool/resources/JAVASE.jsh	Fri Nov 24 17:19:47 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,173 +0,0 @@
-import java.applet.*;
-import java.awt.*;
-import java.awt.color.*;
-import java.awt.datatransfer.*;
-import java.awt.desktop.*;
-import java.awt.dnd.*;
-import java.awt.event.*;
-import java.awt.font.*;
-import java.awt.geom.*;
-import java.awt.im.*;
-import java.awt.im.spi.*;
-import java.awt.image.*;
-import java.awt.image.renderable.*;
-import java.awt.print.*;
-import java.beans.*;
-import java.beans.beancontext.*;
-import java.io.*;
-import java.lang.*;
-import java.lang.annotation.*;
-import java.lang.instrument.*;
-import java.lang.invoke.*;
-import java.lang.management.*;
-import java.lang.module.*;
-import java.lang.ref.*;
-import java.lang.reflect.*;
-import java.math.*;
-import java.net.*;
-import java.net.spi.*;
-import java.nio.*;
-import java.nio.channels.*;
-import java.nio.channels.spi.*;
-import java.nio.charset.*;
-import java.nio.charset.spi.*;
-import java.nio.file.*;
-import java.nio.file.attribute.*;
-import java.nio.file.spi.*;
-import java.rmi.*;
-import java.rmi.activation.*;
-import java.rmi.dgc.*;
-import java.rmi.registry.*;
-import java.rmi.server.*;
-import java.security.*;
-import java.security.acl.*;
-import java.security.cert.*;
-import java.security.interfaces.*;
-import java.security.spec.*;
-import java.sql.*;
-import java.text.*;
-import java.text.spi.*;
-import java.time.*;
-import java.time.chrono.*;
-import java.time.format.*;
-import java.time.temporal.*;
-import java.time.zone.*;
-import java.util.*;
-import java.util.concurrent.*;
-import java.util.concurrent.atomic.*;
-import java.util.concurrent.locks.*;
-import java.util.function.*;
-import java.util.jar.*;
-import java.util.logging.*;
-import java.util.prefs.*;
-import java.util.regex.*;
-import java.util.spi.*;
-import java.util.stream.*;
-import java.util.zip.*;
-import javax.accessibility.*;
-import javax.annotation.processing.*;
-import javax.crypto.*;
-import javax.crypto.interfaces.*;
-import javax.crypto.spec.*;
-import javax.imageio.*;
-import javax.imageio.event.*;
-import javax.imageio.metadata.*;
-import javax.imageio.plugins.bmp.*;
-import javax.imageio.plugins.jpeg.*;
-import javax.imageio.plugins.tiff.*;
-import javax.imageio.spi.*;
-import javax.imageio.stream.*;
-import javax.lang.model.*;
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-import javax.lang.model.util.*;
-import javax.management.*;
-import javax.management.loading.*;
-import javax.management.modelmbean.*;
-import javax.management.monitor.*;
-import javax.management.openmbean.*;
-import javax.management.relation.*;
-import javax.management.remote.*;
-import javax.management.remote.rmi.*;
-import javax.management.timer.*;
-import javax.naming.*;
-import javax.naming.directory.*;
-import javax.naming.event.*;
-import javax.naming.ldap.*;
-import javax.naming.spi.*;
-import javax.net.*;
-import javax.net.ssl.*;
-import javax.print.*;
-import javax.print.attribute.*;
-import javax.print.attribute.standard.*;
-import javax.print.event.*;
-import javax.rmi.ssl.*;
-import javax.script.*;
-import javax.security.auth.*;
-import javax.security.auth.callback.*;
-import javax.security.auth.kerberos.*;
-import javax.security.auth.login.*;
-import javax.security.auth.spi.*;
-import javax.security.auth.x500.*;
-import javax.security.cert.*;
-import javax.security.sasl.*;
-import javax.sound.midi.*;
-import javax.sound.midi.spi.*;
-import javax.sound.sampled.*;
-import javax.sound.sampled.spi.*;
-import javax.sql.*;
-import javax.sql.rowset.*;
-import javax.sql.rowset.serial.*;
-import javax.sql.rowset.spi.*;
-import javax.swing.*;
-import javax.swing.border.*;
-import javax.swing.colorchooser.*;
-import javax.swing.event.*;
-import javax.swing.filechooser.*;
-import javax.swing.plaf.*;
-import javax.swing.plaf.basic.*;
-import javax.swing.plaf.metal.*;
-import javax.swing.plaf.multi.*;
-import javax.swing.plaf.nimbus.*;
-import javax.swing.plaf.synth.*;
-import javax.swing.table.*;
-import javax.swing.text.*;
-import javax.swing.text.html.*;
-import javax.swing.text.html.parser.*;
-import javax.swing.text.rtf.*;
-import javax.swing.tree.*;
-import javax.swing.undo.*;
-import javax.tools.*;
-import javax.transaction.xa.*;
-import javax.xml.*;
-import javax.xml.catalog.*;
-import javax.xml.crypto.*;
-import javax.xml.crypto.dom.*;
-import javax.xml.crypto.dsig.*;
-import javax.xml.crypto.dsig.dom.*;
-import javax.xml.crypto.dsig.keyinfo.*;
-import javax.xml.crypto.dsig.spec.*;
-import javax.xml.datatype.*;
-import javax.xml.namespace.*;
-import javax.xml.parsers.*;
-import javax.xml.stream.*;
-import javax.xml.stream.events.*;
-import javax.xml.stream.util.*;
-import javax.xml.transform.*;
-import javax.xml.transform.dom.*;
-import javax.xml.transform.sax.*;
-import javax.xml.transform.stax.*;
-import javax.xml.transform.stream.*;
-import javax.xml.validation.*;
-import javax.xml.xpath.*;
-import org.ietf.jgss.*;
-import org.w3c.dom.*;
-import org.w3c.dom.bootstrap.*;
-import org.w3c.dom.events.*;
-import org.w3c.dom.ls.*;
-import org.w3c.dom.ranges.*;
-import org.w3c.dom.traversal.*;
-import org.w3c.dom.views.*;
-import org.xml.sax.*;
-import org.xml.sax.ext.*;
-import org.xml.sax.helpers.*;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.scripting.nashorn.shell/share/classes/jdk/nashorn/tools/jjs/JavacPackagesHelper.java	Mon Nov 27 17:04:45 2017 +0000
@@ -0,0 +1,160 @@
+/*
+ * Copyright (c) 2017, 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+
+package jdk.nashorn.tools.jjs;
+
+import java.io.IOException;
+import java.io.File;
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import javax.tools.JavaCompiler;
+import javax.tools.JavaFileManager.Location;
+import javax.tools.JavaFileObject;
+import javax.tools.StandardJavaFileManager;
+import javax.tools.StandardLocation;
+import javax.tools.ToolProvider;
+import jdk.nashorn.internal.runtime.Context;
+
+/**
+ * A javac package helper that uses javac to complete package names.
+ */
+final class JavacPackagesHelper extends PackagesHelper {
+    // JavaCompiler may be null on certain platforms (eg. JRE)
+    private static final JavaCompiler compiler;
+    static {
+        // Use javac only if security manager is not around!
+        compiler = System.getSecurityManager() == null? ToolProvider.getSystemJavaCompiler() : null;
+    }
+
+    /**
+     * Is this class available?
+     *
+     * @return true if javac is available
+     */
+    static boolean isAvailable() {
+        return compiler != null;
+    }
+
+    private final boolean modulePathSet;
+    private final StandardJavaFileManager fm;
+    private final Set<JavaFileObject.Kind> fileKinds;
+
+    /**
+     * Construct a new JavacPackagesHelper.
+     *
+     * @param context the current Nashorn Context
+     */
+    JavacPackagesHelper(final Context context) throws IOException {
+        super(context);
+        final String modulePath = context.getEnv()._module_path;
+        this.modulePathSet = modulePath != null && !modulePath.isEmpty();
+        if (isAvailable()) {
+            final String classPath = context.getEnv()._classpath;
+            fm = compiler.getStandardFileManager(null, null, null);
+            fileKinds = EnumSet.of(JavaFileObject.Kind.CLASS);
+
+            if (this.modulePathSet) {
+                fm.setLocation(StandardLocation.MODULE_PATH, getFiles(modulePath));
+            }
+
+            if (classPath != null && !classPath.isEmpty()) {
+                fm.setLocation(StandardLocation.CLASS_PATH, getFiles(classPath));
+            } else {
+                // no classpath set. Make sure that it is empty and not any default like "."
+                fm.setLocation(StandardLocation.CLASS_PATH, Collections.<File>emptyList());
+            }
+        } else {
+            // javac is not available - caller should have checked!
+            throw new IllegalStateException("JavacPackagesHelper is not available!");
+        }
+    }
+
+
+    @Override
+    void close() throws IOException {
+        if (fm != null) {
+            fm.close();
+        }
+    }
+
+    @Override
+    Set<String> listPackage(final String pkg) throws IOException {
+        final Set<String> props = new HashSet<>();
+        listPackage(StandardLocation.PLATFORM_CLASS_PATH, pkg, props);
+        if (this.modulePathSet) {
+            for (Set<Location> locs : fm.listLocationsForModules(StandardLocation.MODULE_PATH)) {
+                for (Location loc : locs) {
+                    listPackage(loc, pkg, props);
+                }
+            }
+        }
+        listPackage(StandardLocation.CLASS_PATH, pkg, props);
+        return props;
+    }
+
+    private void listPackage(final Location loc, final String pkg, final Set<String> props)
+            throws IOException {
+        for (JavaFileObject file : fm.list(loc, pkg, fileKinds, true)) {
+            final String binaryName = fm.inferBinaryName(loc, file);
+            // does not start with the given package prefix
+            if (!binaryName.startsWith(pkg + ".")) {
+                continue;
+            }
+
+            final int nextDot = binaryName.indexOf('.', pkg.length() + 1);
+            final int start = pkg.length() + 1;
+
+            if (nextDot != -1) {
+                // subpackage - eg. "regex" for "java.util"
+                final String pkgName = binaryName.substring(start, nextDot);
+                if (isPackageAccessible(binaryName.substring(0, nextDot))) {
+                    props.add(binaryName.substring(start, nextDot));
+                }
+            } else {
+                // class - filter out nested, inner, anonymous, local classes.
+                // Dynalink supported public nested classes as properties of
+                // StaticClass object anyway. We don't want to expose those
+                // "$" internal names as properties of package object.
+
+                final String clsName = binaryName.substring(start);
+                if (clsName.indexOf('$') == -1 && isClassAccessible(binaryName)) {
+                    props.add(clsName);
+                }
+            }
+        }
+    }
+
+    // return list of File objects for the given class path
+    private static List<File> getFiles(final String classPath) {
+        return Stream.of(classPath.split(File.pathSeparator))
+                    .map(File::new)
+                    .collect(Collectors.toList());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.scripting.nashorn.shell/share/classes/jdk/nashorn/tools/jjs/JrtPackagesHelper.java	Mon Nov 27 17:04:45 2017 +0000
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2017, 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+
+package jdk.nashorn.tools.jjs;
+
+import java.io.IOException;
+import java.net.URI;
+import java.nio.file.DirectoryStream;
+import java.nio.file.Files;
+import java.nio.file.FileSystem;
+import java.nio.file.FileSystems;
+import java.nio.file.Path;
+import java.util.HashSet;
+import java.util.Set;
+import jdk.nashorn.internal.runtime.Context;
+
+/**
+ * A java packages helper that uses jrt file system.
+ */
+final class JrtPackagesHelper extends PackagesHelper {
+    private final FileSystem jrtfs;
+
+    /**
+     * Construct a new JrtPackagesHelper.
+     *
+     * @param context the current Nashorn Context
+     */
+    JrtPackagesHelper(final Context context) throws IOException {
+        super(context);
+        jrtfs = FileSystems.getFileSystem(URI.create("jrt:/"));
+    }
+
+    @Override
+    void close() throws IOException {
+    }
+
+    @Override
+    Set<String> listPackage(final String pkg) throws IOException {
+        final Set<String> props = new HashSet<>();
+        // look for the /packages/<package_name> directory
+        Path pkgDir = jrtfs.getPath("/packages/" + pkg);
+        if (Files.exists(pkgDir)) {
+            String pkgSlashName = pkg.replace('.', '/');
+            try (DirectoryStream<Path> ds = Files.newDirectoryStream(pkgDir)) {
+                // it has module links under which this package occurs
+                for (Path mod : ds) {
+                    // get the package directory under /modules
+                    Path pkgUnderMod = jrtfs.getPath(mod.toString() + "/" + pkgSlashName);
+                    try (DirectoryStream<Path> ds2 = Files.newDirectoryStream(pkgUnderMod)) {
+                        for (Path p : ds2) {
+                            String str = p.getFileName().toString();
+                            // get rid of ".class", if any
+                            if (str.endsWith(".class")) {
+                                final String clsName = str.substring(0, str.length() - ".class".length());
+                                if (clsName.indexOf('$') == -1 && isClassAccessible(pkg + "." + clsName)) {
+                                    props.add(str);
+                                }
+                            } else if (isPackageAccessible(pkg + "." + str)) {
+                                props.add(str);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        return props;
+    }
+}
--- a/src/jdk.scripting.nashorn.shell/share/classes/jdk/nashorn/tools/jjs/Main.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/jdk.scripting.nashorn.shell/share/classes/jdk/nashorn/tools/jjs/Main.java	Mon Nov 27 17:04:45 2017 +0000
@@ -296,10 +296,10 @@
         }
     }
 
-    private static String JAVADOC_BASE = "https://docs.oracle.com/javase/9/docs/api/";
+    private static String JAVADOC_BASE = "https://docs.oracle.com/javase/%d/docs/api/";
     private static void openBrowserForJavadoc(ScriptFunction browse, String relativeUrl) {
         try {
-            final URI uri = new URI(JAVADOC_BASE + relativeUrl);
+            final URI uri = new URI(String.format(JAVADOC_BASE, Runtime.version().major()) + relativeUrl);
             ScriptRuntime.apply(browse, null, uri);
         } catch (Exception ignored) {
         }
--- a/src/jdk.scripting.nashorn.shell/share/classes/jdk/nashorn/tools/jjs/PackagesHelper.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/jdk.scripting.nashorn.shell/share/classes/jdk/nashorn/tools/jjs/PackagesHelper.java	Mon Nov 27 17:04:45 2017 +0000
@@ -27,58 +27,21 @@
 
 import java.lang.reflect.Modifier;
 import java.io.IOException;
-import java.io.File;
-import java.net.URI;
-import java.nio.file.DirectoryStream;
-import java.nio.file.Files;
-import java.nio.file.FileSystem;
-import java.nio.file.FileSystems;
-import java.nio.file.Path;
 import java.util.ArrayList;
 import java.util.Collections;
-import java.util.EnumSet;
-import java.util.HashSet;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-import javax.tools.JavaCompiler;
-import javax.tools.JavaFileManager.Location;
-import javax.tools.JavaFileObject;
-import javax.tools.StandardJavaFileManager;
-import javax.tools.StandardLocation;
-import javax.tools.ToolProvider;
 import jdk.nashorn.internal.runtime.Context;
 
 /**
- * A helper class to compute properties of a Java package object. Properties of
+ * Abstract helper class to compute properties of a Java package object. Properties of
  * package object are (simple) top level class names in that java package and
  * immediate subpackages of that package.
  */
-final class PackagesHelper {
-    // JavaCompiler may be null on certain platforms (eg. JRE)
-    private static final JavaCompiler compiler;
-    static {
-        // Use javac only if security manager is not around!
-        compiler = System.getSecurityManager() == null? ToolProvider.getSystemJavaCompiler() : null;
-    }
-
-    /**
-     * Is javac available?
-     *
-     * @return true if javac is available
-     */
-    private static boolean isJavacAvailable() {
-        return compiler != null;
-    }
-
+abstract class PackagesHelper {
     private final Context context;
-    private final boolean modulePathSet;
-    private final StandardJavaFileManager fm;
-    private final Set<JavaFileObject.Kind> fileKinds;
-    private final FileSystem jrtfs;
 
     /**
      * Construct a new PackagesHelper.
@@ -87,31 +50,10 @@
      */
     PackagesHelper(final Context context) throws IOException {
         this.context = context;
-        final String modulePath = context.getEnv()._module_path;
-        this.modulePathSet = modulePath != null && !modulePath.isEmpty();
-        if (isJavacAvailable()) {
-            final String classPath = context.getEnv()._classpath;
-            fm = compiler.getStandardFileManager(null, null, null);
-            fileKinds = EnumSet.of(JavaFileObject.Kind.CLASS);
-
-            if (this.modulePathSet) {
-                fm.setLocation(StandardLocation.MODULE_PATH, getFiles(modulePath));
-            }
+    }
 
-            if (classPath != null && !classPath.isEmpty()) {
-                fm.setLocation(StandardLocation.CLASS_PATH, getFiles(classPath));
-            } else {
-                // no classpath set. Make sure that it is empty and not any default like "."
-                fm.setLocation(StandardLocation.CLASS_PATH, Collections.<File>emptyList());
-            }
-            jrtfs = null;
-        } else {
-            // javac is not available - directly use jrt fs
-            // to support at least platform classes.
-            fm = null;
-            fileKinds = null;
-            jrtfs = FileSystems.getFileSystem(URI.create("jrt:/"));
-        }
+    static PackagesHelper create(final Context context) throws IOException {
+        return isJavacHelperAvailable()? new JavacPackagesHelper(context) : new JrtPackagesHelper(context);
     }
 
     // LRU cache for java package properties lists
@@ -132,7 +74,7 @@
      * @param pkg Java package name or package prefix name
      * @return the list of properties of the given Java package or package prefix
      */
-    List<String> getPackageProperties(final String pkg) {
+    final List<String> getPackageProperties(final String pkg) {
         // check the cache first
         if (propsCache.containsKey(pkg)) {
             return propsCache.get(pkg);
@@ -152,95 +94,20 @@
         }
     }
 
-    public void close() throws IOException {
-        if (fm != null) {
-            fm.close();
-        }
-    }
+    /**
+     * Close resources (like file system) used, if any.
+     */
+    abstract void close() throws IOException;
 
-    private Set<String> listPackage(final String pkg) throws IOException {
-        final Set<String> props = new HashSet<>();
-        if (fm != null) {
-            listPackage(StandardLocation.PLATFORM_CLASS_PATH, pkg, props);
-            if (this.modulePathSet) {
-                for (Set<Location> locs : fm.listLocationsForModules(StandardLocation.MODULE_PATH)) {
-                    for (Location loc : locs) {
-                        listPackage(loc, pkg, props);
-                    }
-                }
-            }
-            listPackage(StandardLocation.CLASS_PATH, pkg, props);
-        } else if (jrtfs != null) {
-            // look for the /packages/<package_name> directory
-            Path pkgDir = jrtfs.getPath("/packages/" + pkg);
-            if (Files.exists(pkgDir)) {
-                String pkgSlashName = pkg.replace('.', '/');
-                try (DirectoryStream<Path> ds = Files.newDirectoryStream(pkgDir)) {
-                    // it has module links under which this package occurs
-                    for (Path mod : ds) {
-                        // get the package directory under /modules
-                        Path pkgUnderMod = jrtfs.getPath(mod.toString() + "/" + pkgSlashName);
-                        try (DirectoryStream<Path> ds2 = Files.newDirectoryStream(pkgUnderMod)) {
-                            for (Path p : ds2) {
-                                String str = p.getFileName().toString();
-                                // get rid of ".class", if any
-                                if (str.endsWith(".class")) {
-                                    final String clsName = str.substring(0, str.length() - ".class".length());
-                                    if (clsName.indexOf('$') == -1 && isClassAccessible(pkg + "." + clsName)) {
-                                        props.add(str);
-                                    }
-                                } else if (isPackageAccessible(pkg + "." + str)) {
-                                    props.add(str);
-                                }
-                            }
-                        }
-                    }
-                }
-            }
-        }
-        return props;
-    }
+    /**
+     * Return the set of properties of a given package object.
+     *
+     * @param pkg package start string
+     * @return set of properties of the given Java package
+     */
+    abstract Set<String> listPackage(final String pkg) throws IOException;
 
-    private void listPackage(final Location loc, final String pkg, final Set<String> props)
-            throws IOException {
-        for (JavaFileObject file : fm.list(loc, pkg, fileKinds, true)) {
-            final String binaryName = fm.inferBinaryName(loc, file);
-            // does not start with the given package prefix
-            if (!binaryName.startsWith(pkg + ".")) {
-                continue;
-            }
-
-            final int nextDot = binaryName.indexOf('.', pkg.length() + 1);
-            final int start = pkg.length() + 1;
-
-            if (nextDot != -1) {
-                // subpackage - eg. "regex" for "java.util"
-                final String pkgName = binaryName.substring(start, nextDot);
-                if (isPackageAccessible(binaryName.substring(0, nextDot))) {
-                    props.add(binaryName.substring(start, nextDot));
-                }
-            } else {
-                // class - filter out nested, inner, anonymous, local classes.
-                // Dynalink supported public nested classes as properties of
-                // StaticClass object anyway. We don't want to expose those
-                // "$" internal names as properties of package object.
-
-                final String clsName = binaryName.substring(start);
-                if (clsName.indexOf('$') == -1 && isClassAccessible(binaryName)) {
-                    props.add(clsName);
-                }
-            }
-        }
-    }
-
-    // return list of File objects for the given class path
-    private static List<File> getFiles(final String classPath) {
-        return Stream.of(classPath.split(File.pathSeparator))
-                    .map(File::new)
-                    .collect(Collectors.toList());
-    }
-
-    private boolean isClassAccessible(final String className) {
+    final boolean isClassAccessible(final String className) {
         try {
             final Class<?> clz = context.findClass(className);
             return Modifier.isPublic(clz.getModifiers());
@@ -249,7 +116,7 @@
         return false;
     }
 
-    private boolean isPackageAccessible(final String pkgName) {
+    final boolean isPackageAccessible(final String pkgName) {
         try {
             Context.checkPackageAccess(pkgName);
             return true;
@@ -257,4 +124,20 @@
             return false;
         }
     }
+
+    private static boolean isJavacHelperAvailable() {
+        try {
+            boolean result = JavacPackagesHelper.isAvailable();
+            if (Main.DEBUG && !result) {
+                System.err.println("javac packages helper is not available");
+            }
+            return result;
+        } catch (final LinkageError err) {
+            if (Main.DEBUG) {
+                System.err.println("javac packages helper is not available");
+                err.printStackTrace();
+            }
+            return false;
+        }
+    }
 }
--- a/src/jdk.scripting.nashorn.shell/share/classes/jdk/nashorn/tools/jjs/PropertiesHelper.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/jdk.scripting.nashorn.shell/share/classes/jdk/nashorn/tools/jjs/PropertiesHelper.java	Mon Nov 27 17:04:45 2017 +0000
@@ -57,7 +57,7 @@
      */
     PropertiesHelper(final Context context) {
         try {
-            this.pkgsHelper = new PackagesHelper(context);
+            this.pkgsHelper = PackagesHelper.create(context);
         } catch (final IOException exp) {
             if (Main.DEBUG) {
                 exp.printStackTrace();
--- a/src/jdk.scripting.nashorn.shell/share/classes/module-info.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/jdk.scripting.nashorn.shell/share/classes/module-info.java	Mon Nov 27 17:04:45 2017 +0000
@@ -38,7 +38,7 @@
  * @since 9
  */
 module jdk.scripting.nashorn.shell {
-    requires java.compiler;
+    requires static java.compiler;
     requires jdk.internal.le;
     requires jdk.scripting.nashorn;
     requires jdk.internal.ed;
--- a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeString.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeString.java	Mon Nov 27 17:04:45 2017 +0000
@@ -689,19 +689,17 @@
 
         nativeRegExp.setLastIndex(0);
 
-        int previousLastIndex = 0;
         final List<Object> matches = new ArrayList<>();
 
         Object result;
+        // We follow ECMAScript 6 spec here (checking for empty string instead of previous index)
+        // as the ES5 specification is buggy and causes empty strings to be matched twice.
         while ((result = nativeRegExp.exec(str)) != null) {
-            final int thisIndex = nativeRegExp.getLastIndex();
-            if (thisIndex == previousLastIndex) {
-                nativeRegExp.setLastIndex(thisIndex + 1);
-                previousLastIndex = thisIndex + 1;
-            } else {
-                previousLastIndex = thisIndex;
+            final String matchStr = JSType.toString(((ScriptObject)result).get(0));
+            if (matchStr.isEmpty()) {
+                nativeRegExp.setLastIndex(nativeRegExp.getLastIndex() + 1);
             }
-            matches.add(((ScriptObject)result).get(0));
+            matches.add(matchStr);
         }
 
         if (matches.isEmpty()) {
--- a/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/MessageBundle.properties	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/MessageBundle.properties	Mon Nov 27 17:04:45 2017 +0000
@@ -30,10 +30,10 @@
     Non-existent directory: {0}
 
 VERSION = \
-        schemagen 2.3.0-b170531.0717
+        schemagen 2.3.1-b171012.0423
 
 FULLVERSION = \
-        schemagen full version "2.3.0-b170531.0717"
+        schemagen full version "2.3.1-b171012.0423"
 
 USAGE = \
 Usage: schemagen [-options ...] <java files> \n\
--- a/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/MessageBundle_de.properties	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/MessageBundle_de.properties	Mon Nov 27 17:04:45 2017 +0000
@@ -27,8 +27,8 @@
 
 BASEDIR_DOESNT_EXIST = Nicht vorhandenes Verzeichnis: {0}
 
-VERSION = schemagen 2.3.0-b170531.0717
+VERSION = schemagen 2.3.1-b171012.0423
 
-FULLVERSION = schemagen vollst\u00E4ndige Version "2.3.0-b170531.0717"
+FULLVERSION = schemagen vollst\u00E4ndige Version "2.3.1-b171012.0423"
 
 USAGE = Verwendung: schemagen [-options ...] <java files> \nOptionen: \n\\ \\ \\ \\ -d <path>             : Gibt an, wo die von Prozessor und javac generierten Klassendateien gespeichert werden sollen\n\\ \\ \\ \\ -cp <path>            : Gibt an, wo die vom Benutzer angegebenen Dateien gespeichert sind\n\\ \\ \\ \\ -classpath <path>     : Gibt an, wo die vom Benutzer angegebenen Dateien gespeichert sind\n\\ \\ \\ \\ -encoding <encoding>  : Gibt die Codierung f\u00FCr die Annotationsverarbeitung/den javac-Aufruf an \n\\ \\ \\ \\ -episode <file>       : Generiert Episodendatei f\u00FCr separate Kompilierung\n\\ \\ \\ \\ -version              : Zeigt Versionsinformation an\n\\ \\ \\ \\ -fullversion          : Zeigt vollst\u00E4ndige Versionsinformationen an\n\\ \\ \\ \\ -help                 : Zeigt diese Verwendungsmeldung an
--- a/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/MessageBundle_es.properties	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/MessageBundle_es.properties	Mon Nov 27 17:04:45 2017 +0000
@@ -27,8 +27,8 @@
 
 BASEDIR_DOESNT_EXIST = Directorio no existente: {0}
 
-VERSION = schemagen 2.3.0-b170531.0717
+VERSION = schemagen 2.3.1-b171012.0423
 
-FULLVERSION = versi\u00F3n completa de schemagen "2.3.0-b170531.0717"
+FULLVERSION = versi\u00F3n completa de schemagen "2.3.1-b171012.0423"
 
 USAGE = Sintaxis: schemagen [-options ...] <archivos java> \nOpciones: \n\\ \\ \\ \\ -d <ruta de acceso>             : especifique d\u00F3nde se colocan los archivos de clase generados por javac y el procesador\n\\ \\ \\ \\ -cp <ruta de acceso>            : especifique d\u00F3nde se encuentran los archivos especificados por el usuario\n\\ \\ \\ \\ -encoding <codificaci\u00F3n>  : especifique la codificaci\u00F3n que se va a utilizar para el procesamiento de anotaciones/llamada de javac\n\\ \\ \\ \\ -episode <archivo>       : genera un archivo de episodio para una compilaci\u00F3n diferente\n\\ \\ \\ \\ -version              : muestra la informaci\u00F3n de la versi\u00F3n\n\\ \\ \\ \\ -fullversion          : muestra la informaci\u00F3n completa de la versi\u00F3n\n\\ \\ \\ \\ -help                 : muestra este mensaje de sintaxis
--- a/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/MessageBundle_fr.properties	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/MessageBundle_fr.properties	Mon Nov 27 17:04:45 2017 +0000
@@ -27,8 +27,8 @@
 
 BASEDIR_DOESNT_EXIST = R\u00E9pertoire {0} inexistant
 
-VERSION = schemagen 2.3.0-b170531.0717
+VERSION = schemagen 2.3.1-b171012.0423
 
-FULLVERSION = version compl\u00E8te de schemagen "2.3.0-b170531.0717"
+FULLVERSION = version compl\u00E8te de schemagen "2.3.1-b171012.0423"
 
 USAGE = Syntaxe : schemagen [-options ...] <java files> \nOptions : \n\ \ \ \ -d <path> : indiquez o\u00F9 placer les fichiers de classe g\u00E9n\u00E9r\u00E9s par le processeur et le compilateur javac\n\ \ \ \ -cp <path> : indiquez o\u00F9 trouver les fichiers sp\u00E9cifi\u00E9s par l'utilisateur\n\ \ \ \ -classpath <path> : indiquez o\u00F9 trouver les fichiers sp\u00E9cifi\u00E9s par l'utilisateur\n\ \ \ \ -encoding <encoding> : indiquez l'encodage \u00E0 utiliser pour l'appel de javac/traitement de l'annotation \n\ \ \ \ -episode <file> : g\u00E9n\u00E9rez un fichier d'\u00E9pisode pour la compilation s\u00E9par\u00E9e\n\ \ \ \ -version : affichez les informations de version\n\ \ \ \ -fullversion : affichez les informations compl\u00E8tes de version\n\ \ \ \ -help : affichez ce message de syntaxe
--- a/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/MessageBundle_it.properties	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/MessageBundle_it.properties	Mon Nov 27 17:04:45 2017 +0000
@@ -27,8 +27,8 @@
 
 BASEDIR_DOESNT_EXIST = Directory non esistente: {0}
 
-VERSION = schemagen 2.3.0-b170531.0717
+VERSION = schemagen 2.3.1-b171012.0423
 
-FULLVERSION = versione completa schemagen "2.3.0-b170531.0717"
+FULLVERSION = versione completa schemagen "2.3.1-b171012.0423"
 
 USAGE = Uso: schemagen [-options ...] <java files> \nOpzioni: \n\ \ \ \ -d <path>             : specifica dove posizionare il processore e i file della classe generata javac\n\ \ \ \ -cp <path>            : specifica dove trovare i file specificati dall'utente\n\ \ \ \ -classpath <path>     : specifica dove trovare i file specificati dall'utente\n\ \ \ \ -encoding <encoding>  : specifica la codifica da usare per l'elaborazione dell'annotazione/richiamo javac \n\ \ \ \ -episode <file>       : genera il file di episodio per la compilazione separata\n\ \ \ \ -version              : visualizza le informazioni sulla versione\n\ \ \ \ -fullversion          : visualizza le informazioni sulla versione completa\n\ \ \ \ -help                 : visualizza questo messaggio sull'uso
--- a/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/MessageBundle_ja.properties	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/MessageBundle_ja.properties	Mon Nov 27 17:04:45 2017 +0000
@@ -27,8 +27,8 @@
 
 BASEDIR_DOESNT_EXIST = \u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u304C\u5B58\u5728\u3057\u307E\u305B\u3093: {0}
 
-VERSION = schemagen 2.3.0-b170531.0717
+VERSION = schemagen 2.3.1-b171012.0423
 
-FULLVERSION = schemagen\u30D5\u30EB\u30FB\u30D0\u30FC\u30B8\u30E7\u30F3"2.3.0-b170531.0717"
+FULLVERSION = schemagen\u30D5\u30EB\u30FB\u30D0\u30FC\u30B8\u30E7\u30F3"2.3.1-b171012.0423"
 
 USAGE = \u4F7F\u7528\u65B9\u6CD5: schemagen [-options ...] <java files> \n\u30AA\u30D7\u30B7\u30E7\u30F3: \n\ \ \ \ -d <path>             : \u30D7\u30ED\u30BB\u30C3\u30B5\u304A\u3088\u3073javac\u304C\u751F\u6210\u3057\u305F\u30AF\u30E9\u30B9\u30FB\u30D5\u30A1\u30A4\u30EB\u3092\u7F6E\u304F\u4F4D\u7F6E\u3092\u6307\u5B9A\u3057\u307E\u3059\n\ \ \ \ -cp <path>            : \u30E6\u30FC\u30B6\u30FC\u304C\u6307\u5B9A\u3057\u305F\u30D5\u30A1\u30A4\u30EB\u3092\u691C\u7D22\u3059\u308B\u4F4D\u7F6E\u3092\u6307\u5B9A\u3057\u307E\u3059\n\ \ \ \ -classpath <path>     : \u30E6\u30FC\u30B6\u30FC\u304C\u6307\u5B9A\u3057\u305F\u30D5\u30A1\u30A4\u30EB\u3092\u691C\u7D22\u3059\u308B\u4F4D\u7F6E\u3092\u6307\u5B9A\u3057\u307E\u3059\n\ \ \ \ -encoding <encoding>  : \u6CE8\u91C8\u51E6\u7406/javac\u547C\u51FA\u3057\u306B\u4F7F\u7528\u3059\u308B\u30A8\u30F3\u30B3\u30FC\u30C7\u30A3\u30F3\u30B0\u3092\u6307\u5B9A\u3057\u307E\u3059\n\ \ \ \ -episode <file>       : \u30B3\u30F3\u30D1\u30A4\u30EB\u3054\u3068\u306B\u30A8\u30D4\u30BD\u30FC\u30C9\u30FB\u30D5\u30A1\u30A4\u30EB\u3092\u751F\u6210\u3057\u307E\u3059\n\ \ \ \ -version              : \u30D0\u30FC\u30B8\u30E7\u30F3\u60C5\u5831\u3092\u8868\u793A\u3057\u307E\u3059\n\ \ \ \ -fullversion          : \u30D5\u30EB\u30FB\u30D0\u30FC\u30B8\u30E7\u30F3\u60C5\u5831\u3092\u8868\u793A\u3057\u307E\u3059\n\ \ \ \ -help                 : \u3053\u306E\u4F7F\u7528\u4F8B\u30E1\u30C3\u30BB\u30FC\u30B8\u3092\u8868\u793A\u3057\u307E\u3059
--- a/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/MessageBundle_ko.properties	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/MessageBundle_ko.properties	Mon Nov 27 17:04:45 2017 +0000
@@ -27,8 +27,8 @@
 
 BASEDIR_DOESNT_EXIST = \uC874\uC7AC\uD558\uC9C0 \uC54A\uB294 \uB514\uB809\uD1A0\uB9AC: {0}
 
-VERSION = schemagen 2.3.0-b170531.0717
+VERSION = schemagen 2.3.1-b171012.0423
 
-FULLVERSION = schemagen \uC815\uC2DD \uBC84\uC804 "2.3.0-b170531.0717"
+FULLVERSION = schemagen \uC815\uC2DD \uBC84\uC804 "2.3.1-b171012.0423"
 
 USAGE = \uC0AC\uC6A9\uBC95: schemagen [-options ...] <java files> \n\uC635\uC158: \n\ \ \ \ -d <path>             : \uD504\uB85C\uC138\uC11C \uBC0F javac\uC5D0\uC11C \uC0DD\uC131\uD55C \uD074\uB798\uC2A4 \uD30C\uC77C\uC744 \uBC30\uCE58\uD560 \uC704\uCE58\uB97C \uC9C0\uC815\uD569\uB2C8\uB2E4.\n\ \ \ \ -cp <path>            : \uC0AC\uC6A9\uC790\uAC00 \uC9C0\uC815\uD55C \uD30C\uC77C\uC744 \uCC3E\uC744 \uC704\uCE58\uB97C \uC9C0\uC815\uD569\uB2C8\uB2E4.\n\ \ \ \ -classpath <path>     : \uC0AC\uC6A9\uC790\uAC00 \uC9C0\uC815\uD55C \uD30C\uC77C\uC744 \uCC3E\uC744 \uC704\uCE58\uB97C \uC9C0\uC815\uD569\uB2C8\uB2E4.\n\ \ \ \ -encoding <encoding>  : \uC8FC\uC11D \uCC98\uB9AC/javac \uD638\uCD9C\uC5D0 \uC0AC\uC6A9\uD560 \uC778\uCF54\uB529\uC744 \uC9C0\uC815\uD569\uB2C8\uB2E4. \n\ \ \ \ -episode <file>       : \uBCC4\uB3C4 \uCEF4\uD30C\uC77C\uC744 \uC704\uD574 episode \uD30C\uC77C\uC744 \uC0DD\uC131\uD569\uB2C8\uB2E4.\n\ \ \ \ -version              : \uBC84\uC804 \uC815\uBCF4\uB97C \uD45C\uC2DC\uD569\uB2C8\uB2E4.\n\ \ \ \ -fullversion          : \uC815\uC2DD \uBC84\uC804 \uC815\uBCF4\uB97C \uD45C\uC2DC\uD569\uB2C8\uB2E4.\n\ \ \ \ -help                 : \uC774 \uC0AC\uC6A9\uBC95 \uBA54\uC2DC\uC9C0\uB97C \uD45C\uC2DC\uD569\uB2C8\uB2E4.
--- a/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/MessageBundle_pt_BR.properties	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/MessageBundle_pt_BR.properties	Mon Nov 27 17:04:45 2017 +0000
@@ -27,8 +27,8 @@
 
 BASEDIR_DOESNT_EXIST = Diret\u00F3rio n\u00E3o existente: {0}
 
-VERSION = gera\u00E7\u00E3o do esquema 2.3.0-b170531.0717
+VERSION = gera\u00E7\u00E3o do esquema 2.3.1-b171012.0423
 
-FULLVERSION = vers\u00E3o completa da gera\u00E7\u00E3o do esquema "2.3.0-b170531.0717"
+FULLVERSION = vers\u00E3o completa da gera\u00E7\u00E3o do esquema "2.3.1-b171012.0423"
 
 USAGE = Uso: gera\u00E7\u00E3o do esquema [-options ...] <java files> \nOp\u00E7\u00F5es: \n\\ \\ \\ \\ -d <path>             : especificar onde colocar o processador e os arquivos da classe gerados por javac\n\\ \\ \\ \\ -cp <path>            : especificar onde localizar arquivos especificados pelo usu\u00E1rio\n\\ \\ \\ \\ -classpath <path>     : especificar onde localizar os arquivos especificados pelo usu\u00E1rio\n\\ \\ \\ \\ -encoding <encoding>  : especificar codifica\u00E7\u00E3o a ser usada para processamento de anota\u00E7\u00E3o/chamada javac \n\\ \\ \\ \\ -episode <file>       : gerar arquivo do epis\u00F3dio para compila\u00E7\u00E3o separada\n\\ \\ \\ \\ -version              : exibir informa\u00E7\u00F5es da vers\u00E3o\n\\ \\ \\ \\ -fullversion          : exibir informa\u00E7\u00F5es da vers\u00E3o completa\n\\ \\ \\ \\ -help                 : exibir esta mensagem de uso
--- a/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/MessageBundle_zh_CN.properties	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/MessageBundle_zh_CN.properties	Mon Nov 27 17:04:45 2017 +0000
@@ -27,8 +27,8 @@
 
 BASEDIR_DOESNT_EXIST = \u4E0D\u5B58\u5728\u7684\u76EE\u5F55: {0}
 
-VERSION = schemagen 2.3.0-b170531.0717
+VERSION = schemagen 2.3.1-b171012.0423
 
-FULLVERSION = schemagen \u5B8C\u6574\u7248\u672C "2.3.0-b170531.0717"
+FULLVERSION = schemagen \u5B8C\u6574\u7248\u672C "2.3.1-b171012.0423"
 
 USAGE = \u7528\u6CD5: schemagen [-options ...] <java files> \n\u9009\u9879: \n\ \ \ \ -d <path>             : \u6307\u5B9A\u653E\u7F6E\u5904\u7406\u7A0B\u5E8F\u548C javac \u751F\u6210\u7684\u7C7B\u6587\u4EF6\u7684\u4F4D\u7F6E\n\ \ \ \ -cp <path>            : \u6307\u5B9A\u67E5\u627E\u7528\u6237\u6307\u5B9A\u6587\u4EF6\u7684\u4F4D\u7F6E\n\ \ \ \ -classpath <path>     : \u6307\u5B9A\u67E5\u627E\u7528\u6237\u6307\u5B9A\u6587\u4EF6\u7684\u4F4D\u7F6E\n\ \ \ \ -encoding <encoding>  : \u6307\u5B9A\u7528\u4E8E\u6CE8\u91CA\u5904\u7406/javac \u8C03\u7528\u7684\u7F16\u7801\n\ \ \ \ -episode <file>       : \u751F\u6210\u7247\u6BB5\u6587\u4EF6\u4EE5\u4F9B\u5355\u72EC\u7F16\u8BD1\n\ \ \ \ -version              : \u663E\u793A\u7248\u672C\u4FE1\u606F\n\ \ \ \ -fullversion          : \u663E\u793A\u5B8C\u6574\u7684\u7248\u672C\u4FE1\u606F\n\ \ \ \ -help                 : \u663E\u793A\u6B64\u7528\u6CD5\u6D88\u606F
--- a/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/MessageBundle_zh_TW.properties	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/MessageBundle_zh_TW.properties	Mon Nov 27 17:04:45 2017 +0000
@@ -27,8 +27,8 @@
 
 BASEDIR_DOESNT_EXIST = \u4E0D\u5B58\u5728\u7684\u76EE\u9304: {0}
 
-VERSION = schemagen 2.3.0-b170531.0717
+VERSION = schemagen 2.3.1-b171012.0423
 
-FULLVERSION = schemagen \u5B8C\u6574\u7248\u672C "2.3.0-b170531.0717"
+FULLVERSION = schemagen \u5B8C\u6574\u7248\u672C "2.3.1-b171012.0423"
 
 USAGE = \u7528\u6CD5: schemagen [-options ...] <java files> \n\u9078\u9805: \n\\ \\ \\ \\ -d <path>             : \u6307\u5B9A\u8655\u7406\u5668\u4EE5\u53CA javac \u7522\u751F\u7684\u985E\u5225\u6A94\u6848\u653E\u7F6E\u4F4D\u7F6E\n\\ \\ \\ \\ -cp <path>            : \u6307\u5B9A\u8981\u5C0B\u627E\u4F7F\u7528\u8005\u6307\u5B9A\u6A94\u6848\u7684\u4F4D\u7F6E\n\\ \\ \\ \\ -classpath <path>     : \u6307\u5B9A\u8981\u5C0B\u627E\u4F7F\u7528\u8005\u6307\u5B9A\u6A94\u6848\u7684\u4F4D\u7F6E\n\\ \\ \\ \\ -encoding <encoding>  : \u6307\u5B9A\u8981\u7528\u65BC\u8A3B\u89E3\u8655\u7406/javac \u547C\u53EB\u7684\u7DE8\u78BC \n\\ \\ \\ \\ -episode <file>       : \u7522\u751F\u7368\u7ACB\u7DE8\u8B6F\u7684\u4E8B\u4EF6 (episode) \u6A94\u6848\n\\ \\ \\ \\ -version              : \u986F\u793A\u7248\u672C\u8CC7\u8A0A\n\\ \\ \\ \\ -fullversion          : \u986F\u793A\u5B8C\u6574\u7248\u672C\u8CC7\u8A0A\n\\ \\ \\ \\ -help                 : \u986F\u793A\u6B64\u7528\u6CD5\u8A0A\u606F
--- a/src/jdk.xml.bind/share/classes/com/sun/tools/internal/xjc/MessageBundle.properties	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/jdk.xml.bind/share/classes/com/sun/tools/internal/xjc/MessageBundle.properties	Mon Nov 27 17:04:45 2017 +0000
@@ -23,6 +23,7 @@
 # questions.
 #
 
+
 # Concatenated with Driver.ErrorMessage, Driver.WarningMessage, Driver.InfoMessage (Driver.InfoMessage + exception message + ConsoleErrorReporter.UnknownLocation) if location of the error is not known.
 ConsoleErrorReporter.UnknownLocation = \
         unknown location
@@ -173,23 +174,23 @@
 Driver.FailedToGenerateCode = \
         Failed to produce code.
 
-# DO NOT localize the 2.3.0-b170531.0717 string - it is a token for an mvn <properties filter>
+# DO NOT localize the 2.3.1-b171012.0423 string - it is a token for an mvn <properties filter>
 Driver.FilePrologComment = \
-        This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.3.0-b170531.0717 \n\
-        See <a href="https://jaxb.java.net/">https://jaxb.java.net/</a> \n\
+        This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.3.1-b171012.0423 \n\
+        See <a href="https://javaee.github.io/jaxb-v2/">https://javaee.github.io/jaxb-v2/</a> \n\
         Any modifications to this file will be lost upon recompilation of the source schema. \n\
         Generated on: {0} \n
 
 Driver.Version = \
-        xjc 2.3.0-b170531.0717
+        xjc 2.3.1-b171012.0423
 
 Driver.FullVersion = \
-        xjc full version "2.3.0-b170531.0717"
+        xjc full version "2.3.1-b171012.0423"
 
-Driver.BuildID = 2.3.0-b170531.0717
+Driver.BuildID = 2.3.1-b171012.0423
 
 # for JDK integration - include version in source zip
-jaxb.jdk.version=2.3.0-b170531.0717
+jaxb.jdk.version=2.3.1-b171012.0423
 
 # see java.text.SimpleDateFormat for format syntax
 # DO NOT LOCALIZE, Format should not be changed, English locale is used to transform this string into a real date.
--- a/src/jdk.xml.bind/share/classes/com/sun/tools/internal/xjc/MessageBundle_de.properties	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/jdk.xml.bind/share/classes/com/sun/tools/internal/xjc/MessageBundle_de.properties	Mon Nov 27 17:04:45 2017 +0000
@@ -23,6 +23,7 @@
 # questions.
 #
 
+
 # Concatenated with Driver.ErrorMessage, Driver.WarningMessage, Driver.InfoMessage (Driver.InfoMessage + exception message + ConsoleErrorReporter.UnknownLocation) if location of the error is not known.
 ConsoleErrorReporter.UnknownLocation = unbekanntes Verzeichnis
 
@@ -127,17 +128,17 @@
 
 Driver.FailedToGenerateCode = Code konnte nicht erzeugt werden.
 
-# DO NOT localize the 2.3.0-b170531.0717 string - it is a token for an mvn <properties filter>
-Driver.FilePrologComment = Diese Datei wurde mit der JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.3.0-b170531.0717 generiert \nSiehe <a href="https://jaxb.java.net/">https://jaxb.java.net/</a> \n\u00c4nderungen an dieser Datei gehen bei einer Neukompilierung des Quellschemas verloren. \nGeneriert: {0} \n
+# DO NOT localize the 2.3.1-b171012.0423 string - it is a token for an mvn <properties filter>
+Driver.FilePrologComment = Diese Datei wurde mit der JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.3.1-b171012.0423 generiert \nSiehe <a href="https://javaee.github.io/jaxb-v2/">https://javaee.github.io/jaxb-v2/</a> \n\u00c4nderungen an dieser Datei gehen bei einer Neukompilierung des Quellschemas verloren. \nGeneriert: {0} \n
 
-Driver.Version = xjc 2.3.0-b170531.0717
+Driver.Version = xjc 2.3.1-b171012.0423
 
-Driver.FullVersion = xjc vollst\u00E4ndige Version "2.3.0-b170531.0717"
+Driver.FullVersion = xjc vollst\u00E4ndige Version "2.3.1-b171012.0423"
 
-Driver.BuildID = 2.3.0-b170531.0717
+Driver.BuildID = 2.3.1-b171012.0423
 
 # for JDK integration - include version in source zip
-jaxb.jdk.version=2.3.0-b170531.0717
+jaxb.jdk.version=2.3.1-b171012.0423
 
 # see java.text.SimpleDateFormat for format syntax
 # DO NOT LOCALIZE, Format should not be changed, English locale is used to transform this string into a real date.
--- a/src/jdk.xml.bind/share/classes/com/sun/tools/internal/xjc/MessageBundle_es.properties	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/jdk.xml.bind/share/classes/com/sun/tools/internal/xjc/MessageBundle_es.properties	Mon Nov 27 17:04:45 2017 +0000
@@ -23,6 +23,7 @@
 # questions.
 #
 
+
 # Concatenated with Driver.ErrorMessage, Driver.WarningMessage, Driver.InfoMessage (Driver.InfoMessage + exception message + ConsoleErrorReporter.UnknownLocation) if location of the error is not known.
 ConsoleErrorReporter.UnknownLocation = ubicaci\u00f3n desconocida
 
@@ -127,17 +128,17 @@
 
 Driver.FailedToGenerateCode = Fallo al producir c\u00f3digo.
 
-# DO NOT localize the 2.3.0-b170531.0717 string - it is a token for an mvn <properties filter>
-Driver.FilePrologComment = Este archivo ha sido generado por la arquitectura JavaTM para la implantaci\u00f3n de la referencia de enlace (JAXB) XML v2.3.0-b170531.0717 \nVisite <a href="https://jaxb.java.net/">https://jaxb.java.net/</a> \nTodas las modificaciones realizadas en este archivo se perder\u00e1n si se vuelve a compilar el esquema de origen. \nGenerado el: {0} \n
+# DO NOT localize the 2.3.1-b171012.0423 string - it is a token for an mvn <properties filter>
+Driver.FilePrologComment = Este archivo ha sido generado por la arquitectura JavaTM para la implantaci\u00f3n de la referencia de enlace (JAXB) XML v2.3.1-b171012.0423 \nVisite <a href="https://javaee.github.io/jaxb-v2/">https://javaee.github.io/jaxb-v2/</a> \nTodas las modificaciones realizadas en este archivo se perder\u00e1n si se vuelve a compilar el esquema de origen. \nGenerado el: {0} \n
 
-Driver.Version = xjc 2.3.0-b170531.0717
+Driver.Version = xjc 2.3.1-b171012.0423
 
-Driver.FullVersion = versi\u00F3n completa de xjc "2.3.0-b170531.0717"
+Driver.FullVersion = versi\u00F3n completa de xjc "2.3.1-b171012.0423"
 
-Driver.BuildID = 2.3.0-b170531.0717
+Driver.BuildID = 2.3.1-b171012.0423
 
 # for JDK integration - include version in source zip
-jaxb.jdk.version=2.3.0-b170531.0717
+jaxb.jdk.version=2.3.1-b171012.0423
 
 # see java.text.SimpleDateFormat for format syntax
 # DO NOT LOCALIZE, Format should not be changed, English locale is used to transform this string into a real date.
--- a/src/jdk.xml.bind/share/classes/com/sun/tools/internal/xjc/MessageBundle_fr.properties	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/jdk.xml.bind/share/classes/com/sun/tools/internal/xjc/MessageBundle_fr.properties	Mon Nov 27 17:04:45 2017 +0000
@@ -23,6 +23,7 @@
 # questions.
 #
 
+
 # Concatenated with Driver.ErrorMessage, Driver.WarningMessage, Driver.InfoMessage (Driver.InfoMessage + exception message + ConsoleErrorReporter.UnknownLocation) if location of the error is not known.
 ConsoleErrorReporter.UnknownLocation = emplacement inconnu
 
@@ -131,17 +132,17 @@
 
 Driver.FailedToGenerateCode = Echec de la production du code.
 
-# DO NOT localize the 2.3.0-b170531.0717 string - it is a token for an mvn <properties filter>
-Driver.FilePrologComment = Ce fichier a \u00e9t\u00e9 g\u00e9n\u00e9r\u00e9 par l''impl\u00e9mentation de r\u00e9f\u00e9rence JavaTM Architecture for XML Binding (JAXB), v2.3.0-b170531.0717 \nVoir <a href="https://jaxb.java.net/">https://jaxb.java.net/</a> \nToute modification apport\u00e9e \u00e0 ce fichier sera perdue lors de la recompilation du sch\u00e9ma source. \nG\u00e9n\u00e9r\u00e9 le : {0} \n
+# DO NOT localize the 2.3.1-b171012.0423 string - it is a token for an mvn <properties filter>
+Driver.FilePrologComment = Ce fichier a \u00e9t\u00e9 g\u00e9n\u00e9r\u00e9 par l''impl\u00e9mentation de r\u00e9f\u00e9rence JavaTM Architecture for XML Binding (JAXB), v2.3.1-b171012.0423 \nVoir <a href="https://javaee.github.io/jaxb-v2/">https://javaee.github.io/jaxb-v2/</a> \nToute modification apport\u00e9e \u00e0 ce fichier sera perdue lors de la recompilation du sch\u00e9ma source. \nG\u00e9n\u00e9r\u00e9 le : {0} \n
 
-Driver.Version = xjc 2.3.0-b170531.0717
+Driver.Version = xjc 2.3.1-b171012.0423
 
-Driver.FullVersion = version compl\u00E8te xjc "2.3.0-b170531.0717"
+Driver.FullVersion = version compl\u00E8te xjc "2.3.1-b171012.0423"
 
-Driver.BuildID = 2.3.0-b170531.0717
+Driver.BuildID = 2.3.1-b171012.0423
 
 # for JDK integration - include version in source zip
-jaxb.jdk.version=2.3.0-b170531.0717
+jaxb.jdk.version=2.3.1-b171012.0423
 
 # see java.text.SimpleDateFormat for format syntax
 # DO NOT LOCALIZE, Format should not be changed, English locale is used to transform this string into a real date.
--- a/src/jdk.xml.bind/share/classes/com/sun/tools/internal/xjc/MessageBundle_it.properties	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/jdk.xml.bind/share/classes/com/sun/tools/internal/xjc/MessageBundle_it.properties	Mon Nov 27 17:04:45 2017 +0000
@@ -23,6 +23,7 @@
 # questions.
 #
 
+
 # Concatenated with Driver.ErrorMessage, Driver.WarningMessage, Driver.InfoMessage (Driver.InfoMessage + exception message + ConsoleErrorReporter.UnknownLocation) if location of the error is not known.
 ConsoleErrorReporter.UnknownLocation = posizione sconosciuta
 
@@ -127,17 +128,17 @@
 
 Driver.FailedToGenerateCode = Produzione del codice non riuscita.
 
-# DO NOT localize the 2.3.0-b170531.0717 string - it is a token for an mvn <properties filter>
-Driver.FilePrologComment = Questo file \u00e8 stato generato dall''architettura JavaTM per XML Binding (JAXB) Reference Implementation, v2.3.0-b170531.0717 \nVedere <a href="https://jaxb.java.net/">https://jaxb.java.net/</a> \nQualsiasi modifica a questo file andr\u00e0 persa durante la ricompilazione dello schema di origine. \nGenerato il: {0} \n
+# DO NOT localize the 2.3.1-b171012.0423 string - it is a token for an mvn <properties filter>
+Driver.FilePrologComment = Questo file \u00e8 stato generato dall''architettura JavaTM per XML Binding (JAXB) Reference Implementation, v2.3.1-b171012.0423 \nVedere <a href="https://javaee.github.io/jaxb-v2/">https://javaee.github.io/jaxb-v2/</a> \nQualsiasi modifica a questo file andr\u00e0 persa durante la ricompilazione dello schema di origine. \nGenerato il: {0} \n
 
-Driver.Version = xjc 2.3.0-b170531.0717
+Driver.Version = xjc 2.3.1-b171012.0423
 
-Driver.FullVersion = versione completa xjc "2.3.0-b170531.0717"
+Driver.FullVersion = versione completa xjc "2.3.1-b171012.0423"
 
-Driver.BuildID = 2.3.0-b170531.0717
+Driver.BuildID = 2.3.1-b171012.0423
 
 # for JDK integration - include version in source zip
-jaxb.jdk.version=2.3.0-b170531.0717
+jaxb.jdk.version=2.3.1-b171012.0423
 
 # see java.text.SimpleDateFormat for format syntax
 # DO NOT LOCALIZE, Format should not be changed, English locale is used to transform this string into a real date.
--- a/src/jdk.xml.bind/share/classes/com/sun/tools/internal/xjc/MessageBundle_ja.properties	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/jdk.xml.bind/share/classes/com/sun/tools/internal/xjc/MessageBundle_ja.properties	Mon Nov 27 17:04:45 2017 +0000
@@ -23,6 +23,7 @@
 # questions.
 #
 
+
 # Concatenated with Driver.ErrorMessage, Driver.WarningMessage, Driver.InfoMessage (Driver.InfoMessage + exception message + ConsoleErrorReporter.UnknownLocation) if location of the error is not known.
 ConsoleErrorReporter.UnknownLocation = \u4e0d\u660e\u306a\u5834\u6240
 
@@ -127,17 +128,17 @@
 
 Driver.FailedToGenerateCode = \u30b3\u30fc\u30c9\u306e\u751f\u6210\u306b\u5931\u6557\u3057\u307e\u3057\u305f\u3002
 
-# DO NOT localize the 2.3.0-b170531.0717 string - it is a token for an mvn <properties filter>
-Driver.FilePrologComment = \u3053\u306e\u30d5\u30a1\u30a4\u30eb\u306f\u3001JavaTM Architecture for XML Binding(JAXB) Reference Implementation\u3001v2.3.0-b170531.0717\u306b\u3088\u3063\u3066\u751f\u6210\u3055\u308c\u307e\u3057\u305f \n<a href="https://jaxb.java.net/">https://jaxb.java.net/</a>\u3092\u53c2\u7167\u3057\u3066\u304f\u3060\u3055\u3044 \n\u30bd\u30fc\u30b9\u30fb\u30b9\u30ad\u30fc\u30de\u306e\u518d\u30b3\u30f3\u30d1\u30a4\u30eb\u6642\u306b\u3053\u306e\u30d5\u30a1\u30a4\u30eb\u306e\u5909\u66f4\u306f\u5931\u308f\u308c\u307e\u3059\u3002 \n\u751f\u6210\u65e5: {0} \n
+# DO NOT localize the 2.3.1-b171012.0423 string - it is a token for an mvn <properties filter>
+Driver.FilePrologComment = \u3053\u306e\u30d5\u30a1\u30a4\u30eb\u306f\u3001JavaTM Architecture for XML Binding(JAXB) Reference Implementation\u3001v2.3.1-b171012.0423\u306b\u3088\u3063\u3066\u751f\u6210\u3055\u308c\u307e\u3057\u305f \n<a href="https://javaee.github.io/jaxb-v2/">https://javaee.github.io/jaxb-v2/</a>\u3092\u53c2\u7167\u3057\u3066\u304f\u3060\u3055\u3044 \n\u30bd\u30fc\u30b9\u30fb\u30b9\u30ad\u30fc\u30de\u306e\u518d\u30b3\u30f3\u30d1\u30a4\u30eb\u6642\u306b\u3053\u306e\u30d5\u30a1\u30a4\u30eb\u306e\u5909\u66f4\u306f\u5931\u308f\u308c\u307e\u3059\u3002 \n\u751f\u6210\u65e5: {0} \n
 
-Driver.Version = xjc 2.3.0-b170531.0717
+Driver.Version = xjc 2.3.1-b171012.0423
 
-Driver.FullVersion = xjc\u30D5\u30EB\u30FB\u30D0\u30FC\u30B8\u30E7\u30F3"2.3.0-b170531.0717"
+Driver.FullVersion = xjc\u30D5\u30EB\u30FB\u30D0\u30FC\u30B8\u30E7\u30F3"2.3.1-b171012.0423"
 
-Driver.BuildID = 2.3.0-b170531.0717
+Driver.BuildID = 2.3.1-b171012.0423
 
 # for JDK integration - include version in source zip
-jaxb.jdk.version=2.3.0-b170531.0717
+jaxb.jdk.version=2.3.1-b171012.0423
 
 # see java.text.SimpleDateFormat for format syntax
 # DO NOT LOCALIZE, Format should not be changed, English locale is used to transform this string into a real date.
--- a/src/jdk.xml.bind/share/classes/com/sun/tools/internal/xjc/MessageBundle_ko.properties	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/jdk.xml.bind/share/classes/com/sun/tools/internal/xjc/MessageBundle_ko.properties	Mon Nov 27 17:04:45 2017 +0000
@@ -23,6 +23,7 @@
 # questions.
 #
 
+
 # Concatenated with Driver.ErrorMessage, Driver.WarningMessage, Driver.InfoMessage (Driver.InfoMessage + exception message + ConsoleErrorReporter.UnknownLocation) if location of the error is not known.
 ConsoleErrorReporter.UnknownLocation = \uc54c \uc218 \uc5c6\ub294 \uc704\uce58
 
@@ -127,17 +128,17 @@
 
 Driver.FailedToGenerateCode = \ucf54\ub4dc \uc0dd\uc131\uc744 \uc2e4\ud328\ud588\uc2b5\ub2c8\ub2e4.
 
-# DO NOT localize the 2.3.0-b170531.0717 string - it is a token for an mvn <properties filter>
-Driver.FilePrologComment = \uc774 \ud30c\uc77c\uc740 JAXB(JavaTM Architecture for XML Binding) \ucc38\uc870 \uad6c\ud604 2.3.0-b170531.0717 \ubc84\uc804\uc744 \ud1b5\ud574 \uc0dd\uc131\ub418\uc5c8\uc2b5\ub2c8\ub2e4. \n<a href="https://jaxb.java.net/">https://jaxb.java.net/</a>\ub97c \ucc38\uc870\ud558\uc2ed\uc2dc\uc624. \n\uc774 \ud30c\uc77c\uc744 \uc218\uc815\ud558\uba74 \uc18c\uc2a4 \uc2a4\ud0a4\ub9c8\ub97c \uc7ac\ucef4\ud30c\uc77c\ud560 \ub54c \uc218\uc815 \uc0ac\ud56d\uc774 \uc190\uc2e4\ub429\ub2c8\ub2e4. \n\uc0dd\uc131 \ub0a0\uc9dc: {0} \n
+# DO NOT localize the 2.3.1-b171012.0423 string - it is a token for an mvn <properties filter>
+Driver.FilePrologComment = \uc774 \ud30c\uc77c\uc740 JAXB(JavaTM Architecture for XML Binding) \ucc38\uc870 \uad6c\ud604 2.3.1-b171012.0423 \ubc84\uc804\uc744 \ud1b5\ud574 \uc0dd\uc131\ub418\uc5c8\uc2b5\ub2c8\ub2e4. \n<a href="https://javaee.github.io/jaxb-v2/">https://javaee.github.io/jaxb-v2/</a>\ub97c \ucc38\uc870\ud558\uc2ed\uc2dc\uc624. \n\uc774 \ud30c\uc77c\uc744 \uc218\uc815\ud558\uba74 \uc18c\uc2a4 \uc2a4\ud0a4\ub9c8\ub97c \uc7ac\ucef4\ud30c\uc77c\ud560 \ub54c \uc218\uc815 \uc0ac\ud56d\uc774 \uc190\uc2e4\ub429\ub2c8\ub2e4. \n\uc0dd\uc131 \ub0a0\uc9dc: {0} \n
 
-Driver.Version = XJC 2.3.0-b170531.0717
+Driver.Version = XJC 2.3.1-b171012.0423
 
-Driver.FullVersion = XJC \uC815\uC2DD \uBC84\uC804 "2.3.0-b170531.0717"
+Driver.FullVersion = XJC \uC815\uC2DD \uBC84\uC804 "2.3.1-b171012.0423"
 
-Driver.BuildID = 2.3.0-b170531.0717
+Driver.BuildID = 2.3.1-b171012.0423
 
 # for JDK integration - include version in source zip
-jaxb.jdk.version=2.3.0-b170531.0717
+jaxb.jdk.version=2.3.1-b171012.0423
 
 # see java.text.SimpleDateFormat for format syntax
 # DO NOT LOCALIZE, Format should not be changed, English locale is used to transform this string into a real date.
--- a/src/jdk.xml.bind/share/classes/com/sun/tools/internal/xjc/MessageBundle_pt_BR.properties	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/jdk.xml.bind/share/classes/com/sun/tools/internal/xjc/MessageBundle_pt_BR.properties	Mon Nov 27 17:04:45 2017 +0000
@@ -23,6 +23,7 @@
 # questions.
 #
 
+
 # Concatenated with Driver.ErrorMessage, Driver.WarningMessage, Driver.InfoMessage (Driver.InfoMessage + exception message + ConsoleErrorReporter.UnknownLocation) if location of the error is not known.
 ConsoleErrorReporter.UnknownLocation = localiza\u00e7\u00e3o desconhecida
 
@@ -127,17 +128,17 @@
 
 Driver.FailedToGenerateCode = Falha ao produzir o c\u00f3digo.
 
-# DO NOT localize the 2.3.0-b170531.0717 string - it is a token for an mvn <properties filter>
-Driver.FilePrologComment = Este arquivo foi gerado pela Arquitetura JavaTM para Implementa\u00e7\u00e3o de Refer\u00eancia (JAXB) de Bind XML, v2.3.0-b170531.0717 \nConsulte <a href="https://jaxb.java.net/">https://jaxb.java.net/</a> \nTodas as modifica\u00e7\u00f5es neste arquivo ser\u00e3o perdidas ap\u00f3s a recompila\u00e7\u00e3o do esquema de origem. \nGerado em: {0} \n
+# DO NOT localize the 2.3.1-b171012.0423 string - it is a token for an mvn <properties filter>
+Driver.FilePrologComment = Este arquivo foi gerado pela Arquitetura JavaTM para Implementa\u00e7\u00e3o de Refer\u00eancia (JAXB) de Bind XML, v2.3.1-b171012.0423 \nConsulte <a href="https://javaee.github.io/jaxb-v2/">https://javaee.github.io/jaxb-v2/</a> \nTodas as modifica\u00e7\u00f5es neste arquivo ser\u00e3o perdidas ap\u00f3s a recompila\u00e7\u00e3o do esquema de origem. \nGerado em: {0} \n
 
-Driver.Version = xjc 2.3.0-b170531.0717
+Driver.Version = xjc 2.3.1-b171012.0423
 
-Driver.FullVersion = vers\u00E3o completa de xjc "2.3.0-b170531.0717"
+Driver.FullVersion = vers\u00E3o completa de xjc "2.3.1-b171012.0423"
 
-Driver.BuildID = 2.3.0-b170531.0717
+Driver.BuildID = 2.3.1-b171012.0423
 
 # for JDK integration - include version in source zip
-jaxb.jdk.version=2.3.0-b170531.0717
+jaxb.jdk.version=2.3.1-b171012.0423
 
 # see java.text.SimpleDateFormat for format syntax
 # DO NOT LOCALIZE, Format should not be changed, English locale is used to transform this string into a real date.
--- a/src/jdk.xml.bind/share/classes/com/sun/tools/internal/xjc/MessageBundle_zh_CN.properties	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/jdk.xml.bind/share/classes/com/sun/tools/internal/xjc/MessageBundle_zh_CN.properties	Mon Nov 27 17:04:45 2017 +0000
@@ -23,6 +23,7 @@
 # questions.
 #
 
+
 # Concatenated with Driver.ErrorMessage, Driver.WarningMessage, Driver.InfoMessage (Driver.InfoMessage + exception message + ConsoleErrorReporter.UnknownLocation) if location of the error is not known.
 ConsoleErrorReporter.UnknownLocation = \u672a\u77e5\u4f4d\u7f6e
 
@@ -131,17 +132,17 @@
 
 Driver.FailedToGenerateCode = \u65e0\u6cd5\u751f\u6210\u4ee3\u7801\u3002
 
-# DO NOT localize the 2.3.0-b170531.0717 string - it is a token for an mvn <properties filter>
-Driver.FilePrologComment = \u6b64\u6587\u4ef6\u662f\u7531 JavaTM Architecture for XML Binding (JAXB) \u5f15\u7528\u5b9e\u73b0 v2.3.0-b170531.0717 \u751f\u6210\u7684\n\u8bf7\u8bbf\u95ee <a href="https://jaxb.java.net/">https://jaxb.java.net/</a> \n\u5728\u91cd\u65b0\u7f16\u8bd1\u6e90\u6a21\u5f0f\u65f6, \u5bf9\u6b64\u6587\u4ef6\u7684\u6240\u6709\u4fee\u6539\u90fd\u5c06\u4e22\u5931\u3002\n\u751f\u6210\u65f6\u95f4: {0} \n
+# DO NOT localize the 2.3.1-b171012.0423 string - it is a token for an mvn <properties filter>
+Driver.FilePrologComment = \u6b64\u6587\u4ef6\u662f\u7531 JavaTM Architecture for XML Binding (JAXB) \u5f15\u7528\u5b9e\u73b0 v2.3.1-b171012.0423 \u751f\u6210\u7684\n\u8bf7\u8bbf\u95ee <a href="https://javaee.github.io/jaxb-v2/">https://javaee.github.io/jaxb-v2/</a> \n\u5728\u91cd\u65b0\u7f16\u8bd1\u6e90\u6a21\u5f0f\u65f6, \u5bf9\u6b64\u6587\u4ef6\u7684\u6240\u6709\u4fee\u6539\u90fd\u5c06\u4e22\u5931\u3002\n\u751f\u6210\u65f6\u95f4: {0} \n
 
-Driver.Version = xjc 2.3.0-b170531.0717
+Driver.Version = xjc 2.3.1-b171012.0423
 
-Driver.FullVersion = xjc \u5B8C\u6574\u7248\u672C "2.3.0-b170531.0717"
+Driver.FullVersion = xjc \u5B8C\u6574\u7248\u672C "2.3.1-b171012.0423"
 
-Driver.BuildID = 2.3.0-b170531.0717
+Driver.BuildID = 2.3.1-b171012.0423
 
 # for JDK integration - include version in source zip
-jaxb.jdk.version=2.3.0-b170531.0717
+jaxb.jdk.version=2.3.1-b171012.0423
 
 # see java.text.SimpleDateFormat for format syntax
 # DO NOT LOCALIZE, Format should not be changed, English locale is used to transform this string into a real date.
--- a/src/jdk.xml.bind/share/classes/com/sun/tools/internal/xjc/MessageBundle_zh_TW.properties	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/jdk.xml.bind/share/classes/com/sun/tools/internal/xjc/MessageBundle_zh_TW.properties	Mon Nov 27 17:04:45 2017 +0000
@@ -23,6 +23,7 @@
 # questions.
 #
 
+
 # Concatenated with Driver.ErrorMessage, Driver.WarningMessage, Driver.InfoMessage (Driver.InfoMessage + exception message + ConsoleErrorReporter.UnknownLocation) if location of the error is not known.
 ConsoleErrorReporter.UnknownLocation = \u4e0d\u660e\u7684\u4f4d\u7f6e
 
@@ -127,17 +128,17 @@
 
 Driver.FailedToGenerateCode = \u7121\u6cd5\u7522\u751f\u7a0b\u5f0f\u78bc.
 
-# DO NOT localize the 2.3.0-b170531.0717 string - it is a token for an mvn <properties filter>
-Driver.FilePrologComment = \u6b64\u6a94\u6848\u662f\u7531 JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.3.0-b170531.0717 \u6240\u7522\u751f \n\u8acb\u53c3\u95b1 <a href="https://jaxb.java.net/">https://jaxb.java.net/</a> \n\u4e00\u65e6\u91cd\u65b0\u7de8\u8b6f\u4f86\u6e90\u7db1\u8981, \u5c0d\u6b64\u6a94\u6848\u6240\u505a\u7684\u4efb\u4f55\u4fee\u6539\u90fd\u5c07\u6703\u907a\u5931. \n\u7522\u751f\u6642\u9593: {0} \n
+# DO NOT localize the 2.3.1-b171012.0423 string - it is a token for an mvn <properties filter>
+Driver.FilePrologComment = \u6b64\u6a94\u6848\u662f\u7531 JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.3.1-b171012.0423 \u6240\u7522\u751f \n\u8acb\u53c3\u95b1 <a href="https://javaee.github.io/jaxb-v2/">https://javaee.github.io/jaxb-v2/</a> \n\u4e00\u65e6\u91cd\u65b0\u7de8\u8b6f\u4f86\u6e90\u7db1\u8981, \u5c0d\u6b64\u6a94\u6848\u6240\u505a\u7684\u4efb\u4f55\u4fee\u6539\u90fd\u5c07\u6703\u907a\u5931. \n\u7522\u751f\u6642\u9593: {0} \n
 
-Driver.Version = xjc 2.3.0-b170531.0717
+Driver.Version = xjc 2.3.1-b171012.0423
 
-Driver.FullVersion = xjc \u5B8C\u6574\u7248\u672C "2.3.0-b170531.0717"
+Driver.FullVersion = xjc \u5B8C\u6574\u7248\u672C "2.3.1-b171012.0423"
 
-Driver.BuildID = 2.3.0-b170531.0717
+Driver.BuildID = 2.3.1-b171012.0423
 
 # for JDK integration - include version in source zip
-jaxb.jdk.version=2.3.0-b170531.0717
+jaxb.jdk.version=2.3.1-b171012.0423
 
 # see java.text.SimpleDateFormat for format syntax
 # DO NOT LOCALIZE, Format should not be changed, English locale is used to transform this string into a real date.
--- a/src/jdk.xml.bind/share/classes/com/sun/tools/internal/xjc/reader/xmlschema/bindinfo/BIXSubstitutable.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/jdk.xml.bind/share/classes/com/sun/tools/internal/xjc/reader/xmlschema/bindinfo/BIXSubstitutable.java	Mon Nov 27 17:04:45 2017 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, 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
@@ -34,7 +34,7 @@
  * Forces a non-collapsing behavior to allow extension schemas
  * to perform element substitutions.
  *
- * See https://jaxb.dev.java.net/issues/show_bug.cgi?id=289
+ * See https://github.com/javaee/jaxb-v2/issues/289
  *
  * @author Kohsuke Kawaguchi
  * @since 2.1.1
--- a/src/jdk.xml.ws/share/classes/com/sun/tools/internal/ws/version.properties	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/jdk.xml.ws/share/classes/com/sun/tools/internal/ws/version.properties	Mon Nov 27 17:04:45 2017 +0000
@@ -23,7 +23,8 @@
 # questions.
 #
 
-build-id=2.3.0-SNAPSHOT
-build-version=JAX-WS RI 2.3.0-SNAPSHOT
-major-version=2.3.0
-svn-revision=3012ef421cf43774943c57736dac2207aeea9f07
+
+build-id=2.3.1-SNAPSHOT
+build-version=JAX-WS RI 2.3.1-SNAPSHOT
+major-version=2.3.1
+svn-revision=6a0b290fe358f9de4deeec2d1ec3f6e76afa8005
--- a/src/utils/IdealGraphVisualizer/nbproject/platform.properties	Fri Nov 24 17:19:47 2017 +0000
+++ b/src/utils/IdealGraphVisualizer/nbproject/platform.properties	Mon Nov 27 17:04:45 2017 +0000
@@ -6,7 +6,7 @@
 nbplatform.active.dir=${suite.dir}/nbplatform
 nbplatform.default.netbeans.dest.dir=${suite.dir}/nbplatform
 nbplatform.default.harness.dir=${nbplatform.default.netbeans.dest.dir}/harness
-bootstrap.url=http://deadlock.netbeans.org/hudson/job/nbms-and-javadoc/lastSuccessfulBuild/artifact/nbbuild/netbeans/harness/tasks.jar
+bootstrap.url=http://bits.netbeans.org/dev/nbms-and-javadoc/lastSuccessfulBuild/artifact/nbbuild/netbeans/harness/tasks.jar
 autoupdate.catalog.url=http://updates.netbeans.org/netbeans/updates/7.4/uc/final/distribution/catalog.xml.gz
 suite.dir=${basedir}
 nbplatform.active=default
--- a/test/hotspot/jtreg/Makefile	Fri Nov 24 17:19:47 2017 +0000
+++ b/test/hotspot/jtreg/Makefile	Mon Nov 27 17:04:45 2017 +0000
@@ -62,8 +62,12 @@
   endif
 endif
 
+ifndef CONCURRENCY_FACTOR
+  CONCURRENCY_FACTOR = 1
+endif
+
 # Concurrency based on min(cores / 2, 12)
-CONCURRENCY := $(shell expr $(NUM_CORES) / 2)
+CONCURRENCY := $(shell awk 'BEGIN { printf "%.0f", $(NUM_CORES) / 2 * $(CONCURRENCY_FACTOR) }')
 ifeq ($(CONCURRENCY), 0)
   CONCURRENCY := 1
 else ifeq ($(shell expr $(CONCURRENCY) \> 12), 1)
--- a/test/hotspot/jtreg/compiler/runtime/SpreadNullArg.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/test/hotspot/jtreg/compiler/runtime/SpreadNullArg.java	Mon Nov 27 17:04:45 2017 +0000
@@ -49,8 +49,8 @@
       mh_spread_target =
           MethodHandles.lookup().findStatic(SpreadNullArg.class, "target_spread_arg", mt_ref_arg);
       result = (int) mh_spreadInvoker.invokeExact(mh_spread_target, (Object[]) null);
-      throw new Error("Expected IllegalArgumentException was not thrown");
-    } catch (IllegalArgumentException e) {
+      throw new Error("Expected NullPointerException was not thrown");
+    } catch (NullPointerException e) {
       System.out.println("Expected exception : " + e);
     } catch (Throwable e) {
       throw new Error(e);
@@ -58,7 +58,7 @@
 
     if (result != 42) {
       throw new Error("result [" + result
-          + "] != 42 : Expected IllegalArgumentException was not thrown?");
+          + "] != 42 : Expected NullPointerException was not thrown?");
     }
   }
 
--- a/test/hotspot/jtreg/gc/TestFullGCALot.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/test/hotspot/jtreg/gc/TestFullGCALot.java	Mon Nov 27 17:04:45 2017 +0000
@@ -24,7 +24,7 @@
 /*
  * @test TestFullGCALot
  * @key gc
- * @bug 4187687
+ * @bug 4187687 8187819
  * @summary Ensure no access violation when using FullGCALot
  * @requires vm.debug
  * @run main/othervm -XX:NewSize=10m -XX:+FullGCALot -XX:FullGCALotInterval=120 TestFullGCALot
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/gc/TestGenerationPerfCounter.java	Mon Nov 27 17:04:45 2017 +0000
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2017, 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 static jdk.test.lib.Asserts.*;
+import gc.testlibrary.PerfCounter;
+import gc.testlibrary.PerfCounters;
+
+
+/* @test TestGenerationPerfCounter
+ * @bug 8080345
+ * @requires vm.gc=="null"
+ * @library /test/lib /
+ * @summary Tests that the sun.gc.policy.generations returns 2 for all GCs.
+ * @modules java.base/jdk.internal.misc
+ *          java.compiler
+ *          java.management/sun.management
+ *          jdk.internal.jvmstat/sun.jvmstat.monitor
+ * @run main/othervm -XX:+UsePerfData -XX:+UseSerialGC TestGenerationPerfCounter
+ * @run main/othervm -XX:+UsePerfData -XX:+UseParallelGC TestGenerationPerfCounter
+ * @run main/othervm -XX:+UsePerfData -XX:+UseG1GC TestGenerationPerfCounter
+ * @run main/othervm -XX:+UsePerfData -XX:+UseConcMarkSweepGC TestGenerationPerfCounter
+ */
+public class TestGenerationPerfCounter {
+    public static void main(String[] args) throws Exception {
+        long numGenerations =
+            PerfCounters.findByName("sun.gc.policy.generations").longValue();
+        assertEQ(numGenerations, 2L);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/gc/g1/TestInvalidateArrayCopy.java	Mon Nov 27 17:04:45 2017 +0000
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2017, 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 TestInvalidateArrayCopy
+ * @bug 8182050
+ * @summary Check that benign (0-sized) out of heap bounds card table invalidations do not assert.
+ * @requires vm.gc.G1
+ * @requires vm.debug
+ * @key gc
+ * @run main/othervm -XX:NewSize=1M -Xlog:gc -XX:MaxNewSize=1m -XX:-UseTLAB -XX:OldSize=63M -XX:MaxHeapSize=64M TestInvalidateArrayCopy
+ */
+
+// The test allocates zero-sized arrays of j.l.O and tries to arraycopy random data into it so
+// that the asserting post barrier calls are executed. It assumes that G1 allocates eden regions
+// at the top of the heap for this problem to occur.
+public class TestInvalidateArrayCopy {
+
+    static final int NumIterations = 1000000;
+
+    // "Random" source data to "copy" into the target.
+    static Object[] sourceArray = new Object[10];
+
+    public static void main(String[] args) {
+        for (int i = 0; i < NumIterations; i++) {
+            Object[] x = new Object[0];
+            // Make sure that the compiler can't optimize out the above allocations.
+            if (i % (NumIterations / 10) == 0) {
+                System.out.println(x);
+            }
+            System.arraycopy(sourceArray, 0, x, 0, Math.min(x.length, sourceArray.length));
+        }
+    }
+}
--- a/test/hotspot/jtreg/gc/metaspace/PerfCounter.java	Fri Nov 24 17:19:47 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,68 +0,0 @@
-/*
- * Copyright (c) 2013, 2015, 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 sun.jvmstat.monitor.Monitor;
-
-/**
- * Represents a performance counter in the JVM.
- *
- * See http://openjdk.java.net/groups/hotspot/docs/Serviceability.html#bjvmstat
- * for more details about performance counters.
- */
-public class PerfCounter {
-    private final Monitor monitor;
-    private final String name;
-
-    PerfCounter(Monitor monitor, String name) {
-        this.monitor = monitor;
-        this.name = name;
-    }
-
-    /**
-     * Returns the value of this performance counter as a long.
-     *
-     * @return The long value of this performance counter
-     * @throws RuntimeException If the value of the performance counter isn't a long
-     */
-    public long longValue() {
-        Object value = monitor.getValue();
-        if (value instanceof Long) {
-            return ((Long) value).longValue();
-        }
-        throw new RuntimeException("Expected " + monitor.getName() + " to have a long value");
-    }
-
-    /**
-     * Returns the name of the performance counter.
-     *
-     * @return The name of the performance counter.
-     */
-    public String getName() {
-        return name;
-    }
-
-    @Override
-    public String toString() {
-        return name;
-    }
-}
--- a/test/hotspot/jtreg/gc/metaspace/PerfCounters.java	Fri Nov 24 17:19:47 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,68 +0,0 @@
-/*
- * Copyright (c) 2013, 2016, 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 sun.jvmstat.monitor.Monitor;
-import sun.jvmstat.monitor.MonitorException;
-import sun.jvmstat.monitor.MonitoredHost;
-import sun.jvmstat.monitor.MonitoredVm;
-import sun.jvmstat.monitor.VmIdentifier;
-import jdk.test.lib.process.ProcessTools;
-
-/**
- * PerfCounters can be used to get a performance counter from the currently
- * executing VM.
- *
- * Throws a runtime exception if an error occurs while communicating with the
- * currently executing VM.
- */
-public class PerfCounters {
-    private final static MonitoredVm vm;
-
-    static {
-        try {
-            String pid = Long.toString(ProcessTools.getProcessId());
-            VmIdentifier vmId = new VmIdentifier(pid);
-            MonitoredHost host = MonitoredHost.getMonitoredHost(vmId);
-            vm = host.getMonitoredVm(vmId);
-        } catch (Exception e) {
-            throw new RuntimeException("Could not connect to the VM");
-        }
-    }
-
-    /**
-     * Returns the performance counter with the given name.
-     *
-     * @param name The name of the performance counter.
-     * @throws IllegalArgumentException If no counter with the given name exists.
-     * @throws MonitorException If an error occurs while communicating with the VM.
-     * @return The performance counter with the given name.
-     */
-    public static PerfCounter findByName(String name)
-        throws MonitorException, IllegalArgumentException {
-        Monitor m = vm.findByName(name);
-        if (m == null) {
-            throw new IllegalArgumentException("Did not find a performance counter with name " + name);
-        }
-        return new PerfCounter(m, name);
-    }
-}
--- a/test/hotspot/jtreg/gc/metaspace/TestMetaspacePerfCounters.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/test/hotspot/jtreg/gc/metaspace/TestMetaspacePerfCounters.java	Mon Nov 27 17:04:45 2017 +0000
@@ -32,11 +32,13 @@
 import sun.management.ManagementFactoryHelper;
 
 import static jdk.test.lib.Asserts.*;
+import gc.testlibrary.PerfCounter;
+import gc.testlibrary.PerfCounters;
 
 /* @test TestMetaspacePerfCounters
  * @bug 8014659
  * @requires vm.gc=="null"
- * @library /test/lib
+ * @library /test/lib /
  * @summary Tests that performance counters for metaspace and compressed class
  *          space exists and works.
  * @modules java.base/jdk.internal.misc
--- a/test/hotspot/jtreg/gc/metaspace/TestPerfCountersAndMemoryPools.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/test/hotspot/jtreg/gc/metaspace/TestPerfCountersAndMemoryPools.java	Mon Nov 27 17:04:45 2017 +0000
@@ -26,10 +26,12 @@
 
 import jdk.test.lib.Platform;
 import static jdk.test.lib.Asserts.*;
+import gc.testlibrary.PerfCounter;
+import gc.testlibrary.PerfCounters;
 
 /* @test TestPerfCountersAndMemoryPools
  * @bug 8023476
- * @library /test/lib
+ * @library /test/lib /
  * @requires vm.gc.Serial
  * @summary Tests that a MemoryPoolMXBeans and PerfCounters for metaspace
  *          report the same data.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/gc/testlibrary/PerfCounter.java	Mon Nov 27 17:04:45 2017 +0000
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2013, 2015, 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.
+ */
+
+package gc.testlibrary;
+
+import sun.jvmstat.monitor.Monitor;
+
+/**
+ * Represents a performance counter in the JVM.
+ *
+ * See http://openjdk.java.net/groups/hotspot/docs/Serviceability.html#bjvmstat
+ * for more details about performance counters.
+ */
+public class PerfCounter {
+    private final Monitor monitor;
+    private final String name;
+
+    PerfCounter(Monitor monitor, String name) {
+        this.monitor = monitor;
+        this.name = name;
+    }
+
+    /**
+     * Returns the value of this performance counter as a long.
+     *
+     * @return The long value of this performance counter
+     * @throws RuntimeException If the value of the performance counter isn't a long
+     */
+    public long longValue() {
+        Object value = monitor.getValue();
+        if (value instanceof Long) {
+            return ((Long) value).longValue();
+        }
+        throw new RuntimeException("Expected " + monitor.getName() + " to have a long value");
+    }
+
+    /**
+     * Returns the name of the performance counter.
+     *
+     * @return The name of the performance counter.
+     */
+    public String getName() {
+        return name;
+    }
+
+    @Override
+    public String toString() {
+        return name;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/gc/testlibrary/PerfCounters.java	Mon Nov 27 17:04:45 2017 +0000
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2013, 2016, 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.
+ */
+
+package gc.testlibrary;
+
+import sun.jvmstat.monitor.Monitor;
+import sun.jvmstat.monitor.MonitorException;
+import sun.jvmstat.monitor.MonitoredHost;
+import sun.jvmstat.monitor.MonitoredVm;
+import sun.jvmstat.monitor.VmIdentifier;
+import jdk.test.lib.process.ProcessTools;
+
+/**
+ * PerfCounters can be used to get a performance counter from the currently
+ * executing VM.
+ *
+ * Throws a runtime exception if an error occurs while communicating with the
+ * currently executing VM.
+ */
+public class PerfCounters {
+    private final static MonitoredVm vm;
+
+    static {
+        try {
+            String pid = Long.toString(ProcessTools.getProcessId());
+            VmIdentifier vmId = new VmIdentifier(pid);
+            MonitoredHost host = MonitoredHost.getMonitoredHost(vmId);
+            vm = host.getMonitoredVm(vmId);
+        } catch (Exception e) {
+            throw new RuntimeException("Could not connect to the VM");
+        }
+    }
+
+    /**
+     * Returns the performance counter with the given name.
+     *
+     * @param name The name of the performance counter.
+     * @throws IllegalArgumentException If no counter with the given name exists.
+     * @throws MonitorException If an error occurs while communicating with the VM.
+     * @return The performance counter with the given name.
+     */
+    public static PerfCounter findByName(String name)
+        throws MonitorException, IllegalArgumentException {
+        Monitor m = vm.findByName(name);
+        if (m == null) {
+            throw new IllegalArgumentException("Did not find a performance counter with name " + name);
+        }
+        return new PerfCounter(m, name);
+    }
+}
--- a/test/hotspot/jtreg/runtime/CommandLine/VMDeprecatedOptions.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/test/hotspot/jtreg/runtime/CommandLine/VMDeprecatedOptions.java	Mon Nov 27 17:04:45 2017 +0000
@@ -46,6 +46,11 @@
         {"MinRAMFraction",            "2"},
         {"InitialRAMFraction",        "64"},
         {"AssumeMP",                  "false"},
+        {"UseMembar",                 "true"},
+        {"FastTLABRefill",            "false"},
+        {"DeferPollingPageLoopCount", "-1"},
+        {"SafepointSpinBeforeYield",  "2000"},
+        {"DeferPollingPageLoopCount", "4000"},
 
         // deprecated alias flags (see also aliased_jvm_flags):
         {"DefaultMaxRAMFraction", "4"},
--- a/test/hotspot/jtreg/runtime/ErrorHandling/ErrorHandler.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/test/hotspot/jtreg/runtime/ErrorHandling/ErrorHandler.java	Mon Nov 27 17:04:45 2017 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, 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,6 +23,7 @@
 
 /*
  * @test
+ * @requires (vm.debug == true)
  * @bug 6888954
  * @bug 8015884
  * @summary Exercise HotSpot error handling code by invoking java with
@@ -39,6 +40,7 @@
 public class ErrorHandler {
 
     public static OutputAnalyzer runTest(int testcase) throws Exception {
+        // The -XX:ErrorHandlerTest=N option requires debug bits.
         return new OutputAnalyzer(
             ProcessTools.createJavaProcessBuilder(
             "-XX:-TransmitErrorReport", "-XX:-CreateCoredumpOnCrash", "-XX:ErrorHandlerTest=" + testcase)
@@ -46,10 +48,6 @@
     }
 
     public static void main(String[] args) throws Exception {
-        // Test is only applicable for debug builds
-        if (!Platform.isDebugBuild()) {
-            return;
-        }
         // Keep this in sync with hotspot/src/share/vm/utilities/debug.cpp
         int i = 1;
         String[] strings = {
@@ -69,6 +67,10 @@
         String[] patterns = {
             "(SIGILL|SIGSEGV|EXCEPTION_ACCESS_VIOLATION).* at pc=",
             "(SIGBUS|SIGSEGV|SIGILL|EXCEPTION_ACCESS_VIOLATION).* at pc="
+            // -XX:ErrorHandlerTest=14 is tested by SafeFetchInErrorHandlingTest.java
+            // -XX:ErrorHandlerTest=15 is tested by SecondaryErrorTest.java
+            // -XX:ErrorHandlerTest=16 is tested by ThreadsListHandleInErrorHandlingTest.java
+            // -XX:ErrorHandlerTest=17 is tested by NestedThreadsListHandleInErrorHandlingTest.java
         };
 
         for (String s : strings) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/ErrorHandling/NestedThreadsListHandleInErrorHandlingTest.java	Mon Nov 27 17:04:45 2017 +0000
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2017, 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 java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStreamReader;
+import java.util.regex.Pattern;
+
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.Platform;
+import jdk.test.lib.process.ProcessTools;
+
+/*
+ * @test
+ * @requires (vm.debug == true)
+ * @bug 8167108
+ * @summary Nested ThreadsListHandle info should be in error handling output.
+ * @modules java.base/jdk.internal.misc
+ * @library /test/lib
+ * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+EnableThreadSMRStatistics NestedThreadsListHandleInErrorHandlingTest
+ */
+
+/*
+ * This test was created using SafeFetchInErrorHandlingTest.java
+ * as a guide.
+ */
+public class NestedThreadsListHandleInErrorHandlingTest {
+  public static void main(String[] args) throws Exception {
+
+    // The -XX:ErrorHandlerTest=N option requires debug bits.
+    ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
+        "-XX:+UnlockDiagnosticVMOptions",
+        "-Xmx100M",
+        "-XX:ErrorHandlerTest=17",
+        "-XX:-CreateCoredumpOnCrash",
+        "-version");
+
+    OutputAnalyzer output_detail = new OutputAnalyzer(pb.start());
+
+    // We should have crashed with a specific fatal error:
+    output_detail.shouldMatch("# A fatal error has been detected by the Java Runtime Environment:.*");
+    System.out.println("Found fatal error header.");
+    output_detail.shouldMatch("# +fatal error: Force crash with a nested ThreadsListHandle.");
+    System.out.println("Found specific fatal error.");
+
+    // Extract hs_err_pid file.
+    String hs_err_file = output_detail.firstMatch("# *(\\S*hs_err_pid\\d+\\.log)", 1);
+    if (hs_err_file == null) {
+        throw new RuntimeException("Did not find hs_err_pid file in output.\n");
+    }
+
+    File f = new File(hs_err_file);
+    if (!f.exists()) {
+        throw new RuntimeException("hs_err_pid file missing at "
+                                   + f.getAbsolutePath() + ".\n");
+    }
+
+    System.out.println("Found hs_err_pid file. Scanning...");
+
+    FileInputStream fis = new FileInputStream(f);
+    BufferedReader br = new BufferedReader(new InputStreamReader(fis));
+    String line = null;
+
+    Pattern [] pattern = new Pattern[] {
+        // The "Current thread" line should show a hazard ptr and
+        // a nested hazard ptr:
+        Pattern.compile("Current thread .* _threads_hazard_ptr=0x[0-9A-Fa-f][0-9A-Fa-f]*, _nested_threads_hazard_ptr_cnt=1, _nested_threads_hazard_ptrs=0x.*"),
+        // We should have a section of Threads class SMR info:
+        Pattern.compile("Threads class SMR info:"),
+        // We should have one nested ThreadsListHandle:
+        Pattern.compile(".*, _smr_nested_thread_list_max=1"),
+        // The current thread (marked with '=>') in the threads list
+        // should show a hazard ptr:
+        Pattern.compile("=>.* JavaThread \"main\" .*_threads_hazard_ptr=0x[0-9A-Fa-f][0-9A-Fa-f]*, _nested_threads_hazard_ptr_cnt=1, _nested_threads_hazard_ptrs=0x.*"),
+    };
+    int currentPattern = 0;
+
+    String lastLine = null;
+    while ((line = br.readLine()) != null) {
+        if (currentPattern < pattern.length) {
+            if (pattern[currentPattern].matcher(line).matches()) {
+                System.out.println("Found: " + line + ".");
+                currentPattern++;
+            }
+        }
+        lastLine = line;
+    }
+    br.close();
+
+    if (currentPattern < pattern.length) {
+        throw new RuntimeException("hs_err_pid file incomplete (first missing pattern: " +  currentPattern + ")");
+    }
+
+    if (!lastLine.equals("END.")) {
+        throw new RuntimeException("hs-err file incomplete (missing END marker.)");
+    } else {
+        System.out.println("End marker found.");
+    }
+
+    System.out.println("Done scanning hs_err_pid_file.");
+    System.out.println("PASSED.");
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/ErrorHandling/ThreadsListHandleInErrorHandlingTest.java	Mon Nov 27 17:04:45 2017 +0000
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2017, 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 java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStreamReader;
+import java.util.regex.Pattern;
+
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.Platform;
+import jdk.test.lib.process.ProcessTools;
+
+/*
+ * @test
+ * @requires (vm.debug == true)
+ * @bug 8167108
+ * @summary ThreadsListHandle info should be in error handling output.
+ * @modules java.base/jdk.internal.misc
+ * @library /test/lib
+ * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+EnableThreadSMRStatistics ThreadsListHandleInErrorHandlingTest
+ */
+
+/*
+ * This test was created using SafeFetchInErrorHandlingTest.java
+ * as a guide.
+ */
+public class ThreadsListHandleInErrorHandlingTest {
+  public static void main(String[] args) throws Exception {
+
+    // The -XX:ErrorHandlerTest=N option requires debug bits.
+    ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
+        "-XX:+UnlockDiagnosticVMOptions",
+        "-Xmx100M",
+        "-XX:ErrorHandlerTest=16",
+        "-XX:-CreateCoredumpOnCrash",
+        "-version");
+
+    OutputAnalyzer output_detail = new OutputAnalyzer(pb.start());
+
+    // We should have crashed with a specific fatal error:
+    output_detail.shouldMatch("# A fatal error has been detected by the Java Runtime Environment:.*");
+    System.out.println("Found fatal error header.");
+    output_detail.shouldMatch("# +fatal error: Force crash with an active ThreadsListHandle.");
+    System.out.println("Found specific fatal error.");
+
+    // Extract hs_err_pid file.
+    String hs_err_file = output_detail.firstMatch("# *(\\S*hs_err_pid\\d+\\.log)", 1);
+    if (hs_err_file == null) {
+        throw new RuntimeException("Did not find hs_err_pid file in output.\n");
+    }
+
+    File f = new File(hs_err_file);
+    if (!f.exists()) {
+        throw new RuntimeException("hs_err_pid file missing at "
+                                   + f.getAbsolutePath() + ".\n");
+    }
+
+    System.out.println("Found hs_err_pid file. Scanning...");
+
+    FileInputStream fis = new FileInputStream(f);
+    BufferedReader br = new BufferedReader(new InputStreamReader(fis));
+    String line = null;
+
+    Pattern [] pattern = new Pattern[] {
+        // The "Current thread" line should show a hazard ptr:
+        Pattern.compile("Current thread .* _threads_hazard_ptr=0x.*"),
+        // We should have a section of Threads class SMR info:
+        Pattern.compile("Threads class SMR info:"),
+        // The current thread (marked with '=>') in the threads list
+        // should show a hazard ptr:
+        Pattern.compile("=>.* JavaThread \"main\" .*_threads_hazard_ptr=0x.*"),
+    };
+    int currentPattern = 0;
+
+    String lastLine = null;
+    while ((line = br.readLine()) != null) {
+        if (currentPattern < pattern.length) {
+            if (pattern[currentPattern].matcher(line).matches()) {
+                System.out.println("Found: " + line + ".");
+                currentPattern++;
+            }
+        }
+        lastLine = line;
+    }
+    br.close();
+
+    if (currentPattern < pattern.length) {
+        throw new RuntimeException("hs_err_pid file incomplete (first missing pattern: " +  currentPattern + ")");
+    }
+
+    if (!lastLine.equals("END.")) {
+        throw new RuntimeException("hs-err file incomplete (missing END marker.)");
+    } else {
+        System.out.println("End marker found.");
+    }
+
+    System.out.println("Done scanning hs_err_pid_file.");
+    System.out.println("PASSED.");
+  }
+}
--- a/test/hotspot/jtreg/runtime/SharedArchiveFile/BootAppendTests.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/test/hotspot/jtreg/runtime/SharedArchiveFile/BootAppendTests.java	Mon Nov 27 17:04:45 2017 +0000
@@ -169,7 +169,7 @@
             CDSOptions opts = (new CDSOptions())
                 .setXShareMode(mode).setUseVersion(false)
                 .addPrefix("-Xbootclasspath/a:" + bootAppendJar, "-showversion",
-                           "--limit-modules=java.base,jdk.internal.vm.compiler", "-cp", appJar)
+                           "--limit-modules=java.base", "-cp", appJar)
                 .addSuffix("-Xlog:class+load=info",
                            APP_CLASS, BOOT_APPEND_MODULE_CLASS_NAME);
 
@@ -198,7 +198,7 @@
             CDSOptions opts = (new CDSOptions())
                 .setXShareMode(mode).setUseVersion(false)
                 .addPrefix("-Xbootclasspath/a:" + bootAppendJar, "-showversion",
-                           "--limit-modules=java.base,jdk.internal.vm.compiler", "-cp", appJar)
+                           "--limit-modules=java.base", "-cp", appJar)
                 .addSuffix("-Xlog:class+load=info",
                            APP_CLASS, BOOT_APPEND_DUPLICATE_MODULE_CLASS_NAME);
 
@@ -226,7 +226,7 @@
             CDSOptions opts = (new CDSOptions())
                 .setXShareMode(mode).setUseVersion(false)
                 .addPrefix("-Xbootclasspath/a:" + bootAppendJar, "-showversion",
-                           "--limit-modules=java.base,jdk.internal.vm.compiler", "-cp", appJar)
+                           "--limit-modules=java.base", "-cp", appJar)
                 .addSuffix("-Xlog:class+load=info",
                            APP_CLASS, BOOT_APPEND_CLASS_NAME);
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/Thread/CountStackFramesAtExit.java	Mon Nov 27 17:04:45 2017 +0000
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2017, 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 8167108
+ * @summary Stress test java.lang.Thread.countStackFrames() at thread exit.
+ * @run main/othervm -Xlog:thread+smr=debug CountStackFramesAtExit
+ */
+
+import java.util.concurrent.CountDownLatch;
+
+public class CountStackFramesAtExit extends Thread {
+    final static int N_THREADS = 32;
+    final static int N_LATE_CALLS = 1000;
+
+    public CountDownLatch exitSyncObj = new CountDownLatch(1);
+    public CountDownLatch startSyncObj = new CountDownLatch(1);
+
+    @Override
+    public void run() {
+        // Tell main thread we have started.
+        startSyncObj.countDown();
+        try {
+            // Wait for main thread to interrupt us so we
+            // can race to exit.
+            exitSyncObj.await();
+        } catch (InterruptedException e) {
+            // ignore because we expect one
+        }
+    }
+
+    public static void main(String[] args) {
+        CountStackFramesAtExit threads[] = new CountStackFramesAtExit[N_THREADS];
+
+        for (int i = 0; i < N_THREADS; i++ ) {
+            threads[i] = new CountStackFramesAtExit();
+            int late_count = 1;
+            threads[i].start();
+            try {
+                // Wait for the worker thread to get going.
+                threads[i].startSyncObj.await();
+
+                // This interrupt() call will break the worker out of
+                // the exitSyncObj.await() call and the countStackFrames()
+                // calls will come in during thread exit.
+                threads[i].interrupt();
+                for (; late_count <= N_LATE_CALLS; late_count++) {
+                    try {
+                        threads[i].countStackFrames();
+                    } catch (IllegalThreadStateException itse) {
+                        // ignore because we expect it
+                    }
+
+                    if (!threads[i].isAlive()) {
+                        // Done with Thread.countStackFrames() calls since
+                        // thread is not alive.
+                        break;
+                    }
+                }
+            } catch (InterruptedException e) {
+                throw new Error("Unexpected: " + e);
+            }
+
+            System.out.println("INFO: thread #" + i + ": made " + late_count +
+                               " late calls to java.lang.Thread.countStackFrames()");
+            System.out.println("INFO: thread #" + i + ": N_LATE_CALLS==" +
+                               N_LATE_CALLS + " value is " +
+                               ((late_count >= N_LATE_CALLS) ? "NOT " : "") +
+                               "large enough to cause a Thread.countStackFrames() " +
+                               "call after thread exit.");
+
+            try {
+                threads[i].join();
+            } catch (InterruptedException e) {
+                throw new Error("Unexpected: " + e);
+            }
+            threads[i].countStackFrames();
+            if (threads[i].isAlive()) {
+                throw new Error("Expected !Thread.isAlive() after thread #" +
+                                i + " has been join()'ed");
+            }
+        }
+
+        String cmd = System.getProperty("sun.java.command");
+        if (cmd != null && !cmd.startsWith("com.sun.javatest.regtest.agent.MainWrapper")) {
+            // Exit with success in a non-JavaTest environment:
+            System.exit(0);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/Thread/InterruptAtExit.java	Mon Nov 27 17:04:45 2017 +0000
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2017, 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 8167108
+ * @summary Stress test java.lang.Thread.interrupt() at thread exit.
+ * @run main/othervm -Xlog:thread+smr=debug InterruptAtExit
+ */
+
+import java.util.concurrent.CountDownLatch;
+
+public class InterruptAtExit extends Thread {
+    final static int N_THREADS = 32;
+    final static int N_LATE_CALLS = 1000;
+
+    public CountDownLatch exitSyncObj = new CountDownLatch(1);
+    public CountDownLatch startSyncObj = new CountDownLatch(1);
+
+    @Override
+    public void run() {
+        // Tell main thread we have started.
+        startSyncObj.countDown();
+        try {
+            // Wait for main thread to interrupt us so we
+            // can race to exit.
+            exitSyncObj.await();
+        } catch (InterruptedException e) {
+            // ignore because we expect one
+        }
+    }
+
+    public static void main(String[] args) {
+        InterruptAtExit threads[] = new InterruptAtExit[N_THREADS];
+
+        for (int i = 0; i < N_THREADS; i++ ) {
+            threads[i] = new InterruptAtExit();
+            int late_count = 1;
+            threads[i].start();
+            try {
+                // Wait for the worker thread to get going.
+                threads[i].startSyncObj.await();
+
+                // The first interrupt() call will break the
+                // worker out of the exitSyncObj.await() call
+                // and the rest will come in during thread exit.
+                for (; late_count <= N_LATE_CALLS; late_count++) {
+                    threads[i].interrupt();
+
+                    if (!threads[i].isAlive()) {
+                        // Done with Thread.interrupt() calls since
+                        // thread is not alive.
+                        break;
+                    }
+                }
+            } catch (InterruptedException e) {
+                throw new Error("Unexpected: " + e);
+            }
+
+            System.out.println("INFO: thread #" + i + ": made " + late_count +
+                               " late calls to java.lang.Thread.interrupt()");
+            System.out.println("INFO: thread #" + i + ": N_LATE_CALLS==" +
+                               N_LATE_CALLS + " value is " +
+                               ((late_count >= N_LATE_CALLS) ? "NOT " : "") +
+                               "large enough to cause a Thread.interrupt() " +
+                               "call after thread exit.");
+
+            try {
+                threads[i].join();
+            } catch (InterruptedException e) {
+                throw new Error("Unexpected: " + e);
+            }
+            threads[i].interrupt();
+            if (threads[i].isAlive()) {
+                throw new Error("Expected !Thread.isAlive() after thread #" +
+                                i + " has been join()'ed");
+            }
+        }
+
+        String cmd = System.getProperty("sun.java.command");
+        if (cmd != null && !cmd.startsWith("com.sun.javatest.regtest.agent.MainWrapper")) {
+            // Exit with success in a non-JavaTest environment:
+            System.exit(0);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/Thread/IsInterruptedAtExit.java	Mon Nov 27 17:04:45 2017 +0000
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2017, 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 8167108
+ * @summary Stress test java.lang.Thread.isInterrupted() at thread exit.
+ * @run main/othervm -Xlog:thread+smr=debug IsInterruptedAtExit
+ */
+
+import java.util.concurrent.CountDownLatch;
+
+public class IsInterruptedAtExit extends Thread {
+    final static int N_THREADS = 32;
+    final static int N_LATE_CALLS = 2000;
+
+    public CountDownLatch exitSyncObj = new CountDownLatch(1);
+    public CountDownLatch startSyncObj = new CountDownLatch(1);
+
+    @Override
+    public void run() {
+        // Tell main thread we have started.
+        startSyncObj.countDown();
+        try {
+            // Wait for main thread to interrupt us so we
+            // can race to exit.
+            exitSyncObj.await();
+        } catch (InterruptedException e) {
+            // ignore because we expect one
+        }
+    }
+
+    public static void main(String[] args) {
+        IsInterruptedAtExit threads[] = new IsInterruptedAtExit[N_THREADS];
+
+        for (int i = 0; i < N_THREADS; i++ ) {
+            threads[i] = new IsInterruptedAtExit();
+            int late_count = 1;
+            threads[i].start();
+            try {
+                // Wait for the worker thread to get going.
+                threads[i].startSyncObj.await();
+
+                // This interrupt() call will break the worker out of
+                // the exitSyncObj.await() call and the isInterrupted()
+                // calls will come in during thread exit.
+                threads[i].interrupt();
+                for (; late_count <= N_LATE_CALLS; late_count++) {
+                    threads[i].isInterrupted();
+
+                    if (!threads[i].isAlive()) {
+                        // Done with Thread.isInterrupted() calls since
+                        // thread is not alive.
+                        break;
+                    }
+                }
+            } catch (InterruptedException e) {
+                throw new Error("Unexpected: " + e);
+            }
+
+            System.out.println("INFO: thread #" + i + ": made " + late_count +
+                               " late calls to java.lang.Thread.isInterrupted()");
+            System.out.println("INFO: thread #" + i + ": N_LATE_CALLS==" +
+                               N_LATE_CALLS + " value is " +
+                               ((late_count >= N_LATE_CALLS) ? "NOT " : "") +
+                               "large enough to cause a Thread.isInterrupted() " +
+                               "call after thread exit.");
+
+            try {
+                threads[i].join();
+            } catch (InterruptedException e) {
+                throw new Error("Unexpected: " + e);
+            }
+            threads[i].isInterrupted();
+            if (threads[i].isAlive()) {
+                throw new Error("Expected !Thread.isAlive() after thread #" +
+                                i + " has been join()'ed");
+            }
+        }
+
+        String cmd = System.getProperty("sun.java.command");
+        if (cmd != null && !cmd.startsWith("com.sun.javatest.regtest.agent.MainWrapper")) {
+            // Exit with success in a non-JavaTest environment:
+            System.exit(0);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/Thread/ResumeAtExit.java	Mon Nov 27 17:04:45 2017 +0000
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2017, 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 8167108
+ * @summary Stress test java.lang.Thread.resume() at thread exit.
+ * @run main/othervm -Xlog:thread+smr=debug ResumeAtExit
+ */
+
+import java.util.concurrent.CountDownLatch;
+
+public class ResumeAtExit extends Thread {
+    final static int N_THREADS = 32;
+    final static int N_LATE_CALLS = 2000;
+
+    public CountDownLatch exitSyncObj = new CountDownLatch(1);
+    public CountDownLatch startSyncObj = new CountDownLatch(1);
+
+    @Override
+    public void run() {
+        // Tell main thread we have started.
+        startSyncObj.countDown();
+        try {
+            // Wait for main thread to interrupt us so we
+            // can race to exit.
+            exitSyncObj.await();
+        } catch (InterruptedException e) {
+            // ignore because we expect one
+        }
+    }
+
+    public static void main(String[] args) {
+        ResumeAtExit threads[] = new ResumeAtExit[N_THREADS];
+
+        for (int i = 0; i < N_THREADS; i++ ) {
+            threads[i] = new ResumeAtExit();
+            int late_count = 1;
+            threads[i].start();
+            try {
+                // Wait for the worker thread to get going.
+                threads[i].startSyncObj.await();
+
+                // This interrupt() call will break the worker out
+                // of the exitSyncObj.await() call and the resume()
+                // calls will come in during thread exit.
+                threads[i].interrupt();
+                for (; late_count <= N_LATE_CALLS; late_count++) {
+                    threads[i].resume();
+
+                    if (!threads[i].isAlive()) {
+                        // Done with Thread.resume() calls since
+                        // thread is not alive.
+                        break;
+                    }
+                }
+            } catch (InterruptedException e) {
+                throw new Error("Unexpected: " + e);
+            }
+
+            System.out.println("INFO: thread #" + i + ": made " + late_count +
+                               " late calls to java.lang.Thread.resume()");
+            System.out.println("INFO: thread #" + i + ": N_LATE_CALLS==" +
+                               N_LATE_CALLS + " value is " +
+                               ((late_count >= N_LATE_CALLS) ? "NOT " : "") +
+                               "large enough to cause a Thread.resume() " +
+                               "call after thread exit.");
+
+            try {
+                threads[i].join();
+            } catch (InterruptedException e) {
+                throw new Error("Unexpected: " + e);
+            }
+            threads[i].resume();
+            if (threads[i].isAlive()) {
+                throw new Error("Expected !Thread.isAlive() after thread #" +
+                                i + " has been join()'ed");
+            }
+        }
+
+        String cmd = System.getProperty("sun.java.command");
+        if (cmd != null && !cmd.startsWith("com.sun.javatest.regtest.agent.MainWrapper")) {
+            // Exit with success in a non-JavaTest environment:
+            System.exit(0);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/Thread/SetNameAtExit.java	Mon Nov 27 17:04:45 2017 +0000
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2017, 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 8167108
+ * @summary Stress test java.lang.Thread.setName() at thread exit.
+ * @run main/othervm -Xlog:thread+smr=debug SetNameAtExit
+ */
+
+import java.util.concurrent.CountDownLatch;
+
+public class SetNameAtExit extends Thread {
+    final static int N_THREADS = 32;
+    final static int N_LATE_CALLS = 1000;
+
+    public CountDownLatch exitSyncObj = new CountDownLatch(1);
+    public CountDownLatch startSyncObj = new CountDownLatch(1);
+
+    @Override
+    public void run() {
+        // Tell main thread we have started.
+        startSyncObj.countDown();
+        try {
+            // Wait for main thread to interrupt us so we
+            // can race to exit.
+            exitSyncObj.await();
+        } catch (InterruptedException e) {
+            // ignore because we expect one
+        }
+    }
+
+    public static void main(String[] args) {
+        SetNameAtExit threads[] = new SetNameAtExit[N_THREADS];
+
+        for (int i = 0; i < N_THREADS; i++ ) {
+            threads[i] = new SetNameAtExit();
+            int late_count = 1;
+            threads[i].start();
+            try {
+                // Wait for the worker thread to get going.
+                threads[i].startSyncObj.await();
+
+                // This interrupt() call will break the worker out
+                // of the exitSyncObj.await() call and the setName()
+                // calls will come in during thread exit.
+                threads[i].interrupt();
+                for (; late_count <= N_LATE_CALLS; late_count++) {
+                    threads[i].setName("T" + i + "-" + late_count);
+
+                    if (!threads[i].isAlive()) {
+                        // Done with Thread.setName() calls since
+                        // thread is not alive.
+                        break;
+                    }
+                }
+            } catch (InterruptedException e) {
+                throw new Error("Unexpected: " + e);
+            }
+
+            System.out.println("INFO: thread #" + i + ": made " + late_count +
+                               " late calls to java.lang.Thread.setName()");
+            System.out.println("INFO: thread #" + i + ": N_LATE_CALLS==" +
+                               N_LATE_CALLS + " value is " +
+                               ((late_count >= N_LATE_CALLS) ? "NOT " : "") +
+                               "large enough to cause a Thread.setName() " +
+                               "call after thread exit.");
+
+            try {
+                threads[i].join();
+            } catch (InterruptedException e) {
+                throw new Error("Unexpected: " + e);
+            }
+            threads[i].setName("T" + i + "-done");
+            if (threads[i].isAlive()) {
+                throw new Error("Expected !Thread.isAlive() after thread #" +
+                                i + " has been join()'ed");
+            }
+        }
+
+        String cmd = System.getProperty("sun.java.command");
+        if (cmd != null && !cmd.startsWith("com.sun.javatest.regtest.agent.MainWrapper")) {
+            // Exit with success in a non-JavaTest environment:
+            System.exit(0);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/Thread/SetPriorityAtExit.java	Mon Nov 27 17:04:45 2017 +0000
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2017, 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 8167108
+ * @summary Stress test java.lang.Thread.setPriority() at thread exit.
+ * @run main/othervm -Xlog:thread+smr=debug SetPriorityAtExit
+ */
+
+import java.util.concurrent.CountDownLatch;
+
+public class SetPriorityAtExit extends Thread {
+    final static int N_THREADS = 32;
+    final static int N_LATE_CALLS = 2000;
+
+    final static int MIN = java.lang.Thread.MIN_PRIORITY;
+    final static int NORM = java.lang.Thread.NORM_PRIORITY;
+
+    public CountDownLatch exitSyncObj = new CountDownLatch(1);
+    public CountDownLatch startSyncObj = new CountDownLatch(1);
+
+    @Override
+    public void run() {
+        // Tell main thread we have started.
+        startSyncObj.countDown();
+        try {
+            // Wait for main thread to interrupt us so we
+            // can race to exit.
+            exitSyncObj.await();
+        } catch (InterruptedException e) {
+            // ignore because we expect one
+        }
+    }
+
+    public static void main(String[] args) {
+        SetPriorityAtExit threads[] = new SetPriorityAtExit[N_THREADS];
+
+        int prio = MIN;
+        for (int i = 0; i < N_THREADS; i++ ) {
+            threads[i] = new SetPriorityAtExit();
+            int late_count = 1;
+            threads[i].start();
+            try {
+                // Wait for the worker thread to get going.
+                threads[i].startSyncObj.await();
+
+                // This interrupt() call will break the worker out of
+                // the exitSyncObj.await() call and the setPriority()
+                // calls will come in during thread exit.
+                threads[i].interrupt();
+                for (; late_count <= N_LATE_CALLS; late_count++) {
+                    threads[i].setPriority(prio);
+                    if (prio == MIN) {
+                        prio = NORM;
+                    } else {
+                        prio = MIN;
+                    }
+
+                    if (!threads[i].isAlive()) {
+                        // Done with Thread.setPriority() calls since
+                        // thread is not alive.
+                        break;
+                    }
+                }
+            } catch (InterruptedException e) {
+                throw new Error("Unexpected: " + e);
+            }
+
+            System.out.println("INFO: thread #" + i + ": made " + late_count +
+                               " late calls to java.lang.Thread.setPriority()");
+            System.out.println("INFO: thread #" + i + ": N_LATE_CALLS==" +
+                               N_LATE_CALLS + " value is " +
+                               ((late_count >= N_LATE_CALLS) ? "NOT " : "") +
+                               "large enough to cause a Thread.setPriority() " +
+                               "call after thread exit.");
+
+            try {
+                threads[i].join();
+            } catch (InterruptedException e) {
+                throw new Error("Unexpected: " + e);
+            }
+            threads[i].setPriority(prio);
+            if (threads[i].isAlive()) {
+                throw new Error("Expected !Thread.isAlive() after thread #" +
+                                i + " has been join()'ed");
+            }
+        }
+
+        String cmd = System.getProperty("sun.java.command");
+        if (cmd != null && !cmd.startsWith("com.sun.javatest.regtest.agent.MainWrapper")) {
+            // Exit with success in a non-JavaTest environment:
+            System.exit(0);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/Thread/StopAtExit.java	Mon Nov 27 17:04:45 2017 +0000
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2017, 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 8167108
+ * @summary Stress test java.lang.Thread.stop() at thread exit.
+ * @run main/othervm -Xlog:thread+smr=debug StopAtExit
+ */
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+public class StopAtExit extends Thread {
+    final static int N_THREADS = 32;
+    final static int N_LATE_CALLS = 1000;
+
+    public CountDownLatch exitSyncObj = new CountDownLatch(1);
+    public CountDownLatch startSyncObj = new CountDownLatch(1);
+
+    @Override
+    public void run() {
+        try {
+            // Tell main thread we have started.
+            startSyncObj.countDown();
+            try {
+                // Wait for main thread to interrupt us so we
+                // can race to exit.
+                exitSyncObj.await();
+            } catch (InterruptedException e) {
+                // ignore because we expect one
+            }
+        } catch (ThreadDeath td) {
+            // ignore because we're testing Thread.stop() which throws it
+        } catch (NoClassDefFoundError ncdfe) {
+            // ignore because we're testing Thread.stop() which can cause it
+        }
+    }
+
+    public static void main(String[] args) {
+        StopAtExit threads[] = new StopAtExit[N_THREADS];
+
+        for (int i = 0; i < N_THREADS; i++ ) {
+            threads[i] = new StopAtExit();
+            int late_count = 1;
+            threads[i].start();
+            try {
+                // Wait for the worker thread to get going.
+                threads[i].startSyncObj.await();
+
+                // This interrupt() call will break the worker out
+                // of the exitSyncObj.await() call and the stop()
+                // calls will come in during thread exit.
+                threads[i].interrupt();
+                for (; late_count <= N_LATE_CALLS; late_count++) {
+                    threads[i].stop();
+
+                    if (!threads[i].isAlive()) {
+                        // Done with Thread.stop() calls since
+                        // thread is not alive.
+                        break;
+                    }
+                }
+            } catch (InterruptedException e) {
+                throw new Error("Unexpected: " + e);
+            } catch (NoClassDefFoundError ncdfe) {
+                // Ignore because we're testing Thread.stop() which can
+                // cause it. Yes, a NoClassDefFoundError that happens
+                // in a worker thread can subsequently be seen in the
+                // main thread.
+            }
+
+            System.out.println("INFO: thread #" + i + ": made " + late_count +
+                               " late calls to java.lang.Thread.stop()");
+            System.out.println("INFO: thread #" + i + ": N_LATE_CALLS==" +
+                               N_LATE_CALLS + " value is " +
+                               ((late_count >= N_LATE_CALLS) ? "NOT " : "") +
+                               "large enough to cause a Thread.stop() " +
+                               "call after thread exit.");
+
+            try {
+                threads[i].join();
+            } catch (InterruptedException e) {
+                throw new Error("Unexpected: " + e);
+            }
+            threads[i].stop();
+            if (threads[i].isAlive()) {
+                throw new Error("Expected !Thread.isAlive() after thread #" +
+                                i + " has been join()'ed");
+            }
+        }
+
+        String cmd = System.getProperty("sun.java.command");
+        if (cmd != null && !cmd.startsWith("com.sun.javatest.regtest.agent.MainWrapper")) {
+            // Exit with success in a non-JavaTest environment:
+            System.exit(0);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/Thread/SuspendAtExit.java	Mon Nov 27 17:04:45 2017 +0000
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2017, 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 8167108
+ * @summary Stress test java.lang.Thread.suspend() at thread exit.
+ * @run main/othervm -Xlog:thread+smr=debug SuspendAtExit
+ */
+
+import java.util.concurrent.CountDownLatch;
+
+public class SuspendAtExit extends Thread {
+    final static int N_THREADS = 32;
+    final static int N_LATE_CALLS = 10000;
+
+    public CountDownLatch exitSyncObj = new CountDownLatch(1);
+    public CountDownLatch startSyncObj = new CountDownLatch(1);
+
+    @Override
+    public void run() {
+        // Tell main thread we have started.
+        startSyncObj.countDown();
+        try {
+            // Wait for main thread to interrupt us so we
+            // can race to exit.
+            exitSyncObj.await();
+        } catch (InterruptedException e) {
+            // ignore because we expect one
+        }
+    }
+
+    public static void main(String[] args) {
+        SuspendAtExit threads[] = new SuspendAtExit[N_THREADS];
+
+        for (int i = 0; i < N_THREADS; i++ ) {
+            threads[i] = new SuspendAtExit();
+            int late_count = 1;
+            threads[i].start();
+            try {
+                // Wait for the worker thread to get going.
+                threads[i].startSyncObj.await();
+
+                // This interrupt() call will break the worker out
+                // of the exitSyncObj.await() call and the suspend()
+                // calls will come in during thread exit.
+                threads[i].interrupt();
+                for (; late_count <= N_LATE_CALLS; late_count++) {
+                    threads[i].suspend();
+
+                    if (!threads[i].isAlive()) {
+                        // Done with Thread.suspend() calls since
+                        // thread is not alive.
+                        break;
+                    }
+                    threads[i].resume();
+                }
+            } catch (InterruptedException e) {
+                throw new Error("Unexpected: " + e);
+            }
+
+            System.out.println("INFO: thread #" + i + ": made " + late_count +
+                               " late calls to java.lang.Thread.suspend()");
+            System.out.println("INFO: thread #" + i + ": N_LATE_CALLS==" +
+                               N_LATE_CALLS + " value is " +
+                               ((late_count >= N_LATE_CALLS) ? "NOT " : "") +
+                               "large enough to cause a Thread.suspend() " +
+                               "call after thread exit.");
+
+            try {
+                threads[i].join();
+            } catch (InterruptedException e) {
+                throw new Error("Unexpected: " + e);
+            }
+            threads[i].suspend();
+            threads[i].resume();
+            if (threads[i].isAlive()) {
+                throw new Error("Expected !Thread.isAlive() after thread #" +
+                                i + " has been join()'ed");
+            }
+        }
+
+        String cmd = System.getProperty("sun.java.command");
+        if (cmd != null && !cmd.startsWith("com.sun.javatest.regtest.agent.MainWrapper")) {
+            // Exit with success in a non-JavaTest environment:
+            System.exit(0);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/Thread/TestThreadDumpSMRInfo.java	Mon Nov 27 17:04:45 2017 +0000
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2017, 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     8167108
+ * @summary Checks whether jstack reports a "Threads class SMR info" section.
+ *
+ * @library /test/lib
+ * @modules java.base/jdk.internal.misc
+ *          java.management
+ * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+EnableThreadSMRStatistics TestThreadDumpSMRInfo
+ */
+
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.JDKToolFinder;
+
+public class TestThreadDumpSMRInfo {
+    // jstack tends to be closely bound to the VM that we are running
+    // so use getTestJDKTool() instead of getCompileJDKTool() or even
+    // getJDKTool() which can fall back to "compile.jdk".
+    final static String JSTACK = JDKToolFinder.getTestJDKTool("jstack");
+    final static String PID = "" + ProcessHandle.current().pid();
+
+    // Here's a sample "Threads class SMR info" section:
+    //
+    // Threads class SMR info:
+    // _smr_java_thread_list=0x0000000000ce8da0, length=23, elements={
+    // 0x000000000043a800, 0x0000000000aee800, 0x0000000000b06800, 0x0000000000b26000,
+    // 0x0000000000b28800, 0x0000000000b2b000, 0x0000000000b2e000, 0x0000000000b30000,
+    // 0x0000000000b32800, 0x0000000000b35000, 0x0000000000b3f000, 0x0000000000b41800,
+    // 0x0000000000b44000, 0x0000000000b46800, 0x0000000000b48800, 0x0000000000b53000,
+    // 0x0000000000b55800, 0x0000000000b57800, 0x0000000000b5a000, 0x0000000000b5c800,
+    // 0x0000000000cc8800, 0x0000000000fd9800, 0x0000000000ef4800
+    // }
+    // _smr_java_thread_list_alloc_cnt=24, _smr_java_thread_list_free_cnt=23, _smr_java_thread_list_max=23, _smr_nested_thread_list_max=0
+    // _smr_delete_lock_wait_cnt=0, _smr_delete_lock_wait_max=0
+    // _smr_to_delete_list_cnt=0, _smr_to_delete_list_max=1
+
+    final static String HEADER_STR = "Threads class SMR info:";
+
+    static boolean verbose = false;
+
+    public static void main(String[] args) throws Exception {
+        if (args.length != 0) {
+            int arg_i = 0;
+            if (args[arg_i].equals("-v")) {
+                verbose = true;
+                arg_i++;
+            }
+        }
+
+        ProcessBuilder pb = new ProcessBuilder(JSTACK, PID);
+        OutputAnalyzer output = new OutputAnalyzer(pb.start());
+
+        if (verbose) {
+            System.out.println("stdout: " + output.getStdout());
+        }
+
+        output.shouldHaveExitValue(0);
+        System.out.println("INFO: jstack ran successfully.");
+
+        output.shouldContain(HEADER_STR);
+        System.out.println("INFO: Found: '" + HEADER_STR + "' in jstack output.");
+
+        System.out.println("Test PASSED.");
+    }
+
+    static void usage() {
+        System.err.println("Usage: java TestThreadDumpSMRInfo [-v]");
+        System.exit(1);
+    }
+}
--- a/test/hotspot/jtreg/runtime/handshake/HandshakeWalkExitTest.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/test/hotspot/jtreg/runtime/handshake/HandshakeWalkExitTest.java	Mon Nov 27 17:04:45 2017 +0000
@@ -42,22 +42,18 @@
     }
 
     static volatile boolean exit_now = false;
-    static Thread[] threads;
 
     public static void main(String... args) throws Exception {
-        int testRuns = 100;
-        int testThreads = 500;
+        int testRuns = 20;
+        int testThreads = 128;
 
         HandshakeWalkExitTest test = new HandshakeWalkExitTest();
 
-        threads = new Thread[64];
-
         Runnable hser = new Runnable(){
             public void run(){
                 WhiteBox wb = WhiteBox.getWhiteBox();
                 while(!exit_now) {
                     wb.handshakeWalkStack(null, true);
-                    try { Thread.sleep(1); } catch(Exception e) {}
                 }
             }
         };
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/handshake/HandshakeWalkOneExitTest.java	Mon Nov 27 17:04:45 2017 +0000
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2017, 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 HandshakeWalkOneExitTest
+ * @summary This test tries to stress the handshakes with new and exiting threads
+ * @library /testlibrary /test/lib
+ * @build HandshakeWalkOneExitTest
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ *                              sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI HandshakeWalkOneExitTest
+ */
+
+import jdk.test.lib.Asserts;
+import sun.hotspot.WhiteBox;
+
+public class HandshakeWalkOneExitTest  implements Runnable {
+
+    @Override
+    public void run() {
+    }
+
+    static volatile boolean exit_now = false;
+    static Thread[] threads;
+
+    public static void main(String... args) throws Exception {
+        int testRuns = 20;
+        int testThreads = 128;
+
+        HandshakeWalkOneExitTest test = new HandshakeWalkOneExitTest();
+
+        Runnable hser = new Runnable(){
+            public void run(){
+                WhiteBox wb = WhiteBox.getWhiteBox();
+                while(!exit_now) {
+                    Thread[] t = threads;
+                    for (int i = 0; i<t.length ; i++) {
+                        wb.handshakeWalkStack(t[i], false);
+                    }
+                }
+            }
+        };
+        Thread hst = new Thread(hser);
+        for (int k = 0; k<testRuns ; k++) {
+            threads = new Thread[testThreads];
+            for (int i = 0; i<threads.length ; i++) {
+                threads[i] = new Thread(test);
+                threads[i].start();
+            }
+            if (k == 0) {
+                hst.start();
+            }
+        }
+        exit_now = true;
+        hst.join();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/serviceability/sa/LingeredAppWithLock.java	Mon Nov 27 17:04:45 2017 +0000
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2017, 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 jdk.test.lib.apps.LingeredApp;
+
+
+public class LingeredAppWithLock extends LingeredApp {
+
+    public static void lockMethod(Object lock) {
+        synchronized (lock) {
+            try {
+                Thread.sleep(300000);
+            } catch (InterruptedException e) {
+                throw new RuntimeException(e);
+            }
+        }
+    }
+
+    public static void main(String args[]) {
+        Thread classLock1 = new Thread(() -> lockMethod(LingeredAppWithLock.class));
+        Thread classLock2 = new Thread(() -> lockMethod(LingeredAppWithLock.class));
+        Thread objectLock = new Thread(() -> lockMethod(classLock1));
+        Thread primitiveLock = new Thread(() -> lockMethod(int.class));
+
+        classLock1.start();
+        classLock2.start();
+        objectLock.start();
+        primitiveLock.start();
+
+        LingeredApp.main(args);
+    }
+ }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/serviceability/sa/TestClhsdbJstackLock.java	Mon Nov 27 17:04:45 2017 +0000
@@ -0,0 +1,171 @@
+/*
+ * Copyright (c) 2017, 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 java.util.ArrayList;
+import java.util.Scanner;
+import java.util.List;
+import java.io.File;
+import java.io.IOException;
+import java.util.stream.Collectors;
+import java.io.OutputStream;
+import jdk.test.lib.apps.LingeredApp;
+import jdk.test.lib.JDKToolLauncher;
+import jdk.test.lib.Platform;
+import jdk.test.lib.process.ProcessTools;
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.Utils;
+import jdk.test.lib.Asserts;
+
+/*
+ * @test
+ * @library /test/lib
+ * @run main/othervm TestClhsdbJstackLock
+ */
+
+public class TestClhsdbJstackLock {
+
+    private static final String JSTACK_OUT_FILE = "jstack_out.txt";
+
+    private static void verifyJStackOutput() throws Exception {
+
+        Exception unexpected = null;
+        File jstackFile = new File(JSTACK_OUT_FILE);
+        Asserts.assertTrue(jstackFile.exists() && jstackFile.isFile(),
+                           "File with jstack output not created: " +
+                           jstackFile.getAbsolutePath());
+        try {
+            Scanner scanner = new Scanner(jstackFile);
+
+            boolean classLockOwnerFound = false;
+            boolean classLockWaiterFound = false;
+            boolean objectLockOwnerFound = false;
+            boolean primitiveLockOwnerFound = false;
+
+            while (scanner.hasNextLine()) {
+                String line = scanner.nextLine();
+                System.out.println(line);
+
+                if (line.contains("missing reason for ")) {
+                    unexpected = new RuntimeException("Unexpected msg: missing reason for ");
+                    break;
+                }
+                if (line.matches("^\\s+- locked <0x[0-9a-f]+> \\(a java\\.lang\\.Class for LingeredAppWithLock\\)$")) {
+                    classLockOwnerFound = true;
+                }
+                if (line.matches("^\\s+- waiting to lock <0x[0-9a-f]+> \\(a java\\.lang\\.Class for LingeredAppWithLock\\)$")) {
+                    classLockWaiterFound = true;
+                }
+                if (line.matches("^\\s+- locked <0x[0-9a-f]+> \\(a java\\.lang\\.Thread\\)$")) {
+                    objectLockOwnerFound = true;
+                }
+                if (line.matches("^\\s+- locked <0x[0-9a-f]+> \\(a java\\.lang\\.Class for int\\)$")) {
+                    primitiveLockOwnerFound = true;
+                }
+            }
+
+            if (!classLockOwnerFound || !classLockWaiterFound ||
+                !objectLockOwnerFound || !primitiveLockOwnerFound) {
+                unexpected = new RuntimeException(
+                      "classLockOwnerFound = " + classLockOwnerFound +
+                      ", classLockWaiterFound = " + classLockWaiterFound +
+                      ", objectLockOwnerFound = " + objectLockOwnerFound +
+                      ", primitiveLockOwnerFound = " + primitiveLockOwnerFound);
+            }
+            if (unexpected != null) {
+                throw unexpected;
+            }
+        } catch (Exception ex) {
+            throw new RuntimeException("Test ERROR " + ex, ex);
+        } finally {
+            jstackFile.delete();
+        }
+    }
+
+    private static void startClhsdbForLock(long lingeredAppPid) throws Exception {
+
+        Process p;
+        JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK("jhsdb");
+        launcher.addToolArg("clhsdb");
+        launcher.addToolArg("--pid");
+        launcher.addToolArg(Long.toString(lingeredAppPid));
+
+        ProcessBuilder pb = new ProcessBuilder();
+        pb.command(launcher.getCommand());
+        System.out.println(pb.command().stream().collect(Collectors.joining(" ")));
+
+        try {
+            p = pb.start();
+        } catch (Exception attachE) {
+            throw new Error("Couldn't start jhsdb or attach to LingeredApp : " + attachE);
+        }
+
+        // Issue the 'jstack' input at the clhsdb prompt.
+        OutputStream input = p.getOutputStream();
+        String str = "jstack > " + JSTACK_OUT_FILE + "\nquit\n";
+        try {
+            input.write(str.getBytes());
+            input.flush();
+        } catch (IOException ioe) {
+            throw new Error("Problem issuing the jstack command: " + str, ioe);
+        }
+
+        try {
+            p.waitFor();
+        } catch (InterruptedException ie) {
+            throw new Error("Problem awaiting the child process: " + ie, ie);
+        }
+
+        int exitValue = p.exitValue();
+        if (exitValue != 0) {
+            String output;
+            try {
+                output = new OutputAnalyzer(p).getOutput();
+            } catch (IOException ioe) {
+                throw new Error("Can't get failed clhsdb process output: " + ioe, ioe);
+            }
+            throw new AssertionError("clhsdb wasn't run successfully: " + output);
+        }
+    }
+
+    public static void main (String... args) throws Exception {
+
+        LingeredApp app = null;
+
+        if (!Platform.shouldSAAttach()) {
+            System.out.println("SA attach not expected to work - test skipped.");
+            return;
+        }
+
+        try {
+            List<String> vmArgs = new ArrayList<String>(Utils.getVmOptions());
+
+            app = new LingeredAppWithLock();
+            LingeredApp.startApp(vmArgs, app);
+            System.out.println ("Started LingeredApp with pid " + app.getPid());
+            startClhsdbForLock(app.getPid());
+            verifyJStackOutput();
+        } finally {
+            LingeredApp.stopApp(app);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/serviceability/sa/TestJhsdbJstackLock.java	Mon Nov 27 17:04:45 2017 +0000
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2017, 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 java.io.IOException;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.List;
+import jdk.test.lib.apps.LingeredApp;
+import jdk.test.lib.Asserts;
+import jdk.test.lib.JDKToolLauncher;
+import jdk.test.lib.Platform;
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.process.ProcessTools;
+import jdk.test.lib.Utils;
+
+/*
+ * @test
+ * @library /test/lib
+ * @run main/othervm TestJhsdbJstackLock
+ */
+
+public class TestJhsdbJstackLock {
+
+    public static void main (String... args) throws Exception {
+
+        LingeredApp app = null;
+
+        if (!Platform.shouldSAAttach()) {
+            System.out.println("SA attach not expected to work - test skipped.");
+            return;
+        }
+
+        try {
+            List<String> vmArgs = new ArrayList<String>(Utils.getVmOptions());
+
+            app = new LingeredAppWithLock();
+            LingeredApp.startApp(vmArgs, app);
+            System.out.println ("Started LingeredApp with pid " + app.getPid());
+
+            JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK("jhsdb");
+            launcher.addToolArg("jstack");
+            launcher.addToolArg("--pid");
+            launcher.addToolArg(Long.toString(app.getPid()));
+
+            ProcessBuilder pb = new ProcessBuilder();
+            pb.command(launcher.getCommand());
+            Process jhsdb = pb.start();
+
+            jhsdb.waitFor();
+
+            OutputAnalyzer out = new OutputAnalyzer(jhsdb);
+            System.out.println(out.getStdout());
+            System.err.println(out.getStderr());
+
+            out.shouldMatch("^\\s+- locked <0x[0-9a-f]+> \\(a java\\.lang\\.Class for LingeredAppWithLock\\)$");
+            out.shouldMatch("^\\s+- waiting to lock <0x[0-9a-f]+> \\(a java\\.lang\\.Class for LingeredAppWithLock\\)$");
+            out.shouldMatch("^\\s+- locked <0x[0-9a-f]+> \\(a java\\.lang\\.Thread\\)$");
+            out.shouldMatch("^\\s+- locked <0x[0-9a-f]+> \\(a java\\.lang\\.Class for int\\)$");
+            out.stderrShouldBeEmpty();
+
+            System.out.println("Test Completed");
+        } finally {
+            LingeredApp.stopApp(app);
+        }
+    }
+}
--- a/test/jdk/ProblemList.txt	Fri Nov 24 17:19:47 2017 +0000
+++ b/test/jdk/ProblemList.txt	Mon Nov 27 17:04:45 2017 +0000
@@ -245,8 +245,6 @@
 
 # jdk_swing
 
-sanity/client/SwingSet/src/ButtonDemoScreenshotTest.java        8157338 generic-all
-
 ############################################################################
 
 # jdk_text
--- a/test/jdk/TEST.ROOT	Fri Nov 24 17:19:47 2017 +0000
+++ b/test/jdk/TEST.ROOT	Mon Nov 27 17:04:45 2017 +0000
@@ -17,7 +17,7 @@
 keys=2d dnd headful i18n intermittent printer randomness
 
 # Tests that must run in othervm mode
-othervm.dirs=java/awt java/beans javax/accessibility javax/imageio javax/sound javax/print javax/management com/sun/awt sun/awt sun/java2d sun/pisces javax/xml/jaxp/testng/validation java/lang/ProcessHandle
+othervm.dirs=java/awt java/beans javax/accessibility javax/imageio javax/sound javax/print javax/management com/sun/awt sun/awt sun/java2d javax/xml/jaxp/testng/validation java/lang/ProcessHandle
 
 # Tests that cannot run concurrently
 exclusiveAccess.dirs=java/rmi/Naming java/util/prefs sun/management/jmxremote sun/tools/jstatd sun/security/mscapi java/util/stream java/util/Arrays/largeMemory java/util/BitSet/stream javax/rmi com/sun/corba/cachedSocket
--- a/test/jdk/TEST.groups	Fri Nov 24 17:19:47 2017 +0000
+++ b/test/jdk/TEST.groups	Mon Nov 27 17:04:45 2017 +0000
@@ -324,7 +324,6 @@
 
 jdk_2d = \
     javax/print \
-    sun/pisces  \
     sun/java2d
 
 jdk_beans = \
@@ -426,445 +425,5 @@
     :jdk_sctp \
     javax/accessibility \
     com/sun/java/swing \
-    sun/pisces \
     com/sun/awt
 
-
-###############################################################################
-# Profile-based Test Group Definitions
-#
-# These groups define the tests that cover the different possible runtimes:
-# - compact1, compact2, compact3, full JRE, JDK
-#
-# In addition they support testing of the minimal VM on compact1 and compact2.
-# Essentially this defines groups based around the specified API's and VM
-# services available in the runtime.
-#
-# The groups are defined hierarchically in two forms:
-# - The need_xxx groups list all the tests that have a dependency on
-# a specific profile. This is either because it tests a feature in
-# that profile, or the test infrastructure uses a feature in that
-# profile.
-# - The primary groups are defined in terms of the other primary groups
-# combined with the needs_xxx groups (including and excluding them as
-# appropriate). For example the jre can run all tests from compact3, plus
-# those from needs_jre, but excluding those from need_jdk.
-#
-# The bottom group defines all the actual tests to be considered, simply
-# by listing the top-level test directories.
-
-# Full JDK can run all tests
-#
-jdk = \
-  :jre \
-  :needs_jdk
-
-# Tests that require a full JDK to execute. Either they test a feature
-# only in the JDK or they use tools that are only in the JDK. The latter
-# can be resolved in some cases by using tools from the compile-jdk.
-#
-needs_jdk = \
-  :jdk_jdi \
-  com/sun/tools \
-  jdk/security/jarsigner \
-  sun/security/tools/jarsigner \
-  sun/rmi/rmic \
-  sun/tools \
-  sun/jvmstat \
-  tools \
-  com/sun/jmx/remote/NotificationMarshalVersions/TestSerializationMismatch.java \
-  java/io/Serializable/serialver \
-  java/lang/invoke/lambda/LambdaAccessControlDoPrivilegedTest.java \
-  java/lang/invoke/lambda/LambdaAccessControlTest.java \
-  java/lang/invoke/lambda/LambdaAsm.java \
-  java/lang/System/MacEncoding/TestFileEncoding.java \
-  java/net/URLClassLoader/closetest/GetResourceAsStream.java \
-  java/util/Collections/EmptyIterator.java \
-  java/util/concurrent/locks/Lock/TimedAcquireLeak.java \
-  java/util/jar/JarInputStream/ExtraFileInMetaInf.java \
-  java/util/logging/TestLoggerWeakRefLeak.java \
-  java/util/zip/3GBZipFiles.sh \
-  jdk/lambda/separate/Compiler.java \
-  sun/management/jmxremote/bootstrap/JvmstatCountersTest.java \
-  sun/management/jmxremote/bootstrap/LocalManagementTest.java \
-  sun/management/jmxremote/bootstrap/CustomLauncherTest.java \
-  sun/misc/JarIndex/metaInfFilenames/Basic.java \
-  sun/misc/JarIndex/JarIndexMergeForClassLoaderTest.java \
-  jdk/internal/reflect/CallerSensitive/CallerSensitiveFinder.java \
-  jdk/internal/reflect/CallerSensitive/MissingCallerSensitive.java \
-  sun/security/util/Resources/NewNamesFormat.java \
-  vm/verifier/defaultMethods/DefaultMethodRegressionTestsRun.java \
-  javax/xml/ws/clientjar/TestWsImport.java \
-  javax/xml/bind/xjc/8145039/JaxbMarshallTest.java
-
-# JRE adds further tests to compact3
-#
-jre = \
-  :compact3 \
-  :needs_jre \
- -:needs_jdk
-
-# Tests that require the full JRE
-#
-needs_jre = \
-  :needs_charsets \
-  :jdk_desktop \
-  com/sun/corba \
-  com/sun/jndi/cosnaming \
-  com/oracle/security/ucrypto/Test8004873.java \
-  com/oracle/security/ucrypto/TestAES.java \
-  com/oracle/security/ucrypto/TestDigest.java \
-  com/oracle/security/ucrypto/TestRSA.java \
-  sun/net/ftp \
-  sun/net/www/protocol/ftp \
-  java/net/URI/URItoURLTest.java \
-  java/net/URL/URIToURLTest.java \
-  java/net/URLConnection/HandleContentTypeWithAttrs.java \
-  java/security/Security/ClassLoaderDeadlock/ClassLoaderDeadlock.sh \
-  java/security/Security/ClassLoaderDeadlock/Deadlock.sh \
-  java/text/AttributedCharacterIterator/Attribute/ReadResolve.java \
-  java/text/AttributedString/TestAttributedStringCtor.java \
-  java/text/AttributedString/getRunStartLimitTest.java \
-  java/util/jar/Manifest/CreateManifest.java \
-  java/util/logging/TestMainAppContext.java \
-  java/util/logging/TestLoggingWithMainAppContext.java \
-  java/util/TimeZone/DefaultTimeZoneTest.java \
-  java/text/Bidi/BidiConformance.java \
-  java/text/Bidi/BidiEmbeddingTest.java \
-  java/text/Bidi/Bug7042148.java \
-  java/text/Bidi/Bug7051769.java \
-  javax/crypto/Cipher/CipherStreamClose.java \
-  javax/management/monitor/AttributeArbitraryDataTypeTest.java \
-  javax/management/mxbean/AmbiguousConstructorTest.java \
-  javax/management/mxbean/ExceptionDiagnosisTest.java \
-  javax/management/mxbean/LeakTest.java \
-  javax/management/mxbean/MXBeanTest.java \
-  javax/management/mxbean/PropertyNamesTest.java \
-  jdk/lambda/vm/InterfaceAccessFlagsTest.java \
-  sun/misc/URLClassPath/ClassnameCharTest.java
-
-# Tests dependent on the optional charsets.jar
-# These are isolated for easy exclusions
-#
-needs_charsets = \
-  -:needs_locales_and_charsets \
-  java/io/OutputStreamWriter/TestWrite.java \
-  java/nio/charset/RemovingSunIO/SunioAlias.java \
-  java/nio/charset/coders/Check.java \
-  java/nio/charset/Charset/CharsetContainmentTest.java \
-  java/nio/charset/Charset/Contains.java \
-  java/nio/charset/Charset/NIOCharsetAvailabilityTest.java \
-  java/nio/charset/Charset/RegisteredCharsets.java \
-  java/nio/charset/CharsetEncoder/Flush.java \
-  java/nio/charset/coders/ResetISO2022JP.java \
-  java/util/Locale/InternationalBAT.java \
-  java/util/Locale/LocaleProviders.sh \
-  java/util/Calendar/CldrFormatNamesTest.java \
-  java/util/TimeZone/CLDRDisplayNamesTest.java \
-  java/util/zip/ZipCoding.java \
-  sun/nio/cs/EucJpLinux0212.java \
-  sun/nio/cs/EUCJPUnderflowDecodeTest.java \
-  sun/nio/cs/EuroConverter.java \
-  sun/nio/cs/JISAutoDetectTest.java \
-  sun/nio/cs/OLD/TestIBMDB.java \
-  sun/nio/cs/SJISCanEncode.java \
-  sun/nio/cs/Test6254467.java \
-  sun/nio/cs/TestCp834_SBCS.java \
-  sun/nio/cs/TestEUC_TW.java \
-  sun/nio/cs/TestISO2022CNDecoder.java \
-  sun/nio/cs/TestISO2022JPEncoder.java \
-  sun/nio/cs/TestISO2022JPSubBytes.java \
-  sun/nio/cs/TestIllegalSJIS.java \
-  sun/nio/cs/TestJIS0208Decoder.java \
-  sun/nio/cs/TestJIS0212Decoder.java \
-  sun/nio/cs/TestMiscEUC_JP.java \
-  sun/nio/cs/TestSJIS0213_SM.java \
-  sun/nio/cs/BufferUnderflowEUCTWTest.java \
-  sun/nio/cs/CheckCaseInsensitiveEncAliases.java \
-  sun/nio/cs/CheckHistoricalNames.java \
-  sun/nio/cs/EucJpLinuxDecoderRecoveryTest.java \
-  sun/nio/cs/HWKatakanaMS932EncodeTest.java \
-  sun/nio/cs/ISCIITest.java \
-  sun/nio/cs/LatinCharReplacementTWTest.java \
-  sun/nio/cs/NIOJISAutoDetectTest.java \
-  sun/nio/cs/StreamEncoderClose.java \
-  sun/nio/cs/SurrogateGB18030Test.java \
-  sun/nio/cs/SurrogateTestEUCTW.java \
-  sun/nio/cs/SurrogateTestHKSCS.java \
-  sun/nio/cs/TestConverterDroppedCharacters.java \
-  sun/nio/cs/TestCp93xSISO.java \
-  sun/nio/cs/TestIBM1364.java \
-  sun/nio/cs/TestIBMBugs.java \
-  sun/nio/cs/TestIllegalISO2022Esc.java \
-  sun/nio/cs/TestISO2022JP.java \
-  sun/nio/cs/TestMS5022X.java \
-  sun/nio/cs/TestSJIS0213.java \
-  sun/nio/cs/TestTrailingEscapesISO2022JP.java \
-  sun/nio/cs/TestUni2HKSCS.java \
-  sun/nio/cs/ZeroedByteArrayEUCTWTest.java
-
-# Compact 3 adds further tests to compact2
-#
-compact3 = \
-  :compact2 \
-  :needs_compact3 \
- -:needs_jre \
- -:needs_jdk
-
-
-# Tests that require compact3 API's
-#
-needs_compact3 = \
-  :jdk_instrument \
-  :jdk_jmx \
-  :jdk_management \
-  :jdk_sctp \
-  com/sun/jndi \
-  com/sun/org/apache/xml/internal/security \
-  com/sun/security/auth \
-  com/sun/security/sasl \
-  com/sun/security/jgss \
-  java/util/prefs \
-  javax/naming \
-  javax/security \
-  javax/smartcardio \
-  javax/sql/rowset \
-  javax/xml/crypto \
-  sun/security/jgss \
-  sun/security/krb5 \
-  java/lang/annotation/AnnotationType/AnnotationTypeDeadlockTest.java \
-  java/lang/invoke/lambda/LambdaStackTrace.java \
-  java/lang/invoke/LFCaching/LFGarbageCollectedTest.java \
-  java/lang/invoke/LFCaching/LFMultiThreadCachingTest.java \
-  java/lang/invoke/LFCaching/LFSingleThreadCachingTest.java \
-  java/lang/System/MacEncoding/TestFileEncoding.java \
-  java/nio/channels/AsynchronousSocketChannel/Leaky.java \
-  java/security/PermissionCollection/Concurrent.java \
-  java/security/Principal/Implies.java \
-  java/security/cert/GetInstance.java \
-  java/util/Arrays/largeMemory/ParallelPrefix.java  \
-  java/util/logging/DrainFindDeadlockTest.java \
-  java/util/logging/LoggingMXBeanTest.java \
-  java/util/logging/TestLogConfigurationDeadLock.java \
-  java/util/logging/TestLoggerBundleSync.java \
-  sun/net/www/http/KeepAliveCache/B5045306.java \
-  sun/security/provider/PolicyFile/Alias.java \
-  sun/security/provider/PolicyFile/Comparator.java \
-  sun/security/provider/PolicyFile/SelfWildcard.java \
-  sun/security/ssl/SSLEngineImpl/SSLEngineDeadlock.java \
-  sun/security/util/Oid/OidFormat.java \
-  sun/security/util/Resources/Format.java \
-  sun/security/util/Resources/NewNamesFormat.java
-
-# Compact 2 adds full VM tests
-compact2 = \
-  :compact2_minimal \
-  :compact1 \
-  :needs_full_vm_compact2 \
- -:needs_compact3 \
- -:needs_jre \
- -:needs_jdk
-
-# Tests that require compact2 API's and a full VM
-#
-needs_full_vm_compact2 =
-
-# Minimal VM on Compact 2 adds in some compact2 tests
-#
-compact2_minimal = \
-  :compact1_minimal \
-  :needs_compact2 \
- -:needs_compact3 \
- -:needs_jre \
- -:needs_jdk
-
-# Tests that require compact2 API's
-#
-needs_compact2 = \
-  :jdk_rmi \
-  :jdk_time \
-  com/sun/org/apache \
-  com/sun/net/httpserver \
-  java/sql \
-  javax/sql \
-  javax/xml \
-  jdk/lambda \
-  sun/net/www/http \
-  sun/net/www/protocol/http \
-  java/io/BufferedReader/Lines.java  \
-  java/lang/reflect/DefaultStaticTest/DefaultStaticInvokeTest.java \
-  java/lang/IntegralPrimitiveToString.java  \
-  java/lang/PrimitiveSumMinMaxTest.java  \
-  java/lang/String/StringJoinTest.java  \
-  java/lang/Thread/StopThrowable.java  \
-  java/net/Authenticator/B4769350.java \
-  java/net/Authenticator/Deadlock.java \
-  java/net/CookieHandler/LocalHostCookie.java \
-  java/net/CookieHandler/CookieManagerTest.java \
-  java/net/CookieHandler/EmptyCookieHeader.java \
-  java/net/HttpCookie/IllegalCookieNameTest.java \
-  java/net/HttpURLConnection/UnmodifiableMaps.java \
-  java/net/ResponseCache/Test.java \
-  java/net/URLClassLoader/ClassLoad.java \
-  java/net/URLClassLoader/closetest/CloseTest.java \
-  java/net/URLPermission/URLTest.java \
-  java/nio/Buffer/Chars.java  \
-  java/nio/file/Files/StreamTest.java  \
-  java/security/BasicPermission/Wildcard.java \
-  java/util/Arrays/SetAllTest.java  \
-  java/util/BitSet/stream/BitSetStreamTest.java  \
-  java/util/Collection/CollectionDefaults.java  \
-  java/util/Collections/CheckedIdentityMap.java  \
-  java/util/Collections/CheckedMapBash.java  \
-  java/util/Collections/CheckedSetBash.java  \
-  java/util/Collections/EmptyCollectionSerialization.java  \
-  java/util/Collections/EmptyNavigableMap.java  \
-  java/util/Collections/EmptyNavigableSet.java  \
-  java/util/Collections/UnmodifiableMapEntrySet.java  \
-  java/util/Comparator/BasicTest.java  \
-  java/util/Comparator/TypeTest.java  \
-  java/util/Date/TimestampTest.java \
-  java/util/Iterator/IteratorDefaults.java  \
-  java/util/Iterator/PrimitiveIteratorDefaults.java  \
-  java/util/List/ListDefaults.java  \
-  java/util/Map/BasicSerialization.java  \
-  java/util/Map/Defaults.java  \
-  java/util/Map/EntryComparators.java  \
-  java/util/Optional/Basic.java  \
-  java/util/Optional/BasicDouble.java  \
-  java/util/Optional/BasicInt.java  \
-  java/util/Optional/BasicLong.java  \
-  java/util/Random/RandomStreamTest.java  \
-  java/util/ResourceBundle/Bug6359330.java  \
-  java/util/Spliterator/SpliteratorCharacteristics.java  \
-  java/util/Spliterator/SpliteratorCollisions.java  \
-  java/util/Spliterator/SpliteratorLateBindingTest.java  \
-  java/util/Spliterator/SpliteratorFailFastTest.java  \
-  java/util/Spliterator/SpliteratorTraversingAndSplittingTest.java  \
-  java/util/StringJoiner/MergeTest.java  \
-  java/util/StringJoiner/StringJoinerTest.java  \
-  java/util/concurrent/atomic/AtomicReferenceTest.java  \
-  java/util/function/BinaryOperator/BasicTest.java  \
-  java/util/logging/LoggerSupplierAPIsTest.java  \
-  java/util/zip/ZipFile/StreamZipEntriesTest.java \
-  java/util/zip/ZipFile/DeleteTempJar.java \
-  javax/crypto/Cipher/CipherStreamClose.java \
-  sun/net/www/protocol/https/HttpsURLConnection/HttpsCreateSockTest.java \
-  sun/net/www/protocol/https/HttpsURLConnection/HttpsSocketFacTest.java
-
-# Compact 1 adds full VM tests
-#
-compact1 = \
-  :compact1_minimal \
-  :needs_full_vm_compact1 \
- -:needs_compact2 \
- -:needs_full_vm_compact2 \
- -:needs_compact3 \
- -:needs_jre \
- -:needs_jdk
-
-# Tests that require compact1 API's and a full VM
-#
-needs_full_vm_compact1 =
-
-# All tests that run on the most minimal configuration: Minimal VM on Compact 1
-compact1_minimal = \
-  com \
-  java \
-  javax \
-  jdk \
-  lib \
-  sun \
-  vm \
- -:needs_full_vm_compact1 \
- -:needs_full_vm_compact2 \
- -:needs_compact2 \
- -:needs_compact3 \
- -:needs_jre \
- -:needs_jdk
-
-needs_headful = \
-  java/util/TimeZone/DefaultTimeZoneTest.java
-
-needs_locales = \
-  -:needs_locales_and_charsets \
-  java/text/Collator/APITest.java \
-  java/text/Collator/CollationKeyTest.java \
-  java/text/Collator/DanishTest.java \
-  java/text/Collator/FinnishTest.java \
-  java/text/Collator/FrenchTest.java \
-  java/text/Collator/G7Test.java \
-  java/text/Collator/JapaneseTest.java \
-  java/text/Collator/KoreanTest.java \
-  java/text/Collator/Regression.java \
-  java/text/Collator/TurkishTest.java \
-  java/text/Collator/VietnameseTest.java \
-  java/text/Format/DateFormat/bug4117335.java \
-  java/text/Format/DateFormat/DateFormatTest.java \
-  java/text/Format/DateFormat/IntlTestDateFormatSymbols.java \
-  java/text/Format/DateFormat/NonGregorianFormatTest.java \
-  java/text/Format/NumberFormat/IntlTestNumberFormatAPI.java \
-  java/text/Format/NumberFormat/NumberRegression.java \
-  java/text/Format/NumberFormat/NumberTest.java \
-  java/util/Calendar/Bug4302966.java \
-  java/util/TimeZone/HongKong.java \
-  java/util/TimeZone/TimeZoneTest.java \
-  java/util/Calendar/NarrowNamesTest.sh \
-  java/util/Locale/Bug8001562.java \
-  java/util/Locale/InternationalBAT.java \
-  java/util/Locale/LocaleEnhanceTest.java \
-  java/util/Locale/LocaleTest.java \
-  java/util/Locale/ThaiGov.java \
-  java/text/Format/DateFormat/Bug4823811.java \
-  java/text/Format/DateFormat/Bug6683975.java \
-  java/text/Format/DateFormat/ContextMonthNamesTest.java \
-  java/text/Format/DecimalFormat/RoundingAndPropertyTest.java \
-  java/time/test/java/time/format/TestDateTimeFormatterBuilder.java \
-  java/time/test/java/time/format/TestDateTimeTextProvider.java \
-  java/time/test/java/time/format/TestNonIsoFormatter.java \
-  java/time/test/java/time/format/TestTextParser.java \
-  java/time/test/java/time/format/TestTextPrinter.java \
-  java/util/Currency/CurrencyTest.java \
-  java/util/Formatter/Basic.java \
-  sun/text/resources/Collator/Bug4248694.java \
-  sun/text/resources/Collator/Bug4804273.java \
-  sun/text/resources/Collator/Bug6755060.java \
-  sun/text/resources/Format/Bug4395196.java \
-  sun/text/resources/Format/Bug4442855.java \
-  sun/text/resources/Format/Bug4621320.java \
-  sun/text/resources/Format/Bug4651568.java \
-  sun/text/resources/Format/Bug4762201.java \
-  sun/text/resources/Format/Bug4807540.java \
-  sun/text/resources/Format/Bug4810032.java \
-  sun/text/resources/Format/Bug4994312.java \
-  sun/text/resources/Format/Bug5096553.java \
-  sun/text/resources/LocaleDataTest.java \
-  sun/util/resources/Calendar/Bug4518811.java \
-  sun/util/resources/Calendar/Bug4527203.java \
-  sun/util/resources/Locale/Bug4429024.java \
-  sun/util/resources/Locale/Bug4965260.java \
-  sun/util/resources/Locale/Bug6275682.java \
-  sun/util/resources/TimeZone/Bug6271396.java \
-  sun/util/resources/TimeZone/Bug6317929.java \
-  sun/util/resources/TimeZone/Bug6377794.java \
-  sun/util/resources/TimeZone/Bug6442006.java
-
-needs_locales_and_charsets = \
-  java/text/BreakIterator/NewVSOld_th_TH.java \
-  java/util/Locale/InternationalBAT.java
-
-needs_sunec = \
- -:needs_sunec_and_sunpkcs11 \
-  sun/security/ec/TestEC.java
-
-needs_sunpkcs11 = \
- -:needs_sunec_and_sunpkcs11 \
-  sun/security/pkcs11/Secmod \
-  sun/security/tools/keytool/autotest.sh
-
-needs_sunec_and_sunpkcs11 = \
-  sun/security/pkcs11/Secmod/AddPrivateKey.java \
-  sun/security/pkcs11/Secmod/TrustAnchors.java
-
-needs_nashorn = \
-  javax/script
--- a/test/jdk/java/awt/BasicStroke/DashStrokeTest.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/test/jdk/java/awt/BasicStroke/DashStrokeTest.java	Mon Nov 27 17:04:45 2017 +0000
@@ -24,7 +24,6 @@
  * @bug 8075942 8080932
  * @summary test there is no exception rendering a dashed stroke
  * @run main DashStrokeTest
- * @run main/othervm -Dsun.java2d.renderer=sun.java2d.pisces.PiscesRenderingEngine DashStrokeTest
  */
 
 import java.awt.BasicStroke;
--- a/test/jdk/java/awt/JAWT/JAWT.sh	Fri Nov 24 17:19:47 2017 +0000
+++ b/test/jdk/java/awt/JAWT/JAWT.sh	Mon Nov 27 17:04:45 2017 +0000
@@ -158,12 +158,10 @@
 
 JAVA=${TESTJAVA}${FS}bin${FS}java
 JAVAC=${TESTJAVA}${FS}bin${FS}javac
-JAVAH=${TESTJAVA}${FS}bin${FS}javah
 
 export CC SYST ARCH LD_LIBRARY_PATH
 
-${JAVAC} -d . ${TESTSRC}${FS}MyCanvas.java
-${JAVAH} -jni -classpath . -d . MyCanvas
+${JAVAC} -d . -h . ${TESTSRC}${FS}MyCanvas.java
 ${MAKE} -f ${MAKEFILE}
 ${JAVA} ${TESTVMOPTS} -classpath . MyCanvas
 
--- a/test/jdk/java/awt/JAWT/Makefile.cygwin	Fri Nov 24 17:19:47 2017 +0000
+++ b/test/jdk/java/awt/JAWT/Makefile.cygwin	Mon Nov 27 17:04:45 2017 +0000
@@ -26,7 +26,6 @@
 
 JAVA =		$(TESTJAVA)/bin/java -classpath .
 JAVAC =		$(TESTJAVA)/bin/javac
-JAVAH =		$(TESTJAVA)/bin/javah
 DEL =		rm -rf
 LINK =		$(CC)
 
--- a/test/jdk/java/awt/JAWT/Makefile.unix	Fri Nov 24 17:19:47 2017 +0000
+++ b/test/jdk/java/awt/JAWT/Makefile.unix	Mon Nov 27 17:04:45 2017 +0000
@@ -27,7 +27,6 @@
 ENV =		/usr/bin/env
 JAVA =		$(TESTJAVA)/bin/java -classpath .
 JAVAC =		$(TESTJAVA)/bin/javac
-JAVAH =		$(TESTJAVA)/bin/javah
 LINK =		ld
 
 J_INC =		$(TESTJAVA)/include
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/Package/PackageVersionTest.java	Mon Nov 27 17:04:45 2017 +0000
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2017, 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 8190987
+ * @summary Test verifies that individual Package.VersionInfo elements can be
+ *          supplied and retrieved even if no other elements are set.
+ * @run testng PackageVersionTest
+ */
+
+
+import java.net.URL;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+public class PackageVersionTest {
+
+    @Test
+    public static void testSpecTitle() {
+        TestClassLoader loader = new TestClassLoader();
+        Package p = loader.definePackage("testSpecTitle", "SpecTitle",
+                                         null, null, null,
+                                         null, null, null);
+        Assert.assertEquals(p.getSpecificationTitle(), "SpecTitle",
+                            "Package specification titles do not match!");
+    }
+
+    @Test
+    public static void testSpecVersion() {
+        TestClassLoader loader = new TestClassLoader();
+        Package p = loader.definePackage("testSpecVersion", null,
+                                         "1.0", null, null,
+                                         null, null, null);
+        Assert.assertEquals(p.getSpecificationVersion(), "1.0",
+                            "Package specification versions do not match!");
+    }
+
+    @Test
+    public static void testSpecVendor() {
+        TestClassLoader loader = new TestClassLoader();
+        Package p = loader.definePackage("testSpecVendor", null,
+                                         null, "SpecVendor", null,
+                                         null, null, null);
+        Assert.assertEquals(p.getSpecificationVendor(), "SpecVendor",
+                            "Package specification vendors do not match!");
+    }
+
+    @Test
+    public static void testImplTitle() {
+        TestClassLoader loader = new TestClassLoader();
+        Package p = loader.definePackage("testImplTitle", null,
+                                         null, null, "ImplTitle",
+                                         null, null, null);
+        Assert.assertEquals(p.getImplementationTitle(), "ImplTitle",
+                            "Package implementation titles do not match!");
+    }
+
+    @Test
+    public static void testImplVersion() {
+        TestClassLoader loader = new TestClassLoader();
+        Package p = loader.definePackage("testImplVersion", null,
+                                         null, null, null,
+                                         "1.0", null, null);
+        Assert.assertEquals(p.getImplementationVersion(), "1.0",
+                            "Package implementation versions do not match!");
+    }
+
+    @Test
+    public static void testImplVendor() {
+        TestClassLoader loader = new TestClassLoader();
+        Package p = loader.definePackage("testImplVendor", null,
+                                         null, null, null,
+                                         null, "ImplVendor", null);
+        Assert.assertEquals(p.getImplementationVendor(), "ImplVendor",
+                            "Package implementation vendors do not match!");
+    }
+}
+
+class TestClassLoader extends ClassLoader {
+    @Override
+    protected Package definePackage(String name, String specTitle,
+                                    String specVersion, String specVendor,
+                                    String implTitle, String implVersion,
+                                    String implVendor, URL sealBase) {
+        return super.definePackage(name, specTitle, specVersion, specVendor,
+                                   implTitle, implVersion, implVendor, sealBase);
+    }
+}
--- a/test/jdk/java/lang/String/concat/WithSecurityManager.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/test/jdk/java/lang/String/concat/WithSecurityManager.java	Mon Nov 27 17:04:45 2017 +0000
@@ -38,13 +38,13 @@
  * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT      WithSecurityManager
  * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT  WithSecurityManager
  *
- * @run main/othervm -Xverify:all --limit-modules=java.base,jdk.internal.vm.compiler WithSecurityManager
- * @run main/othervm -Xverify:all --limit-modules=java.base,jdk.internal.vm.compiler -Djava.lang.invoke.stringConcat=BC_SB                  WithSecurityManager
- * @run main/othervm -Xverify:all --limit-modules=java.base,jdk.internal.vm.compiler -Djava.lang.invoke.stringConcat=BC_SB_SIZED            WithSecurityManager
- * @run main/othervm -Xverify:all --limit-modules=java.base,jdk.internal.vm.compiler -Djava.lang.invoke.stringConcat=MH_SB_SIZED            WithSecurityManager
- * @run main/othervm -Xverify:all --limit-modules=java.base,jdk.internal.vm.compiler -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT      WithSecurityManager
- * @run main/othervm -Xverify:all --limit-modules=java.base,jdk.internal.vm.compiler -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT      WithSecurityManager
- * @run main/othervm -Xverify:all --limit-modules=java.base,jdk.internal.vm.compiler -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT  WithSecurityManager
+ * @run main/othervm -Xverify:all --limit-modules=java.base WithSecurityManager
+ * @run main/othervm -Xverify:all --limit-modules=java.base -Djava.lang.invoke.stringConcat=BC_SB                  WithSecurityManager
+ * @run main/othervm -Xverify:all --limit-modules=java.base -Djava.lang.invoke.stringConcat=BC_SB_SIZED            WithSecurityManager
+ * @run main/othervm -Xverify:all --limit-modules=java.base -Djava.lang.invoke.stringConcat=MH_SB_SIZED            WithSecurityManager
+ * @run main/othervm -Xverify:all --limit-modules=java.base -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT      WithSecurityManager
+ * @run main/othervm -Xverify:all --limit-modules=java.base -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT      WithSecurityManager
+ * @run main/othervm -Xverify:all --limit-modules=java.base -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT  WithSecurityManager
 */
 public class WithSecurityManager {
     public static void main(String[] args) throws Throwable {
--- a/test/jdk/java/lang/invoke/ArrayConstructorTest.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/test/jdk/java/lang/invoke/ArrayConstructorTest.java	Mon Nov 27 17:04:45 2017 +0000
@@ -88,4 +88,11 @@
         assertEquals(17, a.length);
     }
 
+    @Test(expectedExceptions = {NegativeArraySizeException.class})
+    public static void testArrayConstructorNegativeIndex() throws Throwable {
+        MethodHandle h = MethodHandles.arrayConstructor(String[].class);
+        assertEquals(methodType(String[].class, int.class), h.type());
+        h.invoke(-1); // throws exception
+    }
+
 }
--- a/test/jdk/java/lang/invoke/ArrayLengthTest.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/test/jdk/java/lang/invoke/ArrayLengthTest.java	Mon Nov 27 17:04:45 2017 +0000
@@ -78,4 +78,9 @@
         MethodHandles.arrayLength(null);
     }
 
+    @Test(expectedExceptions = NullPointerException.class)
+    public void testNullReference() throws Throwable {
+        MethodHandle arrayLength = MethodHandles.arrayLength(String[].class);
+        int len = (int)arrayLength.invokeExact((String[])null);
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/invoke/InvokeMethodHandleWithBadArgument.java	Mon Nov 27 17:04:45 2017 +0000
@@ -0,0 +1,164 @@
+/*
+ * Copyright (c) 2017, 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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 8157246
+ * @summary Tests invocation of MethodHandle with invalid leading argument
+ * @run testng/othervm test.java.lang.invoke.InvokeMethodHandleWithBadArgument
+ */
+
+package test.java.lang.invoke;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodHandles.Lookup;
+import java.lang.invoke.MethodType;
+import java.lang.invoke.VarHandle;
+
+import static java.lang.invoke.MethodType.methodType;
+
+import static org.testng.AssertJUnit.*;
+
+import org.testng.annotations.*;
+
+/**
+ * Tests invocation of MethodHandle with invalid leading argument such as
+ * MethodHandle, VarHandle, and array object
+ */
+public class InvokeMethodHandleWithBadArgument {
+    // ---- null array reference ----
+
+    @Test(expectedExceptions = {NullPointerException.class})
+    public static void testAsSpreaderPosInvokeWithNull() throws Throwable {
+        MethodHandle spreader = MH_spread.asSpreader(1, int[].class, 3);
+        spreader.invoke("A", null, "B");
+    }
+
+    @Test(expectedExceptions = {NullPointerException.class})
+    public static void testAsSpreaderInvokeWithNull() throws Throwable {
+        MethodHandle spreader = MH_String_equals.asSpreader(String[].class, 2);
+        assert ((boolean) spreader.invokeExact(new String[]{"me", "me"}));
+        boolean eq = (boolean) spreader.invokeExact((String[]) null);
+    }
+
+    // ---- incorrect array element count ----
+    @Test(expectedExceptions = {IllegalArgumentException.class})
+    public static void testAsSpreaderPosInvokeWithBadElementCount() throws Throwable {
+        MethodHandle spreader = MH_spread.asSpreader(1, int[].class, 3);
+        spreader.invoke("A", new int[]{1, 2}, "B");
+    }
+
+    @Test(expectedExceptions = {IllegalArgumentException.class})
+    public static void testAsSpreaderInvokeWithBadElementCount() throws Throwable {
+        MethodHandle spreader = MH_String_equals.asSpreader(String[].class, 2);
+        assert (!(boolean) spreader.invokeExact(new String[]{"me", "thee"}));
+        boolean eq = (boolean) spreader.invokeExact(new String[0]);
+    }
+
+    // ---- spread no argument ----
+    @Test
+    public static void testAsSpreaderPosInvokeWithZeroLength() throws Throwable {
+        MethodHandle spreader = MH_spread.asSpreader(1, int[].class, 0);
+        assert("A123B".equals(spreader.invoke("A", (int[])null, 1, 2, 3, "B")));
+    }
+
+    @Test
+    public static void testAsSpreaderInvokeWithZeroLength() throws Throwable {
+        MethodHandle spreader = MH_String_equals.asSpreader(String[].class, 0);
+        assert ((boolean) spreader.invokeExact("me", (Object)"me", new String[0]));
+        boolean eq = (boolean) spreader.invokeExact("me", (Object)"me", (String[]) null);
+    }
+
+    // ---- invokers with null method/var handle argument ----
+    @Test(expectedExceptions = {NullPointerException.class})
+    public static void testInvokerWithNull() throws Throwable {
+        MethodType type = methodType(int.class, int.class, int.class);
+        MethodHandle invoker = MethodHandles.invoker(type);
+        assert((int) invoker.invoke(MH_add, 1, 2) == 3);
+        int sum = (int)invoker.invoke((MethodHandle)null, 1, 2);
+    }
+
+    @Test(expectedExceptions = {NullPointerException.class})
+    public static void testExactInvokerWithNull() throws Throwable {
+        MethodType type = methodType(int.class, int.class, int.class);
+        MethodHandle invoker = MethodHandles.exactInvoker(type);
+        assert((int) invoker.invoke(MH_add, 1, 2) == 3);
+        int sum = (int)invoker.invokeExact((MethodHandle)null, 1, 2);
+    }
+
+    @Test(expectedExceptions = {NullPointerException.class})
+    public static void testSpreadInvokerWithNull() throws Throwable {
+        MethodType type = methodType(boolean.class, String.class, String.class);
+        MethodHandle invoker = MethodHandles.spreadInvoker(type, 0);
+        assert ((boolean) invoker.invoke(MH_String_equals, new String[]{"me", "me"}));
+        boolean eq = (boolean) invoker.invoke((MethodHandle)null, new String[]{"me", "me"});
+    }
+
+    @Test(expectedExceptions = {NullPointerException.class})
+    public static void testVarHandleInvokerWithNull() throws Throwable {
+        VarHandle.AccessMode am = VarHandle.AccessMode.GET;
+        MethodHandle invoker = MethodHandles.varHandleInvoker(am, VH_array.accessModeType(am));
+        assert ((int) invoker.invoke(VH_array, array, 3) == 3);
+        int value = (int)invoker.invoke((VarHandle)null, array, 3);
+    }
+
+    @Test(expectedExceptions = {NullPointerException.class})
+    public static void testVarHandleExactInvokerWithNull() throws Throwable {
+        VarHandle.AccessMode am = VarHandle.AccessMode.GET;
+        MethodHandle invoker = MethodHandles.varHandleExactInvoker(am, VH_array.accessModeType(am));
+        assert ((int) invoker.invoke(VH_array, array, 3) == 3);
+        int value = (int)invoker.invokeExact((VarHandle)null, array, 3);
+    }
+
+    static final Lookup LOOKUP = MethodHandles.lookup();
+    static final MethodHandle MH_add;
+    static final MethodHandle MH_spread;
+    static final MethodHandle MH_String_equals;
+    static final VarHandle VH_array;
+
+    static final int[] array = new int[] { 0, 1, 2, 3, 4, 5};
+    static {
+        try {
+            Class<?> arrayClass = Class.forName("[I");
+            VH_array = MethodHandles.arrayElementVarHandle(arrayClass);
+            MH_add = LOOKUP.findStatic(InvokeMethodHandleWithBadArgument.class, "add",
+                methodType(int.class, int.class, int.class));
+            MH_spread = LOOKUP.findStatic(InvokeMethodHandleWithBadArgument.class, "spread",
+                methodType(String.class, String.class, int.class, int.class, int.class, String.class));
+            MH_String_equals = LOOKUP.findVirtual(String.class, "equals", methodType(boolean.class, Object.class));
+        } catch (Exception e) {
+            throw new ExceptionInInitializerError(e);
+        }
+    }
+
+    static String spread(String s1, int i1, int i2, int i3, String s2) {
+        return s1 + i1 + i2 + i3 + s2;
+    }
+
+    static int add(int x, int y) {
+        return x+y;
+    }
+}
--- a/test/jdk/java/lang/invoke/JavaDocExamplesTest.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/test/jdk/java/lang/invoke/JavaDocExamplesTest.java	Mon Nov 27 17:04:45 2017 +0000
@@ -415,7 +415,7 @@
 assert(!(boolean) eq2.invokeExact(new Object[]{ "me", "thee" }));
 // try to spread from anything but a 2-array:
 for (int n = 0; n <= 10; n++) {
-  Object[] badArityArgs = (n == 2 ? null : new Object[n]);
+  Object[] badArityArgs = (n == 2 ? new Object[0] : new Object[n]);
   try { assert((boolean) eq2.invokeExact(badArityArgs) && false); }
   catch (IllegalArgumentException ex) { } // OK
 }
--- a/test/jdk/java/lang/invoke/SpreadCollectTest.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/test/jdk/java/lang/invoke/SpreadCollectTest.java	Mon Nov 27 17:04:45 2017 +0000
@@ -94,6 +94,21 @@
         MethodHandle s = h.asSpreader(String[].class, 1);
     }
 
+    @Test(expectedExceptions = {NullPointerException.class})
+    public static void testAsSpreaderNullArrayType() {
+        SpreadCollect.MH_forSpreading.asSpreader(null, 0);
+    }
+
+    @Test(expectedExceptions = {NullPointerException.class})
+    public static void testAsSpreaderNullArrayNonZeroLength() {
+        SpreadCollect.MH_forSpreading.asSpreader(null, 1);
+    }
+
+    @Test(expectedExceptions = {IllegalArgumentException.class})
+    public static void testAsSpreaderTooManyParams() throws Throwable {
+        SpreadCollect.MH_forSpreading.asSpreader(1, int[].class, 6);
+    }
+
     @Test
     public static void testAsCollector() throws Throwable {
         MethodHandle collector = SpreadCollect.MH_forCollecting.asCollector(1, int[].class, 1);
--- a/test/jdk/java/nio/channels/spi/SelectorProvider/inheritedChannel/Makefile	Fri Nov 24 17:19:47 2017 +0000
+++ b/test/jdk/java/nio/channels/spi/SelectorProvider/inheritedChannel/Makefile	Mon Nov 27 17:04:45 2017 +0000
@@ -68,11 +68,8 @@
 	$(CC) -c $(CFLAGS) -o $(LIBDIR)/Launcher.o \
 	    -I$(JAVA_HOME)/include -I$(JAVA_HOME)/include/$(PLATFORM) Launcher.c
 	
-Launcher.h : Launcher.class
-	$(JAVA_HOME)/bin/javah -force Launcher
-
-Launcher.class : Launcher.java
-	$(JAVA_HOME)/bin/javac Launcher.java
+Launcher.class Launcher.h : Launcher.java
+	$(JAVA_HOME)/bin/javac -h . Launcher.java
 
 java_home:
 ifndef JAVA_HOME
--- a/test/jdk/java/util/Locale/Bug8040211.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/test/jdk/java/util/Locale/Bug8040211.java	Mon Nov 27 17:04:45 2017 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017, 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,9 +23,9 @@
 
 /*
  * @test
- * @bug 8040211
+ * @bug 8040211 8191404
  * @summary Checks the IANA language subtag registry data updation
- *          (LSR Revision: 2016-02-10) with Locale and Locale.LanguageRange
+ *          (LSR Revision: 2017-08-15) with Locale and Locale.LanguageRange
  *          class methods.
  * @run main Bug8040211
  */
@@ -66,9 +66,9 @@
 
     private static void test_parse() {
         boolean error = false;
-        String str = "Accept-Language: aam, adp, aue, ema, en-gb-oed,"
-                + " gti, koj, kwq, kxe, lii, lmm, mtm, ngv, oyb, phr, pub,"
-                + " suj, taj;q=0.9, yug;q=0.5, gfx;q=0.4";
+        String str = "Accept-Language: aam, adp, aue, bcg, cqu, ema,"
+                + " en-gb-oed, gti, koj, kwq, kxe, lii, lmm, mtm, ngv,"
+                + " oyb, phr, pub, suj, taj;q=0.9, yug;q=0.5, gfx;q=0.4";
         ArrayList<LanguageRange> expected = new ArrayList<>();
         expected.add(new LanguageRange("aam", 1.0));
         expected.add(new LanguageRange("aas", 1.0));
@@ -76,6 +76,10 @@
         expected.add(new LanguageRange("dz", 1.0));
         expected.add(new LanguageRange("aue", 1.0));
         expected.add(new LanguageRange("ktz", 1.0));
+        expected.add(new LanguageRange("bcg", 1.0));
+        expected.add(new LanguageRange("bgm", 1.0));
+        expected.add(new LanguageRange("cqu", 1.0));
+        expected.add(new LanguageRange("quh", 1.0));
         expected.add(new LanguageRange("ema", 1.0));
         expected.add(new LanguageRange("uok", 1.0));
         expected.add(new LanguageRange("en-gb-oed", 1.0));
@@ -98,6 +102,8 @@
         expected.add(new LanguageRange("nnx", 1.0));
         expected.add(new LanguageRange("oyb", 1.0));
         expected.add(new LanguageRange("thx", 1.0));
+        expected.add(new LanguageRange("skk", 1.0));
+        expected.add(new LanguageRange("jeg", 1.0));
         expected.add(new LanguageRange("phr", 1.0));
         expected.add(new LanguageRange("pmu", 1.0));
         expected.add(new LanguageRange("pub", 1.0));
@@ -170,15 +176,15 @@
     private static void test_filter() {
         boolean error = false;
 
-        String ranges = "mtm-RU, en-gb-oed";
-        String tags = "de-DE, en, mtm-RU, ymt-RU, en-gb-oxendict, ja-JP";
+        String ranges = "mtm-RU, en-gb-oed, coy";
+        String tags = "de-DE, en, mtm-RU, ymt-RU, en-gb-oxendict, ja-JP, pij, nts";
         FilteringMode mode = EXTENDED_FILTERING;
 
         List<LanguageRange> priorityList = LanguageRange.parse(ranges);
         List<Locale> tagList = generateLocales(tags);
         String actualLocales
                 = showLocales(Locale.filter(priorityList, tagList, mode));
-        String expectedLocales = "mtm-RU, ymt-RU, en-GB-oxendict";
+        String expectedLocales = "mtm-RU, ymt-RU, en-GB-oxendict, nts, pij";
 
         if (!expectedLocales.equals(actualLocales)) {
             error = true;
@@ -212,14 +218,14 @@
     private static void test_filterTags() {
         boolean error = false;
 
-        String ranges = "gti;q=0.2, gfx";
-        String tags = "de-DE, gti, he, nyc, mwj, vaj";
+        String ranges = "gti;q=0.2, gfx, kzj";
+        String tags = "de-DE, gti, he, nyc, mwj, vaj, ktr, dtp";
 
         List<LanguageRange> priorityList = LanguageRange.parse(ranges);
         List<String> tagList = generateLanguageTags(tags);
         String actualTags
                 = showLanguageTags(Locale.filterTags(priorityList, tagList));
-        String expectedTags = "mwj, vaj, gti, nyc";
+        String expectedTags = "mwj, vaj, ktr, dtp, gti, nyc";
 
         if (!expectedTags.equals(actualTags)) {
             error = true;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/javax/imageio/plugins/png/PngNegativeDimensionTest.java	Mon Nov 27 17:04:45 2017 +0000
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2017, 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     8190512
+ * @summary Test verifies whether PNGImageReader throws IIOException with proper
+ *          message or not when IHDR chunk contains negative value for width
+ *          and height.
+ * @run     main PngNegativeDimensionTest
+ */
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.util.Base64;
+import javax.imageio.ImageIO;
+
+public class PngNegativeDimensionTest {
+
+    private static String negativeWidthString = "iVBORw0KGgoAAAANSUhEUoAAAAEAA"
+            + "AABCAAAAAA6fptVAAAACklEQVQYV2P4DwABAQEAWk1v8QAAAABJRU5ErkJgggo=";
+
+    private static String negativeHeightString = "iVBORw0KGgoAAAANSUhEUgAAAAGAA"
+            + "AABCAAAAAA6fptVAAAACklEQVQYV2P4DwABAQEAWk1v8QAAAABJRU5ErkJgggo=";
+
+    private static InputStream input;
+    private static Boolean failed = false;
+
+    public static void main(String[] args) {
+        // Create InputStream
+        byte[] inputBytes = Base64.getDecoder().decode(negativeWidthString);
+        input = new ByteArrayInputStream(inputBytes);
+        // Attempt to read PNG with negative IHDR width
+        readNegativeIHDRWidthImage();
+
+        inputBytes = Base64.getDecoder().decode(negativeHeightString);
+        input = new ByteArrayInputStream(inputBytes);
+        // Attempt to read PNG with negative IHDR height
+        readNegativeIHDRHeightImage();
+
+        if (failed) {
+            throw new RuntimeException("Test didnt throw proper IIOException"
+                    + " when IHDR width/height is negative");
+        }
+    }
+
+    private static void readNegativeIHDRWidthImage() {
+        try {
+            ImageIO.read(input);
+        } catch (Exception e) {
+            /*
+             * We expect the test case to throw IIOException with message
+             * under root cause as "Image width <= 0!". If it throws
+             * any other message or exception test will fail.
+             */
+            Throwable cause = e.getCause();
+            if (cause == null ||
+                (!(cause.getMessage().equals("Image width <= 0!"))))
+            {
+                failed = true;
+            }
+        }
+    }
+
+    private static void readNegativeIHDRHeightImage() {
+        try {
+            ImageIO.read(input);
+        } catch (Exception e) {
+            /*
+             * We expect the test case to throw IIOException with message
+             * under root cause as "Image height <= 0!". If it throws
+             * any other message or exception test will fail.
+             */
+            Throwable cause = e.getCause();
+            if (cause == null ||
+                (!(cause.getMessage().equals("Image height <= 0!"))))
+            {
+                failed = true;
+            }
+        }
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/javax/swing/JTextArea/TestTabSize.java	Mon Nov 27 17:04:45 2017 +0000
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2017, 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 8187957
+ * @summary  Verifies Tab Size works correctly in JTextArea
+ * @run main TestTabSize
+ */
+
+import java.awt.geom.Rectangle2D;
+import javax.swing.GroupLayout;
+import javax.swing.JFrame;
+import javax.swing.JScrollPane;
+import javax.swing.JTextArea;
+import javax.swing.SwingUtilities;
+import javax.swing.text.BadLocationException;
+import javax.swing.text.Caret;
+
+public class TestTabSize {
+    private static JScrollPane jScrollPane1;
+    private static JTextArea jTextArea1;
+    private static JFrame f;
+    private static Rectangle2D rect;
+    private static Rectangle2D rect1;
+    private static boolean excpnthrown = false;
+
+    public static void main(String args[]) throws Exception {
+
+        SwingUtilities.invokeAndWait(() -> {
+            try {
+                jScrollPane1 = new javax.swing.JScrollPane();
+                jTextArea1 = new javax.swing.JTextArea();
+                jTextArea1.setTabSize(8);
+                f = new JFrame();
+
+                jTextArea1.setFont(new java.awt.Font("Monospaced", 0, 10));
+                String str =
+                        "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!#\n"
+                        + "! Some Text\t\t\t\t\t#";
+                jTextArea1.setText(str);
+                jScrollPane1.setViewportView(jTextArea1);
+
+                GroupLayout layout = new javax.swing.GroupLayout(f.getContentPane());
+                f.getContentPane().setLayout(layout);
+                layout.setHorizontalGroup(
+                    layout.createParallelGroup(
+                            javax.swing.GroupLayout.Alignment.LEADING)
+                            .addGroup(layout.createSequentialGroup()
+                                    .addContainerGap()
+                                    .addComponent(jScrollPane1,
+                                            javax.swing.GroupLayout.DEFAULT_SIZE,
+                                            446, Short.MAX_VALUE)
+                                    .addContainerGap())
+                );
+                layout.setVerticalGroup(
+                        layout.createParallelGroup(
+                                javax.swing.GroupLayout.Alignment.LEADING)
+                                .addGroup(layout.createSequentialGroup()
+                                        .addContainerGap()
+                                        .addComponent(jScrollPane1)
+                                        .addContainerGap())
+                );
+
+                f.pack();
+                int first = str.indexOf("#");
+                jTextArea1.setCaretPosition(first);
+                Caret caret = jTextArea1.getCaret();
+                rect = jTextArea1.modelToView2D(caret.getDot());
+                System.out.println("caret x position " + rect.getX());
+
+                jTextArea1.setCaretPosition(str.indexOf("#", first+1));
+                caret = jTextArea1.getCaret();
+                rect1 = jTextArea1.modelToView2D(caret.getDot());
+                System.out.println("2nd caret x position " + rect1.getX());
+
+            } catch (BadLocationException ex) {
+                excpnthrown = true;
+            } finally {
+                f.dispose();
+            }
+        });
+        if (excpnthrown) {
+            throw new RuntimeException("BadLocationException thrown");
+        }
+        if ((int)rect.getX() != (int)rect1.getX()) {
+            throw new RuntimeException("Tab width calculation wrong");
+        }
+    }
+}
--- a/test/jdk/javax/swing/JWindow/ShapedAndTranslucentWindows/PerPixelTranslucent.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/test/jdk/javax/swing/JWindow/ShapedAndTranslucentWindows/PerPixelTranslucent.java	Mon Nov 27 17:04:45 2017 +0000
@@ -25,6 +25,7 @@
 
 /*
  * @test
+ * @bug 8164811
  * @key headful
  * @summary Check if a per-pixel translucent window is dragged and resized
  *          by mouse correctly.
@@ -42,6 +43,7 @@
  * @library ../../../../lib/testlibrary
  * @build Common ExtendedRobot
  * @run main PerPixelTranslucent
+ * @run main/othervm -Dsun.java2d.uiScale=1.5 PerPixelTranslucent
  */
 
 public class PerPixelTranslucent extends Common {
--- a/test/jdk/javax/swing/JWindow/ShapedAndTranslucentWindows/PerPixelTranslucentGradient.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/test/jdk/javax/swing/JWindow/ShapedAndTranslucentWindows/PerPixelTranslucentGradient.java	Mon Nov 27 17:04:45 2017 +0000
@@ -26,7 +26,7 @@
 /*
  * @test
  * @key headful
- * @bug 8032644
+ * @bug 8032644 8164811
  * @summary Check if a per-pixel translucent window is dragged and resized by
  *          mouse correctly
  * Test Description: Check if PERPIXEL_TRANSLUCENT translucency type is supported
@@ -44,6 +44,7 @@
  * @library ../../../../lib/testlibrary
  * @build Common ExtendedRobot
  * @run main PerPixelTranslucentGradient
+ * @run main/othervm -Dsun.java2d.uiScale=1.5 PerPixelTranslucentGradient
  */
 
 public class PerPixelTranslucentGradient extends Common {
--- a/test/jdk/javax/swing/JWindow/ShapedAndTranslucentWindows/PerPixelTranslucentSwing.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/test/jdk/javax/swing/JWindow/ShapedAndTranslucentWindows/PerPixelTranslucentSwing.java	Mon Nov 27 17:04:45 2017 +0000
@@ -26,6 +26,7 @@
 
 /*
  * @test
+ * @bug 8164811
  * @key headful
  * @summary Check if a per-pixel translucent window shows only the area having
  *          opaque pixels
@@ -40,6 +41,7 @@
  * @library ../../../../lib/testlibrary
  * @build Common ExtendedRobot
  * @run main PerPixelTranslucentSwing
+ * @run main/othervm -Dsun.java2d.uiScale=1.5 PerPixelTranslucentSwing
  */
 
 public class PerPixelTranslucentSwing extends Common {
--- a/test/jdk/javax/swing/JWindow/ShapedAndTranslucentWindows/ShapedPerPixelTranslucentGradient.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/test/jdk/javax/swing/JWindow/ShapedAndTranslucentWindows/ShapedPerPixelTranslucentGradient.java	Mon Nov 27 17:04:45 2017 +0000
@@ -26,7 +26,7 @@
 /*
  * @test
  * @key headful
- * @bug 7043845
+ * @bug 7043845 8164811
  * @summary Check if shaped and per-pixel translucent window is dragged and
  *          resized by mouse correctly.
  * Test Description: Check if PERPIXEL_TRANSLUCENT and PERPIXEL_TRANSPARENT
@@ -48,6 +48,7 @@
  * @library ../../../../lib/testlibrary
  * @build Common ExtendedRobot
  * @run main ShapedPerPixelTranslucentGradient
+ * @run main/othervm -Dsun.java2d.uiScale=1.5 ShapedPerPixelTranslucentGradient
  */
 
 public class ShapedPerPixelTranslucentGradient extends Common {
--- a/test/jdk/javax/swing/JWindow/ShapedAndTranslucentWindows/ShapedTranslucentPerPixelTranslucentGradient.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/test/jdk/javax/swing/JWindow/ShapedAndTranslucentWindows/ShapedTranslucentPerPixelTranslucentGradient.java	Mon Nov 27 17:04:45 2017 +0000
@@ -25,6 +25,7 @@
 
 /*
  * @test
+ * @bug 8164811
  * @key headful
  * @summary Check if shaped, translucent and per-pixel translucent window is
  *          dragged and resized by mouse correctly.
@@ -48,6 +49,7 @@
  * @library ../../../../lib/testlibrary
  * @build Common ExtendedRobot
  * @run main ShapedTranslucentPerPixelTranslucentGradient
+ * @run main/othervm -Dsun.java2d.uiScale=1.5 ShapedTranslucentPerPixelTranslucentGradient
  */
 
 public class ShapedTranslucentPerPixelTranslucentGradient extends Common {
--- a/test/jdk/javax/swing/JWindow/ShapedAndTranslucentWindows/TranslucentPerPixelTranslucentGradient.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/test/jdk/javax/swing/JWindow/ShapedAndTranslucentWindows/TranslucentPerPixelTranslucentGradient.java	Mon Nov 27 17:04:45 2017 +0000
@@ -25,7 +25,7 @@
 
 /*
  * @test
- * @bug 8144735
+ * @bug 8144735 8164811
  * @key headful
  * @summary Check if a per-pixel translucent and translucent window is dragged
  *          and resized by mouse correctly
@@ -46,6 +46,7 @@
  * @library ../../../../lib/testlibrary
  * @build Common ExtendedRobot
  * @run main TranslucentPerPixelTranslucentGradient
+ * @run main/othervm -Dsun.java2d.uiScale=1.5 TranslucentPerPixelTranslucentGradient
  */
 
 public class TranslucentPerPixelTranslucentGradient extends Common {
--- a/test/jdk/sanity/client/SwingSet/src/ButtonDemoScreenshotTest.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/test/jdk/sanity/client/SwingSet/src/ButtonDemoScreenshotTest.java	Mon Nov 27 17:04:45 2017 +0000
@@ -23,18 +23,21 @@
 
 import com.sun.swingset3.demos.button.ButtonDemo;
 import org.jtregext.GuiTestListener;
-import java.awt.Point;
-import java.awt.Robot;
-import java.awt.event.InputEvent;
-import java.awt.image.BufferedImage;
 import org.netbeans.jemmy.ClassReference;
+import org.netbeans.jemmy.ComponentChooser;
 import org.netbeans.jemmy.image.StrictImageComparator;
 import org.netbeans.jemmy.operators.JButtonOperator;
 import org.netbeans.jemmy.operators.JFrameOperator;
-import static org.jemmy2ext.JemmyExt.*;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Listeners;
 import org.testng.annotations.Test;
-import static com.sun.swingset3.demos.button.ButtonDemo.*;
-import org.testng.annotations.Listeners;
+
+import java.awt.Component;
+import java.awt.Robot;
+import java.awt.image.BufferedImage;
+
+import static com.sun.swingset3.demos.button.ButtonDemo.DEMO_TITLE;
+import static org.jemmy2ext.JemmyExt.*;
 
 /*
  * @test
@@ -55,7 +58,13 @@
 @Listeners(GuiTestListener.class)
 public class ButtonDemoScreenshotTest {
 
-    private static final int BUTTON_COUNT = 6; // TODO: Decide about "open browser" buttons (value was 8 originally)
+    private static final int[] BUTTONS = {0, 1, 2, 3, 4, 5}; // "open browser" buttons (6, 7) open a browser, so ignore
+    private static StrictImageComparator sComparator = null;
+
+    @BeforeClass
+    public void init() {
+        sComparator = new StrictImageComparator();
+    }
 
     @Test
     public void test() throws Exception {
@@ -67,32 +76,37 @@
         waitImageIsStill(rob, mainFrame);
 
         // Check all the buttons
-        for (int i = 0; i < BUTTON_COUNT; i++) {
+        for (int i : BUTTONS) {
             checkButton(mainFrame, i, rob);
         }
     }
 
-    public void checkButton(JFrameOperator jfo, int i, Robot rob) {
+    private void checkButton(JFrameOperator jfo, int i, Robot rob) {
         JButtonOperator button = new JButtonOperator(jfo, i);
-
-        Point loc = button.getLocationOnScreen();
-        rob.mouseMove(loc.x, loc.y);
+        button.moveMouse(button.getCenterX(), button.getCenterY());
 
         BufferedImage initialButtonImage = capture(rob, button);
         assertNotBlack(initialButtonImage);
-        save(initialButtonImage, "button" + i + "_0initial.png");
-        rob.mousePress(InputEvent.BUTTON1_MASK);
+        save(initialButtonImage, "button" + i + ".png");
+
+        BufferedImage[] pressedImage = new BufferedImage[1];
+
+        button.pressMouse();
         try {
             waitPressed(button);
-            BufferedImage pressedButtonImage = capture(rob, button);
-            assertNotBlack(pressedButtonImage);
-            save(pressedButtonImage, "button" + i + "_1pressed.png");
-
-            StrictImageComparator sComparator = new StrictImageComparator();
-            assertNotEquals("Button " + i + " Test", sComparator, initialButtonImage, pressedButtonImage);
+            button.waitState(new ComponentChooser() {
+                public boolean checkComponent(Component c) {
+                    pressedImage[0] = capture(rob, button);
+                    assertNotBlack(pressedImage[0]);
+                    return !sComparator.compare(initialButtonImage, pressedImage[0]);
+                }
+                public String getDescription() {
+                    return "Button with new image";
+                }
+            });
         } finally {
-            rob.mouseRelease(InputEvent.BUTTON1_MASK);
+            if(pressedImage[0] != null) save(pressedImage[0], "button" + i + "_pressed.png");
+            button.releaseMouse();
         }
     }
-
 }
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/FrameOperator.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/FrameOperator.java	Mon Nov 27 17:04:45 2017 +0000
@@ -30,6 +30,7 @@
 
 import org.netbeans.jemmy.ComponentChooser;
 import org.netbeans.jemmy.FrameWaiter;
+import org.netbeans.jemmy.JemmyException;
 import org.netbeans.jemmy.JemmyProperties;
 import org.netbeans.jemmy.Outputable;
 import org.netbeans.jemmy.TestOut;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/sun/java2d/marlin/DashStrokeTest.java	Mon Nov 27 17:04:45 2017 +0000
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2009, 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
+ * @summary verify that first element is a dash
+ * @bug 6793344
+ */
+
+import java.awt.*;
+import java.awt.image.*;
+
+import javax.swing.JButton;
+import javax.swing.JFrame;
+import javax.swing.SwingUtilities;
+import javax.swing.WindowConstants;
+
+public class DashStrokeTest extends Component {
+
+    static BufferedImage bi;
+    static boolean printed = false;
+
+    public Dimension getPreferredSize() {
+      return new Dimension(200,200);
+    }
+
+    public static void drawGui() {
+        bi = new BufferedImage(200, 20, BufferedImage.TYPE_INT_RGB);
+        Graphics2D g2d = bi.createGraphics();
+        BasicStroke dashStroke = new BasicStroke(1.0f, BasicStroke.CAP_ROUND,
+                BasicStroke.JOIN_ROUND, 1.0f, new float[] { 0.0f, 200 },
+                1.0f);
+
+        g2d.setStroke(dashStroke);
+        g2d.setColor(Color.RED);
+        g2d.drawLine(5,10, 100,10);
+        printed =true;
+    }
+
+    public static void main(String[] args) {
+            try {
+            SwingUtilities.invokeAndWait(new Runnable() {
+
+            @Override
+            public void run() {
+                drawGui();
+            }
+
+            });
+            } catch (Exception e) {
+            }
+
+            if (printed) {
+                checkBI(bi, Color.RED);
+            }
+    }
+
+    static void checkBI(BufferedImage bi, Color badColor) {
+      int badrgb = badColor.getRGB();
+
+      int col = bi.getRGB(6, 9);
+      if (col == badrgb) {
+          throw new RuntimeException("A pixel was turned on. ");
+      }
+   }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/sun/java2d/marlin/JoinMiterTest.java	Mon Nov 27 17:04:45 2017 +0000
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2009, 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
+ * @summary Pass if no RuntimeException.
+ * @bug 6812600
+ */
+import java.awt.*;
+import java.awt.image.BufferedImage;
+
+public class JoinMiterTest {
+
+  public static void main(String[] args) throws Exception {
+    BufferedImage image = new BufferedImage(200, 200,
+BufferedImage.TYPE_INT_RGB);
+    Graphics2D g = image.createGraphics();
+    g.setPaint(Color.WHITE);
+    g.fill(new Rectangle(image.getWidth(), image.getHeight()));
+    g.translate(25, 100);
+    g.setPaint(Color.BLACK);
+    g.setStroke(new BasicStroke(20, BasicStroke.CAP_BUTT,
+                                BasicStroke.JOIN_MITER));
+    g.draw(new Polygon(new int[] {0, 150, 0}, new int[] {75, 0, -75}, 3));
+    if (image.getRGB(16, 10) == Color.WHITE.getRGB()) {
+      throw new RuntimeException("Miter is not rendered.");
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/sun/java2d/marlin/OpenJDKFillBug.java	Mon Nov 27 17:04:45 2017 +0000
@@ -0,0 +1,173 @@
+/*
+ * Copyright (c) 2015, 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 java.awt.Color;
+import java.awt.Composite;
+import java.awt.CompositeContext;
+import java.awt.Graphics2D;
+import java.awt.RenderingHints;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.GeneralPath;
+import java.awt.image.BufferedImage;
+import java.awt.image.ColorModel;
+import java.awt.image.Raster;
+import java.awt.image.WritableRaster;
+import java.awt.image.RasterFormatException;
+
+/**
+ * @test
+ * @bug 8048782
+ * @summary Test program that demonstrates PiscesRendering bug in
+ * OpenJDK 1.7.0.60 (and probably in all other OpenJDK versions, too).
+ */
+
+public class OpenJDKFillBug
+{
+    /**
+     * Test program that demonstrates a bug in OpenJDK 1.7.0.60 (and
+     * probably in all other OpenJDK versions, too). To see the bug, simply run
+     * the 'main' program with OpenJDK. The bug makes the 'g2d.fill'
+     * method fail with the following exception:
+     *
+     * This bug is found in OpenJDK but also is present in OracleJDK
+     * if run with
+     * -Dsun.java2d.renderer=sun.java2d.pisces.PiscesRenderingEngine
+     *
+     * The bug is related to sun.java2d.pisces.PiscesCache constructor
+     * that accepts '(int minx,int miny,int maxx,int maxy)' arguments:
+     * the internal 'bboxX1' and 'bboxY1' are set to values one greater
+     * than given maximum X and Y values. Those maximum values are then
+     * later used in AAShapePipe' class 'renderTiles' method, where a
+     * Y/X loop eventually calls 'GeneralCompositePipe' class
+     * 'renderPathTile' method. In that method, the operation will
+     * eventually call 'IntegerInterleavedRaster' class
+     * 'createWritableChild' method with arguments:
+     *
+     * <UL>
+     * <LI>x=800
+     * <LI>y=0
+     * <LI>width=2 (this value is too high: should be 1)
+     * <LI>height=32
+     * <LI>x0=0
+     * <LI>y0=0
+     * <LI>bandList[]=null
+     * </UL>
+     *
+     * This calls for a sub-raster with bounds that fall outside the
+     * original raster, and therefore the 'createWritableChild' method
+     * correctly throws 'RasterFormatException'.
+     *
+     * The bug is closely related to the use of a custom Composite
+     * implementation, which are quite rare. The application where this
+     * bug was first detected implements a high-quality PDF rendering
+     * engine that needs custom Composite operations to properly
+     * implement PDF advanced color blending and masking operators.
+     */
+
+    public static void main(String args[])
+    {
+        BufferedImage bi = new BufferedImage(801,1202,
+                                             BufferedImage.TYPE_INT_ARGB);
+        Graphics2D g2d = bi.createGraphics();
+        GeneralPath gp = new GeneralPath();
+        AffineTransform m = new AffineTransform(2.483489907915543,
+                                                0.0,
+                                                0.0,
+                                                -2.4844977263331955,
+                                                0.0,
+                                                1202.0);
+        Composite c = new CustomComposite();
+
+        gp.moveTo(-4.511, -14.349);
+        gp.lineTo(327.489, -14.349);
+        gp.lineTo(327.489, 494.15);
+        gp.lineTo(-4.511, 494.15);
+        gp.closePath();
+
+        g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION,
+                             RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
+        g2d.setRenderingHint(RenderingHints.KEY_RENDERING,
+                             RenderingHints.VALUE_RENDER_QUALITY);
+        g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING,
+                             RenderingHints.VALUE_COLOR_RENDER_QUALITY);
+        g2d.setRenderingHint(RenderingHints.KEY_TEXT_LCD_CONTRAST,
+                             Integer.valueOf(140));
+        g2d.setRenderingHint(RenderingHints.KEY_DITHERING,
+                             RenderingHints.VALUE_DITHER_ENABLE);
+        g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
+                             RenderingHints.VALUE_TEXT_ANTIALIAS_DEFAULT);
+        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
+                             RenderingHints.VALUE_ANTIALIAS_ON);
+        g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL,
+                             RenderingHints.VALUE_STROKE_NORMALIZE);
+        g2d.setPaint(Color.red);
+        g2d.setComposite(c);
+        g2d.setTransform(m);
+        try {
+            g2d.fill(gp);
+        } catch (RasterFormatException rfe) {
+            System.out.println("Test failed");
+            throw new RuntimeException("xmax/ymax rounding cause RasterFormatException: " + rfe);
+        }
+        g2d.dispose();
+        System.out.println("Test passed");
+    }
+
+    // === CustomComposite ===
+
+    /**
+     * Dummy custom Composite implementation.
+     */
+
+    public static class CustomComposite implements Composite
+    {
+        @Override
+        public CompositeContext createContext(ColorModel srcColorModel,
+                                              ColorModel dstColorModel,
+                                              RenderingHints hints)
+        {
+            return new CustomCompositeContext();
+        }
+
+        // === CustomCompositeContext ===
+
+        /**
+         * Dummy custom CompositeContext implementation.
+         */
+
+        public static class CustomCompositeContext implements CompositeContext
+        {
+
+            @Override
+            public void dispose()
+            {
+                // NOP
+            }
+
+            @Override
+            public void compose(Raster src,Raster dstIn,WritableRaster dstOut)
+            {
+                // NOP
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/sun/java2d/marlin/Renderer/Test7019861.java	Mon Nov 27 17:04:45 2017 +0000
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2011, 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     7019861
+ *
+ * @summary Verifies that the last scanline isn't skipped when doing
+ *          antialiased rendering.
+ *
+ * @run     main Test7019861
+ */
+
+import java.awt.BasicStroke;
+import java.awt.Color;
+import java.awt.Graphics2D;
+import java.awt.geom.Path2D;
+import java.awt.image.BufferedImage;
+import java.util.Arrays;
+
+import static java.awt.RenderingHints.*;
+
+public class Test7019861 {
+
+    public static void main(String[] argv) throws Exception {
+        BufferedImage im = getWhiteImage(30, 30);
+        Graphics2D g2 = (Graphics2D)im.getGraphics();
+        g2.setRenderingHint(KEY_ANTIALIASING, VALUE_ANTIALIAS_ON);
+        g2.setRenderingHint(KEY_STROKE_CONTROL, VALUE_STROKE_PURE);
+        g2.setStroke(new BasicStroke(10, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL));
+        g2.setBackground(Color.white);
+        g2.setColor(Color.black);
+
+        Path2D p = getPath(0, 0, 20);
+        g2.draw(p);
+
+        if (!(new Color(im.getRGB(20, 19))).equals(Color.black)) {
+            throw new Exception("This pixel should be black");
+        }
+    }
+
+    private static Path2D getPath(int x, int y, int len) {
+        Path2D p = new Path2D.Double();
+        p.moveTo(x, y);
+        p.quadTo(x + len, y, x + len, y + len);
+        return p;
+    }
+
+    private static BufferedImage getWhiteImage(int w, int h) {
+        BufferedImage ret = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
+        final int[] white = new int[w * h];
+        Arrays.fill(white, 0xffffff);
+        ret.setRGB(0, 0, w, h, white, 0, w);
+        return ret;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/sun/java2d/marlin/Renderer/TestNPE.java	Mon Nov 27 17:04:45 2017 +0000
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2009, 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     6887494
+ *
+ * @summary Verifies that no NullPointerException is thrown in Pisces Renderer
+ *          under certain circumstances.
+ *
+ * @run     main TestNPE
+ */
+
+import java.awt.*;
+import java.awt.geom.*;
+import java.awt.image.BufferedImage;
+
+public class TestNPE {
+
+    private static void paint(Graphics g) {
+        Graphics2D g2d = (Graphics2D) g;
+        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
+                             RenderingHints.VALUE_ANTIALIAS_ON);
+        g2d.setClip(0, 0, 0, 0);
+        g2d.setTransform(
+               new AffineTransform(4.0f, 0.0f, 0.0f, 4.0f, -1248.0f, -744.0f));
+        g2d.draw(new Line2D.Float(131.21428571428572f, 33.0f,
+                                  131.21428571428572f, 201.0f));
+    }
+
+    public static void main(String[] args) {
+        BufferedImage im = new BufferedImage(100, 100,
+                                             BufferedImage.TYPE_INT_ARGB);
+
+        // Trigger exception in main thread.
+        Graphics g = im.getGraphics();
+        paint(g);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/sun/java2d/marlin/ScaleTest.java	Mon Nov 27 17:04:45 2017 +0000
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2009, 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 java.awt.*;
+import java.awt.geom.Ellipse2D;
+import java.awt.image.BufferedImage;
+import java.io.File;
+import javax.imageio.ImageIO;
+
+
+public class ScaleTest {
+  public static void main(String[] args) throws Exception {
+    BufferedImage image = new BufferedImage(200, 200, BufferedImage.TYPE_INT_RGB);
+    Graphics2D g = image.createGraphics();
+
+    g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
+    g.setPaint(Color.WHITE);
+    g.fill(new Rectangle(image.getWidth(), image.getHeight()));
+    g.scale(.9, .9);
+    g.setPaint(Color.BLACK);
+    g.setStroke(new BasicStroke(0.5f));
+    g.draw(new Ellipse2D.Double(25, 25, 150, 150));
+
+    // To visually check it
+    //ImageIO.write(image, "PNG", new File(args[0]));
+
+    boolean nonWhitePixelFound = false;
+    for (int x = 100; x < 200; ++x) {
+      if (image.getRGB(x, 90) != Color.WHITE.getRGB()) {
+        nonWhitePixelFound = true;
+        break;
+      }
+    }
+    if (!nonWhitePixelFound) {
+      throw new RuntimeException("A circle is rendered like a 'C' shape.");
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/sun/java2d/marlin/StrokeShapeTest.java	Mon Nov 27 17:04:45 2017 +0000
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2009, 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 java.awt.*;
+import java.awt.geom.Ellipse2D;
+import java.awt.geom.GeneralPath;
+import java.awt.image.BufferedImage;
+import java.io.File;
+
+import javax.imageio.ImageIO;
+
+/**
+ * @author chrisn@google.com (Chris Nokleberg)
+ * @author yamauchi@google.com (Hiroshi Yamauchi)
+ */
+public class StrokeShapeTest {
+  public static void main(String[] args) throws Exception {
+    BufferedImage image = new BufferedImage(200, 200, BufferedImage.TYPE_INT_RGB);
+    Graphics2D g = image.createGraphics();
+    g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
+    g.setPaint(Color.WHITE);
+    g.fill(new Rectangle(image.getWidth(), image.getHeight()));
+    g.translate(25, 100);
+
+    Stroke stroke = new BasicStroke(200, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
+    Shape shape = new Polygon(new int[] {0, 1500, 0}, new int[] {750, 0, -750}, 3);
+
+    g.scale(.1, .1);
+    g.setPaint(Color.BLACK);
+    g.setStroke(stroke);
+    g.draw(shape);
+    g.setPaint(Color.RED);
+    g.fill(stroke.createStrokedShape(shape));
+
+    // To visually check it
+    //ImageIO.write(image, "PNG", new File(args[0]));
+
+    boolean blackPixelFound = false;
+    outer:
+    for (int x = 0; x < 200; ++x) {
+      for (int y = 0; y < 200; ++y) {
+        if (image.getRGB(x, y) == Color.BLACK.getRGB()) {
+          blackPixelFound = true;
+          break outer;
+        }
+      }
+    }
+    if (blackPixelFound) {
+      throw new RuntimeException("The shape hasn't been filled in red.");
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/sun/java2d/marlin/Test7036754.java	Mon Nov 27 17:04:45 2017 +0000
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2011, 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     7036754
+ *
+ * @summary Verifies that there are no non-finite numbers when stroking
+ *          certain quadratic curves.
+ *
+ * @author Jim Graham
+ * @run     main Test7036754
+ */
+
+import java.awt.*;
+import java.awt.geom.*;
+
+public class Test7036754 {
+    public static void main(String argv[]) {
+        Shape s = new QuadCurve2D.Float(839.24677f, 508.97888f,
+                                        839.2953f, 508.97122f,
+                                        839.3438f, 508.96353f);
+        s = new BasicStroke(10f).createStrokedShape(s);
+        float nsegs[] = {2, 2, 4, 6, 0};
+        float coords[] = new float[6];
+        PathIterator pi = s.getPathIterator(null);
+        while (!pi.isDone()) {
+            int type = pi.currentSegment(coords);
+            for (int i = 0; i < nsegs[type]; i++) {
+                float c = coords[i];
+                if (Float.isNaN(c) || Float.isInfinite(c)) {
+                    throw new RuntimeException("bad value in stroke");
+                }
+            }
+            pi.next();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/sun/java2d/marlin/ThinLineTest.java	Mon Nov 27 17:04:45 2017 +0000
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2009, 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 java.awt.*;
+import java.awt.geom.Ellipse2D;
+import java.awt.image.BufferedImage;
+import java.io.File;
+import javax.imageio.ImageIO;
+
+/**
+ * @author chrisn@google.com (Chris Nokleberg)
+ * @author yamauchi@google.com (Hiroshi Yamauchi)
+ */
+public class ThinLineTest {
+  private static final int PIXEL = 381;
+
+  public static void main(String[] args) throws Exception {
+    BufferedImage image = new BufferedImage(200, 200, BufferedImage.TYPE_INT_RGB);
+    Graphics2D g = image.createGraphics();
+
+    g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
+    g.setPaint(Color.WHITE);
+    g.fill(new Rectangle(image.getWidth(), image.getHeight()));
+
+    g.scale(0.5 / PIXEL, 0.5 / PIXEL);
+    g.setPaint(Color.BLACK);
+    g.setStroke(new BasicStroke(PIXEL));
+    g.draw(new Ellipse2D.Double(PIXEL * 50, PIXEL * 50, PIXEL * 300, PIXEL * 300));
+
+    // To visually check it
+    //ImageIO.write(image, "PNG", new File(args[0]));
+
+    boolean nonWhitePixelFound = false;
+    for (int x = 0; x < 200; ++x) {
+      if (image.getRGB(x, 100) != Color.WHITE.getRGB()) {
+        nonWhitePixelFound = true;
+        break;
+      }
+    }
+    if (!nonWhitePixelFound) {
+      throw new RuntimeException("The thin line disappeared.");
+    }
+  }
+}
--- a/test/jdk/sun/java2d/pisces/OpenJDKFillBug.java	Fri Nov 24 17:19:47 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,173 +0,0 @@
-/*
- * Copyright (c) 2015, 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 java.awt.Color;
-import java.awt.Composite;
-import java.awt.CompositeContext;
-import java.awt.Graphics2D;
-import java.awt.RenderingHints;
-import java.awt.geom.AffineTransform;
-import java.awt.geom.GeneralPath;
-import java.awt.image.BufferedImage;
-import java.awt.image.ColorModel;
-import java.awt.image.Raster;
-import java.awt.image.WritableRaster;
-import java.awt.image.RasterFormatException;
-
-/**
- * @test
- * @bug 8048782
- * @summary Test program that demonstrates PiscesRendering bug in
- * OpenJDK 1.7.0.60 (and probably in all other OpenJDK versions, too).
- */
-
-public class OpenJDKFillBug
-{
-    /**
-     * Test program that demonstrates a bug in OpenJDK 1.7.0.60 (and
-     * probably in all other OpenJDK versions, too). To see the bug, simply run
-     * the 'main' program with OpenJDK. The bug makes the 'g2d.fill'
-     * method fail with the following exception:
-     *
-     * This bug is found in OpenJDK but also is present in OracleJDK
-     * if run with
-     * -Dsun.java2d.renderer=sun.java2d.pisces.PiscesRenderingEngine
-     *
-     * The bug is related to sun.java2d.pisces.PiscesCache constructor
-     * that accepts '(int minx,int miny,int maxx,int maxy)' arguments:
-     * the internal 'bboxX1' and 'bboxY1' are set to values one greater
-     * than given maximum X and Y values. Those maximum values are then
-     * later used in AAShapePipe' class 'renderTiles' method, where a
-     * Y/X loop eventually calls 'GeneralCompositePipe' class
-     * 'renderPathTile' method. In that method, the operation will
-     * eventually call 'IntegerInterleavedRaster' class
-     * 'createWritableChild' method with arguments:
-     *
-     * <UL>
-     * <LI>x=800
-     * <LI>y=0
-     * <LI>width=2 (this value is too high: should be 1)
-     * <LI>height=32
-     * <LI>x0=0
-     * <LI>y0=0
-     * <LI>bandList[]=null
-     * </UL>
-     *
-     * This calls for a sub-raster with bounds that fall outside the
-     * original raster, and therefore the 'createWritableChild' method
-     * correctly throws 'RasterFormatException'.
-     *
-     * The bug is closely related to the use of a custom Composite
-     * implementation, which are quite rare. The application where this
-     * bug was first detected implements a high-quality PDF rendering
-     * engine that needs custom Composite operations to properly
-     * implement PDF advanced color blending and masking operators.
-     */
-
-    public static void main(String args[])
-    {
-        BufferedImage bi = new BufferedImage(801,1202,
-                                             BufferedImage.TYPE_INT_ARGB);
-        Graphics2D g2d = bi.createGraphics();
-        GeneralPath gp = new GeneralPath();
-        AffineTransform m = new AffineTransform(2.483489907915543,
-                                                0.0,
-                                                0.0,
-                                                -2.4844977263331955,
-                                                0.0,
-                                                1202.0);
-        Composite c = new CustomComposite();
-
-        gp.moveTo(-4.511, -14.349);
-        gp.lineTo(327.489, -14.349);
-        gp.lineTo(327.489, 494.15);
-        gp.lineTo(-4.511, 494.15);
-        gp.closePath();
-
-        g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION,
-                             RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
-        g2d.setRenderingHint(RenderingHints.KEY_RENDERING,
-                             RenderingHints.VALUE_RENDER_QUALITY);
-        g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING,
-                             RenderingHints.VALUE_COLOR_RENDER_QUALITY);
-        g2d.setRenderingHint(RenderingHints.KEY_TEXT_LCD_CONTRAST,
-                             Integer.valueOf(140));
-        g2d.setRenderingHint(RenderingHints.KEY_DITHERING,
-                             RenderingHints.VALUE_DITHER_ENABLE);
-        g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
-                             RenderingHints.VALUE_TEXT_ANTIALIAS_DEFAULT);
-        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
-                             RenderingHints.VALUE_ANTIALIAS_ON);
-        g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL,
-                             RenderingHints.VALUE_STROKE_NORMALIZE);
-        g2d.setPaint(Color.red);
-        g2d.setComposite(c);
-        g2d.setTransform(m);
-        try {
-            g2d.fill(gp);
-        } catch (RasterFormatException rfe) {
-            System.out.println("Test failed");
-            throw new RuntimeException("xmax/ymax rounding cause RasterFormatException: " + rfe);
-        }
-        g2d.dispose();
-        System.out.println("Test passed");
-    }
-
-    // === CustomComposite ===
-
-    /**
-     * Dummy custom Composite implementation.
-     */
-
-    public static class CustomComposite implements Composite
-    {
-        @Override
-        public CompositeContext createContext(ColorModel srcColorModel,
-                                              ColorModel dstColorModel,
-                                              RenderingHints hints)
-        {
-            return new CustomCompositeContext();
-        }
-
-        // === CustomCompositeContext ===
-
-        /**
-         * Dummy custom CompositeContext implementation.
-         */
-
-        public static class CustomCompositeContext implements CompositeContext
-        {
-
-            @Override
-            public void dispose()
-            {
-                // NOP
-            }
-
-            @Override
-            public void compose(Raster src,Raster dstIn,WritableRaster dstOut)
-            {
-                // NOP
-            }
-        }
-    }
-}
--- a/test/jdk/sun/java2d/pisces/Renderer/Test7019861.java	Fri Nov 24 17:19:47 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,76 +0,0 @@
-/*
- * Copyright (c) 2011, 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     7019861
- *
- * @summary Verifies that the last scanline isn't skipped when doing
- *          antialiased rendering.
- *
- * @run     main Test7019861
- */
-
-import java.awt.BasicStroke;
-import java.awt.Color;
-import java.awt.Graphics2D;
-import java.awt.geom.Path2D;
-import java.awt.image.BufferedImage;
-import java.util.Arrays;
-
-import static java.awt.RenderingHints.*;
-
-public class Test7019861 {
-
-    public static void main(String[] argv) throws Exception {
-        BufferedImage im = getWhiteImage(30, 30);
-        Graphics2D g2 = (Graphics2D)im.getGraphics();
-        g2.setRenderingHint(KEY_ANTIALIASING, VALUE_ANTIALIAS_ON);
-        g2.setRenderingHint(KEY_STROKE_CONTROL, VALUE_STROKE_PURE);
-        g2.setStroke(new BasicStroke(10, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL));
-        g2.setBackground(Color.white);
-        g2.setColor(Color.black);
-
-        Path2D p = getPath(0, 0, 20);
-        g2.draw(p);
-
-        if (!(new Color(im.getRGB(20, 19))).equals(Color.black)) {
-            throw new Exception("This pixel should be black");
-        }
-    }
-
-    private static Path2D getPath(int x, int y, int len) {
-        Path2D p = new Path2D.Double();
-        p.moveTo(x, y);
-        p.quadTo(x + len, y, x + len, y + len);
-        return p;
-    }
-
-    private static BufferedImage getWhiteImage(int w, int h) {
-        BufferedImage ret = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
-        final int[] white = new int[w * h];
-        Arrays.fill(white, 0xffffff);
-        ret.setRGB(0, 0, w, h, white, 0, w);
-        return ret;
-    }
-}
--- a/test/jdk/sun/java2d/pisces/Renderer/TestNPE.java	Fri Nov 24 17:19:47 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,59 +0,0 @@
-/*
- * Copyright (c) 2009, 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     6887494
- *
- * @summary Verifies that no NullPointerException is thrown in Pisces Renderer
- *          under certain circumstances.
- *
- * @run     main TestNPE
- */
-
-import java.awt.*;
-import java.awt.geom.*;
-import java.awt.image.BufferedImage;
-
-public class TestNPE {
-
-    private static void paint(Graphics g) {
-        Graphics2D g2d = (Graphics2D) g;
-        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
-                             RenderingHints.VALUE_ANTIALIAS_ON);
-        g2d.setClip(0, 0, 0, 0);
-        g2d.setTransform(
-               new AffineTransform(4.0f, 0.0f, 0.0f, 4.0f, -1248.0f, -744.0f));
-        g2d.draw(new Line2D.Float(131.21428571428572f, 33.0f,
-                                  131.21428571428572f, 201.0f));
-    }
-
-    public static void main(String[] args) {
-        BufferedImage im = new BufferedImage(100, 100,
-                                             BufferedImage.TYPE_INT_ARGB);
-
-        // Trigger exception in main thread.
-        Graphics g = im.getGraphics();
-        paint(g);
-    }
-}
--- a/test/jdk/sun/java2d/pisces/Test7036754.java	Fri Nov 24 17:19:47 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,58 +0,0 @@
-/*
- * Copyright (c) 2011, 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     7036754
- *
- * @summary Verifies that there are no non-finite numbers when stroking
- *          certain quadratic curves.
- *
- * @author Jim Graham
- * @run     main Test7036754
- */
-
-import java.awt.*;
-import java.awt.geom.*;
-
-public class Test7036754 {
-    public static void main(String argv[]) {
-        Shape s = new QuadCurve2D.Float(839.24677f, 508.97888f,
-                                        839.2953f, 508.97122f,
-                                        839.3438f, 508.96353f);
-        s = new BasicStroke(10f).createStrokedShape(s);
-        float nsegs[] = {2, 2, 4, 6, 0};
-        float coords[] = new float[6];
-        PathIterator pi = s.getPathIterator(null);
-        while (!pi.isDone()) {
-            int type = pi.currentSegment(coords);
-            for (int i = 0; i < nsegs[type]; i++) {
-                float c = coords[i];
-                if (Float.isNaN(c) || Float.isInfinite(c)) {
-                    throw new RuntimeException("bad value in stroke");
-                }
-            }
-            pi.next();
-        }
-    }
-}
--- a/test/jdk/sun/pisces/DashStrokeTest.java	Fri Nov 24 17:19:47 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,86 +0,0 @@
-/*
- * Copyright (c) 2009, 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
- * @summary verify that first element is a dash
- * @bug 6793344
- */
-
-import java.awt.*;
-import java.awt.image.*;
-
-import javax.swing.JButton;
-import javax.swing.JFrame;
-import javax.swing.SwingUtilities;
-import javax.swing.WindowConstants;
-
-public class DashStrokeTest extends Component {
-
-    static BufferedImage bi;
-    static boolean printed = false;
-
-    public Dimension getPreferredSize() {
-      return new Dimension(200,200);
-    }
-
-    public static void drawGui() {
-        bi = new BufferedImage(200, 20, BufferedImage.TYPE_INT_RGB);
-        Graphics2D g2d = bi.createGraphics();
-        BasicStroke dashStroke = new BasicStroke(1.0f, BasicStroke.CAP_ROUND,
-                BasicStroke.JOIN_ROUND, 1.0f, new float[] { 0.0f, 200 },
-                1.0f);
-
-        g2d.setStroke(dashStroke);
-        g2d.setColor(Color.RED);
-        g2d.drawLine(5,10, 100,10);
-        printed =true;
-    }
-
-    public static void main(String[] args) {
-            try {
-            SwingUtilities.invokeAndWait(new Runnable() {
-
-            @Override
-            public void run() {
-                drawGui();
-            }
-
-            });
-            } catch (Exception e) {
-            }
-
-            if (printed) {
-                checkBI(bi, Color.RED);
-            }
-    }
-
-    static void checkBI(BufferedImage bi, Color badColor) {
-      int badrgb = badColor.getRGB();
-
-      int col = bi.getRGB(6, 9);
-      if (col == badrgb) {
-          throw new RuntimeException("A pixel was turned on. ");
-      }
-   }
-}
-
--- a/test/jdk/sun/pisces/JoinMiterTest.java	Fri Nov 24 17:19:47 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,48 +0,0 @@
-/*
- * Copyright (c) 2009, 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
- * @summary Pass if no RuntimeException.
- * @bug 6812600
- */
-import java.awt.*;
-import java.awt.image.BufferedImage;
-
-public class JoinMiterTest {
-
-  public static void main(String[] args) throws Exception {
-    BufferedImage image = new BufferedImage(200, 200,
-BufferedImage.TYPE_INT_RGB);
-    Graphics2D g = image.createGraphics();
-    g.setPaint(Color.WHITE);
-    g.fill(new Rectangle(image.getWidth(), image.getHeight()));
-    g.translate(25, 100);
-    g.setPaint(Color.BLACK);
-    g.setStroke(new BasicStroke(20, BasicStroke.CAP_BUTT,
-                                BasicStroke.JOIN_MITER));
-    g.draw(new Polygon(new int[] {0, 150, 0}, new int[] {75, 0, -75}, 3));
-    if (image.getRGB(16, 10) == Color.WHITE.getRGB()) {
-      throw new RuntimeException("Miter is not rendered.");
-    }
-  }
-}
--- a/test/jdk/sun/pisces/ScaleTest.java	Fri Nov 24 17:19:47 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,58 +0,0 @@
-/*
- * Copyright (c) 2009, 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 java.awt.*;
-import java.awt.geom.Ellipse2D;
-import java.awt.image.BufferedImage;
-import java.io.File;
-import javax.imageio.ImageIO;
-
-
-public class ScaleTest {
-  public static void main(String[] args) throws Exception {
-    BufferedImage image = new BufferedImage(200, 200, BufferedImage.TYPE_INT_RGB);
-    Graphics2D g = image.createGraphics();
-
-    g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
-    g.setPaint(Color.WHITE);
-    g.fill(new Rectangle(image.getWidth(), image.getHeight()));
-    g.scale(.9, .9);
-    g.setPaint(Color.BLACK);
-    g.setStroke(new BasicStroke(0.5f));
-    g.draw(new Ellipse2D.Double(25, 25, 150, 150));
-
-    // To visually check it
-    //ImageIO.write(image, "PNG", new File(args[0]));
-
-    boolean nonWhitePixelFound = false;
-    for (int x = 100; x < 200; ++x) {
-      if (image.getRGB(x, 90) != Color.WHITE.getRGB()) {
-        nonWhitePixelFound = true;
-        break;
-      }
-    }
-    if (!nonWhitePixelFound) {
-      throw new RuntimeException("A circle is rendered like a 'C' shape.");
-    }
-  }
-}
--- a/test/jdk/sun/pisces/StrokeShapeTest.java	Fri Nov 24 17:19:47 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,71 +0,0 @@
-/*
- * Copyright (c) 2009, 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 java.awt.*;
-import java.awt.geom.Ellipse2D;
-import java.awt.geom.GeneralPath;
-import java.awt.image.BufferedImage;
-import java.io.File;
-
-import javax.imageio.ImageIO;
-
-/**
- * @author chrisn@google.com (Chris Nokleberg)
- * @author yamauchi@google.com (Hiroshi Yamauchi)
- */
-public class StrokeShapeTest {
-  public static void main(String[] args) throws Exception {
-    BufferedImage image = new BufferedImage(200, 200, BufferedImage.TYPE_INT_RGB);
-    Graphics2D g = image.createGraphics();
-    g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
-    g.setPaint(Color.WHITE);
-    g.fill(new Rectangle(image.getWidth(), image.getHeight()));
-    g.translate(25, 100);
-
-    Stroke stroke = new BasicStroke(200, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
-    Shape shape = new Polygon(new int[] {0, 1500, 0}, new int[] {750, 0, -750}, 3);
-
-    g.scale(.1, .1);
-    g.setPaint(Color.BLACK);
-    g.setStroke(stroke);
-    g.draw(shape);
-    g.setPaint(Color.RED);
-    g.fill(stroke.createStrokedShape(shape));
-
-    // To visually check it
-    //ImageIO.write(image, "PNG", new File(args[0]));
-
-    boolean blackPixelFound = false;
-    outer:
-    for (int x = 0; x < 200; ++x) {
-      for (int y = 0; y < 200; ++y) {
-        if (image.getRGB(x, y) == Color.BLACK.getRGB()) {
-          blackPixelFound = true;
-          break outer;
-        }
-      }
-    }
-    if (blackPixelFound) {
-      throw new RuntimeException("The shape hasn't been filled in red.");
-    }
-  }
-}
--- a/test/jdk/sun/pisces/TEST.properties	Fri Nov 24 17:19:47 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-modules=java.desktop
--- a/test/jdk/sun/pisces/ThinLineTest.java	Fri Nov 24 17:19:47 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,63 +0,0 @@
-/*
- * Copyright (c) 2009, 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 java.awt.*;
-import java.awt.geom.Ellipse2D;
-import java.awt.image.BufferedImage;
-import java.io.File;
-import javax.imageio.ImageIO;
-
-/**
- * @author chrisn@google.com (Chris Nokleberg)
- * @author yamauchi@google.com (Hiroshi Yamauchi)
- */
-public class ThinLineTest {
-  private static final int PIXEL = 381;
-
-  public static void main(String[] args) throws Exception {
-    BufferedImage image = new BufferedImage(200, 200, BufferedImage.TYPE_INT_RGB);
-    Graphics2D g = image.createGraphics();
-
-    g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
-    g.setPaint(Color.WHITE);
-    g.fill(new Rectangle(image.getWidth(), image.getHeight()));
-
-    g.scale(0.5 / PIXEL, 0.5 / PIXEL);
-    g.setPaint(Color.BLACK);
-    g.setStroke(new BasicStroke(PIXEL));
-    g.draw(new Ellipse2D.Double(PIXEL * 50, PIXEL * 50, PIXEL * 300, PIXEL * 300));
-
-    // To visually check it
-    //ImageIO.write(image, "PNG", new File(args[0]));
-
-    boolean nonWhitePixelFound = false;
-    for (int x = 0; x < 200; ++x) {
-      if (image.getRGB(x, 100) != Color.WHITE.getRGB()) {
-        nonWhitePixelFound = true;
-        break;
-      }
-    }
-    if (!nonWhitePixelFound) {
-      throw new RuntimeException("The thin line disappeared.");
-    }
-  }
-}
--- a/test/jdk/sun/security/ssl/SSLSocketImpl/SSLSocketCloseHang.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/test/jdk/sun/security/ssl/SSLSocketImpl/SSLSocketCloseHang.java	Mon Nov 27 17:04:45 2017 +0000
@@ -100,8 +100,11 @@
          */
         serverReady = true;
 
+        System.err.println("Server accepting: " + System.nanoTime());
         SSLSocket sslSocket = (SSLSocket) sslServerSocket.accept();
+        System.err.println("Server accepted: " + System.nanoTime());
         sslSocket.startHandshake();
+        System.err.println("Server handshake complete: " + System.nanoTime());
         while (!clientClosed) {
             Thread.sleep(500);
         }
@@ -123,10 +126,11 @@
         while (!serverReady) {
             Thread.sleep(50);
         }
+        Thread.sleep(500);
         System.out.println("server ready");
 
         Socket baseSocket = new Socket("localhost", serverPort);
-        baseSocket.setSoTimeout(100);
+        baseSocket.setSoTimeout(1000);
 
         SSLSocketFactory sslsf =
             (SSLSocketFactory) SSLSocketFactory.getDefault();
@@ -134,15 +138,16 @@
             sslsf.createSocket(baseSocket, "localhost", serverPort, false);
 
         // handshaking
+        System.err.println("Client starting handshake: " + System.nanoTime());
         sslSocket.startHandshake();
-        System.out.println("handshake done");
+        System.err.println("Client handshake done: " + System.nanoTime());
 
         Thread.sleep(500);
-        System.out.println("client closing");
+        System.err.println("Client closing: " + System.nanoTime());
 
         sslSocket.close();
         clientClosed = true;
-        System.out.println("client closed");
+        System.err.println("Client closed: " + System.nanoTime());
     }
 
     /*
--- a/test/langtools/ProblemList.txt	Fri Nov 24 17:19:47 2017 +0000
+++ b/test/langtools/ProblemList.txt	Mon Nov 27 17:04:45 2017 +0000
@@ -38,6 +38,9 @@
 
 jdk/jshell/UserJdiUserRemoteTest.java                                           8173079    linux-all
 jdk/jshell/UserInputTest.java                                                   8169536    generic-all   
+jdk/jshell/StartOptionTest.java                                                 8191455    windows-all 
+jdk/jshell/ToolProviderTest.java                                                8191455    windows-all
+jdk/jshell/ExternalEditorTest.java                                              8191456    generic-all
 
 ###########################################################################
 #
--- a/test/langtools/jdk/javadoc/doclet/testDeprecatedDocs/TestDeprecatedDocs.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/test/langtools/jdk/javadoc/doclet/testDeprecatedDocs/TestDeprecatedDocs.java	Mon Nov 27 17:04:45 2017 +0000
@@ -24,7 +24,7 @@
 /*
  * @test
  * @bug      4927552 8026567 8071982 8162674 8175200 8175218 8183511 8186332 8169819 8074407
- * @summary  <DESC>
+ * @summary  test generated docs for deprecated items
  * @author   jamieh
  * @library  ../lib
  * @modules jdk.javadoc/jdk.javadoc.internal.tool
@@ -254,6 +254,7 @@
                 + "<tbody>\n"
                 + "<tr class=\"altColor\">\n"
                 + "<th class=\"colDeprecatedItemName\" scope=\"row\"><a href=\"pkg/DeprecatedClassByAnnotation.html#field\">pkg.DeprecatedClassByAnnotation.field</a></th>\n"
+                + "<td class=\"colLast\"></td>\n"
                 + "</tr>\n"
                 + "<tr class=\"rowColor\">\n"
                 + "<th class=\"colDeprecatedItemName\" scope=\"row\"><a href=\"pkg/TestClass.html#field\">pkg.TestClass.field</a></th>\n"
--- a/test/langtools/jdk/javadoc/doclet/testGroupName/TestGroupName.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/test/langtools/jdk/javadoc/doclet/testGroupName/TestGroupName.java	Mon Nov 27 17:04:45 2017 +0000
@@ -64,10 +64,8 @@
         checkExit(Exit.OK);
 
         checkOutput("overview-summary.html", true,
-                "<span><a href=\"javascript:showGroups(1);\">abc &lt; &amp; &gt; def</a></span>");
-
-        checkOutput("overview-summary.html", false,
-                "abc < & > def");
+                "<span><a href=\"javascript:showGroups(1);\">abc &lt; &amp; &gt; def</a></span>",
+                ",\"abc < & > def\"],");
     }
 
     @Test
@@ -99,10 +97,8 @@
         checkExit(Exit.OK);
 
         checkOutput("overview-summary.html", true,
-                "<span><a href=\"javascript:showGroups(1);\">abc &lt; &amp; &gt; def</a></span>");
-
-        checkOutput("overview-summary.html", false,
-                "abc < & > def");
+                "<span><a href=\"javascript:showGroups(1);\">abc &lt; &amp; &gt; def</a></span>",
+                ",\"abc < & > def\"],");
     }
 }
 
--- a/test/langtools/jdk/javadoc/doclet/testHtmlDocument/TestHtmlDocument.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/test/langtools/jdk/javadoc/doclet/testHtmlDocument/TestHtmlDocument.java	Mon Nov 27 17:04:45 2017 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2017, 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
@@ -69,7 +69,7 @@
     // Generate the HTML output using the HTML document generation within doclet.
     public static String generateHtmlTree() {
         // Document type for the HTML document
-        DocType htmlDocType = DocType.TRANSITIONAL;
+        DocType htmlDocType = DocType.HTML4_TRANSITIONAL;
         HtmlTree html = new HtmlTree(HtmlTag.HTML);
         HtmlTree head = new HtmlTree(HtmlTag.HEAD);
         HtmlTree title = new HtmlTree(HtmlTag.TITLE);
--- a/test/langtools/jdk/javadoc/doclet/testLinkOption/TestBadLinkOption.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/test/langtools/jdk/javadoc/doclet/testLinkOption/TestBadLinkOption.java	Mon Nov 27 17:04:45 2017 +0000
@@ -23,8 +23,8 @@
 
 /*
  * @test
- * @bug 4625883
- * @summary Make sure that bad -link arguments trigger warnings.
+ * @bug 4625883 8180019
+ * @summary Make sure that bad -link arguments trigger errors.
  * @author jamieh
  * @library ../lib
  * @modules jdk.javadoc/jdk.javadoc.internal.tool
@@ -44,11 +44,10 @@
         String out = "out";
         javadoc("-d", out,
                 "-sourcepath", testSrc,
-                "-link", out,
+                "-link", "a-non-existent-link",
                 "pkg");
-        checkExit(Exit.OK);
+        checkExit(Exit.ERROR);
 
-        // TODO: the file it is trying to read, out/out/package-list, warrants investigation
         checkOutput(Output.OUT, true,
                 "Error reading file:");
     }
--- a/test/langtools/jdk/javadoc/doclet/testLinkOption/TestNewLineInLink.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/test/langtools/jdk/javadoc/doclet/testLinkOption/TestNewLineInLink.java	Mon Nov 27 17:04:45 2017 +0000
@@ -44,7 +44,7 @@
     void test() {
         javadoc("-d", "out",
                 "-sourcepath", testSrc,
-                "-linkoffline", "http://www.java.sun.com/j2se/1.4/docs/api", testSrc,
+                "-linkoffline", "http://www.java.sun.com/j2se/1.4/docs/api", testSrc("jdk"),
                 "testNewLineInLink");
         checkExit(Exit.OK);
 
--- a/test/langtools/jdk/javadoc/doclet/testModules/TestModules.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/test/langtools/jdk/javadoc/doclet/testModules/TestModules.java	Mon Nov 27 17:04:45 2017 +0000
@@ -24,8 +24,8 @@
 /*
  * @test
  * @bug 8154119 8154262 8156077 8157987 8154261 8154817 8135291 8155995 8162363
- *      8168766 8168688 8162674 8160196 8175799 8174974 8176778 8177562 8175218 8175823 8166306
- *      8178043 8181622 8183511 8169819 8074407 8183037
+ *      8168766 8168688 8162674 8160196 8175799 8174974 8176778 8177562 8175218
+ *      8175823 8166306 8178043 8181622 8183511 8169819 8074407 8183037 8191464
  * @summary Test modules support in javadoc.
  * @author bpatel
  * @library ../lib
@@ -1050,7 +1050,7 @@
                 + "<li><a href=\"#module\">Modules</a></li>\n"
                 + "</ul>",
                 "<tr class=\"altColor\">\n"
-                + "<th class=\"colFirst\" scope=\"row\"><a href=\"moduleA-summary.html\">moduleA</a></th>\n"
+                + "<th class=\"colDeprecatedItemName\" scope=\"row\"><a href=\"moduleA-summary.html\">moduleA</a></th>\n"
                 + "<td class=\"colLast\">\n"
                 + "<div class=\"deprecationComment\">This module is deprecated.</div>\n"
                 + "</td>\n"
@@ -1100,7 +1100,7 @@
                 + "&nbsp;</span></span><span id=\"t4\" class=\"tableTab\"><span><a href=\"javascript:showGroups(4);\">"
                 + "Other Modules</a></span><span class=\"tabEnd\">&nbsp;</span></span></caption>",
                 "var groups = {\"i0\":1,\"i1\":2,\"i2\":2,\"i3\":4};\n"
-                + "var tabs = {65535:[\"t0\",\"All Modules\"],1:[\"t1\",\"Module Group A\"],2:[\"t2\",\"Module Group B &amp; C\"],4:[\"t4\",\"Other Modules\"]};\n"
+                + "var tabs = {65535:[\"t0\",\"All Modules\"],1:[\"t1\",\"Module Group A\"],2:[\"t2\",\"Module Group B & C\"],4:[\"t4\",\"Other Modules\"]};\n"
                 + "var altColor = \"altColor\";\n"
                 + "var rowColor = \"rowColor\";\n"
                 + "var tableTab = \"tableTab\";\n"
--- a/test/langtools/jdk/javadoc/doclet/testOptions/help.html	Fri Nov 24 17:19:47 2017 +0000
+++ b/test/langtools/jdk/javadoc/doclet/testOptions/help.html	Mon Nov 27 17:04:45 2017 +0000
@@ -2,10 +2,10 @@
 <!-- NewPage -->
 <html lang="ru">
 <head>
-<!-- Generated by javadoc (9-internal) on Mon Jan 04 22:47:26 MSK 2016 -->
+<!-- Generated by javadoc (removed) -->
 <title>API Help</title>
 <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
-<meta name="date" content="2016-01-04">
+<meta name="date" content="(removed)">
 <link rel="stylesheet" type="text/css" href="stylesheet.css" title="Style">
 <link rel="stylesheet" type="text/css" href="jquery/jquery-ui.css" title="Style">
 <script type="text/javascript" src="script.js"></script>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/jdk/javadoc/tool/testSourceOption/TestSourceOption.java	Mon Nov 27 17:04:45 2017 +0000
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2017, 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 8187588
+ * @summary -bootclasspath should work with -source 8
+ * @modules jdk.compiler/com.sun.tools.javac.api
+ *          jdk.compiler/com.sun.tools.javac.main
+ *          jdk.javadoc/jdk.javadoc.internal.api
+ *          jdk.javadoc/jdk.javadoc.internal.tool
+ * @library /tools/lib
+ * @build toolbox.JavacTask toolbox.JavadocTask toolbox.TestRunner toolbox.ToolBox
+ * @run main TestSourceOption
+ */
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import toolbox.JarTask;
+import toolbox.JavadocTask;
+import toolbox.ModuleBuilder;
+import toolbox.Task;
+import toolbox.Task.Expect;
+import toolbox.TestRunner;
+import toolbox.ToolBox;
+
+import javax.tools.JavaFileManager;
+import javax.tools.StandardLocation;
+import javax.tools.ToolProvider;
+
+public class TestSourceOption extends TestRunner {
+
+    public static void main(String... args) throws Exception {
+        TestSourceOption t = new TestSourceOption();
+        t.runTests(m -> new Object[] { Paths.get(m.getName()) });
+    }
+
+    private final ToolBox tb = new ToolBox();
+
+    TestSourceOption() throws IOException {
+        super(System.err);
+    }
+
+    @Test
+    public void testSourceWithBootclasspath(Path base) throws Exception {
+        Files.createDirectory(base);
+
+        Path smallRtJar = base.resolve("small-rt.jar");
+        try (JavaFileManager fm = ToolProvider.getSystemJavaCompiler()
+                .getStandardFileManager(null, null, null)) {
+
+            new JarTask(tb, smallRtJar)
+                    .files(fm, StandardLocation.PLATFORM_CLASS_PATH,
+                            "java.lang.**", "java.io.*", "java.util.*")
+                    .run();
+        }
+
+        tb.writeJavaFiles(base, "public class C { }");
+        Path out = base.resolve("out");
+        Files.createDirectory(out);
+
+        JavadocTask task = new JavadocTask(tb);
+        task.outdir(out)
+            .options("-bootclasspath", smallRtJar.toString(),
+                     "-source", "8")
+            .files(base.resolve("C.java"))
+            .run(Expect.SUCCESS);
+    }
+}
--- a/test/langtools/jdk/jshell/StartOptionTest.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/test/langtools/jdk/jshell/StartOptionTest.java	Mon Nov 27 17:04:45 2017 +0000
@@ -21,9 +21,9 @@
  * questions.
  */
 
-/*
- * @test 8151754 8080883 8160089 8170162 8166581 8172102 8171343 8178023 8186708 8179856
- * @summary Testing start-up options.
+ /*
+ * @test 8151754 8080883 8160089 8170162 8166581 8172102 8171343 8178023 8186708 8179856 8185840 8190383
+ * @summary Testing startExCe-up options.
  * @modules jdk.compiler/com.sun.tools.javac.api
  *          jdk.compiler/com.sun.tools.javac.main
  *          jdk.jdeps/com.sun.tools.javap
@@ -32,7 +32,6 @@
  * @build Compiler toolbox.ToolBox
  * @run testng StartOptionTest
  */
-
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.InputStream;
@@ -57,239 +56,308 @@
 @Test
 public class StartOptionTest {
 
-    private ByteArrayOutputStream cmdout;
-    private ByteArrayOutputStream cmderr;
-    private ByteArrayOutputStream console;
-    private ByteArrayOutputStream userout;
-    private ByteArrayOutputStream usererr;
-    private InputStream cmdInStream;
+    protected ByteArrayOutputStream cmdout;
+    protected ByteArrayOutputStream cmderr;
+    protected ByteArrayOutputStream console;
+    protected ByteArrayOutputStream userout;
+    protected ByteArrayOutputStream usererr;
+    protected InputStream cmdInStream;
 
     private JavaShellToolBuilder builder() {
         // turn on logging of launch failures
         Logger.getLogger("jdk.jshell.execution").setLevel(Level.ALL);
         return JavaShellToolBuilder
-                    .builder()
-                    .out(new PrintStream(cmdout), new PrintStream(console), new PrintStream(userout))
-                    .err(new PrintStream(cmderr), new PrintStream(usererr))
-                    .in(cmdInStream, null)
-                    .persistence(new HashMap<>())
-                    .env(new HashMap<>())
-                    .locale(Locale.ROOT);
+                .builder()
+                .out(new PrintStream(cmdout), new PrintStream(console), new PrintStream(userout))
+                .err(new PrintStream(cmderr), new PrintStream(usererr))
+                .in(cmdInStream, null)
+                .persistence(new HashMap<>())
+                .env(new HashMap<>())
+                .locale(Locale.ROOT);
     }
 
-    private void runShell(String... args) {
+    protected int runShell(String... args) {
         try {
-            builder()
-                    .run(args);
+            return builder()
+                    .start(args);
         } catch (Exception ex) {
             fail("Repl tool died with exception", ex);
         }
+        return -1; // for compiler
     }
 
     protected void check(ByteArrayOutputStream str, Consumer<String> checkOut, String label) {
         byte[] bytes = str.toByteArray();
         str.reset();
-        String out =  new String(bytes, StandardCharsets.UTF_8);
+        String out = new String(bytes, StandardCharsets.UTF_8);
         if (checkOut != null) {
             checkOut.accept(out);
         } else {
-            assertEquals("", out, label + ": Expected empty -- ");
+            assertEquals(out, "", label + ": Expected empty -- ");
         }
     }
 
-    protected void start(Consumer<String> checkCmdOutput,
-            Consumer<String> checkUserOutput, Consumer<String> checkError,
-            String... args) throws Exception {
-        runShell(args);
+    protected void checkExit(int ec, Consumer<Integer> checkCode) {
+        if (checkCode != null) {
+            checkCode.accept(ec);
+        } else {
+            assertEquals(ec, 0, "Expected standard exit code (0), but found: " + ec);
+        }
+    }
+
+    // Start and check the resultant: exit code (Ex), command output (Co),
+    // user output (Uo), command error (Ce), and console output (Cn)
+    protected void startExCoUoCeCn(Consumer<Integer> checkExitCode,
+            Consumer<String> checkCmdOutput,
+            Consumer<String> checkUserOutput,
+            Consumer<String> checkError,
+            Consumer<String> checkConsole,
+            String... args) {
+        int ec = runShell(args);
+        checkExit(ec, checkExitCode);
         check(cmdout, checkCmdOutput, "cmdout");
         check(cmderr, checkError, "cmderr");
-        check(console, null, "console");
+        check(console, checkConsole, "console");
         check(userout, checkUserOutput, "userout");
         check(usererr, null, "usererr");
     }
 
-    protected void start(String expectedCmdOutput, String expectedError, String... args) throws Exception {
-        startWithUserOutput(expectedCmdOutput, "",  expectedError, args);
+    // Start with an exit code and command error check
+    protected void startExCe(int eec, Consumer<String> checkError, String... args) {
+        StartOptionTest.this.startExCoUoCeCn(
+                (Integer ec) -> assertEquals((int) ec, eec,
+                        "Expected error exit code (" + eec + "), but found: " + ec),
+                null, null, checkError, null, args);
+    }
+
+    // Start with a command output check
+    protected void startCo(Consumer<String> checkCmdOutput, String... args) {
+        StartOptionTest.this.startExCoUoCeCn(null, checkCmdOutput, null, null, null, args);
+    }
+
+    private Consumer<String> assertOrNull(String expected, String label) {
+        return expected == null
+                ? null
+                : s -> assertEquals(s.trim(), expected.trim(), label);
     }
 
-    private void startWithUserOutput(String expectedCmdOutput, String expectedUserOutput,
-            String expectedError, String... args) throws Exception {
-        start(
-                s -> assertEquals(s.trim(), expectedCmdOutput, "cmdout: "),
-                s -> assertEquals(s.trim(), expectedUserOutput, "userout: "),
-                s -> assertEquals(s.trim(), expectedError, "cmderr: "),
+    // Start and check the resultant: exit code (Ex), command output (Co),
+    // user output (Uo), command error (Ce), and console output (Cn)
+    protected void startExCoUoCeCn(int expectedExitCode,
+            String expectedCmdOutput,
+            String expectedUserOutput,
+            String expectedError,
+            String expectedConsole,
+            String... args) {
+        startExCoUoCeCn(
+                expectedExitCode == 0
+                        ? null
+                        : (Integer i) -> assertEquals((int) i, expectedExitCode,
+                        "Expected exit code (" + expectedExitCode + "), but found: " + i),
+                assertOrNull(expectedCmdOutput, "cmdout: "),
+                assertOrNull(expectedUserOutput, "userout: "),
+                assertOrNull(expectedError, "cmderr: "),
+                assertOrNull(expectedConsole, "console: "),
                 args);
     }
 
+    // Start with an expected exit code and command error
+    protected void startExCe(int ec, String expectedError, String... args) {
+        startExCoUoCeCn(ec, null, null, expectedError, null, args);
+    }
+
+    // Start with an expected command output
+    protected void startCo(String expectedCmdOutput, String... args) {
+        startExCoUoCeCn(0, expectedCmdOutput, null, null, null, args);
+    }
+
+    // Start with an expected user output
+    protected void startUo(String expectedUserOutput, String... args) {
+        startExCoUoCeCn(0, null, expectedUserOutput, null, null, args);
+    }
+
     @BeforeMethod
     public void setUp() {
-        cmdout  = new ByteArrayOutputStream();
-        cmderr  = new ByteArrayOutputStream();
+        cmdout = new ByteArrayOutputStream();
+        cmderr = new ByteArrayOutputStream();
         console = new ByteArrayOutputStream();
         userout = new ByteArrayOutputStream();
         usererr = new ByteArrayOutputStream();
-        cmdInStream = new ByteArrayInputStream("/exit\n".getBytes());
+        setIn("/exit\n");
     }
 
-    protected String writeToFile(String stuff) throws Exception {
+    protected String writeToFile(String stuff) {
         Compiler compiler = new Compiler();
         Path p = compiler.getPath("doit.repl");
         compiler.writeToFile(p, stuff);
         return p.toString();
     }
 
-    public void testCommandFile() throws Exception {
-        String fn = writeToFile("String str = \"Hello \"\n/list\nSystem.out.println(str + str)\n/exit\n");
-        startWithUserOutput("1 : String str = \"Hello \";", "Hello Hello", "", "--no-startup", fn, "-s");
+    // Set the input from a String
+    protected void setIn(String s) {
+        cmdInStream = new ByteArrayInputStream(s.getBytes());
     }
 
-    public void testUsage() throws Exception {
+    // Test load files
+    public void testCommandFile() {
+        String fn = writeToFile("String str = \"Hello \"\n" +
+                "/list\n" +
+                "System.out.println(str + str)\n" +
+                "/exit\n");
+        startExCoUoCeCn(0,
+                "1 : String str = \"Hello \";\n",
+                "Hello Hello",
+                null,
+                null,
+                "--no-startup", fn, "-s");
+    }
+
+    // Test that the usage message is printed
+    public void testUsage() {
         for (String opt : new String[]{"-h", "--help"}) {
-            start(s -> {
+            startCo(s -> {
                 assertTrue(s.split("\n").length >= 7, "Not enough usage lines: " + s);
                 assertTrue(s.startsWith("Usage:   jshell <option>..."), "Unexpect usage start: " + s);
                 assertTrue(s.contains("--show-version"), "Expected help: " + s);
                 assertFalse(s.contains("Welcome"), "Unexpected start: " + s);
-            }, null, null, opt);
+            }, opt);
         }
     }
 
-    public void testHelpExtra() throws Exception {
+    // Test the --help-extra message
+    public void testHelpExtra() {
         for (String opt : new String[]{"-X", "--help-extra"}) {
-            start(s -> {
+            startCo(s -> {
                 assertTrue(s.split("\n").length >= 5, "Not enough help-extra lines: " + s);
                 assertTrue(s.contains("--add-exports"), "Expected --add-exports: " + s);
                 assertTrue(s.contains("--execution"), "Expected --add-exports: " + s);
                 assertFalse(s.contains("Welcome"), "Unexpected start: " + s);
-            }, null, null, opt);
+            }, opt);
         }
     }
 
-    public void testUnknown() throws Exception {
-        start(null, null,
-              s -> assertEquals(s.trim(), "Unknown option: u"), "-unknown");
-        start(null, null,
-              s -> assertEquals(s.trim(), "Unknown option: unknown"), "--unknown");
+    // Test handling of bogus options
+    public void testUnknown() {
+        startExCe(1, "Unknown option: u", "-unknown");
+        startExCe(1, "Unknown option: unknown", "--unknown");
     }
 
-    /**
-     * Test that input is read with "-" and there is no extra output.
-     * @throws Exception
-     */
-    public void testHypenFile() throws Exception {
-        cmdInStream = new ByteArrayInputStream("System.out.print(\"Hello\");\n".getBytes());
-        startWithUserOutput("", "Hello", "", "-");
-        cmdInStream = new ByteArrayInputStream("System.out.print(\"Hello\");\n".getBytes());
-        startWithUserOutput("", "Hello", "", "-", "-");
-        Compiler compiler = new Compiler();
-        Path path = compiler.getPath("markload.jsh");
-        compiler.writeToFile(path, "System.out.print(\"===\");");
-        cmdInStream = new ByteArrayInputStream("System.out.print(\"Hello\");\n".getBytes());
-        startWithUserOutput("", "===Hello===", "", path.toString(), "-", path.toString());
+    // Test that input is read with "-" and there is no extra output.
+    public void testHypenFile() {
+        setIn("System.out.print(\"Hello\");\n");
+        startUo("Hello", "-");
+        setIn("System.out.print(\"Hello\");\n");
+        startUo("Hello", "-", "-");
+        String fn = writeToFile("System.out.print(\"===\");");
+        setIn("System.out.print(\"Hello\");\n");
+        startUo("===Hello===", fn, "-", fn);
         // check that errors go to standard error
-        cmdInStream = new ByteArrayInputStream(") Foobar".getBytes());
-        start(
-                s -> assertEquals(s.trim(), "", "cmdout: empty"),
-                s -> assertEquals(s.trim(), "", "userout: empty"),
-                s -> assertTrue(s.contains("illegal start of expression"),
-                            "cmderr: illegal start of expression"),
+        setIn(") Foobar");
+        startExCe(0, s -> assertTrue(s.contains("illegal start of expression"),
+                "cmderr: illegal start of expression"),
                 "-");
     }
 
-    /**
-     * Test that non-existent load file sends output to stderr and does not start (no welcome).
-     * @throws Exception
-     */
-    public void testUnknownLoadFile() throws Exception {
-        start("", "File 'UNKNOWN' for 'jshell' is not found.", "UNKNOWN");
+    // Test that user specified exit codes are propagated
+    public void testExitCode() {
+        setIn("/exit 57\n");
+        startExCoUoCeCn(57, null, null, null, "-> /exit 57", "-s");
+        setIn("int eight = 8\n" +
+                "/exit eight + \n" +
+                " eight\n");
+        startExCoUoCeCn(16, null, null, null,
+                "-> int eight = 8\n" +
+                "-> /exit eight + \n" +
+                ">>  eight",
+                "-s");
     }
 
-    public void testStartup() throws Exception {
-        Compiler compiler = new Compiler();
-        Path p = compiler.getPath("file.txt");
-        compiler.writeToFile(p);
-        start("", "Argument to startup missing.", "--startup");
-        start("", "Conflicting options: both --startup and --no-startup were used.", "--no-startup", "--startup", p.toString());
-        start("", "Conflicting options: both --startup and --no-startup were used.", "--startup", p.toString(), "--no-startup");
-        start("", "Argument to startup missing.", "--no-startup", "--startup");
+    // Test that non-existent load file sends output to stderr and does not startExCe (no welcome).
+    public void testUnknownLoadFile() {
+        startExCe(1, "File 'UNKNOWN' for 'jshell' is not found.", "UNKNOWN");
     }
 
-    public void testStartupFailedOption() throws Exception {
-        start(
-                s -> assertEquals(s.trim(), "", "cmdout: "),
-                s -> assertEquals(s.trim(), "", "userout: "),
-                s -> assertTrue(s.contains("Unrecognized option: -hoge-foo-bar"), "cmderr: " + s),
+    // Test bad usage of the --startup option
+    public void testStartup() {
+        String fn = writeToFile("");
+        startExCe(1, "Argument to startup missing.", "--startup");
+        startExCe(1, "Conflicting options: both --startup and --no-startup were used.", "--no-startup", "--startup", fn);
+        startExCe(1, "Conflicting options: both --startup and --no-startup were used.", "--startup", fn, "--no-startup");
+        startExCe(1, "Argument to startup missing.", "--no-startup", "--startup");
+    }
+
+    // Test an option that causes the back-end to fail is propagated
+    public void testStartupFailedOption() {
+        startExCe(1, s -> assertTrue(s.contains("Unrecognized option: -hoge-foo-bar"), "cmderr: " + s),
                 "-R-hoge-foo-bar");
     }
 
-    public void testStartupUnknown() throws Exception {
-        start("", "File 'UNKNOWN' for '--startup' is not found.", "--startup", "UNKNOWN");
-        start("", "File 'UNKNOWN' for '--startup' is not found.", "--startup", "DEFAULT", "--startup", "UNKNOWN");
+    // Test the use of non-existant files with the --startup option
+    public void testStartupUnknown() {
+        startExCe(1, "File 'UNKNOWN' for '--startup' is not found.", "--startup", "UNKNOWN");
+        startExCe(1, "File 'UNKNOWN' for '--startup' is not found.", "--startup", "DEFAULT", "--startup", "UNKNOWN");
     }
 
-    public void testClasspath() throws Exception {
-        for (String cp : new String[] {"--class-path"}) {
-            start("", "Only one --class-path option may be used.", cp, ".", "--class-path", ".");
-            start("", "Argument to class-path missing.", cp);
+    // Test bad usage of --class-path option
+    public void testClasspath() {
+        for (String cp : new String[]{"--class-path"}) {
+            startExCe(1, "Only one --class-path option may be used.", cp, ".", "--class-path", ".");
+            startExCe(1, "Argument to class-path missing.", cp);
         }
     }
 
-    public void testUnknownModule() throws Exception {
-        start(
-                s -> assertEquals(s.trim(), "", "cmdout: "),
-                s -> assertEquals(s.trim(), "", "userout: "),
-                s -> assertTrue(s.contains("rror") && s.contains("unKnown"), "cmderr: " + s),
+    // Test bogus module on --add-modules option
+    public void testUnknownModule() {
+        startExCe(1, s -> assertTrue(s.contains("rror") && s.contains("unKnown"), "cmderr: " + s),
                 "--add-modules", "unKnown");
     }
 
-    public void testFeedbackOptionConflict() throws Exception {
-        start("", "Only one feedback option (--feedback, -q, -s, or -v) may be used.",
+    // Test that muliple feedback options fail
+    public void testFeedbackOptionConflict() {
+        startExCe(1, "Only one feedback option (--feedback, -q, -s, or -v) may be used.",
                 "--feedback", "concise", "--feedback", "verbose");
-        start("", "Only one feedback option (--feedback, -q, -s, or -v) may be used.", "--feedback", "concise", "-s");
-        start("", "Only one feedback option (--feedback, -q, -s, or -v) may be used.", "--feedback", "verbose", "-q");
-        start("", "Only one feedback option (--feedback, -q, -s, or -v) may be used.", "--feedback", "concise", "-v");
-        start("", "Only one feedback option (--feedback, -q, -s, or -v) may be used.", "-v", "--feedback", "concise");
-        start("", "Only one feedback option (--feedback, -q, -s, or -v) may be used.", "-q", "-v");
-        start("", "Only one feedback option (--feedback, -q, -s, or -v) may be used.", "-s", "-v");
-        start("", "Only one feedback option (--feedback, -q, -s, or -v) may be used.", "-v", "-q");
-        start("", "Only one feedback option (--feedback, -q, -s, or -v) may be used.", "-q", "-s");
+        startExCe(1, "Only one feedback option (--feedback, -q, -s, or -v) may be used.", "--feedback", "concise", "-s");
+        startExCe(1, "Only one feedback option (--feedback, -q, -s, or -v) may be used.", "--feedback", "verbose", "-q");
+        startExCe(1, "Only one feedback option (--feedback, -q, -s, or -v) may be used.", "--feedback", "concise", "-v");
+        startExCe(1, "Only one feedback option (--feedback, -q, -s, or -v) may be used.", "-v", "--feedback", "concise");
+        startExCe(1, "Only one feedback option (--feedback, -q, -s, or -v) may be used.", "-q", "-v");
+        startExCe(1, "Only one feedback option (--feedback, -q, -s, or -v) may be used.", "-s", "-v");
+        startExCe(1, "Only one feedback option (--feedback, -q, -s, or -v) may be used.", "-v", "-q");
+        startExCe(1, "Only one feedback option (--feedback, -q, -s, or -v) may be used.", "-q", "-s");
     }
 
-    public void testNegFeedbackOption() throws Exception {
-        start("", "Argument to feedback missing.", "--feedback");
-        start("", "Does not match any current feedback mode: blorp -- --feedback blorp", "--feedback", "blorp");
+    // Test bogus arguments to the --feedback option
+    public void testNegFeedbackOption() {
+        startExCe(1, "Argument to feedback missing.", "--feedback");
+        startExCe(1, "Does not match any current feedback mode: blorp -- --feedback blorp", "--feedback", "blorp");
     }
 
-    public void testVersion() throws Exception {
-        start(
-                s -> {
-                    assertTrue(s.startsWith("jshell"), "unexpected version: " + s);
-                    assertFalse(s.contains("Welcome"), "Unexpected start: " + s);
-                },
-                null, null,
+    // Test --version
+    public void testVersion() {
+        startCo(s -> {
+            assertTrue(s.startsWith("jshell"), "unexpected version: " + s);
+            assertFalse(s.contains("Welcome"), "Unexpected start: " + s);
+        },
                 "--version");
     }
 
-    public void testShowVersion() throws Exception {
-        runShell("--show-version");
-        check(cmdout,
+    // Test --show-version
+    public void testShowVersion() {
+        startExCoUoCeCn(null,
                 s -> {
                     assertTrue(s.startsWith("jshell"), "unexpected version: " + s);
                     assertTrue(s.contains("Welcome"), "Expected start (but got no welcome): " + s);
                 },
-                "cmdout");
-        check(cmderr, null, "cmderr");
-        check(console,
+                null,
+                null,
                 s -> assertTrue(s.trim().startsWith("jshell>"), "Expected prompt, got: " + s),
-                "console");
-        check(userout, null, "userout");
-        check(usererr, null, "usererr");
+                "--show-version");
     }
 
     @AfterMethod
     public void tearDown() {
-        cmdout  = null;
-        cmderr  = null;
+        cmdout = null;
+        cmderr = null;
         console = null;
         userout = null;
         usererr = null;
--- a/test/langtools/jdk/jshell/ToolProviderTest.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/test/langtools/jdk/jshell/ToolProviderTest.java	Mon Nov 27 17:04:45 2017 +0000
@@ -21,21 +21,14 @@
  * questions.
  */
 
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.InputStream;
-import java.nio.file.Path;
 import java.util.ServiceLoader;
-import java.util.function.Consumer;
 import javax.tools.Tool;
-import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
 import static org.testng.Assert.assertTrue;
-import static org.testng.Assert.fail;
 
 /*
  * @test
- * @bug 8170044 8171343 8179856
+ * @bug 8170044 8171343 8179856 8185840 8190383
  * @summary Test ServiceLoader launching of jshell tool
  * @modules jdk.compiler/com.sun.tools.javac.api
  *          jdk.compiler/com.sun.tools.javac.main
@@ -48,30 +41,25 @@
 @Test
 public class ToolProviderTest extends StartOptionTest {
 
-    private ByteArrayOutputStream cmdout;
-    private ByteArrayOutputStream cmderr;
-    private InputStream cmdInStream;
-
-    @BeforeMethod
+    // Through the provider, the console and console go to command out (we assume,
+    // because it works with the current tests) that console and user output are
+    // after command out.
     @Override
-    public void setUp() {
-        cmdout = new ByteArrayOutputStream();
-        cmderr = new ByteArrayOutputStream();
-        cmdInStream = new ByteArrayInputStream("/exit\n".getBytes());
+    protected void startExCoUoCeCn(int expectedExitCode,
+            String expectedCmdOutput,
+            String expectedUserOutput,
+            String expectedError,
+            String expectedConsole,
+            String... args) {
+        super.startExCoUoCeCn(expectedExitCode,
+                (expectedCmdOutput  == null? "" : expectedCmdOutput) +
+                (expectedConsole    == null? "" : expectedConsole) +
+                (expectedUserOutput == null? "" : expectedUserOutput),
+                null, expectedError, null, args);
     }
 
     @Override
-    protected void start(Consumer<String> checkCmdOutput,
-            Consumer<String> checkUserOutput, Consumer<String> checkError,
-            String... args) throws Exception {
-        if (runShellServiceLoader(args) != 0) {
-            fail("Repl tool failed");
-        }
-        check(cmdout, checkCmdOutput, "cmdout");
-        check(cmderr, checkError, "cmderr");
-    }
-
-    private int runShellServiceLoader(String... args) {
+    protected int runShell(String... args) {
         ServiceLoader<Tool> sl = ServiceLoader.load(Tool.class);
         for (Tool provider : sl) {
             if (provider.name().equals("jshell")) {
@@ -81,38 +69,14 @@
         throw new AssertionError("Repl tool not found by ServiceLoader: " + sl);
     }
 
-    @Override
-    public void testCommandFile() throws Exception {
-        String fn = writeToFile("String str = \"Hello \"\n/list\nSystem.out.println(str + str)\n/exit\n");
-        start("1 : String str = \"Hello \";" + "\n" + "Hello Hello", "", "--no-startup", fn, "-s");
-    }
-
+    // Test --show-version
     @Override
-    public void testShowVersion() throws Exception {
-        start(
-                s -> {
-                    assertTrue(s.startsWith("jshell "), "unexpected version: " + s);
-                    assertTrue(s.contains("Welcome"), "Expected start (but got no welcome): " + s);
-                    assertTrue(s.trim().contains("jshell>"), "Expected prompt, got: " + s);
-                },
-                null, null,
+    public void testShowVersion() {
+        startCo(s -> {
+            assertTrue(s.startsWith("jshell "), "unexpected version: " + s);
+            assertTrue(s.contains("Welcome"), "Expected start (but got no welcome): " + s);
+            assertTrue(s.trim().contains("jshell>"), "Expected prompt, got: " + s);
+        },
                 "--show-version");
     }
-    /**
-     * Test that input is read with "-" and there is no extra output.
-     * @throws Exception
-     */
-    @Override
-    public void testHypenFile() throws Exception {
-        cmdInStream = new ByteArrayInputStream("System.out.print(\"Hello\");\n".getBytes());
-        start("Hello", "", "-");
-        cmdInStream = new ByteArrayInputStream("System.out.print(\"Hello\");\n".getBytes());
-        start("Hello", "", "-", "-");
-        Compiler compiler = new Compiler();
-        Path path = compiler.getPath("markload.jsh");
-        compiler.writeToFile(path, "System.out.print(\"===\");");
-        cmdInStream = new ByteArrayInputStream("System.out.print(\"Hello\");\n".getBytes());
-        start("===Hello===", "", path.toString(), "-", path.toString());
-    }
-
 }
--- a/test/langtools/jdk/jshell/ToolSimpleTest.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/test/langtools/jdk/jshell/ToolSimpleTest.java	Mon Nov 27 17:04:45 2017 +0000
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug 8153716 8143955 8151754 8150382 8153920 8156910 8131024 8160089 8153897 8167128 8154513 8170015 8170368 8172102 8172103  8165405 8173073 8173848 8174041 8173916 8174028 8174262 8174797 8177079 8180508 8177466
+ * @bug 8153716 8143955 8151754 8150382 8153920 8156910 8131024 8160089 8153897 8167128 8154513 8170015 8170368 8172102 8172103  8165405 8173073 8173848 8174041 8173916 8174028 8174262 8174797 8177079 8180508 8177466 8172154
  * @summary Simple jshell tool tests
  * @modules jdk.compiler/com.sun.tools.javac.api
  *          jdk.compiler/com.sun.tools.javac.main
@@ -633,6 +633,17 @@
     }
 
     @Test
+    public void testJavaSeSetStart() {
+        test(
+                (a) -> assertCommand(a, "/set sta JAVASE", ""),
+                (a) -> assertCommand(a, "/reset", "|  Resetting state."),
+                (a) -> assertCommandCheckOutput(a, "/li -a",
+                            s -> assertTrue(s.split("import ").length > 160,
+                            "not enough imports for JAVASE:\n" + s))
+        );
+    }
+
+    @Test
     public void defineClasses() {
         test(
                 (a) -> assertCommandCheckOutput(a, "/list", assertList()),
--- a/test/langtools/jdk/jshell/ToolTabCommandTest.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/test/langtools/jdk/jshell/ToolTabCommandTest.java	Mon Nov 27 17:04:45 2017 +0000
@@ -23,7 +23,7 @@
 
 /**
  * @test
- * @bug 8177076
+ * @bug 8177076 8185840 8178109
  * @modules
  *     jdk.compiler/com.sun.tools.javac.api
  *     jdk.compiler/com.sun.tools.javac.main
@@ -107,11 +107,16 @@
             waitOutput(out, Pattern.quote(getResource("help.exit.summary")) + "\n\n" +
                             Pattern.quote(getResource("jshell.console.see.full.documentation")) + "\n\r\u0005/exit ");
             inputSink.write("\011");
-            waitOutput(out, Pattern.quote(getResource("help.exit")) + "\n" +
+            waitOutput(out, Pattern.quote(getResource("help.exit").replaceAll("\t", "    ")) + "\n" +
                             "\r\u0005/exit ");
             inputSink.write("\011");
             waitOutput(out, Pattern.quote(getResource("help.exit.summary")) + "\n\n" +
                             Pattern.quote(getResource("jshell.console.see.full.documentation")) + "\n\r\u0005/exit ");
+            inputSink.write("\u0003");
+            inputSink.write("int zebraStripes = 11\n");
+            waitOutput(out, "zebraStripes ==> 11\n\u0005");
+            inputSink.write("/exit zeb\011");
+            waitOutput(out, "braStr.*es");
             inputSink.write("\u0003/doesnotexist\011");
             waitOutput(out, "\u0005/doesnotexist\n" +
                             Pattern.quote(getResource("jshell.console.no.such.command")) + "\n" +
@@ -120,4 +125,67 @@
         });
     }
 
+    public void testHelp() throws Exception {
+        // set terminal height so that help output won't hit page breaks
+        System.setProperty("test.terminal.height", "1000000");
+
+        doRunTest((inputSink, out) -> {
+            inputSink.write("/help \011");
+            waitOutput(out, ".*/edit.*/list.*intro.*\n\n" + Pattern.quote(getResource("jshell.console.see.synopsis")) + "\n" +
+                            "\r\u0005/");
+            inputSink.write("\011");
+            waitOutput(out,   ".*\n/edit\n" + Pattern.quote(getResource("help.edit.summary")) +
+                            "\n.*\n/list\n" + Pattern.quote(getResource("help.list.summary")) +
+                            "\n.*\nintro\n" + Pattern.quote(getResource("help.intro.summary")) +
+                            ".*\n\n" + Pattern.quote(getResource("jshell.console.see.full.documentation")) + "\n" +
+                            "\r\u0005/");
+            inputSink.write("/env\011");
+            waitOutput(out,   "help /env ");
+            inputSink.write("\011");
+            waitOutput(out,   ".*\n/env\n" + Pattern.quote(getResource("help.env.summary")) +
+                            ".*\n\n" + Pattern.quote(getResource("jshell.console.see.full.documentation")) + "\n" +
+                            "\r\u0005/help /env ");
+            inputSink.write("\011");
+            waitOutput(out,   ".*\n/env\n" + Pattern.quote(getResource("help.env").replaceAll("\t", "    ")) + "\n" +
+                            "\r\u0005/help /env ");
+            inputSink.write("\u0003/help intro\011");
+            waitOutput(out,   "help intro ");
+            inputSink.write("\011");
+            waitOutput(out,   ".*\nintro\n" + Pattern.quote(getResource("help.intro.summary")) +
+                            ".*\n\n" + Pattern.quote(getResource("jshell.console.see.full.documentation")) + "\n" +
+                            "\r\u0005/help intro ");
+            inputSink.write("\011");
+            waitOutput(out,   ".*\nintro\n" + Pattern.quote(getResource("help.intro").replaceAll("\t", "    ")) + "\n" +
+                            "\r\u0005/help intro ");
+            inputSink.write("\u0003/help /set \011");
+            waitOutput(out, ".*format.*truncation.*\n\n" + Pattern.quote(getResource("jshell.console.see.synopsis")) + "\n" +
+                            "\r\u0005/help /set ");
+            inputSink.write("\011");
+            waitOutput(out,   ".*\n/set format\n" + Pattern.quote(getResource("help.set.format.summary")) +
+                            "\n.*\n/set truncation\n" + Pattern.quote(getResource("help.set.truncation.summary")) +
+                            ".*\n\n" + Pattern.quote(getResource("jshell.console.see.full.documentation")) + "\n" +
+                            "\r\u0005/help /set ");
+            inputSink.write("truncation\011");
+            waitOutput(out,   ".*truncation\n" + Pattern.quote(getResource("jshell.console.see.synopsis")) + "\n" +
+                            "\r\u0005/help /set truncation");
+            inputSink.write("\011");
+            waitOutput(out,   ".*/set truncation\n" + Pattern.quote(getResource("help.set.truncation.summary")) + "\n" +
+                            "\n" + Pattern.quote(getResource("jshell.console.see.full.documentation")) + "\n" +
+                            "\r\u0005/help /set truncation");
+            inputSink.write("\011");
+            waitOutput(out,   ".*/set truncation\n" + Pattern.quote(getResource("help.set.truncation").replaceAll("\t", "    ")) +
+                            "\r\u0005/help /set truncation");
+            inputSink.write("\u0003/help env \011");
+            waitOutput(out,   ".*\n/env\n" + Pattern.quote(getResource("help.env.summary")) +
+                            ".*\n\n" + Pattern.quote(getResource("jshell.console.see.full.documentation")) + "\n" +
+                            "\r\u0005/help env ");
+            inputSink.write("\u0003/help set truncation\011");
+            waitOutput(out,   ".*truncation\n" + Pattern.quote(getResource("jshell.console.see.synopsis")) + "\n" +
+                            "\r\u0005/help set truncation");
+            inputSink.write("\011");
+            waitOutput(out,   ".*\n/set truncation\n" + Pattern.quote(getResource("help.set.truncation.summary")) +
+                            ".*\n\n" + Pattern.quote(getResource("jshell.console.see.full.documentation")) + "\n" +
+                            "\r\u0005/help set truncation");
+        });
+    }
 }
--- a/test/langtools/tools/javac/failover/CheckAttributedTree.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/test/langtools/tools/javac/failover/CheckAttributedTree.java	Mon Nov 27 17:04:45 2017 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2017, 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
@@ -138,8 +138,13 @@
             else
                 System.exit(1);
         }
+        System.err.println("total number of compilations " + totalNumberOfCompilations);
+        System.err.println("number of failed compilations " + numberOfFailedCompilations);
     }
 
+    static private int totalNumberOfCompilations = 0;
+    static private int numberOfFailedCompilations = 0;
+
     /**
      * Run the program. A base directory can be provided for file arguments.
      * In jtreg mode, the -r option can be given to change the default base
@@ -307,10 +312,12 @@
             Iterable<? extends JavaFileObject> files = fileManager().getJavaFileObjects(file);
             final List<Element> analyzedElems = new ArrayList<>();
             final List<CompilationUnitTree> trees = new ArrayList<>();
+            totalNumberOfCompilations++;
             newCompilationTask()
                 .withWriter(pw)
                     .withOption("--should-stop:at=ATTR")
                     .withOption("-XDverboseCompilePolicy")
+                    .withOption("-Xdoclint:none")
                     .withSource(files.iterator().next())
                     .withListener(new TaskListener() {
                         public void started(TaskEvent e) {
@@ -324,16 +331,18 @@
                     }
                 }).analyze(res -> {
                 Iterable<? extends Element> elems = res.get();
-                if (!elems.iterator().hasNext())
-                    throw new AssertionError("No results from analyze");
-                for (CompilationUnitTree t : trees) {
-                   JCCompilationUnit cu = (JCCompilationUnit)t;
-                   for (JCTree def : cu.defs) {
-                       if (def.hasTag(CLASSDEF) &&
-                               analyzedElems.contains(((JCTree.JCClassDecl)def).sym)) {
-                           c.accept(cu, def);
+                if (elems.iterator().hasNext()) {
+                    for (CompilationUnitTree t : trees) {
+                       JCCompilationUnit cu = (JCCompilationUnit)t;
+                       for (JCTree def : cu.defs) {
+                           if (def.hasTag(CLASSDEF) &&
+                                   analyzedElems.contains(((JCTree.JCClassDecl)def).sym)) {
+                               c.accept(cu, def);
+                           }
                        }
-                   }
+                    }
+                } else {
+                    numberOfFailedCompilations++;
                 }
             });
         }
--- a/test/langtools/tools/javac/flow/tests/TestCaseForEach.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/test/langtools/tools/javac/flow/tests/TestCaseForEach.java	Mon Nov 27 17:04:45 2017 +0000
@@ -3,7 +3,7 @@
 public class TestCaseForEach {
 
     @AliveRange(varName="o", bytecodeStart=25, bytecodeLength=11)
-    @AliveRange(varName="o", bytecodeStart=39, bytecodeLength=1)
+    @AliveRange(varName="o", bytecodeStart=44, bytecodeLength=1)
     void m(String[] args) {
         Object o;
         for (String s : args) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/generics/bridges/AnonymousSubtypeOfRawSupertype.java	Mon Nov 27 17:04:45 2017 +0000
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2017, 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 8189659
+ * @summary Anonymous subtype of raw type causes VerifyError
+ * @run main AnonymousSubtypeOfRawSupertype
+ */
+
+public class AnonymousSubtypeOfRawSupertype<_J extends AnonymousSubtypeOfRawSupertype> implements Comparable<_J> {
+    static {
+        System.err.println(System.getProperty("java.version"));
+    }
+    public static AnonymousSubtypeOfRawSupertype EMPTY = new AnonymousSubtypeOfRawSupertype() {
+        void something() {
+            System.out.println("This is something");
+        }
+    };
+    public AnonymousSubtypeOfRawSupertype() {
+    }
+    @Override
+    public int compareTo(_J o) {
+        return 0;
+    }
+    public static void main(String[] args) {
+        AnonymousSubtypeOfRawSupertype generic = AnonymousSubtypeOfRawSupertype.EMPTY;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/generics/bridges/VerifyNoBridgeLoopTest.java	Mon Nov 27 17:04:45 2017 +0000
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2017, 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 8189659
+ * @summary Verify that the infinite loop of bridges from JDK-6996415 is not reintroduced
+ * @run main VerifyNoBridgeLoopTest
+ */
+
+public class VerifyNoBridgeLoopTest {
+    static class Expression {}
+    abstract static class ExpVisitor<R,D> {
+      static int f = 1;
+      protected R visitExpression (Expression exp, D d) { f *= 100; System.out.println(exp); return null; }
+    }
+
+    abstract static class ExpExpVisitor<D> extends ExpVisitor<Expression,D> { }
+
+    static class FindTail extends ExpExpVisitor<Expression> {
+      protected Expression visitExpression (Expression exp, Expression returnContinuation) {
+          return super.visitExpression(exp, exp);
+      }
+    }
+    public static void main(String [] args) {
+        new FindTail().visitExpression(new Expression(), new Expression());
+        ExpVisitor<Expression, Expression> e = new FindTail();
+        e.visitExpression(new Expression(), new Expression());
+        if (e.f != 10000)
+            throw new AssertionError("Incorrect call sequence");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/lambda/methodReferenceExecution/MethodReferenceIntersectionInducedTest.java	Mon Nov 27 17:04:45 2017 +0000
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2017, 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 8191655
+ * @summary LambdaConversionException: Invalid receiver type interface; not a subtype of implementation type interface
+ * @run main MethodReferenceIntersectionInducedTest
+ */
+
+
+import java.util.function.Consumer;
+public class MethodReferenceIntersectionInducedTest {
+   static String blah;
+   <T> void forAll(Consumer<T> consumer, T... values) { consumer.accept(values[0]); }
+
+   public void secondTest() {
+       forAll(Picture::draw, new MyPicture(), new Universal());
+   }
+
+   interface Shape { void draw(); }
+   interface Marker { }
+   interface Picture { void draw(); }
+
+   class MyShape implements Marker, Shape { public void draw() { } }
+   class MyPicture implements Marker, Picture { public void draw() { blah = "MyPicture"; } }
+   class Universal implements Marker, Picture, Shape { public void draw() { System.out.println("Universal"); } }
+
+   public static void main(String[] args) {
+       new MethodReferenceIntersectionInducedTest().secondTest();
+       if (!blah.equals("MyPicture"))
+            throw new AssertionError("Incorrect output");
+   }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/lambda/methodReferenceExecution/MethodReferenceUnionTypeTest.java	Mon Nov 27 17:04:45 2017 +0000
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2017, 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 8191655
+ * @summary LambdaConversionException: Invalid receiver type interface; not a subtype of implementation type interface
+ * @run main MethodReferenceUnionTypeTest
+ */
+
+import java.util.function.Consumer;
+public class MethodReferenceUnionTypeTest {
+   static String blah = "NONE";
+   <T> void forAll(Consumer<T> consumer, T value) { consumer.accept(value); }
+
+   public void secondTest() {
+       try {
+          throwing();
+        } catch (A | B ex) {
+            forAll(Picture::draw, ex);
+        }
+   }
+
+   void throwing() throws A, B { throw new A();}
+
+   interface Shape { void draw(); }
+   interface Marker { }
+   interface Picture { void draw();  }
+
+   class A extends Exception implements Marker, Picture { public void draw() { blah = "A"; }}
+   class B extends Exception implements Marker, Picture, Shape { public void draw() {}}
+
+   public static void main(String[] args) {
+       new MethodReferenceUnionTypeTest().secondTest();
+       if (!blah.equals("A"))
+            throw new AssertionError("Incorrect output");
+   }
+}
\ No newline at end of file
--- a/test/langtools/tools/javac/modules/ExportsUnexported.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/test/langtools/tools/javac/modules/ExportsUnexported.java	Mon Nov 27 17:04:45 2017 +0000
@@ -23,6 +23,7 @@
 
 /*
  * @test
+ * @bug 8191112
  * @summary tests for module declarations
  * @library /tools/lib
  * @modules jdk.compiler/com.sun.tools.javac.api
@@ -31,12 +32,15 @@
  * @run main ExportsUnexported
  */
 
+import java.nio.file.Files;
 import java.nio.file.Path;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
+import java.util.stream.Collectors;
 
+import toolbox.JarTask;
 import toolbox.JavacTask;
 import toolbox.Task;
 
@@ -374,4 +378,98 @@
             throw new Exception("expected output not found");
     }
 
+    @Test
+    public void testTransitiveAndAutomaticModules(Path base) throws Exception {
+        Path modulePath = base.resolve("module-path");
+
+        Files.createDirectories(modulePath);
+
+        createAutomaticModule(base,
+                              modulePath.resolve("api-one-1.0.jar"),
+                              "package api1; public interface Api1 {}");
+        createAutomaticModule(base,
+                              modulePath.resolve("api-two-1.0.jar"),
+                              "package api2; public interface Api2 {}");
+        createAutomaticModule(base,
+                              modulePath.resolve("api-three-1.0.jar"),
+                              "package api3; public interface Api3 {}");
+
+        Path src = base.resolve("src");
+        Path src_api = src.resolve("api");
+        tb.writeJavaFiles(src_api,
+                          "module api {\n" +
+                          "    requires transitive dep;\n" +
+                          "    requires transitive api.one;\n" +
+                          "    exports api;\n" +
+                          "}\n",
+                          "package api;\n" +
+                          "public class Api extends dep.Dep implements api2.Api2 {}\n");
+        Path src_dep = src.resolve("dep");
+        tb.writeJavaFiles(src_dep,
+                          "module dep {\n" +
+                          "    requires transitive api.one;\n" +
+                          "    exports dep;\n" +
+                          "}\n",
+                          "package dep;\n" +
+                          "public class Dep {}\n");
+        Path classes = base.resolve("classes");
+        tb.createDirectories(classes);
+
+        List<String> log = new JavacTask(tb)
+                .options("-XDrawDiagnostics",
+                         "-Werror",
+                         "--module-source-path", src.toString(),
+                         "--module-path", modulePath.toString(),
+                         "-Xlint:exports,-requires-transitive-automatic")
+                .outdir(classes)
+                .files(findJavaFiles(src))
+                .run(Task.Expect.FAIL)
+                .writeAll()
+                .getOutputLines(Task.OutputKind.DIRECT);
+
+        List<String> expected = Arrays.asList(
+            "Api.java:2:49: compiler.warn.leaks.not.accessible.not.required.transitive: kindname.interface, api2.Api2, api.two",
+            "- compiler.err.warnings.and.werror",
+            "1 error",
+            "1 warning"
+        );
+
+        if (!log.equals(expected))
+            throw new Exception("expected output not found");
+    }
+
+    private void createAutomaticModule(Path base, Path jar, String content) throws Exception {
+        Path scratch = base.resolve("scratch");
+        Files.createDirectories(scratch);
+        tb.cleanDirectory(scratch);
+        tb.writeJavaFiles(scratch,
+                          content);
+        Path scratchClasses = base.resolve("scratch-classes");
+        Files.createDirectories(scratchClasses);
+        tb.cleanDirectory(scratchClasses);
+
+        String log = new JavacTask(tb)
+                .options()
+                .outdir(scratchClasses)
+                .files(findJavaFiles(scratch))
+                .run()
+                .writeAll()
+                .getOutput(Task.OutputKind.DIRECT);
+
+        if (!log.isEmpty()) {
+            throw new Exception("unexpected output: " + log);
+        }
+
+        Files.createDirectories(scratchClasses.getParent());
+        Files.deleteIfExists(jar);
+
+        new JarTask(tb, jar)
+          .baseDir(scratchClasses)
+          .files(Arrays.stream(tb.findFiles(".class", scratchClasses))
+                       .map(p -> scratchClasses.relativize(p).toString())
+                       .collect(Collectors.toList())
+                       .toArray(new String[0]))
+          .run();
+    }
+
 }
--- a/test/langtools/tools/javadoc/sourceOnly/Test.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/test/langtools/tools/javadoc/sourceOnly/Test.java	Mon Nov 27 17:04:45 2017 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, 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,11 +23,11 @@
 
 /*
  * @test
- * @bug 4548768
+ * @bug 4548768 8034258
  * @summary Javadoc in JDK 1.4 uses classpath and not just source dir
  * @author gafter
  * @modules jdk.javadoc
- * @compile p/SourceOnly.java
+ * @compile p/SourceOnly.java p/NonSource.jasm
  * @run main p.SourceOnly
  */
 
Binary file test/langtools/tools/javadoc/sourceOnly/p/NonSource.class has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javadoc/sourceOnly/p/NonSource.jasm	Mon Nov 27 17:04:45 2017 +0000
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+package  p;
+
+super public class NonSource
+        version 46:0
+{
+    public Method "<init>":"()V"
+        stack 1 locals 1
+    {
+                aload_0;
+                invokespecial   Method java/lang/Object."<init>":"()V";
+                return;
+    }
+}
--- a/test/langtools/tools/javadoc/sourceOnly/p/SourceOnly.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/test/langtools/tools/javadoc/sourceOnly/p/SourceOnly.java	Mon Nov 27 17:04:45 2017 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2017, 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
@@ -26,8 +26,9 @@
 /** Test that when running javadoc on a package, we only get
  *  documentation for those classes for which source was provided.
  */
-public class SourceOnly extends com.sun.javadoc.Doclet
-{
+public class SourceOnly extends com.sun.javadoc.Doclet {
+    NonSource dependency; // force a compilation error if not on classpath.
+
     public static void main(String[] args) {
         // run javadoc on package p
         int result = com.sun.tools.javadoc.Main.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javap/AnnoTest.java	Mon Nov 27 17:04:45 2017 +0000
@@ -0,0 +1,170 @@
+/*
+ * Copyright (c) 2014, 2017, 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 8156694
+ * @summary javap should render annotations in a friendly way
+ * @modules jdk.jdeps/com.sun.tools.javap
+ */
+
+import java.io.*;
+import java.lang.annotation.*;
+import javax.lang.model.element.ElementKind;
+
+public class AnnoTest {
+    public static void main(String... args) throws Exception {
+        new AnnoTest().run();
+    }
+
+    void run() throws Exception {
+        String testClasses = System.getProperty("test.classes");
+        String out = javap("-v", "-classpath", testClasses, A.class.getName());
+
+        String nl = System.getProperty("line.separator");
+        out = out.replaceAll(nl, "\n");
+
+        if (out.contains("\n\n\n"))
+            error("double blank line found");
+
+        expect(out,
+                "RuntimeVisibleAnnotations:\n" +
+                "  0: #18(#19=B#20)\n" +
+                "    AnnoTest$ByteAnno(\n" +
+                "      value=(byte) 42\n" +
+                "    )\n" +
+                "  1: #23(#19=S#24)\n" +
+                "    AnnoTest$ShortAnno(\n" +
+                "      value=(short) 3\n" +
+                "    )");
+        expect(out,
+                "RuntimeInvisibleAnnotations:\n" +
+                "  0: #28(#19=[J#29,J#31,J#33,J#35,J#37])\n" +
+                "    AnnoTest$ArrayAnno(\n" +
+                "      value=[1l,2l,3l,4l,5l]\n" +
+                "    )\n" +
+                "  1: #41(#19=Z#42)\n" +
+                "    AnnoTest$BooleanAnno(\n" +
+                "      value=false\n" +
+                "    )\n" +
+                "  2: #45(#46=c#47)\n" +
+                "    AnnoTest$ClassAnno(\n" +
+                "      type=class Ljava/lang/Object;\n" +
+                "    )\n" +
+                "  3: #50(#51=e#52.#53)\n" +
+                "    AnnoTest$EnumAnno(\n" +
+                "      kind=Ljavax/lang/model/element/ElementKind;.PACKAGE\n" +
+                "    )\n" +
+                "  4: #56(#19=I#57)\n" +
+                "    AnnoTest$IntAnno(\n" +
+                "      value=2\n" +
+                "    )\n" +
+                "  5: #60()\n" +
+                "    AnnoTest$IntDefaultAnno\n" +
+                "  6: #63(#64=s#65)\n" +
+                "    AnnoTest$NameAnno(\n" +
+                "      name=\"NAME\"\n" +
+                "    )\n" +
+                "  7: #68(#69=D#70,#72=F#73)\n" +
+                "    AnnoTest$MultiAnno(\n" +
+                "      d=3.14159d\n" +
+                "      f=2.71828f\n" +
+                "    )\n" +
+                "  8: #76()\n" +
+                "    AnnoTest$SimpleAnno\n" +
+                "  9: #79(#19=@#56(#19=I#80))\n" +
+                "    AnnoTest$AnnoAnno(\n" +
+                "      value=@AnnoTest$IntAnno(\n" +
+                "        value=5\n" +
+                "      )\n" +
+                "    )");
+        expect(out,
+                "RuntimeInvisibleTypeAnnotations:\n" +
+                "  0: #84(): CLASS_EXTENDS, type_index=0\n" +
+                "    AnnoTest$TypeAnno");
+
+        if (errors > 0)
+            throw new Exception(errors + " errors found");
+    }
+
+    String javap(String... args) throws Exception {
+        StringWriter sw = new StringWriter();
+        int rc;
+        try (PrintWriter out = new PrintWriter(sw)) {
+            rc = com.sun.tools.javap.Main.run(args, out);
+        }
+        System.out.println(sw.toString());
+        if (rc < 0)
+            throw new Exception("javap exited, rc=" + rc);
+        return sw.toString();
+    }
+
+    void expect(String text, String expect) {
+        if (!text.contains(expect))
+            error("expected text not found");
+    }
+
+    void error(String msg) {
+        System.out.println("Error: " + msg);
+        errors++;
+    }
+
+    int errors;
+
+    /* Simple test classes to run through javap. */
+    public @interface SimpleAnno { }
+    public @interface BooleanAnno { boolean value(); }
+    public @interface IntAnno { int value(); }
+    public @interface IntDefaultAnno { int value() default 3; }
+
+    @Retention(RetentionPolicy.RUNTIME)
+    public @interface ByteAnno { byte value(); }
+
+    @Retention(RetentionPolicy.RUNTIME)
+    public @interface ShortAnno { short value(); }
+
+    public @interface NameAnno { String name(); }
+    public @interface ArrayAnno { long[] value(); }
+    public @interface EnumAnno { ElementKind kind(); }
+    public @interface ClassAnno { Class<?> type(); }
+    public @interface MultiAnno { float f(); double d(); }
+
+    public @interface AnnoAnno { IntAnno value(); }
+
+    @Target(ElementType.TYPE_USE)
+    public @interface TypeAnno { }
+
+    @ArrayAnno({1, 2, 3, 4, 5})
+    @BooleanAnno(false)
+    @ByteAnno(42)
+    @ClassAnno(type = Object.class)
+    @EnumAnno(kind = ElementKind.PACKAGE)
+    @IntAnno(2)
+    @IntDefaultAnno
+    @NameAnno(name = "NAME")
+    @MultiAnno(d = 3.14159, f = 2.71828f)
+    @ShortAnno(3)
+    @SimpleAnno
+    @AnnoAnno(@IntAnno(5))
+    public abstract class A implements @TypeAnno Runnable { }
+}
--- a/test/langtools/tools/javap/typeAnnotations/InvisibleParameterAnnotationsTest.java	Fri Nov 24 17:19:47 2017 +0000
+++ b/test/langtools/tools/javap/typeAnnotations/InvisibleParameterAnnotationsTest.java	Mon Nov 27 17:04:45 2017 +0000
@@ -65,9 +65,11 @@
             "      parameter 0:\n" +
             "      parameter 1:\n" +
             "        0: #16()\n" +
+            "          Sample$VisAnno\n" +
             "    RuntimeInvisibleParameterAnnotations:\n" +
             "      parameter 0:\n" +
             "        0: #18()\n" +
+            "          Sample$InvisAnno\n" +
             "      parameter 1:";
 
     public static void main(String[] args) throws Exception {
@@ -78,6 +80,7 @@
                 .options("-v")
                 .classes("Sample.class")
                 .run()
+                .writeAll()
                 .getOutputLines(Task.OutputKind.DIRECT);
 
         List<String> expectedList = tb.split(ExpectedSubstring, "\n");
--- a/test/make/TestCopyFiles.gmk	Fri Nov 24 17:19:47 2017 +0000
+++ b/test/make/TestCopyFiles.gmk	Mon Nov 27 17:04:45 2017 +0000
@@ -52,7 +52,7 @@
 	$(TOUCH) $(SRC_DIR)/foo/foofile
 	$(TOUCH) "$(SRC_DIR)/foo/foo file"
         # Spaces in directories only works with gnu make 4.0 or later
-        ifeq (4.0dfd, $(firstword $(sort 4.0 $(MAKE_VERSION))))
+        ifeq (4.0, $(firstword $(sort 4.0 $(MAKE_VERSION))))
 	  $(MKDIR) -p "$(SRC_DIR)/foo bar"
 	  $(TOUCH) "$(SRC_DIR)/foo bar/foobarfile"
 	  $(TOUCH) "$(SRC_DIR)/foo bar/foo bar file"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/nashorn/script/basic/JDK-8191468.js	Mon Nov 27 17:04:45 2017 +0000
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+/**
+ * JDK-8191468: jdk.scripting.nashorn.shell (jjs) module should use optional dependency for java.compiler module
+ *
+ * @test
+ * @run
+ */
+
+var optJjsMod = java.lang.ModuleLayer.boot().findModule("jdk.scripting.nashorn.shell");
+
+// make sure that the module exists!
+Assert.assertTrue(optJjsMod.isPresent());
+
+// jdk.scripting.nashorn.shell should use optional dependency for java.compiler
+var javaCompilerDependency = optJjsMod.get().
+        descriptor.requires().
+        stream().
+        filter(function(mod) { return mod.name() == "java.compiler" }).
+        findFirst();
+
+// java.compiler dependency should be present
+Assert.assertTrue(javaCompilerDependency.isPresent());
+
+var Modifier = java.lang.module.ModuleDescriptor.Requires.Modifier;
+// java.compiler requires should be "requires static"
+Assert.assertTrue(javaCompilerDependency.get().modifiers().contains(Modifier.STATIC));
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/nashorn/script/basic/JDK-8191819.js	Mon Nov 27 17:04:45 2017 +0000
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+/**
+ * JDK-8191819: String.prototype.match should follow ES6 specification
+ *
+ * @test
+ * @run
+ */
+
+Assert.assertEquals("a\nb\rc\n\rd\r\ne".match(/^(.*)/gm).join("*"), "a*b*c**d**e");
+
+