Merge
authorjwilhelm
Wed, 22 Nov 2017 16:57:34 +0100
changeset 48093 2cb07c3778e1
parent 48092 72855b7d10ac (current diff)
parent 47919 66350f079368 (diff)
child 48094 bca569f79fa1
Merge
make/hotspot/lib/CompileJvm.gmk
src/hotspot/cpu/aarch64/templateInterpreterGenerator_aarch64.cpp
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/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	Thu Nov 16 14:06:44 2017 -0500
+++ b/.hgtags	Wed Nov 22 16:57:34 2017 +0100
@@ -456,3 +456,4 @@
 a6e591e12f122768f675428e1e5a838fd0e9c7ec jdk-10+29
 8fee80b92e65149f7414250fd5e34b6f35d417b4 jdk-10+30
 e6278add9ff28fab70fe1cc4c1d65f7363dc9445 jdk-10+31
+a2008587c13fa05fa2dbfcb09fe987576fbedfd1 jdk-10+32
--- a/make/autoconf/configure	Thu Nov 16 14:06:44 2017 -0500
+++ b/make/autoconf/configure	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/make/autoconf/generated-configure.sh	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/make/autoconf/hotspot.m4	Wed Nov 22 16:57:34 2017 +0100
@@ -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/Modules.gmk	Thu Nov 16 14:06:44 2017 -0500
+++ b/make/common/Modules.gmk	Wed Nov 22 16:57:34 2017 +0100
@@ -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/hotspot/lib/CompileJvm.gmk	Thu Nov 16 14:06:44 2017 -0500
+++ b/make/hotspot/lib/CompileJvm.gmk	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/make/hotspot/lib/CompileLibjsig.gmk	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/make/mapfiles/libawt/mapfile-mawt-vers	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/make/mapfiles/libawt_xawt/mapfile-vers	Wed Nov 22 16:57:34 2017 +0100
@@ -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/src/java.base/share/classes/java/lang/ModuleLayer.java	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/java.base/share/classes/java/lang/ModuleLayer.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/java.base/share/classes/java/lang/Package.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/java.base/share/classes/java/lang/StackTraceElement.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/java.base/share/classes/java/lang/invoke/LambdaFormBuffer.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/java.base/share/classes/java/lang/invoke/MethodHandle.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/java.base/share/classes/java/lang/invoke/MethodHandles.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/java.base/share/classes/java/lang/invoke/VarForm.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/java.base/share/classes/java/lang/invoke/VarHandle.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/java.base/share/classes/java/lang/invoke/VarHandles.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/java.base/share/classes/java/lang/module/ModuleDescriptor.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/java.base/share/classes/java/lang/module/Resolver.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/java.base/share/classes/java/math/BigInteger.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/java.base/share/classes/java/util/List.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/java.base/share/classes/jdk/internal/loader/URLClassPath.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/java.base/share/classes/jdk/internal/misc/JavaLangAccess.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/java.base/share/classes/jdk/internal/misc/Unsafe.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/java.base/share/classes/jdk/internal/module/ModulePath.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/java.base/share/classes/jdk/internal/module/Modules.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/java.base/share/classes/jdk/internal/module/SystemModulesMap.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/java.base/share/classes/sun/net/idn/StringPrep.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/java.base/share/classes/sun/net/www/MimeEntry.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/java.base/share/classes/sun/security/provider/certpath/PolicyNodeImpl.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/java.base/share/classes/sun/security/x509/PrivateKeyUsageExtension.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/java.base/solaris/native/libjvm_dtrace/jvm_dtrace.c	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/java.compiler/share/classes/javax/lang/model/util/AbstractAnnotationValueVisitor6.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/java.compiler/share/classes/javax/lang/model/util/AbstractElementVisitor6.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/java.compiler/share/classes/javax/lang/model/util/AbstractElementVisitor9.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/java.compiler/share/classes/javax/lang/model/util/ElementKindVisitor6.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/java.compiler/share/classes/javax/lang/model/util/ElementKindVisitor7.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/java.compiler/share/classes/javax/lang/model/util/ElementKindVisitor9.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/java.compiler/share/classes/javax/lang/model/util/ElementScanner6.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/java.compiler/share/classes/javax/lang/model/util/ElementScanner7.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/java.compiler/share/classes/javax/lang/model/util/ElementScanner9.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/java.compiler/share/classes/javax/lang/model/util/SimpleAnnotationValueVisitor6.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/java.compiler/share/classes/javax/lang/model/util/SimpleElementVisitor6.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/java.compiler/share/classes/javax/lang/model/util/SimpleElementVisitor7.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/java.compiler/share/classes/javax/lang/model/util/SimpleElementVisitor9.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/java.compiler/share/classes/javax/lang/model/util/SimpleTypeVisitor6.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/java.compiler/share/classes/javax/lang/model/util/SimpleTypeVisitor7.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/java.compiler/share/classes/javax/lang/model/util/SimpleTypeVisitor8.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/java.compiler/share/classes/javax/lang/model/util/TypeKindVisitor6.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/java.compiler/share/classes/javax/lang/model/util/TypeKindVisitor7.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/java.compiler/share/classes/javax/lang/model/util/TypeKindVisitor8.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/java.desktop/macosx/classes/sun/lwawt/LWLightweightFramePeer.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/png/PNGImageReader.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKGraphicsUtils.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/java.desktop/share/classes/java/awt/EventQueue.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/java.desktop/share/classes/java/awt/im/InputContext.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/java.desktop/share/classes/javax/swing/text/PlainView.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ /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	Thu Nov 16 14:06:44 2017 -0500
+++ /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	Thu Nov 16 14:06:44 2017 -0500
+++ /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	Thu Nov 16 14:06:44 2017 -0500
+++ /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	Thu Nov 16 14:06:44 2017 -0500
+++ /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	Thu Nov 16 14:06:44 2017 -0500
+++ /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	Thu Nov 16 14:06:44 2017 -0500
+++ /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	Thu Nov 16 14:06:44 2017 -0500
+++ /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	Thu Nov 16 14:06:44 2017 -0500
+++ /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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/java.desktop/share/classes/sun/swing/JLightweightFrame.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/java.desktop/unix/classes/sun/awt/X11/XLightweightFramePeer.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/java.desktop/unix/classes/sun/awt/X11/XWindowPeer.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ /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	Thu Nov 16 14:06:44 2017 -0500
+++ /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	Thu Nov 16 14:06:44 2017 -0500
+++ /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	Thu Nov 16 14:06:44 2017 -0500
+++ /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	Thu Nov 16 14:06:44 2017 -0500
+++ /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	Thu Nov 16 14:06:44 2017 -0500
+++ /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	Thu Nov 16 14:06:44 2017 -0500
+++ /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	Thu Nov 16 14:06:44 2017 -0500
+++ /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	Thu Nov 16 14:06:44 2017 -0500
+++ /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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/java.desktop/unix/classes/sun/java2d/xr/XRBackend.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/java.desktop/unix/classes/sun/java2d/xr/XRBackendNative.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/java.desktop/unix/classes/sun/java2d/xr/XRCompositeManager.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/java.desktop/unix/classes/sun/java2d/xr/XRSurfaceData.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/java.desktop/unix/native/libawt_xawt/java2d/x11/XRBackendNative.c	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/java.desktop/windows/classes/sun/awt/windows/TranslucentWindowPainter.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/java.desktop/windows/classes/sun/awt/windows/WLightweightFramePeer.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/java.desktop/windows/classes/sun/awt/windows/WWindowPeer.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/java.desktop/windows/native/libawt/windows/awt_Component.cpp	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/java.desktop/windows/native/libawt/windows/awt_Dialog.cpp	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/java.desktop/windows/native/libawt/windows/awt_Font.cpp	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/java.desktop/windows/native/libawt/windows/awt_Frame.cpp	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/java.desktop/windows/native/libawt/windows/awt_Window.cpp	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/java.desktop/windows/native/libawt/windows/awt_Window.h	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/java.management.rmi/share/classes/javax/management/remote/rmi/RMIConnectorServer.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransTypes.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractExecutableMemberWriter.java	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractExecutableMemberWriter.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractIndexWriter.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractMemberWriter.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractModuleIndexWriter.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractPackageIndexWriter.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractTreeWriter.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeFieldWriterImpl.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeOptionalMemberWriterImpl.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeRequiredMemberWriterImpl.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeWriterImpl.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassUseWriter.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriterImpl.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConstantsSummaryWriterImpl.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConstructorWriterImpl.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/Contents.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/DeprecatedListWriter.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/EnumConstantWriterImpl.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/FieldWriterImpl.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/FrameOutputWriter.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HelpWriter.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlConfiguration.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlSerialFieldWriter.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlSerialMethodWriter.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/IndexRedirectWriter.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/LinkFactoryImpl.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/LinkInfoImpl.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/MethodWriterImpl.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleFrameWriter.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleIndexFrameWriter.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleIndexWriter.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModulePackageIndexFrameWriter.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleWriterImpl.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/NestedClassWriterImpl.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageFrameWriter.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageIndexFrameWriter.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageIndexWriter.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageTreeWriter.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageUseWriter.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageWriterImpl.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PropertyWriterImpl.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SerializedFormWriterImpl.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SingleIndexWriter.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SourceToHTMLConverter.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SplitIndexWriter.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SubWriterHolderWriter.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ /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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/TagletWriterImpl.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/TreeWriter.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/ContentBuilder.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/DocType.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ /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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlDocument.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlTree.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ /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	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/package-info.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/AbstractDoclet.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/BaseConfiguration.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/Content.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/MemberSummaryWriter.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/MemberSummaryBuilder.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Extern.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ /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	Thu Nov 16 14:06:44 2017 -0500
+++ /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	Thu Nov 16 14:06:44 2017 -0500
+++ /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	Thu Nov 16 14:06:44 2017 -0500
+++ /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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/ToolOption.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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.jdeps/share/classes/com/sun/tools/javap/AnnotationWriter.java	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/jdk.jdeps/share/classes/com/sun/tools/javap/AnnotationWriter.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/jdk.jdeps/share/classes/com/sun/tools/javap/ConstantWriter.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/ConsoleIOContext.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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;
@@ -108,6 +115,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 +207,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 +224,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 +370,7 @@
                             .stream()
                             .collect(joining(", ")));
                 }
+                exitCode = 1;
                 return null;
             }
         }
@@ -420,7 +431,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 +549,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 +564,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 +880,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 +900,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 +908,7 @@
         for (String loadFile : commandLineArgs.nonOptions()) {
             if (!runFile(loadFile, "jshell")) {
                 // Load file failed -- abort
-                return;
+                return 1;
             }
         }
         // if we survived that...
@@ -930,6 +951,7 @@
             }
         }
         closeState();
+        return exitCode;
     }
 
     private EditorSetting configEditor() {
@@ -1067,6 +1089,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 +1124,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 +1148,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 +1740,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()));
@@ -2124,10 +2231,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 +2854,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 +2951,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 +3294,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 +3388,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 +3415,7 @@
             addToReplayHistory(source);
         }
 
-        return failed;
+        return !failed;
     }
 
     // Handle incoming snippet events -- return true on failure
@@ -3166,23 +3429,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 +3570,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 +3868,7 @@
         scannerIn.close();
     }
 
+    @Override
     public int readUserInput() {
         return -1;
     }
@@ -3648,6 +3900,7 @@
     public void close() {
     }
 
+    @Override
     public int readUserInput() {
         return -1;
     }
--- a/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellToolBuilder.java	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellToolBuilder.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellToolProvider.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/resources/l10n.properties	Wed Nov 22 16:57:34 2017 +0100
@@ -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 = \
--- a/src/jdk.jshell/share/classes/jdk/jshell/tool/JavaShellToolBuilder.java	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/jdk.jshell/share/classes/jdk/jshell/tool/JavaShellToolBuilder.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/jdk.jshell/share/classes/jdk/jshell/tool/package-info.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ /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	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Wed Nov 22 16:57:34 2017 +0100
@@ -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/PackagesHelper.java	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/jdk.scripting.nashorn.shell/share/classes/jdk/nashorn/tools/jjs/PackagesHelper.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/jdk.scripting.nashorn.shell/share/classes/jdk/nashorn/tools/jjs/PropertiesHelper.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/src/jdk.scripting.nashorn.shell/share/classes/module-info.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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/test/jdk/ProblemList.txt	Thu Nov 16 14:06:44 2017 -0500
+++ b/test/jdk/ProblemList.txt	Wed Nov 22 16:57:34 2017 +0100
@@ -245,8 +245,6 @@
 
 # jdk_swing
 
-sanity/client/SwingSet/src/ButtonDemoScreenshotTest.java        8157338 generic-all
-
 ############################################################################
 
 # jdk_text
--- a/test/jdk/TEST.ROOT	Thu Nov 16 14:06:44 2017 -0500
+++ b/test/jdk/TEST.ROOT	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/test/jdk/TEST.groups	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/test/jdk/java/awt/BasicStroke/DashStrokeTest.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/Package/PackageVersionTest.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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/invoke/ArrayConstructorTest.java	Thu Nov 16 14:06:44 2017 -0500
+++ b/test/jdk/java/lang/invoke/ArrayConstructorTest.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/test/jdk/java/lang/invoke/ArrayLengthTest.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/test/jdk/java/lang/invoke/JavaDocExamplesTest.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/test/jdk/java/lang/invoke/SpreadCollectTest.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/javax/imageio/plugins/png/PngNegativeDimensionTest.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/test/jdk/javax/swing/JWindow/ShapedAndTranslucentWindows/PerPixelTranslucent.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/test/jdk/javax/swing/JWindow/ShapedAndTranslucentWindows/PerPixelTranslucentGradient.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/test/jdk/javax/swing/JWindow/ShapedAndTranslucentWindows/PerPixelTranslucentSwing.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/test/jdk/javax/swing/JWindow/ShapedAndTranslucentWindows/ShapedPerPixelTranslucentGradient.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/test/jdk/javax/swing/JWindow/ShapedAndTranslucentWindows/ShapedTranslucentPerPixelTranslucentGradient.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/test/jdk/javax/swing/JWindow/ShapedAndTranslucentWindows/TranslucentPerPixelTranslucentGradient.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/test/jdk/sanity/client/SwingSet/src/ButtonDemoScreenshotTest.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/FrameOperator.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ /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	Thu Nov 16 14:06:44 2017 -0500
+++ /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	Thu Nov 16 14:06:44 2017 -0500
+++ /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	Thu Nov 16 14:06:44 2017 -0500
+++ /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	Thu Nov 16 14:06:44 2017 -0500
+++ /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	Thu Nov 16 14:06:44 2017 -0500
+++ /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	Thu Nov 16 14:06:44 2017 -0500
+++ /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	Thu Nov 16 14:06:44 2017 -0500
+++ /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	Thu Nov 16 14:06:44 2017 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-modules=java.desktop
--- a/test/jdk/sun/pisces/ThinLineTest.java	Thu Nov 16 14:06:44 2017 -0500
+++ /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	Thu Nov 16 14:06:44 2017 -0500
+++ b/test/jdk/sun/security/ssl/SSLSocketImpl/SSLSocketCloseHang.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/test/langtools/ProblemList.txt	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/test/langtools/jdk/javadoc/doclet/testDeprecatedDocs/TestDeprecatedDocs.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/test/langtools/jdk/javadoc/doclet/testGroupName/TestGroupName.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/test/langtools/jdk/javadoc/doclet/testHtmlDocument/TestHtmlDocument.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/test/langtools/jdk/javadoc/doclet/testLinkOption/TestBadLinkOption.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/test/langtools/jdk/javadoc/doclet/testLinkOption/TestNewLineInLink.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/test/langtools/jdk/javadoc/doclet/testModules/TestModules.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/test/langtools/jdk/javadoc/doclet/testOptions/help.html	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/test/langtools/jdk/jshell/StartOptionTest.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/test/langtools/jdk/jshell/ToolProviderTest.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/test/langtools/jdk/jshell/ToolSimpleTest.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/test/langtools/jdk/jshell/ToolTabCommandTest.java	Wed Nov 22 16:57:34 2017 +0100
@@ -23,7 +23,7 @@
 
 /**
  * @test
- * @bug 8177076
+ * @bug 8177076 8185840
  * @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" +
--- a/test/langtools/tools/javac/failover/CheckAttributedTree.java	Thu Nov 16 14:06:44 2017 -0500
+++ b/test/langtools/tools/javac/failover/CheckAttributedTree.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/test/langtools/tools/javac/flow/tests/TestCaseForEach.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/test/langtools/tools/javac/modules/ExportsUnexported.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/test/langtools/tools/javadoc/sourceOnly/Test.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/test/langtools/tools/javadoc/sourceOnly/p/SourceOnly.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/test/langtools/tools/javap/typeAnnotations/InvisibleParameterAnnotationsTest.java	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Thu Nov 16 14:06:44 2017 -0500
+++ b/test/make/TestCopyFiles.gmk	Wed Nov 22 16:57:34 2017 +0100
@@ -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	Wed Nov 22 16:57:34 2017 +0100
@@ -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));